Schreiben Sie einen ASP / Prolog / SAT-Flusslöser

9

Flow Free ist ein süchtig machendes Android-Spiel, bei dem Sie Elementpaare über nicht überlappende Schlangen miteinander verbinden und das gesamte Raster ausfüllen müssen. Eine Beschreibung finden Sie hier:

https://play.google.com/store/apps/details?id=com.bigduckgames.flow&hl=de

Ich habe eine ASP-Lösung (Answer Set Programming), die nur ein paar Regeln enthält, und ich glaube nicht, dass es möglich ist, dieselbe Lösung fast so präzise wie eine SAT-Instanz zu formulieren, aber ich wäre daran interessiert, mich als falsch zu erweisen.

Jede Sprache ist in Ordnung, aber ich bezweifle, dass sie präzise ausgeführt werden kann, ohne dass ein Solver ausgeführt wird, weshalb ich sie als ASP / Prolog / SAT bezeichnet habe

Gewinner sind die wenigsten Charaktere.

Sie können davon ausgehen, dass das Problem mithilfe der Prädikate definiert wird:

v(V). % A vertex

a(V,W). % V and W are adjacent

c(C). % A color

s(V,C). % V is an endpoint of color C

Darüber hinaus erfüllt die Eingabe

a(W,V) :- a(V,W) % Adjacencies are bidirectional

2{s(V,C) : v(V)}2 :- c(C). % Every color has exactly two endpoints

Das Lösungsprädikat hat die Form

e(V,W,C).

Angenommen, es gibt eine Kante zwischen V und W der Farbe C.

Die Kanten müssen bidirektional sein (von derselben Farbe). Jeder Scheitelpunkt muss Kanten von und zu genau einer Farbe haben. Endpunkte haben genau eine Kante, alle anderen Eckpunkte haben genau zwei Kanten. Es gibt keine Schleifen, jede Schlange muss bis zu zwei Endpunkten zurückverfolgbar sein.

Hier ist eine Beispieleingabe zum Testen (5x5 Level 2 im regulären Paket):

v(v11; v12; v13; v14; v15).
v(v21; v22; v23; v24; v25).
v(v31; v32; v33; v34; v35).
v(v41; v42; v43; v44; v45).
v(v51; v52; v53; v54; v55).

a(v11, v12).
a(v12, v13).
a(v13, v14).
a(v14, v15).
a(v12, v11).
a(v13, v12).
a(v14, v13).
a(v15, v14).
a(v11, v21).
a(v12, v22).
a(v13, v23).
a(v14, v24).
a(v15, v25).

a(v21, v22).
a(v22, v23).
a(v23, v24).
a(v24, v25).
a(v22, v21).
a(v23, v22).
a(v24, v23).
a(v25, v24).
a(v21, v31).
a(v22, v32).
a(v23, v33).
a(v24, v34).
a(v25, v35).
a(v21, v11).
a(v22, v12).
a(v23, v13).
a(v24, v14).
a(v25, v15).

a(v31, v32).
a(v32, v33).
a(v33, v34).
a(v34, v35).
a(v32, v31).
a(v33, v32).
a(v34, v33).
a(v35, v34).
a(v31, v41).
a(v32, v42).
a(v33, v43).
a(v34, v44).
a(v35, v45).
a(v31, v21).
a(v32, v22).
a(v33, v23).
a(v34, v24).
a(v35, v25).

a(v41, v42).
a(v42, v43).
a(v43, v44).
a(v44, v45).
a(v42, v41).
a(v43, v42).
a(v44, v43).
a(v45, v44).
a(v41, v51).
a(v42, v52).
a(v43, v53).
a(v44, v54).
a(v45, v55).
a(v41, v31).
a(v42, v32).
a(v43, v33).
a(v44, v34).
a(v45, v35).

a(v51, v52).
a(v52, v53).
a(v53, v54).
a(v54, v55).
a(v52, v51).
a(v53, v52).
a(v54, v53).
a(v55, v54).
a(v51, v41).
a(v52, v42).
a(v53, v43).
a(v54, v44).
a(v55, v45).

s(v11, yellow).
s(v45, yellow).
s(v41, blue).
s(v55, blue).
s(v51, red).
s(v43, red).
s(v42, green).
s(v33, green).

c(red; green; blue; yellow).

Und um die Ausgabe zu testen

