Quais são os dígitos de Fibonacci repetidos?

30

Como você provavelmente sabe, um número de Fibonacci é aquele que é a soma dos dois números anteriores da série.

Um Fibonacci Digit ™ é aquele que é a soma dos dois dígitos anteriores .

Por exemplo, para o início da série 1,1, a série seria 1,1,2,3,5,8,13,4,7,11,2...A alteração ocorre após o 13, onde, em vez de adicionar 8+13, você adiciona 1+3. A série faz um loop no final, onde 4+7=11e 1+1=2, o mesmo que a série começa.

Para outro exemplo, as séries começando 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Este começa de forma exclusiva, mas quando os dígitos somam 10, você termina com 1+0=1, 0+1=1, e a série continua - e faz um loop - da mesma forma que a 1,1série.


O desafio

Dada uma entrada inteira 0≤n≤99, calcule o loop na série Fibonacci Digit começando com esses dois dígitos. (Você certamente pode considerar números inteiros fora desse intervalo, mas isso não é obrigatório.) Se for fornecida uma entrada de um dígito, seu código deve interpretá-la para indicar o início da série 0,n.

Todos os números no loop com dois dígitos devem ser emitidos como dois dígitos. Assim, por exemplo, o loop para 1,1conteria 13, não 1,3.

A saída começa com o primeiro número no loop. Portanto, com base nas restrições acima, o loop para 1,1começa com 2, desde 1,1e 11é contado separadamente.

Cada número da saída pode ser separado pelo que você quiser, desde que seja consistente. Em todos os meus exemplos, uso vírgulas, mas espaços, quebras de linha, letras aleatórias etc. são permitidos, desde que você sempre use a mesma separação. Assim 2g3g5g8g13g4g7g11é uma saída legal para 1, mas 2j3g5i8s13m4g7sk11não é. Você pode usar cadeias, listas, matrizes, o que for, desde que você tenha os números corretos na ordem correta separados por um separador consistente. O bracketing de toda a saída também é permitido (ex. (5,9,14)Ou [5,9,14]etc.).

Casos de teste:

1 -> 2,3,5,8,13,4,7,11
2 -> 2,3,5,8,13,4,7,11
3 -> 11,2,3,5,8,13,4,7
4 -> 3,5,8,13,4,7,11,2
5 -> 2,3,5,8,13,4,7,11
6 -> 3,5,8,13,4,7,11,2
7 -> 14,5,9
8 -> 13,4,7,11,2,3,5,8
9 -> 11,2,3,5,8,13,4,7
0 -> 0
14 -> 5,9,14
59 -> 5,9,14

Isso é , então o menor número de bytes vence.

DonielF
fonte
1
Podemos usar 2 dígitos como entrada, em vez de ? 0 0n99
Arnauld
1
Como, pegue duas entradas em vez de uma entrada dividida? Não.
DonielF
Ainda não entendo o porquê 14e 59dou o mesmo resultado. Se 59é interpretado como iniciando 5,9e permitindo que, como parte do loop, então certamente 14deve ser o início do loop?
Neil
1
@ williamporter O início da sequência é 0,1,1,2,3,5,8,13,4,7,11,2,3. A primeira vez que o loop se repete é na segunda 2.
DonielF
2
@ Neil O início dessas respectivas seqüências é 1,4,5,9,14,5e 5,9,14,5,9. Ambos repetem começando com o segundo 5. Como eu disse anteriormente, apenas a entrada é dividida; os números posteriores mantêm seus dígitos juntos na sequência.
DonielF

Respostas:

10

Gelatina , 15 bytes

DFṫ-SṭḊ
d⁵ÇÐḶZḢ

Experimente online!

Como funciona

d⁵ÇÐḶZḢ  Main link. Argument: n (integer)

d⁵       Divmod 10; yield [n:10, n%10].
  ÇÐḶ    Call the helper link until a loop is reached. Return the loop.
     Z   Zip/transpose the resulting array of pairs.
      Ḣ  Head; extract the first row.


