Une brève histoire des langages de programmation 2D: 16 (+2) ans
v19977/2{@{{4{\_______>/02&&&#???? * P+++++1P1P-1P+1E * *
\'\02'oo100@n590@n; * * *
>"8991",,,;5-;,@ * * *
* * * *
\ * ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX******* *
* #2018O@ * * * * * * *
* * * * * * * *
* * * * * * * *
* **** **** * **** **** * **** **** * **** *****
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * **** * * * * **** * * * * **** * * * * ****
* * * * * * * * * * * * * * * *
R"2014"; ***** ******* ****** ******* ****** ******* ****** *******
x
x%"2010"x
x
$'main' \/\/\/\
\-[2005]o-# \++++++\
/++++++/
\++++++\
/++++++/
\/\/\/\++.--..+++.#
S1^2^2^6^8MAOUOAOOF
/K:0:1:@
> "7102"4&o@
| }+++++[>++++++++++<-]>.--..++++++.@
Ai-je mentionné que j'aime les langages de programmation 2D?
La langue qui (prétendument, voir la dernière section) a tout déclenché. Dans Befunge, vous pouvez rediriger le flux de contrôle avec <v>^
, mais les miroirs maintenant omniprésents \
et /
n'étaient pas encore une chose. L'interpréteur Befunge utilisé sur Anarchy Golf ignore les commandes inconnues. Nous pouvons utiliser ceci pour distinguer la famille Befunge de la famille> <>. Par conséquent, le code exécuté par Befunge est le suivant:
v
\
>"8991",,,;5-;,@
Le "8991"
pousse les caractères individuels sur la pile. ,,,
imprime les trois premiers d'entre eux. Alors ;
est inconnu (que nous utiliserons pour le distinguer de Befunge 98), le 5-
transforme 8
en 3
et ,
imprime cela aussi avant la @
fin du programme.
Écrire cette partie de la solution m'a probablement pris aussi longtemps que d'écrire toutes les autres et de les assembler ...
Wierd ne connaît que deux symboles: l'espace et tout le reste. Le pointeur d'instruction essaie de suivre le chemin formé par les caractères non-espace, en partant en diagonale du coin supérieur gauche et en essayant toujours d'aller aussi droit que possible. Les courbes du chemin forment les instructions réelles (les degrés du tour déterminant l’instruction à exécuter). Donc, le code vu par Wierd est le suivant:
v1997 * * *
' * * *
8 * * *
* * * *
* ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX******* *
* * * * * * * *
* * * * * * * *
* * * * * * * *
* **** **** * **** **** * **** **** * **** *****
* * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * *
* * * **** * * * * **** * * * * **** * * * * ****
* * * * * * * * * * * * * * * *
***** ******* ****** ******* ****** ******* ****** *******
La partie 1997
supérieure n'est pas réellement exécutée, mais Wierd nous permet de la lire à partir du code source, ce qui est beaucoup plus court que d'essayer de construire les codes de caractères des quatre chiffres eux-mêmes (même si cela ne ressemble pas à ça .. .) Je n'ai pas envie de tout casser, mais vous pouvez voir clairement les quatre sections répétées. Cela signifie que nous stockons d’abord 1
sur la pile, puis chacune de ces quatre sections l’incrémente 1
, puis des branches. La branche du bas en pousse un autre1
, récupère le caractère source à ces coordonnées et l’imprime, alors que la branche du haut est redirigée vers la section suivante. Vous vous demandez peut-être pourquoi les extrémités des chemins sont si longues, mais c'est parce que lorsque Wierd frappe l'extrémité d'un chemin, il tente de sauter sur un chemin voisin avant de décider de mettre fin à la branche actuelle. Pour éviter cela, nous devons déplacer ces extrémités suffisamment loin de tout autre code.
Befunge a reçu une mise à jour assez connue en 1998 avec une spécification très rigoureuse pouvant être généralisée à des dimensions arbitraires (et je pense aussi à des topologies arbitraires). Cependant, il est largement compatible avec Befunge, ce qui le rend assez facile à polygloter les deux. Ce Befunge n'avait toujours pas de miroir, donc le chemin exécuté est le même que pour Befunge 93:
v
\
>"8991",,,;5-;,@
La différence est que Befunge 98 n’ignore pas le ;
. Au lieu de cela, il agit un peu comme un commentaire en ce que toutes les commandes jusqu’à la prochaine ;
sont ignorées. De cette façon, nous ne décrémente que 8
pour 3
et imprimer le 1998
tel quel.
2001: Un espace ... PingPong
2001 est l’année de Piet, mais je n’avais pas vraiment envie de polygloter un fichier image avec tous les autres programmes. Voici donc un langage 2D moins connu. Il semble avoir beaucoup de fonctionnalités (que nous n'allons pas utiliser). Merci à Sp3000 d’avoir trouvé l’interprète original (seul lien mort sur la version archivée du site officiel).
PingPong est un peu inhabituel dans la mesure où il n’a que des miroirs et pas de <v>^
redirecteur. Donc, cela se déplace v19977
au début et ensuite frappe le miroir qui l'enveloppe vers le bas. Le code pertinent est alors:
v19977/
...
/K:0:1:@
...
Le code actuel est assez simple: K
Pousse 20
, les chiffres eux - mêmes pousser, :
imprime un entier et se @
termine le programme.
C'est la première langue où les choses deviennent un peu plus faciles, car SNUSP prend en charge un point d'entrée explicite. Ce point d'entrée est marqué par $
. À en juger par certains articles sur les esolangs, ce langage en a inspiré plusieurs autres, mais malheureusement, en fin de compte, il s’agit d’un dérivé de Brainfuck. Cela dit, je pense que la façon dont la cellule actuelle est fixée à 48 est assez nette (et a été volée dans l'article d'esolangs). Voici la partie pertinente du code:
$'main' \/\/\/\
\++++++\
/++++++/
\++++++\
/++++++/
\/\/\/\++.--..+++.#
Ce sont 24 +
s et les miroirs envoient l'adresse IP à travers chacun exactement deux fois.
Quelle qu'en soit la raison, cette langue n'ont les redirecteurs mais au lieu de l'habituel qu'il utilise . Par conséquent, cela ne fait que traverser la première ligne. Le code pertinent est:<^>
v
%
v19977/2{@{{4{\
Pour commencer, nous allons pousser quelques chiffres, effectuer une division. Puis 2{
imprime le 2
, @
efface la pile. {{
imprime deux s (implicites) 0
s. 4{
imprime le 4
et \
termine le programme.
2005 était un choix difficile. Je n'ai pas trouvé autant de langages 2D que l'année précédente, et ADJUST et Archway sont tous deux situés dans le coin inférieur gauche (ce qui leur aurait facilité l'ajout). J'aime bien le rail et comme il a un point d’entrée explicite, il n’était pas difficile de l’ajouter non plus. Le train cherche une ligne de départ $'main'
et commence à se déplacer du sud-est au sud-est $
. Cela signifie que le code pertinent est:
$'main'
\-[2005]o-#
Les \
et ne -
sont que des pistes (no-ops). Le [2005]
est un littéral de chaîne qui o
s'imprime avant la #
fin du programme.
Un brainfuck à deux dimensions. Il existe un autre langage intéressant pour cette année appelé Black, qui commence au niveau des coordonnées (3,3)
(basé sur 1) et qui aurait rendu l’utilisation de cela dans un polyglotte intéressante également. Je n'ai cependant pas pu trouver d'interprète. Nous devrons donc travailler avec un autre dérivé de BF à la place ...
La chose intéressante à propos de celui-ci est qu’il ne formate pas la grille en lignes avec sauts de ligne comme la plupart des autres langages 2D. Au lieu de cela |
est utilisé comme séparateur de ligne. Comme je ne l’utilisais pas |
pour d’autres langues, je pouvais simplement mettre une |
dernière ligne, ce qui fait du reste du programme une seule ligne en ce qui concerne BF.js. Le code pertinent est alors le suivant (transformer le |
en un saut de ligne réel):
v19977/2{...
}+++++[>++++++++++<-]>.--..++++++.@
BF.js utilise ni <v>^
ni miroirs. Le seul moyen de rediriger le flux de contrôle consiste à faire {}
pivoter la direction IP de 90 °. Donc, ces accolades déplacent l'IP à la deuxième ligne. Le reste est une solution simple de Brainfuck (qui ne joue pas particulièrement bien au golf) qui définit une cellule sur 50
(code de 2
), puis l’imprime 2006
en décalant légèrement la valeur. @
termine le programme.
Pour cette année, je voulais vraiment utiliser DOBELA, qui utilise plusieurs points d’entrée et qui ressemble au lovechild de Fission et Ziim . Malheureusement, je n'ai pas réussi à faire travailler l'interprète. Donc, voici un autre dérivé de BF (le dernier, je le promets).
Contrairement au dernier, celui-ci connaît les deux <v>^
miroirs, le code pertinent est donc:
v
\'\
8
\ * ++++++++++++++++++++++++ ++++++++++++++++++++++++ ++O--OO++++++++OX
Celui-ci ne possède pas la []
boucle habituelle de style BF (au lieu de cela, vous devez former une boucle 2D réelle), alors j'ai simplement décidé de le coder en dur 50
car j'avais une tonne de caractères dans une rangée de Wierd de toute façon. Notez que les '
et 8
sont ignorés, le *
est un trampoline conditionnel que nous pouvons ignorer et le O
Brainfuck .
. Le X
termine le programme.
Probablement le fungeoid le plus populaire (autre que Befunge lui-même) au moins autour de ces parties. > <> a les deux <v>^
et les miroirs mais aussi les chaînes de caractères, donc le code exécuté est le suivant:
v
\'\02'oo100@n590@n;
Le littéral chaîne sert principalement à ignorer le \
code que nous avons utilisé pour BrainSpace 1.0, mais pendant que nous y sommes, nous pourrions aussi bien insérer les deux premiers caractères. oo
les imprime. Ensuite, 100
appuie sur trois chiffres, @
déplace le haut vers le bas et n
imprime le 0
dessous. Nous faisons à nouveau la même chose avec 590
laquelle imprime le 9
. Si vous vous demandez pourquoi je n'imprime pas uniquement 2009
tel quel , attendez 2015. ;
met fin au programme.
Celui-ci était simple, car il a un point d'entrée explicite à %
. Cependant, celui-ci crée 4 adresses IP dans toutes les directions (d'où le nom de la langue, je suppose), et nous devons nous débarrasser de 3 d'entre elles. Voici le code pertinent:
x
x%"2010"x
x
Ben ouais. (Dans Cardinal, le mode chaîne imprime directement au lieu de placer les caractères sur une pile.)
Une autre langue avec un point d’entrée explicite (par David Catt qui a créé quelques autres très beaux esolangs), cette fois sur S
. Cela rend le code pertinent cette partie:
S1^2^2^6^8MAOUOAOOF
RunR est un peu intéressant car la plupart des opérations fonctionnent avec une sorte de registre et les valeurs doivent être déplacées explicitement vers la pile pour les opérations binaires. Les chiffres définissent les valeurs du registre et ^
poussent le registre actuel vers la pile. Ensuite, la M
multiplication (valeur du registre fois extraite de la pile), la U
soustraction, l' A
addition, la O
sortie. F
termine le programme.
Comme Wierd, Ropy essaie de suivre des sections de caractères autres que des espaces, mais ici, les courbes ne déterminent pas les commandes. En fait, il s'avère que Ropy ressemble plus à mon propre labyrinthe en ce que la direction choisie dépend du haut de la pile. Cependant, nous n'avons pas vraiment besoin de nous inquiéter à ce sujet ici, car Ropy se déplace tout au long de la première ligne:
v19977/2{@{{4{\_______>/02&&&#????
Il y a beaucoup de choses que nous pouvons ignorer jusqu'à la >
. Tout ce que nous avons besoin de savoir, c'est que le sommet de la pile sera à ce moment 4
-là et il y en aura un en 2
dessous.
>
duplique le 4
, /
est la division en le transformant en un 1
. Puis on pousse 02
. &&&
joint les quatre premiers numéros de la pile dans l’ordre inverse 2012
. #
le sort. ????
efface simplement la pile car sinon, le haut de la pile est également généré.
Un point intéressant est que le second 7
en a 19977
été ajouté à cause de Ropy. La /
division dans Ropy fait top / second
(contrairement à l'ordre habituel dans de nombreux langages basés sur des piles), où 7 / 9
donnerait 0
. Si nous avions un zéro au sommet de la pile, Ropy ferait quelques trucs déchaînés avec sa direction de déplacement. Nous devons donc pousser l’autre 7
pour que le haut de la pile reste positif et que Ropy continue de se déplacer vers l’est.
Avec ses points d'entrée explicites, celui-ci est facile. RDLU
créer des atomes (pointeurs d'instructions) dans la direction correspondante, le bit pertinent est donc le suivant:
R"2014";
Notez qu'il y a aussi un U
code source dans le code source, mais que cet atome finit par atteindre l'un des éléments *
de Wierd, ce qui termine le programme (et cet atome prend beaucoup plus de temps que les R
besoins d'impression 2014
).
Le dérivé plus puissant> <> de Sp3000. Il est largement compatible avec> <>, donc le code exécuté est toujours:
v
\'\02'oo100@n590@n;
Cependant, le sens de rotation de a @
été changé, ce qui est l'astuce habituelle pour distinguer> <> et Gol> <> dans les polyglottes, donc celle-ci s'imprime 15
au lieu de 09
. D'où l'étrangeté dans la seconde moitié du programme.
CSL est très intéressant car les commandes ne sont pas exécutées immédiatement. Au lieu de cela, chaque commande est poussée sur une pile de commandes e
et E
peut être utilisée pour exécuter des commandes à partir de celle-ci. Le code correspondant devient:
v19977/2{@{{4{\_______>/02&&&#???? * P+++++1P1P-1P+1E
Ainsi, il E
exécute la totalité de la pile de commandes, ce qui signifie que les éléments précédents sont exécutés à l'envers. Il suffit de regarder *
:
1+P1-P1P1+++++P*
Les 1
s se poussent sur la pile de données. +
et -
sont décrémentés / incrémentés. P
affiche le haut de la pile. Ensuite, *
tente de multiplier les deux premières valeurs de la pile. Cependant, la pile est vide, le programme est donc terminé.
Nous arrivons maintenant aux langues qui ont été publiées après la publication de ce défi. Je ne les compte donc pas vraiment pour la partition, surtout que je les ai moi-même créées (pas avec ce défi en tête cependant). Cependant, ils ont une nouvelle sémantique de mouvement de propriété intellectuelle, ce qui facilite leur intégration dans le polyglotte tout en ajoutant quelque chose d'intéressant à cette vitrine des langages 2D.
Alice a été conçue pour être un fungeoid riche en fonctionnalités. Une différence intéressante par rapport à la majorité des autres langages 2D (mais pas à tous) est que l’IP peut se déplacer orthogonalement ou diagonalement. Le passage de l'un à l'autre modifie également la sémantique de presque toutes les commandes du langage. De plus, Alice prend en charge à la fois les <^>v
indicateurs de direction et les \/
miroirs traditionnels , mais les miroirs ont un comportement très unique dans Alice (ce qui permet de diriger facilement l'adresse IP d'Alice vers une partie du code inutilisée jusqu'à présent).
Alors que la plupart des langues traitent \
et /
qu’il s’agissait de miroirs à un angle de 45 ° et que l’IP est un rayon lumineux qui rebondit dessus, Alice les traite comme ayant un angle de 67,5 ° (qui est plus proche de l’angle des glyphes de barre oblique réels). , et l’IP se déplace également dans le miroir (d’où le nom de la langue). En raison de cet angle, les miroirs basculent entre les mouvements dans des directions orthogonales ou diagonales. De plus, en mode ordinal (c’est-à-dire pendant que l’IP se déplace le long de diagonales), la grille ne s’enroule pas et l’IP rebondit plutôt sur les bords (alors qu’en mode Cardinal, elle s’enroule).
Dans l’ensemble, le code exécuté par Alice est le suivant:
v19
\ \
...
> "7102"4&o@
...
L’IP commence dans le coin en haut à gauche, comme d’habitude, et le v
renvoie au sud. Maintenant, la \
propriété intellectuelle se déplace vers le nord-ouest, où elle rebondit immédiatement sur le bord gauche de la grille (et se déplace vers le nord-est). 1
peut être ignoré, l’IP rebondit sur le bord supérieur pour se déplacer ensuite vers le sud-est. Nous avons frappé un autre \
qui reflète le nord IP. 9
peut également être ignoré, puis l'adresse IP est renvoyée au bas de la grille. Après quelques lignes, nous le redirigeons vers l'est avec plus >
de commodité. "7102"
Pousse ensuite les points de code du 2017
, 4&o
imprime ces quatre caractères et @
termine le programme.
Wumpus est le premier langage 2D sur une grille triangulaire, ce qui rend le déplacement dans le code très différent (et nous permet à nouveau d’atteindre facilement une partie inutilisée du code). Ainsi, au lieu de considérer chaque caractère de la grille comme un petit carré, pensez plutôt à alterner des triangles ascendants et descendants. Le coin supérieur gauche est toujours un triangle ascendant.
Wumpus n'a pas de direction <^>v
, mais il a des miroirs \/
. Cependant, en raison de la grille triangulaire, ceux-ci fonctionnent différemment de la plupart des autres langues. L’IP rebondit comme un rayon lumineux (comme d’habitude), mais vous devriez penser qu’ils ont un angle de 60 °. Ainsi, une IP se déplaçant vers l’est finira par se déplacer le long de l’axe nord-ouest de la grille.
Autre différence par rapport à la plupart des autres langues, les bords de la grille ne sont pas enveloppés, mais la propriété intellectuelle rebondit sur les bords (comme si ces cellules contenaient les miroirs appropriés). Un autre détail amusant est que les diagonales à travers la grille triangulaire ressemblent en fait à des escaliers dans le code source.
Dans cet esprit, le code exécuté par Wumpus est le suivant (où j'ai remplacé des espaces par .
souci de clarté:
v19977/
02
89
..
..
.....*...#2018O@
Ce ne v19977
sont que des cochonneries que nous pouvons ignorer. /
envoie l'IP au nord-ouest, où il se déplace à nouveau 977
(de la droite) en rebondissant sur le bord supérieur. Ensuite, l’IP se déplace vers le sud-ouest à travers le 2089
et un tas d’espaces, avant d’atteindre le bord gauche pour être à nouveau reflété vers l’est. *
est également indésirable. Enfin, #2018
appuie 2018
, O
imprime et @
termine le programme.
Années manquantes
Enfin, quelques notes sur des années que je n'ai pas couvertes.
Alors que je cherchais des langages 2D pour trouver, au fil des années, des langages appropriés qui pourraient être utilisés dans un polyglotte, j'ai découvert que contrairement à la croyance populaire, Befunge n'était pas le premier langage 2D. Ce titre semble appartenir à Biota, qui a déjà été créé en 1991. Malheureusement, la langue n’a aucun résultat, je n’ai donc pas pu l’utiliser pour ce défi.
Autant que je sache, aucun langage 2D n'a été créé en 1992 et 1995. Cela laisse quelques années que je n'ai pas couvertes:
- 1994: Orthagonal est créé indépendamment de Befunge. Les langues sont sémantiquement assez similaires en réalité, mais Orthagonal ne présente pas le code source en 2D. Au lieu de cela, chaque ligne est un
(x, y, instruction)
tuple. J'ai même obtenu les spécifications de langue et l'interprète original du créateur Jeff Epler, mais au final, le fait que la syntaxe ne soit pas 2D rendait le langage inapproprié pour ce polyglotte.
- 1996: Orthogonal , un successeur d'Orthagonal (créé par quelqu'un d'autre) est créé, mais aux fins de cette polyglotte, il souffre des mêmes problèmes qu'Orthagonal.
- 1999: Le seul langage que j'ai pu trouver était l'automate cellulaire REDGREEN de Chris Pressey . Malheureusement, contrairement à son prédécesseur RUBE, il ne semble pas avoir de sémantique d’E / S.
- 2000: Il existe un autre automate cellulaire appelé noit o'main worb de Chris Pressey, mais il ne possède pas non plus d'E / S. Il y a aussi Numberix que je n'ai pas essayé de lancer et je ne sais pas s'il ignorerait les caractères non hexadécimaux dans le code source.
- 2002: Clunk sans I / O et ZT dont les spécifications linguistiques me terrifient.
- 2007: J'ai trouvé trois langues ici. Zetaplex est basé sur des images (donc pas assez ) et RubE On Conveyor Belts semble nécessiter un en-tête avec un format plutôt strict qui aurait gâché la première ligne du programme. Il y a aussi Cellbrain by Quintopia, mais cela semble également nécessiter un en-tête spécifique.
- 2013: Encore une fois, j'ai trouvé trois langues. La pêche pourrait être possible avec une bonne quantité de restructuration, mais il faudrait que le programme commence par un quai valide. Quipu , de mémoire, est beaucoup trop strict sur sa syntaxe pour permettre beaucoup de polyglot. Et Swordfish est un autre membre de la> <> famille, mais malheureusement, je n’ai pas pu trouver d’interprète. Sinon, celui-ci serait probablement assez facile à ajouter.
Si vous êtes intéressé, voici la liste complète des langues 2D implémentées, triées par année dans la mesure où je les ai trouvées (au moment où cette réponse a été publiée). S'il en manque, merci de me le faire savoir par chat , je serais très intéressé par une liste complète.