El período más largo iterando quine

10

Como sabemos, un quine es un programa que genera su propio código fuente. Sin embargo, también es posible escribir un programa que genere otro programa diferente que emita el primer programa nuevamente. Por ejemplo, el programa Python 2

x = '''x = {}
print 'print '+'"'*3+x.format("'"*3+x+"'"*3)+'"'*3'''
print 'print '+'"'*3+x.format("'"*3+x+"'"*3)+'"'*3

Cuando se ejecute, mostrará el siguiente texto:

print """x = '''x = {}
print 'print '+'"'*3+x.format("'"*3+x+"'"*3)+'"'*3'''
print 'print '+'"'*3+x.format("'"*3+x+"'"*3)+'"'*3"""

Cuando se ejecuta como un programa Python, esto generará el código original nuevamente. Esto se llama una quine iterativa . Como debe ejecutarlo dos veces para recuperar el código original, decimos que tiene el período 2 . Pero, por supuesto, son posibles períodos mucho más altos.

Su desafío es escribir un quine iterativo con el mayor tiempo posible, en 100 bytes o menos , en el idioma que elija. (Tenga en cuenta que mi ejemplo anterior no se ajusta a esta especificación, ya que son 119 bytes, incluida la nueva línea final).

Tenga en cuenta las siguientes reglas y aclaraciones:

  • Se aplican las reglas habituales de quine, es decir, su programa no puede usar funciones de lenguaje que le permitan acceder directamente a su propio código fuente.
  • Las salidas iteradas finalmente tienen que volver a su código original, y debe incluir una demostración o prueba de que lo hará.
  • También debe incluir una explicación de por qué el ciclo es tan largo como usted lo dice. Esto no tiene que estar al nivel de una prueba matemática, pero debería ser convincente para alguien familiarizado con su idioma. (Esta regla está aquí porque espero que algunas de las respuestas involucren números muy, muy grandes).
  • Está bien decir algo así como "al menos 1,000,000 de iteraciones" en lugar de dar el número exacto, siempre y cuando pueda probar que es al menos ese tiempo. En este caso, su puntaje sería de 1,000,000. De lo contrario, su puntaje es el período de su quine.
  • El límite de 100 bytes solo se aplica a su programa inicial: los programas que genera pueden ser más largos, aunque, por supuesto, eventualmente tendrán que volver a bajar a 100 bytes para generar su código original.
  • Puede suponer que su máquina tiene RAM infinita y tiempo de ejecución infinito, pero no puede asumir tipos de datos de precisión ilimitados (como enteros) si su idioma no los tiene. Usted puede asumir que no hay límite a la longitud de la entrada de su analizador puede manejar.
  • El puntaje más alto gana.

Tenga en cuenta: hay un desafío existente llamado Quit Whining; Comience Quining que también implica iterar quines. Sin embargo, aparte de basarse en el mismo concepto, estos son tipos de desafíos completamente diferentes. El otro es el golf de código directo, mientras que este es (¡intencionalmente!) Realmente un problema de castor ocupado disfrazado. Es probable que las técnicas necesarias para producir una buena respuesta a esta pregunta sean muy diferentes de las que se necesitan para responder a la otra pregunta, y esto es muy similar al diseño.

Nathaniel
fuente
1
@LeakyNun No sé si fue usted o un mod que eliminó su respuesta, pero tal vez si le explique lo que está mal, comprenderá por qué esto no es un duplicado. Esta pregunta especifica un límite de 100 bytes en la longitud de la fuente, por lo que en realidad no puede ir "tan alto como desee" utilizando ese método. Ese es el punto central de esta pregunta. Para responderlo, lo que tendría que hacer es publicar la versión más larga que se ajuste a 100 caracteres y decir cuál es su período. Lo que publicaste sería un buen primer intento, pero es muy poco probable que sea el ganador.
Nathaniel
1
@Dave el desafío consiste precisamente en especificar un gran número en un pequeño número de bytes, sí. Ese es todo el principio alrededor del cual fue diseñado. La pregunta es, ¿es 3 ^^^ 3 el número más alto que puede especificar en 100 bytes en su idioma, o hay uno más grande? De eso se trata este desafío. Es el núcleo de esto. Es lo que quería ver hacer a la gente. Es súper, muy frustrante tenerlo cerrado basado en una semejanza superficial a un desafío que no tiene nada de esta estructura.
Nathaniel
1
@Dave (segundo comentario) pero si eres inteligente, no necesitas estar limitado por la precisión de la máquina. Esperaría que las respuestas competitivas tuvieran un período mucho más largo que 2 ^ (2 ^ 64).
Nathaniel
3
Entonces, ¿preferiría que se cerrara como un duplicado de codegolf.stackexchange.com/q/18028/194 ?
Peter Taylor
1
@PeterTaylor es un tema mucho más cercano, pero sigue siendo un desafío muy diferente: imprimir un número es bastante diferente de hacer algo muchas veces. Por supuesto, preferiría que no se cerrara en absoluto.
Nathaniel

