The Random Quine


15

Scrivi un programma in grado di generarsi casualmente.

Deve farlo in base ai token utilizzati nel suo codice sorgente. Se il codice sorgente del programma è composto da 50 token univoci ed è lungo 60 token, il programma dovrebbe generare 60 token in cui ogni token viene scelto casualmente da uno dei 50 token univoci.

Ad esempio, questo programma avrebbe una possibilità su 50 ^ 60 di riprodursi.

Che cos'è un token? Dipende dalla lingua. Ad esempio, identificatori ( foo_bar), parole chiave ( while) e numeri ( 42) contano come token nella maggior parte delle lingue. Gli spazi bianchi non contano nella maggior parte delle lingue.

Regole aggiuntive:

  • L'output può contenere solo token trovati nel codice sorgente dei programmi, separati dal delimitatore appropriato
  • L'output deve avere la stessa lunghezza del codice sorgente del programma, conteggiato da token
  • È possibile utilizzare un solo linguaggio di programmazione
  • Il codice sorgente deve avere almeno 3 token univoci
  • Escludere i commenti dal codice sorgente
  • Il programma dovrebbe avere solo una possibilità in U ^ L di riprodursi

Punteggio: vince il programma che ha le migliori possibilità di riprodursi.


@MathieuRodic: stai supponendo che il programma disegna token senza ripetizioni.
user2357112 supporta Monica

@MathieuRodic: fammi riformulare. Stai assumendo che il programma casualmente mescoli il multiset dei suoi token, piuttosto che disegnare i token L con ripetizione dall'insieme dei token U usati nella sua sorgente.
user2357112 supporta Monica

@ user2357112: vedo. Il mio errore è stato quello di considerare questo problema come un pareggio senza sostituzione.
Mathieu Rodic,

1
Le regole n. 1 e n. 5 sembrano contraddire me.
Cruncher,

4
Puoi presumere che le funzioni casuali integrate siano TRNG? Le implementazioni tipiche hanno semi troppo piccoli per produrre tutti gli output e quindi potrebbero non essere in grado di rigenerarsi.
Codici A Caos il

Risposte:


11

Python 2, 3 ^ -3 = 0.037

execl'abuso è abbastanza utile per ridurre il numero di token. Ora aggiornato per non leggere il file sorgente!

exec '' """
s = '''{a}
s = {b}
s = s.format(a='"'*3, b="'"*3+s+"'"*3)
import random
tokens = ['exec', "''", s]
print random.choice(tokens), random.choice(tokens), random.choice(tokens),
{a}'''
s = s.format(a='"'*3, b="'"*3+s+"'"*3)
import random
tokens = ['exec', "''", s]
print random.choice(tokens), random.choice(tokens), random.choice(tokens),
"""

Il extra ''tra exece la stringa tripla tra virgolette gigante è solo per riempire il conteggio di token al minimo richiesto di 3. Viene unito nella seconda stringa a causa della concatenazione letterale implicita della stringa.

Versione originale di apertura del file sorgente:

exec '''
# String literals are one token!
import random
import tokenize

with open(__file__) as f:
    tokens = [x[1] for x in tokenize.generate_tokens(f.readline)][:-1]

''' '''
# Splitting the string into two strings pads the token count to the minimum of 3.

print random.choice(tokens), random.choice(tokens), random.choice(tokens),
'''

A rigor di termini, la grammatica di Python posiziona un token ENDMARKER alla fine del file sorgente e non possiamo produrre un file sorgente con ENDMARKER sparso casualmente. Facciamo finta che non esista.


@Cruncher Questa è la probabilità. 3 ^ -3 == 1/3 ^ 3
Austin Henley

