Các chữ số Fibonacci lặp lại là gì?


30

Như bạn có thể biết, Số Fibonacci là một số là tổng của hai số trước đó trong chuỗi.

Một chữ số Fibonacci ™ là một số là tổng của hai chữ số trước đó .

Ví dụ, đối với chuỗi bắt đầu 1,1, chuỗi sẽ là 1,1,2,3,5,8,13,4,7,11,2...Thay đổi xảy ra sau 13, ở đâu, thay vì thêm 8+13, bạn thêm 1+3. Chuỗi vòng ở cuối, ở đâu 4+7=11, và 1+1=2giống như chuỗi bắt đầu.

Đối với một ví dụ khác, loạt bắt đầu 2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... Cái này bắt đầu một cách duy nhất, nhưng một khi các chữ số tổng hợp 10, bạn kết thúc 1+0=1, 0+1=1và chuỗi tiếp tục - và các vòng lặp - giống như cách mà 1,1chuỗi đã làm.


Các thách thức

Đưa ra một đầu vào số nguyên 0≤n≤99, tính toán vòng lặp trong chuỗi Số Fibonacci bắt đầu bằng hai chữ số đó. (Bạn chắc chắn được phép xem xét các số nguyên trong phạm vi này, nhưng không bắt buộc.) Nếu được cung cấp đầu vào một chữ số, mã của bạn sẽ diễn giải nó để biểu thị bắt đầu chuỗi 0,n.

Tất cả các số trong vòng lặp có hai chữ số phải được xuất ra dưới dạng hai chữ số. Vì vậy, ví dụ, vòng lặp cho 1,1sẽ chứa 13, không 1,3.

Đầu ra bắt đầu với số đầu tiên trong vòng lặp. Vì vậy, dựa trên các hạn chế ở trên, vòng lặp 1,1bắt đầu bằng 2, 1,111được tính riêng.

Mỗi số lượng đầu ra có thể được phân tách bằng bất cứ thứ gì bạn muốn, miễn là nó phù hợp. Trong tất cả các ví dụ của tôi, tôi sử dụng dấu phẩy, nhưng dấu cách, dấu ngắt dòng, chữ cái ngẫu nhiên, v.v ... đều được phép, miễn là bạn luôn sử dụng cùng một phân tách. Vì vậy, 2g3g5g8g13g4g7g11là một đầu ra hợp pháp cho 1, nhưng 2j3g5i8s13m4g7sk11không. Bạn có thể sử dụng chuỗi, danh sách, mảng, bất cứ điều gì, miễn là bạn có các số chính xác theo đúng thứ tự được phân tách bằng dấu phân cách nhất quán. Việc đóng khung toàn bộ đầu ra cũng được cho phép (ví dụ , (5,9,14)hoặc [5,9,14], v.v.).

Các trường hợp thử nghiệm:

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

Đây là , vì vậy số byte thấp nhất sẽ thắng.


1
Chúng ta có thể mất 2 chữ số như đầu vào, thay vì ? 0n99
Arnauld

1
Như trong, lấy hai đầu vào chứ không phải một đầu vào tách ra? Số
DonielF

Tôi vẫn không hiểu tại sao 1459đưa ra kết quả tương tự. Nếu 59được hiểu là bắt đầu 5,9và cho phép đó là một phần của vòng lặp thì chắc chắn 14nên bắt đầu vòng lặp của nó?
Neil

1
@williamporter Bắt đầu trình tự là 0,1,1,2,3,5,8,13,4,7,11,2,3. Lần đầu tiên vòng lặp lặp lại là lần thứ hai 2.
DonielF

2
@Neil Sự khởi đầu của các chuỗi tương ứng là 1,4,5,9,14,55,9,14,5,9. Cả hai lặp lại bắt đầu với lần thứ hai 5. Như tôi đã nói trước đó, chỉ có đầu vào được tách ra; các số sau giữ các chữ số của chúng với nhau trong chuỗi.
DonielF

Câu trả lời:


10

Thạch , 15 byte

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

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

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 nhờ nwellnhof

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

Hãy thử trực tuyến!

0 trả về 0 và số khác trả về một đối tượng Khớp nối với các số được phân tách bằng khoảng trắng có khoảng trắng ở cuối.

Giải trình:

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

Hãy thử trực tuyến!

Đã bình luận

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

Hãy thử trực tuyến!

Chỉnh sửa: Theo ghi nhận của @ Jules , giải pháp ngắn hơn áp dụng cho Python 3.6+. Không còn các giải pháp khác biệt cho Python 3 / 3.6+