Respuestas:

10

PHP, período 2,100,000,000

¿Quién hubiera pensado que esto es posible en PHP? :-)

Esta es realmente mi primera quine y tiene 99 bytes de longitud

<?$i=1;$i*=21e8>$i;printf($a='<?$i=%d;$i*=21e8>$i;printf($a=%c%s%c,++$i,39,$a,39);',++$i,39,$a,39);

Aunque PHP admite números más grandes que 2 * 10^8al cambiar de integera double, el incremento ya no funciona (conduce a un bucle infinito) y no he encontrado otra solución que se ajuste a los 100 bytes. Todavía.

La prueba es bastante simple, ya que solo cuenta en cada iteración hasta que alcanza el punto de reinicio en 2,1 mil millones.

Créditos para Dave , que publicó el enfoque en pseudocódigo en los comentarios y para Bob Twells , de quien copié el código por una cantidad mínima de PHP.

Programa de prueba (sloooooow):

<?php
$o = file_get_contents('quine.php');
for ($i = 0; $i < 22e8; $i++) {
    if ($i%2==0) exec('php q > p'); else exec('php p > q');
    $a = file_get_contents(($i%2==0) ? 'p' : 'q');
    echo "\r" . str_pad($i,6,' ') . ":\t$a";
    if ($a == $o) {
        die;
    }
}

Bueno, al menos soy el primero en responder.

YetiCGN
fuente
1
Nota al margen: Esto es del orden de ~ 10 ^ 9.322219295.
LegionMammal978
8

Mathematica, período E8.5678 # 3 E2.1923 # 4 ~ E6.2695 # 3 # 2

Print[ToString[#0, InputForm], "[", #1 - 1 /. 0 -> "Nest[#!,9,9^9^99!]", "]"] & [Nest[#!,9,9^9^99!]]

Tenga en cuenta que las puntuaciones se describen en notación Hyper-E . Las iteraciones reemplazan el final Nest[#!,9,9^9^99!]con las expansiones decimales de Nest[#!,9,9^9^99!]- 1, Nest[#!,9,9^9^99!]- 2, Nest[#!,9,9^9^99!]- 3, ..., 3, 2, 1 y de regreso a Nest[#!,9,9^9^99!].

LegionMammal978
fuente
¿No crecerían los factoriales más rápido?
Maltysen
1
No conozco Mathematica, pero ¿no es esto una violación de las reglas para un quine: leer su propio código fuente? ToString[#0, InputForm]
daniero
entonces, solo 9 !!!! no funciona idk porque yo no tengo mi Mathica Rpi conmigo en este momento.
Maltysen
¡@Maltysen que calcula el doble factorial del doble factorial de nueve, o (9 !!) !! ≈ 2.116870635 · 10¹²⁰²
LegionMammal978
@daniero quiero decir, la idea es similar a una CJam estándar {"_~"}_~, así que supongo que debería ser válida ...
LegionMammal978
5

R, período aleatorio con expectativa 2 ^ 19936-0.5

f=function(){
    options(scipen=50)
    body(f)[[4]]<<-sum(runif(623))
    0
    cat("f=")
    print(f)
}

El generador de números aleatorios predeterminado de R tiene un período de 2 ^ 19937-1 y equidistribución en 623 dimensiones consecutivas. Por lo tanto, en algún lugar (pero solo una vez) en su período habrá un vector de ceros de 623 de largo. Cuando lleguemos allí (y estemos alineados con el inicio de la secuencia) la suma de los siguientes 623 números aleatorios de U [0,1] será cero y volveremos a nuestro programa original.

Tenga en cuenta que el programa con muy alta probabilidad pasará por el mismo estado distinto de cero varias veces antes de volver a cero. Por ejemplo, la suma 311.5 es la más probable, y hay muchas maneras en que puede suceder, pero el RNG permite que el período de 0 sea más largo que el período de 311.5.

JDL
fuente
No estoy seguro de a qué puntaje desea asignar esta entrada: P
JDL
1
Según las reglas: "Está bien decir algo como" al menos 1,000,000 de iteraciones "en lugar de dar el número exacto" Entonces, en mi opinión, es "al menos 1 iteración" porque si tenemos mucha suerte en el primer intento ...;)
YetiCGN
A diferencia de muchas lagunas estándar como "podría generar alguna entrada aleatoria, la respuesta está ahí", esta es una prueba realmente clara de que la respuesta precisa está destinada a ocurrir, y se da una muy buena estimación. ¡Agradable!
Andreï Kostyrka
1
Una vez que el programa regrese a su estado base una vez, tendrá un período no aleatorio de exactamente 2 ^ 19937-1.
JDL
El resultado de esto no coincide con el programa real (falta un poco de espacio en blanco). Además, el estado no se conservará entre las llamadas del programa, por lo que el período no será un número exacto ni será coherente
Jo King
1

JavaScript, período 9,007,199,254,700,000

No voy a ganar, pero fue divertido trabajar con JavaScript en este desafío:

a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),1-1||90071992547e5)

Sigue el siguiente ciclo:

a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),1-1||90071992547e5)
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),9007199254700000-1||90071992547e5)
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),9007199254699999-1||90071992547e5)
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),9007199254699998-1||90071992547e5)
// etc...
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),3-1||90071992547e5)
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),2-1||90071992547e5)
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),1-1||90071992547e5)
a="a=%s;console.log(a,uneval(a),%.0f-1||90071992547e5)";console.log(a,uneval(a),9007199254700000-1||90071992547e5)
// and so on