2
+1 per un brillante hack delle regole. La stessa idea implementata in J: ".]';(?3 3 3){]`".;~({:,],{:,],6#{:)'';(?3 3 3){]`".;~({:,],{:,],6#{:)'''''''.
algoritmo

5

Javascript, 102 token, 33 unici, 7,73 × 10-154

Nota, questo è un vero quine. Non legge il file o usa evaloFunction.toString

meta = "meta = ; out = '' ; tokens = meta . split ( '\\u0020' ) ; tokens . push ( '\"' + meta + '\"' ) ; length = tokens . length ; tmp = length ; unique = { } ; while ( tmp -- ) unique [ tokens [ tmp ] ] = unique ; unique = Object . keys ( unique ) ; tmp = unique . length ; while ( length -- ) out += tokens [ ~~ ( Math . random ( ) * tmp ) ] + '\\u0020' ; console . log ( out )"; 
out = '';
tokens = meta.split('\u0020');
tokens.push('"' + meta + '"');
//console.log(tokens);
length = tokens.length;
tmp = length;
unique = { };
while(tmp--) unique[tokens[tmp]] = unique;
unique = Object.keys(unique);
//console.log(unique);
tmp = unique.length;
while(length--)
    out += unique[~~(Math.random() * tmp)] + '\u0020';
console.log(out)

4

Python: P (generazione del programma in 1 prova) = 3.0317 * 10 ^ -123

34 token unici, 80 token totali. Nota che c'è uno spazio alla fine di ogni riga.

import tokenize , random 
tokens = [ x [ 1 ] for x in tokenize . generate_tokens ( open ( __file__ , 'r' ) . readline ) ] [ : -1 ] 
s = '' 
for x in tokens : s += random . choice ( list ( set ( tokens ) ) ) ; s += [ ' ' , '' ] [ s [ -1 ] == '\n' ] 
print s 

Uscita campione:

' ' random len set 'r' , for ( list , import ] ] tokens : random [ for '\n' import readline readline 'r' tokens [ len 'r' import '' choice '' '' for in ( readline ( = open readline , list 1 list s += for s 1 , '' : 1 += list len - __file__ ; open __file__ print . - ] 'r' for import [ print . , 

; . [ [ print print __file__ generate_tokens ] ; open ] , readline 

Grazie all'altra soluzione Python di user2357112 per avermi ricordato di scartare l'ultimo token e utilizzare di __file__cui in precedenza ero ignaro.


3

J - 1 in 11 17 = 1.978 x 10 -18

;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''

J ha un sacco di piccoli strumenti utili per svolgere questo tipo di lavori.

  • Prima di tutto, qualsiasi stringa di numeri separata da spazio è un token . Significa una matrice unidimensionale di quei numeri. Ecco come funziona il lexer di J. A proposito, sono diciassette anni 11, se qualcuno è curioso.

  • (,,,{:,{:)'QUINE'''è un trucco di quine comune in J, fatto per usare il minor numero possibile di token: {:significa coda , quindi aggiunge la stringa a se stesso e quindi aggiunge due copie dell'ultimo carattere alla fine. Poiché l'ultimo carattere è una virgoletta singola (J usa stringhe in stile Pascal), il risultato è QUINE'QUINE'''.

  • ;:è un tokenizer e spezza una stringa di input come se fosse un codice J, restituendo un elenco di caselle. La lunghezza di questo risultato è 17.

  • ~.prende tutti gli elementi unici di questo array. La lunghezza di questo risultato è 11.

  • ?si chiama Roll . Per ogni numero intero nel suo argomento, seleziona un numero positivo casuale maggiore o uguale a zero, minore di quel numero. Quindi qui J genererà 17 numeri da 0 a 10 inclusi.

  • { utilizza gli indici casuali per selezionare gli elementi dal nostro elenco di token unici in scatole.

  • ; apre tutte queste caselle ed esegue il risultato insieme.

Seguono alcuni esempi. Le righe rientrate sono i prompt di input e le linee a filo con il lato sinistro sono l'output dell'interprete.

   ;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''
~.~.(?;;:11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''(){11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){(;:;
   ;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''
{';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)''',?{:;:{:';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11{:{;(;:{:,~.

2

poscritto

Questo è stato divertente

/cvx /cvx cvx /exec /exec cvx /dup /rand /mod /get /== /array /astore /realtime
/srand /repeat 6 17 54 17 /array cvx exec /astore cvx exec 54 /dup cvx /rand
cvx 17 /mod cvx /get cvx /== cvx 6 /array cvx exec /astore cvx exec cvx /realtime
cvx exec /srand cvx exec /repeat cvx exec

Ci sono 17 token unici e 54 token in totale per circa 1 probabilità 3.6e-67.


2

Spazio bianco, 3 ^ -205 3 ^ -189 3 ^ -181 3 ^ -132 ~ = 10 ^ -63

Questo è un programma di spazi bianchi che, se seminato con caratteri casuali, ha una possibilità 1 su 3 ^ 132 di riprodursi (3 token distinti, ripetuto 132 volte). Deve essere eseguito il seeding con almeno 132 caratteri casuali quando eseguito, (Whitespace non ha una funzione casuale o data incorporata con cui eseguire il seeding) ad es.some_whitespace_interpreter my_quine.ws <some_random_source >quine_output.ws . Il punteggio sarebbe migliorato se il programma potesse essere ulteriormente giocato a golf, ma questo è il mio primo "vero" spazio degli spazi bianchi, quindi lo lascerò con la mia magra quantità di golf.

Codice Whitespace semplice o vederlo in esecuzione : (per provarlo, fai clic su "modifica", copia il materiale all'interno dei tag <pre>; dovrebbe essere 132 caratteri con EOL in stile Unix)

    

























Codice annotato con quale comando è cosa (non tecnicamente un quine, in quanto non riprodurrà i commenti):

stack push_number + 0 end
stack push_number + 1 0 0 1 fine
pila heap store push_number + 1 fine
stack push_number + 1 0 0 0 0 0 fine
pila heap store push_number + 1 0 end
stack push_number + 1 0 1 0 fine
pila heap store push_number + 1 0 0 0 0 0 1 1 fine
flusso
make_label loop_begin  
pila push_number + 1 1 fine
IO  
leggere la pila di caratteri push_number + 1 1 fine
heap recupera stack push_number + 1 1 end
aritmetica modulo heap recuperare IO  
stack di caratteri di stampa push_number + 1 fine
aritmetica sottrarre la pila duplicata
 flusso
jump_if_zero end_prog
flusso
salta a 
loop_begin  
flusso
make_label end_prog
flusso
END_PROGRAM

Se il seme sembra essere equivalente (i personaggi sono presi mod 3 per essere convertiti in token) a questo, avrà successo:

CCCCACCCBCCBABBCCCCBACCCBCCCCCABBCCCCBCACCCBCBCABBCCCCBCCCCCBBAACCBACCCBBABABCCCCBBABBBCCCBBABCBBBBBBACCCCCBABCCBCACABBAACABAACCAAAA

È un programma piuttosto semplice, approssimativamente equivalente a questo programma Ruby:

i = 131
while true
    print '\t \n'[STDIN.getc.ord % 3]
    i = i - 1
    break if i < 0
end

1

Perl, 27 token, P = 1.4779 x 10 -34

@ARGV=$0;print$W[rand@W]for@W=split/(\W)/,readline

Ultima modifica: utilizzare @ARGV=$0invece di open*ARGV,$0salvare un token.

  • 15 token unici
  • Appaiono 4 gettoni 2 volte ( =, /, @, $)
  • 1 token appare 4 volte ( W)

Quindi penso che renda la probabilità (pow (2,2 * 4) * pow (4,4)) / pow (27,27), circa 1,48E-34.

Se il codice sorgente si trova in un file chiamato ARGV, è possibile utilizzare questa soluzione token 26 con P = ~ 2.193 x 10 -31 :

@ARGV=ARGV;print$ARGV[rand@ARGV]for@ARGV=split/(\W)/,readline

In realtà, P = (4 * 2! + 4!) / 27!che si aggira intorno a 1.7632684538487448 x 10 ^ -26
Mathieu Rodic

0

133 = 0.037037 ...

(So ​​che questo non è code-golf, ma ...)

q[say |roll <<~~"q[$_]".EVAL>>: 3]~~.EVAL

Provalo online!

Più o meno la risposta di Python, in cui il primo token è una stringa letterale che viene valutata. I token sono

q[say |roll <<~~"q[$_]".EVAL>>: 3]   String literal
~~                                   Smartmatch operator
.EVAL                                Function call

Spiegazione:

q[say |roll <<~~"q[$_]".EVAL>>: 3]         # Push as string literal
                                  ~~       # Smartmatch by setting $_ to the string literal
                                    .EVAL  # Eval the string
            <<~~"q[$_]".EVAL>>             # From the list of tokens
       roll                   : 3          # Pick 3 times with replacement
  say |                                    # Join and print
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.