Was sind die sich wiederholenden Fibonacci-Ziffern?

30

Wie Sie wahrscheinlich wissen, ist eine Fibonacci-Zahl eine Zahl, die die Summe der beiden vorherigen Zahlen in der Reihe ist.

Eine Fibonacci-Ziffer ist eine, die die Summe der beiden vorherigen Ziffern ist .

Zum Beispiel wäre für den Serienanfang 1,1die Serie 1,1,2,3,5,8,13,4,7,11,2...Die Änderung erfolgt nach dem 13, wo Sie anstelle des Hinzufügens 8+13hinzufügen 1+3. Die Serie wird am Ende wiederholt, wo 4+7=11und 1+1=2wie die Serie beginnt.

Für ein anderes Beispiel beginnt die Serie 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Dieser beginnt einmalig, aber sobald die Ziffern zusammengezählt sind 10, haben Sie das Ergebnis 1+0=1, 0+1=1, und die Serie wird fortgesetzt - und wiederholt sich - auf dieselbe Weise wie die 1,1Serie.


Die Herausforderung

0≤n≤99Berechnen Sie bei einer Ganzzahleingabe die Schleife in der Fibonacci-Ziffernreihe, die mit diesen beiden Ziffern beginnt. ( Ganzzahlen außerhalb dieses Bereichs dürfen natürlich berücksichtigt werden, sind jedoch nicht erforderlich.) Bei einer einstelligen Eingabe sollte der Code diese interpretieren, um den Beginn der Reihe zu kennzeichnen 0,n.

Alle zweistelligen Zahlen in der Schleife müssen zweistellig ausgegeben werden. So zum Beispiel für die Schleife 1,1enthalten würde 13, nicht 1,3.

Die Ausgabe beginnt mit der ersten Nummer in der Schleife. Basierend auf den obigen Einschränkungen 1,1beginnt die Schleife für also mit 2, da 1,1und 11wird separat gezählt.

Jede Nummer der Ausgabe kann nach Belieben getrennt werden, solange sie konsistent ist. In allen meinen Beispielen verwende ich Kommas, aber Leerzeichen, Zeilenumbrüche, Zufallsbuchstaben usw. sind zulässig, solange Sie immer die gleiche Trennung verwenden. Ist 2g3g5g8g13g4g7g11also eine legale Ausgabe für 1, ist es aber 2j3g5i8s13m4g7sk11nicht. Sie können beliebige Zeichenfolgen, Listen und Arrays verwenden, vorausgesetzt, Sie haben die richtigen Zahlen in der richtigen Reihenfolge, die durch ein konsistentes Trennzeichen voneinander getrennt sind. Die Belichtungsreihe für die gesamte Ausgabe ist ebenfalls zulässig (z. B. (5,9,14)oder [5,9,14]usw.).

Testfälle:

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

Das ist , also gewinnt die niedrigste Anzahl von Bytes.

DonielF
quelle
1
Können wir 2 Ziffern anstelle von als Eingabe verwenden ? 0n99
Arnauld
1
Nehmen Sie wie in zwei Eingänge anstelle eines geteilten Eingangs? Nein
DonielF
Ich verstehe immer noch nicht warum 14und 59gebe das gleiche Ergebnis. Wenn dies 59so interpretiert wird 5,9, dass es als Teil der Schleife startet und dies zulässt, 14sollte dies sicher der Anfang der Schleife sein?
Neil
1
@williamporter Der Beginn der Sequenz ist 0,1,1,2,3,5,8,13,4,7,11,2,3. Das erste Mal, dass die Schleife wiederholt wird, erfolgt beim zweiten Mal 2.
DonielF
2
@Neil Der Beginn dieser jeweiligen Sequenzen ist 1,4,5,9,14,5und 5,9,14,5,9. Beide wiederholen sich beginnend mit der Sekunde 5. Wie ich bereits sagte, wird nur die Eingabe aufgeteilt. Spätere Nummern behalten ihre Ziffern in der Reihenfolge bei.
DonielF

Antworten:

10

Gelee , 15 Bytes

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

Probieren Sie es online!

Wie es funktioniert

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
quelle
6

Perl 6 , 96 & ndash ; 78 75 Bytes

-3 bytes dank nwellnhof

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

Probieren Sie es online!

0 gibt 0 zurück, und andere Zahlen geben ein Match-Objekt zurück, das die durch ein Leerzeichen mit einem vorangestellten und einem nachfolgenden Leerzeichen getrennten Zahlen angibt.

Erläuterung:

{                                                                         }   # 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
Scherzen
quelle
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)

Probieren Sie es online!

Kommentiert

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

Probieren Sie es online!

