El juego principal de Conway

18

Específicamente, el PRIMEGAME de Conway .

Este es un algoritmo ideado por John H. Conway para generar números primos usando una secuencia de 14 números racionales:

 A   B   C   D   E   F   G   H   I   J   K   L   M   N
17  78  19  23  29  77  95  77   1  11  13  15  15  55
--  --  --  --  --  --  --  --  --  --  --  --  --  --
91  85  51  38  33  29  23  19  17  13  11  14   2   1

Por ejemplo, F es la fracción 77/29.

Así es como el algoritmo encuentra los números primos. Comenzando con el número 2, encuentre la primera entrada en la secuencia que, cuando se multiplica, produce un número entero. Aquí es M, 15/2que produce 15. Luego, para ese número entero 15, encuentre la primera entrada en la secuencia que cuando se multiplica produce un número entero. Ese es el último N, o 55/1, que rinde 825. Escribe la secuencia correspondiente. (El astuto entre ustedes puede reconocer esto como un programa FRACTRAN ).

Después de algunas iteraciones, obtendrá lo siguiente:

2, 15, 825, 725, 1925, 2275, 425, 390, 330, 290, 770, 910, 170, 156, 132, 116, 308, 364, 68, 4 ...

Tenga en cuenta que el último elemento de la lista es 4, o 2^2. ¡Mira nuestro primer número primo (el 2exponente) generado con este algoritmo! Finalmente, la secuencia tendrá el siguiente aspecto:

2 ... 2^2 ... 2^3 ... 2^5 ... 2^7 ... etc.

Por lo tanto, arrojando los números primos. Este es OEIS A007542 .

El reto

Dado un número de entrada n, ya sea cero o uno indexado (su elección), puede generar los primeros nnúmeros de esta secuencia o generar el nnúmero th de esta secuencia.

Ejemplos

Los siguientes ejemplos muestran el ntérmino th de la secuencia indexada a cero.

 n   output
 5   2275
19   4
40   408

Reglas

  • Si corresponde, puede suponer que la entrada / salida se ajustará al tipo entero nativo de su idioma.
  • La entrada y salida se pueden dar por cualquier método conveniente .
  • Un programa completo o una función son aceptables. Si es una función, puede devolver el resultado en lugar de imprimirlo.
  • Las lagunas estándar están prohibidas.
  • Este es el por lo que se aplican todas las reglas habituales de golf, y gana el código más corto (en bytes).
AdmBorkBork
fuente
11
Quizás el juego principal de Conway sería un nombre más descriptivo para este desafío que Let's Play a Game . Eso facilitaría encontrar este desafío en el futuro.
Lynn el
¿La salida puede ser flotante? 408.0en lugar de 408por ejemplo.
dylnan
Desafortunadamente no tenemos el desafío (canónico) "Interpretar Fractran". El que está en Desbordamiento de pila está bloqueado.
usuario202729
@dylnan Claro, está bien.
AdmBorkBork

Respuestas:

5

Python 3 , 173 165 153 145 144 136 135 127 126 125 108 107 104 bytes

f=lambda n:2>>n*2or[f(n-1)*t//d for t,d in zip(b"NM_M\r7",b"[U3&!\r")if f(n-1)*t%d<1][0]

Pruébalo en línea!

  • -30 bytes gracias a Jonathan Frech!
  • -3 bytes gracias a Lynn!

2>>n*2es 2para n==0y de lo 0contrario.

103 bytes si podemos devolver flotantes.

dylnan
fuente
Usando Python 2; 153 bytes .
Jonathan Frech
@JonathanFrech Genial, buen truco. ¡Gracias!
dylnan
1
Alojarse en Python 3, 146 bytes !
Jonathan Frech
144 bytes .
Jonathan Frech el
Gracias de nuevo, ¡hiciste más que yo ahora!
dylnan
5

FRACTRAN , 99 bytes

17/2821 78/2635 19/1581 23/1178 29/1023 77/899 95/713 77/589 1/527 11/403 13/341 15/434 15/62 55/31

Pruébalo en línea!

El programa toma 2*31^ncomo entrada, que se utiliza como estado inicial.

Todas las fracciones en el programa FRACTRAN original se han dividido entre 31 (el primer registro principal no utilizado), por lo que el programa se detiene en la enésima iteración.

Vincent
fuente
Respuesta descarada. ;-)
AdmBorkBork
4

Jalea , 49 43 bytes

