Fibonacci Digits ที่ซ้ำกันคืออะไร


30

อย่างที่คุณอาจทราบหมายเลข Fibonacci เป็นหนึ่งซึ่งเป็นผลรวมของตัวเลขสองตัวก่อนหน้าในชุด

Fibonacci Digit ™เป็นหนึ่งซึ่งเป็นผลรวมของทั้งสองก่อนหน้านี้ตัวเลข

ตัวอย่างเช่นสำหรับชุดเริ่มต้น1,1ชุดจะเป็นการ1,1,2,3,5,8,13,4,7,11,2...เปลี่ยนแปลงเกิดขึ้นหลังจาก13ที่แทนที่จะเพิ่มคุณเพิ่ม8+13 1+3ซีรีส์วนซ้ำในตอนท้ายที่ไหน4+7=11และ1+1=2เช่นเดียวกับซีรีย์เริ่ม

สำหรับตัวอย่างอื่นชุดเริ่มต้น2,2: 2,2,4,6,10,1,1,2,3,5,8,13,4,7,11,2,3.... อันนี้เริ่มต้นที่ไม่ซ้ำกัน แต่เมื่อตัวเลขรวมถึง10คุณจบลงด้วย1+0=1, 0+1=1และซีรีส์ยังคง - และลูป - แบบเดียวกับที่1,1ซีรีส์ทำ


ความท้าทาย

กำหนดอินพุตจำนวนเต็ม0≤n≤99คำนวณลูปในซีรีส์ Fibonacci Digit ที่ขึ้นต้นด้วยตัวเลขสองหลัก (คุณเป็นอย่างแน่นอนได้รับอนุญาตที่จะต้องพิจารณาจำนวนเต็มออกจากช่วงนี้ แต่ก็ไม่จำเป็นต้อง.) 0,nหากได้รับการป้อนข้อมูลหนึ่งหลักบาทรหัสของคุณควรตีความมันเพื่อแสดงถึงการเริ่มต้นซีรีส์

ตัวเลขทั้งหมดในลูปที่เป็นตัวเลขสองหลักจะต้องแสดงผลลัพธ์เป็นตัวเลขสองหลัก ดังนั้นสำหรับตัวอย่างเช่นห่วงสำหรับ1,1จะมีไม่ได้131,3

เอาต์พุตเริ่มต้นด้วยหมายเลขแรกในลูป ดังนั้นตามข้อ จำกัด ข้างต้นลูปสำหรับการ1,1เริ่มต้นด้วย2ตั้งแต่1,1และ11ถูกนับแยก

แต่ละเอาต์พุตอาจถูกคั่นด้วยสิ่งที่คุณต้องการตราบใดที่มันสอดคล้องกัน ในตัวอย่างทั้งหมดของฉันฉันใช้เครื่องหมายจุลภาค แต่อนุญาตให้เว้นวรรคการแบ่งบรรทัดตัวอักษรแบบสุ่ม ฯลฯ ได้ตราบใดที่คุณใช้การแยกแบบเดียวกัน ดังนั้น2g3g5g8g13g4g7g11ผลลัพธ์ทางกฎหมายสำหรับ1คือ2j3g5i8s13m4g7sk11ไม่ใช่ คุณสามารถใช้สตริงรายการอาร์เรย์สิ่งใดก็ตามโดยที่คุณมีหมายเลขที่ถูกต้องในลำดับที่ถูกต้องโดยคั่นด้วยตัวคั่นที่สอดคล้องกัน ถ่ายคร่อมเอาท์พุตทั้งหมดได้เช่นกัน (เช่น(5,9,14)หรือ[5,9,14]ฯลฯ )

กรณีทดสอบ:

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

นี่คือดังนั้นจำนวนไบต์ต่ำที่สุดจึงเป็นผู้ชนะ


1
เราสามารถใช้ตัวเลข 2 หลักเป็น input แทน ? 0n99
Arnauld

