Um gerador principal de ocorrência natural


42

Há um número bastante grande de funções geradoras primárias. Praticamente todos eles são construídos e são baseados na peneira de Eratóstenes, na função de Möbius ou no teorema de Wilson e geralmente são inviáveis ​​de calcular na prática. Mas também existem geradores, que possuem uma estrutura muito fácil e foram encontrados por acidente.

Em 2003, Stephen Wolfram explorou uma classe de equações de recorrência aninhadas em um experimento com computador ao vivo na NKS Summer School. Um grupo de pessoas ao redor de Matthew Frank seguiu com experimentos adicionais e descobriu uma propriedade interessante da simples recorrência

a(n) = a(n-1) + gcd(n,a(n-1))

com o valor inicial de a(1) = 7. A diferença a(n) - a(n-1) = gcd(n,a(n-1))sempre parecia ser 1 ou primo. As primeiras diferenças são ( OEIS A132199 ):

1, 1, 1, 5, 3, 1, 1, 1, 1, 11, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 23, 3, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 47, 3, 1, 5, 3, ...

Se omitirmos apenas os 1s, obteremos a seguinte sequência ( OEIS A137613 ):

5, 3, 11, 3, 23, 3, 47, 3, 5, 3, 101, 3, 7, 11, 3, 13, 233, 3, 467, 3, 5, 3, 
941, 3, 7, 1889, 3, 3779, 3, 7559, 3, 13, 15131, 3, 53, 3, 7, 30323, 3, ...

Eric S. Rowland provou a primidez de cada elemento nesta lista alguns anos depois. Como você pode ver, os números primos são misturados e alguns deles aparecem várias vezes. Também foi comprovado que a sequência inclui infinitamente muitos primos distintos. Além disso, é conjecturado que todos os números primos ímpares apareçam.

Como esse gerador principal não foi construído, mas simplesmente encontrado por acidente, o gerador primário é chamado de "ocorrência natural". Mas observe que, na prática, esse gerador também é bastante inviável de calcular. Como se vê, um primo p aparece somente após (p–3)/21s consecutivos. Não obstante, implementar este gerador principal será sua tarefa.

Desafio:

Escreva uma função ou um programa que imprima os primeiros nelementos da sequência A137613(a sequência sem os 1s). Você pode ler o número de entrada n >= 0via STDIN, argumento de linha de comando, prompt ou argumento de função. Envie os primeiros nelementos em qualquer formato legível para STDOUT ou retorne uma matriz ou uma lista com esses valores.

Isso é código-golfe. Portanto, o código mais curto vence.

Entre os melhores:

Aqui está um snippet de pilha para gerar uma classificação regular e uma visão geral dos vencedores por idioma. Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

# Language Name, N bytes

onde N é o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

# Ruby, <s>104</s> <s>101</s> 96 bytes


1
Embora o gerador principal não seja construído, você está implementando efetivamente uma divisão de teste usando a recursão.
orlp 25/08/15

Se a (1) = 7, por que a sequência não começa com 7?
feersum

3
@feersum porque a sequência com a qual estamos preocupados éa(n)-a(n-1)
Maltysen

Pode nser zero?
Sp3000 25/08/2015