Bearbeiten: Wie von @ Jules bemerkt , gilt eine kürzere Lösung für Python 3.6+. Keine unterschiedlichen Lösungen mehr für Python 3 / 3.6+

Edit: Indizierung von zwar zu ausführlich. Ohne das gibt es jetzt keinen Nutzen mehr eval.

Bearbeiten: Vereinfachtes Ermitteln, ob die letzten beiden Elemente bereits in der Sequenz enthalten waren.

Edit: Changed Ausgabeformat aus der Liste zu Tupel + ersetzt lambdamitdef

Bearbeiten: Zurück zu, lambdaaber eingebettet tin f.

Bearbeiten: Eingaben nkönnen tatsächlich als Kopf einer wachsenden Sammlung interpretiert werden, zdie im rekursiven Ansatz den Endpunkt darstellen würde. Schlägt auch wieder @ Arbos Lösung.

Bearbeiten: Eigentlich können Sie zwei Elemente aus dem Kopf entpacken, was weitere 16 Bytes schneidet.

Edit: Eigentlich 17 Bytes.

Bearbeiten: Wie von @ Arbo festgestellt, gab Lösung Antworten für 14und 59Fälle, wie sie in ersten Testfällen waren, die sich später als falsch erwiesen haben. Im Moment ist das nicht so kurz, aber es funktioniert zumindest richtig.


Ein Missbrauch von f-stringsund eval. Original ungolfed code obwohl ich vermute es könnte irgendwie einfacher gemacht werden:

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
quelle
1
Kleine Korrektur: Dies ist Python 3.6+. Dies wird in 3.5 oder älter nicht funktionieren.
0xdd
1
Ihr Testcode scheint nicht zu funktionieren. eine Eingabe von 59Erträgen(14, 5, 9)
ArBo
Ich sehe, dass sich die Testfälle geändert haben, seit ich mit der Herausforderung begonnen habe. Deshalb gab es eine falsche Ausgabe. Ich habe meine Lösung so geändert, dass sie funktioniert, aber im Moment ist sie nicht so kurz. Trotzdem vielen Dank für den Hinweis.
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;);}

Probieren Sie es online!

-3 von ceilingcat

Beinhaltet ein Leerzeichen.

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
quelle
1
huh, do...whilebraucht keine geschweiften Klammern, wenn es eine einzelne Anweisung ist O_o
ASCII
3

Perl 5, 90 76 Bytes

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

TIO

Nahuel Fouilleul
quelle
@JoKing, behoben und optimiert
Nahuel Fouilleul
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)

Probieren Sie es online!

Hardcoded schien die kürzeste zu sein, da Python bereits eine Antwort von 187 hatte ...

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

Probieren Sie es 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
quelle
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]

Probieren Sie es online!

Das Programm baut ein Tupel paller 2-Wert-Paare auf, die in der Sequenz aufgetreten sind. Dieses Tupel wird mit Junk initialisiert, um einige Bytes zu sparen. Die Sequenz selbst wird im Tupel erstellt l, und die letzten beiden Elemente dieses Tupels werden bzur einfachen (und kurzen) Bezugnahme gespeichert . Sobald eine Wiederholung gefunden wird, können wir den Index von bin nachschlagenp zu wissen, wo die Schleife begonnen hat.

EDIT: Bereinigt dies ein bisschen und rasiert ein weiteres Byte ... Meine Methode scheint sich dem Limit für die Byteanzahl zu nähern, und ich sollte wirklich aufhören, daran zu arbeiten.

ArBo
quelle
1

Kohle , 46 Bytes

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

Probieren Sie es online! Link ist eine ausführliche Version des Codes. Erläuterung:

≔E◧S²Σιθ

Geben Sie die Nummer ein, füllen Sie sie mit 2 Zeichen auf, nehmen Sie die digitale Summe jedes Zeichens und speichern Sie die resultierende Liste.

W¬υ

Wiederholen, solange die Liste der Schleifen leer ist.

⊞OθΣ…⮌⪫θω²

Berechnen Sie die Summe der beiden vorherigen Ziffern und fügen Sie sie der Fibonacci-Liste hinzu.

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

Nehmen Sie alle nichttrivialen Suffixe der Liste.

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

Filtern Sie diejenigen heraus, die sich nicht wiederholen, und speichern Sie das Ergebnis in der Liste der Schleifen.

Iυ

Wandeln Sie die Liste der Schleifen in Zeichenfolge und drucken Sie sie aus.

Neil
quelle
1

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

Probieren Sie es online!

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

Probieren Sie es online!

Erwartet eine nicht negative Ganzzahl als Eingabe. Kleinere Bytecount, aber wahrscheinlich nicht mehr für ganze Zahlen> 99.

Erläuterung:

# 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]
Triggernometrie
quelle