1
ในขณะที่ใช้สองอินพุทมากกว่าหนึ่งอินพุทที่แยก? ไม่ได้
DonielF

ฉันยังไม่เข้าใจว่าทำไม14และ59ให้ผลลัพธ์เดียวกัน หาก59ถูกตีความว่าเป็นการเริ่มต้น5,9และการอนุญาตให้เป็นส่วนหนึ่งของการวนซ้ำแน่นอนว่า14ควรเป็นการเริ่มต้นของการวนรอบ
Neil

1
@williamporter 0,1,1,2,3,5,8,13,4,7,11,2,3จุดเริ่มต้นของลำดับคือ 2ในครั้งแรกที่วงซ้ำที่สอง
DonielF

2
@Neil จุดเริ่มต้นของลำดับที่เกี่ยวข้องเหล่านั้นและ1,4,5,9,14,5 ทั้งของพวกเขาเริ่มต้นด้วยซ้ำสอง5,9,14,5,9 5อย่างที่ฉันพูดไปก่อนหน้านี้เฉพาะอินพุตจะถูกแยกออก ตัวเลขที่ตามมาจะเก็บตัวเลขไว้ด้วยกันตามลำดับ
DonielF

คำตอบ:


10

เยลลี่ 15 ไบต์

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

ลองออนไลน์!

มันทำงานอย่างไร

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 ไบต์

-3 ไบต์ขอบคุณ nwellnhof

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

ลองออนไลน์!

0 ส่งคืนค่า 0 และหมายเลขอื่น ๆ ส่งคืนวัตถุการจับคู่ซึ่งทำให้เกิดตัวเลขที่คั่นด้วยช่องว่างที่มีช่องว่างนำหน้า

คำอธิบาย:

{                                                                         }   # 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 ไบต์

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)

ลองออนไลน์!

แสดงความคิดเห็น

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 ไบต์

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

ลองออนไลน์!

แก้ไข: ตามที่บันทึกไว้โดย @ Julesโซลูชันที่สั้นกว่าจะใช้กับ Python 3.6+ไม่มีวิธีที่แตกต่างสำหรับ Python 3 / 3.6+ อีกต่อไป

แก้ไข: การสร้างดัชนีของzมีรายละเอียดมากเกินไป หากปราศจากตอนนี้ก็จะไม่มีประโยชน์ในการใช้งานevalโดยไม่ว่าตอนนี้มีกำไรในการใช้ไม่มี

แก้ไข: การค้นหาแบบง่ายหากองค์ประกอบสองรายการสุดท้ายปรากฏในลำดับ

แก้ไข: เปลี่ยนรูปแบบเอาต์พุตจากรายการเป็น tuple + แทนที่ lambdaด้วยdef

แก้ไข: กลับไปlambdaแต่ฝังตัวเข้าไปในtf

แก้ไข: อินพุตnสามารถตีความได้ว่าเป็นหัวหน้าของคอลเลกชันที่เพิ่มขึ้นzซึ่งจะเป็นตัวแทนของหางในวิธีแบบเรียกซ้ำ รวมทั้งแก้ปัญหาของเต้น @ Arboอีกครั้ง

แก้ไข: จริง ๆ แล้วคุณสามารถนำสินค้าสองชิ้นออกจากส่วนหัวซึ่งจะตัดอีก 16 ไบต์

แก้ไข: จริง 17 ไบต์

แก้ไข: ตามที่บันทึกไว้โดย @ Arboวิธีการแก้ปัญหาได้ให้คำตอบ14และ59กรณีที่พวกเขาอยู่ในกรณีทดสอบเริ่มต้นซึ่งได้รับการพิสูจน์แล้วว่าผิด สำหรับตอนนี้มันไม่สั้น แต่อย่างน้อยก็ทำงานได้อย่างถูกต้อง


