Hyper sur les quines

27

Inspiré de l' hyperprogrammation: N + N, N × N, N ^ N tout en un .
Merci à @MartinEnder et @trichoplax pour leur aide dans le bac à sable.

Définitions

Hyperquines

Définissez une hyperquine d'ordre n comme un programme complet ou une fonction P de type quine qui satisfait toutes les règles qui s'appliquent aux quines appropriées et, en outre, a la structure suivante.

P est la concaténation des caractères groupes qui sont constitués de n copies du même caractère. Lorsque P est exécuté, la sortie est la concaténation des mêmes groupes, augmentée d'une copie de plus du caractère.

Exemples

  • Dans un langage de programmation hypothétique où le code source aabbccgénère la sortie aaabbbccc, ce programme constitue un hyperquine d'ordre 2 .

  • La définition n'exige pas que les caractères des différents groupes soient différents.

    Si le code source aabbccgénère la sortie aaaabbbbcccc, le programme est un hyperquine d'ordre 1 ; le code source se compose de six groupes de caractères uniques, la sortie de six paires de caractères.

  • Dans GS2 , le programme vide s'imprime \net le programme \ns'imprime \n\n. Cependant, les hyperquines \nne le \n\nsont pas non plus, car elles ne satisfont pas à toutes les propriétés des quines appropriées ; aucune partie du code source n'encode une partie différente de la sortie.

Chaînes hyperquines

Définissons une chaîne hyperquine de longueur n comme une séquence finie de n programmes complets ou n fonctions
(P 1 ,…, P n ) qui satisfait les contraintes suivantes.

  1. Les sorties de P 1 ,…, P n-1 sont respectivement P 2 ,…, P n .

  2. P 1 ,…, P n sont des hyperquines.

  3. Les ordres de P 1 ,…, P n forment une séquence strictement croissante d' entiers adjacents .

Enfin, définissons une chaîne hyperquine infinie comme une séquence infinie de programmes ou fonctions complets (P 1 , P 2 ,…) de sorte que chaque intervalle initial (P 1 ,…, P n ) constitue une chaîne hyperquine de longueur n .

Exemples

  • Dans un langage de programmation hypothétique où le code source aabbccgénère la sortie aaabbbccc, qui, à son tour, génère la sortie aaaabbbbcccc, la paire ( aabbcc, aaabbbccc) constitue une chaîne hyperquine de longueur 2 .

    Notez que aaaabbbbcccc- la sortie de la dernière hyperquine de la chaîne - n'a pas à produire une sortie spécifique; il n'a même pas besoin d'être du code source valide.

  • En reprenant l'exemple précédent, si aaaabbbbccccgénère la sortie aaaaabbbbbccccc, le triplet ( aabbcc, aaabbbccc, aaaabbbbcccc) constitue une chaîne de longueur hyperquine 3 .

    Si cette tendance se poursuit toujours, la séquence ( aabbcc, aaabbbccc, aaaabbbbcccc, ...) constitue une chaîne hyperquine infinie.

  • La paire de programmes ( abc, aabbcc) avec des sorties ( aabbcc, aaaabbbbcccc) n'est pas une chaîne hyperquine, puisque les ordres des hyperquines sont tous les deux 1 , donc ils ne forment pas une séquence strictement croissante.

  • La paire de programmes ( aabbcc, aaaabbbbcccc) avec des sorties ( aaaabbbbcccc, aaaaabbbbbccccc) n'est pas une chaîne hyperquine, puisque les ordres des hyperquines sont 1 et 4 , donc ils ne forment pas une séquence d'entiers adjacents.

Règles

Tâche

Dans un langage de programmation de votre choix, écrivez une chaîne hyperquine non triviale, c'est-à-dire une chaîne composée d'au moins 2 hyperquines.

Comme d'habitude, vos programmes ne peuvent prendre aucune entrée ni accéder à leur propre code source sous quelque forme que ce soit.

Si votre interprète imprime une nouvelle ligne implicite, vos hyperquines doivent en tenir compte.

Toutes les failles standard - en particulier celles liées aux quines - s'appliquent.

Notation

La chaîne hyperquine la plus longue gagne. Si deux soumissions ou plus sont liées, la soumission parmi celles qui commence par l'hyperquine la plus courte (mesurée en caractères ) l'emporte. Comme d'habitude, le temps d'affichage est le dernier bris d'égalité.


Vous devez utiliser le même codage de caractères pour le code source, la sortie, le nombre de caractères et l’exécution. Par exemple, le programme Python print 42n'est pas une soumission UTF-32 à 2 caractères, car l'interpréteur traite chaque octet comme un seul caractère. Si la langue de votre choix n'est pas basée sur des caractères, traitez tous les octets individuels comme des caractères.

