$p=$a[$p]+=$_ for@F;redo
Essayez-le en ligne! (contient un en-tête qui imprime l'état interne et s'arrête après 10 itérations, afin que le comportement soit observable)
À propos de la langue
Ces derniers jours, j'ai travaillé sur la machine I / D , une de mes dernières idées pour des langages de programmation très simples. Cela fonctionne comme suit: le stockage de données consiste en une RAM non limitée, initialement tous des zéros. Chaque élément peut stocker un entier non lié (bien qu'en pratique, la plupart des programmes d'ordinateur I / D ne stockent que de petits entiers dans la plupart d'entre eux, et utilisent les entiers non bornés uniquement comme moyen d'adresser des cellules avec de grandes adresses). Il y a aussi un pointeur de données, qui pointe vers une cellule (c'est-à-dire que l'adresse est stockée sous forme de cellule); c'est initialement aussi zéro.
Il n'y a que deux commandes:
I
: Incrémente la cellule sur laquelle pointe le pointeur de données. (Le pointeur de données lui-même reste inchangé.)
D
: Déréférencer le pointeur de données, c'est-à-dire lire la valeur de la cellule vers laquelle pointe le pointeur de données. Puis stockez la valeur résultante que vous avez lue dans le pointeur de données.
L'exécution exécute simplement le programme dans une boucle à plusieurs reprises, pour toujours.
Il est assez surprenant qu'un langage aussi simple soit Turing-complete. Je m'efforce donc de le prouver. Voici la preuve . C'est assez similaire à (mais plus simple que) la preuve de Three Star Programmer, un langage très similaire (et en fait, cette soumission utilise le même "shell" OISC de base autour du programme, ne différant que par les instructions réellement mises en œuvre).
A propos du programme
Usage
L'entrée doit être donnée sur l'entrée standard. Il s'agit d'un programme d'ordinateur I / D sans commentaires, utilisant la syntaxe RLE / OISC. (La machine I / D a deux syntaxes équivalentes différentes, mais pour golfiness ce programme ne prend en charge que l'une d'entre elles.) Dans cette syntaxe, un programme est une séquence de nombres en décimal, représentant la longueur des exécutions de I
commandes entre D
commandes. (Vous pouvez spécifier deux D
commandes consécutives ou plus en plaçant une "série de I
commandes 0 " entre elles, la syntaxe est donc très générale.)
Explication
Comme on peut le voir dans le programme, cela n’implémente pas les commandes I
et D
individuellement. En fait, il s’agit d’un interprète (très légèrement) optimisant (uniquement parce que c’est plus court pour écrire de cette façon). La clé est de voir qu'une série de n commandes d'incrémentation incrémente la cible du pointeur de données n fois, c'est-à-dire lui ajoute n ; et une série de 0 commandes d’incrémentation peuvent également être implémentées de cette façon, car l’ajout de 0 à la mémoire n’a aucun effet. Ainsi , l'opération que nous mettons en œuvre est en fait d'alterner entre la mise en œuvre d' une exécution Of- I
s et un D
. Ou en d'autres termes, "add nà la valeur indiquée par le pointeur de données (en la mémorisant dans la valeur indiquée par le pointeur de données), puis lisez la valeur indiquée par le pointeur de données et stockez-la dans le pointeur de données ". C'est clairement plus détaillé que nécessaire. pour être, et nous pouvons simplifier davantage ceci en "ajoutant n à la valeur pointée par le pointeur de données, puis stockons cette valeur à la fois dans la cible du pointeur de données et dans le pointeur de données lui-même".
Cela constitue donc le cœur de notre programme. Nous utilisons un tableau $a
pour stocker la RAM, et en $p
tant que pointeur de données (indexation dans le tableau):
$p=$a[$p]+=$_
+ $_ add {the run length}
$a[$p] to the element of $a pointed to by $p
$a[$p] = storing the result back into that element
$p= and also in the pointer itself
Perl interprète commodément les éléments non-initialisés du tableau comme étant 0 quand ils sont traités comme des nombres, de sorte que le tableau sera initialisé par zéro à zéro pour nous sans qu'aucun code explicite ne soit nécessaire à cet effet. (Un problème potentiel est l'exactitude numérique lorsque les nombres deviennent grands. Cependant, cela ne se produira que si la quantité de la matrice utilisée dépasse l'espace d'adressage de la machine (les entiers Perl sont suffisamment grands pour contenir des pointeurs), ce qui ne peut pas arriver sur une machine idéalisée.)
Enfin, tout ce que nous avons à faire est de placer ce programme en boucle. La for@F
boucle, combinée à l' -a
option de ligne de commande, parcourt les champs d'entrée standard (la définition par défaut de "champ" se scinde ici sur des espaces). La redo
boucle place le programme entier dans une boucle implicite (autre que, commodément, la lecture d'une entrée standard), ce qui entraîne l'exécution répétée du programme dans une boucle, comme requis par la sémantique de la machine I / D.
eval
solutions triviales .