2017-04-25 2 views
1

Aus Spaß habe ich versucht, einen Knight's Tour (https://en.wikipedia.org/wiki/Knight%27s_tour) Löser in gprolog mit der Warnsdorf-Regel zu schreiben.Übersetzen eines tabellierten Prädikats von b-prolog nach gprolog

Ich fand einen anderen SO Post nach der Effizienz, die eine Lösung in B-Prolog zur Verfügung stellte: knight's tour efficient solution.

Mein Problem ergibt sich mit dem folgenden Abschnitt:

:- table warnsdorff(+,+,+,+,+,-,-,min). 
warnsdorff(R, C, X, Y, Visits, NewX, NewY, Score) :- 
    possible_knight_moves(R, C, X, Y, Visits, NewX, NewY), 
    possible_moves_count(R, C, NewX, NewY, [(NewX, NewY) | Visits], Score). 

B-prolog Merkmale eingereicht Prädikate und gprolog nicht. Ich habe große Schwierigkeiten, den Tabellenabschnitt in gprolog zu übersetzen. In der Praxis soll die Funktion die Bewegung von der aktuellen Position zurückbringen, die die kleinste Anzahl der möglichen Züge von der neuen Position (Krawatten sind zufällig ausgewählt) ergibt.

Jede Hilfe würde sehr geschätzt werden. Prost!

+1

Frage Dr. Google über "Springer Tour Prolog". Es gibt viele Lösungen. – false

+0

"zum Spaß" ähnliche Fragen beginnen zu schwärmen machen mich denken, das ist eine Zuordnung (siehe http://stackoverflow.com/questions/43622353/gprolog-knights-tour-using-warnsdorffs-rule und http: // stackoverflow. com/questions/43628413/simulating-knight-movement-using-prolog) – Rafalon

Antwort

1

Wahrscheinlich ist Tabling Overkill für dieses Problem. Da die Visits Listen bereits beim Lösen ausgeführt werden, verwenden Sie einfach memberchk/2. Ich erhalte diese Lösung in SWI-Prolog (wo, BTW, Einreichungs implementiert ist, aber nicht das Rätsel lösen mit der ursprünglichen Codierung Sie verknüpft):

?- time(knight(8, 8, 1, 1, [], Path))... 
% 19,973 inferences, 0.019 CPU in 0.019 seconds (100% CPU, 1047591 Lips) 
[(1,1),(2,3),(1,5),(2,7),(4,8),(6,7),(8,8),(7,6),(6,8),(8,7),(7,5),(8,3),(7,1),(5,2),(3,1),(1,2),(2,4),(1,6),(2,8),(3,6),(1,7),(3,8),(5,7),(7,8),(8,6),(7,4),(8,2),(6,1),(4,2),(2,1),(1,3),(3,2),(5,1),(6,3),(8,4),(7,2),(5,3),(4,1),(2,2),(1,4),(3,3),(2,5),(4,4),(6,5),(4,6),(3,4),(5,5),(4,3),(6,2),(8,1),(7,3),(5,4),(3,5),(4,7),(2,6),(1,8),(3,7),(4,5),(6,4),(5,6),(7,7),(5,8),(6,6),(8,5)] 

Wenn Sie wollen, ich Ihnen die Warnsdorff Regel zeigen . Ich habe setof/3 verwendet, um die minimale Anzahl zu erhalten, die possible_knight_moves/7 und possible_moves_count/6 verbindet.

bearbeiten

nach Bedarf:

warnsdorff(R, C, X, Y, Visits, NewX_, NewY_) :- 
    setof((Count, NewX, NewY), (
       possible_knight_moves(R, C, X, Y, Visits, NewX, NewY), 
       possible_moves_count(R, C, NewX, NewY, [(NewX, NewY) | Visits], Count) 
     ), [(_, NewX_, NewY_)|_]). 

Aus Gründen der Übersichtlichkeit habe ich die Ausgangsvariablen NewX_, NewY_ umbenannt, aber das ist irrelevant - es mit der ursprünglichen Namensgebung als auch gearbeitet.

+0

Ich stimme zu, aber es macht den Code viel einfacher. Wenn Sie Ihre Warnsdorff-Regel zeigen könnten, würden wir uns freuen. Ich kann nicht genau herausfinden, was du als Ziel in deiner Aufrechnung benutzt hast/3. –

+0

Ah, das ist ziemlich einfach. Ich denke, es war nicht der richtige Weg, um 2 Uhr morgens in Prolog zu denken. Ich habe seltsame Probleme, bei denen possible_knight_moves/7 'no' zurückgibt, wenn die not-Klausel (\ + memberchk ((NewX, NewY), Besuche)) eine NewX und NewY erhält, die bereits in der Liste sind. Es dauert etwa 15 Iterationen, bevor dies auftritt. Haben Sie andere Abschnitte geändert? –

+0

Korrektur: Es schlägt fehl, weil es keinen weiteren Zug zu finden gibt. Mein vorheriger Kommentar ergab sowieso keinen Sinn. –

Verwandte Themen