Jako interpretr prologu jsem použil SWI-Prolog, který je dodáván s vcelku přijatelnými licenčními podmínkami (a zdrojové kódy jsou součástí). Přikládám krátký patch, aby SWI-Prolog nepočítal percentuální podíly funkcí při profilování a vypnutí automatického garbage collectoru.
sigblock()
,
ale může to být jen problém mé instalace
Ačkoliv by oba programy (obě Prolog a jedna C verze) měly být spustitelné na jakékoliv platformě, uvádím testované/vývojové prostředí:
Díval jsem se také na BinProlog, ale zdrojové kódy nebyly vůbec k dispozici, a tudíž nepřipadl v úvahu.
Zadáním bylo převést hrací plochu ze vstupního tvaru:
/-------\ | {}{}# | | AB^#+ | | CDv#+ | | {}{}# | \-------/
postupným přesouváním kostek do tvaru:
/-------\ | ????? | | ???AB | | ???CD | | ????? | \-------/
kde znaky "?" samozřejmě představují políčka, na kterých nezáleží. Pro popis jednotlivých znaku bude lepší následující legenda:
AB - 2x2 |
{} - 2x1 |
^ - 1x2 |
# - 1x1 |
-volno-+ - 1x1 |
Postupné stavy hrací plochy při jednotlivých krocích minimálního (nejkratšího) řešení jsou v souboru "minsol.txt". Rozbor řešení úlohy je sumarizován zde:
Velikost stavového prostoru | 25955 |
Počet různých řešení | 482 (+sym.) |
Počet tahů nejkratšího řešení | 116 |
Počet různých nejkratších řešení | 1 (+sym.) |
Počet tahů nejdelšího řešení | 158 |
Počet různých nejdelších řešení | 7 (+sym.) |
Maximální počet tahů bez opakování | 167 |
Všechny tyto výsledky lze získat ze všech verzí (Prolog assert / Prolog hash / C), z rychlostních důvodů ovšem doporučuji použít C verzi. Pro některé výsledky je třeba zapnout ladící výpisy (v obou verzích se zapínají různě a nezdokumentovaně).
Poznámka "(+sym.)" znamená, že takových řešení je ve skutečnosti dvojnásobný počet než je uvedeno, ale tato zbylá řešení jsou symetrická dle X-ové osy. To vyplývá ze symetričnosti zadání dle osy X a tomu, že všechny povolené tahy žádným způsobem neupřednostňují či neomezují směr pohybu.
kategorie \ verze | Prolog assert | Prolog hash | C |
doba běhu bez výstupu | 1m:55s=115s | 4m:27s=267s | 0m:0.22s=~1s |
doba běhu s výstupem | 4m:29s=269s | 6m:19s=379s | 0m:1.90s=~2s |
paměťová náročnost | cca 50MB | cca 150MB (!) | cca 1MB |
V Prologu assert se využívá funkcí assert a flag. Toto řešení je rychlejší i přehlednější než následující, ale neodpovídá duchu Prologovského programování.
V Prologu hash používám hashování s velikostí tabulky 150 položek (deklarace "geths(150).", čímž se snažím převést stavový prostor do čtvercového tvaru, aby Prolog lineárně procházel hash index i hash link-list celkově minimální čas.
Varování: Při standardním spuštění (přes SWI-Prolog) Oslíka budou obě Prologovské verze dumpovat velké množství ladících informací. Pro "production" použití slouží bash skript "do", který tyto ladící informace ve zdrojovém kódu zruší a spustí automaticky prolog. Při spuštění bez parametrů vypíše tento skript help. Nadefinování prázdného termu jako funkce pro ladící výpis mělo bohužel drtivý dopad na rychlost interpretace.
Obě Prologovské verze víceméně neobsahují žádné komentáře, doporučuji si případně k nim otevřít verzi v C, kde je vše zřejmé.
STSTEP
")
nyní jaksi nadbytečný a působí spíše humorným dojmem. Celý kód jsem se také snažil hned napoprvé napsat co možná nejrychlejší.
Pro množinu stavů mám konstantní hashovací pole, seznam doposud nezpracovaných stavů i zpětné reference pro vypisování
výsledku (tj. z kterého stavu jsme se do aktuálního dostali).
{}{}#AB^#+CDv#+{}{}#
".
V Prologu jsem se původně potýkal s problémem nefungující unifikace nezatomizovaných řetězců, ale poté, co jsem objevil predikát "string_to_atom" již SWI Prolog unifikoval jak měl.
oslik.zip | celý package (včetně Makefile-u apod.) |
oslik-assert.pl | oslík v SWI-Prologu, assert verze |
oslik-hash.pl | oslík v SWI-Prologu, hash verze |
do | bash skript pro spuštění předchozích dvou programů |
oslik.c | oslík v ANSI C (+BSD extenze) |
minsol.txt | minimální řešení (CR/LF) |
pl-3.1.2.diff | patch pro SWI-Prolog 3.1.2 (viz výše) |
Datum: | 30. 12. 1998 |
Autor: | Jan Kratochvíl |
Kontakt: | e-mail web@jankratochvil.net |
Licence: | Public domain |
Tento software je poskytnut bez jakýchkoliv záruk a autor nenese žádnou zodpovědnost za škody způsobené jeho používáním. Autor se také vzdává jakýchkoliv práv, ale i závazků, dle smyslu public domain licence.