证明我是错的!


22

介绍

您的人生使命很简单:在互联网上证明人们做错了!
为此,您通常会仔细分析他们的陈述并指出他们之间的矛盾。
现在该使它自动化了,但是由于我们很懒惰,所以我们希望以最小的努力(最短代码)证明人们是错误的。

规格

输入项

您的输入将是合取范式的公式。对于格式,可以根据您的语言需要使用以下格式或定义自己的格式(不过,您可以使用的格式编码不能超过纯CNF)。但是,测试用例(此处)以以下格式提供(尽管生成您自己的用例并不难)。

您的输入将是一个变量列表的列表(您也可以将其读为字符串/需要字符串)。输入是合取范式(CNF)的公式,写为一子句,每个子句都是两个列表的列表。子句中的第一个列表对正文字(变量)进行编码,第二个列表对负(负)文字(变量)进行编码。子句中的每个变量都进行“或”运算,所有子句都进行“与”运算。

更清楚地说:[[[A,B],[C]],[[C,A],[B]],[[B],[A]]]可以理解为:
(A OR B OR (NOT C)) AND (C OR A OR (NOT B)) AND (B OR (NOT A))

输出量

输出为布尔值,例如某个真实值或一些虚假值。

该怎么办?

很简单:检查手头给出的公式是否可以满足要求,例如,是否对所有变量都分配了true和false,以便整个公式得出“ true”。如果公式可满足要求,则输出将为“ true”,否则为“ false”。
事实:在一般情况下,这是一个NP完全问题。
注意:允许生成真值表并检查结果是否为真。

角落案例

如果您得到一个空的3级列表,则该子句中没有这样的(正/负)变量-有效输入。
如果需要,可以保留其他不确定的情况。
您也可以在公式为空(一级列表)时返回true,在子句为空(二级列表)时返回false。

谁赢?

这是代码高尔夫球,因此最短的答案以字节为单位!
标准规则当然适用。

测试用例

[[[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)

1
我们可以接受输入(A OR B OR (NOT C)) AND (C OR A OR (NOT B)) AND (B OR (NOT A))吗?
2013年

1
根据挑战中的说明,@Adám的格式完全取决于您,只要它不编码比基于列表的信息更多的信息即可。(例如,您所给的配方是完全允许的)
SEJPM

@SEJPM如果我正确理解了表示法,我认为第3和第4个测试用例应该返回true。我尝试用(P,Q)=(1,1)和(P,Q,R,S,T)=(0,0,0,0,0)代替,发现两者都正确,所以至少应该有一个表达式为真的情况。
busukxuan

@busukxuan,我100%确信第三和第四个错误。对于3):这是{{P,Q},{P,!Q},{!P,Q},{!P,!Q}}(不是按此顺序),可以很容易地看出来是一个矛盾。对于4):这是一个简单的矛盾,因为P AND ... AND (NOT P)对于任何P值,它显然永远都不是正确的
。– SEJPM

2
有趣的是,较短的代码实际上需要花费更多的精力来编写。
user6245072 '16

Answers:


41

Mathematica,12个字节

SatisfiableQ

好吧,有一个内置的...

输入格式为And[Or[a, b, Not[c], Not[d]], Or[...], ...]。对于空子表达式,这确实可以正常工作,因为Or[]is FalseAnd[]is True

作为记录,一个解决方案从质询中接收基于列表的格式并进行转换,但它本身是44个字节,但是OP在注释中阐明了任何格式都可以,只要它不对任何其他信息进行编码即可:

SatisfiableQ[Or@@Join[#,Not/@#2]&@@@And@@#]&

18
因为Mathematica ...
Leaky Nun

11
Mathematica确实有大量的内置._。
TuxCrafting

3
@TùxCräftîñg 确实
jpmc26 2016年

15
在一秒钟之内,我认为这个答案是用晦涩的,基于堆栈的esolang编写的,仅靠偶然的机会,命令序列S a t i s f i a b l e Q就可以解决问题。只有那时,阅读理解才敲响了……
ojdo

3

Haskell,203 200字节

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)

这个挑战值得一个没有内在的答案,所以就到这里。在ideone上尝试一下。该算法仅尝试所有变量分配,然后检查其中之一是否满足公式。

输入采用的形式[([],["P","Q"]),(["Q","P"],[]),(["P"],["Q"]),(["Q"],["P"])],尽管每种具有相等性的类型都可以代替字符串来使用。

取消程式码:

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

1

JavaScript 6,69B

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

用法:

f('a|b')(['a','b'])
true
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.