Hyper circa quines


27

Ispirato da Hyperprogramming: N + N, N × N, N ^ N tutto in uno .
Grazie a @MartinEnder e @trichoplax per il loro aiuto nella sandbox.

definizioni

Hyperquines

Definire un hyperquine di ordine n come un programma completo simile a un quine o una funzione P che soddisfa tutte le regole che si applicano ai quines corretti e, inoltre, ha la seguente struttura.

P è la concatenazione di gruppi di caratteri costituiti da n copie dello stesso personaggio. Quando viene eseguito P , l' output è la concatenazione degli stessi gruppi, aumentata di un'altra copia del personaggio.

Esempi

  • In un ipotetico linguaggio di programmazione in cui il codice sorgente aabbccgenera l'output aaabbbccc, questo programma costituisce un'iperquina di ordine 2 .

  • La definizione non richiede che i caratteri di gruppi diversi siano diversi.

    Se il codice sorgente aabbccgenera l'output aaaabbbbcccc, il programma è un hyperquine di ordine 1 ; il codice sorgente è costituito da sei gruppi di caratteri singoli, l'output di sei coppie di caratteri.

  • In GS2 , il programma vuoto viene stampato \ne il programma \nstampa \n\n. Tuttavia, \nné lo \n\nsono né le hyperquine, dal momento che non soddisfano tutte le proprietà delle quine appropriate ; nessuna parte del codice sorgente codifica una parte diversa dell'output.

Catene iperquine

Definire una catena hyperquine di lunghezza n come sequenza finita di n programmi completi o n funzioni
(P 1 , ..., P n ) che soddisfa i seguenti vincoli.

  1. Le uscite di P 1 , ..., P n-1 sono rispettivamente P 2 , ..., P n .

  2. P 1 , ..., P n sono iperquine.

  3. Gli ordini di P 1 , ..., P n formano una sequenza strettamente crescente di numeri interi adiacenti .

Infine, definire una catena iperquina infinita come una sequenza infinita di programmi o funzioni completi (P 1 , P 2 , ...) in modo tale che ogni intervallo iniziale (P 1 , ..., P n ) costituisca una catena iperquina di lunghezza n .

Esempi

  • In un ipotetico linguaggio di programmazione in cui il codice sorgente aabbccgenera l'output aaabbbccc, che a sua volta genera l'output aaaabbbbcccc, la coppia ( aabbcc, aaabbbccc) costituisce una catena hyperquine di lunghezza 2 .

    Si noti che aaaabbbbcccc- l'output dell'ultima hyperquine nella catena - non deve produrre un output specifico; non deve nemmeno essere un codice sorgente valido.

  • Continuando l'esempio precedente, se aaaabbbbccccgenera l'uscita aaaaabbbbbccccc, la tripletta ( aabbcc, aaabbbccc, aaaabbbbcccc) costituisce una catena hyperquine di lunghezza 3 .

    Se questo modello continua sempre, la sequenza ( aabbcc, aaabbbccc, aaaabbbbcccc, ...) costituisce una catena infinita hyperquine.

  • La coppia di programmi ( abc, aabbcc) con output ( aabbcc, aaaabbbbcccc) non è una catena hyperquine, poiché gli ordini delle hyperquine sono entrambi 1 , quindi non formano una sequenza strettamente crescente.

  • La coppia di programmi ( aabbcc, aaaabbbbcccc) con output ( aaaabbbbcccc, aaaaabbbbbccccc) non è una catena hyperquine, poiché gli ordini delle hyperquine sono 1 e 4 , quindi non formano una sequenza di numeri interi adiacenti.

Regole

Compito

In un linguaggio di programmazione a tua scelta, scrivi una catena di hyperquine non banale, cioè una catena che consiste di almeno 2 hyperquine.

Come al solito, i tuoi programmi non possono accettare alcun input o accedere al proprio codice sorgente in qualsiasi forma.

Se il tuo interprete stampa una nuova riga implicita, le tue hyperquine devono tenerne conto.

Si applicano tutte le scappatoie standard , in particolare quelle relative alle quine.

punteggio

Vince la catena iperquina più lunga . Se due o più invii sono in parità, l'inoltro tra questi che inizia con l'iperquina più breve (misurata in caratteri ) vince. Come al solito, il tempo di pubblicazione è l'ultimo tiebreaker.


