Які повторюються цифри Фібоначчі?


30

Як ви, мабуть, знаєте, число Фібоначчі - це число, яке є сумою попередніх двох чисел у ряді.

Цифра Фібоначчі ™ - це сума двох попередніх цифр .

Наприклад, для початку серії 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, обчисліть цикл у ряді цифр Фібоначчі, починаючи з цих двох цифр. (Вам, безумовно, дозволяється розглядати цілі числа поза цим діапазоном, але це не потрібно.) Якщо вам введено одноцифрове введення, ваш код повинен інтерпретувати його для позначення початку серії 0,n.

Усі числа в циклі, які є двоцифровими, повинні виводитися у вигляді двох цифр. Так, наприклад, цикл для 1,1містив би 13, не 1,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 цифри як вхідні дані замість 0н99 ?
Арнольд

1
Як у, візьміть два входи, а не один вхід, який розділений? Ні
ДоніельФ

Я досі не розумію, чому 14і 59даю той же результат. Якщо 59трактується як початковий5,9 і дозволяє це як частина циклу, то, безумовно, 14повинен бути початок його циклу?
Ніл

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. Як я вже говорив раніше, тільки вхід розділений; пізніші числа зберігають свої цифри разом у послідовності.
ДоніельФ

Відповіді:


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

Перл 6 , 96 78 75 байт

-3 байти завдяки nwellnhof

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

Спробуйте в Інтернеті!

0 повертає 0, а інше число повертає об'єкт Match, який вводить рядки на числа, розділені пробілом з провідним проміжним пробілом.

Пояснення:

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

Редагувати: спрощений пошук, якщо останні два елементи вже з'явилися в послідовності.

Редагувати: Змінено формат виводу зі списку на кортеж + замінено lambda наdef

Edit: Назад , lambdaале вбудований tвf .

Редагувати: Введення nможна насправді інтерпретувати як керівник зростаючої колекції, zякий би представляв хвіст у рекурсивному підході. Також б'є @ Арбо рішення .

Редагувати: насправді ви можете розпакувати два елементи з голови, які скорочують ще 16 байт.

Редагувати: насправді 17 байт.

Редагувати: Як зазначає рішення @ Arbo, було дано відповіді 14та 59випадки, коли вони були в початкових тестових випадках, які пізніше виявилися неправильними. Наразі це не так коротко, але принаймні воно працює правильно.


Досить зловживання f-stringsта eval. Оригінальний код, що не використовується для гольфу, хоча я підозрюю, що це можна зробити якось простіше:

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 від стельового кота

Включає простір.

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
так, do...whileне потрібні дужки, якщо це одне твердження O_o
лише для ASCII



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]

Спробуйте в Інтернеті!

Програма створює кортеж pусіх пар двох значень, що відбулися в послідовності, яка ініціалізується з небажаним файлом, щоб зберегти кілька байт. Сама послідовність вбудовується в кортеж l, і останні два елементи цього кортежу зберігаються bдля легкої (і короткої) довідки. Як тільки буде знайдено повтор, ми можемо шукати індексb в, pщоб знати, з чого починається цикл.

EDIT: Трохи очистив це і відголив ще один байт ... Моя методика, здається, наближається до межі кількості байтів, і я дійсно повинен припинити роботу над цим.


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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.