Jogo Principal de Conway

18

Especificamente, o PRIMEGAME de Conway .

Este é um algoritmo desenvolvido por John H. Conway para gerar números primos usando uma sequência de 14 números racionais:

 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 exemplo, F é a fração 77/29.

Então, aqui está como o algoritmo encontra os números primos. Começando com o número 2, encontre a primeira entrada na sequência que, quando multiplicadas juntas, produz um número inteiro. Aqui é M, 15/2que produz 15. Em seguida, para esse número inteiro 15, encontre a primeira entrada na sequência que, quando multiplicada, produz um número inteiro. Esse é o último N, ou 55/1, que produz 825. Anote a sequência correspondente. (Os astutos entre vocês podem reconhecer isso como um programa FRACTRAN .)

Após algumas iterações, você obterá o seguinte:

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

Observe que o último item listado é 4, ou 2^2. Veja nosso primeiro número primo (o 2expoente) gerado com este algoritmo! Eventualmente, a sequência terá a seguinte aparência:

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

Assim, produzindo os números primos. Este é o OEIS A007542 .

O desafio

Dado um número de entrada n, indexado com zero ou um (sua escolha), produz os primeiros nnúmeros dessa sequência ou o nth número dessa sequência.

Exemplos

Os exemplos abaixo estão exibindo o ntermo th da sequência indexada a zero.

 n   output
 5   2275
19   4
40   408

Regras

  • Se aplicável, você pode supor que a entrada / saída caiba no tipo Inteiro nativo do seu idioma.
  • A entrada e saída podem ser fornecidas por qualquer método conveniente .
  • Um programa completo ou uma função são aceitáveis. Se uma função, você pode retornar a saída em vez de imprimi-la.
  • As brechas padrão são proibidas.
  • Isso é portanto todas as regras usuais de golfe se aplicam e o código mais curto (em bytes) vence.
AdmBorkBork
fonte
11
Talvez o jogo principal de Conway seja um nome mais descritivo para esse desafio do que o Let's Play a Game . Isso tornaria mais fácil encontrar esse desafio no futuro.
19418 Lynn
A saída pode ser flutuante? 408.0em vez de 408por exemplo.
dylnan
Infelizmente, não temos o desafio (canônico) de "Interpretar Fractran". O do Stack Overflow está bloqueado.
usar o seguinte comando
@ Dylnan Claro, tudo bem.
AdmBorkBork

Respostas:

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]

Experimente online!

  • -30 bytes graças a Jonathan Frech!
  • -3 bytes graças a Lynn!

2>>n*2é 2para n==0e de 0outra forma.

103 bytes se pudermos retornar carros alegóricos.

dylnan
fonte
Usando Python 2; 153 bytes .
22618 Jonathan Frech
@JonathanFrech Legal, bom truque. Obrigado!
dylnan
1
Ficando em Python 3, 146 bytes !
22618 Jonathan Frech
144 bytes .
22618 Jonathan Frech
Mais uma vez obrigado, você fez mais do que eu fiz agora!
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

Experimente online!

O programa toma 2*31^ncomo uma entrada, que é usada como o estado inicial.

Todas as frações do programa FRACTRAN original foram divididas por 31 (o primeiro registro primário não utilizado), portanto, o programa para na enésima iteração.

Vincent
fonte
Resposta atrevida. ;-)
AdmBorkBork
4

Geléia , 49 43 bytes

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

Experimente online!

  • -6 bytes graças a milhas
dylnan
fonte
Pena que 0ọ0¤é inf, caso contrário você poderia ter reduzido este a 42 bytes ...
Erik as 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

Experimente online!

Codifica a lista de frações zipinserindo duas cadeias de caracteres contendo caracteres imprimíveis de baixo ASCII.

Se nfor zero, retornamos o argumento k; caso contrário, recorremos a novos parâmetros. Nosso novo ké o primeiro valor k*a//bcorrespondente a alguma fração (a, b)da lista, que k*a//bé um número inteiro, ou seja k*a%b<1.

Lynn
fonte
2

MATL , 50 bytes

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

Experimente online!

Luis Mendo
fonte
3
Acho que partes do código são strings literais e que são declarações reais ...
Luis Mendo
2
Hi:... aww, "Olá" para você também, código. :-)
AdmBorkBork
2

J , 116 110 bytes

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

Experimente online!

