Os porcos são capazes de voar?

45

Tarefa

Sua tarefa é escrever uma função ou um programa em um idioma de sua escolha que analise algumas declarações e determine se é possível concluir com base nessas declarações que os porcos são capazes de voar.

Entrada

A entrada é uma String que pode ser lida em STDIN, usada como argumento de função ou mesmo armazenada em um arquivo. A entrada pode ser descrita usando o seguinte 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" ;

Exemplo de entrada (veja mais exemplos abaixo):

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

Resultado

A saída pode ser retornada por sua função, ser gravada em um arquivo ou impressa em STDOUT. Existem 5 casos diferentes a serem tratados:

  1. As declarações dadas são válidas, consistentes e têm como consequência lógica que os porcos possam voar. Nesse caso, você deve produzir Yes.
  2. As declarações dadas são válidas, consistentes e têm como consequência lógica que os porcos não podem voar. Nesse caso, você deve produzir No.
  3. Não se pode concluir com base em declarações válidas e consistentes, se os porcos podem voar ou não. Nesse caso, você deve produzir Maybe.
  4. As declarações dadas são válidas, mas não consistentes (ou seja, há uma contradição nas declarações dadas). Desde o ex quodlibet falso , decidimos produzir Yesnesse caso.
  5. As instruções fornecidas não são válidas, ou seja, não são formatadas de acordo com o EBNF fornecido. Nesse caso, você pode fazer o que quiser.

Detalhes

  • Você pode assumir que os atributos fornecidos são independentes um do outro. Assim, por exemplo, um porco pode ser jovem e velho, verde, vermelho e azul ao mesmo tempo, sem causar inconsistência. No entanto, um porco pode não ser 'verde' e 'não verde' ao mesmo tempo, isso é uma contradição e deve ser tratado como descrito em (4).
  • Para cada atributo, suponha que exista pelo menos um objeto (não necessariamente um porco) no universo que tenha o atributo fornecido e um objeto que não o possua.

Exemplo de entradas e saídas

Entrada:

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

Resultado: Como os porcos são verdes e, portanto, inteligentes, e tudo o que é capaz de voar não é inteligente, os porcos não podem voar. Saída é No.

Entrada:

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

Resultado: se os porcos não conseguiam voar, eles também não eram velhos. Mas como eles são antigos, você deve produzir Yes.

Entrada:

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

Saída: Maybe .

Entrada:

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

Saída: Embora a primeira declaração implique que os porcos não podem voar, as seguintes declarações se contradizem e, portanto, a saída deve ser Yes.

Entrada:

Pigs are very smart. Pigs are able to fly. 

Saída: o que você quiser, pois a String não corresponde aos critérios mencionados acima.

Vencedora

Isso é , então a resposta correta mais curta (em bytes) vence. O vencedor será escolhido uma semana após a publicação da primeira resposta correta.

Um porco voador

vauge
fonte
por que o terceiro exemplo retorna yes?
xem
10
Estou pensando em escrever uma resposta que traduza a entrada em código Prolog.
Tal
1
Você só pode concluir que não existe nada vermelho. Coisas doces e não vermelhas estão bem.
precisa saber é o seguinte
1
Eu estava esperando por mais exemplos, só para eu mesmo poder fazê-los.
precisa saber é
1
@xem: ex falso quodlibet, procure na wikipedia como o princípio da explosão. Se existe uma contradição, qualquer coisa pode ser provada. Portanto, se "deus existe" é verdadeiro e "deus não existe" é verdadeiro, qualquer coisa pode ser mostrada como verdadeira; portanto, os porcos podem voar podem ser provados verdadeiros.
Fightermagethief 19/09/14

Respostas:

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

Ungolfed / Explicação:

# 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
Thaylon
fonte
4
Seria ótimo se você pudesse nos dizer como funciona / escrever alguns comentários!
flawr
E outro voto positivo para mais comentários ... alguma coisa em particular precisa de mais explicações?
Thaylon
Adicionado ainda mais comentários ...
Thaylon
@AlanBerndt sugeriu um postfix while. Desde que ele não pode comentar e eu não posso aprovar. Eu gostaria de agradecer! aqui.
Thaylon
10

Haskell, 586 566 547 bytes

Escrevi isso no pressuposto de que para toda propriedade P deve existir algum x e y, de modo que P (x) seja verdadeiro e P (y) seja falso; sem essa suposição, o quarto exemplo de entrada não teria uma contradição e responderia "Não".

#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(/='.')

