Un programma che stampa i programmi


13

Sfida

Il tuo obiettivo è quello di scrivere un programma che stampa un altro programma. Quel programma stampato dovrebbe stampare un altro programma e il nuovo programma dovrebbe stampare un altro programma, fino alla fine.

Regole

  1. Ogni programma deve contenere meno di 256 byte. (Se questo deve essere cambiato, lascia un commento)
  2. L'ultimo programma deve essere un programma vuoto.
  3. Ci deve essere un numero finito di programmi, quindi il programma non può essere un quine.
  4. Tutti i programmi devono essere eseguiti nella stessa lingua.
  5. Nessun input consentito.
  6. Il programma vincente è il programma che stampa il maggior numero possibile di programmi, contando se stesso.

In bocca al lupo!


Il punteggio massimo è 2^2048, o 3.2317e616.
orlp,

Per rendere più facile confrontare punteggi grande, si prega di includere un'approssimazione al tuo punteggio nella forma a*10^bin cui 1<=a<10e bè un numero naturale.
Flawr,

2
In realtà, il mio calcolo precedente era sbagliato. Supponendo che il programma debba essere in byte, il punteggio massimo possibile è <numero troppo lungo per un commento> o 1.2673e614.
orlp,

Risposte:


20

CJam, 4.56 × 10 526 programmi

2D#2b{"\256b_(256b:c'\s`_:(er`":T~{;38'ÿ*`{:T~{;63'ÿ*`{:T~{;88'ÿ*`{:T~{;114'ÿ*`{:T~{;140'ÿ*`{:T~{;166'ÿ*`{:T~{;192'ÿ*`{:T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}s(\T`}?\"_~"}_~

Punteggio esatto: 254 219 + 254 192 + 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 3

Tutti i programmi devono essere salvati utilizzando la codifica ISO-8859-1 per rispettare il limite della dimensione del file.

Grazie a @ChrisDrost che ha segnalato un bug e suggerito l'approccio di nidificazione.

Provalo online nell'interprete CJam .

254 219 + 2 ≈ 4,56 × 10 526 programmi

La condivisione della linea del punteggio può essere ottenuta con il seguente programma 1 molto più semplice .

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

