Quali sono le cifre ripetute di Fibonacci?


30

Come probabilmente saprai, un numero di Fibonacci è quello che è la somma dei due numeri precedenti nella serie.

Una Fibonacci Digit ™ è quella che è la somma delle due cifre precedenti .

Ad esempio, per l'inizio della serie 1,1, la serie sarebbe 1,1,2,3,5,8,13,4,7,11,2...La modifica si verifica dopo il 13, dove, invece di aggiungere 8+13, si aggiunge 1+3. La serie scorre alla fine, dove 4+7=11e 1+1=2, come inizia la serie.

Per un altro esempio, le serie Beginning 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Questo inizia in modo univoco, ma una volta che le cifre si sommano 10, si finisce con 1+0=1, 0+1=1, e la serie continua - e continua - allo stesso modo della 1,1serie.


La sfida

Dato un input intero 0≤n≤99, calcola il loop nella serie Digit Fibonacci che inizia con quelle due cifre. (Si sono certamente permesso di prendere in considerazione gli interi fuori di questo intervallo, ma non è obbligatorio.) Se dato un ingresso a una cifra, il codice dovrebbe interpretarlo per indicare l'inizio della serie 0,n.

Tutti i numeri nel loop che sono a due cifre devono essere emessi come due cifre. Quindi, per esempio, il ciclo per 1,1dovrebbe contenere 13, no 1,3.

L'output inizia con il primo numero nel loop. Quindi, in base alle restrizioni di cui sopra, il ciclo per 1,1inizia con 2, poiché 1,1e 11vengono conteggiati separatamente.

Ogni numero dell'output può essere separato da quello che vuoi, purché sia ​​coerente. In tutti i miei esempi uso le virgole, ma sono consentiti spazi, interruzioni di riga, lettere casuali, ecc., Purché utilizzi sempre la stessa separazione. Quindi 2g3g5g8g13g4g7g11è un risultato legale per 1, ma 2j3g5i8s13m4g7sk11non lo è. È possibile utilizzare stringhe, elenchi, matrici, qualunque cosa, purché si disponga dei numeri corretti nell'ordine corretto separati da un separatore coerente. È consentito anche il bracketing dell'intero output (es. (5,9,14)O [5,9,14], ecc.).

Casi test:

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

Questo è , quindi vince il numero più basso di byte.


1
Possiamo prendere 2 cifre come input, invece di ? 0n99
Arnauld

1
Come in, prendi due input anziché un input che è diviso? No.
DonielF

Continuo a non capire perché 14e 59dare lo stesso risultato. Se 59viene interpretato come avvio 5,9e consenti ciò come parte del ciclo, allora sicuramente 14dovrebbe essere l'inizio del suo ciclo?
Neil

1
@williamporter L'inizio della sequenza è 0,1,1,2,3,5,8,13,4,7,11,2,3. La prima volta che il loop si ripete è al secondo 2.
DonielF

2
@Neil L'inizio di quelle rispettive sequenze è 1,4,5,9,14,5e 5,9,14,5,9. Entrambi si ripetono a partire dal secondo 5. Come ho detto prima, solo l'input è suddiviso; i numeri successivi tengono insieme le cifre nella sequenza.
DonielF

Risposte:


10

Gelatina , 15 byte

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

Provalo online!

Come funziona

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

6

Perl 6 , 96 78 75 byte

-3 byte grazie a nwellnhof

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

Provalo online!

0 restituisce 0 e un altro numero restituisce un oggetto Match che si stringe ai numeri separati da uno spazio con uno spazio iniziale iniziale.

Spiegazione:

{                                                                         }   # 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

5

JavaScript (ES6),  111 104  103 byte

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)

Provalo online!

Commentate

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

5

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

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

Provalo online!

Modifica: come notato da @ Jules , la soluzione più breve si applica a Python 3.6+. Soluzioni non più distinte per Python 3 / 3.6+

Modifica: l'indicizzazione di zera troppo dettagliata. Senza questo ora non c'è guadagno nell'uso eval.

Modifica: scoperta semplificata se gli ultimi due elementi sono già comparsi nella sequenza.

Modifica: formato di output modificato dall'elenco alla tupla + sostituito lambdacondef

Modifica: torna a lambdama incorporato tin f.

Modifica: l'input npuò essere effettivamente interpretato come responsabile della collezione in crescita zche rappresenterebbe la coda in un approccio ricorsivo. Inoltre batte di nuovo la soluzione di @ Arbo .

Modifica: in realtà è possibile decomprimere due elementi dalla testa che taglia altri 16 byte.

Modifica: attualmente 17 byte.

Modifica: come notato da @ Arbo, la soluzione forniva risposte 14e 59casi come in casi di test iniziali, che in seguito si sono rivelati errati. Per ora questo non è così breve ma almeno funziona correttamente.


Abbastanza un abuso di f-stringse eval. Codice originale non registrato, anche se sospetto che potrebbe essere fatto in qualche modo più semplice:

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]

1
Piccola correzione: questo è Python 3.6+. Questo chiaramente non funzionerà in 3.5 o precedenti.
0xdd

1
Il codice di test sembra non funzionare; un input di 59rese(14, 5, 9)
ArBo

Vedo che i casi di test sono cambiati da quando ho iniziato la sfida, per questo motivo l'output non è corretto. Ho cambiato la mia soluzione in modo che funzioni, ma per ora non è così breve. Tuttavia grazie per averlo sottolineato.
Nishioka,

4

C (gcc) , 114 112 109 byte

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;);}

Provalo online!

-3 da plafoniera

Include uno spazio finale.

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
}

1
eh, do...whilenon ha bisogno delle parentesi graffe se è una singola istruzione O_o
ASCII, solo il


2

Java (JDK) , 194 byte

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

Provalo online!

Hardcoded sembrava il più breve dato che Python aveva già una risposta di 187 ...


2

Haskell, 100 byte

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

Provalo 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

2

Python 2 , 123 114 113 byte

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]

Provalo online!

Il programma crea una tupla pdi tutte le coppie di 2 valori che si sono verificate nella sequenza, che viene inizializzata con junk per salvare alcuni byte. La sequenza stessa viene creata nella tupla le gli ultimi due elementi di questa tupla vengono archiviati bper un riferimento facile (e breve). Non appena viene trovata una ripetizione, possiamo cercare l'indice di bin pper sapere dove è iniziato il ciclo.

EDIT: risolto un po 'e rimosso un altro byte ... Il mio metodo sembra avvicinarsi al limite del conteggio dei byte e dovrei davvero smettere di lavorare su questo.


1

Carbone , 46 byte

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

Provalo online! Il collegamento è alla versione dettagliata del codice. Spiegazione:

≔E◧S²Σιθ

Inserisci il numero, inseriscilo in 2 caratteri, quindi prendi la somma digitale di ciascun carattere e salva l'elenco risultante.

W¬υ

Ripetere mentre l'elenco dei loop è vuoto.

⊞OθΣ…⮌⪫θω²

Calcola la somma delle due cifre precedenti e aggiungila all'elenco Fibonacci.

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

Prendi tutti i suffissi non banali dell'elenco.

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

Filtra quelli che non si ripetono e salva il risultato nell'elenco dei loop.

Iυ

Trasmetti l'elenco dei loop da stringere e stampare.


1

Rosso , 189 178 164 137 byte

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]

Provalo online!


1

Python 2 , 149 139 byte

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]

Provalo online!

Si aspetta un numero intero non negativo come input. Byteunt più piccolo, ma probabilmente non funzionerà più per numeri interi> 99.

Spiegazione:

# 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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.