ד×NŒçøM_M¢¿ÆÐÐ7‘“[U3&!øçŒ×Æ¿Ç£¢‘:@xḍɗḢ
2Ç¡

Pruébalo en línea!

  • -6 bytes gracias a millas
dylnan
fuente
Lástima que 0ọ0¤es inf, de lo contrario podría haber reducido este a 42 bytes ...
Erik el Outgolfer
3

Python 3 , 107 bytes

f=lambda n,k=2:n and f(n-1,[k*a//b for a,b in zip(b"NM_M\r7",b"[U3&!\r")if k*a%b<1][0])or k

Pruébalo en línea!

Codifica la lista de fracciones zipincorporando dos cadenas de bytes que contienen caracteres ASCII bajos no imprimibles.

Si nes cero, devolvemos el argumento k; de lo contrario, recurrimos con nuevos parámetros. Nuestro nuevo kes el primer valor k*a//bcorrespondiente a alguna fracción (a, b)de la lista, de modo que k*a//bsea ​​un número entero, es decir k*a%b<1.

Lynn
fuente
2

MATL , 50 bytes

Hi:"'0m26<l~l *,..V'31-*'{uSFA=731-+."!'32-&\w~)1)

Pruébalo en línea!

Luis Mendo
fuente
3
Adivina qué partes del código son literales de cadena y cuáles son declaraciones reales ...
Luis Mendo
2
Hi:... aww, "Hola" a ti también, código. :-)
AdmBorkBork
2

J , 116 110 bytes

g=.3 :0
((1047856500267924709512946135x%&(96#.inv])5405040820893044303890643137x)([:({.@I.@(=<.){[)*)])^:y 2
)

Pruébalo en línea!

0 indexado; devuelve el enésimo número

Algunos bytes se pueden guardar haciendo que el verbo sea tácito, pero tengo problemas para que ^:funcione.

Explicación:

J describe los números racionales en la forma NrD, donde N es el numerador y D es el denominador, por ejemplo 17r91 78r85 19r51 23r38..., creé 2 listas separadas para los numeradores y denominadores e hice 2 números base-96 a partir de ellos.

1047856500267924709512946135x%&(96#.inv])5405040820893044303890643137x convierte los números de base 96 en listas y construye una lista de fracciones dividiendo las dos listas.

   1047856500267924709512946135x%&(96#.inv])5405040820893044303890643137x
17r91 78r85 19r51 23r38 29r33 77r29 95r23 77r19 1r17 11r13 13r11 15r14 15r2 55

2 comenzar con 2

^:yrepite el verbo a la izquierda n(y es el argumento de la función)

] el argumento correcto (comienza en 2 y luego usa el resultado de cada iteración)

* multiplicar la lista de fracciones por el argumento correcto

(=<.) son los resultados enteros (compare cada número con su piso)

{.@I.@encuentra el índice I.del primero {.de los enteros

{[ usa el índice para recuperar el número

Galen Ivanov
fuente
1
62 bytes:('0m26<l~l *,..V'%&(31x-~3&u:)'ztRE@<620,*-! ')&(0{*#~0=1|*)2:
millas
@miles Gracias, creo que debes publicar tu solución, es mucho mejor que la mía.
Galen Ivanov
2

05AB1E ,  44  43 bytes

0 indexado

2sF•Ë₁ǝßÌ?ƒ¥"h2ÔδD‡béαA5À>,•тв2ä`Š*s‰ʒθ_}нн

Pruébalo en línea!

Explicación

2                                             # initialize stack with 2
 sF                                           # input times do:
   •Ë₁ǝßÌ?ƒ¥"h2ÔδD‡béαA5À>,•                  # push a base-255 compressed large number
                            тв                # convert to a list of base-100 digits
                              2ä`             # split in 2 parts to stack
                                 Š            # move denominators to bottom of stack
                                  *           # multiply the last result by the numerators
                                   s‰         # divmod with denominators
                                     ʒθ_}     # filter, keep only those with mod result 0
                                         нн   # get the div result

El gran número empujado es 17781923297795770111131515559185513833292319171311140201

Emigna
fuente
1

Pari / GP , 121 bytes

n->a=2;for(i=1,n,a=[x|x<-a*[17/91,78/85,19/51,23/38,29/33,77/29,95/23,77/19,1/17,11/13,13/11,15/14,15/2,55],x\1==x][1]);a

Pruébalo en línea!

alephalpha
fuente
1

JavaScript (Node.js) , 106 95 bytes

  • gracias a @Arnauld y @Neil por reducir en 11 bytes
(n,N=2,I=13,B=Buffer(`[U3&!\rNM_M\r7`))=>n--?f(n,N/B.find(x=>N%x<!!++I)*B[I]):N

Pruébalo en línea!

DanielIndie
fuente
Logré exprimir un par de bytes pero no puedo evitar pensar que me falta algo: ¡ Pruébelo en línea!
Neil
1
@Neil No hay necesidad de usar el operador de propagación activado Buffer. Además, creo que es seguro poner todos los datos en un solo búfer: 95 bytes .
Arnauld
@Arnauld El OP utilizó el operador de propagación (no estoy familiarizado con Buffer, así que no conocía nada mejor), ¡pero ese es un gran movimiento con el único Buffer!
Neil
@Arnauld correcto, actualizado :)
DanielIndie
1

Retina , 213 bytes

K`17/91¶78/85¶19/51¶23/38¶29/33¶77/29¶95/23¶77/19¶1/17¶11/13¶13/11¶15/2¶1/7¶55/1¶17/91¶78/85¶19/51¶23/38¶29/33¶77/29¶95/23¶77/19¶1/17¶11/13¶13/11¶15/2¶1/7¶55/1¶2
\d+
*
"$+"+`((_+)/(_+)¶(.+¶)*)(\3)+$
$1$#5*$2
r`_\G

Pruébalo en línea! Explicación:

K`17/91¶78/85¶19/51¶23/38¶29/33¶77/29¶95/23¶77/19¶1/17¶11/13¶13/11¶15/2¶1/7¶55/1¶17/91¶78/85¶19/51¶23/38¶29/33¶77/29¶95/23¶77/19¶1/17¶11/13¶13/11¶15/2¶1/7¶55/1¶2

Reemplace la entrada con una lista de todas las fracciones, más el entero inicial.

\d+
*

Convierte todo a unario.

"$+"+`

Repita la sustitución la cantidad de veces dada por la entrada original.

((_+)/(_+)¶(.+¶)*)(\3)+$

Encuentre un denominador que divida uniformemente el número entero.

$1$#5*$2

Reemplace el entero con el resultado de la división multiplicada por el numerador.

r`_\G

Convierta el entero a decimal y genere el resultado.

Neil
fuente
1

Adjunto , 81 bytes

Nest<~{Find[Integral,_*&`//=>Chop[Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "-31,2]]},2~>

Pruébalo en línea! Produce una fracción sobre 1. Por ejemplo, la entrada 5devuelve 2275/1. Esto se puede solucionar con más 2 bytes al anteponer N@al programa.

Explicación

Esta es una función currificada, que curry Nest con dos argumentos predefinidos:

{Find[Integral,_*&`//=>Chop[Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "-31,2]]}

y 2. Este último argumento es simplemente la semilla inicial, y el argumento que se pasa a esta función es el número de iteraciones para anidar la función dada.

Lo siguiente se usa para codificar PRIMEGAME:

&`//=>Chop[Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "-31,2]]

Esto se evalúa como tal:

A> "0zmt2R6E<@l<~6l2 0*,,*.-.!V "
"0zmt2R6E<@l<~6l2 0*,,*.-.!V "
A> Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "
[48, 122, 109, 116, 50, 82, 54, 69, 60, 64, 108, 60, 126, 54, 108, 50, 32, 48, 42, 44, 44, 42, 46, 45, 46, 33, 86, 32]
A> Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "-31
[17, 91, 78, 85, 19, 51, 23, 38, 29, 33, 77, 29, 95, 23, 77, 19, 1, 17, 11, 13, 13, 11, 15, 14, 15, 2, 55, 1]
A> Chop[Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "-31,2]
 17 91
 78 85
 19 51
 23 38
 29 33
 77 29
 95 23
 77 19
  1 17
 11 13
 13 11
 15 14
 15  2
 55  1
A> &`//=>Chop[Ords!"0zmt2R6E<@l<~6l2 0*,,*.-.!V "-31,2]
[(17/91), (78/85), (19/51), (23/38), (29/33), (77/29), (95/23), (77/19), (1/17), (11/13), (13/11), (15/14), (15/2), (55/1)]

Reemplacemos esta expresión con Gen la explicación. Nuestra primera función se convierte en:

{Find[Integral,_*G]}

Esto realiza una única iteración del código FRACTRAN _, la entrada a la función. Es Findun Integralmiembro (uno que es un entero) de la matriz _*G, que es la entrada _multiplicada con cada miembro de G. Nestsimplemente aplica esta transformación el número dado de veces.

Adjunto, 42 bytes

Implementé partes de la $langsbiblioteca, inspirándome en este desafío, así que marco esta sección como no competitiva.

Needs[$langs]2&FRACTRAN_EXAMPLES.prime.run

Esto simplemente consulta la lista de FRACTRAN_EXAMPLESque tengo. Cada ejemplo es una FractranExampleinstancia, que llama a la FRACTRANfunción incorporada . El primeejemplo es el PRIMEGAME de Conway.

Conor O'Brien
fuente
1

F # (Mono) , 215 bytes

let q m=
 let rec i x y=
  if y=m then x 
  else[17;91;78;85;19;51;23;38;29;33;77;29;95;23;77;19;1;17;11;13;13;11;15;14;15;2;55;1]|>List.chunkBySize 2|>List.find(fun[n;d]->x*n%d=0)|>fun[n;d]->i(x*n/d)(y+1)   
 i 2 0

Pruébalo en línea!

Henrik Hansen
fuente
0

PHP, 183 bytes (189 con etiqueta "php")

Golfizado:

$t=2;for(;@$i++<$argv[1];){foreach([17/91,78/85,19/51,23/38,29/33,77/29,95/23,77/19,1/17,11/13,13/11,15/14,15/2,55/1]as$n){$a=$t*$n;if(preg_match('/^\d+$/',$a)){$t=$a;break;}}}echo$t;

Sin golf:

<?php 
$t=2;
for(;@$i++<$argv[1];){
    foreach([17/91,78/85,19/51,23/38,29/33,77/29,95/23,77/19,1/17,11/13,13/11,15/14,15/2,55/1] as $n){
        $a=$t*$n;
        if(preg_match('/^\d+$/',$a)){
            $t=$a;break;
        }
    }
}
echo $t;

Pruébalo en línea!

Boian Ivanov
fuente