Le problème général SAT (booléen satisfibility) est NP-complet. Mais 2-SAT , où chaque clause ne dispose que de deux variables est en P . Écrivez un solveur pour 2-SAT.
Contribution:
Une instance 2-SAT, codée en CNF comme suit. La première ligne contient V, le nombre de variables booléennes et N, le nombre de clauses. Ensuite, N lignes suivent, chacune avec 2 entiers non nuls représentant les littéraux d'une clause. Les entiers positifs représentent la variable booléenne donnée et les entiers négatifs représentent la négation de la variable.
Exemple 1
contribution
4 5
1 2
2 3
3 4
-1 -3
-2 -4
qui code la formule (x 1 ou x 2 ) et (x 2 ou x 3 ) et (x 3 ou x 4 ) et (pas x 1 ou pas x 3 ) et (pas x 2 ou pas x 4 ) .
Le seul paramètre des 4 variables qui rend la formule entière vraie est x 1 = faux, x 2 = vrai, x 3 = vrai, x 4 = faux , donc votre programme devrait sortir la seule ligne
production
0 1 1 0
représentant les valeurs de vérité des variables V (dans l'ordre de x 1 à x V ). S'il existe plusieurs solutions, vous pouvez générer n'importe quel sous-ensemble non vide, une par ligne. S'il n'y a pas de solution, vous devez sortir UNSOLVABLE
.
Exemple 2
contribution
2 4
1 2
-1 2
-2 1
-1 -2
production
UNSOLVABLE
Exemple 3
contribution
2 4
1 2
-1 2
2 -1
-1 -2
production
0 1
Exemple 4
contribution
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
production
1 1 1 1 1 1 0 0
0 1 0 1 1 0 1 0
0 1 0 1 1 1 1 0
(ou tout sous-ensemble non vide de ces 3 lignes)
Votre programme doit gérer tous les N, V <100 dans un délai raisonnable. Essayez cet exemple pour vous assurer que votre programme peut gérer une grande instance. Le plus petit programme gagne.
Réponses:
Haskell, 278 caractères
Pas de force brute. Fonctionne en temps polynomial. Résout le problème difficile (60 variables, 99 clauses) rapidement:
Et en fait, la plupart de ce temps est consacré à la compilation du code!
Fichier source complet, avec cas de test et tests de vérification rapide disponibles .
Non golfé:
Dans la version golf,
satisfy
etformat
ont été intégrésreduce
, bien que pour éviter de passern
,reduce
renvoie une fonction d'une liste de variables ([1..n]
) au résultat de la chaîne.s
un opérateur, une meilleure gestion de la nouvelle ligne∮
comme opérateur!★
donc le test est maintenant renommé∈
la source
J,
119103Réussit tous les cas de test. Aucun temps d'exécution notable.Edit: Éliminé
(n#2)
et doncn=:
, ainsi que l'élimination de certaines parens de rang (merci, isawdrones). Tacite-> explicite et dyadique-> monadique, éliminant chacun quelques caractères supplémentaires.}.}.
à}.,
.Edit: Oups. Non seulement c'est une non-solution pour les grands N, mais
i. 2^99x
-> "erreur de domaine" pour ajouter l'insulte à la stupidité.Voici la version originale non golfée et une brève explication.
input=:0&".;._2(1!:1)3
coupe les entrées sur les nouvelles lignes et analyse les nombres sur chaque ligne (en accumulant les résultats en entrée).n
, matrice de clause affectée àclauses
(n'a pas besoin du nombre de clauses)cases
est 0..2 n -1 converti en chiffres binaires (tous les cas de test)(Long tacit function)"(_,1)
est appliqué à chaque cascases
avec tousclauses
.<:@|@[{"(0,1)]
obtient une matrice des opérandes des clauses (en prenant abs (op number) - 1 et en déréférençant de case, qui est un tableau)*@>:@*@[
obtient un tableau en forme de clause de bits 'not not' (0 pour not) via un abus de signum.=
applique les bits non aux opérandes.[:*./[:+./"1
s'applique+.
(et) à travers les lignes de la matrice résultante, et*.
(ou) à travers le résultat de cela.*@+/
appliqué aux résultats donne un 0 s'il y a des résultats et 1 s'il n'y en a pas.('UNSOLVABLE'"_)
`(#&cases) @.(*@+/) results
exécute une fonction constante donnant 'UNSOLVABLE' si 0, et une copie de chaque élément 'solution' des cas si 1.echo
imprime le résultat par magie.la source
"(_,1)
à"_ 1
.#:
fonctionnerait sans l'argument de gauche.K - 89
La même méthode que la solution J.
la source
Rubis, 253
Mais c'est lent :(
Assez lisible une fois étendu:
la source
OCaml + Batteries,
438436 caractèresNécessite un OCaml Batteries inclus de niveau supérieur:
Je dois avouer que c'est une traduction directe de la solution Haskell. Pour ma défense, qui à son tour est un codage directe de l'algorithme présenté ici [PDF], avec la mutuelle
satisfy
-eliminate
récursion roulé en une seule fonction. Une version non obscurcie du code, sans l'utilisation de piles, est:(le
iota k
jeu de mots j'espère que vous pardonnerez).la source