高尔夫代码:通过解析英语解决“骑士与刀子”的逻辑问题


16

背景

有两个人,比尔和约翰。其中一个是骑士,总是说出真相,另一个是小刀,总是说出谎言。您不知道谁是骑士,谁是骑士。然后每个人都说几句关于谁是小刀和谁是骑士。使用此信息,您必须得出结论,谁是骑士,谁是骑士。

骑士和无赖逻辑问题是基于Booleen代数。一个人说的话构成了Booleen可满足性问题。骑士的陈述必须始终为false,其他骑士的陈述必须始终为true。

约翰说:“我既是个刀匠,比尔也是个刀匠”。如果约翰是骑士,那么这个说法将是错误的,因此他不能成为骑士。如果他是骑士,而比尔是骑士,那么即使第一部分是正确的,这个陈述仍然是错误的。所以,约翰是个k夫。

挑战

您面临的挑战是编写尽可能最短的程序,该程序将列出每个人的声明列表,并弄清楚谁是骑士,谁是骑士。有很多细节要介绍,因此在三个部分中描述了此问题。

输入值

输入将是两行,后跟一个换行符。每行将给出一个字符的名称,后跟一个冒号,然后是该人说的几句话。如果一个人是骑士,那么他所有的句子都是正确的,而所有那位知识分子的句子都是错误的。句子的第一个字母将始终大写,并且每个句子将以句号结尾。这是一个例子:

Joe: Both I am a knight and neither Steve is a knave nor I am a knave.
Steve: Joe is a knave. Either Joe is a knight or I am a knight.

解析中

每个句子至少包含一个从句。每个子句包含以下几项之一(希望您能理解我的表示法):

both [clause] and [clause]
either [clause] or [clause]
neither [clause] nor [clause]
[I am | (other person's name) is] a [knight | knave]

这是明确的,因为可以用类似于波兰表示法的方式来理解。这是一个句子的示例:

Both I am a knight and neither Steve is a knave nor I am a knave.

转换为Booleen代数很简单。“两个”语句都是AND,“两个”语句都是XOR,“两个”语句都是NOR。

(I am a knight) AND ((Steve is a knave) NOR (I am a knave))

输出量

输出将包含两行。每行包括一个人的名字(按顺序),然​​后说出他是骑士还是or夫。总会有一个骑士和一个刀法。这是以上示例的输出:

Joe is the knave.
Steve is the knight.

如果问题无法解决(您无法分辨谁是谁,或者没有解决方案),那么您的程序可以做任何事情,但不能产生有效的输出。

更多例子

输入值

Sir Lancelot: Either both I am a knight and Merlin is a knave or both I am a knave and Merlin is a knight.
Merlin: Either both I am a knight and Sir Lancelot is a knight or both I am a knave and Sir Lancelot is a knave.

输出量

Sir Lancelot is the knight.
Merlin is the knave.

输入值

David: Neither I am a knave nor Patrick is a knight. Either I am a knight or Patrick is a knave.
Patrick: Either I am a knight or both I am a knight and David is a knight.

输出量

David is the knave.
Patrick is the knight.

输入值

Lizard: I am a knight.
Spock: I am a knave.

一种可能的输出

Rock Paper Scissors

规则,条例和说明

  1. 适用标准守则的高尔夫球规则
  2. 您的程序只能由可打印的ASCII组成
  3. 所有输入和输出将来自STDIN和STDOUT

区分大小写怎么办?您的语法描述是小写的,您的示例是大写的。是否不区分大小写?
ugoren

每个词的首字母将大写,但除此之外,仅姓名将大写。您看到什么具体问题?
PhiNotPi'4

由于您使用正确的英文大写字母,因此,第一个/两个/第一个字母均取决于上下文。我想不区分大小写是处理它的简单方法。
ugoren

Answers:


6

Python,491个字符

通过将每行转换为Python表达式并进行评估来工作。
刀和骑士的评估值为0和1。对于这两个人,我们尝试两种选择。
例如,Joe: Steve is a knave变为Joe==(Steve==knave)。这样,如果他Joe是一个刀匠,那么只有他在说谎,结果才是正确的。
当不可能或不确定时,您会收到难看的错误。如果不可能,r[0]则为索引错误,因为r为空。如果r[1:]无法确定,则连接到字符串列表会引起麻烦。

import sys
def p():
    a=s.pop(0)
    try:return{"both":"(%s*%s)","either":"(%s|%s)","neither":"(1-(%s|%s))"}[a.lower()]%(p(),p())
    except KeyError:r=s[2];del s[:4];return"(%s==%s)"%((a,m)[a=="I"],r)
x=[];w=[]
for l in sys.stdin:
    m,l=l.split(":");w+=[m]
    for s in l.split("."):
        s=s.split()
        while s:x+=["%s==%s"%(m,p())]
k=("knave","knight")
r=[a for a in[{w[0]:z,w[1]:1-z}for z in(0,1)]if all(eval(l,{k[0]:0,k[1]:1},a)for l in x)]
print"\n".join(x+" is the "+k[r[0][x]]+"."for x in w+r[1:])

3

Ruby,352个字符

解决方案变得相当长,因此可能仍然有打高尔夫球的地方。它要求输入的格式正确(就像上面的所有示例一样,但是不要试图将人都命名为“ Both” ...)。

q=->{gets.split /: |\.\s/}
C,*E=q[]
D,*F=q[]
r=->c,m{t=c.shift;t[1]?(x=r[c,m];c.shift;y=r[c,m];t[0]==?B?x&y :t[0]==?E?x^y :1-(x|y)):(c.shift(2);h=c.shift[2]==?I?m : 1-m;t==?I?h :1-h)}
s=->u,v,b{u.map{|c|r[c.gsub(v,?J).upcase.split,b]==b}.all?}
t=->b{s[E,D,b]&&s[F,C,1-b]}
u=->v,b{v+" is the kn#{b ?:ight: :ave}."}
puts t[1]^t[0]&&u[C,t[1]]+$/+u[D,t[0]]

您似乎在输出中省略了句点,但似乎解决了两个字符的问题。
PhiNotPi'4

1
@PhiNotPi完成。是零字符修复吗?
Howard

0

Perl-483字节

(($a,$b),($c,$d))=map{split':'}@ARGV;$h='y';$i='x';$s=' is the kn';$g='ight.';$v='ave.';for($b,$d){$_.=' 1';s/ am a | is a /==/g;s/knight/1)/g;s/knave/0)/g;s/I=/(\$$i=/g;s/($a|$c)=/(\$$h=/g;s/([^.]+)\./($1)and/g;s/ or / xor /g;s/ nor / or /g;while(s/(?<= )(\w+ \((?:[^()]+|(?1))\) \w+ \((?:[^()]+|(?1))\))/($1)/g){}s/neither/!/gi;s/both|either//gi;$h=$i++}$x=0;$y=1;$k=!eval($b)&&eval($d);$x=$y--;$n=!eval($d)&&eval($b);print"$a$s$v
$c$s$g"if($k&&!$n);print"$a$s$g
$c$s$v"if($n&&!$k)

与Python解决方案相似。它将句子简化为Perl代码,然后eval对其进行处理。如果输入很奇怪,它可以打印几乎有效的输出,但是如果输入不确定,则不打印任何内容。格式正确的输入将按预期工作。句子在引号内的命令行中传递,不需要特殊标志。

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.