Tekrarlayan Fibonacci Basamakları nelerdir?


30

Muhtemelen bildiğiniz gibi, bir Fibonacci Sayı serideki önceki iki sayının toplamıdır.

Bir Fibonacci Rakamı, önceki iki basamağın toplamıdır .

Örneğin, seri başlangıcı için 1,1 için seri şöyle olacaktır 1,1,2,3,5,8,13,4,7,11,2...: Değişiklik , eklemek 13yerine, eklemek yerine, sonra gerçekleşir . Dizi sonunda dönüyor , serinin başladığı yer aynı ve burada .8+131+34+7=111+1=2

Başka bir örnek için, seri başlar 2,2 : 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Bu, benzersiz bir şekilde başlar, ancak rakamlar bir kez toplandığında, 10sonuçta kalırsınız 1+0=1, 0+1=1ve seri devam eder - ve döngüler - 1,1seriyle aynı şekilde devam eder .


Meydan okuma

Bir tamsayı girişi verildiğinde 0≤n≤99, Fibonacci Rakam serisindeki döngüyü bu iki rakamdan başlayarak hesaplayın. ( Bu aralığın dışındaki tam sayıları dikkate almanıza kesinlikle izin verilir , ancak bu gerekli değildir.) Bir basamaklı bir giriş verilirse, kodunuz seri başlangıcını belirtmek için yorumlamalıdır 0,n.

İki basamaklı olan döngüde bütün numaralar zorunluluk . Yani, örneğin, için döngü 1,1içerecektir 13değil 1,3.

Çıktı, döngüdeki ilk sayı ile başlar. Yani, yukarıdaki kısıtlamalara dayanarak,1,12 , o zamandan beri başlar 1,1ve 11ayrı olarak sayılır.

Çıktının her sayısı, tutarlı olduğu sürece, istediklerinizle ayrılabilir. Örneklerimin hepsinde virgül kullanıyorum, ancak boşlukları, satır sonlarını, rasgele harfleri vb. Her zaman aynı ayırım kullandığınız sürece izin verilir. Bu yüzden 2g3g5g8g13g4g7g11yasal bir çıktı1 ama 2j3g5i8s13m4g7sk11değil. Tutarlı bir ayırıcıyla ayrılmış doğru sırada doğru numaralara sahip olmak koşuluyla dizeleri, listeleri, dizileri ne olursa olsun kullanabilirsiniz. Çıktının tamamının parantez içine alınmasına da izin verilir (ör. (5,9,14)Veya [5,9,14], vb.).

Test Durumları:

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

Bu , bu yüzden en düşük bayt sayısı kazanır.


1
yerine giriş olarak 2 rakam alabilir miyiz ? 0n99
Arnauld

1
Olduğu gibi, bölünmüş bir giriş yerine iki giriş mi alıyorsunuz? No.
DonielF

Nedenini hala anlamadım 14ve 59aynı sonucu verdim . Eğer 59başlangıç ​​olarak 5,9ve bu döngünün bir parçası olarak izin verildiyse yorumlandığında kesinlikle döngünün 14başlangıcı mı olmalı?
Neil

1
@williamporter Dizinin başlangıcı 0,1,1,2,3,5,8,13,4,7,11,2,3. Döngünün ilk tekrarladığı an ikinci olur 2.
DonielF

2
@Neil Bu dizilerin başlangıcı 1,4,5,9,14,5ve 5,9,14,5,9. İkisi de ikinci ile başlayarak tekrar eder 5. Daha önce de söylediğim gibi, sadece girdi bölünmüş durumda; sonraki sayılar rakamlarını sırayla bir arada tutar.
DonielF

Yanıtlar:


10

Jöle , 15 bayt

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

Çevrimiçi deneyin!

Nasıl çalışır

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 bayt

Nwellnhof sayesinde -3 bayt

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

Çevrimiçi deneyin!

0, 0 değerini döndürür ve diğer sayı, sonunda bir boşluk olan bir boşlukla ayrılan sayılara dize olan bir Eşleme nesnesi döndürür.

Açıklama:

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

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)

Çevrimiçi deneyin!

Yorumlananlar

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 bayt

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

Çevrimiçi deneyin!

Düzenleme: @ Jules tarafından belirtildiği gibi , daha kısa bir çözüm Python 3.6+ için geçerlidir. Python 3 / 3.6+ için artık farklı çözümler yok

