Végteleníthetõ tantrix-minták

"A feladat a teljes tantrix-készlet felhasználásával olyan színhelyes elrendezés előállítása, amely végteleníthető, azaz amelynek eltolt példányaival színhelyesen "kiparkettázható" a teljes sík. Ehhez az kell, hogy a minta teteje színhelyesen csatlakozzon az aljához, a bal oldala pedig a jobb oldalához."

Szobonya László, 2004. január 10.

 

Bevezetés

Nagyjából egy éve annak, hogy ez a probléma komolyan foglalkoztatni kezdett, és akkor egy intenzív hetet töltöttem azzal, hogy megpróbáljak végteleníthető tantrix-mintákat keresni. Miután ez elég hamar sikerült (már a legelső programommal is kb. fél napos munka után találtam megoldást), elkezdtem arra törekedni, hogy minél elegánsabb megoldás(oka)t találjak. Utólag visszagondolva a végeredmény megtalálása eléggé természetesnek tűnik számomra, de azért emlékszem, hogy komoly fejtörést okozott minden egyes új lépés megtétele a végleges megoldás felé. A következő leírás tehát ennek az egy hétnek a sűrített (és remélem, az érdekesebb részleteit kiragadó) összefoglalása lesz. Először azonban nem árt azt tisztázni, hogy mi is pontosan a feladat:

 

A feladat a teljes tantrix-készlet felhasználásával olyan színhelyes elrendezés előállítása, amely végteleníthető, azaz amelynek eltolt példányaival színhelyesen "kiparkettázható" a teljes sík. Ehhez az kell, hogy a minta teteje színhelyesen csatlakozzon az aljához, a bal oldala pedig a jobb oldalához.

 

A megoldás keresése során, ha találtam egy új, az addigiaknál elegánsabb megoldást, akkor azt szinte azonnal feltettem a sokak számára jól ismert Tantrix Fórumba, így egyrészt a többiek rögtön értesültek a fejleményekről, másrészt pedig nekem is komoly motivációt adott a többiek támogatása. Az ott látható képek némelyike különbözik az itt láthatóaktól, mert most, hogy elkezdtem ezt az összefoglalót írni, a programokat egységes keretbe foglaltam, ami esetleg befolyásolta futás során a keresési sorrendet, tehát ne lepődjön meg senki, ha nem ugyanazokat a képeket találja ott és itt.

 

A módszerről általában

A feladatnak rengeteg megoldása van, és igen nagy szabadság mutatkozik abban is, hogy hogyan álljunk neki ezek megkeresésének. Módszerem lényege az volt, hogy először lerögzítettem egy 56 lapka méretű, paralelogramma vagy téglalap alakú, egyelőre üres táblát. Ennek mezőit beszámoztam 1-től 56-ig és ebben a táblában egyesével próbáltam a lapkákat elhelyezni. Például az első próbálkozásomkor használt tábla 4x14-es paralelogramma alakú (röviden döntött) tábla volt, a következő számozással:

1. ábra: Az első módszer táblája és kitöltési terve

A módszer alapja a matematikai algoritmusokban használt mélységi keresés volt (aki nem ismeri, az se ijedjen meg, a lényegét egyszerű megérteni). A mélységi keresés úgy működik, hogy "mohó" módon próbáljuk kitölteni a táblát, azaz először az 1. helyre betesszük az 1-es lapkát, egyelőre nem elforgatva. Ezután a 2. mezőre elhelyezzük a legelső olyan, még fel nem használt lapkát, ami szabályosan mellé illeszthető, majd ezt így folytatjuk tovább. Amíg nem akadunk el, ezt folytatjuk, de előbb-utóbb bekövetkezik még az 56. lapka elhelyezése előtt, hogy az éppen aktuális szabad helyet már nem tudjuk kitölteni.

Ilyenkor (megint csak mohó módon) egyet visszalépünk, és az előző mezőt vizsgálva vesszük az ott lévő lapka következő elforgatását, ha pedig ezt már teljesen körbeforgattuk, akkor vesszük a soron következő lapkát, ami oda illik. Mindössze ezzel a két elemi lépéssel (előre- és visszalépés) folytatjuk tovább a kitöltést. Könnyű végiggondolni, hogy így minden teljes kitöltést meg fogunk találni. Célszerű továbbá feltennünk, hogy a bal felső sarokban mindig az 1-es sorszámú lapka van (esetleg elforgatva), hisz ha már meglenne a keresett végtelen kitöltésünk, akkor abból ki tudnánk vágni úgy 1 periódust, hogy az 1-es lapka a bal felső sarokba kerüljön.

