Apa digit Fibonacci berulang?


30

Seperti yang mungkin Anda ketahui, Angka Fibonacci adalah angka yang merupakan jumlah dari dua angka sebelumnya dalam seri.

Digit Fibonacci ™ adalah angka yang merupakan jumlah dari dua digit sebelumnya .

Misalnya, untuk seri awal 1,1, seri akan menjadi 1,1,2,3,5,8,13,4,7,11,2...Perubahan terjadi setelah 13, di mana, alih-alih menambahkan 8+13, Anda menambahkan 1+3. Serial loop di akhir, di mana 4+7=11, dan 1+1=2, sama dengan seri dimulai.

Sebagai contoh lain, seri awal 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Yang satu ini dimulai secara unik, tetapi setelah jumlah digit 10, Anda berakhir dengan 1+0=1, 0+1=1, dan seri berlanjut - dan loop - dengan cara yang sama seperti 1,1seri.


Tantangan

Diberikan input integer 0≤n≤99, hitung loop dalam seri Fibonacci Digit yang dimulai dengan dua digit itu. (Anda tentu saja diperbolehkan untuk mempertimbangkan bilangan bulat di luar rentang ini, tetapi itu tidak diperlukan.) Jika diberi input satu digit, kode Anda harus menafsirkannya untuk menunjukkan awal seri 0,n.

Semua angka dalam loop yang dua digit harus dikeluarkan sebagai dua digit. Jadi, misalnya, loop untuk 1,1berisi 13, bukan 1,3.

Output dimulai dengan angka pertama dalam loop. Jadi, berdasarkan batasan di atas, loop untuk 1,1dimulai dengan 2, sejak 1,1dan 11dihitung secara terpisah.

Setiap jumlah output dapat dipisahkan oleh apa pun yang Anda inginkan, asalkan konsisten. Dalam semua contoh saya, saya menggunakan koma, tetapi spasi, jeda baris, huruf acak, dll. Semua diperbolehkan, selama Anda selalu menggunakan pemisahan yang sama. Jadi 2g3g5g8g13g4g7g11adalah hasil hukum untuk 1, tetapi 2j3g5i8s13m4g7sk11tidak. Anda dapat menggunakan string, daftar, array, apa pun, asalkan Anda memiliki angka yang benar dalam urutan yang benar dipisahkan oleh pemisah yang konsisten. Membatasi seluruh output juga diperbolehkan (mis. (5,9,14)Atau [5,9,14], dll.).

Kasus uji:

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

Ini adalah , sehingga jumlah byte terendah menang.


1
Bisakah kita mengambil 2 digit sebagai input, bukannya ? 0n99
Arnauld

1
Seperti dalam, ambil dua input daripada satu input yang terbagi? Tidak.
DonielF

Saya masih tidak mengerti mengapa 14dan 59memberikan hasil yang sama. Jika 59diartikan sebagai awal 5,9dan membiarkan itu sebagai bagian dari loop maka tentunya 14harus menjadi awal dari loopnya?
Neil

1
@williamporter Awal urutannya adalah 0,1,1,2,3,5,8,13,4,7,11,2,3. Pertama kali loop berulang adalah pada detik 2.
DonielF

2
@ Neil Awal dari urutan masing-masing adalah 1,4,5,9,14,5dan 5,9,14,5,9. Keduanya diulang mulai dengan yang kedua 5. Seperti yang saya katakan sebelumnya, hanya input yang dipisahkan; nomor-nomor selanjutnya menyimpan digit mereka bersama-sama dalam urutan.
DonielF

Jawaban:


10

Jelly , 15 byte

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

Cobalah online!

Bagaimana itu bekerja

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 terima kasih kepada nwellnhof

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

Cobalah online!

0 menghasilkan 0, dan angka lainnya mengembalikan objek Match yang bersesuaian dengan angka yang dipisahkan oleh spasi dengan spasi tambahan di awal.

Penjelasan:

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

Cobalah online!

Berkomentar

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

