Das allgemeine SAT- Problem (Boolesche Erfüllbarkeit) ist NP-vollständig. Aber 2-SAT , wobei jede Klausel nur zwei Variablen hat, ist in P . Schreiben Sie einen Löser für 2-SAT.
Eingang:
Eine 2-SAT-Instanz, die wie folgt in CNF codiert ist . Die erste Zeile enthält V, die Anzahl der Booleschen Variablen und N, die Anzahl der Klauseln. Dann folgen N Zeilen mit jeweils 2 Ganzzahlen ungleich Null, die die Literale einer Klausel darstellen. Positive Ganzzahlen repräsentieren die angegebene boolesche Variable und negative Ganzzahlen repräsentieren die Negation der Variablen.
Beispiel 1
Eingang
4 5
1 2
2 3
3 4
-1 -3
-2 -4
welches die Formel (x 1 oder x 2 ) und (x 2 oder x 3 ) und (x 3 oder x 4 ) und (nicht x 1 oder nicht x 3 ) und (nicht x 2 oder nicht x 4 ) codiert .
Die einzige Einstellung der 4 Variablen, die die gesamte Formel wahr macht, ist x 1 = falsch, x 2 = wahr, x 3 = wahr, x 4 = falsch , daher sollte Ihr Programm die einzelne Zeile ausgeben
Ausgabe
0 1 1 0
Darstellen der Wahrheitswerte der V-Variablen (in der Reihenfolge von x 1 bis x V ). Wenn es mehrere Lösungen gibt, können Sie jede nicht leere Teilmenge davon ausgeben, eine pro Zeile. Wenn es keine Lösung gibt, müssen Sie ausgeben UNSOLVABLE
.
Beispiel 2
Eingang
2 4
1 2
-1 2
-2 1
-1 -2
Ausgabe
UNSOLVABLE
Beispiel 3
Eingang
2 4
1 2
-1 2
2 -1
-1 -2
Ausgabe
0 1
Beispiel 4
Eingang
8 12
1 4
-2 5
3 7
2 -5
-8 -2
3 -1
4 -3
5 -4
-3 -7
6 7
1 7
-7 -1
Ausgabe
1 1 1 1 1 1 0 0
0 1 0 1 1 0 1 0
0 1 0 1 1 1 1 0
(oder jede nicht leere Teilmenge dieser 3 Zeilen)
Ihr Programm muss alle N, V <100 in angemessener Zeit verarbeiten. Probieren Sie dieses Beispiel aus , um sicherzustellen, dass Ihr Programm eine große Instanz verarbeiten kann. Das kleinste Programm gewinnt.
Antworten:
Haskell, 278 Zeichen
Keine rohe Gewalt. Läuft in Polynomzeit. Löst das schwierige Problem (60 Variablen, 99 Klauseln) schnell:
Und tatsächlich wird die meiste Zeit damit verbracht, den Code zu kompilieren!
Vollquelldatei, mit Testfällen und Quick-Check - Tests zur Verfügung .
Ungolf'd:
In der golf'd Version,
satisfy
undformat
wurde in gerolltreduce
, wenn auch um zu vermeiden , beiläufign
,reduce
eine Funktion aus einer Liste von Variablen (zurück[1..n]
) auf das String Ergebnis.s
Operator gemacht, besseres Handling der Newline∮
als Operator benutze !★
testen also jetzt umbenannt∈
quelle
J
119,103Besteht alle Testfälle. Keine merkliche Laufzeit.Edit: Ausgeschieden
(n#2)
und damitn=:
auch einige Rangparens (danke, isawdrones). Tacit-> explizit und dyadisch-> monadisch, wobei jeweils einige weitere Zeichen eliminiert werden.}.}.
zu}.,
.Bearbeiten: Whoops. Dies ist nicht nur eine Nichtlösung für große N, sondern
i. 2^99x
-> "Domänenfehler", um die Dummheit zu beleidigen.Hier ist die unbespielte Originalversion und eine kurze Erklärung.
input=:0&".;._2(1!:1)3
Schneidet Eingaben in Zeilenumbrüchen ab und analysiert die Zahlen in jeder Zeile (Summierung der Ergebnisse in Eingaben).n
, Klauselmatrix ist zugewiesenclauses
(die Klauselzählung ist nicht erforderlich)cases
ist 0..2 n -1 konvertiert in binäre Ziffern (alle Testfälle)(Long tacit function)"(_,1)
wird auf jeden fallcases
bei allen angewendetclauses
.<:@|@[{"(0,1)]
Ruft eine Matrix der Operanden der Klauseln ab (indem abs (op number) - 1 genommen und aus case, einem Array, dereferenziert wird)*@>:@*@[
Erhält eine klauselförmige Anordnung von Nicht-Nicht-Bits (0 für Nicht) durch Missbrauch des Zeichens.=
Wendet die Nicht-Bits auf die Operanden an.[:*./[:+./"1
Wendet+.
(und) auf die Zeilen der resultierenden Matrix und*.
(oder) auf das Ergebnis davon an.*@+/
Auf Ergebnisse angewendet ergibt 0, wenn es Ergebnisse gibt, und 1, wenn es keine gibt.('UNSOLVABLE'"_)
`(#&cases) @.(*@+/) results
Führt eine konstante Funktion aus, die "UNSOLVABLE" bei 0 und eine Kopie jedes "solution" -Elements von Fällen bei 1 angibt.echo
Magie druckt das Ergebnis.quelle
"(_,1)
zu"_ 1
.#:
würde ohne das linke Argument funktionieren.K - 89
Die gleiche Methode wie die J-Lösung.
quelle
Rubin, 253
Aber es ist langsam :(
Ziemlich gut lesbar, wenn erweitert:
quelle
OCaml + Batterien,
438436 ZeichenBenötigt eine OCaml-Batterie
Ich muss gestehen, dies ist eine direkte Übersetzung der Haskell-Lösung. In meiner Verteidigung ist , dass wiederum ein direkter des Algorithmus Codierung hier präsentiert [PDF], mit der gegenseitigen
satisfy
-eliminate
Rekursion in einer einzigen Funktion gerollt. Eine nicht verschleierte Version des Codes ohne die Verwendung von Batterien lautet:(das
iota k
Wortspiel, das ich hoffe, Sie werden vergeben).quelle