DFṫ-SṭḊ  Helper link. Argument: [a, b] (integer pair)

D        Decimal; replace a and b with the digits in base 10.
 F       Flatten the resulting array of digit arrays.
  ṫ-     Tail -1; take the last two digits.
    S    Compute their sum.
      Ḋ  Dequeue; yield [b].
     ṭ   Append the sum to [b].
Dennis
fonte
6

Perl 6 , 96 78 75 bytes

-3 bytes graças a nwellnhof

{0,|.comb,((*~*)%100).comb.sum...{my$a=.tail(2);m/(\s$a.*)$a/}o{@_};$_&&$0}

Experimente online!

0 retorna 0 e outro número retorna um objeto Match que se restringe aos números separados por um espaço com um espaço à direita à esquerda.

Explicação:

{                                                                         }   # Anonymous code block
 0,|.comb,                    ...   # Start a sequence with 0,input
                                    # Where each element is
                          .sum      # The sum of
          (     %100).comb          # The last two digits
           (*~*)                    # Of the previous two elements joined together
                                                                         # Until
                                 {                           }o{@_}   # Pass the list into another function
                                  my$a=.tail(2); # Save the last two elements
                                                m/(\s$a.*)$a/  # The list contains these elements twice?
                                                                     # And return
                                                                   ;$_     # Input if input is 0
                                                                      &&   # Else
                                                                        $0 # The looping part, as matched
Brincadeira
fonte
5

JavaScript (ES6),  111 104  103 bytes

f=(n,o=[p=n/10|0,n%10])=>n^o[i=o.lastIndexOf(n=(q=p+[p=n])/10%10+q%10|0)-1]?f(n,[...o,n]):o.slice(i,-1)

Experimente online!

Comentado

f = (                       // f = recursive function taking:
  n,                        //    n = last term, initialized to the input
  o = [                     //    o = sequence, initially containing:
    p = n / 10 | 0,         //      p = previous term, initialized to floor(n / 10)
    n % 10 ]                //      n mod 10
) =>                        //
  n ^                       // we compare n against
  o[                        // the element in o[] located at
    i = o.lastIndexOf(      //   the index i defined as the last position of
      n =                   //     the next term:
        (q = p + [p = n])   //       q = concatenation of p and n; update p to n
        / 10 % 10           //       compute the sum of the last two digits
        + q % 10            //       of the resulting string
        | 0                 //       and coerce it back to an integer
      ) - 1                 //   minus 1
  ] ?                       // if o[i] is not equal to n:
    f(n, [...o, n])         //   append n to o[] and do a recursive call
  :                         // else:
    o.slice(i, -1)          //   we've found the cycle: return it
Arnauld
fonte
5

Python 3 , 187 176 158 139 138 129 121 120 112 96 95 120 116 bytes

