¿Cuáles son los dígitos de Fibonacci que se repiten?

30

Como probablemente sepa, un número de Fibonacci es uno que es la suma de los dos números anteriores de la serie.

Un Fibonacci Digit ™ es uno que es la suma de los dos dígitos anteriores .

Por ejemplo, para el comienzo de la serie 1,1, la serie sería 1,1,2,3,5,8,13,4,7,11,2...El cambio ocurre después de 13, donde, en lugar de agregar 8+13, agrega 1+3. La serie se repite al final, donde 4+7=11, y 1+1=2, al igual que la serie comienza.

Para dar otro ejemplo, la serie que comienza 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Este comienza de manera única, pero una vez que los dígitos se suman 10, terminas 1+0=1, 0+1=1y la serie continúa, y se repite, de la misma manera que la 1,1serie.


El reto

Dada una entrada entera 0≤n≤99, calcule el bucle en la serie de dígitos de Fibonacci que comienza con esos dos dígitos. (Ciertamente se le permite considerar números enteros fuera de este rango, pero no es obligatorio). Si se le da una entrada de un dígito, su código debe interpretarlo para indicar el comienzo de la serie 0,n.

Todos los números en el bucle que son de dos dígitos se deben generar como dos dígitos. Entonces, por ejemplo, el bucle para 1,1contendría 13, no 1,3.

La salida comienza con el primer número en el bucle. Por lo tanto, en base a las restricciones anteriores, el bucle de 1,1comienza con 2, puesto 1,1y 11se cuentan por separado.

Cada número de salida puede estar separado por lo que desee, siempre que sea coherente. En todos mis ejemplos utilizo comas, pero se permiten espacios, saltos de línea, letras aleatorias, etc., siempre que use siempre la misma separación. Entonces, 2g3g5g8g13g4g7g11es una salida legal para 1, pero 2j3g5i8s13m4g7sk11no lo es. Puede usar cadenas, listas, matrices, lo que sea, siempre que tenga los números correctos en el orden correcto separados por un separador consistente. También se permite el horquillado de toda la salida (ej. (5,9,14)O [5,9,14], etc.).

Casos de prueba:

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

Este es el , por lo que gana el menor número de bytes.

DonielF
fuente
1
¿Podemos tomar 2 dígitos como entrada, en lugar de ? 0n99
Arnauld
1
Como en, tomar dos entradas en lugar de una entrada que está dividida? No.
DonielF
Todavía no entiendo por qué 14y 59doy el mismo resultado. Si 59se interpreta como inicio 5,9y lo permite como parte del ciclo, ¿entonces seguramente 14debería ser el comienzo de su ciclo?
Neil
1
@williamporter El comienzo de la secuencia es 0,1,1,2,3,5,8,13,4,7,11,2,3. La primera vez que se repite el ciclo es en la segunda 2.
DonielF
2
@Neil el comienzo de las respectivas secuencias es 1,4,5,9,14,5y 5,9,14,5,9. Ambos repiten comenzando con el segundo 5. Como dije antes, solo la entrada se divide; los números posteriores mantienen sus dígitos juntos en la secuencia.
DonielF

Respuestas:

10

Jalea , 15 bytes

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

Pruébalo en línea!

Cómo 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
fuente
6

Perl 6 , 96 78 75 bytes

-3 bytes gracias a nwellnhof

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

Pruébalo en línea!

0 devuelve 0, y otro número devuelve un objeto Match que encadena a los números separados por un espacio con un espacio inicial al final.

Explicación:

{                                                                         }   # 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
Jo King
fuente
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)

Pruébalo en línea!

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
fuente
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))

Pruébalo en línea!

Editar: como señaló @ Jules , la solución más corta se aplica a Python 3.6+. Ya no hay soluciones distintas para Python 3 / 3.6+

Editar: La indexación de zera demasiado detallada. Sin eso ahora no hay ganancia en el uso eval.

Editar: búsqueda simplificada si los dos últimos elementos ya aparecieron en la secuencia.

Editar: Se cambió el formato de salida de la lista a tupla + reemplazado lambdapordef

Editar: Volver a lambdapero incrustado ten f.

Editar: La entrada nse puede interpretar realmente como la cabeza de una colección en crecimiento zque representaría la cola en un enfoque recursivo. También supera la solución de @ Arbo nuevamente.

Editar: en realidad, puede descomprimir dos elementos de la cabeza que corta otros 16 bytes.

Editar: en realidad 17 bytes.

Editar: Como lo señaló @ Arbo, la solución estaba dando respuestas 14y 59casos como en los casos de prueba iniciales que luego se demostró que estaban equivocados. Por ahora esto no es tan corto, pero al menos funciona correctamente.


Todo un abuso de f-stringsy eval. Código original no protegido, aunque sospecho que podría hacerse de alguna manera más 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
fuente
1
Pequeña corrección: esta es Python 3.6+. Esto simplemente no funcionará en 3.5 o más antiguo.
0xdd
1
Su código de prueba parece no funcionar; una entrada de 59rendimientos(14, 5, 9)
ArBo
Veo que los casos de prueba han cambiado desde que comencé el desafío, por eso hubo resultados incorrectos. Cambié mi solución para que funcione, pero por ahora no es tan corta. Sin embargo, gracias por señalar eso.
Nishioka
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;);}

Pruébalo en línea!

-3 de ceilingcat

Incluye un espacio final.

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
fuente
1
eh, do...whileno necesita los frenos si es una sola declaración O_o
solo ASCII
3

Perl 5, 90 76 bytes

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

TIO

Nahuel Fouilleul
fuente
@JoKing, arreglado y optimizado
Nahuel Fouilleul
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)

Pruébalo en línea!

Hardcoded parecía el más corto dado que Python ya tenía una respuesta de 187 ...

Olivier Grégoire
fuente
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

Pruébalo en línea!

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
fuente
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]

Pruébalo en línea!

El programa crea una tupla pde todos los pares de 2 valores que se han producido en la secuencia, que se inicializa con basura para guardar algunos bytes. La secuencia misma se construye en la tupla l, y los dos últimos elementos de esta tupla se almacenan bpara una referencia fácil (y breve). Tan pronto como se encuentre una repetición, podemos buscar el índice de benp para saber dónde comenzó el ciclo.

EDITAR: Limpié esto un poco y me afeité un byte más ... Mi método parece estar llegando a su límite de conteo de bytes, y realmente debería dejar de trabajar en esto.

ArBo
fuente
1

Carbón , 46 bytes

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

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

≔E◧S²Σιθ

Ingrese el número, rellene con 2 caracteres, luego tome la suma digital de cada carácter y guarde la lista resultante.

W¬υ

Repita mientras la lista de bucles esté vacía.

⊞OθΣ…⮌⪫θω²

Calcule la suma de los dos dígitos anteriores y agréguela a la lista de Fibonacci.

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

Tome todos los sufijos no triviales de la lista.

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

Filtre los que no se repiten y guarde el resultado en la lista de bucles.

Iυ

Transmita la lista de bucles para encadenar e imprimir.

Neil
fuente
1

Rojas , 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]

Pruébalo en línea!

Galen Ivanov
fuente
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]

Pruébalo en línea!

Espera un entero no negativo como entrada. Menor bytecount, pero probablemente ya no funcionará para enteros> 99.

Explicación:

# 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]
Triggernometry
fuente