Comprimentos do programa Fibonacci

14

Escreva um programa com comprimento n que emita outro programa cujo tamanho seja o próximo número de Fibonacci após n. O novo programa deve fazer o mesmo - gerar outro programa cujo tamanho seja o próximo número de Fibonacci, etc.
n em si (o tamanho do programa original) não precisa ser um número de Fibonacci, embora seja bom se for.

O menor código vence.

Nenhum recurso externo, apenas ASCII, compilador / intérprete gratuito necessário.
Se sua saída terminar em uma nova linha, ela também será contada.

aditsu
fonte
Isso precisa continuar para sempre? ( intou BigInteger)
Justin
1
@Quincunx está tudo bem se parar de funcionar no limite do int ou no compilador / intérprete, o que ocorrer primeiro. Espero que chegue a 10000+.
Aditsu
1
Existem restrições no uso de espaço em branco ou comentários ou nomes de variáveis ​​/ funções / classes arbitrariamente longos nos programas originais ou produzidos posteriormente?
Jonathan Pullano
1
O programa pode ler seu próprio código-fonte ou você está procurando um verdadeiro quase-quine?
histocrat
@JonathanPullano sem restrições, eles só precisam de ser programas válidos
aditsu

Respostas:

5

CJam, 26 23

Acabei de experimentar o seu idioma.

