¿Los cerdos pueden volar?

45

Tarea

Su tarea es escribir una función o un programa en un lenguaje de su elección que analice un par de declaraciones y determine si de esas declaraciones se puede concluir que los cerdos pueden volar.

Entrada

La entrada es una cadena que puede leerse desde STDIN, tomarse como un argumento de función o incluso almacenarse en un archivo. La entrada se puede describir utilizando el siguiente 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" ;

Entrada de ejemplo (ver más ejemplos a continuación):

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

Salida

La función puede devolver el resultado, escribirlo en un archivo o imprimirlo en STDOUT. Hay 5 casos diferentes para ser manejados:

  1. Las declaraciones dadas son válidas, consistentes y tienen como consecuencia lógica que los cerdos pueden volar. En ese caso, debe generar Yes.
  2. Las declaraciones dadas son válidas, consistentes y tienen como consecuencia lógica que los cerdos no pueden volar. En ese caso, debe generar No.
  3. No se puede concluir de las declaraciones dadas, válidas y consistentes si los cerdos pueden volar o no. En ese caso, debe generar Maybe.
  4. Las declaraciones dadas son válidas, pero no consistentes (es decir, hay una contradicción en las declaraciones dadas). Desde ex falso quodlibet , decidimos dar salida Yesen ese caso.
  5. Las declaraciones dadas no son válidas, es decir, no están formateadas de acuerdo con el EBNF dado. En ese caso, puede hacer lo que quiera.

Detalles

  • Puede suponer que los atributos dados son independientes entre sí. Entonces, por ejemplo, un cerdo puede ser joven y viejo, verde, rojo y azul al mismo tiempo sin causar ninguna inconsistencia. Sin embargo, un cerdo puede no ser 'verde' y 'no verde' al mismo tiempo, eso es una contradicción y debe manejarse como se describe en (4).
  • Para cada atributo, suponga que hay al menos un objeto (no necesariamente un cerdo) en el universo que tiene el atributo dado y un objeto que no lo tiene.

Ejemplo de entradas y salidas

Entrada:

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

Salida: como los cerdos son verdes y, por lo tanto, inteligentes, y todo lo que puede volar no es inteligente, los cerdos no pueden volar. La salida es No.

Entrada:

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

Salida: si los cerdos no pudieron volar, tampoco eran viejos. Pero como son viejos, debes dar salida Yes.

Entrada:

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

Salida: Maybe .

Entrada:

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

Salida: aunque la primera declaración implica que los cerdos no pueden volar, las siguientes declaraciones se contradicen entre sí y, por lo tanto, la salida debe serlo Yes.

Entrada:

Pigs are very smart. Pigs are able to fly. 

Salida: lo que quieras, ya que la cadena no coincide con los criterios mencionados anteriormente.

Ganador

Este es el , por lo que gana la respuesta correcta más corta (en bytes). El ganador será elegido una semana después de que se publique la primera respuesta correcta.

Un cerdo volador

vagabundo
fuente
¿Por qué el tercer ejemplo devuelve sí?
xem
10
Estoy considerando escribir una respuesta que traduzca la entrada al código Prolog.
Tal
1
Solo puede concluir que no existe nada rojo. Las cosas dulces no rojas están bien.
user2357112
1
Esperaba más ejemplos, solo para poder hacerlo yo mismo.
cjfaure
1
@xem: ex falso quodlibet, búscalo en wikipedia como el principio de la explosión. Si existe una contradicción, entonces cualquier cosa puede ser probada. Entonces, si 'dios existe' es verdadero y 'dios no existe' es verdadero, se puede demostrar que cualquier cosa es verdadera, por lo tanto, los cerdos pueden volar puede probarse que es cierto.
Fightermagethief

Respuestas:

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

Sin golf / Explicación:

# 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
fuente
44
¡Sería genial si pudieras decirnos cómo funciona / escribir algunos comentarios!
error
Y otro voto a favor para más comentarios ... ¿algo en particular necesita más explicación?
Thaylon
Se agregaron aún más comentarios ...
Thaylon
@AlanBerndt sugirió un postfix mientras. Ya que no puede comentar y no puedo aprobar. Me gustaría decir gracias! aquí.
Thaylon
10

Haskell, 586 566 547 bytes

Escribí esto suponiendo que para cada propiedad P debe existir alguna x e y tal que P (x) sea ​​verdadera y P (y) sea ​​falsa; sin esta suposición, la entrada del cuarto ejemplo no tendría una contradicción y respondería "No".

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

