Acc !! , 129 octets
Pas mal pour un tarpit assez bavard de Turing ...
N
Count i while _%128-9 {
Count x while _/128%2 {
Write 40
_+128
}
Write _%128
_+128-_%128+N
}
Count j while _/256-j {
Write 41
}
(Oui, tout cet espace est obligatoire.)
Note: à cause des limitations d'entrée de Acc !! , il est impossible de lire une chaîne de caractères arbitraire sans un délimiteur de fin. Par conséquent, ce programme attend une entrée (sur stdin) sous la forme d'une chaîne suivie d'un caractère de tabulation.
Acc !! ?
C'est un langage que j'ai créé et qui semble seulement être inutilisable . Les seuls types de données sont des entiers, la seule construction de flux de contrôle est la Count x while y
boucle et le seul moyen de stocker des données est un seul accumulateur _
. L'entrée et la sortie sont effectuées caractère par caractère, à l'aide de la valeur spéciale N
et de l' Write
instruction. Malgré ces limitations, je suis à peu près sûr que Acc !! est Turing-complet.
Explication
La stratégie de base dans Acc !! la programmation consiste à utiliser la %
division mod et integer /
pour partitionner conceptuellement l'accumulateur, ce qui lui permet de stocker plusieurs valeurs à la fois. Dans ce programme, nous utilisons trois de ces sections: les sept bits les plus faibles ( _%128
) stockent un code ASCII à partir d’une entrée; le bit suivant ( _/128%2
) stocke une valeur de drapeau; et les bits restants ( _/256
) comptent le nombre de parents proches dont nous aurons besoin.
Entrée dans Acc !! provient de la valeur spéciale N
, qui lit un seul caractère et s’évalue en code ASCII. Toute instruction composée uniquement d'une expression affecte le résultat de cette expression à l'accumulateur. Nous commençons donc par stocker le code du premier caractère dans l'accumulateur.
_%128
stockera le dernier caractère lu. Ainsi, la première boucle s'exécute avec une valeur autre que _%128-9
zéro, c'est-à-dire jusqu'à ce que le caractère actuel soit un onglet.
À l'intérieur de la boucle, nous voulons imprimer (
sauf si nous en sommes à la première itération. Depuis Acc !! n'a pas de déclaration if, nous devons utiliser des boucles pour les conditions. Nous utilisons le bit 128 de l'accumulateur _/128%2
, comme valeur d'indicateur. Lors du premier passage, la seule chose dans l'accumulateur est une valeur ASCII <128, donc le drapeau est 0 et la boucle est ignorée. Lors de chaque passage ultérieur, nous nous assurerons que le drapeau est à 1.
Dans la Count x
boucle (chaque fois que le drapeau est à 1), nous écrivons un code ouvert (ASCII 40
) et ajoutons 128 à l'accumulateur, ce qui met le drapeau à 0 et quitte la boucle. Cela arrive également à incrémenter la valeur de _/256
, que nous utiliserons comme notre décompte de parents proches à afficher.
Indépendamment de la valeur du drapeau, nous écrivons le dernier caractère en entrée, qui est simplement _%128
.
La prochaine affectation ( _+128-_%128+N
) fait deux choses. Tout d'abord, en ajoutant 128, il active l'indicateur pour la prochaine fois dans la boucle. Deuxièmement, il met la _%128
fente à zéro, lit un autre caractère et le stocke à cet endroit. Puis on boucle.
Lorsque la Count i
boucle se termine, nous venons de lire un caractère de tabulation, et la valeur de l'accumulateur se décompose comme suit:
_%128
: 9
(le caractère de tabulation)
_/128%2
: 1
(le drapeau)
_/256
: nombre de caractères lus, moins 1
(Le moins 1 est dû au fait que nous n’ajoutons que 128 à l’accumulateur une fois lors du premier passage dans la boucle principale.) Count j while _/256-j
effectue des boucles en _/256
écrivant un ASCII proche 41
chaque fois. Voila!