Calcular o enésimo termo da sequência auto-descritiva de Golomb


11

Inspirado na pergunta anterior .

A sequência auto-descritiva de Golomb g (n) é uma sequência em que qualquer número natural né repetido dentro da sequência g (n) vezes.

Os primeiros números na sequência são:

n    1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20
g(n) 1  2  2  3  3  4  4  4  5  5  5  6  6  6  6  7  7  7  7  8

Você pode ver que g (4) = 3 e que "4" é repetido 3 vezes na sequência.

Dada uma entrada de n, saída g(n).

Limitações: n <100000.

O menor código vence.


Para abordagens ingênuas, isso é o mesmo que a pergunta anterior, exceto que ela usa nmais do que 2 - n % 1. Você tem algum motivo para esperar que as respostas sejam significativamente diferentes?
Peter Taylor

2
Em Haskell, você pode usar isto:golomb=1:2:2:concat(zipWith replicate(drop 2 golomb)[3..])
FUZxxl

@ Peter Taylor: Eu não sabia disso.
precisa saber é o seguinte

Respostas:


5

GolfScript (31 caracteres)

~([1 2.]2{.2$=[1$)]*@\+\)}3$*;=

Demo


Bom, mas você realmente tentou isso com n = 99999 e, se sim, quanto tempo levou? (Quando eu tentei, ele correu por uma hora antes de bater o MiB limite de memória 100 que eu definido para ele e cair.)
Ilmari Karonen

@IlmariKaronen, no. A questão não define limites de eficiência de memória ou tempo, portanto, suponho que o limite do tamanho da entrada seja para os idiomas que possuem ints de largura fixa.
Peter Taylor

6

Gelatina , não concorrente

10 bytes Esta resposta não é competitiva, pois o desafio antecede a criação do Jelly.

’ßßạ¹ß‘µṖ¡

Isso usa a fórmula recursiva a (1) = 1, a (n + 1) = 1 + a (n + 1 - a (a (n))) da página OEIS.

Experimente online!

Como funciona

’ßßạ¹ß‘µṖ¡ Main link. Input: n

’          Decrement; yield n - 1.
 ßß        Recursively call the main link twice, with argument n - 1.
   ạ¹      Take the absolute difference of a(a(n - 1)) and n.
     ß     Recursively call the main link, with argument n - a(a(n - 1)).
      ‘    Increment the result, yielding 1 + a(n - a(a(n - 1))).
       µ   Combine the chain to the left into a single link.
        Ṗ  Pop [1, ..., n]. This yields [] iff n == 1.
         ¡ Execute the chain iff Ṗ returned a non-empty array.

4

PHP - 63 caracteres

function g($n){for(;++$i<=$n;){for(;++$j<=$i;){echo $i;}$j=0;}}

Rápido e curto.

Eu pareço ter tido a sequência errada em mente. Derp.

Isso é CORRETO, rápido e curto.

function g($n){for(;++$i<$n;){echo round(1.201*pow($i,.618));}}

A precisão pode ultrapassar a marca exigida de 100.000, mas eu realmente a encontrei.


3

PHP

Esta versão recursiva é mais curta (60), mas computacionalmente ineficiente:

function g($n){return$n==1?1:1+g($n-g(g($n-1)));}echo g($n);

Isso é muito mais rápido, mas mais longo (78):

$a=[1,2,2];for($i=3;$i<$n;$i++)for($j=0;$j<$a[$i-1];$j++)$a[]=$i;echo$a[$n-1];

Muito mais rápido, mas com 89 caracteres, seria:

$a=[1,2,2];for($i=3;!isset($a[$n-1]);$i++)for($j=0;$j<$a[$i-1];$j++)$a[]=$i;echo$a[$n-1];

Qual é O (n)



3

Oásis , 7 bytes (não concorrente)

Código:

n<aae>T

Experimente online!

Oasis é uma linguagem projetada por Adnan, especializada em seqüências.

Atualmente, esse idioma pode fazer recursão e formulário fechado.

O Tno final é uma abreviação de 10, o que indica que a(0) = 0e a(1) = 1. Para adicionar mais casos de teste, basta adicionar à lista no final.

n<aae>T
n<aae>10  expanded

       0  a(0) = 0
      1   a(1) = 1

n         push n (input)
 <        -1
  a       a(above)  [a is the sequence]
   a      a(above)
    e     a(n-above)
     >    +1

