Este es un desafío de código de golf en el que debe diseñar un programa que actúe como una quine o una quine que se modifique para ilustrar el aprendizaje automático.
Fondo
Hay un programa básico de inteligencia artificial llamado 'el juego de pangolín' que se describe aquí . La idea básica es que el programa cuando se ejecuta por primera vez pregunta:
OK, por favor piensa en algo
¿Es un pangolín?
Luego puede responder:
Sí
En cuyo caso dice:
Bueno. Eso fue muuuy fácil.
O si no dice:
Oh. Bueno, entonces ganas. ¿En qué estabas pensando?
A lo que podrías decir:
un perro
A lo que diría
Por favor, háganme una pregunta sobre un perro, para que pueda distinguir entre un perro y un pangolín.
podrías responder
¿Come hormigas?
Luego preguntaría:
¿Cuál es la respuesta para un perro?
A lo que dirías
no
Y diría
Gracias
La próxima vez que se ejecute, haría la pregunta anterior y generaría un árbol binario de tales preguntas.
El reto
Basta de antecedentes. Este desafío es escribir un programa de pangolín auto modificable. Las reglas son las siguientes:
La salida del programa (como se describió anteriormente) debe ser a
STDERR
. La respuesta final siempre será "Bien. Eso fue muuuy fácil". o "gracias". Después de esto, debería mostrar la versión actual del programa o una nueva versión del programa que incorpore la preguntaSTDOUT
. No será válida ninguna respuesta escrita en un idioma que no admita escribirSTDOUT
ySTDERR
leerSTDIN
.En otras palabras, bajo UNIX podría invocar el programa de esta manera:
ejemplo:
$ mylanguage myprogram > myprogram.1
[dialog goes here]
$ mylanguage myprogram1 > myprogram.2
[dialog goes here]
- El programa tiene que usar exactamente las indicaciones especificadas (porque acortar las indicaciones no muestra habilidad). Las indicaciones son (sin las comillas, y donde se sustituye% s) de la siguiente manera:
lista:
"OK, please think of something"
"Is it %s?"
"Good. That was soooo easy."
"Oh. Well you win then -- What were you thinking of?"
"Please give me a question about %s, so I can tell the difference between %s and %s"
"What is the answer for %s?"
"Thanks"
Al esperar respuestas sí / no, su programa debe aceptar
y
o,yes
en cualquier caso, 'sí', y /n
ono
en cualquier caso 'no'. Lo que haga con entradas no conformes depende de usted. Por ejemplo, puede decidir tomar cualquier respuesta que comience cony
oY
como 'sí', y cualquier otra cosa como no.Puede suponer que los nombres de los elementos suministrados y las preguntas consisten solo en letras ASCII, números, espacios, guiones, signos de interrogación, comas, puntos, puntos y punto y coma, es decir, coinciden con la siguiente expresión regular
^[-?,.;: a-zA-Z]+$
. Si puede hacer frente a algo más que eso (especialmente los caracteres entre comillas en el idioma elegido) puede ser presumido, pero no gana ningún punto extra.Su programa no puede leer o escribir en cualquier archivo (excluyendo
STDIN
,STDOUT
ySTDERR
), o desde la red; específicamente no puede leer ni escribir su propio código desde el disco. Su estado debe guardarse en el propio código del programa.Cuando se ejecuta el programa y adivina la respuesta correctamente, debe funcionar exactamente como una quine, es decir, debe escribir
STDOUT
exactamente su propio código, sin cambios.Cuando el programa se ejecuta y adivina la respuesta incorrectamente, debe codificar la nueva pregunta y respuesta proporcionadas dentro de su propio código y escribirla
STDOUT
en su propio código, por lo que es capaz de distinguir entre su conjetura original y el nuevo objeto proporcionado. Además de distinguir entre todos los objetos dados previamente.Debe poder hacer frente a múltiples ejecuciones secuenciales del software para que aprenda sobre muchos objetos. Consulte aquí para ver ejemplos de ejecuciones múltiples.
Las pruebas se ejecutan en el enlace en la cabecera (obviamente, solo cubren el diálogo
STDIN
ySTDERR
).Las lagunas estándar están excluidas.
Respuestas:
Lisp común,
631576Sesión de ejemplo
Asigne un nombre al script
pango1.lisp
y ejecútelo de la siguiente manera (usando SBCL):Otra ronda, agregando el oso:
Agregar un perezoso (probamos el caso donde la respuesta es "no"):
Probar el último archivo:
Observaciones
"Thanks"
, aquí está.(y or n)
, porque estoy usando lay-or-n-p
función existente . Puedo actualizar la respuesta para eliminar esta salida si es necesario.*QUERY-IO*
flujo bidireccional dedicado a la interacción del usuario, que es lo que estoy usando aquí. La salida estándar y la interacción del usuario no se complican, lo que sigue en mi humilde opinión el espíritu de la pregunta.SAVE-LISP-AND-DIE
sería un mejor enfoque en la práctica.Salida generada
Aquí está el último script generado:
Explicaciones
Un árbol de decisión puede ser:
"a pangolin"
, que representa una hoja.(question if-true if-false)
dondequestion
es una pregunta cerrada sí / no , como una cadena,if-true
yif-false
son los dos posibles subárboles asociados con la pregunta.La
U
función camina y devuelve un árbol posiblemente modificado. Cada pregunta se hace a su vez, comenzando desde la raíz hasta llegar a una hoja, mientras interactúa con el usuario.El valor devuelto para un nodo intermedio
(Q Y N)
es(Q (U Y) N)
(resp.(Q Y (U N))
) Si la respuesta a la preguntaQ
es sí (resp. No ).El valor devuelto para una hoja es la hoja misma, si el programa adivinó correctamente la respuesta, o un árbol refinado donde la hoja se reemplaza por una pregunta y dos resultados posibles, de acuerdo con los valores tomados del usuario.
Esta parte fue bastante sencilla. Para imprimir el código fuente, utilizamos variables de lectura para construir código autorreferencial.
Al establecerloEl truco cuando se usa*PRINT-CIRCLE*
en verdadero, evitamos la recursión infinita durante la impresión bonita.WRITE
con:print-circle T
es que la función también puede devolver el valor a REPL, dependiendo de si escribir es la última forma, y si REPL no maneja estructuras circulares, como se define por el valor predeterminado estándar de*PRINT-CIRCLE*
, habrá una recursión infinita. Solo necesitamos asegurarnos de que la estructura circular no se devuelva al REPL, por eso hay un NIL en la última posición del LET. Este enfoque reduce en gran medida el problema.fuente
(y or n)
es obligatorio, pero estoy tentado a permitirlo, ya que es una mejora.Python 2.7.6,
820728 bytes(Podría funcionar en diferentes versiones pero no estoy seguro)
Bueno, no es tan corto como la respuesta de Common Lisp, ¡pero aquí hay un código!
fuente
Python 3, 544 bytes
Pruébalo en línea!
Las preguntas / respuestas / respuestas se almacenan en una matriz, donde si la matriz almacena tres elementos (por ejemplo
['Does it eat ants',['a pangolin'],['a dog']]
), obtiene una respuesta a la pregunta y se repite solo con el contenido del segundo o tercer elemento, dependiendo de la respuesta. Cuando llega a una matriz con solo un elemento, hace la pregunta, y dado que tiene todo su código fuente como una cadena, puede usar el método de unión dividida para insertar la extensión en la matriz para agregar la nueva rama .Originalmente escribí esto sin darme cuenta del requisito de quine, por lo que volver a leer la pregunta y tener que encontrar una manera de poder ejecutar el código y usarlo como una cadena fue difícil, pero finalmente me topé con la idea del buen formato de quine expandible:
fuente
Python 3 , 497 bytes
Muy similar a la respuesta Inofensiva para la representación de árbol. Hace recursivamente la siguiente pregunta, mientras profundiza en la lista, hasta que solo hay una respuesta.
Versión sin golf (sin comillas)
fuente