Isso deve ser compilado com a opção de linha de comando ghc "-cpp". A entrada deve ser finalizada por EOF (^ D). Você pode experimentá-lo online em http://melpon.org/wandbox/ , mas não pode definir opções de linha de comando. Em vez disso, você pode prefixar o programa com a opção de idioma

{-# LANGUAGE CPP #-}

Ele funciona coletando o conjunto de características e, em seguida, filtrando o conjunto de características -> avaliações da verdade usando as implicações na entrada. O resultado é então testado para garantir que cada característica possa ser atribuída validamente a Verdadeiro e Falso (falha aqui é o caso ex falso quodlibet ). Por fim, procura avaliações que correspondam aos fatos do porco, verificando o valor de "capaz de voar" em cada avaliação.

Poucos bytes foram perdidos para o estado de segmentação: o conjunto de características vistas até agora, a função de seleção de fatos de porco e a função de filtragem determinada pelas implicações. Provavelmente a mesma idéia seria muito mais curta em uma linguagem impura.

Editar: salvou vários bytes por sugestão de orgulhoso haskeller, e mais alguns substituindo a ligação de z e "u% drop 2 z" por uma ligação em "_: _: z" e "u% z", salvando 3.

Editar 2: economizou um pouco mais. Usou o truque (#) = (,) para salvar 2 bytes e aprendeu sobre sinônimos de padrões ( https://ghc.haskell.org/trac/ghc/wiki/PatternSynônimos ), mas a notação era muito detalhada para obter uma economia de eliminando o restante dos pares neste programa. Conseguiu um pouco mais de economia, alterando os padrões que o analisador procura. Por exemplo: se uma frase não começa com Porcos e ainda resta alguma coisa no estado do analisador, analisamos a frase "Tudo o que é ..". Isso salvou muitos caracteres nos padrões para X e%.

Matt Noonan
fonte
Sua suposição está correta, eu esqueci de mencioná-la em primeiro lugar, mas agora a adicionei à seção de detalhes!
vauge
2
Você deve incluir os sinalizadores na sua contagem de bytes (consulte a tag wiki para code-golf ). Portanto, são 607 bytes.
precisa saber é o seguinte
Isso está realmente correto? O link menciona apenas sinalizadores relacionados a codificações unicode; A meta menciona um problema semelhante em relação aos sinalizadores C ++ -D (uma fraude óbvia) vs -std = c ++ 11 (selecionando uma variação específica de idioma, provavelmente ok). Na IMO, os sinalizadores usados ​​são para permitir uma extensão bastante comum do Haskell98 no GHC, portanto análoga a -std = c ++ 11. Ref: meta.codegolf.stackexchange.com/questions/1859/...
Matt Noonan
você pode substituir a sua segunda definição de u com u n=(:)<$>[t,f]<*>u(n-1)(embora isso exigiria importação Control.Applicative, assim, no segundo pensamento é pior)
haskeller orgulhoso
1
você pode substituir a definição de c comc l=(all(==l!!0)l,and l)
haskeller orgulhoso
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

Para cada a -> bentrada, adicionamos a cláusula fornecida e sua negação not b -> not a ao conjunto de cláusulas e depois calculamos o conjunto de proposições que são ->acessíveis a partir de qualquer proposição usando um loop de ponto de fixação. Sempre que encontramos uma contradição, jogamos (e depois capturamos) um ZeroDivisionErrore imprimimos Yes.

Finalmente, verificamos se 'capaz de voar' (e / ou sua negação) é acessível a partir da proposição 'é porco' ''e imprimimos a resposta apropriada.

EDIT : Este é um buggy, corrigindo-o. Fixo.

user2361830
fonte
1
você deve ser capaz de salvar 2 bytes por colocar o trybloco na mesma linhatry:
undergroundmonorail
@undergroundmonorail: obrigado por descobrir isso! mudou isso.
user2361830
5

Ruby 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'}

Uso

O código acima define uma função f, que leva um parâmetro que representa a entrada de texto e retorna Yes, No, ou Maybe.

Por exemplo:

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

Teste online: http://ideone.com/fxLemg

O código não protegido (incluindo testes de unidade) está disponível aqui .

Cristian Lupascu
fonte
* estão disponíveis (sob o cabeçalho "teste online"). Plurais, meu bom amigo.
Stan Strum
@StanStrum Thanks! Modifiquei o texto - quero dizer que o código está disponível e também inclui testes de unidade.
Cristian Lupascu 1/11