Ha nem követnénk semmilyen kitöltési elvet, hanem csak szisztematikusan végignéznénk az összes esetet, azaz az 56 lapka minden lehetséges sorrendjét (és forgásirányát!) is végigpróbálnánk, akkor évmilliárdok alatt se végeznénk (sőt…). Ezért fontos szerepe van a kitöltés hatékony megszervezésének. Nézzük, hogy tettem ezt az első esetben (senki ne lepődjön meg, ha kötelező helyek is fel fognak bukkanni…).

 

1. módszer (4x14-es, döntött tábla)

Ahhoz, hogy pontosabban lássuk, miképpen is megy a kitöltés, érdemes először végiggondolni, hogy hogyan is illeszkedjenek egymáshoz a szomszédos táblák. Vízszintesen kézenfekvő az elhelyezés, tegyünk azonos magasságban balra és jobbra 1-1 táblát (2. ábra, szürkével). Az egymás alatt levő táblák egymáshoz képesti elcsúsztatása már érdekesebb kérdés (2. ábra, pirossal), mert ha a kézenfekvő elhelyezést választanánk, azaz azt, amellyel 2 egymás alatti tábla egy nagy (8x14-es) paralelogrammát alkotna, akkor nem tudnánk hatékonyan megoldást keresni, mert nem alakulnának ki automatikusan kötelező helyek. De miért is lenne fontos ez? Rögtön meglátjuk, ha 1-gyel eltoljuk egymáshoz képest a függőlegesen egymás alatt levő táblákat. Ekkor a második oszloptól kezdve csupa kötelező helyet kell kitölteni, mint ahogy ez az ábrán is látható (az első 4 lapka lerakása után az 5-ös mező egy kötelező hely, mégpedig a 2-es, 1-es, és 4-es lapkák által):

 

2. ábra: a táblák egymáshoz képesti eltolása

Kötelező helyek kialakításával elérjük, hogy egy adott helyre legfeljebb 6 lapkát kell odapróbálni, ellentétben az 56-tal, ami szervezés nélkül lenne, vagy a kb. 18-20-szal, ami akkor lenne, ha nem csúsztatnánk el egymáshoz képest a táblákat. (pl. eltolás nélkül az 1-es és 2-es mező nem 3, hanem csak 2 oldalát határozná meg az 5-ösnek). Az 5-ös lapka elhelyezése után a 6-os is kötelező hellyé alakul, és ez így megy végig, biztosítva azt, hogy minden lapkánál csak kevés számú elágazás legyen. Sőt, a végén az 53-56. lapkák már teljesen, mind a 6 oldalról meg vannak határozva, ami tovább csökkenti a lehetőségek számát. A program megírása és elindítása után pár másodperccel elő is állt az első megoldás, mely a 3. ábrán látható:

 

3. ábra: 4x14-es, döntött minta

 

2. módszer: (4x14-es, téglalap elrendezés)

Az eredmény, noha igen örömteli volt, mégsem tetszett igazán. Két problémám is volt vele: az egyik, hogy a 4x14-es elrendezés "túl lapos", emiatt szerintem nem túl elegáns (ennyi erővel akár 2x28-as, vagy igen extrémnek számító 1x56-os kitöltéseket is vizsgálhattam volna), a 7x8-as minták sokkal szimpatikusabbak voltak számomra kezdettől fogva. Viszont ez utóbbiakat lényegesen bonyolultabb is kezelni, mint azt látni fogjuk. A másik problémám pedig az volt ezzel az első megoldással, hogy ha valaki szeretné például háttérnek használni a 3. ábrán látható megoldást, és 1 táblát tesz a képre, majd Mozaik módot választ, akkor az egymás alatti táblák nem jó helyre fognak kerülni, és csúnya (sőt helytelen) eredményt kapunk. Ezt a második problémát küszöböltem ki a második módszeremmel, melynél a következő beszámozott táblát használtam:

4. ábra: 4x14-es téglalap elrendezés és számozás