f=lambda n,m=0,z=[]:(n,m)in zip(z,z[1:])and z[z.index(m)::-1]or f((z and n//10or m%10)+n%10,z and n or n//10,(m,*z))

Experimente online!

Edit: Conforme observado por @ Jules , a solução mais curta se aplica ao Python 3.6+. Não há mais soluções distintas para Python 3 / 3.6+

Editar: a indexação de zera muito detalhada. Sem isso, agora não há ganho no uso eval.

Editar: localização simplificada se os dois últimos elementos já apareceram na sequência.

Editar: formato de saída alterado da lista para tupla + substituído lambdapordef

Edit: Voltar lambdamas incorporado tem f.

Editar: a entrada npode ser realmente interpretada como chefe da coleção crescente, o zque representaria uma cauda na abordagem recursiva. Também supera a solução da @ Arbo novamente.

Editar: Na verdade, você pode descompactar dois itens da cabeça, o que corta outros 16 bytes.

Edit: Na verdade, 17 bytes.

Edit: Como observado por @ Arbo solução estava dando respostas 14e 59casos como eles estavam em casos de teste inicial que foram provados mais tarde estar errado. Por enquanto, isso não é tão curto, mas pelo menos funciona corretamente.


Bastante abuso de f-stringse eval. Código original não-golfado, embora eu suspeite que possa ser feito de alguma maneira mais fácil:

def is_subsequence(l1, l2):
    N, n = len(l1), len(l2)
    for i in range(N-n):
        if l1[i:i+n]==l2:
            return True
    return False

def generate_sequence(r):
    if is_subsequence(r,r[-2:]):
        return r
    last_two_digits = "".join(map(str,r))[-2:]
    new_item = sum(int(digit) for digit in last_two_digits)
    return generate_sequence(r + [new_item])

def f(n):
    seq = generate_sequence([n,n])[::-1]
    second_to_last = seq[1]
    first_occurence = seq.index(second_to_last)
    second_occurence = seq.index(second_to_last, first_occurence + 1)
    return seq[first_occurence + 1 : second_occurence + 1][::-1]
Nishioka
fonte
1
Correção pequena: este é o Python 3.6+. Obviamente, isso não funcionará em 3.5 ou mais antigo.
0xdd 9/01
1
Seu código de teste parece não funcionar; uma entrada de 59rendimentos(14, 5, 9)
ArBo 11/01
Vejo que os casos de teste mudaram desde que comecei o desafio, por isso houve uma saída incorreta. Alterei minha solução para que funcione, mas por enquanto não é tão curta. No entanto, obrigado por apontar isso.
Nishioka 12/01
4

C (gcc) , 114 112 109 bytes

f(n,s){int i[19]={};for(s=n/10,n%=10;i[s]-n;n+=n>9?-9:s%10,s=i[s])i[s]=n;for(;printf("%d ",s),i[s=i[s]]-n;);}

Experimente online!

-3 de roofcat

Inclui um espaço à direita.

f(n,s){
    int i[19]={};                               //re-initialize edges for each call
    for(s=n/10,n%=10;                           //initialize from input
        i[s]-n;                                 //detect loop when an edge s->n repeats
        n+=n>9?-9:s%10,s=i[s])i[s]=n;           //step
    for(;printf("%d ",s),i[s=i[s]]-n;);         //output loop
}
attinat
fonte
1
hein, do...whilenão precisa do aparelho se for uma única instrução O_o
somente ASCII
3

Perl 5, 90 76 bytes

s/.\K/ /;s/(.?) *(.)\K$/$".($1+$2)/e until/^0|\b(.\B.|. .)\b.*(?= \1)/;$_=$&

TIO

Nahuel Fouilleul
fonte
@JoKing, fixo e otimizado
Nahuel Fouilleul 10/01
2

Java (JDK) , 194 bytes

n->"acdfinehlcdfinehfjofj".chars().map(x->x-97).skip((n="abbicbcsfibbbgqifiibbgbbbcsfbiiqcigcibiccisbcqbgcfbffifbicdqcibcbicfsisiibicfsiffbbicfsifiibicfsifii".charAt(n)%97)).limit(n<1?1:n<9?8:3)

Experimente online!

Hardcoded parecia o mais curto, já que o Python já tinha uma resposta de 187 ...

Olivier Grégoire
fonte
2

Haskell, 100 bytes

d!p@(s,t)|(_,i:h)<-span(/=p)d=fst<$>i:h|q<-d++[p]=q!(t,last$mod s 10+t:[t-9|t>9])
h x=[]!divMod x 10

Experimente online!

d!p@(s,t)                -- function '!' recursively calculates the sequence
                         -- input parameter:
                         -- 'p': pair (s,t) of the last two numbers of the sequence
                         -- 'd': a list of all such pairs 'p' seen before
  |       <-span(/=p)d   -- split list 'd' into two lists, just before the first
                         -- element that is equal to 'p'
   (_,i:h)               -- if the 2nd part is not empty, i.e. 'p' has been seen
                         -- before
          =fst<$>i:h     -- return all first elements of that 2nd part. This is
                         -- the result.
  |q<-d++[p]             -- else (p has not been seen) bind 'q' to 'd' followed by 'p'
   =q!                   -- and make a recursive call to '!' with 'q' and
     (t,    )            -- make the last element 't' the second to last element
                         -- the new last element is
          [t-9|t>9]      -- 't'-9 (digit sum of 't'), if 't'>9
       mod s 10+t        -- last digit of 's' plus 't', otherwise

h x=                     -- main function
     []!divMod x 10      -- call '!' with and empty list for 'd' and
                         -- (x/10,x%10) as the pair of last numbers
nimi
fonte
2

Python 2 , 123 114 113 bytes

n=input()
p=b=l=n/10,n%10
while~-(b in p):p+=b,;l+=(b[1]/10or b[0]%10)+b[1]%10,;b=l[-2:]
print l[p.index(b)-2:-2]

Experimente online!

O programa constrói uma tupla pde todos os pares de 2 valores que ocorreram na sequência, que é inicializada com lixo eletrônico para salvar alguns bytes. A própria sequência é criada na tupla l, e os dois últimos elementos dessa tupla são armazenados bpara referência fácil (e curta). Assim que uma repetição é encontrada, podemos procurar o índice de bin ppara saber onde o loop começou.

EDIT: Limpei isso um pouco e eliminou mais um byte ... Meu método parece estar se aproximando do limite de contagem de bytes, e eu realmente deveria parar de trabalhar nisso.

ArBo
fonte
1

Carvão , 46 bytes

≔E◧S²ΣιθW¬υ≔ΦE⊖L⊞OθΣ…⮌⪫θω²✂θλLθ¹⁼κ✂θ⊗⁻λLθλ¹υIυ

Experimente online! Link é a versão detalhada do código. Explicação:

≔E◧S²Σιθ

Digite o número, preencha com 2 caracteres, pegue a soma digital de cada caractere e salve a lista resultante.

W¬υ

Repita enquanto a lista de loops está vazia.

⊞OθΣ…⮌⪫θω²

Calcule a soma dos dois dígitos anteriores e adicione-a à lista de Fibonacci.

E⊖L...✂θλLθ¹

Pegue todos os sufixos não triviais da lista.

≔Φ...⁼κ✂θ⊗⁻λLθλ¹υ

Filtre aqueles que não se repetem e salve o resultado na lista de loops.

Iυ

Lance a lista de loops para string e imprima.

Neil
fonte
1

Vermelho , 189 178 164 137 bytes

func[n][b: n % 10 c: reduce[a: n / 10]until[append c e: b
b: a *(pick[0 1]b > 9)+(a: b % 10)+(b / 10)k: find c reduce[e b]]take/last k k]

Experimente online!

Galen Ivanov
fonte
1

Python 2 , 149 139 bytes

s=input()
s=[s/10,s%10]
while zip(s,s[1:]).count((s[-2],s[-1]))<2:s+=[(s[-1]/10or s[-2]%10)+s[-1]%10]
print s[-s[::-1].index(s[-2],2)-1:-2]

Experimente online!

Espera um número inteiro não negativo como entrada. Número de bytes menor, mas provavelmente não funcionará mais para números inteiros> 99.

Explicação:

# get the input from STDIN
s=input()
# convert the input into two integers via a divmod operation
s=[s/10,s%10]
# count number of times the last two numbers appear in sequence in list.
# turn list into list of adjacent value pairs Ex: [1,1,2]->[(1,1),(1,2)]
      zip(s,s[1:])
                  # count number of times the last two items in list appear in entire list
                  .count((s[-2],s[-1]))
# if >1 matches, we have found a repeat.
while .................................<2:
        # the first digit of the last number, if it is >9
        # else the last digit of the second to last number
        (s[-1]/10or s[-2]%10)
                             # the last digit of the last number
                             +s[-1]%10
    # add the new item to the list
    s+=[..............................]
         # reverse the list, then find the second occurrence of the second to last item
         s[::-1].index(s[-2],2)
# get the section of the list from the second occurrence from the end, discard the final two items of the list
print s[-......................-1:-2]
Triggernometria
fonte