1
@jrenk Não tenho certeza. Talvez conte-o como 2 bytes (já que você está removendo 2 caracteres //) e explique-o no seu envio. Se alguém discordar de você, você sempre pode editar sua postagem.
Jakube 25/08/15

Respostas:



7

Python 3.5.0b1 +, 95 93 bytes

Link para o Python 3.5.0b1 + release

import math
def f(k,n=2,a=7,L=[]):x=math.gcd(n,a);return k and f(k-1%x,n+1,a+x,L+1%x*[x])or L

Uma implementação direta da recorrência, apresentando:

  • Nosso bom amigo 1%x, e
  • math.gcd, ao contrário de fractions.gcd.

O que 1%xfaz? Pergunta secundária: onde encontro a documentação do histórico de revisões do Python que inclui betas? Edit: Nevermind, encontrou-o no final do histórico de revisões .
mbomb007

@ mbomb007 Desde x >= 1, 1%xretorna 0 se x == 1, 1 caso contrário (usado para decidir se deseja adicionar xà lista)
SP3000

5

Julia, 110 bytes

n->(a(n)=(n1&&(n==1?7:a(n-1)+gcd(n,a(n-1))));i=2;j=0;while j<n x=a(i)-a(i-1);x>1&&(j+=1;println(x));i+=1end)

Ungolfed:

function a(n::Int)
    n  1 && (n == 1 ? 7 : a(n-1) + gcd(n, a(n-1)))
end

function f(n::Int)
    i = 2;
    j = 0;
    while j < n
        x = a(i) - a(i-1)
        if x > 1
            j += 1
            println(x)
        end
        i += 1
    end
end

Uau, um 8k perfeito, legal: D
Beta Decay

1
Use em n<2vez de n==1. Além disso, se você olhar para a frente em vez de para trás, você pode usar i=1e x=a(i)-a(i+=1), em seguida, println(-x)e -x>1para corrigir a negatividade, evitando assim a necessidade de um incremento separada de i. E são três bytes, enquanto >=são dois ... mas então, você pode usar em n<1||()vez de n>=1&&()... e, no entanto, nem é necessário em primeiro lugar (abandone o condicional, n nunca será menor que 1). Você também não precisa dos colchetes mais externos ao definir a (n). Com essas alterações, você deve ter no mínimo 97 bytes.
Glen O

5

PHP, 101 96 99 98 77 72 bytes

<?for(;2>$t=gmp_strval(gmp_gcd(~++$i,7+$e+=$t))or$argv[1]-=print"$t ";);


Uso:
Chame o Script com um argumento: php -d error_reporting=0 script.php 30
Se você quiser testá-lo, precisará descomentar ;extension=php_gmp.dllno seu php.ini
-> extension=php_gmp.dll
Devo adicionar a extensão à minha contagem de bytes? Alguma ideia?


Log:
salvou 3 bytes graças a Ismael Miguel.
Economizou 26 bytes graças ao primo.


1
Você pode encurtar sua tag de abertura <?e remover a definição de $j.
Ismael Miguel

1
Sim, conta. Mas você pode remover essa nova linha. O que economizará de 1 a 2 bytes, dependendo de como você contou o tamanho do seu código.
Ismael Miguel

1
Pequenas melhorias: use <in $j<=$argv[1](imprime demais) (-1). Deixe $enão inicializado, use $e+7(-3). Use em for(;;)vez de while(), usando as expressões pré e pós (-2). Substitua echo$t.' ';$j++por $j+=print"$t ", largue os suportes (-3). Substitua if($t>1)por 2>$t||(-2). Combine a atribuição $tcom a condicional, alterne ||para or, solte os colchetes (-5). Vá $argv[1]para o $jincremento, mova a expressão inteira para o forcondicional (-2). Mude >=$j+=printpara -=print(-3). Passo a passo: codepad.org/s6LNSPSM
primo

1
@primo obrigado pela boa explicação! Não sabia que eu poderia fazer tudo isso.
jrenk

1
Um pouco mais: Combine $e+7com $e+=$t(-2). Deixe $inão inicializado, use ~++$i(-3). codepad.org/fDIImajp
primo

4

Haskell, 51 bytes

d=zipWith gcd[2..]$scanl(+)7d
f=($filter(>1)d).take

Observe que fé uma função que retornará os primeiros n elementos.

Em vez de a(n)calcular as diferenças d(n)e depois calcular as diferenças, calculamos as diferenças e as somamos para obter a(n). (Aqueles que não estão familiarizados com Haskell podem protestar que precisamos a(n)primeiro d(n), mas é claro que uma avaliação preguiçosa nos ajuda a solucionar esse problema!)

Ungolfed:

a = scanl (+) 7 d        -- yielding a(n) = 7 + d(1) + d(2) + ... + d(n-1)
d = zipWith gcd [2..] a  -- yielding d(n) = gcd(n+1, a(n))

f n = take n $ filter (> 1) d -- get rid of 1s and take the first n

4

Pitão, 30 bytes

Muito mal jogado, pode ser consideravelmente reduzido. Define a função recursiva na frente, filtra .first-n e mapeia a diferença.

L?tb+KytbibK7m-yhdyd.ft-yhZyZQ

Experimente aqui online .


Isso dá a saída errada paran = 0
Sp3000 25/15

2
@ Sp3000 que é um bug no Pyth. Vou fazer um pedido pull.
Maltysen

Bug encontrado e corrigido - o patch será implementado quando o github parar de ser DDoS.
Isaacg

1
Aqui está: meta.codegolf.stackexchange.com/questions/5318/… . Pessoalmente, eu consideraria correções de bugs em linguagens de programação como resposta #
Thomas Weller

2
@ThomasWeller É o tipo de atingido toda a língua ...
isaacg

4

Julia, 69 67 bytes

n->(i=1;a=7;while n>0 x=gcd(i+=1,a);a+=x;x>1&&(n-=1;println(x))end)

Esta é uma solução iterativa simples para o problema. xé a diferença (que é a gcd) e, em seguida, atualizo aadicionando x.


Eu acho que imprime A231900 .
alephalpha

@alephalpha - Acho que vejo o erro. Facilmente reparado. Inclusive raspou dois bytes no processo.
Glen O

3

JavaScript (ES6), 91

GCD recursivo, função principal iterativa. Não tão rápido.

Nota habitual: teste de execução do snippet em qualquer navegador compatível com EcmaScript 6 (principalmente o Chrome, não o MSIE. Eu testei no Firefox, o Safari 9 pode ir)

F=m=>{
  for(G=(a,b)=>b?G(b,a%b):a,o=[],p=7,n=1;m;d>1&&(o.push(d),--m))
    p+=d=G(++n,p);
  return o
}

O.innerHTML=F(+I.value)
<input id=I value=10><button onclick='O.innerHTML=F(+I.value)'>-></button>
<pre id=O></pre>


3

Haskell, 74 71 66 bytes

f=($filter(>1)$tail>>=zipWith(-)$scanl(\x->(x+).gcd x)7[2..]).take

Usou o truque aqui: https://codegolf.stackexchange.com/a/39730/43318 e deixou de fazer sentido.

(Anterior: 71 bytes)

a=scanl(\x->(x+).gcd x)7[2..]
f m=take m$filter(>1)$zipWith(-)(tail a)a

Primeiro faça a sequência de a e depois faça as diferenças.

(Anterior: 74 bytes)

f m=take m$filter(>1)$map snd$scanl(\(x,d)->(\y->(x+y,y)).gcd x)(7,1)[2..]

Funções de lista padrão, além de uso inteligente da função lambda. Observe que este é 1 byte menor que o mais óbvio

g m=take m$filter(>1)$map snd$scanl(\(x,d)n->(x+gcd x n,gcd x n))(7,1)[2..]

Se não contarmos as importações, posso reduzir para 66.

import Data.List
h m=take m$filter(>1)$snd$mapAccumL(\x->(\y->(x+y,y)).gcd x)7[2..]

3

PARI / GP, 60 bytes

a(n)=a=7;i=1;while(n,if(1<d=gcd(i+=1,a),n-=1;print(d));a+=d)

Retirado mais ou menos direto da definição a (n) - a (n-1) = gcd (n, a (n-1))

Saída para a(20):

5
3
11
3
23
3
47
3
5
3
101
3
7
11
3
13
233
3
467
3

2

C ++, 193 182 180 172 bytes

Obrigado @Jakube - salvou 8 bytes na saída.

int g(int a,int b){return a==b?a:a>b?g(b,a-b):g(a,b-a);}void f(int *r,int n){int m=1,i=0,a=7,b;while(i<n){b=g(a,++m);if(b>1){r[i]=b;++i;}a+=b;}}int main(){int r[6];f(r,6);}

Provavelmente, você pode salvar alguns bytes definindo uma função fque retorna uma matriz com os resultados. Dessa forma, você pode remover a inclusão, o scanf e a impressão.
Jakube 27/08/15

2

Mathematica, 59 bytes

For[i=j=1;a=7,i<=#,,d=GCD[++j,a];If[d>1,Print@d;i++];a+=d]&
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.