Ennek az elrendezésnek nagy előnye, hogy az egymás fölötti táblák nem tolódnak el egymáshoz képest (a 4-es pl. az 1-es és 5-ös lapka közé ékelődik be). A gyors kitöltés érdekében az előzőhöz képest felcseréltem a 2. és 3. sor kitöltési sorrendjét, amivel megint elértem, hogy az első 4 lapka lerakása után a többi lapka más kötelező helyre kerüljön. Futtatás után az első kiadódó megoldás a következő volt:

5. ábra: 4x14-es, álló minta

Ez a trükk minden további módszeremben alkalmazható, úgyhogy ezentúl nem szükséges az "álló" megnevezés, mert minden további megoldás ilyen lesz, azaz mindegyik alkalmas pl. háttérképnek.

 

3. módszer: (7x8-as téglalap elrendezés)

Ezen a ponton megvolt tehát kétféle 4x14-es minta, de még mindig nem éreztem úgy, hogy a probléma meg lenne oldva, hiszen, mint mondtam, egy 7x8-as megoldást sokkal elegánsabbnak tartottam volna. Úgyhogy meg is tettem az első lépést ezen az úton, először nem sok sikerrel… 

Az előző módszert futtattam változtatás nélkül, csupán a tábla méretét átírva, azaz a következő táblát próbáltam kitölteni:

 

6. ábra: 8x7-es kitöltőtábla

Ezzel a táblával az volt a gond, hogy 3 nap alatt nem találtam vele egyetlen megoldást se. Futott volna tovább is, csak éppen nem volt türelmem megvárni. Ez a kísérlet tehát egyelőre kudarcot vallott, de kiindulópontja volt a javított és sikeresebb keresési módszereimnek. A 2. és a 3. módszer között az lehet a (méretekből adódó) lényeges különbség, hogy itt az első 8 lapka az, ami sok elágazást okoz az előző módszer mindössze 4 lapkájához képest, amivel megnő a keresés futásideje. És emellett az is megnehezíti egy megoldás megtalálását, hogy a 49-52. lapkák már 4, míg az 53-56. lapkák már mind a 6 oldalról meg vannak határozva, ami azt eredményezi, hogy igen kis gyakorisággal jutunk csak el az 55., vagy valami csoda folytán az 56. lapkáig (megjegyzem, hogy azért a 3 nap alatt, amíg ez a verzió futott, kb. 10 percenként talált olyan elrendezést, amikor mindössze az utolsó lapka nem stimmelt, de egy olyan se akadt, amikor mind az 56 a helyén lett volna). A 3 napos futtatás a munkahelyem egyik ritkán használt 1600 MHz-es gépén történt, úgyhogy közben tudtam haladni a módszer csiszolásában, így született meg a

 

4. módszer: (7x8-as szimmetrikus módszer)

A nagy számításigényen úgy próbáltam segíteni, hogy gondolatban vízszintesen középen félbevágtam a táblát, és egy fél készletből próbáltam meg a felső részt kitölteni, majd a maradék fél készletből ennek mintájára az alsó felét. Az volt az ötletem, hogy az ábra felső felét abból a 28 lapkából rakom ki, melyekben egyszerre szerepel kék és sárga is. Ezután a felső ábra minden kék ívét pirosra és viszont, valamint minden sárga ívét zöldre (és viszont) cserélem ki, és a kapott táblát a felső rész alá teszem. Ekkor alulra pont a készlet maradék fele fog kerülni, ezt könnyen végig lehet gondolni. Ilyenkor figyelni kell viszont arra, hogy a 4x7-es tábla kitöltésének keresésénél az alsó "kilógó" ívvégek színének nem megegyeznie kell a felső kilógó végek színével, hanem ezeknek éppen színpároknak kell lenniük, ezáltal lesz színhelyes a végső kapcsolódás (nem mondtam, de a kitöltési tábla ugyanaz, mint amit a 2. módszernél (4x14-es, álló) használtam, csak 56 lapka helyett mindössze 28-at használva).

