La quine aleatoria


15

Escriba un programa que sea capaz de generarse al azar.

Debe hacer esto en función de los tokens utilizados en su código fuente. Si el código fuente de su programa está compuesto por 50 tokens únicos y tiene 60 tokens de largo, entonces el programa debería generar 60 tokens donde cada token se elige aleatoriamente de uno de los 50 tokens únicos.

Por ejemplo, este programa tendría una posibilidad entre 50 y 60 para reproducirse.

¿Qué es un token? Eso depende del idioma. Por ejemplo, los identificadores ( foo_bar), las palabras clave ( while) y los números ( 42) contarían como tokens en la mayoría de los idiomas. Los espacios en blanco no contarían en la mayoría de los idiomas.

Reglas adicionales:

  • La salida solo puede contener tokens encontrados en el código fuente de los programas, separados por el delimitador apropiado
  • La salida debe tener la misma longitud que el código fuente del programa, contada por tokens
  • Solo se puede usar un lenguaje de programación
  • El código fuente debe tener al menos 3 tokens únicos
  • Excluir comentarios del código fuente
  • El programa solo debe tener una oportunidad de U ^ L para reproducirse

Puntuación: el programa que tiene la mejor oportunidad de reproducirse, gana.


@MathieuRodic: Asumes que el programa dibuja tokens sin repetición.
user2357112 es compatible con Monica

@MathieuRodic: Déjame reformular. Supone que el programa codifica aleatoriamente el conjunto múltiple de sus tokens, en lugar de dibujar tokens L con repetición del conjunto de tokens U utilizados en su fuente.
user2357112 es compatible con Monica

@ user2357112: Ya veo. Mi error fue considerar este problema como un empate sin reemplazo.
Mathieu Rodic

1
Las reglas 1 y 5 parecen estar en contradicción conmigo.
Cruncher

44
¿Se puede suponer que las funciones aleatorias integradas son TRNG? Las implementaciones típicas tienen semillas demasiado pequeñas para producir todos los resultados y, por lo tanto, podrían no poder regenerarse realmente.
CodesInChaos

Respuestas:


11

Python 2, 3 ^ -3 = 0.037

execEl abuso es bastante útil para reducir el recuento de fichas. ¡Ahora actualizado para no leer el archivo fuente!

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

El extra ''entre execy la cadena gigante entre comillas triples es solo para rellenar el recuento de tokens al mínimo requerido de 3. Se fusiona en la segunda cadena debido a la concatenación literal de cadena implícita.

Versión original de apertura del archivo fuente:

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

Estrictamente hablando, la gramática de Python coloca un token ENDMARKER al final del archivo fuente, y no podemos producir un archivo fuente con ENDMARKER esparcidos al azar. Fingimos que no existe.


@Cruncher Esa es la probabilidad. 3 ^ -3 == 1/3 ^ 3
Austin Henley

