Il s'agit d'un défi de code-golf dans lequel vous devez concevoir un programme qui agit comme un quine ou un quine qui se modifie pour illustrer l'apprentissage automatique.
Contexte
Il existe un programme d'intelligence artificielle de base appelé «le jeu du pangolin» qui est décrit ici . L'idée de base est que le programme lors de sa première exécution demande:
OK, pensez à quelque chose
Est-ce un pangolin?
Vous pouvez alors répondre soit:
Oui
Dans ce cas, il dit:
Bien. C'était tellement facile.
Sinon, il dit:
Oh. Eh bien, vous gagnez alors - À quoi pensiez-vous?
À laquelle vous pourriez dire:
un chien
À quoi il dirait
Veuillez me poser une question sur un chien, afin que je puisse faire la différence entre un chien et un pangolin
tu pourrais répondre
Mange-t-il des fourmis?
Il demanderait alors:
Quelle est la réponse pour un chien?
À laquelle vous diriez
non
Et ça dirait
Merci
La prochaine fois qu'il s'exécutera, il posera la question ci-dessus et construira un arbre binaire de ces questions.
Le défi
Assez de fond. Ce défi consiste à écrire un programme de pangolins auto-modifiant. Les règles sont les suivantes:
La sortie du programme (comme décrit ci-dessus) doit être vers
STDERR
. La réponse finale sera toujours "Bien. C'était tellement facile." ou "Merci". Après cela, il doit sortir soit la version actuelle du programme, soit une nouvelle version du programme qui incorpore la question àSTDOUT
. Aucune réponse écrite dans une langue qui ne prend pas en charge l'écritureSTDOUT
et /STDERR
ou la lectureSTDIN
ne sera valide.En d'autres termes, sous UNIX, vous pouvez appeler le programme comme ceci:
Exemple:
$ mylanguage myprogram > myprogram.1
[dialog goes here]
$ mylanguage myprogram1 > myprogram.2
[dialog goes here]
- Le programme doit utiliser exactement les invites spécifiées (car le raccourcissement des invites ne montre aucune compétence). Les invites sont (sans les guillemets et où% s est substitué) comme suit:
liste:
"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"
Lorsque vous attendez des réponses oui / non, votre programme doit accepter
y
ouyes
dans tous les cas pour «oui» etn
ouno
dans tous les cas pour «non». Ce que vous faites avec des entrées non conformes dépend de vous. Par exemple, vous pourriez décider de prendre n'importe quelle réponse commençant pary
ouY
comme «oui», et toute autre chose comme non.Vous pouvez supposer que les noms des éléments fournis et les questions ne comprennent que des lettres ASCII, des chiffres, des espaces, des tirets, des points d'interrogation, des virgules, des points, des deux-points et des points-virgules, c'est-à-dire qu'ils correspondent à l'expression régulière suivante
^[-?,.;: a-zA-Z]+$
. Si vous pouvez faire face à plus que cela (en particulier les caractères de citation dans la langue que vous avez choisie), vous devenez suffisant, mais ne gagnez pas de points supplémentaires.Votre programme ne peut pas lire ou écrire un fichier ( à l' exception
STDIN
,STDOUT
etSTDERR
), ou du réseau; en particulier, il ne peut ni lire ni écrire son propre code à partir du disque. Son état doit être enregistré dans le code du programme lui-même.Lorsque le programme est exécuté et suppose la réponse correctement, il doit fonctionner exactement comme une quine, c'est-à-dire qu'il doit écrire
STDOUT
exactement dans son propre code, inchangé.Lorsque le programme est exécuté et devine la réponse de manière incorrecte, il doit coder la nouvelle question et la réponse fournies dans son propre code et l'écrire
STDOUT
dans son propre code, afin qu'il soit capable de faire la distinction entre sa supposition d'origine et le nouvel objet fourni, dans en plus de distinguer entre tous les objets précédemment donnés.Vous devez être en mesure de faire face à plusieurs exécutions séquentielles du logiciel afin qu'il se renseigne sur de nombreux objets. Voir ici pour des exemples de plusieurs exécutions.
Les tests sont donnés au lien dans la tête (couvrant évidemment uniquement la boîte de dialogue
STDIN
etSTDERR
).Les failles standard sont exclues.
Réponses:
Lisp commun,
631576Exemple de session
Nommez le script
pango1.lisp
et exécutez comme suit (à l'aide de SBCL):Un autre tour, en ajoutant l'ours:
Ajout d'un paresseux (nous testons le cas où la réponse est "non"):
Test du dernier fichier:
Remarques
"Thanks"
, la voici.(y or n)
, car j'utilise lay-or-n-p
fonction existante . Je peux mettre à jour la réponse pour supprimer cette sortie si nécessaire.*QUERY-IO*
flux bidirectionnel dédié à l'interaction avec l'utilisateur, c'est ce que j'utilise ici. La sortie standard et l'interaction utilisateur ne gâchent pas, ce qui suit à mon humble avis l'esprit de la question.SAVE-LISP-AND-DIE
serait une meilleure approche dans la pratique.Sortie générée
Voici le dernier script généré:
Explications
Un arbre de décision peut être:
"a pangolin"
, qui représente une feuille.(question if-true if-false)
oùquestion
est une question fermée oui / non , sous forme de chaîne, etif-true
etif-false
sont les deux sous-arbres possibles associés à la question.La
U
fonction marche et retourne un arbre éventuellement modifié. Chaque question est posée tour à tour, depuis la racine jusqu'à atteindre une feuille, tout en interagissant avec l'utilisateur.La valeur retournée pour un nœud intermédiaire
(Q Y N)
est(Q (U Y) N)
(resp.(Q Y (U N))
) Si la réponse à la questionQ
est oui (resp. No ).La valeur retournée pour une feuille est soit la feuille elle-même, si le programme a correctement deviné la réponse, soit un arbre raffiné où la feuille est remplacée par une question et deux résultats possibles, selon les valeurs prises par l'utilisateur.
Cette partie était plutôt simple. Afin d'imprimer le code source, nous utilisons des variables de lecteur pour construire du code auto-référentiel.
En définissant la valeurL'astuce lors de l'utilisation*PRINT-CIRCLE*
true, nous évitons la récursion infinie lors de la jolie impression.WRITE
avec:print-circle T
est que la fonction peut également renvoyer la valeur au REPL, selon que l'écriture est la dernière forme, et donc, si le REPL ne gère pas les structures circulaires, comme il est défini par la valeur par défaut standard de*PRINT-CIRCLE*
, il y aura une récursion infinie. Nous devons seulement nous assurer que la structure circulaire n'est pas retournée au REPL, c'est pourquoi il y a un NIL dans la dernière position du LET. Cette approche réduit considérablement le problème.la source
(y or n)
n'est pas obligatoire, mais je suis tenté de le permettre car c'est une amélioration.Python 2.7.6,
820728 octets(Pourrait fonctionner sur différentes versions mais je ne suis pas sûr)
Eh bien, ce n'est pas aussi court que la réponse Common Lisp, mais voici du code!
la source
Python 3, 544 octets
Essayez-le en ligne!
Les questions / réponses / réponses sont stockées dans un tableau, où si le tableau stocke trois éléments (par exemple
['Does it eat ants',['a pangolin'],['a dog']]
), il obtient une réponse à la question et se répète avec uniquement le contenu du deuxième ou du troisième élément, selon la réponse. Quand il arrive à un tableau avec un seul élément, il pose la question, et comme il a son code source entier une chaîne, il est capable d'utiliser la méthode de jointure fractionnée pour insérer l'extension dans le tableau afin d'ajouter la nouvelle branche .À l'origine, j'ai écrit ceci sans réaliser l'exigence de quine, donc relire la question et avoir à trouver un moyen d'exécuter du code et de l'utiliser comme chaîne était difficile, mais j'ai finalement trouvé l'idée d'un joli format de quine extensible:
la source
Python 3 , 497 octets
Assez similaire à la réponse de Harmless pour la représentation des arbres. Il pose récursivement la question suivante, tout en approfondissant la liste, jusqu'à ce qu'il n'y ait qu'une seule réponse.
Version non golfée (sans quining)
la source