Esto debe compilarse con la opción de línea de comando ghc "-cpp". La entrada debe ser terminada por EOF (^ D). Puede probarlo en línea en http://melpon.org/wandbox/ , pero no puede configurar las opciones de línea de comandos. En cambio, puede prefijar el programa con la opción de idioma

{-# LANGUAGE CPP #-}

Funciona recolectando el conjunto de rasgos, luego filtrando el conjunto de rasgos -> valoraciones de verdad usando las implicaciones en la entrada. Luego, el resultado se prueba para garantizar que cada rasgo pueda asignarse de manera válida tanto a Verdadero como a Falso (el caso aquí es el caso de falso falso quodlibet ). Finalmente, busca valoraciones que coincidan con los hechos del cerdo, verificando el valor de "capaz de volar" en cada valoración.

Se perdieron bastantes bytes en el estado de subprocesamiento: el conjunto de rasgos vistos hasta ahora, la función de selector de hechos de cerdo y la función de filtrado determinada por las implicaciones. Probablemente, la misma idea exacta sería mucho más corta en un lenguaje impuro.

Editar: ahorró varios bytes por sugerencia de Haskeller orgulloso, luego un par extra al reemplazar el enlace de z y "u% drop 2 z" con un enlace a "_: _: z" y "u% z", guardando 3.

Edición 2: guardado un poco más. Utilicé el truco (#) = (,) para guardar 2 bytes y aprendí sobre sinónimos de patrones ( https://ghc.haskell.org/trac/ghc/wiki/PatternSynomains ), pero la notación era demasiado detallada para obtener un ahorro de eliminando el resto de los pares en este programa. Exprimió algunos ahorros más al cambiar los patrones que busca el analizador. Por ejemplo: si una oración no comienza con Cerdos y nos queda algo en el estado del analizador, analizamos una oración "Todo lo que es ...". Esto ahorró muchos caracteres en los patrones para X y%.

Matt Noonan
fuente
Su suposición es correcta, olvidé mencionarlo en primer lugar, ¡pero ahora lo he agregado a la sección de detalles!
Vauge
2
Debe incluir las banderas en su conteo de bytes (vea la etiqueta wiki para code-golf ). Por lo tanto, son 607 bytes.
nyuszika7h
¿Es eso realmente correcto? El enlace solo menciona marcas relacionadas con codificaciones Unicode; meta menciona un problema similar con respecto a los indicadores de C ++ -D (un truco obvio) vs -std = c ++ 11 (seleccionando una variación de lenguaje específica, por lo que probablemente esté bien). En mi opinión, los indicadores utilizados son para habilitar una extensión GHC bastante común de Haskell98, por lo tanto, análoga a -std = c ++ 11. Ref: meta.codegolf.stackexchange.com/questions/1859/…
Matt Noonan
puede reemplazar su segunda definición de u con u n=(:)<$>[t,f]<*>u(n-1)(aunque esto requeriría importar
Control. Aplicativo
1
puede reemplazar la definición de c conc l=(all(==l!!0)l,and l)
proud haskeller
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 uno a -> ben la entrada, agregamos la cláusula dada y su negación not b -> not a al conjunto de cláusulas y luego calculamos el conjunto de proposiciones que son ->accesibles desde cualquier proposición usando un bucle de punto fijo. Cada vez que encontramos una contradicción, tiramos (y luego atrapamos) a ZeroDivisionErrore imprimimos Yes.

Finalmente, verificamos si 'capaz de volar' (y / o su negación) es accesible desde la propuesta 'es cerdo' ''e imprimimos la respuesta adecuada.

EDITAR : Esto tiene errores, lo está arreglando. Fijo.

usuario2361830
fuente
1
debería poder guardar 2 bytes colocando el trybloque en la misma línea quetry:
undergroundmonorail
@undergroundmonorail: ¡gracias por ver eso! lo cambió
user2361830
5

Rubí 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

El código anterior define una función f, que tiene un parámetro que representa la entrada textual y vuelve Yes, Noo Maybe.

Por ejemplo:

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

Prueba en línea: http://ideone.com/fxLemg

El código no protegido (incluidas las pruebas unitarias) está disponible aquí .

Cristian Lupascu
fuente
* están disponibles (bajo el encabezado "prueba en línea"). Plurales, mi buen amigo.
Stan Strum el
@StanStrum ¡Gracias! Modifiqué el texto, quiero decir que el código está disponible y también incluye pruebas unitarias.
Cristian Lupascu el