Hyper über Quines

27

Inspiriert von Hyperprogramming: N + N, N × N, N ^ N in einem .
Vielen Dank an @MartinEnder und @trichoplax für ihre Hilfe im Sandkasten.

Definitionen

Hyperquines

Definieren Sie eine Hyperquine der Ordnung n als ein quineähnliches vollständiges Programm oder eine Funktion P , die alle Regeln erfüllt, die für richtige Quines gelten, und außerdem die folgende Struktur aufweist.

P ist die Verkettung von Zeichen Gruppen , die bestehen aus n Kopien des gleichen Charakters. Wenn P ausgeführt wird, ist die Ausgabe die Verkettung derselben Gruppen, ergänzt um eine weitere Kopie des Zeichens.

Beispiele

  • In einer hypothetischen Programmiersprache, in der der Quellcode aabbccdie Ausgabe generiert aaabbbccc, bildet dieses Programm eine Hyperquin der Ordnung 2 .

  • Die Definition erfordert nicht, dass die Zeichen verschiedener Gruppen unterschiedlich sind.

    Wenn der Quellcode aabbccdie Ausgabe generiert aaaabbbbcccc, ist das Programm ein Hyperquin der Ordnung 1 ; Der Quellcode besteht aus sechs Einzelzeichengruppen, die Ausgabe aus sechs Zeichenpaaren.

  • In GS2 wird das leere Programm gedruckt \nund das Programm wird \ngedruckt \n\n. Weder Hyperquine \nnoch \n\nHyperquine, da sie nicht alle Eigenschaften von erfüllen richtigen . Kein Teil des Quellcodes kodiert einen anderen Teil der Ausgabe.

Hyperquine Ketten

Definieren Sie eine Hyperquinkette der Länge n als endliche Folge von n vollen Programmen oder n Funktionen
(P 1 ,…, P n ) , die die folgenden Bedingungen erfüllen.

  1. Die Ausgänge von P 1 , ..., P n-1 sind P 2 , ..., P n .

  2. P 1 ,…, P n sind Hyperquinen.

  3. Die Ordnungen von P 1 ,…, P n bilden eine streng ansteigende Folge von benachbarter ganzer Zahlen.

Definieren Sie schließlich eine unendliche Hyperquinkette als eine unendliche Folge von vollständigen Programmen oder Funktionen (P 1 , P 2 ,…), so dass jedes Anfangsintervall (P 1 ,…, P n) ) eine Hyperquinkette der Länge n darstellt .

Beispiele

  • In einer hypothetischen Programmiersprache, in der der Quellcode aabbccdie Ausgabe generiert aaabbbccc, die wiederum die Ausgabe generiert aaaabbbbcccc, wird das Paar (aabbcc , aaabbbccc) eine Hyperquinkette der Länge 2 .

    Beachten Sie, dass aaaabbbbcccc- die Ausgabe des letzten Hyperquins in der Kette - keine bestimmte Ausgabe erzeugen muss. Es muss nicht einmal gültiger Quellcode sein.

  • Die Fortsetzung des vorherigen Beispiel, wenn aaaabbbbccccdas Ausgangssignal erzeugt aaaaabbbbbccccc, das Triplett ( aabbcc, aaabbbccc, aaaabbbbccccdarstellt) , um eine Kette von hyperquine Länge 3 .

    Wenn dieses Muster für immer fort, die Folge ( aabbcc, aaabbbccc, aaaabbbbcccc, ...) bildet eine unendliche hyperquine Kette.

  • Das Programmpaar ( abc, aabbcc) mit Ausgaben ( aabbcc, aaaabbbbcccc) ist keine Hyperquinkette, da die Ordnungen der Hyperquine beide 1 sind und daher keine streng ansteigende Folge bilden.

  • Das Programmpaar ( aabbcc, aaaabbbbcccc) mit den Ausgängen ( aaaabbbbcccc, aaaaabbbbbccccc) ist keine Hyperquinkette, da die Ordnungen der Hyperquine 1 und 4 sind daher keine Folge benachbarter Ganzzahlen bilden.

Regeln

Aufgabe

Schreiben Sie in einer Programmiersprache Ihrer Wahl eine nicht triviale Hyperquin-Kette, dh eine Kette, die aus mindestens 2 besteht Hyperquinen besteht.

Wie üblich dürfen Ihre Programme in keiner Form Eingaben vornehmen oder auf ihren eigenen Quellcode zugreifen.

Wenn Ihr Interpreter eine implizite Newline druckt, Ihre hyperquines müssen berücksichtigen.

Alle Standardlücken - insbesondere solche, die sich auf Quines beziehen.

Wertung

Die längste Hyperquinkette gewinnt. Wenn zwei oder mehr Einsendungen gleich sind, gewinnt die Einsendung unter diesen, die mit dem kürzesten Hyperquin (gemessen in Zeichen ) beginnt . Wie üblich ist die Posting-Zeit der letzte Tiebreaker.


Sie müssen dieselbe Zeichenkodierung für Quellcode, Ausgabe, Zeichenzahl und Ausführung verwenden. Zum Beispiel kann das Python - Programm print 42ist nicht eine 2-Zeichen UTF-32 Einreichung, da der Interpreter jedes Byte als ein einzelnes Zeichen behandelt. Wenn Ihre Sprache nicht zeichenbasiert ist, behandeln Sie alle einzelnen Bytes als Zeichen.