Agora calculamos essencialmente a(n-a(a(n-1))+1.


2

Perl, 48 caracteres

(@a=(@a,($,)x($a[$,++]||$,)))<$_?redo:say$,for<>

Entrada em stdin, saída para stdout. Precisa do Perl 5.10+ e -M5.010para ativar o sayrecurso. Demora cerca de O ( n 2 ) tempo devido à manipulação ineficiente da matriz, mas ainda é rápido o suficiente para calcular facilmente até o 100.000º termo.


2

Julia - 28

De uma maneira recursiva :

a(n)=n==1?1:1+a(n-a(a(n-1)))

Resultado:

[a(i) for i=1:20]'
1x20 Array{Int64,2}:
 1  2  2  3  3  4  4  4  5  5  5  6  6  6  6  7  7  7  7  8

2

Python - 64 caracteres

n=input()
g=[1,2,2]
for i in range(3,n):g+=[i]*g[i-1]
print g[n]

1
Isso é bom. Eu não achei [i]*g[i-1]que fazer isso, então me inclinei para trás para fazer de outra maneira; Eu pensei que iria se comportar mais como multiplicar uma matriz por um escalar por algum motivo ...
chucksmash

1

Javascript, 93 caracteres

c=[,1],i=c.length;function g(n){for(i;i<n;i++) c[i]=g(i);return c[n]||(c[n]=1+g(n-g(g(n-1))))}

1

J, 43 caracteres

f=:3 :'<.@:+&0.5(p^2-p)*y^p-1[p=:(+%)/20$1'

Define uma função usando a expressão assintótica fornecida na página da Wikipedia.

   f 5
3
   f 20
8
   f 100000
1479

Irritantemente 9 caracteres são usados ​​apenas para arredondar para o número inteiro mais próximo.


1

Prelúdio , 69 55 54 bytes

?1-(v  #1)-
1   0v ^(#    0 (1+0)#)!
    (#)  ^#1-(0)#

Se um intérprete compatível com o padrão for usado, isso terá entrada e saída como valores de bytes . Para realmente usar números decimais em STDIN / STDOUT, você precisa do interpretador Python com NUMERIC_OUTPUT = Truee uma opção adicional NUMERIC_INPUT = True.

Explicação

O esqueleto do programa é

?1-(    1 -
1                     )!

Lemos a entrada Nna primeira voz e a diminuímos N-1. Também inicializamos a segunda voz para 1. Em seguida, fazemos N-1um loop uma vez, cada iteração da qual obtém o próximo valor da sequência na segunda pilha. No final, imprimimos o Nnúmero th.

A idéia do programa é colocar cada elemento da sequência em uma fila na terceira voz e diminuir o cabeçalho dessa fila em cada iteração. Quando a cabeça chega 0, aumentamos o valor da sequência e removemos isso 0.

Agora, o problema é que o Prelude usa pilhas e não filas. Portanto, precisamos mudar um pouco a pilha para usá-la como uma fila.

v  #
0v ^
(#)

Isso copia o valor atual da sequência para a primeira voz (como uma cópia temporária), empurra a 0para a segunda voz (para marcar o fim da fila). E, em seguida, executa um loop para deslocar (e, assim, reverter) a terceira pilha para a segunda. Após o loop, colocamos a cópia do valor atual da sequência no topo da segunda pilha (que é a cauda da nossa fila).

 )
(#
 ^#1-

Isso parece um pouco feio, mas essencialmente é um loop que muda a pilha de volta para a terceira voz. Como a )coluna está na mesma coluna das instruções de mudança, a 0que colocamos na segunda voz anteriormente também terminará na terceira, portanto, precisamos removê-la com outra #. Em seguida, diminua o topo da 3ª voz, ou seja, o início da fila.

Agora fica um pouco chato - queremos executar algum código quando esse valor for 0, mas a única estrutura de controle do Prelude (o loop) responde apenas a valores diferentes de zero.

 0 (1+0)#
(0)#

Observe que o topo da segunda voz é verdadeiro (já que a sequência de Golomb não contém nenhum 0s). Portanto, a carga de trabalho entra nessa voz (o último par de parênteses). Só precisamos impedir que isso aconteça se o início da fila 0ainda não estiver. Então, primeiro temos um "loop" na terceira voz que empurra um 0para a segunda voz se a cabeça da fila ainda é diferente de zero. Também colocamos uma 0terceira voz para sair do loop imediatamente. A #terceira voz remove isso 0ou remove a cabeça da fila, se esse já era zero. Agora esse segundo loop será inserido apenas se o cabeçalho da fila for zero (e o0na segunda voz nunca foi pressionada). Nesse caso, incrementamos o valor atual da sequência e pressionamos a 0para sair do loop. Por fim, sempre haverá um 0no topo da pilha, que precisamos descartar.

Eu lhe disse que a negação lógica é irritante no Prelude ...


1

Mathematica, 27 bytes

f@1=1;f@n_:=1+f[n-f@f[n-1]]

Outra solução recursiva.


1

CJam, 14 bytes

Como o CJam é muito mais jovem que esse desafio, essa resposta não é elegível para a marca de seleção verde. No entanto, é muito raro você usar jisso muito bem, então eu queria publicá-lo de qualquer maneira.

l~2,{_(jj-j)}j

Teste aqui.

Explicação

jé basicamente o "operador de recursão memorizado". É preciso um número inteiro N, uma matriz e um bloco F. A matriz é usada para inicializar a memória: o elemento no índice iserá retornado F(i). jentão calcula F(N), procurando ou executando o bloco (com nna pilha) se o valor ainda não tiver sido memorizado. O recurso realmente bacana é que, dentro do bloco, japenas leva um número inteiro ie chama F(i)recursivamente. Então aqui está o código:

l~             "Read and eval input.";
  2,           "Push a 2-range onto the stack, i.e. [0 1]. The first value is irrelevant
                but the second value is the base case of the recursion.";
    {       }j "Compute F(N).";
     _(        "Duplicate i and decrement to i-1.";
       jj      "Compute F(F(i-1)).";
         -     "Subtract from i.";
          j    "Compute F(n-F(F(i-1))).";
           )   "Increment the result.";

1

J, 16 bytes

    <:{1($1+I.)^:[~]

    (<:{1($1+I.)^:[~]) every 1+i.20  NB. results for inputs 1..20
1 2 2 3 3 4 4 4 5 5 5 6 6 6 6 7 7 7 7 8

Esta solução baseia-se fortemente na solução de algoritmshark para um problema semelhante. Você pode encontrar alguma explicação sobre esse método aqui.

J, 33 bytes

Nesta abordagem eu construir-se uma sequência h(k)com os valores dos índices primeiros ionde o g(i)=kassim h = 1 2 4 6 9 12 16.... Podemos obter h(k)bastante simples a partir h(1..k-1)com a expressão ({:+1+[:+/#<:])onde a entrada é h(1..k-1).

O cálculo da saída hé simples.h ([:+/]>:[) input

[:+/]>:1 2(,{:+1+[:+/#<:])@]^:[~]

1

Brachylog , 13 bytes (não concorrente)

1|-₁↰↰:?-ṅ↰+₁

Experimente online!

Explicação

1                Input = 1 = Output
 |               Or
  -₁↰            a(Input - 1)
     ↰           a(a(Input - 1))
      :?-ṅ       Input - a(a(Input - 1))
          ↰      a(Input - a(a(Input - 1))
           +₁    1 + a(Input - a(a(Input -1))

0

Python - 76 caracteres

n=20;g=[1,2,2];[[g.append(i)for j in range(g[i-1])]for i in range(3,n)];g[n]

Na verdade, isso preenche a lista com vários Nones. Parece ser o valor "correcta" de Nones tho :)
daniero

1
@ Daniero sim, é um tipo de código estranho. Eu tive que executá-lo algumas vezes para me convencer de que realmente funcionava. Ele preenche a compreensão da lista com um monte de Nones, já que list.append () retorna o Nonetipo. Eu apenas usei as compreensões da lista aninhada para obter um loop aninhado. A única finalidade das compreensões lista aqui é fazer com que o código para repetir o número certo de vezes - eles são jogar fora os valores
chucksmash

Ele salva dois personagens ao longo loops aninhados tradicionais Se eu tivesse feito :)
chucksmash

Infelizmente, parece que você está codificando a entrada, o que não permitimos, e assumindo um ambiente REPL, o que tornaria isso um trecho. Por padrão , todos os envios devem ser programas ou funções completos que usam um de nossos métodos de E / S padrão em vez de snippets. Deixe-me saber se você tiver alguma dúvida.
Alex A.

@AlexA. Fazendo um pouco de arqueologia?
Chrismash

0

JavaScript - 48 caracteres

for(g=[,i=j=k=1,2];i<1e5;k=--k?k:g[++j])g[i++]=j

Cria uma matriz indexada em 1 gcontendo os valores da sequência.

Editar - JavaScript - 46 caracteres

v=[,1];for(x=2;x<1e5;)v[x]=1+v[x-v[v[x++-1]]]

Cria uma matriz indexada em 1 vcontendo os valores da sequência.

Editar 2 - ECMAScript 6 - 27 caracteres

g=x=>x-1?1+g(x-g(g(x-1))):1

Os dois primeiros são razoavelmente rápidos - o terceiro é muito lento


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.