猪会飞吗?


45

任务

您的任务是用您选择的语言编写函数或程序,该函数或程序分析几个语句并确定是否可以从这些语句中得出猪可以飞的结论。

输入项

输入是一个字符串,可以从STDIN读取,可以作为函数参数,甚至可以存储在文件中。可以使用以下EBNF描述输入:

input = statement , {statement};
statement = (("Pigs are ", attribute) | ("Everything that is ", attribute, "is also ", attribute)), ". ";
attribute = [not], ("able to fly" | singleAttribute);
singleAttribute = letter, {letter};
letter = "a" | "b" | "c" | "d" | "e" | "f" | "g"
       | "h" | "i" | "j" | "k" | "l" | "m" | "n"
       | "o" | "p" | "q" | "r" | "s" | "t" | "u"
       | "v" | "w" | "x" | "y" | "z" ;

输入示例(请参见下面的更多示例):

Pigs are green. Everything that is green is also intelligent. Everything that is able to fly is also not intelligent. Pigs are sweet. 

输出量

输出可以由您的函数返回,可以写入文件或打印到STDOUT。有5种不同的情况需要处理:

  1. 给定的陈述是有效,一致的,并且逻辑上会导致猪会飞。在这种情况下,您必须输出Yes
  2. 给定的陈述是有效,一致的,并且逻辑上导致猪不能飞。在这种情况下,您必须输出No
  3. 不能从给定的,有效的,一致的陈述中得出结论,即猪是否会飞。在这种情况下,您必须输出Maybe
  4. 给定的语句有效,但不一致(即给定的语句存在矛盾)。由于ex quodlibet,我们决定Yes在这种情况下输出。
  5. 给定的语句无效,即,未根据给定的EBNF格式化它们。在这种情况下,您可以做任何您想做的事情。

细节

  • 您可以假设给定的属性彼此独立。因此,例如,一头猪可以是老幼的,绿色,红色和蓝色的,而不会引起任何不一致。但是,猪可能不会同时是“绿色”和“不是绿色”,这是矛盾的,应按照(4)中所述进行处理。
  • 对于每个属性,假定宇宙中至少有一个具有给定属性的对象(不一定是猪),以及一个不具有给定属性的对象。

输入和输出示例

输入:

Pigs are green. Everything that is green is also intelligent. Everything that is able to fly is also not intelligent. 

输出:由于猪是绿色的,因此很聪明,并且所有能飞的都不聪明,所以猪不能飞。输出为No

输入:

Pigs are old. Everything that is not able to fly is also not old. 

输出:如果猪不能飞行,那么它们也不老。但是,由于它们很旧,您必须输出Yes

输入:

Everything that is sweet is also not old. Everything that is intelligent is also blue. 

输出: Maybe

输入:

Pigs are not able to fly. Everything that is red is also sweet. Everything that is sweet is also not red. 

输出:尽管第一个语句暗示猪不能飞,但以下语句彼此矛盾,因此输出必须为Yes

输入:

Pigs are very smart. Pigs are able to fly. 

输出:所需的任何内容,因为字符串不符合上述条件。

优胜者

这是,因此最短的正确答案(以字节为单位)获胜。在第一个正确答案发布后的一周内将选择获奖者。

飞猪


为什么第三个示例返回是?
xem 2014年

10
我正在考虑编写一个将输入转换为Prolog代码的答案。
2014年

1
您只能得出结论,没有红色存在。甜的,非红色的东西很好。
user2357112

1
我希望有更多示例,以便我自己做。
2014年

1
@xem:以前也是quodlibet,在Wikipedia上将其视为爆炸原理。如果存在矛盾,那么任何事情都可以得到证明。因此,如果“神存在”为真,“神不存在”为真,那么任何事物都可以证明为真,因此可以证明猪可以飞翔。
fightermagethief 2014年

Answers:


10

Perl,363 353 350 347 343 297 266 264

$_=<>;s/able to fly/X/g;$m=' ?(not )?\b(P|\w+)';$h{$1?N.$2:$2}{$3?N.$4:$4}=$h{$3?$4:N.$4}{$1?$2:N.$2}=1while s/$m.{8}$m\.//;map{%x=0,r($_,$_)}%h;sub r{($a,$b)=@_;$e+=$h{$a}{N.$b};$x{$b}++or$h{$a}{$b}=1,map{r($a,$_)}%{$h{$b}}}print$e|$h{P}{X}?Yes:$h{P}{NX}?No:Maybe