Düzenleme: endekslemesi zçok ayrıntılı. Bu olmadan şimdi kullanımda bir kazanç yoktur eval.

Düzenleme: Sıralamada en son iki öğenin zaten görünüp görünmediğini basitleştirilmiş bulma.

Düzenleme: Çıktı formatı listeden tuple + değiştirildi lambda iledef

Düzenleme: Geri lambdaancak gömülü tiçine f.

Düzenleme: Girdi n, zözyinelemeli yaklaşımda kuyruğu temsil edecek , büyüyen koleksiyonun başı olarak yorumlanabilir . Ayrıca @ Arbo'nun çözümünü tekrar yener .

Düzenleme: Aslında iki öğeyi baştan başlayarak başka bir 16 bayt kesen paketten çıkarabilirsiniz.

Düzenleme: Aslında 17 bayt.

Düzenleme: As @ tarafından da belirtildiği Arbo çözümü için cevaplar veriyordu 14ve 59onlar yanlış olduğu sonradan kanıtlanmış edildi başlangıç test örnekleri görüldüğü üzere vakaları. Şimdilik bu çok kısa değil ama en azından düzgün çalışıyor.


Oldukça kötüye f-stringsve eval. Orijinal kodsuz kod, bunun bir şekilde daha kolay olabileceğinden şüphelenmeme rağmen:

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
Küçük düzeltme: bu Python 3.6+. Bu kesinlikle 3.5 veya daha eski sürümlerde çalışmaz.
49'da 0xdd

1
Test kodunuz çalışmıyor gibi görünüyor; 59verim girişi(14, 5, 9)
ArBo

Göreve başladığımdan bu yana test vakalarının değiştiğini görüyorum, bu yüzden hatalı çıktılar oldu. Çözümümü değiştirdim ki işe yarayacak ama şimdilik çok kısa değil. Yine de bunu belirttiğiniz için teşekkürler.
Nishioka

4

C (gcc) , 114 112 109 bayt

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

Çevrimiçi deneyin!

-3 tavan uçundan

Bir takip alanı içerir.

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
huh, do...whileeğer tek bir açıklama ise parantezlere ihtiyaç duymuyor O_o
ASCII


2

Java (JDK) , 194 bayt

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

Çevrimiçi deneyin!

Sabit kod, Python'un zaten 187 cevabı olduğu göz önüne alındığında ...


2

Haskell, 100 bayt

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

Çevrimiçi deneyin!

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 bayt

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]

Çevrimiçi deneyin!

Program, pbazı baytları kurtarmak için önemsiz ile başlatılan dizide meydana gelen tüm 2-değer çiftlerinin bir demetini oluşturur . Dizilimin kendisi kanalın içine yerleştirilirl ve bu son iki elemanı bkolay (ve kısa) referans için saklanır . En kısa sürede tekrar bulunur bulunmaz, biz dizinini bakabilirsiniz biçinde pdöngü başladığı bilmek.

EDIT: Bu biraz temizledik ve bir bayt daha traş oldu ... Benim yöntem bayt sayısı sınırına yaklaşıyor gibi görünüyor, ve gerçekten bu konuda çalışmayı bırakmalıyım.


1

Kömür , 46 bayt

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

Çevrimiçi deneyin! Bağlantı, kodun ayrıntılı bir versiyonudur. Açıklama:

≔E◧S²Σιθ

Sayıyı girin, 2 karaktere kadar kaydırın, sonra her karakterin dijital toplamını alın ve elde edilen listeyi kaydedin.

W¬υ

Döngü listesi boşken tekrarlayın.

⊞OθΣ…⮌⪫θω²

Önceki iki hanenin toplamını hesaplayın ve Fibonacci listesine ekleyin.

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

Listedeki tüm önemsiz ekleri al.

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

Tekrarlanmayanları filtreleyin ve sonucu döngüler listesine kaydedin.

Iυ

Dize ve baskı için döngüler listesini yayınla.



1

Python 2 , 149 139 bayt

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]

Çevrimiçi deneyin!

Girdi olarak negatif olmayan bir tam sayı bekliyor. Küçük bytecount, ancak büyük olasılıkla> 99 olan tamsayılar için çalışmayacak.

Açıklama:

# 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]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.