7{9\@5mq)2/*')*\"_~"}_~

9 é (22*0.618 + 0.5 - 1)/1.618 + 1.

Ele calcula seu próprio comprimento em *1.618vez de adicionar repetidamente os dois números. Na primeira versão, ele preencherá a saída antes do {like 1))))))))), que conta esses caracteres. Diga o resultado n. O comprimento total é n+22, e o novo comprimento anterior {deve ser (n+22)*1.618-22arredondado. Diminua-o em um para contar o número de )'s. Então será aproximadamente igual a (n+8)*1.618.

Versão antiga:

-3{1\@5mq)2/*E+')*\"_~"}_~

O número 14 é 24*0.618 + 0.5 - 1.

jimmy23013
fonte
Muito impressionante!
Dennis
Acho que temos um novo vencedor :)
aditsu
7

Python 2, 160 bytes

s='s=%s;c=s;l=len(s%%c)+4;a,b=1,1\nwhile b<l:a,b=b,a+b\nc+="1"*(b-l-1);print s%%`c`;a=1'
c=s
l=len(s%c)+4
a,b=1,1
while b<l:a,b=b,a+b
c+="1"*(b-l-1)
print s%`c`

Este é um verdadeiro quase quine; não lê sua própria fonte, mas a gera. Primeira saída (com nova linha à direita):

s='s=%s;c=s;l=len(s%%c)+4;a,b=1,1\nwhile b<l:a,b=b,a+b\nc+="1"*(b-l-1);print s%%`c`;a=111111111111111111111111111111111111111111111111111111111111111111111';c=s;l=len(s%c)+4;a,b=1,1
while b<l:a,b=b,a+b
c+="1"*(b-l-1);print s%`c`;a=1

Segundo:

s='s=%s;c=s;l=len(s%%c)+4;a,b=1,1\nwhile b<l:a,b=b,a+b\nc+="1"*(b-l-1);print s%%`c`;a=1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111';c=s;l=len(s%c)+4;a,b=1,1
while b<l:a,b=b,a+b
c+="1"*(b-l-1);print s%`c`;a=111111111111111111111111111111111111111111111111111111111111111111111

Editar: Opa. Esqueci de mudar a string quando mudei de; s para 1s, então a segunda saída estava produzindo ponto-e-vírgula extra (que o Python não suporta). Fixo

Justin
fonte
Receio que pára de funcionar após cerca de 3 iterações ...
aditsu
@aditsu What? Python tem um limite para o tamanho de um número inteiro ?! (ou é que a contagem não é um fibonacci / pula / outra coisa?) Oh, espere. Duh. Eu esqueci de mudar a string XD
Justin
7

CJam, 41 31 bytes

{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~

Experimente online.

Resultado

$ cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~'); echo
{1$+S@]_1=4+1$`,-S*"2$~"}34 21 2$~
$ cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~') | wc -c
34
$ cjam <(cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~')); echo
{1$+S@]_1=4+1$`,-S*"2$~"}55 34                      2$~
$ cjam <(cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~')) | wc -c
55
$ cjam (cjam <(cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~'))); echo
bash: syntax error near unexpected token `cjam'
$ cjam <(cjam <(cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~'))); echo
{1$+S@]_1=4+1$`,-S*"2$~"}89 55                                                        2$~
$ cjam <(cjam <(cjam <(echo '{1$+S@]_1=4+1$`,-S*"2$~"}21D2$~'))) | wc -c
89

Como funciona

{       "                                                   {…} 21 13                     ";
  1$+   " Duplicate the higher number and add.              {…} 21 34                     ";
  S@    " Push a space and rotate the lower number on top.  {…} 34 ' ' 21                 ";
  ]     " Wrap the stack into an array.                     [ {…} 34 ' ' 21 ]             ";
  _1=   " Push the second element of the array.             [ {…} 34 ' ' 21 ] 34          ";
  4+    " Add 4 to it.                                      [ {…} 34 ' ' 21 ] 38          ";
  1$`,  " Push the length of the stringified array.         [ {…} 34 ' ' 21 ] 38 37       ";
  -S*   " Subtract and push that many spaces.               [ {…} 34 ' ' 21 ] ' '         ";
  "2$~" " Push the string '2$~'.                            [ {…} 34 ' ' 21 ] ' ' '2$~'   ";
}       "                                                   {…}                           ";

21D     " Push 21 and 13.                                   {…} 21 13                     ";
2$~     " Copy the code block an evaluate.                  [ {…} 34 ' ' 21 ] ' ' '2$~'   ";
Dennis
fonte
2
Bom, confirmou até 1 milhão :) Acho que são 37 em vez de 39, embora na explicação.
Aditsu
@aditsu: Você não notou que você editou seu comentário até agora. Deve ser de fato 37, obrigado.
Dennis
6

Python - 89

g="%(s,b,a+b);print o.ljust(b-1)";s,a,b="s,a,b=%r,%i,%i;o=s%"+g,89,144;exec("o=s"+g)#####

Minha contagem perfeita de caracteres se foi . ; _; Agradeço ao TheRare por apontar a coisa da nova linha e ao Quincunx por sugerir o uso do Python 2, eliminando 2 caracteres.

EDIT : Agora apenas usa mais #s em vez de 1s; 12 caracteres mais curtos.

EDIT 2 : 94 caracteres! Eliminado alguma repetição. >: 3

EDIT 3 : Alternativa de repr mais curta para Python 2.

EDIT 4 : A saída é um caractere menor agora.

EDIT 5 : O uso de %rencurtá-lo foi retirado de uma resposta de outra pergunta do @primo.

EDIT 6 : Mais curto. : D

Aqui está uma versão do Python 3:

g="%(s,b,a+b);print(o.ljust(b-1))";s,a,b="s,a,b=%r,%i,%i;o=s%"+g,89,144;exec("o=s"+g)####

Essa resposta é semelhante à do @Quincunx.

cjfaure
fonte
printsempre adiciona uma nova linha, a menos que você especifique end=''argumento.
see
Por que não usar Python 2 ?:s,a,b="s,a,b=%s,%i,%i;o=s%%(`s`,b,a+b)+'#';print o+(b-len(o)-1)*'1'",89,144;o=s%(`s`,b,a+b)+'#';print o+(b-len(o)-1)*'1'
Justin
@Quincunx eu devo! Obrigado: D
cjfaure
Seu programa de 90-char não funciona com python 3, e tem uma saída 145-char (não é um número de Fibonacci)
aditsu
@aditsu Fixed. : 3
cjfaure
2

JavaScript, 94

(function q(w,e){return ('('+q+')('+e+','+(s=w+e)+')'+Array(s).join('/')).substr(0,s)})(55,89)

Com base em um conhecido JavaScript Quine , isso retorna quase a mesma função, seguida apenas pela quantidade de barras, de modo que soma 144, que é o próximo número de Fibonacci após N. E assim por diante ...

N não é um número de Fibonacci, mas era apenas "bom ter".

Jacob
fonte
Parece não funcionar corretamente quando passa de 1000
aditsu
1000 o que? Iterações?
Jacob
Não, duração do programa
aditsu 18/06/2014
Hmm ... eu estava testando no Console do Chrome, usando p = (my answer)-o p = eval(p)algumas vezes e até 196418 ... depois que o tempo de processamento era> 1seg, encerrei o teste: P Mas acho que ele pode continuar ainda mais.
Jacob
Você não entende .. Eu não disse que para de funcionar ou é muito lento. Eu disse que não funciona corretamente. Não basta fazer p=eval(p), também verifique p.length. Depois que chega a 987, recebo o comprimento 1598, não um número de Fibonacci.
Aditsu
0

Mathematica

({0};
 With[{n = Ceiling[ InverseFunction[Fibonacci]@LeafCount@#0 ], l = Length[#0[[1, 1]]]},
    #0 /. {0..} -> ConstantArray[0, Fibonacci[n+1] - LeafCount[#0] + l]
 ]) &

Esta é uma implementação muito simples (ou seja, sem ofuscação aqui). É uma função anônima que retorna com um pouco de preenchimento para obter o comprimento correto. O Mathematica é homoicônico: código e dados são representados como expressões do Mathematica, o que facilita muito a modificação / geração de código em tempo real. Isso também significa que a contagem de caracteres não é uma medida natural do comprimento do código. O tamanho da epxressão ( "contagem de folhas" ) é. Esta versão é baseada na contagem de folhas como medida do comprimento do código.

Se atribuirmos essa função anônima a uma variável f (para que eu possa mostrar o que acontece de maneira legível) e continuar chamando 1, 2, 3, ... vezes, sempre medindo a duração do valor de retorno, é isso que Nós temos:

In[]:= f // LeafCount
Out[]= 42

In[]:= f[] // LeafCount
Out[]= 89

In[]:= f[][] // LeafCount
Out[]= 144

In[]:= f[][][] // LeafCount
Out[]= 233

Em relação ao requisito de intérprete gratuito: o Mathematica é gratuito para o Raspberry Pi. Caso contrário, esse código deve ser direto para a porta para Mathics (código aberto) . A única coisa que falta na matemática é InverseFunction, que pode ser substituída como aqui (mas eu sou preguiçoso :).

Szabolcs
fonte
Uau, eu não sabia que o Mathematica estava livre para o Pi, eu deveria dar uma olhada. No entanto, o programa deve imprimir caracteres na saída padrão, e é isso que deve ser contado.
Aditsu
@aditsu Na verdade, eu fiz isso mais por diversão do que por competir no desafio, e usar LeafCountparecia muito mais interessante do que usar contagens de caracteres (o que implicaria manipulação de código chata como manipulação de string). :-) Não vou alterá-lo para usar a contagem de caracteres, mas posso excluí-lo sem nenhum mau pressentimento, se desejar.
precisa
Ah eu vejo. Basta deixá-lo, não é necessário excluir.
Aditsu