Dennis
la source
3
D'accord, alors peut-être que le défi d'Helka n'était pas impossible, mais c'est sûrement le cas: D
Beta Decay
1
@BetaDecay Est-ce vraiment? :)
Martin Ender

Réponses:

10

Befunge-98 , ordre infini, 54 52 38 36 octets

Deuxième approche - ordre infini, 36 octets

Ce programme se briserait en fait à la 34e hyperquine puisque la valeur ASCII de "perturberait l'interprétation des chaînes (et à 59 ;), mais nous compensons le stockage de cette valeur à une position qui ne sera jamais exécutée (c'est- (0, 1)à- dire à la place de (0, 0)).

1+::0*x01pn'!1+:#jr;,kg10@k!:kg10;#"

Essayez-le en ligne: 1 , 2 , 10 , 34 , 42

Explication

INSTRUCTIONS  STACK (PYTHON PSEUDOCODE)           EXPLANATION
1+            [n]                                 Push n many 1s onto the stack, then sum them up
::            [n]*(at least 3)                    Duplicate that sum at least twice
0*            [n]*(at least 2)+[0]                Push a whole lot of zeros, then multiply them all together
x             [n]*(at least 1)                    Pop a vector off the stack (n, 0) and set the IP delta to that; now the IP is only executing every nth character
01p           [n]*(at least 1)                    Place n in the program at coordinates (0, 1); this is just for storage
n             []                                  Clear the stack
'!1+          ['"']                               '!' is character 33; one less than 34, or '"'
:#jr          ['"']                               We duplicate the 34 (all we care is that it's a rather large number), then turn around and skip that many spaces
                                                  The IP, having jumped 34*n instructions to the left, is now way in the negatives
                                                  Execution resumes on the other side of the program (the following instructions have been reversed for readability
"             [the program of order 1]            The quote-at-the-end-of-the-program is a common trick for one-liner Befunge quines
#; ... ;                                          Jumps into a loop (when the IP hits one semicolon it skips to the next, restarting the loop)
01gk:         [(rest of string), char*(n+2)]      This duplicates the letter n+1 times*, leaving n+2 copies on the stack
!k@                                                If the number on the top of the stack is zero (i.e. we are printing), it will execute '@',
                                                  ending the program; otherwise, it will NOT execute '@' and will instead continue normally
                                                  Vague* 'k' instruction FTW
10gk,                                             If we aren't done yet, print the character n+1 times* (and restart the loop)

* 'k' is a very strange instruction. It pops a number off the stack; if the number is zero, it skips the command in front of it. If the number is greater than zero,
  it will execute the instruction that many times PLUS ONE. This is actually strangely advantageous in this program.

Première approche - ordre 34, 52 octets (utilise l'introspection, donc techniquement non légal)

Pour la raison indiquée dans le post ci-dessus, ce programme tomberait en panne à l'ordre 34 (même si je n'ai pas testé).

1+::0*x:00p'1\k:00gk,1#;:00g*0g00gk:$00gk,1+:'4-!k@;

Essayez-le en ligne!

Hactar
la source
2
Bien que la sortie semble être correcte et c'est certainement impressionnant, je ne suis pas convaincu qu'une quine appropriée puisse utiliser g, qui semble lire directement le code source du programme. Cela dit, je ne suis guère un expert Befunge, donc je peux mal comprendre quelque chose.
Dennis
J'utilise gici à deux fins: pour stocker des données et pour lire le code source. Le second pourrait être un peu sommaire, même si esolangs.org/wiki/Befunge#Quine a un exemple gpermettant également de lire le code source. En attendant, je vais voir si je peux créer une version qui n'utilise aucune introspection.
Hactar
Je savais que cela devait être possible à Befunge, mais je ne savais pas comment. Merci de m'avoir montré. +1
ETHproductions
10

> <> , ordre infini, 178 octets

Le programme contient un saut de ligne arrière.

^
.
*
&
:
&
+
*
2
b
*
*
6
9
$
0
)
*
4
8
:
~
.
*
&
:
&
+
*
2
b
*
*
2
b
$
0
)
i
:
-
1
o
a
&
:
&
o
~
.
*
&
:
&
+
*
7
7
*
*
4
6
$
0
)
0
:
-
1
$
o
:
$
&
:
&
&
,
*
8
b
-
1
l
}
*
3
d
'

Essayez-le en ligne: 1 , 2 , 3 , 10 (Ce dernier prend un certain temps à courir.)