取消高尔夫/说明:

# Read one line from STDIN
$_=<>;
# Replaces special attribute with X
s/able to fly/X/g;
# Prepare attribute match
$m=' ?(not )?\b(P|\w+)';
# Match "Everything that is A is also B. "
#                        "\bA........ \bB\."
# Match "Pigs are B. "
#     "\bP........\bB\."
while(s/$m.{8}$m\.//)
{
  # Add facts for A => B and !B => !A, where A may equal "P" for "Pigs are"
  # Facts are stored as a hash of hashes %h; keys%h are the source attributes;
  # keys%{$h{$a}} are the attributes that follow from attribute $a
  # A "not attribute" is stored as "Nattribute", while a "attribute" is just stored as "attribute"
  $h{$1?N.$2:$2}{$3?N.$4:$4}=$h{$3?$4:N.$4}{$1?$2:N.$2}=1
}
# For all known source attributes ... (this should really be keys%h but we dont mind the extra hashrefs)
map{%x=0,r($_,$_)}%h;
sub r
{
  ($a,$b)=@_;
  # ... remember that we hit a negation and therefor an inconsistency ...
  # If we check/add $b and find an existing "N$b" that means that attribute $b is supposed to be true and not true at the same time
  # It is cheaper bytewise to just add up all consistency errors (remember each fact has a hard value of 1) than to exit right here
  $e+=$h{$a}{N.$b};
  # ... remember that we processed this attribute for the current source attribute so we prevent loops ...
  $x{$b}++or
  # ... add a new fact and then follow the chains (again omitting keys).
  $h{$a}{$b}=1,map{r($a,$_)}%{$h{$b}}
}
# Did we happen on an inconsistency? Do pigs fly? Dont pigs fly? Maybe (Bitwise or is okay too)
print$e|$h{P}{X}?Yes:$h{P}{NX}?No:Maybe

4
如果您能告诉我们它的工作原理/写一些评论,那就太好了!
瑕疵的

另一个支持更多评论的提议……特别需要进一步解释的内容吗?
Thaylon 2014年

添加了更多评论...
Thaylon 2014年

@AlanBerndt提出了一个后缀。由于他无法发表评论,因此我无法批准。我想说谢谢!这里。
Thaylon 2014年

10

哈斯克尔,586个 566 547字节

我写这个假设的前提是,对于每个属性P,都必须存在一些xy,使得P(x)为true,P(y)为false。如果没有这个假设,第四个示例输入将没有矛盾,并且将回答“否”。

#define X p s q m
#define W where
t=0<1;f=0>1;y="Yes"
l=length;r=filter;h=head;(#)=(,)
u 0=[[]];u n=[x:y|x<-[t,f],y<-u$n-1]
c l=all(==h l)l#and l
X[]|or[fst$c$map(!!(n-1))e|n<-[1..l$h e]]=y|z t=y|z f="No"|t="Maybe"W e=m$u$l s;z m=t#m==(c$map h$q e)
X("Pigs":_:y)=p v((r$(==a).(!!k)).q)m z W((k,v),z,a)=s%y
X(_:_:_:y)=p w q((r(\x->(x!!j/=a)||(x!!k==b))).m)v W((j,u),_:_:z,a)=s%y;((k,w),v,b)=u%z
s%("not":w)=(i,u,not p)W(i,u,p)=s%w
s%(_:"to":_:w)=(0#s,w,t)
s%(w:z)=(maybe(l s,s++[w#l s])(#s)$lookup w s,z,t)
main=interact$p[""#0]id id.words.r(/='.')

应该使用ghc命令行选项“ -cpp”进行编译。输入必须以EOF(^ D)终止。您可以在http://melpon.org/wandbox/上在线尝试它,但不能设置命令行选项。相反,您可以在程序前加上语言选项

{-# LANGUAGE CPP #-}

它通过收集特征集,然后使用输入中的含义过滤特征集->真值评估来工作。然后测试结果,以确保可以将每个特征都有效地分配给True和False(此处失败是另外的quodlibet情况)。最后,它寻找与猪事实相匹配的估值,并在每个估值中检查“能够飞行”的值。

线程状态丢失了很多字节:到目前为止看到的特征集,猪事实选择器功能以及由含义决定的过滤功能。如果用不纯正的语言表达,那么完全相同的想法可能会短得多。

编辑:通过自豪的haskeller的建议保存了几个字节,然后通过将z和“ u%drop 2 z”的绑定替换为对“ _:_:z”和“ u%z”的绑定,节省了两个字节,节省了3。

编辑2:保存了更多。使用(#)=(,)技巧来节省2个字节并了解了模式同义词(https://ghc.haskell.org/trac/ghc/wiki/PatternSynonyms),但是该符号太冗长而无法从中获取节省消除该程序中的其余对。通过更改解析器搜索的模式,节省了更多的节省。例如:如果一个句子不是以Pigs开头,并且在解析器状态中还剩下任何东西,我们将解析一个“ Everything that ...”句子。这在X和%的模式中节省了很多字符。


您的假设是正确的,我首先忘记提及它,但现在将其添加到详细信息部分!
vauge

2
您应该在字节数中包含这些标志(有关代码高尔夫,请参见标签Wiki)。因此,它是607个字节。
nyuszika7h 2014年

真的对吗?该链接仅提及与unicode编码有关的标志。meta提到了有关C ++标志-D(明显是作弊)与-std = c ++ 11(选择特定的语言版本,所以可能没关系)的类似问题。IMO所使用的标志用于启用Haskell98的相当通用的GHC扩展,因此类似于-std = c ++ 11。参考:meta.codegolf.stackexchange.com/questions/1859/…–
Matt Noonan

您可以将u的第二个定义替换为u n=(:)<$>[t,f]<*>u(n-1)(尽管这将需要导入Control.Applicative,所以第二个认为它更糟)
骄傲的haskeller 2014年

1
您可以用c l=(all(==l!!0)l,and l)
自豪的haskeller 2014年

6

Python,547 536 525 521 513 509 497 503 501

m=map
o='not ';R={'':{''}}
S=lambda x,y:filter(len,m(str.strip,x.split(y)))
N=lambda a:[o+a,a[4:]][a[:4]==o]
def C(s):a,c=S(s[19:],'is also');return[(a,c),(N(c),N(a))]
X=lambda A:A&set(m(N,A))and 1/0 or A
for a,c in sum(m(lambda x:[('',x[9:])]if'P'==x[0]else C(x),S(raw_input(),'.')),[]):R.setdefault(a,{a}).add(c)
def F(s):
 i,n={s},{s}
 while 1:
  for r in i:n|=R.get(r,n)
  if X(i)>=n:return i
  i|=n
try:a='able to fly';n=N(a);c={n:'No','':'Maybe'}[''.join({a,n}&m(F,R)[0])]
except:c='Yes'
print c

对于a -> b输入中的每一个,我们将给定的子句及其取反添加到子句not b -> not a 集中,然后->使用定点循环计算从任何命题均可到达的命题集。每当遇到矛盾时,我们都会抛出(并随后捕获)a ZeroDivisionError并打印Yes

最后,我们从“是猪”命题中检查“可飞”(和/或它的否定)是否可行,''并打印适当的回复。

编辑这是越野车,将其修复。固定。


1
你应该能够通过将节省2个字节try在同一行块作为try:
undergroundmonorail

@undergroundmonorail:感谢您发现!改变了。
user2361830

5

红宝石1.9.3(365 364 362)

h='able to fly'
i="(not )?(#{h}|\\w+)"
o=->s{n=Regexp.new(i+" (is also|are) "+i).match s
[[n[2],!n[1]],[n[5],!n[4]]]}
c=e=!z=[]
w=->r{z.member?(r)||(z<<(a,b=r)
c|=a[0]==b[0]&&a[1]!=b[1]
w[[[b[0],!b[1]],[a[0],!a[1]]]]
z.map{|q|q[1]==r[0]&&w[[q[0],r[1]]]})}
y=->x{z.member?([[p='Pigs',!e],[h,x]])}
f=->x{x.split(?.).map{|s|w[o[s]]}
c|y[!e]?'Yes':y[e]?'No':'Maybe'}

用法

以上定义了码的功能f,这需要表示所述文本输入,并返回一个参数YesNoMaybe

例如:

f['Pigs are old. Everything that is not able to fly is also not old.']
=> "Yes"

在线测试:http//ideone.com/fxLemg

此处提供未经处理的代码(包括单元测试)。


*可用(在标题“在线测试”下)。复数,我的好朋友。
Stan Strum,

@StanStrum谢谢!我修改了文字-我指的是代码可用的,它也包括单元测试。
Cristian Lupascu
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.