ค่อนข้างละเมิดของและf-strings evalรหัส ungolfed ดั้งเดิมแม้ว่าฉันสงสัยว่ามันสามารถทำได้ง่ายขึ้น:

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
การแก้ไขเล็กน้อย: นี่คือ Python 3.6+ สิ่งนี้จะไม่สามารถใช้งานได้ใน 3.5 ปีขึ้นไป
0xdd

1
รหัสทดสอบของคุณดูเหมือนจะไม่ทำงาน อินพุตของ59อัตราผลตอบแทน(14, 5, 9)
ArBo

ฉันเห็นว่ากรณีทดสอบมีการเปลี่ยนแปลงตั้งแต่ฉันเริ่มต้นความท้าทายดังนั้นนั่นเป็นสาเหตุที่มีผลลัพธ์ไม่ถูกต้อง ฉันเปลี่ยนวิธีแก้ปัญหาของฉันเพื่อให้ใช้งานได้ แต่ตอนนี้ยังไม่สั้น อย่างไรก็ตามขอบคุณสำหรับการชี้ให้เห็นว่า
ชิโอกะ

4

C (gcc) , 114 112 109 ไบต์

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

ลองออนไลน์!

-3 จากCeilingcat

รวมถึงพื้นที่ต่อท้าย

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...whileไม่ต้องการวงเล็บปีกกาถ้ามันเป็นคำสั่งเดียว O_o
ASCII เท่านั้น


2

Java (JDK) , 194 ไบต์

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

ลองออนไลน์!

Hardcoded ดูเหมือนว่าจะสั้นที่สุดเนื่องจาก Python มีคำตอบที่ 187 ...


2

Haskell, 100 ไบต์

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

ลองออนไลน์!

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 ไบต์

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]

ลองออนไลน์!

โปรแกรมสร้างค่า tuple pของคู่ค่า 2 ทั้งหมดที่เกิดขึ้นในลำดับซึ่งถูกกำหนดค่าเริ่มต้นด้วยขยะเพื่อบันทึกบางไบต์ ลำดับตัวเองได้รับการสร้างขึ้นใน tuple lและสององค์ประกอบสุดท้ายของ tuple นี้จะถูกเก็บไว้ในbการอ้างอิง (และสั้น) ง่าย เร็วที่สุดเท่าที่ซ้ำพบว่าเราสามารถดูดัชนีของbในpที่จะทราบว่าห่วงที่จะเริ่มต้น

แก้ไข: ทำความสะอาดสิ่งนี้สักหน่อยและกำจัดไบต์อีกหนึ่งอัน ... วิธีการของฉันดูเหมือนจะใกล้ถึงขีด จำกัด จำนวนไบต์แล้วและฉันควรหยุดทำงานในเรื่องนี้


1

ถ่าน 46 ไบต์

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

ลองออนไลน์! การเชื่อมโยงคือการใช้รหัสเวอร์ชันอย่างละเอียด คำอธิบาย:

≔E◧S²Σιθ

ใส่ตัวเลขแล้ววางไว้ที่ 2 ตัวอักษรจากนั้นนำผลรวมดิจิตอลของแต่ละตัวอักษรและบันทึกรายการผลลัพธ์

W¬υ

ทำซ้ำในขณะที่รายการของลูปว่างเปล่า

⊞OθΣ…⮌⪫θω²

คำนวณผลรวมของตัวเลขสองหลักก่อนหน้าและเพิ่มลงในรายการฟีโบนักชี

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

ใช้คำต่อท้ายที่ไม่สำคัญทั้งหมดของรายการ

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

กรองสิ่งที่ไม่ทำซ้ำและบันทึกผลลัพธ์ในรายการลูป

Iυ

โยนรายการของลูปเป็นสตริงและพิมพ์



1

Python 2 , 149 139 ไบต์

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]

ลองออนไลน์!

คาดหวังว่าเป็นจำนวนเต็มไม่เป็นลบ จำนวนน้อยลง แต่มีแนวโน้มว่าจะไม่ทำงานสำหรับจำนวนเต็ม> 99 อีกต่อไป

คำอธิบาย:

# 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]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.