2
+1 por truco brillante de las reglas. La misma idea se aplica en J: ".]';(?3 3 3){]`".;~({:,],{:,],6#{:)'';(?3 3 3){]`".;~({:,],{:,],6#{:)'''''''.
algormshark

5

Javascript, 102 tokens, 33 únicos, 7.73 × 10-154

Tenga en cuenta que esta es una verdadera quine. No lee el archivo ni 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 (programa generador en 1 prueba) = 3.0317 * 10 ^ -123

34 fichas únicas, 80 fichas en total. Tenga en cuenta que hay un espacio al final de cada línea.

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 

Salida de muestra:

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

Gracias a la otra solución de Python de user2357112 por recordarme que descarte el último token y use el __file__que anteriormente ignoraba.


3

J - 1 en 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 tiene un montón de pequeñas herramientas útiles para hacer este tipo de trabajos.

  • En primer lugar, cualquier cadena de números separada por espacios es una ficha . Significa una matriz unidimensional de esos números. Así es como funciona el lexer de J. Por cierto, son diecisiete 11, si alguien tiene curiosidad.

  • (,,,{:,{:)'QUINE'''es un truco de quine común en J, hecho para usar la menor cantidad posible de tokens: {:significa Cola , por lo que agrega la cadena a sí mismo y luego agrega dos copias del último carácter al final de eso. Como el último carácter es una comilla simple (J usa cadenas de estilo Pascal), el resultado es QUINE'QUINE'''.

  • ;:es un tokenizador, y divide una cadena de entrada como si fuera un código J, devolviendo una lista de cuadros. La longitud de este resultado es 17.

  • ~.toma todos los elementos únicos de esta matriz. La longitud de este resultado es 11.

  • ?se llama Roll . Para cada entero en su argumento, selecciona un número positivo aleatorio mayor o igual a cero, menor que ese número. Entonces aquí J generará 17 números del 0 al 10 inclusive.

  • { usa los índices aleatorios para seleccionar elementos de nuestra lista de fichas únicas en cajas.

  • ; abre todos estos cuadros y ejecuta el resultado juntos.

Algunos ejemplos siguen. Las líneas sangradas son las indicaciones de entrada, y las líneas alineadas con el lado izquierdo son la salida del intérprete.

   ;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''
~.~.(?;;:11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''(){11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){(;:;
   ;(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)'''
{';(?11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11){~.;:(,,,{:,{:)''',?{:;:{:';(?11 11 11 11 11 11 11 11 11 11 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

Posdata

Esto fue divertido

/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

Hay 17 tokens únicos y 54 tokens en total para aproximadamente 1 en 3.6e-67 de probabilidad.


2

Espacio en blanco , 3 ^ -205 3 ^ -189 3 ^ -181 3 ^ -132 ~ = 10 ^ -63

Este es un programa de espacios en blanco que, cuando se siembra con caracteres aleatorios, tiene una probabilidad de 1 en 3 ^ 132 de reproducirse (3 fichas distintas, repetidas 132 veces). Se debe sembrar con al menos 132 caracteres aleatorios cuando se ejecuta, (Whitespace no tiene una función aleatoria o de fecha incorporada para inicializar), por ejemplo some_whitespace_interpreter my_quine.ws <some_random_source >quine_output.ws. El puntaje mejoraría si el programa pudiera seguir jugando golf, pero este es mi primer programa de espacio en blanco "real", así que lo dejaré con mi escasa cantidad de golf.

Código de espacio en blanco simple, o vea cómo se ejecuta : (para probarlo, haga clic en "editar", copie el contenido dentro de las etiquetas <pre>; debe tener 132 caracteres con EOL de estilo Unix)

    

























Código anotado con qué comando es qué (no técnicamente una quine, ya que no reproducirá los comentarios):

stack push_number + 0 end
stack push_number + 1 0 0 1 end
pila de la tienda de almacenamiento dinámico número_punto + 1 final
stack push_number + 1 0 0 0 0 0 end
pila de la tienda de almacenamiento dinámico número_ empuje + 1 0 final
stack push_number + 1 0 1 0 end
pila de la tienda de almacenamiento dinámico número_ empuje + 1 0 0 0 0 0 1 1 final
fluir
make_label loop_begin  
stack push_number + 1 1 end
IO  
leer la pila de caracteres push_number + 1 1 end
montón de recuperación de pila push_number + 1 1 end
módulo aritmético montón recuperar IO  
imprimir pila de caracteres número_ empuje + 1 final
pila aritmética restar duplicado
 fluir
jump_if_zero end_prog
fluir
Salta a 
loop_begin  
fluir
make_label end_prog
fluir
programa_final

Si la semilla resulta ser equivalente (los personajes se toman mod 3 para convertirlos en tokens) a esto, tendrá éxito:

CCCCACCCBCCBABBCCCCBACCCBCCCCCABBCCCCBCACCCBCBCABBCCCCBCCCCCBBAACCBACCCBBABABCCCCBBABBBCCCBBABCBBBBBBACCCCCBABCCBCACABBAACABAACCAAAA

Es un programa bastante simple, más o menos equivalente a este programa Ruby:

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

1

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

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

Última edición: use en @ARGV=$0lugar de open*ARGV,$0guardar un token.

  • 15 fichas únicas
  • Aparecen 4 fichas de 2 veces ( =, /, @, $)
  • 1 ficha aparece 4 veces ( W)

Así que creo que eso hace que la probabilidad (pow (2,2 * 4) * pow (4,4)) / pow (27,27), aproximadamente 1.48E-34.

Si el código fuente está en un archivo llamado ARGV, puede usar esta solución de 26 tokens con P = ~ 2.193 x 10 -31 :

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

En realidad, P = (4 * 2! + 4!) / 27!que es alrededor de 1.7632684538487448 x 10 ^ -26
Mathieu Rodic

0

1330,037037 ...

(Sé que esto no es código golf, pero ...)

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

Pruébalo en línea!

Al igual que la respuesta de Python, donde el primer token es un literal de cadena que se evalúa. Las fichas son

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

Explicación:

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.