L'esecuzione di questo programma produce il programma

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ"
{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

e dopo 254 219 - 1 più iterazioni, il programma

{\256b_(256b:c'\s`_:(er`Q?\"_~"}_~

Quest'ultimo programma non vuoto termina con un errore 2 e non stampa nulla (il programma vuoto).

Come funziona

Supponiamo che la stringa sia già nello stack.

{      e# Push a code block.
  \    e# Swap the string on top of the code block.
       e# This will cause a runtime error if there is no string on the stack.
  256b e# Convert the string (treated as a base-256 number) to integer (I).
  _(   e# Copy the integer and decrement the copy.
  256b e# Convert the integer into the array of its base-256 digits.
  :c   e# Cast each base-256 digit to character. Converts from array to string.
  '\s  e# Push a string that contains a single backslash.
  `    e# Push its string representation, i.e., the array ['" '\ '\ '"].
  _:(  e# Push a copy and decrement each character. Pushes ['! '[ '[ '!].
  er   e# Perform transliteration to replace "s with !s and \s with [s.
       e# This skips characters that require escaping.
  `    e# Push its string representation, i.e., surround it with double quotes.
  Q    e# Push an empty string.
  ?    e# Select the first string if I is non-zero, the empty string otherwise.
  \    e# Swap the selected string with the code block.
  "_~" e# Push that string on the stack.
}      e#
_~     e# Push a copy of the code block and execute it.
       e# The stack now contains the modified string, the original code block
       e# and the string "_~", producing an almost exact copy of the source.

254 192 ≈ 5,35 × 10 461 altri programmi

Questo è dove le cose diventano un po 'pazze.

Il primo programma è altamente comprimibile. Scrivendo un programma simile che, anziché il programma vuoto, alla fine produce il primo programma della sezione precedente, possiamo migliorare il punteggio di 254 192 programmi 3 .

Il programma

"ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ"
{"\256b_(256b:c'\s`_:(er`":T~{;219'ÿ*`{Q?\"_~"}s(\T}?\"_~"}_~

è simile al primo programma della sezione precedente e l'esecuzione del primo e il suo output per 254 192 iterazioni produce il secondo.

Supponiamo che la stringa sia già nello stack:

{                           e# Push a code block.
  "\256b_(256b:c'\s`_:(er`" e# Push that string on the stack.
                            e# The characters inside it behave exactly as
                            e# they did in the previous section.
  :T~                       e# Save the string in T and evaluate it.
  {                         e# If the integer I is non-zero, keep the generated
                            e# string; else:
    ;                       e#   Pop the code block from the stack.
    219'ÿ*`                 e#   Push a string of 219 ÿ's (with double quotes).
    {Q?\"_~"}               e#   Push that block on the stack.
    s                       e#   Push its string representation.
    (\                      e#   Shift out the { and swap it with the tail.
    T                       e#   Push T.
  }?                        e#
  \                         e# Swap the selected string with the code block
                            e# or T with the tail of the code block.
  "_~"                      e# Push that string on the stack.
}                           e#
_~                          e# Push a copy of the code block and execute it.

Programmi Moar

Il primo programma della sezione precedente è ancora altamente comprimibile, quindi possiamo applicare un metodo simile e scrivere un programma che, dopo 254 166 iterazioni, produce il suddetto programma.

Ripetendo questa tecnica ancora e ancora finché non raggiungiamo il limite di 255 byte, possiamo aggiungere un totale di 254 166 + 254 140 + 254 114 + 254 88 + 254 63 + 254 38 + 254 13 + 1 ≈ 1,59 × 10 399 programmi a quelli delle sezioni precedenti.


1 Newline aggiunto per chiarezza.
2 Per consenso su Meta , questo è consentito per impostazione predefinita.
3 o 0,000000000000000000000000000000000000000000000000000000000000000012%



5

JavaScript, 1000 programmi

x=999;
q=";alert(x=999?`q=${JSON.stringify(q)+q}`.split(x).join(x-1):``)";
alert(
    x ? `x=999;q=${JSON.stringify(q)+q}`.split(x).join(x-1) // basically .replaceAll(x, x-1)
      : ``
)

Se questo è valido dipende precisamente da come comprendere la terza regola.


Tecnicamente non è un quine, poiché stampa una versione modificata del proprio codice sorgente anziché una copia identica. Utilizza ovviamente tecniche simili a quelle dei quine. Penso che avremo bisogno di chiarimenti da @TheTurtle.
Giovanni,

5
@JohnE e Ypnypn Questo è qualcosa che avevo immaginato. Questo funziona
The Turtle,

6
Sei ancora ben al di sotto del limite di lunghezza del codice. Perché non cambi 999 in qualcosa di più grande?
DankMemes,

4

Ruby, 1.628 × 10 ^ 237 programmi

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;_="a=%#x-1;_=%p;puts _%%[a,_]if a";puts _%[a,_]if a

Lo stesso approccio della mia risposta al Perl, ma poiché Ruby gestisce già i big ints, è più facile memorizzarlo come esadecimale.


Ruby, 9.277 × 10 ^ 90 programmi

a=0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;b=0xf;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-("%x"%a).length));_="a=%#x;b=%#x;(b<1)&&(a-=1)&&b=eval('0x'+'f'*(74-('%%x'%%a).length));_=%p;puts _%%[a,b-1,_]if a";puts _%[a,b-1,_]if a

Quindi questo tentativo è una variazione leggermente diversa rispetto al precedente tipo di Quine, ma a causa di tutte le funzioni extra non riesco a ottenere il numero in nessun punto più vicino dell'altro ... È stato interessante provare un altro approccio!


4

Programmi Python 2, 9.7 * 10 ^ 229

O=0
if len(hex(O))<191:print"O=0x%x"%(O+1)+open(__file__).read()[-68:]

Bello, non ho pensato alla ripetizione delle stringhe!
Dom Hastings,

2

Programmi C, 2.2 * 10 ^ 177

#define S(s)char*q=#s,n[]="#####################################################################################################";i;s
S(main(){while(n[i]==91)n[i++]=35;i==101?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})

Non è perfetto, ma abbastanza buono. Voglio dire, è esattamente 255lungo byte e genera programmi della stessa lunghezza. Probabilmente potresti armeggiare ancora un po 'per ottenere altri programmi, ma lo lascerò com'è per ora.

Il programma si basa su un semplice C quine. Inoltre c'è un algoritmo di conteggio abbastanza semplice che conta attraverso tutti i possibili valori dell'array char n. Abbiamo tanti programmi quante permutazioni della stringa n.

L'intervallo di caratteri è limitato a un intervallo da #(= 35) a [= (91). Questo perché non ne voglio nessuno "o \nella stringa, perché devono essere salvati.

La generazione programma termina quando tutti i valori nella matrice char nsono [. Quindi emette un semplice programma fittizio main(){}, che a sua volta non genera nulla.

#define  S(s) char *q = #s; /* have the source as a string */ \
char n[] = "#####################################################################################################"; \ 
int i; \
s /* the source itself */
S(main() {
    while(n[i]=='[') /* clear out highest value, so next array element be incremented */
        n[i++]='#'; 
    i==101 /* end of array reached? output dummy program */
        ? q = "main(){}"
        : n[i]++; /* count one up in the whole array */
    printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)", n, q);
})

A dimostrazione che dovrebbe funzionare Ho appena cambiato i limiti, in modo che solo i caratteri tra ASCII-Code 35e 36vengono utilizzati e solo 4 elementi di un array.

I programmi risultanti sono

% echo > delim; find -iname 'program_*.c' | xargs -n1 cat delim

#define S(s)char*q=#s,n[]="####";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$###";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$##";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$#";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="###$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$##$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$#$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="##$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$#$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="#$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="$$$$";i;s
S(main(){while(n[i]==36)n[i++]=35;i==4?q="main(){}":n[i]++;printf("#define S(s)char*q=#s,n[]=\"%s\";i;s\nS(%s)",n,q);})
#define S(s)char*q=#s,n[]="####";i;s
S(main(){})

Questo genera 2^4 + 1 = 17diversi programmi.

Quindi il programma sopra mostra ((91-35)+1)^101 + 1 = 57^101 + 1 ~= 2.2 * 10^177diversi programmi. Non sono del tutto sicuro se questo conta, o se il mio calcolo è persino corretto


1
Potresti per favore includere che si tratta di 2.2 * 10^177(per coloro che vogliono confrontare)?
Flawr,

Non sapevo come calcolare questo, ma l'ho incluso ;-)
MarcDefiant,


1

Perl, 1 × 10 ^ 163

Altrimenti si tratta di un quine piuttosto semplice, ridotto al minor numero possibile di caratteri, che funziona solo mentre il contatore non lo è 0.

use bigint;$i=9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999||die;$_=<<'e';eval
print"use bigint;\$i=$i-1||die;\$_=<<'e';eval
${_}e
"
e

1

Lisp comune, 10 113 -1

(LET ((X
       99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999))
  (WHEN #1=(PLUSP X)
    #2=(SETF *PRINT-CIRCLE* T)
    #3=(PRINT (LIST 'LET `((X ,(1- X))) (LIST 'WHEN '#1# '#2# '#3#)))))
  • Ci sono 113 nove.
  • Il prossimo programma ha 112 nove seguiti da un 8
  • Il prossimo programma ha 112 nove seguiti da un 7
  • ...

Il numero di nove è limitato dalla dimensione massima del codice, 256, tenendo conto degli spazi introdotti dalla stampante.


1

Perl, 1,4 * 10 ^ 225

use bignum;open$F,__FILE__;$_=<$F>;s/0x\w+/($&-1)->as_hex/e;0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff&&print

Approccio simile a Python; stesso risultato!


0

> <> , 65534 (?) Programmi

Ho aggiunto un punto interrogativo accanto a 65533 poiché non ho ancora verificato che possa stampare 65533 (anche se ho motivo di credere che dovrebbe). Una volta che ho un po 'più di tempo, ho intenzione di trovare un modo per testarlo.

":?!;1-r00gol?!;a0.�

Puoi provarlo online qui .

L'essenza di questo programma è che cambia l'output del personaggio alla fine e quindi diminuisce il suo valore numerico prima della stampa. Ho ottenuto 65534 programmi perché il valore ascii del carattere alla fine del codice è 65533, quindi contando il primo programma ne abbiamo 65534 (se contate il programma vuoto 65535, immagino). L'ultimo programma "restituito" non è nulla; termina semplicemente quando il valore del carattere è 0.

Sono abbastanza sicuro che sarà in grado di stampare un personaggio per tutte le iterazioni: non sono riuscito a trovare una fonte definitiva per quanti caratteri> <> possono stampare, ma ci sono caratteri direttamente sotto 65533, numericamente.

Fammi sapere se ci sono problemi con questa implementazione; Non sono sicuro della validità della mia iscrizione.


Spiegazione

Ho spudoratamente rubato l'idea di usare una virgoletta singola per creare una pseudo-quine dal wiki> <> e un commento che ho visto qui una volta.

":?!;1-r00gol?!;a0.�
"                     begins string parsing
 :?!;                 terminates program if final character is 0, numerically
     1-               decrements final character by 1
       r              reverses stack
        00g           grabs quotation mark (fancy way of putting " ")
           ol?!;      prints and terminates if stack is empty
                a0.   jumps back to o to loop 

Ciò che fa è analizzare tutto dopo le virgolette come caratteri, quindi decrementare l'ultimo. Da lì inverte semplicemente la pila (in modo da stampare nell'ordine giusto), inserisce una virgoletta sulla pila e quindi stampa fino a quando la pila è vuota.


0

Python, 1 × 10 ^ 194 programmi

n=99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
if n:print open(__file__).read().replace(str(n),str(n-1))

Questo deve essere eseguito da un file, non da un sostituto interattivo. Non è un quine.

Grazie a @The Turtle per avermi aiutato a salvare 3 byte, che è più spazio per nove!
Grazie a @poke per avermi aiutato a salvare 2 byte, che è più spazio per nove!


@ Cheese Lover The if n!=0è ridondante. Puoi semplicemente scrivere if n.
The Turtle,

Puoi liberarti anche di due spazi; dopo if n:e tra gli replaceargomenti.
colpì il

0

Bash, 52 programmi

Assolutamente privo di ispirazione e (si spera) solidamente all'ultimo posto.

echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo echo
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.