Chỉnh sửa: Lập chỉ mục zlà quá dài dòng. Không có điều đó bây giờ không có lợi trong việc sử dụng eval.

Chỉnh sửa: Tìm kiếm đơn giản hóa nếu hai yếu tố cuối cùng đã xuất hiện trong chuỗi.

Chỉnh sửa: Đã thay đổi định dạng đầu ra từ danh sách sang tuple + thay thế lambda bằngdef

Chỉnh sửa: Quay lại lambdanhưng được nhúng tvào f.

Chỉnh sửa: Đầu vào nthực sự có thể được hiểu là người đứng đầu của bộ sưu tập đang phát triển zđại diện cho đuôi trong cách tiếp cận đệ quy. Cũng đánh bại giải pháp của @ Arbo một lần nữa.

Chỉnh sửa: Trên thực tế, bạn có thể giải nén hai mục từ đầu mà cắt thêm 16 byte.

Chỉnh sửa: Trên thực tế 17 byte.

Chỉnh sửa: Như đã lưu ý bởi giải pháp @ Arbo đã đưa ra câu trả lời cho các trường hợp 1459vì chúng là trong các trường hợp thử nghiệm ban đầu được chứng minh là sai. Bây giờ điều này không quá ngắn nhưng ít nhất nó hoạt động chính xác.


Khá lạm dụng f-stringseval. Mã không mã gốc mặc dù tôi nghi ngờ nó có thể được thực hiện bằng cách nào đó dễ dàng hơn:

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
Hiệu chỉnh nhỏ: đây là Python 3.6+. Điều này rõ ràng sẽ không hoạt động trong 3,5 hoặc cũ hơn.
0xdd

1
Mã kiểm tra của bạn dường như không hoạt động; đầu vào của 59sản lượng(14, 5, 9)
ArBo

Tôi thấy rằng các trường hợp thử nghiệm đã thay đổi kể từ khi tôi bắt đầu thử thách vì vậy đó là lý do tại sao có đầu ra không chính xác. Tôi đã thay đổi giải pháp của mình để nó hoạt động nhưng bây giờ nó không quá ngắn. Tuy nhiên, cảm ơn đã chỉ ra rằng.
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;);}

Hãy thử trực tuyến!

-3 từ trần

Bao gồm một không gian dấu.

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...whilekhông cần niềng răng nếu đó là một tuyên bố duy nhất O_o
ASCII - chỉ


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)

Hãy thử trực tuyến!

Hardcoding dường như ngắn nhất cho rằng Python đã có câu trả lời là 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

Hãy thử trực tuyến!

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]

Hãy thử trực tuyến!

Chương trình xây dựng một bộ pgồm tất cả các cặp giá trị 2 đã xảy ra trong chuỗi, được khởi tạo với rác để lưu một số byte. Trình tự được xây dựng trong bộ dữ liệu lvà hai phần tử cuối cùng của bộ dữ liệu này được lưu trữ bđể tham khảo dễ dàng (và ngắn). Ngay sau khi lặp lại được tìm thấy, chúng ta có thể tìm kiếm các chỉ số btrong pđể biết được nơi vòng lặp bắt đầu.

EDIT: Làm sạch điều này một chút và xóa đi thêm một byte ... Phương pháp của tôi dường như gần đạt giới hạn số byte của nó và tôi thực sự nên ngừng làm việc với điều này.


1

Than , 46 byte

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

Hãy thử trực tuyến! Liên kết là phiên bản dài dòng của mã. Giải trình:

≔E◧S²Σιθ

Nhập số, đệm vào 2 ký tự, sau đó lấy tổng số của từng ký tự và lưu danh sách kết quả.

W¬υ

Lặp lại trong khi danh sách các vòng lặp trống.

⊞OθΣ…⮌⪫θω²

Tính tổng của hai chữ số trước đó và thêm nó vào danh sách Fibonacci.

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

Lấy tất cả các hậu tố không cần thiết của danh sách.

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

Lọc ra những cái không lặp lại và lưu kết quả vào danh sách các vòng lặp.

Iυ

Truyền danh sách các vòng lặp thành chuỗi và in.



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]

Hãy thử trực tuyến!

Yêu cầu một số nguyên không âm làm đầu vào. Số lượng nhỏ hơn, nhưng có thể sẽ không còn hoạt động cho số nguyên> 99.

Giải trình:

# 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]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.