Fueue , 423 octets
Fueue est un esolang basé sur une file d'attente dans lequel le programme en cours est la file d'attente.
)$$4255%%1(~):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]](H-):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Essayez-le en ligne!
Comment ça fonctionne
Cette explication peut ou peut ne pas être échappée de la main. D'autre part, je ne sais pas comment l'expliquer de manière beaucoup plus courte, j'espère que les gens pourront suivre.
Aide-mémoire Fueue
Voir l' article du wiki esolang pour plus de détails, y compris les quelques fonctionnalités non utilisées dans ce programme.
Le programme initial est l'état initial de la file d'attente, qui peut contenir les éléments suivants:
- Les littéraux entiers (non négatifs uniquement dans la source, mais les négatifs peuvent être calculés), en les exécutant imprime un caractère.
- Blocs imbriqués délimités par des crochets, inertes (conservés intacts sauf si une fonction agit sur eux).
- Fonctions, leurs arguments sont les éléments qui les suivent immédiatement dans la file d'attente:
+*/-%
: arithmétique entière ( -
est unaire, %
négation logique). Inerte si pas d'arguments numériques.
()<
: mettre l'élément entre crochets, supprimer les crochets du bloc, ajouter le dernier élément au bloc. Les deux derniers sont inertes sauf s’ils sont suivis d’un bloc.
~:
: échange, dupliquer.
$
: copie (prend nombre + élément). Inerte avant non-nombre.
H
: arrêter le programme.
Notez que []
nid, ()
ne le faites pas - ces derniers sont simplement des fonctions séparées.
Syntaxe de trace d'exécution
Les espaces sont facultatifs dans Fueue, sauf entre les chiffres. Dans les traces d'exécution suivantes, il sera utilisé pour suggérer la structure du programme, en particulier:
- Lorsqu'une fonction s'exécute, ses arguments et ses arguments sont définis à partir des éléments entourés d'espaces. Si certains des arguments sont compliqués, il peut également y avoir un espace entre eux.
- De nombreuses traces d'exécution sont divisées en un "blob de délai" sur la gauche, séparé d'une partie à droite qui effectue la manipulation substantielle des données. Voir la section suivante.
Les accolades {}
(non utilisées dans Fueue) sont utilisées dans les traces pour représenter le résultat entier d'expressions mathématiques. Cela inclut les nombres négatifs, comme Fueue n'a que des littéraux non négatifs - -
est la fonction de négation.
Différents noms métavariables ...
sont utilisés pour désigner les valeurs et les abréviations.
Tactique dilatoire
Intuitivement, l'exécution tourne autour de la file d'attente, modifiant partiellement ce qu'elle traverse. Les résultats d'une fonction ne peuvent plus être utilisés avant le cycle suivant. Différentes parties du programme évoluent efficacement en parallèle tant qu'elles n'interagissent pas.
En conséquence, une grande partie du code est consacrée à la synchronisation, en particulier au retardement de l'exécution de parties du programme jusqu'au moment opportun. Il y a beaucoup d'options pour jouer au golf, ce qui a tendance à transformer ces parties en blobs illisibles qui ne peuvent être compris qu'en traçant leur cycle d'exécution par cycle.
Ces tactiques ne seront pas toujours mentionnées individuellement ci-dessous:
)[A]
retards A
pour un cycle. (Probablement la méthode la plus facile et la plus lisible.)
~ef
permute les éléments e
et f
retarde également leur exécution. (Probablement le moins lisible, mais souvent le plus court pour les retards mineurs.)
$1e
retarde un seul élément e
.
-
et %
sont utiles pour retarder des nombres (ces derniers pour 0
et 1
.)
- Lors du retard de plusieurs éléments égaux dans une ligne,
:
ou $
peut être utilisé pour les créer à partir d'un seul.
(n
les enveloppes n
entre parenthèses peuvent être supprimées ultérieurement. Ceci est particulièrement vital pour les calculs numériques, car les nombres sont trop instables pour être même copiés sans les mettre d'abord dans un bloc.
Structure générale
Le reste de l'explication est divisé en sept parties, chacune correspondant à une section du programme en cours. Les cycles les plus longs, après lesquels la plupart d’entre eux se répètent, seront appelés "itérations" pour les distinguer des "cycles" de passages uniques dans toute la file.
Voici comment le programme initial est divisé entre eux:
A: )$$4255%%1(~
B: ):[)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
C:
D: (H-
E:
F:
G: ):~:[)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:](106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
Le grand chiffre à la fin du programme code le reste en inverse, deux chiffres par caractère, avec 30 soustractions de chaque valeur ASCII (donc, par exemple, 10
code a (
.)
À un niveau supérieur, vous pouvez penser que les données de ce programme (à commencer par le bignum) vont de droite à gauche, alors que le contrôle coule de gauche à droite. Cependant, à un niveau inférieur, Fueue brouille constamment la distinction entre code et données.
- La section G décode le bignum en chiffres ASCII (par exemple, digit en
0
tant qu’entier 48
), en séparant d’abord les chiffres les moins significatifs. Il produit un chiffre tous les 15 cycles.
- La section F contient les valeurs numériques ASCII produites (chacune dans un bloc) jusqu'à ce que la section E puisse les consommer.
- La section E traite les chiffres produits deux à la fois, en les associant dans des blocs du formulaire
[x[y]]
et en imprimant également le caractère codé de chaque paire.
- La section D consiste en un bloc profondément imbriqué, construit progressivement à partir des
[x[y]]
blocs, de sorte qu'une fois qu'il contient tous les chiffres, il peut être exécuté pour les imprimer tous, puis arrêter l'ensemble du programme.
- La section C traite de la construction de la section D et recrée également la section E.
- La section B recrée la section C ainsi que elle-même tous les 30 cycles.
- La section A compte à rebours les cycles jusqu'à la dernière itération des autres sections. Ensuite, il abandonne la section B et exécute la section D.
Section A
La section A traite de la planification de la fin du programme. Il faut 4258 cycles pour réduire à une seule fonction d'échange ~
, qui effectue ensuite un ajustement à la section B qui arrête sa boucle principale et commence à exécuter la section D à la place.
)$ $4255% %1 (~
)$%%%...%% %0 [~]
)$%%%...% %1 [~]
⋮
)$ %0 [~]
) $1[~]
)[~]
~
- Une
$
fonction crée 4255 copies de ce qui suit %
tandis que le (
retour à la ligne est mis ~
entre crochets.
- Chaque cycle, le dernier
%
est utilisé pour faire basculer le nombre suivant entre 0
et 1
.
- Lorsque tous les
%
s sont utilisés, le $1
crée une copie du [~]
(effectivement un NOP), et au cycle suivant le )
supprime les crochets.
Section B
La section B gère la régénération et une nouvelle itération de la section C tous les 30 cycles.
) : [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [)$$24%%0:<[~:)~)]~[$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] [BkB]
)$ $24% %0 :< [~:)~)] ~ [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] [BkB]
)$ %...%%% %1 < < [~:)~)] [BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...%% %0 < [~:)~)[BkB]] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
)$ %...% %1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
⋮
) $1 [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]]
) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
~:) ~)[BkB] [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]
) : [BkB] ) [$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<] (2)
) [BkB] [BkB] $11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<
- Un
:
duplique le gros bloc suivant (une copie abrégée [BkB]
), puis )
supprime les crochets de la première copie.
$$24%%0
met en place un compte à rebours similaire à celui de la section A.
- Tandis que ce compte à rebours
:<
décale , se transforme en <<
et ~
échange deux blocs, plaçant le code d’une nouvelle section C en dernier.
- Les deux
<
fonctions regroupent les deux derniers blocs dans le premier - ceci est redondant dans les itérations normales, mais permettra à la ~
section A de faire son travail à la fin.
- (1) Lorsque le compte à rebours est terminé, le
)
supprime les crochets extérieurs. Next se ~:)
transforme en ):
et bascule ~)
a )
au début du code de la section C.
- (2) La section B est maintenant revenue à son cycle initial, alors que a
)
est sur le point de supprimer les crochets pour commencer à exécuter une nouvelle itération de la section C.
Dans la dernière itération, le ~
from de la section A apparaît au point (1) ci-dessus:
~ ) [~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] (1)
[~:)~)[BkB][$11~)~<[[+$4--498+*-:~-10)):])<~][)))~]<]] )
Ils ~
basculent à )
travers le bloc et dans la section C, empêchant la section B d’être réexécutée.
Section C
La section C gère la fusion de nouvelles paires de caractères numériques dans le bloc de la section D, ainsi que la création de nouvelles itérations de la section E.
L'illustration ci-dessous montre une itération typique avec x
et y
représentant les codes ASCII des chiffres. À la toute première itération, les éléments "D" et "E" entrants sont les éléments initiaux [H]
et, à la -
place, aucune section précédente E n’ayant été exécutée pour produire des paires de caractères numériques.
C D E
$11~ ) ~<[[+$4--498+*-:~-10)):])<~] [)))~] < [)))~[...]] [x[y]]
~~~ ~~~ ~~~ ~~) [[+$4--498+*-:~-10)):])<~] < [)))~] [)))~[...][x[y]]]
~~~ ~~~ ) ~ [[+$4--498+*-:~-10)):])<~] [)))~[)))~[...][x[y]]]]
~~~ ~ ) [)))~[....]] [[+$4--498+*-:~-10)):])<~]
~~[)))~[....]] )[[+$4--498+*-:~-10)):])<~]
[)))~[....]] ~[+$4--498+*-:~-10)):])<~
- Ceci utilise une méthode de synchronisation différente que j'ai découverte pour cette réponse. Lorsque vous avez plusieurs fonctions d'échange
~
dans une ligne, celle-ci sera réduite d'environ 2/3 à chaque cycle (car on ~
échange deux suivantes), mais parfois avec un reste de ~
s qui fait des ravages, manipule soigneusement ce qui suit.
$11~
produit une telle ligne. La prochaine ~
échange un à <
travers le bloc suivant. Un autre <
à la fin ajoute un nouveau bloc de paires de chiffres (les chiffres x et y sous forme de codes ASCII) dans le bloc de la section D.
- Au cycle suivant, la
~
ligne a un ~~
reste qui remplace ~
le suivant )
. L'autre <
ajoute la section D à un [)))~]
bloc.
- Ensuite, le commutateur
~
lui-même permute le bloc suivant avec le nouveau code de section E dans le bloc de section D. Ensuite, un nouveau reste ~
bascule a )
travers, et finalement le dernier ~~
de la ~
rangée échange l'un d'entre eux contre la section E, tout comme il )
a supprimé ses crochets.
Lors de la dernière itération, les sections A ~
ont remplacé les )
sections B par les sections C. Toutefois, la section C est si courte qu'elle a déjà disparu et )
se termine au début de la section D.
Section D
La section D traite de l’impression du grand chiffre final et de l’arrêt du programme. Pendant la majeure partie du programme, les sections B – G coopèrent pour la construction.
(H -
[H]-
⋮
[)))~[H-]] After one iteration of section C
⋮
[)))~[)))~[H-][49[49]]]] Second iteration, after E has also run
⋮
) [)))~[...]] [49[48]] Final printing starts as ) is swapped in
))) ~[...][49[48]]
)) )[49[48]] [...]
)) 49 [48][...] Print first 1
) )[48] [...]
) 48 [...] Print 0
)[...] Recurse to inner block
...
⋮
)[H-] Innermost block reached
H - Program halts
- Dans le premier cycle du programme, un
(
encapsule la fonction d’arrêt H
entre parenthèses. A -
suit, il sera utilisé comme élément factice pour la première itération au lieu d’une paire de chiffres.
- La première paire de chiffres réels incorporée
[49[49]]
correspond au dernier 11
dans le chiffre.
- La toute dernière paire de chiffres
[49[48]]
(correspondant 10
au début du chiffre) n'est pas réellement incorporée dans le bloc, mais cela ne fait aucune différence car )[A[B]]
et )[A][B]
sont équivalents, les deux se transformant en A[B]
.
Après l'itération finale, la )
permutation vers la droite de la section B arrive et le bloc de la section D est débloqué. Au )))~
début de chaque sous-bloc, vous vous assurez que toutes les pièces sont exécutées dans le bon ordre. Enfin, le bloc le plus à l'intérieur contient un H
arrêt du programme.
Section E
La section E gère la combinaison de paires de chiffres ASCII générés par la section G et imprime le caractère codé correspondant et envoie un bloc avec la paire combinée vers la gauche aux sections C et D.
Encore une fois, ci-dessous montre une itération typique avec x
et y
représentant les codes ASCII des chiffres.
E F
~ [+$4--498+*-:~-10)):] ) < ~ [y] [x]
) [+$4--498+*-:~-10)):] < [x] [y]
+ $4- - 498 +*- :~ -10 ) ) : [x[y]]
+--- -{-498} +*- ~~{-10} ) ) [x[y]] [x[y]]
+-- - 498 +* -{-10} ~ ) x [y] [x[y]]
+- -{-498} + * 10 x )[y] [x[y]]
+ - 498 + {10*x} y [x[y]]
+ {-498} {10*x+y} [x[y]]
{10*x+y-498} [x[y]]
[x[y]]
- Les blocs de chiffres entrants sont permutés, puis le bloc y est ajouté au bloc x et le bloc de paires entier est copié. Un exemplaire sera laissé jusqu'à la fin pour les sections C et D.
- L'autre copie est à nouveau débloquée, puis une séquence de fonctions arithmétiques est appliquée pour calculer
10*x+y-498
la valeur ASCII du caractère codé. 498 = 10*48+48-30
, le 48
s annule l’encodage ASCII de x
et y
tandis que le 30
décale l’encodage de 00–99
à 30–129
, qui inclut tout l’ASCII imprimable.
- Le nombre résultant est alors laissé à exécuter, ce qui affiche son caractère.
Section F
La section F comprend des blocs inertes contenant des codes de chiffres ASCII. Pour la majeure partie du programme, il y en aura au plus deux ici, car la section E les consomme à la même vitesse que G les produit. Cependant, lors de la phase d'impression finale, certains 0
chiffres redondants seront collectés ici.
[y] [x] ...
Section G
La section G gère le fractionnement du grand nombre à la fin du programme, les chiffres les moins significatifs en premier, et l'envoi de blocs avec leurs codes ASCII à gauche des autres sections.
Comme il n'a pas de vérification d'arrêt, il continuera à produire des 0
chiffres lorsque le nombre sera réduit à 0, jusqu'à ce que la section D interrompe tout le programme avec la H
fonction.
[BkG]
abrégé une copie du gros bloc de code de départ, qui est utilisé pour l'auto-réplication pour démarrer de nouvelles itérations.
Initialisation dans les premiers cycles:
) :~ : [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ( 106328966328112328136317639696111819119696281563139628116326221310190661962811611211962861109696289611619628116111612896281115421063633063961111116163963011632811111819159628151213262722151522061361613096119619190661966311961128966130281807072220060611612811961019070723232022060611
) ~ ~ [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] [BkG] [10...11]
) [)[):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):]~:] ~ [BkG] [10...11]
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [10...11] [BkG]
Itération typique, N
indique le nombre à diviser:
) [):~[)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+:5):] ~ : [N] [BkG]
) :~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/]+ :5 ) : [N] : [BkG]
) ~ ~ [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] +5 5 ) [N] [N] [BkG] [BkG]
) [)~:~~([:~)*[):~[$1(+48]):~+]-:~~)10)~~]/] ~ 10 N [N] [BkG] [BkG]
) ~:~ ~ ( [:~)*[):~[$1(+48]):~+]-:~~)10)~~] / N 10 [N] [BkG] [BkG]
) ~ : [:~)*[):~[$1(+48]):~+]-:~~)10)~~] ( {N/10} [N] [BkG] [BkG]
) [:~)*[):~[$1(+48]):~+]-:~~)10)~~] : [{N/10}] [N] [BkG] [BkG]
:~ )*[):~[$1(+48]):~+]- :~ ~)10 ) ~ ~ [{N/10}] [{N/10}] [N] [BkG] [BkG]
~~) *[):~[$1(+48]):~+]- ~~10 ) ) [{N/10}] ~ [{N/10}] [N] [BkG] [BkG]
) ~ * [):~[$1(+48]):~+] -10 ~ ) {N/10} [N] [{N/10}] [BkG] [BkG]
) [):~[$1(+48]):~+] * {-10} {N/10} ) [N] [{N/10}] [BkG] [BkG]
) :~ [$1(+48]) :~ + {-10*(N/10)} N [{N/10}] [BkG] [BkG]
) ~ ~ [$1(+48] ) ~ ~ {N%10} [{N/10}] [BkG] [BkG]
) [$1(+48] ~ ) {N%10} ~ [{N/10}] [BkG] [BkG]
$1( + 48 {N%10} ) [BkG] [{N/10}] [BkG]
( {48+N%10} BkG [{N/10}] [BkG] New iteration starts
[{48+N%10}] ....
- La tâche de retard ici est particulièrement poilue. Cependant, la seule nouvelle astuce de retardement consiste à utiliser
+:5
au lieu de --10
retarder 10
deux cycles. Hélas, un seul des participants 10
au programme en a bénéficié.
- Les blocs
[N]
et [BkG]
sont dupliqués, puis une copie de N
est divisée par 10
.
[{N/10}]
est dupliqué, plusieurs fonctions arithmétiques sont utilisées pour calculer le code ASCII du dernier chiffre de N
as 48+((-10)*(N/10)+N)
. Le bloc avec ce code ASCII est laissé pour la section F.
- L'autre copie de
[{N/10}]
est échangée entre les [BkG]
blocs pour définir le début d'une nouvelle itération.
Bonus Quine (540 octets)
)$$3371%%1[~!~~!)!]):[)$$20%%0[):]~)~~[)$$12%%0[<$$7%~~0):~[+----48+*-~~10))]<]<~!:~)~~[40~[:~))~:~[)~(~~/[+--48):]~10]+30])):]]][)[H]](11(06(06(21(21(25(19(07(07(19(61(96(03(96(96(03(11(03(63(11(28(61(11(06(06(20(18(07(07(18(61(11(28(63(96(11(96(96(61(11(06(06(19(20(07(07(18(61(30(06(06(25(07(96(96(18(11(28(96(61(13(15(15(15(15(22(26(13(12(15(96(96(19(18(11(11(63(30(63(30(96(03(28(96(11(96(96(61(22(18(96(61(28(96(11(11(96(28(96(61(11(96(10(96(96(17(61(13(15(15(22(26(11(28(63(96(19(18(63(13(21(18(63(11(11(28(63(63(63(61(11(61(42(63(63
Essayez-le en ligne!
Comme je ne savais pas quelle méthode serait la plus courte, j'ai d'abord essayé de coder les caractères sous forme de nombres à deux chiffres séparés par (
s. Le code de base est un peu plus court, mais la représentation de données 50% plus grande le compense. Pas aussi golfé que l'autre, car je me suis arrêté quand j'ai réalisé que ça ne battrait pas. Il a un avantage: il ne nécessite pas d'implémentation avec le support bignum.
Sa structure générale est quelque peu similaire à celle principale. La section G est manquante car la représentation des données remplit directement la section F. Cependant, la section E doit effectuer un calcul de divmod similaire pour reconstruire les chiffres des nombres à deux chiffres.