¡Prueba que estoy equivocado!

22

Introducción

Tu misión en la vida es simple: ¡Demuestra que las personas están equivocadas en Internet!
Para hacer esto, generalmente analiza cuidadosamente sus declaraciones y señala la contradicción en ellas.
Es hora de automatizar esto, pero como somos flojos, queremos demostrar que las personas están equivocadas con el menor esfuerzo posible (léase: el código más corto) posible.

Especificación

Entrada

Su entrada será una fórmula en forma conjuntiva normal . Para el formato, puede usar el siguiente formato o definir el suyo, según las necesidades de su idioma (aunque no puede codificar más en el formato que el CNF puro). Sin embargo, los casos de prueba (aquí) se proporcionan en el siguiente formato (aunque no será demasiado difícil generar el suyo).

Su entrada será una lista de una lista de una lista de variables (también puede leerla como cadenas / requerir cadenas). La entrada es una fórmula en forma normal conjuntiva (CNF) escrita como un conjunto de cláusulas, cada una de las cuales es una lista de dos listas. La primera lista en la cláusula codifica los literales positivos (variables), la segunda lista codifica los literales (variables) negativos (negados). Cada variable en la cláusula se OR 'juntas y todas las cláusulas se AND' juntas.

Para hacerlo más claro: [[[A,B],[C]],[[C,A],[B]],[[B],[A]]]puede leerse como:
(A OR B OR (NOT C)) AND (C OR A OR (NOT B)) AND (B OR (NOT A))

Salida

La salida es booleana, por ejemplo, algún valor verdadero o algún valor falso.

¿Qué hacer?

Es simple: verifique si la fórmula dada a mano es satisfactoria, por ejemplo, si existe alguna asignación de verdadero y falso a todas las variables, de modo que la fórmula general arroje "verdadero". Su salida será "verdadera" si la fórmula es satisfactoria y "falsa" si no lo es.
Dato curioso: este es un problema NP-completo en el caso general.
Nota: Se permite generar una tabla de verdad y verificar si alguna entrada resultante es verdadera.

Casos de esquina

Si obtiene una lista vacía de tercer nivel, entonces no hay tal variable (positiva / negativa) en esa cláusula: una entrada válida.
Puede dejar otros casos de esquina sin definir si lo desea.
También puede devolver verdadero en una fórmula vacía (lista de primer nivel) y falso en una cláusula vacía (lista de segundo nivel).

¿Quién gana?

Este es el código de golf, por lo que gana la respuesta más corta en bytes.
Se aplican reglas estándar, por supuesto.

Casos de prueba

[[[P],[Q,R]],[[Q,R],[P]],[[Q],[P,R]]] -> true
[[[],[P]],[[S],[]],[[R],[P]],[[U],[Q]],[[X],[R]],[[Q],[S]],[[],[P,U]],[[W],[Q,U]]] -> true
[[[],[P,Q]],[[Q,P],[]],[[P],[Q]],[[Q],[P]]] -> false
[[[P],[]],[[],[P,S]],[[P,T],[]],[[Q],[R]],[[],[R,S]],[[],[P,Q,R]],[[],[P]]] -> false
optional behavior (not mandatory, may be left undefined):
[] -> true (empty formula)
[[]] -> false (empty clause)
[[[],[]]] -> false (empty clause)
SEJPM
fuente
1
¿Podemos tomar entrada como (A OR B OR (NOT C)) AND (C OR A OR (NOT B)) AND (B OR (NOT A))?
Adám
1
@ Adám, como se especifica en el desafío, el formato depende completamente de usted, siempre y cuando no codifique más información que la lista. (Por ejemplo, la formulación tal como la dio está totalmente permitida)
SEJPM
@SEJPM Si entiendo la notación correctamente, creo que los casos de prueba tercero y cuarto deberían ser verdaderos. Traté de sustituir (P, Q) = (1,1) y (P, Q, R, S, T) = (0,0,0,0,0) y encontré que ambos son verdaderos, por lo que al menos debería haber uno caso donde la expresión es verdadera.
busukxuan
@busukxuan, estoy 100% seguro de que el tercero y el cuarto son falsos. Para el 3): esto es {{P,Q},{P,!Q},{!P,Q},{!P,!Q}}(no en este orden) que se puede mostrar fácilmente es una contradicción. Para el 4): Esto es trivialmente una contradicción porque es lo P AND ... AND (NOT P)que obviamente nunca puede ser cierto para ningún valor de P.
SEJPM
2
Es curioso cómo el código más corto realmente requiere más esfuerzo para ser escrito.
user6245072