Nota: Puede hacerlo 18 bytes más corto, mientras solo elimina solo ~ 0.08% de la puntuación, así:

a="a=%s;console.log(a,uneval(a),%.0f-1||9e15)";console.log(a,uneval(a),1-1||9e15)
ETHproducciones
fuente
1

C, período 2,100,000,000

unsigned long long i;main(a){i=1;i*=21e8>i;printf(a="ungisned long long i;main(a){i=%d;i*=21e8>i;printf(a=%c%s%2$c,++i,34,a);}",++i,34,a);}

Basado en la respuesta PHP (obviamente). Se actualizará con una explicación cuando tenga tiempo.

MD XF
fuente
1

C (gcc) , 66 bytes, período 2 ^ 64

f(s){printf(s="f(s){printf(s=%c%s%1$c,34,s,%lu+1L);}",34,s,0+1L);}

Pruébalo en línea!

2 ^ 64 números están disponibles en un unsigned longentero. Por lo tanto, un período de 2 ^ 64.

SS Anne
fuente
1

Python 2

9((99↑↑(9((99↑↑(9((99↑↑(9↑↑51))9)1))9)1))9)+1

99(99↑↑12)+1

b=0;s="print'b=%d;s=%r;exec s'%(-~b%eval('9**9'*eval('9**9'*eval('9**9'*9**9**9**9**9))),s)";exec s

Pruébalo en línea!

En el código, los b=0cambios a b=1continuación, b=2etc., hasta que llegue, b=decimal expansion of the periodse restablecen ab=0

Mukundan
fuente
1
9**9**9**9**9**9**9**9**9**9**9**9**9**9**9**9**9**9es mucho mayor que 9**9**99**99**99**99**99**99**99**99**99**99**99**99. Dicho esto, podrías hacer algo así eval('9**9'*eval('9**9'*eval('9**9'*9**9**9**9**9)))por MUCHO más números altos.
Bubbler
¿Qué significa peroide?
SS Anne
@SSAnne está escrito en la notación de flecha hacia arriba de Knuth
Mukundan
1
@Mukundan Creo que puede querer decir punto, pero no estoy seguro. Entiendo lo que es la tetración.
SS Anne
@SSAnne lo siento, fue un error tipográfico, gracias por señalarlo
Mukundan
0

Gol> <> , 70 bytes, periodo 325883196621297064957600206175719056476804879488288708188003274919860959534770101079512433396348062803055739640225395758790852315876868469390603793729639715908136196505908165227136154287969475839017544811926036808089596209081885772040898530121921794489026069641113281250

Otro sabio conocido como realmente grande (3.25E270)

":1=l8:*6+=S&Q~:'~'=Q~~'H#'||lPffXfX=?1:1=Q$~$~|:1)lPffXfX(Q?:|r2ssH##

Esta es en realidad una versión alterada de la respuesta que puse en el iterador de 500 bytes

":1=l8:*6+=S&Q~:'~'=Q~~'H#'||//if last is equal to 1 and length is 71, delete the delete char, if the last char is '~', delete and push 'H#', which will later return to 'H##', completing the cycle!
lPffXfX=?1:1=Q$~$~|          //if length is equal to 15^15^15, then start delete process(append ascii one)
:1)lPffXfX(Q?:|              //if the last character is not 1 (the delete checker), and length is less than 15^15^15, duplicate the last value and append
r2ssH##                      //push the " to the front and output the whole thing

Espero haber acertado, y no hay errores. No hay una forma real de realmente calcular este valor, es teórica. Pero hombre, ese es un gran número !!!

Pruébalo en línea!

KrystosEl Señor Supremo
fuente