Das Zufällige Quine

15

Schreiben Sie ein Programm, das sich selbst zufällig generieren kann.

Dies muss auf der Grundlage der im Quellcode verwendeten Token erfolgen . Wenn der Quellcode Ihres Programms aus 50 eindeutigen Token besteht und 60 Token lang ist, sollte das Programm 60 Token ausgeben, wobei jedes Token zufällig aus einem der 50 eindeutigen Token ausgewählt wird.

Zum Beispiel hätte dieses Programm eine Chance von eins zu 60, sich selbst zu reproduzieren.

Was ist ein Token? Das kommt auf die Sprache an. Beispielsweise werden Bezeichner ( foo_bar), Schlüsselwörter ( while) und Zahlen ( 42) in den meisten Sprachen als Token gezählt. Leerzeichen würden in den meisten Sprachen nicht zählen.

Zusätzliche Regeln:

  • Die Ausgabe darf nur Token enthalten, die sich im Quellcode des Programms befinden und durch das entsprechende Trennzeichen getrennt sind
  • Die Ausgabe muss dieselbe Länge haben wie der Quellcode des Programms, gerechnet nach Token
  • Es darf nur eine Programmiersprache verwendet werden
  • Der Quellcode muss mindestens 3 eindeutige Token enthalten
  • Kommentare aus dem Quellcode ausschließen
  • Das Programm sollte nur eine einzige Chance haben, sich selbst zu reproduzieren

Wertung: Das Programm, das die beste Chance hat, sich selbst zu reproduzieren, gewinnt.

Austin Henley
quelle
@MathieuRodic: Sie gehen davon aus, dass das Programm Token ohne Wiederholung zeichnet.
user2357112 unterstützt Monica am
@ MathieuRodic: Lassen Sie mich umformulieren. Sie gehen davon aus, dass das Programm das Multiset seiner Token zufällig verschlüsselt, anstatt L-Token mit Wiederholung aus dem in seiner Quelle verwendeten Set von U-Token zu zeichnen.
user2357112 unterstützt Monica am
@ user2357112: Ich verstehe. Mein Fehler war es, dieses Problem als ein Unentschieden ohne Ersatz zu betrachten.
Mathieu Rodic
1
Regel 1 und 5 scheinen mir zu widersprechen.
Cruncher
4
Können Sie annehmen, dass eingebaute Zufallsfunktionen TRNGs sind? Typische Implementierungen haben zu kleine Seeds, um alle Ausgaben zu erzeugen, und sind daher möglicherweise nicht in der Lage, sich selbst zu regenerieren.
CodesInChaos

Antworten:

11

Python 2, 3 ^ -3 = 0,037