Script Retina pour générer une source à partir d'un programme linéaire.

Explication

L'idée principale est de tourner le quine verticalement, afin que le flux de contrôle réel ne soit pas affecté par la répétition. Par exemple, le deuxième hyper quine commence comme:

^^

..

**

Comme nous ne parcourons que la première colonne, nous n'avons pas à nous soucier des caractères répétés. De plus, lorsque nous poussons la majorité du code sous forme de chaîne avec ', cela poussera un espace pour chaque ligne vide, ce qui nous donne un moyen de déterminer le nombre de répétitions. Cela dit, il y a quelques limitations en raison de ces lignes vides:

  • Nous ne pouvons pas utiliser "pour pousser de grands nombres comme codes de caractères dans la partie principale du quine, car cela pousserait des 32s supplémentaires dont nous ne voulons pas.
  • Nous ne pouvons pas utiliser ?ou !parce qu'ils ne sautent que le caractère suivant qui serait un espace dans ce cas (donc ils ne sauteraient pas la commande suivante).

Par conséquent, tout le flux de contrôle se fait avec des sauts explicites (goto 2D, essentiellement), dont nous devons calculer les décalages réels en fonction du nombre de répétitions.

Examinons donc le code réel. Nous commençons par ^donc le code est exécuté de bas en haut. Pour une lecture plus facile, écrivons le code réel dans l'ordre d'exécution (et supprimons le ^car il n'est plus jamais exécuté):

'd3*}l1-b8*,&&:&$:o$1-:0)0$64**77*+&:&*.~o&:&ao1-:i)0$b2**b2*+&:&*.~:84*)0$96**b2*+&:&*.

C'est 'la technique de quining standard pour> <> (et Befunge, je suppose). Il passe en mode chaîne, ce qui signifie que les caractères rencontrés sont poussés sur la pile jusqu'à ce que le suivant 'soit rencontré. Les lignes vides sont implicitement remplies d'espaces, c'est pourquoi nous obtenons tous les espaces entre les deux. Les lignes vides à la fin du programme sont ignorées. Donc, après que l'IP se termine et frappe à 'nouveau, nous avons la première colonne du programme sur la pile, à l'exception du 'lui - même.

Voyons comment nous utilisons cela pour imprimer l'ensemble du programme.

d3*}    Put a 36 (the ') at the bottom of the stack. Now the stack holds
        a representation of the entire first column.
l1-     Push the depth of the stack, minus (so minus to ').
b8*,    Divide by 88. The original program has 89 lines. If we divide the 
        depth of the stack (minus 1) by 88, we get the order of the current
        hyperquine (due to all the spaces we've pushed).
&       Store the order of the hyperquine in the register.
        Begin of main loop:
&:&       Push a copy of the register onto the stack. Call that N.
          Begin of line-printing loop:
$:o$        Print a copy of the top character on the stack.
1-          Decrement N.
:0)         Check whether it's still positive (gives 0 or 1).
0$          Put a 0 underneath. This will be the x-coordinate of a jump.
64**        Multiply the conditional by 24. This is the number of commands
            in this inner loop.
77*+        Add this to 49, the offset of the end of the loop.
            The result is line we want to jump to in the order-1 hyperquine.
&:&*        Multiply by the order of the quine (so that we jump further on
            higher quine orders).
.         Jump. If N isn't zero yet, this repeats the inner loop. Otherwise
          we continue right here.
~         Discard N (now 0).
o         Output one last copy of the top character on the stack.
&:&       Push a copy of the register onto the stack. Call that N.
          Begin of linefeed-printing loop:
ao          Print a linefeed.
1-          Decrement N.
:i)         Check whether it's still non-negative (gives 0 or 1).
            The next bit is essentially the same loop structure as above,
            but with loop length 22 and offset 22:
0$
b2**
b2*+
&:&*
.         Jump. If N isn't -1 yet, this repeats the inner loop. Otherwise
          we continue right here.
          Begin of space-clearing loop:
~           Discard the top of the stack. On the first iteration this is the
            -1 from the previous loop. Afterwards, it's one of the spaces
            representing an empty line.
:84*)       Check if the top of the stack is a space.
            And another loop conditional. This one works the other way round:
            the difference is 54, which is the distance between the beginning
            of this loop and the main loop. The offset is the beginning
            of this loop, at 22 as above.
0$
96**
b2*+
&:&*
.         Jump. If the top of the stack is still a space this repeats the 
          inner loop. Otherwise we continue from the top of the main loop.

Le programme se termine lorsque la pile est vide et la première boucle interne ne parvient pas à imprimer un autre caractère.

Martin Ender
la source