Amikor anno ezt a verziót megírtam, akkor került bele egy kisebb hiba, ami miatt kihagytam néhány megoldás vizsgálatát. Emiatt először nem is találtam megoldást. Csak úgy sikerült egy - az itt láthatónál kevésbé szimmetrikus - mintát előállítanom, hogy amikor 27 lapkát sikerült elhelyeznem, csak a 28.-at nem, akkor megpróbáltam azt a párjával pótolni, és ez elég hamar sikerült is. Azonban az azóta kijavított programot újrafuttatva fél percen belül megszületett ez a minta (érdekessége, hogy nincsenek benne vonalak, minden színből hurkok alakultak ki - színenként 4, illetve 5 darab):

 

7. ábra: 8x7-es, szimmetrikus minta

 

5. módszer: (7x8-as, "extraszimmetrikus" módszer)

Az előző módszerből nyert megoldás már tetszett, de ekkor már vérszemet kaptam, és nem akartam itt megállni. Ez az 5. módszer lett aztán a végleges, melyben minden szín teljesen egyenrangú, azaz a megoldásban teljesen azonos alakú mintázatot követnek a színek. Véleményem szerint az ebből a megoldásból kapott minták a legszebbek, ráadásul messze ez a program bizonyult a leggyorsabbnak, úgyhogy miután lefutott, befejezettnek tekintettem a feladat megoldását. De nézzük, hogyan is működik ez az utolsó módszer (azután kedvenc mintám következik):

8. ábra: A színeltolás ötlete

A 8. ábrán az ötletem lényege látható, amit színeltolásnak neveztem el. Egy lapka színeltoltját úgy kapom, hogy minden ívének a színét "eltolom" a következő színre. Elvileg többféle sorrend választható, én a piros → sárga → kék → zöld → piros sorrendet választottam. Ilyenkor bármely lapkából kiindulva 4 lépés után visszajutunk önmagába (8. ábra), ezenfelül igaz az is, hogy mondjuk az első 14 lapkát véve (ezek azok, melyekben nincs zöld ív), és ezeket négyszer eltolva a teljes készlet minden lapkáját pontosan egyszer fogjuk megkapni. Nézzük ezek után, miképpen kerestem "extraszimmetrikus" mintákat:

 

9. ábra: az "extraszimmetrikus" minták táblája

Vettem egy mindössze 2x7-es méretű táblát, és ezt próbáltam a szokásos módon kitölteni. Két dolgot kivéve: az egyik, hogy a 2x7-es minta alja ne ugyanolyan legyen, mint a teteje, hanem éppen a színeltoltja. A másik dolog pedig, hogy nem 14 lapkát próbáltam felülre elhelyezni, hanem mind az 56-ot, viszont ha egy lapkát letettem a táblára, akkor az egyszeres, kétszeres illetve háromszoros színeltoltját is kiszedtem a még felhasználható lapkák közül. Visszalépésnél pedig értelemszerűen nem csak a visszalépésnél felszabadult lapka lett újra felhasználható, hanem mindhárom színeltoltja is.

Ezáltal mire kitöltöttem a felső táblát, éppen minden lapka elfogyott. A felső 2x7-es tábla egyszeres, kétszeres és háromszoros színeltolásával pedig rendre megkaptam a 2., 3. és 4. negyedét a táblának. Így kis számolással (mindössze 14 lapka nyomon követésével) könnyen tudtam találni (négyszeresen) szimmetrikus kitöltéseket.

 

10. ábra: kedvenc mintám, egy dinó

 

Ezt a programot már lefuttattam végig, és a végén, kb. 10 másodperc alatt 3742 helyes kitöltést (és ezek tükörképeit) kaptam eredményül. Mivel ez kezelhetetlenül nagy szám, ezért tovább specializáltam a keresést: csak olyan megoldásokat tartottam meg, melyeknél a színek periódusonként 42 lapkás (azaz maximális, egy adott színből minden lapkát tartalmazó) hurkokat alkotnak. Ezzel a számomra érdekes megoldások száma lecsökkent 224-re (és ugyanennyi tükörképre). Ezek között már nem tudtam különbséget tenni szabályossági alapon, ezért a 10. ábrán kedvencemet, a dinoszauruszt láthatjátok (a jobb láthatóság érdekében 2x2 periódust megjelenítve). Ezzel az ábrával végére is értem összefoglalómnak, remélem, nem volt túlságosan technikai jellegű ahhoz, hogy emellett szórakoztató is legyen. És ha bármi megjegyzésed, ötleted van a problémával kapcsolatban, írj!

 

Szobonya László, 2004. január 10.