Indexado a 0; retorna o n-ésimo número

Alguns bytes podem ser salvos tornando o verbo tácito, mas tenho problemas para ^: trabalho.

Explicação:

J descreve os números racionais na forma NrD, onde N é o numerador e D é o denominador, por exemplo 17r91 78r85 19r51 23r38..., criei 2 listas separadas para os numeradores e denominadores e fiz 2 números base-96 a partir deles.

1047856500267924709512946135x%&(96#.inv])5405040820893044303890643137x converte os números da base-96 em listas e constrói uma lista de frações dividindo as duas listas.

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

2 comece com 2

^:yrepita o verbo no ntempo esquerdo (y é o argumento da função)

] o argumento correto (começa em 2 e depois usa o resultado de cada iteração)

* multiplique a lista de frações pelo argumento correto

(=<.) são os resultados inteiros (compare cada número com seu piso)

{.@I.@localiza o índice I.do primeiro {.dos inteiros

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

Galen Ivanov
fonte
1
62 bytes:('0m26<l~l *,..V'%&(31x-~3&u:)'ztRE@<620,*-! ')&(0{*#~0=1|*)2:
milhas
@ milhas Obrigado, acho que você deve postar sua solução, é muito melhor que a minha.
Galen Ivanov
2

05AB1E ,  44  43 bytes

Indexado a 0

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

Experimente online!

Explicação

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

O grande número pressionado é 17781923297795770111131515559185513833292319171311140201

Emigna
fonte
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

Experimente online!

alefalpha
fonte
1

JavaScript (Node.js) , 106 95 bytes

  • graças a @Arnauld e @Neil por reduzir em 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

Experimente online!

DanielIndie
fonte
Consegui espremer alguns bytes, mas não consigo deixar de pensar que estou perdendo alguma coisa: Experimente online!
194 Neil
1
@ Neil Não há necessidade de usar o operador de propagação Buffer. Além disso, acho seguro colocar todos os dados em um único buffer: 95 bytes .
Arnauld
@Arnauld O OP usou o operador de spread (não estou familiarizado com o Buffer, então não conhecia melhor), mas essa é uma ótima jogada com o único Buffer!
194 Neil
@Arnauld correto, atualizado :)
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

Experimente online! Explicação:

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

Substitua a entrada por uma lista de todas as frações, mais o número inteiro inicial.

\d+
*

Converta tudo em unário.

"$+"+`

Repita a substituição o número de vezes indicado pela entrada original.

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

Encontre um denominador que divida uniformemente o número inteiro.

$1$#5*$2

Substitua o número inteiro pelo resultado da divisão multiplicada pelo numerador.

r`_\G

Converta o número inteiro em decimal e produza o resultado.

Neil
fonte
1

Anexo , 81 bytes

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

Experimente online! Emite uma fração acima de 1. Por exemplo, a entrada 5retorna 2275/1. Isso pode ser corrigido com mais 2 bytes, acrescentandoN@ ao programa.

Explicação

Esta é uma função ao curry, que ao curry Nest com dois argumentos predefinidos:

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

e 2. Esse último argumento é simplesmente a semente inicial, e o argumento que é passado para essa função é o número de iterações para aninhar a função especificada.

O seguinte é usado para codificar PRIMEGAME:

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

Isso é avaliado 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)]

Vamos substituir esta expressão por Gna explicação. Nossa primeira função se torna:

{Find[Integral,_*G]}

Isso executa uma única iteração do código FRACTRAN _, a entrada para a função. É Findum Integralmembro (um que é um número inteiro) da matriz _*G, que é a entrada _multiplicada por cada membro de G.Nestsimplesmente aplica essa transformação o número especificado de vezes.

Anexo, 42 bytes

Eu implementei partes da $langsbiblioteca, sendo inspirado por esse desafio, então marquei esta seção como não competitiva.

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

Isso simplesmente consulta a lista que FRACTRAN_EXAMPLESeu tenho. Cada exemplo é uma FractranExampleinstância, que chama a FRACTRANfunção embutida. O primeexemplo é o PRIMEGAME de Conway.

Conor O'Brien
fonte
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

Experimente online!

Henrik Hansen
fonte
0

PHP, 183 bytes (189 com a tag "php")

Golfe:

$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;

Ungolfed:

<?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;

Experimente online!

Boian Ivanov
fonte