Egyszerű listaművelet Pythonban

Sziasztok.

A feladat a következő: legyen adott egy számpárokból álló halmaz, a következő módon: { p_n, p_n, p_n+1, p_n+1, p_n+2, p_n+2 ... } Adjunk egy olyan listát amelyben a halmaz elemei úgy foglalnak helyet, hogy köztük az értéküknek megfelelő számú másik elem van. Vagyis azt szeretnénk, hogy a párok az értékük + 1 távolságban helyezkedjenek el egymástól.

Példa az érthetőség kedvéért: {1,1,2,2,3,3} halmaz esetén ilyen lista a következő:
[3,1,2,1,3,2]. megj.: a példa biztosan jó, ha nem illene össze pontosan a feladat megfogalmazásával, akkor a példa a helyes. :)

Ezt a feladványt szeretném megoldani tetszőlegesen nagy halmazra. Vagyis először 6-ra, mert arra már kézzel nem találtam meg a megoldást. :) Mivel semmi képzettségem nincs algoritmuselméletben ezért egyenlőre a következő -- minden bizonnyal rossz hatékonyságú -- eljárást szeretném kipróbálni:


vedd a számok listáját és nézd meg, hogy meg van-e oldva:
  ha meg van oldva: 
    True
  ha nincs megoldva:
    vedd az elso szamot aminek a parja nincs jo helyen es rakd be a helyere
    ismeteld meg az eljarast ezen a listan

Nem tudom, hogy ez jó megoldás-e, egyenlőre csak ki szeretném próbálni. De itt jön a gond: valamiért az istennek nem tudom megoldani, hogy megértse a python, hogy mit szeretnék (pedig régebben szót értettünk egymással).

Eddig ezeket írtam meg:


def switcher ( list , point1 , point2 ):
        v = list[point2]
        list[point2] = list[point1]
        list[point1] = v
        return list

(ezt nem is magyaraznam)


def checker ( list, point ): 
        try:
                num = list[point] 
                numToCheck = list[point + num + 1]
                if num == numToCheck:
                        return True 
                else:
                        return switcher( list, \
                                        (point + num + 1 ),
                                        list.index(num , point + 1) )
        except IndexError:
                print  "kilogok"

A try - except egyenlőre csak a debuggolás miatt van benne, elvileg elég a lista felén végigszaladni, ha addig helyes, akkor végig helyes (legalábbis azt hiszem).

Példa:


>>> teszt = [7,7,6,6,5,5,4,4,3,3,2,2,1,1]
>>> teszt2 = [3,1,2,1,3,2]
>>> checker( teszt, 0 )
[7, 3, 6, 6, 5, 5, 4, 4, 7, 3, 2, 2, 1, 1]
>>> checker( teszt2, 0 )
True

Van még egy ellenőrzőfüggvény is:


def solved ( list ): 
        index = 0 
        while index < len(list)/2:
                if checker( list , index ) == True:
                        index += 1
                else:
                        return False
        return True

Példa:


>>> solved( teszt )
False
>>> solved( teszt2 )
True

Van egy olyan sanda gyanúm, hogy ennek a három fv.nek már elégnek kéne lenni az eljárás megvalósításához, de valamiért nem tudom összepasszítani őket. (tudom: ciki, de nyugtasson a tudat, hogy csak egy bölcsész vagyok) Ha valakinek van egy kis ideje tudna javaslatot adni, hogyan tudnám megcsinálni a fent leírt eljárást? (Esetleg egy tipp is jó lenne, hogy fog-e működni, meg hogy hol érdemes hatékonyabb megoldás után kutatni)

Előre is köszi.

Disclaimer: nem beadandó feladat (jól is nézne ki), nem mással akarom megcsináltatni, csak elakadtam, és egy kis segítség kéne. Just for fun. :)

Hozzászólások

Csak a pontosítás kedvéért:

{1,1,2,2,3,3}

Ez nem halmaz ám :)

--
Keep it simple, stupid.