Cobalah online!

Sunting: Seperti dicatat oleh @ Jules , solusi yang lebih pendek berlaku untuk Python 3.6+. Tidak ada lagi solusi berbeda untuk Python 3 / 3.6+

Edit: Pengindeksan z terlalu bertele-tele. Tanpa itu sekarang tidak ada keuntungan dalam menggunakan eval.

Sunting: Temuan yang disederhanakan jika dua elemen terakhir sudah muncul dalam urutan.

Edit: Mengubah format output dari daftar ke tuple + diganti lambda dengandef

Sunting: Kembali ke lambdatetapi disematkan tke f.

Sunting: Input nsebenarnya dapat diartikan sebagai kepala koleksi tumbuh zyang akan mewakili ekor dalam pendekatan rekursif. Juga mengalahkan solusi @ Arbo lagi.

Sunting: Sebenarnya Anda dapat membongkar dua item dari kepala yang memotong 16 byte lainnya.

Sunting: Sebenarnya 17 byte.

Sunting: Seperti dicatat oleh @ solusi Arbo memberi jawaban untuk 14dan 59kasus karena mereka dalam kasus uji awal yang terbukti kemudian salah. Untuk saat ini ini tidak terlalu pendek tetapi setidaknya berfungsi dengan benar.


Cukup penyalahgunaan f-stringsdan eval. Kode ungolfed asli walaupun saya menduga itu bisa dilakukan dengan lebih mudah:

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
Koreksi kecil: ini Python 3.6+. Ini jelas tidak akan bekerja di 3,5 atau lebih tua.
0xdd

1
Kode pengujian Anda tampaknya tidak berfungsi; input 59hasil(14, 5, 9)
ArBo

Saya melihat bahwa test case telah berubah sejak saya memulai tantangan jadi itu sebabnya ada output yang salah. Saya telah mengubah solusi saya agar berfungsi tetapi untuk saat ini tidak terlalu pendek. Namun demikian terima kasih telah menunjukkannya.
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;);}

Cobalah online!

-3 dari ceilingcat

Termasuk ruang tambahan.

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...whiletidak perlu kawat gigi jika itu adalah satu pernyataan O_o
ASCII-satunya


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)

Cobalah online!

Hardcoded sepertinya yang terpendek mengingat Python sudah memiliki jawaban 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

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

Cobalah online!

Program ini membangun tuple pdari semua pasangan 2-nilai yang telah terjadi dalam urutan, yang diinisialisasi dengan junk untuk menyimpan beberapa byte. Urutan itu sendiri dibangun di tuple l, dan dua elemen terakhir dari tuple ini disimpan dalam buntuk referensi yang mudah (dan pendek). Begitu mengulang ditemukan, kita dapat melihat indeks bdi ptahu di mana loop dimulai.

EDIT: Membersihkan ini sedikit, dan memotong satu byte lagi ... Metode saya tampaknya mendekati batas jumlah byte, dan saya benar-benar harus berhenti bekerja pada ini.


1

Arang , 46 byte

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

Cobalah online! Tautan adalah untuk mengucapkan versi kode. Penjelasan:

≔E◧S²Σιθ

Masukkan nomor, gabungkan menjadi 2 karakter, lalu ambil jumlah digital setiap karakter, dan simpan daftar yang dihasilkan.

W¬υ

Ulangi saat daftar loop kosong.

⊞OθΣ…⮌⪫θω²

Hitung jumlah dari dua digit sebelumnya dan tambahkan ke daftar Fibonacci.

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

Ambil semua sufiks nontrivial dari daftar.

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

Saring yang tidak berulang dan simpan hasilnya di daftar loop.

Iυ

Keluarkan daftar loop ke string dan cetak.


1

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

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

Cobalah online!

Mengharapkan bilangan bulat non-negatif sebagai input. Bytecount lebih kecil, tetapi kemungkinan tidak akan lagi berfungsi untuk bilangan bulat> 99.

Penjelasan:

# 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]
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.