È necessario utilizzare la stessa codifica dei caratteri per codice sorgente, output, conteggio dei caratteri ed esecuzione. Ad esempio, il programma Python nonprint 42 è un invio UTF-32 a 2 caratteri, poiché l'interprete tratta ogni byte come un singolo carattere. Se la tua lingua preferita non è basata sui caratteri, tratta tutti i singoli byte come caratteri.


3
Ok, quindi forse la sfida di Helka non è stata impossibile, ma sicuramente questo è: D
Decadimento beta

1
@BetaDecay È davvero? :)
Martin Ender,

Risposte:


10

Befunge-98 , ordine infinito, 54 52 38 36 byte

Secondo approccio - ordine infinito, 36 byte

Questo programma si spezzerebbe effettivamente alla 34a hyperquine poiché il valore ASCII "interromperebbe l'interpretazione della stringa (e a 59, ;), ma compensiamo la memorizzazione di quel valore su una posizione che non verrà mai eseguita (cioè (0, 1)invece di (0, 0)).

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

Provalo online: 1 , 2 , 10 , 34 , 42

Spiegazione

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.

Primo approccio - ordine 34, 52 byte (utilizza l'introspezione, quindi tecnicamente non legale)

Per la ragione nel post sopra, questo programma si romperà all'ordine 34 (anche se non ho ancora testato).

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

Provalo online!


2
Mentre l'output sembra essere corretto e questo è certamente impressionante, non sono convinto che possa essere usato un vero quine g, che sembra leggere direttamente il codice sorgente del programma. Detto questo, difficilmente sono un esperto di Befunge, quindi potrei fraintendere qualcosa.
Dennis,

Sto usando gper due scopi qui: per memorizzare i dati e leggere il codice sorgente. Il secondo potrebbe essere un po 'impreciso, anche se esolangs.org/wiki/Befunge#Quine ha un esempio che utilizza gper leggere anche il codice sorgente. Nel frattempo, vedrò se riesco a creare una versione che non utilizza alcuna introspezione.
Hactar,

Sapevo che questo doveva essere possibile in Befunge, ma non avevo idea di come. Grazie per avermelo mostrato. +1
ETHproductions

10

> <> , ordine infinito, 178 byte

Il programma contiene un avanzamento riga finale.

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

Provalo online: 1 , 2 , 3 , 10 (l'ultimo richiede un po 'di tempo per essere eseguito.)

Script Retina per generare sorgente dal programma lineare.

Spiegazione

L'idea principale è di ruotare il quine in verticale, in modo che il flusso di controllo effettivo non sia influenzato dalla ripetizione. Ad esempio il secondo hyper quine inizia come:

^^

..

**

Dal momento che ci stiamo muovendo solo attraverso la prima colonna, non dobbiamo preoccuparci di personaggi ripetuti. Inoltre, quando si preme la maggior parte del codice come stringa ', questo spinge uno spazio per ogni riga vuota, il che ci dà un modo per determinare il numero di ripetizioni. Detto questo, ci sono alcune limitazioni dovute a queste righe vuote:

  • Non possiamo usare "per spingere grandi numeri come codici carattere nella parte principale del quine, perché questo spingerebbe ulteriori 32s che non vogliamo.
  • Non possiamo usare ?o !perché saltano solo il personaggio successivo che sarebbe uno spazio in quel caso (quindi in realtà non saltare il prossimo comando).

Quindi, tutto il flusso di controllo viene eseguito con salti espliciti (goto 2D, in pratica), di cui dobbiamo calcolare gli offset effettivi in ​​base al numero di ripetizioni.

Quindi diamo un'occhiata al codice reale. Iniziamo ^quindi il codice viene eseguito dal basso verso l'alto. Per una lettura più semplice, scriviamo il codice effettivo in ordine di esecuzione (e rilasciamo il ^perché non viene mai eseguito di nuovo):

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

Il 'è la tecnica standard per quining> <> (e Befunge, credo). Passa alla modalità stringa, il che significa che i caratteri incontrati vengono inseriti nello stack fino a quando non 'viene rilevato il successivo . Le linee vuote sono implicitamente riempite di spazi, motivo per cui abbiamo tutti gli spazi in mezzo. Le righe vuote alla fine del programma vengono ignorate. Quindi dopo che l'IP si sposta e colpisce di 'nuovo, abbiamo la prima colonna del programma nello stack, tranne per se 'stessa.

Diamo un'occhiata a come lo usiamo per stampare l'intero programma.

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.

Il programma termina quando la pila è vuota e il primo ciclo interno non riesce a stampare un altro carattere.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.