Respuestas:

41

Mathematica, 12 bytes

SatisfiableQ

Bueno, hay un incorporado ...

El formato de entrada es And[Or[a, b, Not[c], Not[d]], Or[...], ...]. Esto hace el trabajo correctamente para vacías sub-expresiones, porque Or[]es Falsey And[]es True.

Para el registro, una solución que recibe el formato basado en listas del desafío y realiza la conversión en sí es de 44 bytes, pero el OP aclaró en un comentario que cualquier formato está bien siempre que no codifique ninguna información adicional:

SatisfiableQ[Or@@Join[#,Not/@#2]&@@@And@@#]&
Martin Ender
fuente
18
Porque Mathematica ...
Leaky Nun
11
Mathematica realmente tiene una cantidad increíble de builtin ._.
TuxCrafting
3
@ TùxCräftîñg De hecho .
jpmc26
15
Por una fracción de segundo, pensé que esta respuesta estaba escrita en un oscuro esolang basado en apilamiento donde, por casualidad, la secuencia de comandos S a t i s f i a b l e Qresolvería el problema. Solo entonces, la comprensión lectora tocó a la puerta ...
ojdo
3

Haskell, 203 200 bytes

t=1<3
e%((t,f):r)=or((e<$>t)++map(not.e)f)&&e%r
e%_=t
u v b e s|s==v=b|t=e s
s e[]c=1<0
s e(v:w)c=e%c||s(u v t e)w c||s(u v(1<0)e)w c
g v[]=v
g v((t,f):r)=g(v++[x|x<-t++f,notElem x v])r
g[]>>=s(\x->t)

Este desafío merece una respuesta no incorporada, así que aquí tienes. Pruébalo con ideone . El algoritmo simplemente prueba todas las asignaciones de variables y verifica si una de ellas cumple con la fórmula.

La entrada tiene la forma de [([],["P","Q"]),(["Q","P"],[]),(["P"],["Q"]),(["Q"],["P"])], aunque en lugar de cadenas, todos los tipos con igualdad funcionarán.

Código sin golf:

type Variable   = String
type CNF        = [([Variable], [Variable])]
type Evaluation = (Variable -> Bool)

satisfies :: Evaluation -> CNF -> Bool
satisfies eval [] = True
satisfies eval ((t,f):r) = or(map eval t ++ map (not.eval) f) && satisfies eval r

update :: Evaluation -> Variable -> Bool -> Evaluation
update eval s b var = if var == s then b else eval var

search :: Evaluation -> [Variable] -> CNF -> Bool
search eval [] cnf = False
search eval (v:vars) cnf = satisfies eval cnf || search (update eval v True) vars cnf || search (update eval v False) vars cnf 

getVars :: CNF -> [Variable] -> [Variable]
getVars [] vars = vars
getVars ((t,f):cnf) vars = getVars cnf (vars ++ [v |v<-(t++f), notElem v vars])

isSat :: CNF -> Bool
isSat cnf = search (\x->True) (getVars cnf []) cnf
Laikoni
fuente
1

JavaScript 6, 69B

x=>f=(v,e)=>(e=v.pop())?[0,1].some(t=>f([...v],eval(e+'=t'))):eval(x)

Uso:

f('a|b')(['a','b'])
true
l4m2
fuente