shouldbe(v33,v32,green).
shouldbe(v42,v32,green).
shouldbe(v43,v53,red).
shouldbe(v51,v52,red).
shouldbe(v55,v54,blue).
shouldbe(v41,v31,blue).
shouldbe(v45,v35,yellow).
shouldbe(v11,v12,yellow).
shouldbe(v12,v11,yellow).
shouldbe(v35,v45,yellow).
shouldbe(v31,v41,blue).
shouldbe(v54,v55,blue).
shouldbe(v52,v51,red).
shouldbe(v53,v43,red).
shouldbe(v32,v42,green).
shouldbe(v32,v33,green).
shouldbe(v53,v52,red).
shouldbe(v52,v53,red).
shouldbe(v54,v44,blue).
shouldbe(v31,v21,blue).
shouldbe(v35,v25,yellow).
shouldbe(v12,v13,yellow).
shouldbe(v13,v12,yellow).
shouldbe(v25,v35,yellow).
shouldbe(v21,v31,blue).
shouldbe(v44,v54,blue).
shouldbe(v44,v34,blue).
shouldbe(v21,v22,blue).
shouldbe(v25,v15,yellow).
shouldbe(v13,v14,yellow).
shouldbe(v14,v13,yellow).
shouldbe(v15,v25,yellow).
shouldbe(v22,v21,blue).
shouldbe(v34,v44,blue).
shouldbe(v34,v24,blue).
shouldbe(v22,v23,blue).
shouldbe(v15,v14,yellow).
shouldbe(v14,v15,yellow).
shouldbe(v23,v22,blue).
shouldbe(v24,v34,blue).
shouldbe(v24,v23,blue).
shouldbe(v23,v24,blue).

:-not e(V,W,C),shouldbe(V,W,C).
:-e(V,W,C),not shouldbe(V,W,C).

Auch Level 21 5x5 sollte das erste Puzzle mit mehr als 1 Lösung sein (insbesondere gibt es 9 Lösungen, nicht 40). Um Level 21 einzurichten, setzen Sie die letzten Zeilen der Eingabe auf

s(v55, yellow).
s(v44, yellow).
s(v15, blue).
s(v45, blue).
s(v51, red).
s(v53, red).
s(v22, green).
s(v14, green).
s(v23, orange).
s(v43, orange).

c(red; green; blue; yellow; orange).
dspyz
quelle
Siehe auch codegolf.stackexchange.com/questions/38366/…
Christian Sievers

Antworten:

4

ASP (Clingo), 180 Bytes

{e(V,W,C):a(V,W),c(C)}.r(V):-s(V,_).r(V):-r(W),e(W,V,_).o(V):-r(V),{e(V,W,_):v(W);s(V,_)}=2.:-e(V,_,C),e(V,_,D),C!=D.:-e(V,W,C),not e(W,V,C).:-v(V),not o(V).:-s(V,C),e(V,_,D),C!=D.

Ich bin neu bei ASP und war begeistert, diese Aufgabe zu finden, auch wenn sie etwas alt ist. Es war schön zu sehen, dass es Orte für Variationen und eine Gelegenheit zum Golfen gab, was zu den Grenzen meines Verständnisses führte (ich hoffe, es ist immer noch richtig, es scheint zu sein).

Hier ist eine kommentierte Version:

% Select some edges e(V,W,C) s.t. V and W are adjacent and C is a color.
{e(V,W,C):a(V,W),c(C)}.

% Auxilary predicates:

% A vertex is reachable from an endpoint if
% it is an endpoint ...
r(V):-s(V,_).
% ... or it has an edge to it from a reachable vertex.
r(V):-r(W),e(W,V,_).

% A vertex is okay if it is reachable and either
% is an endpoint with one edge or is not an endpoint and has two edges.
% This is golfed to: the set of edges from V and endpoints V has
% cardinality 2.
o(V):-r(V),{e(V,W,_):v(W);s(V,_)}=2.

% Constraints:  We do not want ...

% edges from the same vertex with different colors:
:-e(V,_,C),e(V,_,D),C!=D.

% edges without their inverses:
:-e(V,W,C),not e(W,V,C).

% vertices that are not okay:
:-v(V),not o(V).

% edges from endpoints with the wrong color
:-s(V,C),e(V,_,D),C!=D.

% We're only interested in the e predicate:
#show e/3.

Ich kenne keine verschiedenen ASP-Löser, aber ich habe Clingo verwendet, das in Debian im Gringo-Paket enthalten ist.

Wenn Sie ein Problem in einer Datei probund meinen Code in einer Datei haben solve, rufen Sie an clingo 0 prob solve. Für jede Lösung erhalten Sie die Liste der verwendeten farbigen Kanten (und alle anderen Prädikate, wenn Sie die Golfversion verwenden, bei der die #showLinie fehlt ). Wenn Sie nur die Anzahl der Lösungen wünschen, fügen Sie die Option hinzu -q. Wenn Sie nur wissen möchten, ob es mindestens eine Lösung gibt, rufen Sie ohne an 0.

Christian Sievers
quelle