execMissbrauch ist sehr praktisch, um die Anzahl der Token zu verringern. Jetzt aktualisiert, um die Quelldatei nicht zu lesen!

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),
"""

Das Extra ''zwischen execund der riesigen dreifach zitierten Zeichenfolge besteht nur darin, die Tokenanzahl auf das erforderliche Minimum von 3 aufzufüllen. Sie wird aufgrund der impliziten String-Literal-Verkettung in die zweite Zeichenfolge eingebunden.

Ursprüngliche Version der Quelldatei:

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),
'''

Genau genommen platziert die Python-Grammatik ein ENDMARKER-Token am Ende der Quelldatei, und wir können keine Quelldatei mit zufällig verteilten ENDMARKERs erstellen. Wir geben vor, dass es nicht existiert.

user2357112 unterstützt Monica
quelle
@Cruncher Das ist die Wahrscheinlichkeit. 3 ^ -3 == 1/3 ^ 3
Austin Henley
2
+1 für brillanten Hack der Regeln. Die gleiche Idee in J umgesetzt: ".]';(?3 3 3){]`".;~({:,],{:,],6#{:)'';(?3 3 3){]`".;~({:,],{:,],6#{:)'''''''.
Algorithmushai
5

Javascript, 102 Token, 33 einzigartig, 7,73 × 10 -154

Beachten Sie, dass dies eine echte Quine ist. Es liest die Datei nicht oder verwendet evaloderFunction.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)
Aebabis
quelle
4

Python: P (Erzeugungsprogramm in 1 Versuch) = 3,0317 * 10 ^ -123

34 einzigartige Token, 80 Token insgesamt. Beachten Sie, dass am Ende jeder Zeile ein Leerzeichen steht.

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 

Beispielausgabe:

' ' 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 

Vielen Dank an die andere Python-Lösung von user2357112, die mich daran erinnert hat, das letzte Token zu verwerfen und es zu verwenden, von __file__dem ich vorher nichts wusste .

Kaya
quelle
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 hat eine Menge nützlicher kleiner Werkzeuge, um diese Art von Arbeit zu erledigen.

  • Zuallererst ist jede durch Leerzeichen getrennte Folge von Zahlen ein Token . Es bedeutet ein eindimensionales Array dieser Zahlen. So funktioniert Js Lexer. Das sind übrigens siebzehn 11, wenn jemand neugierig ist.

  • (,,,{:,{:)'QUINE'''ist ein in J gebräuchlicher Quine-Trick, bei dem so wenig Token wie möglich verwendet werden: {:bedeutet " Tail" , also hängt er die Zeichenfolge an sich selbst an und fügt am Ende zwei Kopien des letzten Zeichens hinzu. Da das letzte Zeichen ein einfaches Anführungszeichen ist (J verwendet Strings im Pascal-Stil), lautet das Ergebnis QUINE'QUINE'''.

  • ;:ist ein Tokenizer, der eine Eingabezeichenfolge wie J-Code aufteilt und eine Liste von Feldern zurückgibt. Die Länge dieses Ergebnisses beträgt 17.

  • ~.Nimmt alle eindeutigen Elemente dieses Arrays. Die Länge dieses Ergebnisses beträgt 11.

  • ?heißt Roll . Für jede Ganzzahl in ihrem Argument wird eine positive Zufallszahl größer oder gleich Null ausgewählt, die kleiner als diese Zahl ist. Hier generiert J also 17 Zahlen von 0 bis einschließlich 10.

  • { Verwendet die Zufallsindizes, um Elemente aus unserer Liste der Unique-Token-In-Boxen auszuwählen.

  • ; öffnet alle diese Felder und führt das Ergebnis zusammen aus.

Es folgen einige Beispiele. Die eingerückten Zeilen sind die Eingabeaufforderungen, und die linksbündigen Zeilen sind die Ausgabe des Interpreters.

   ;(?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{:{;(;:{:,~.
algorithmshark
quelle
2

Nachsatz

Dies war ein Spaß

/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

Es gibt 17 einzigartige Token und insgesamt 54 Token für eine Chance von ca. 1 zu 3.6e-67.

Geoff Reedy
quelle
2

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

Dies ist ein Whitespace-Programm, das, wenn es mit zufälligen Zeichen besetzt ist, eine 1: 3 ^ 132-Chance hat, sich selbst zu reproduzieren (3 verschiedene Token, 132-mal wiederholt). Es muss beim Ausführen mit mindestens 132 zufälligen Zeichen gesetzt werden (Whitespace hat keine eingebaute Zufalls- oder Datumsfunktion zum Setzen), z some_whitespace_interpreter my_quine.ws <some_random_source >quine_output.ws. Die Punktzahl würde sich verbessern, wenn das Programm nicht mehr golfen könnte, aber dies ist mein erstes "echtes" Whitespace-Programm, also lasse ich es einfach bei meiner mageren Menge an Golf.

Einfacher Whitespace-Code, oder sehen Sie , wie er ausgeführt wird : (Klicken Sie zum Ausprobieren auf "Bearbeiten", kopieren Sie das Material in die <pre> -Tags; sollte 132 Zeichen mit Unix-EOL enthalten)

    

























Mit what befehl annotierter Code ist what (technisch gesehen kein Quine, da er die Kommentare nicht reproduziert):

stack push_number + 0 end
stack push_number + 1 0 0 1 end
Heap Store Stack Push_Number + 1 Ende
stack push_number + 1 0 0 0 0 0 end
Heap-Speicherstapel push_number + 1 0 end
stack push_number + 1 0 1 0 end
Heap-Speicherstapel push_number + 1 0 0 0 0 0 1 1 end
fließen
make_label loop_begin  
stack push_number + 1 1 end
IO  
Zeichenstapel lesen push_number + 1 1 end
Heap-Abrufstapel push_number + 1 1 end
arithmetisches Modulo-Heap-Abrufen von E / A  
print char stack push_number + 1 end
Arithmetik subtrahieren Stapel duplizieren
 fließen
jump_if_zero end_prog
fließen
springen zu 
loop_begin  
fließen
make_label end_prog
fließen
end_program

Wenn der Startwert gerade äquivalent ist (die Zeichen werden in Mod 3 umgewandelt, um in die Token umgewandelt zu werden), ist dies erfolgreich:

CCCCACCCBCCBABBCCCCBACCCBCCCCCABBCCCCBCACCCBCBCABBCCCCBCCCCCBBAACCBACCCBBABCCBBABBBCCCBBABCBBBBBBACCCCBAAAA

Es ist ein ziemlich einfaches Programm, das ungefähr diesem Ruby-Programm entspricht:

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

Perl, 27 Token, P = 1,4779 × 10 –34

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

Letzte Änderung: Verwenden Sie diese @ARGV=$0Option open*ARGV,$0, um ein Token zu speichern.

  • 15 einzigartige Spielsteine
  • 4 - Token erscheinen 2mal ( =, /, @, $)
  • 1 Token erscheint 4 mal ( W)

Ich denke also, dass die Wahrscheinlichkeit (pow (2,2 * 4) * pow (4,4)) / pow (27,27) ungefähr 1,48E-34 beträgt.

Wenn sich der Quellcode in einer Datei mit dem Namen befindet ARGV, können Sie diese 26-Token-Lösung mit P = ~ 2.193 x 10 -31 verwenden :

@ARGV=ARGV;print$ARGV[rand@ARGV]for@ARGV=split/(\W)/,readline
Mob
quelle
Eigentlich, P = (4 * 2! + 4!) / 27!das ist ungefähr 1.7632684538487448 x 10 ^ -26
Mathieu Rodic
0

1330.037037...

(Ich weiß, das ist kein Code-Golf, aber ...)

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

Probieren Sie es online!

Ähnlich wie bei der Python-Antwort, bei der das erste Token ein ausgewertetes Zeichenfolgenliteral ist. Die Token sind

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

Erläuterung:

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
Scherzen
quelle