Dans les aventures précédentes de la série de blogs Quine, nous avons exploré comment écrire nos propres Quines et Introns. Aujourd'hui, nous verrons ce que sont les QuineRelays et comment vous pouvez exploiter les Introns pour les créer.
Imaginez un cercle de programmes, chacun écrit dans une langue différente. Chaque programme de ce cercle a un seul objectif : imprimer le code source du programme suivant dans la séquence. Le dernier programme boucle ensuite la boucle en imprimant le code source du tout premier programme.
Essentiellement, les QuineRelays sont un ensemble de n programmes, dans n langages différents tels que :
Voyons quelques exemples pour mieux saisir le concept.
Ce QuineRelay de 2e ordre comprend un programme JavaScript qui imprime un programme Python, qui réimprime ensuite le programme JavaScript d'origine. C'est un duo dynamique d'auto-réplication.
JavaScript → Python ⥀
JavaScript : essayez-le en ligne !
console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q+[]})())`)})`)())
Python : essayez-le en ligne !
print("console.log((q=_=>`print(${JSON.stringify(`console.log((q=${q+[]})())`)})`)())")
Les choses deviennent encore plus intéressantes avec un QuineRelay de 3ème ordre. Celui-ci commence par un programme Haskell, qui génère un programme Python, qui génère un programme Ruby, et enfin, le programme Ruby revient au programme Haskell d'origine.
Haskell → Python2 → Ruby ⥀
Haskell : Essayez-le en ligne !
q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')'] main=q "q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']" "def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'" "def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end"
Python2 : essayez-le en ligne !
def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')' q("def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'","def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end","q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']")
Ruby : Essayez-le en ligne !
def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end q("def e(x) return 34.chr+x+34.chr end;def q(a,b,c) print b+10.chr+'main=q '+e(b)+' '+e(c)+' '+e(a)+' '+10.chr end","q a b c=putStrLn $ b ++ [toEnum 10,'q','('] ++ show b ++ [','] ++ show c ++ [','] ++ show a ++ [')']","def q(a,b,c):print b+chr(10)+'q('+repr(b)+','+repr(c)+','+repr(a)+')'")
Voici un QuineRelay de 4ème ordre : Ruby → Java → C# → Python ⥀
GitHub
À travers les cultures, il existe plusieurs symbolismes partagés. L’un d’eux est l’Ouroboros, qui fait référence aux mythologies égyptienne, grecque, romaine, hindoue, sibérienne, nordique, africaine et sud-américaine. L'Ouroboros est un ancien symbole représentant un serpent ou un dragon consommant sa propre queue, représentant le cycle éternel de création et de destruction.
Dans la mythologie nordique, Jörmungandr est un serpent colossal, l'enfant du milieu de Loki et de la géante Angrboða. Odin jeta Jörmungandr dans l'océan entourant Midgard (le royaume des humains), où le serpent devint si immense qu'il encercla le monde et saisit sa propre queue. En raison du fait qu'il entoure Midgard (la Terre), il est appelé le Serpent du Monde - Ouroboros. Jörmungandr lâchant sa queue est l'un des signes du début du Ragnarök (la bataille finale du monde).
Les relais Quine incarnent assez bien ce symbolisme, car chaque programme du cycle donne naissance au suivant, pour finalement renaître, et sont donc surnommés Ouroboros programmes.
Accrochez-vous à vos sièges. Voici un Ouroboros QuineRelay d'ordre 128. Oui, vous avez bien lu. 128 !!!
Ruby → Rust → Scala → ... (120 autres) ... → Python → R → Ratfor → rc → REXX ⥀
GitHub
Comme si ce n'était pas assez impressionnant, il comprend un œuf de Pâques. Le code Ruby original lors d'un zoom arrière contient un dragon Ouroboros !
Commençons l'intron Python que nous avons écrit plus tôt et essayons de le transformer en QuineRelay de 2ème ordre.
Python Intron : essayez-le en ligne !
intron = 'wubbalubbadubdub' data = "print('intron =', repr(intron)); print('data =', repr(data)); print(data)" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
Grâce à la magie des introns, nous pouvons désormais facilement mettre la partie code d'un Quine frère d'une langue différente dans l'intron. Produire un programme de la forme :
Python :
intron = "code part of sibling" data = "code part of self" print('intron =', repr(intron)); print('data =', repr(data)); print(data)
Depuis, chaque variable est juste, agissant comme donnée d'un Quine différent. Renommons data et intron, respectivement en d1 et d2.
Python :
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d1)
Maintenant, d2 agit comme un intron, mais le programme ci-dessus essayait toujours d'imprimer une partie du code de lui-même. Pour qu'il imprime la source du suivant, imprimons(d2) au lieu de print(d1) à la fin.
Python :
d1 = "code part of self" d2 = "code part of sibling" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
Nous savons déjà que le contenu de d1 n'est qu'une copie de la ligne 3. Mais nous n'avons pas encore le contenu de d2.
Dites, nous voulions créer un QuineRelay avec JavaScript. Écrivons un intron similaire en JS.
JavaScript :
d1 = "code part of sibling" d2 = "code part of self" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1);
Maintenant, la ligne 3 de l'intron JS ci-dessus, est le code du programme frère que nous voulions !
Collez le code de chacun comme introns dans l'autre.
Note. Nous devons ajouter d1 + '' dans js pour éviter certaines incohérences de citation
Python: Try it online!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 + '');" print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)
JavaScript: Try it online!
d1 = "print('d1 =', repr(d1)); print('d2 =', repr(d2)); print(d2)" d2 = "console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 + '');" console.log(`d1 = ${JSON.stringify(d1)}`); console.log(`d2 = ${JSON.stringify(d2)}`); console.log(d1 + '');
There you go. It's a proper 2nd order QuineRelay! A Python program, that prints a JavaScript program, that prints the original Python program back in a cycle.
Creating a QuineRelay is an exercise in creative coding and understanding how different languages represent and manipulate strings. It involves weaving together introns from various programs, each containing the code to replicate its next neighbour.
At its core, an nth-order relay is a game of n clever ways to escape quotes across n programming languages.
Stay tuned for the next post on MultiQuine!
Sources and references:
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!