Le but de ce défi est de produire (éventuellement) tous les programmes d'arrêt possibles dans la langue de votre choix. Au début, cela peut sembler impossible, mais vous pouvez le faire avec un choix très attentif de l'ordre d'exécution.
Voici un diagramme ASCII pour illustrer cela. Laissez les colonnes représenter une numérotation de chaque programme possible (chaque programme est un nombre fini de symboles d'un alphabet fini). Que chaque ligne représente une étape singulière dans l'exécution de ce programme. An X
représente l'exécution effectuée par ce programme à ce pas de temps.
step# p1 p2 p3 p4 p5 p6
1 X X X X X X
2 X X X X X
3 X X X X
4 X X X X
5 X X X
6 X X
7 X X
8 X X
9 X X
∞ X X
Comme vous pouvez le constater, les programmes 2 et 4 ne s'arrêtent pas. Si vous les exécutiez un par un, votre contrôleur resterait coincé dans la boucle infinie qu'est le programme 2 et ne sortirait jamais les programmes 3 et au-delà.
Au lieu de cela, vous utilisez une approche en queue d'aronde . Les lettres représentent un ordre d'exécution possible pour les 26 premières étapes. Les *
s sont des endroits où ce programme s'est arrêté et est sorti. Les .
s sont des étapes qui n'ont pas encore été exécutées.
step# p1 p2 p3 p4 p5 p6
1 A C F J N R V
2 B E I M Q * Z
3 D H * P U
4 G L T Y
5 K O X
6 * S .
7 W .
8 . .
9 . .
∞ . .
Exigences pour la langue cible
La langue cible (celle qui est interprétée en parallèle) doit être Turing-complete. À part cela, il peut s'agir de langue Turing-complete, y compris des sous-ensembles Turing-complete de langues beaucoup plus grandes. Vous êtes également libre d'interpréter des choses comme les règles du système d'étiquettes cycliques. Vous êtes également autorisé à créer un langage à tester, tant que vous pouvez montrer pourquoi il est Turing-complet.
Par exemple, si vous choisissez de tester le brainfuck, il est préférable de tester uniquement []-+<>
sous ensemble, car l'entrée n'est pas prise en charge et la sortie est simplement jetée (voir ci-dessous).
En ce qui concerne le programme "contrôleur" (auquel vous jouez), il n'y a pas d'exigences particulières. Des restrictions linguistiques normales s'appliquent.
Comment créer une liste infinie de programmes
La majorité des langages de programmation peuvent être représentés comme une série de symboles d'un alphabet fini. Dans ce cas, il est relativement facile d'énumérer une liste de tous les programmes possibles par ordre de longueur croissante. L'alphabet que vous utilisez doit être représentatif des exigences de la langue cible. Dans la plupart des cas, il s'agit d'un fichier ASCII imprimable. Si votre langue prend en charge Unicode en tant que fonctionnalité supplémentaire, vous ne devez pas tester toutes les combinaisons possibles de caractères Unicode, uniquement ASCII. Si votre langue utilise uniquement, []-+<>
ne testez pas les différentes combinaisons de caractères ASCII "commentaire". Des langues comme APL auraient leurs propres alphabets spéciaux.
Si votre langue est mieux décrite d'une manière non alphabétique, comme Fractran ou Turing Machines, il existe d'autres méthodes également valables pour générer une liste de tous les programmes valides possibles.
Interpréter une liste sans cesse croissante de programmes
L'élément clé de ce défi est d'écrire un interprète parallèle pour une liste croissante de programmes. Il y a quelques étapes de base pour cela:
- Ajouter un nombre fini de programmes à la liste
- Interprétez chaque programme de la liste individuellement pour une durée limitée. Cela peut être accompli en effectuant une étape d'instruction pour chacune. Enregistrez tous les états.
- Supprimer tous les programmes se terminant / générant des erreurs de la liste
- Sortie des programmes * correctement arrêtés
- Ajoutez d'autres programmes à la liste
- Simulez chaque programme à tour de rôle, reprenant l'exécution des anciens programmes là où ils s'étaient arrêtés
- Supprimer tous les programmes se terminant / générant des erreurs de la liste
- Sortie des programmes * correctement arrêtés
- répéter
* Vous ne devez sortir que les programmes qui s'arrêtent proprement. Cela signifie qu'aucune erreur de syntaxe ni exception non interceptée n'a été levée lors de l'exécution. Les programmes qui demandent une entrée doivent également être interrompus sans les sortir. Si un programme produit une sortie, vous ne devriez pas y mettre fin, jetez simplement la sortie.
Plus de règles
- Vous ne devez pas générer de nouveaux threads pour contenir les programmes testés, car cela décharge le travail de parallélisation sur le système d'exploitation hôte / autre logiciel.
- Modifier: pour fermer les futures failles potentielles, vous n'êtes pas autorisé à
eval
(ou toute fonction connexe) une partie du code du programme testé . Vous pouvezeval
un bloc de code à partir du code de l'interpréteur. (La réponse BF-in-Python est toujours valide selon ces règles.) - C'est du code-golf
- La langue dans laquelle vous écrivez votre soumission n'a pas besoin d'être la même que la langue que vous testez / produisez.
- Vous devez supposer que votre mémoire disponible est illimitée.
- Lorsque vous prouvez l'intégralité de Turing, vous pouvez supposer que l'entrée est codée en dur dans le programme et que la sortie peut être lue dans l'état interne du programme.
- Si votre programme sort lui-même, c'est probablement faux ou un polyglotte.
"If your program outputs itself, it is probably wrong or a polyglot."