Dennis
quelle
3
Okay, vielleicht war Helkas Herausforderung nicht unmöglich, aber das ist sicherlich: D
Beta Decay
1
@BetaDecay Ist es wirklich? :)
Martin Ender

Antworten:

10

Befunge-98 , unendliche Ordnung, 54 52 38 36 Bytes

Zweiter Ansatz - unendliche Ordnung, 36 Bytes

Dieses Programm würde tatsächlich beim 34. Hyperquin brechen, da der ASCII-Wert von "die String-Interpretation stören würde (und bei 59 ;), aber wir versetzen die Speicherung dieses Werts an eine Position, die niemals ausgeführt wird (dh (0, 1)anstelle von (0, 0)).

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

Versuchen Sie es online: 1 , 2 , 10 , 34 , 42

Erläuterung

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.

Erster Ansatz - Ordnung 34, 52 Bytes (verwendet Introspektion, also technisch nicht legal)

Aus dem Grund in dem obigen Beitrag würde dieses Programm bei der Bestellung 34 abbrechen (obwohl ich es nicht getestet habe).

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

Probieren Sie es online!

Hactar
quelle
2
Obwohl die Ausgabe korrekt zu sein scheint und dies sicherlich beeindruckend ist, bin ich nicht davon überzeugt, dass eine richtige Quine verwendet werden kann g, die den Quellcode des Programms direkt zu lesen scheint. Trotzdem bin ich kaum ein Befunge-Experte, daher könnte ich etwas missverstehen.
Dennis
Ich gverwende hier für zwei Zwecke: zum Speichern von Daten und zum Lesen des Quellcodes. Die zweite ist vielleicht etwas lückenhaft , obwohl esolangs.org/wiki/Befunge#Quine ein Beispiel gibt, mit gdem auch der Quellcode gelesen werden kann. In der Zwischenzeit werde ich sehen, ob ich eine Version erstellen kann, die keine Selbstbeobachtung verwendet.
Hactar
Ich wusste, dass dies in Befunge möglich sein musste, aber ich hatte keine Ahnung, wie. Danke, dass du es mir gezeigt hast. +1
ETHproductions
10

> <> , unendliche Reihenfolge, 178 Bytes

Das Programm enthält einen nachgestellten Zeilenvorschub.

^
.
*
&
:
&
+
*
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
'

Probieren Sie es online aus: 1 , 2 , 3 , 10 (Das letzte Mal dauert es eine Weile, bis es ausgeführt wird.)

Retina-Skript zum Generieren der Quelle aus einem linearen Programm.

Erläuterung

Die Hauptidee ist es, die Quine vertikal zu drehen, damit der tatsächliche Kontrollfluss durch die Wiederholung nicht beeinträchtigt wird. ZB beginnt die zweite Hyper-Quine wie folgt:

^^

..

**

Da wir uns nur durch die erste Spalte bewegen, müssen wir uns nicht um wiederholte Zeichen kümmern. Auch wenn wir den größten Teil des Codes als Zeichenfolge mit übergeben ', wird ein Leerzeichen für jede leere Zeile übergeben, wodurch wir die Anzahl der Wiederholungen bestimmen können. Das heißt, es gibt einige Einschränkungen aufgrund dieser Leerzeilen:

  • Wir können keine "großen Zahlen als Zeichencodes in den Hauptteil der Quine eingeben, da dies zu einem zusätzlichen Druck führen würde32 s die wir nicht wollen.
  • Wir können nicht verwenden ?oder !weil sie nur das nächste Zeichen überspringen, was in diesem Fall ein Leerzeichen wäre (damit sie den nächsten Befehl nicht wirklich überspringen).

Daher erfolgt der gesamte Steuerungsfluss mit expliziten Sprüngen (im Grunde genommen 2D goto), deren tatsächliche Offsets wir basierend auf der Anzahl der Wiederholungen berechnen müssen.

Schauen wir uns also den eigentlichen Code an. Wir beginnen damit, ^dass der Code von unten nach oben ausgeführt wird. Zum leichteren Lesen schreiben wir den eigentlichen Code in der Ausführungsreihenfolge aus (und löschen den Code, ^weil er nie wieder ausgeführt wird):

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

Das 'ist die Standard - quining Technik für> <> (und Befunge, glaube ich). Es wechselt in den Zeichenkettenmodus, was bedeutet, dass die gefundenen Zeichen auf den Stapel geschoben werden, bis die nächste gefunden 'wird. Leerzeilen werden implizit mit Leerzeichen aufgefüllt, weshalb wir alle Leerzeichen dazwischen setzen. Leerzeilen am Programmende werden ignoriert. Nachdem sich die IP-Adresse geändert hat und erneut trifft ', haben wir die erste Spalte des Programms auf dem Stapel, mit Ausnahme der eigentlichen '.

Schauen wir uns an, wie wir damit das gesamte Programm drucken.

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.

Das Programm wird beendet, wenn der Stapel leer ist und die erste innere Schleife kein weiteres Zeichen druckt.

Martin Ender
quelle