"elvileg elég a lista felén végigszaladni, ha addig helyes, akkor végig helyes (legalábbis azt hiszem)."

Ezt nem látom. Mi van, ha egy hosszú lista végén van ez?

..., 1, 2, 3, 1 }

Az eleje lehet jó, csak a végén derül ki, hogy hibás.

Megj.: Persze, az lehet, hogy nem értettem meg a feladatot. :-)

KisKresz

Hát az én ötletem az volt, hogy azért, mert a lista hosszúsága és elemei fixek , így ha a végén el van rontva vmi (rossz helyen van, mint az egyes), akkor más elemek is el lesznek rontva. Ha ellenben a feléig nincs semmi elrontva akkor valamiért úgy tűnt, hogy már onnan sem lehet benne hiba (hiszen ha hiba lenne, akkor már előbb kijött volna). Ezt biztod be lehet bizonyítani könnyen, de nekem ez egyenlőre csak megérzés. :)

-----------
"Generally, Russian technology assumes dumb machines and smart humans, not the other way around." -- The Russian Tea HOWTO

Tekinthetsz a számpárokra, mint középen üres blokkokra:

1x1
2xx2
3xxx3
4xxxx4
5xxxxx5
...

amiket egy 2*n hosszú területre kell bezsúfolni.
Ha n=5, akkor az 5-ös blokkot négyféleképpen rakhatod le (illetve szimmetriaokok miatt csak kétféleképpen), a 4-est ötféleképpen, stb.
Ha nem tudod lerakni az adott blokkot, akkor visszalépsz, és így végessok lépésben megáll a keresés.

Erre is gondoltam, sőt igazából ez volt az első ötletem. (a második meg az, hogy szerzek pár LEGO darabot, és... ) :)

A gond az, hogy nincs ötletem, hogy hogyan álljak neki ábrázolni ilyen objektumokat (*), és hogyan játszam le velük a keresést. Tudsz javasolni vmi könyvet/tutorialt/howto-t?

(*) Mármint szépen és átláthatóan.
-----------
"Generally, Russian technology assumes dumb machines and smart humans, not the other way around." -- The Russian Tea HOWTO

Nem is minden n-re van megoldás, pl. 5, 6, 9, 10-re nincs.

Viszont például 23-ra:

[23, 21, 22, 18, 16, 20, 12, 19, 11, 8, 17, 4, 1, 15, 1, 14, 4, 13, 8, 12, 11, 16, 18, 21, 23, 22, 20, 19, 17, 15, 14, 13, 10, 7, 9, 3, 5, 2, 6, 3, 2, 7, 5, 10, 9, 6]

:)

Némi fejtörés után a következő kódnál kötöttem ki:


def slotList ( num ):
        emptySpaces = [0]*num*2
        return emptySpaces
        
def put ( num , line , point ):
        line[point] = num
        line[point + num + 1] = num
        return line

def fitsIn ( num , line, point ):
        try:
                if line[point + num + 1] == 0 and line[point] == 0:
                        return True
                else:
                        return False
        except IndexError:
                return False

def tryIt ( num , list ):
        point = 0
        while (0 in list) == True:
                if fitsIn( num, list, point ) == True:
                        list = put( num, list, point)
                        tryIt( num-1, list )
                else:
                        point +=1
                
        return list

Namost ezzel az van, hogy kidobja a megoldást, ha pl.

tryIt ( 3 , slotList(3))

-t adok neki, de magasabb értékre nem, gondolom pont azért mert a visszaléptetés nics beledrótozva. Hogyan tudnám kifejezni pythonul, hogy: "ha semmiképp nem tudod lerakni az aktuális darabot, lépj vissza az előző állapotba és indulj el másfele"?

(Gondolom valamit az IndexErrornál kéne birizgálni, meg letárolni valahol az előző ciklus állapotát, de nem bírom megfogalmazni.)

Előre is köszi.

-----------
"Generally, Russian technology assumes dumb machines and smart humans, not the other way around." -- The Russian Tea HOWTO