Цифрова сума Фібоначчі


30

Всі ми знайомі з послідовністю Фібоначчі :

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765

Однак замість цього f(n) = f(n-1) + f(n-2)ми візьмемо цифрову суму попередніх 2 записів.


Послідовність все-таки повинна починатися з цього 0, 1, після чого відмінності швидко виявляються. Цей список 0-індексований, ви також можете використовувати 1-індексований стан, який ви використовували.

f(0)  = 0
f(1)  = 1
f(2)  = 1   # 0 + 1
f(3)  = 2   # 1 + 1
f(4)  = 3   # 1 + 2
f(5)  = 5   # 2 + 3
f(6)  = 8   # 3 + 5
f(7)  = 13  # 8 + 5
f(8)  = 12  # 8 + 1 + 3
f(9)  = 7   # 1 + 3 + 1 + 2
f(10) = 10  # 1 + 2 + 7
f(11) = 8   # 7 + 1 + 0
f(12) = 9   # 1 + 0 + 8
f(13) = 17  # 8 + 9
f(14) = 17  # 9 + 1 + 7
f(15) = 16  # 1 + 7 + 1 + 7
f(16) = 15  # 1 + 7 + 1 + 6
f(17) = 13  # 1 + 6 + 1 + 5
f(18) = 10  # 1 + 5 + 1 + 3
f(19) = 5   # 1 + 3 + 1 + 0
f(20) = 6   # 1 + 0 + 5
f(21) = 11  # 5 + 6
f(22) = 8   # 6 + 1 + 1
f(23) = 10  # 1 + 1 + 8
f(24) = 9   # 8 + 1 + 0
f(25) = 10  # 1 + 0 + 9
f(26) = 10  # 9 + 1 + 0
f(27) = 2   # 1 + 0 + 1 + 0
(After this point it repeats at the 3rd term, 0-indexed)

Примітка: я не помітив повторення, поки не опублікував сам виклик, і тут я подумав, що неможливо написати ще один роман «Виклик Фібоначчі».


Ваше завдання - задане число n, вивести n-ту цифру цієї послідовності.

Перші 3 цифри: [0,1,1],

24-значний повторний зразок: [2,3,5,8,13,12,7,10,8,9,17,17,16,15,13,10,5,6,11,8,10,9,10,10]

Підказка: Ви можете використати це повторення на свою користь.


Це , найнижчий байт - переможець.


БОНУС: Якщо ви використовуєте повторення у своїй відповіді, я присуджую найнижчу відповідь підрахунку байтів, яка використовує перевагу повторення в послідовності, в розмірі 100 балів. Це слід подати як частину оригінальної відповіді після оригінальної відповіді. Дивіться цей пост як приклад того, про що я говорю: https://codegolf.stackexchange.com/a/108972/59376

Щоб отримати право на цей бонус, ваш код повинен працювати постійно ( O(1)) з поясненням.

Переможець бонусів: Dennis https://codegolf.stackexchange.com/a/108967/59376 <Dennis win.

Найунікальніша реалізація: https://codegolf.stackexchange.com/a/108970/59376
(Також отримає 100 балів, доопрацьовані після обрання правильної відповіді)


2
Чи можемо ми використовувати індексацію на основі 1 або це має бути на основі 0?
Ділова кішка

1
@BusinessCat Так, звичайно, накрутити.
Чарівний восьминіг Урна

1
Як Ви визначаєте, чи використовує перевагу повторення ? Чи потрібно це бути жорстко закодованим або я просто додати %24«нормальне» рішення?
Денніс

1
@Dennis Я визначаю, як скористатися повторенням O(1). Ваш код повинен працювати постійно, якщо він справді використовує повторення.
Magic Octopus Urn

1
@Dennis технічно% 24 на вході зробить його верхньою межею при 27 ітераціях; в той час, як не цікаво, воно напевно рахується.
Чарівний восьминога Урна

Відповіді:



28

JavaScript (ES6), 45 байт

f=(n,x=0,y=1)=>n?f(n-1,y,(x%9||x)+(y%9||y)):x
<input type=number min=0 oninput=o.textContent=f(this.value)><pre id=o>

xі yне може бути обома 9, оскільки це вимагатиме попереднього числа 0, тому їх цифрова сума не може перевищувати 17. Це означає, що цифровий корінь для чисел, більших за 9той самий, що і решту модулів 9.


6
Це також отримає щедрий еквівалент лідеру повторень ... Це дивовижне математичне розуміння.
Magic Octopus Urn

13

Python 2, 53 байти

f=lambda n:n>1and sum(map(int,`f(n-1)`+`f(n-2)`))or n

Рекурсивна функція. У базових випадках n=0і n=1прибутковості nбільші числа обчислюють значення, викликаючи f(n-1)та f(n-2)перетворюючи кожну в рядок, об'єднуючи два рядки, перетворюючи кожен символ у ціле число за mapдопомогою intфункції, а потім підсумовуємо отриманий список.


Використовуючи інформацію модуля-24, в даний момент я можу отримати 56-байтну нерекурсивну неназвану функцію:

lambda n:int(('011'+'2358dc7a89hhgfda56b8a9aa'*n)[n],18)

1
Так! Стільки +1! Відповідь на повторення :). Я додав розділ про бонуси на вашу честь, сер, тепер ви лідер у конкурсі на 100 балів!
Чарівний восьминіг урна

11

JavaScript (ES6), 34 байти

f=n=>n<2?n:~-f(--n)%9+~-f(--n)%9+2

Може заморозити ваш веб-переглядач для даних, що перевищують 27 або більше, але він працює для всіх вхідних значень. Це можна перевірити за допомогою простого кеша:

c=[];f=n=>n<2?n:c[n]=c[n]||~-f(--n)%9+~-f(--n)%9+2
<input type=number value=0 min=0 step=1 oninput="O.value=f(this.value)"> <input id=O value=0 disabled>

Як вказувалося в блискучій відповіді Ніла , вихід ніколи не може перевищувати 17, тому цифрова сума будь-якого виходу вище 9 дорівнює n%9. Це також працює з виходами нижче 9; ми можемо змусити його працювати і для 9, віднімаючи 1 з ~-до модуля, а потім додаючи ще 1 через.


Найкраще, що я міг зробити із жорстким кодуванням, - це 50 байт:

n=>"0x"+"7880136ba5867ffedb834968"[n%24]-(n<3)*9+2

6

Желе , 8 байт

;DFS
ç¡1

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

Як це працює

ç¡1   Main link. No arguments. Implicit left argument: 0

  1   Set the right argument to 1.
ç¡    Repeatedly execute the helper link n times – where n is an integer read from
      STDIN – updating the left argument with the return value and the right
      argument with the previous value of the left argument. Yield the last result.


;DFS  Helper link. Arguments: a, b

;     Concatenate; yield [a, b].
 D    Decimal; convert both a and b to their base-10 digit arrays.
  F   Flatten the result.
   S  Compute the sum of the digits.

Черговий розчин, 19 байт, постійний час

;DFS
9⁵ç23С⁸ịµṠ>?2

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

Як це працює

9⁵ç23С⁸ịµṠ>?2  Main link. Argument: n

9               Set the return value to 9
 ⁵              Yield 10.
  ç23С         Execute the helper link 23 times, with initial left argument 10
                and initial right argument 9, updating the arguments as before.
                Yield all intermediate results, returning
                [10,10,2,3,5,8,13,12,7,10,8,9,17,17,16,15,13,10,5,6,11,8,10,9].
   ⁸ị           Extract the element at index n. Indexing is 1-based and modular.
     µ          Combine all links to the left into a chain.
       >?2      If n > 2, execute the chain.
      Ṡ         Else, yield the sign if n.

1
+1 для чутливості "давайте просто обчислимо весь повторний розділ за постійний час": D
Фелікс Домбек

4

JavaScript (ES6), 52 46 45 байт

_=$=>$<2?$:eval([..._(--$)+[_(--$)]].join`+`)

Використання

_=$=>$<2?$:eval([..._(--$)+[_(--$)]].join`+`)
_(7)

Вихідні дані

13

Пояснення

Ця функція перевіряє, чи вхід менший за 2, і якщо так, він повертає вхід. В іншому випадку він створює масив з двох значень, які додаються один до одного як рядки. Ці два значення є результатом виклику функції за допомогою input - 1і input - 2.

...Оператор розбиває цей рядок в масив символів, який потім перетворюється в рядок ще раз, але тепер з +ес між значеннями. Потім цей рядок інтерпретується як код, тому обчислюється сума, яка потім повертається.

Це подвійний рекурсивний алгоритм, який робить його досить неефективним. n-2Для введення потрібно 2 виклики функцій n. Отже, ось довше, але швидше рішення. Завдяки ETHproductions за те, що придумали.

f=($,p=1,c=0)=>$?f($-1,c,eval([...p+[c]].join`+`)):c

Це не працює для великих значень, таких як 27, він заморожує браузер (принаймні, це для мене)
Kritixi Lithos

Проходить якийсь час, але він дістанеться ... врешті-решт. Я вивчу це, але ефективність не важлива для цього виклику ...
Люк

Ну, Ісусе, це не так обчислювально обчислювально, твоя програма повинна працювати на значення понад 27 ... Але якщо вона працює на 1-28, це технічно доводить, що вона працює і на вищі.
Чарівний восьминіг урна

1
@KritixiLithos Проблема полягає в рекурсії. Обчислення n- го числа в послідовності вимагає приблизно 2 ^ (n-2) викликів функції, яка наростає досить швидко.
ETHproductions

Ви можете зберегти байт за допомогою [..._(--$)+[_(--$)]]:-)
ETHproductions


3

CJam, 22 20 байт

Збережено 2 байти завдяки Мартіну Ендеру

ri2,{(_(jAb\jAb+:+}j

Прямий рекурсивний алгоритм, нічого фантазійного. 0-індексований.

Спробуйте в Інтернеті! або тест на 0-50 (насправді працює досить швидко).

Пояснення

ri                    Read an integer from input
  2,                  Push the array [0 1]
    {             }j  Recursive block, let's call it j(n), using the input as n and [0 1] as base cases
     (                 Decrement (n-1)
      _(               Duplicate and decrement again (n-2)
        jAb            Get the list digits of j(n-2)
           \           Swap the top two elements
            jAb        Get the list of digits of j(n-1)
               +       Concatenate the lists of digits
                :+     Sum the digits

CJam, 42 байти

Розв’язання за допомогою повторення. Аналогічний алгоритм рішення Джонатана Аллана.

ri_2,1+"[2358DC7A89HHGFDA56B8A9AA]"S*~@*+=

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


3

Perl 6 ,  41  37 байт

{(0,1,{[+] |$^a.comb,|$^b.comb}...*)[$_]}

Спробуй це

{(0,1,*.comb.sum+*.comb.sum...*)[$_]}

Спробуй це

{ # bare block lambda with implicit parameter 「$_」
  (

    0, 1,           # first two values

    # WhateverCode lambda with two parameters ( the two 「*」 )
    *.comb.sum      # digital sum of first parameter
    +
    *.comb.sum      # digital sum of second parameter

    ...            # keep using that code object to generate new values until:

    *              # never stop

  )[ $_ ]          # index into the sequence
}

1
Ви можете написати внутрішню лямбда як *.comb.sum+*.comb.sum.
smls

2

MATL , 15 байт

lOi:"yyhFYAss]&

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

lO       % Push 1, then 0. So the next generated terms will be 1, 1, 2,... 
i        % Input n
:"       % Repeat that many times
  yy     %   Duplicate top two elements in the stack
  h      %   Concatenate into length-2 horizontal vector
  FYA    %   Convert to decimal digits. Gives a 2-row matrix
  ss     %   Sum of all matrix entries
]        % End
&        % Specify that next function (display) will take only 1 input
         % Implicit display


2

C, 96 байт

або 61 байт, рахуючи коди евакуації як 1 байт

0 індексовано. Як і деякі інші відповіді, я індексую таблицю пошуку значень, але я стиснув її до 4-х байтних фрагментів. Я не переймався дослідженням версії mod 24, тому що не вважав, що це так цікаво, оскільки інші вже зробили це, але давайте зіткнемося з цим, C все одно не виграє.

#define a(n) n<3?!!n:2+(15&"\x1\x36\xba\x58\x67\xff\xed\xb8\x34\x96\x87\x88"[(n-3)/2%12]>>n%2*4)

пояснення:

#define a(n)                                                                                     // using a preprocessor macro is shorter than defining a function
             n<3?!!n:                                                                            // when n is less than 3 !!n will give the series 0,1,1,1..., otherwise..
                                                                             (n-3)/2%12          // condition the input to correctly index the string...
                           "\x1\x36\xba\x58\x67\xff\xed\xb8\x34\x96\x87\x88"                     // which has the repeating part of the series encoded into 4 bits each number
                                                                                                 // these are encoded 2 less than what we want as all numbers in the series after the third are 2 <= a(n>2) <= 17 which conforms to 0 <= a(n>2) - 2 <= 15
                                                                                        >>n%2*4  // ensure the data is in the lower 4 bits by shifting it down, n%2 will give either 0 or 1, which is then multiplied by 4
                        15&                                                                      // mask those bits off
                     2+                                                                          // finally, add 2 to correct the numbers pulled from the string

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


Я рахую коди втечі як 1 байт кожен! Чудова робота
Альберт Реншо



2

Математика, 49 байт

If[#<2,#,Tr[Join@@IntegerDigits[#0/@{#-1,#-2}]]]&

Пряме рекурсивне визначення. Через деякий час виходить досить повільним.

Математика, 79 71 байт

If[#<3,Sign@#,(9@@LetterNumber@"JJBCEHMLGJHIQQPOMJEFKHJ")[[#~Mod~24]]]&

Жорстке кодування періодичної картини. Блискавка швидко і задовільно зловживає Mathematica :) Дякую JungHwan Min за економію 8 байт!


Для вашого другого коду LetterNumber@"JJBCEHMLGJHIQQPOMJEFKHJ"на 8 байт коротше 43626804920391712116157158790~IntegerDigits~18.
JungHwan Мін

ти правий! Одного дня я пам’ятаю LetterNumber
Грег Мартін

1

Пітон 2 , 56 байт

Просте ітеративне рішення.

a,b=0,1
exec'a,b=b,(a%9or a)+(b%9or b);'*input()
print a

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

Використання (a%9or a)+(b%9or b)насправді виявилося коротшим, ніж sum(map(int(`a`+`b`)))!


Я думаю, ти маєш на увазі sum(map(int,a+b))(не можу зрозуміти, як використовувати `у коментарях)

1

PowerShell , 79 байт

$b,$c=0,1;for($a=$args[0];$a;$a--){$z=[char[]]"$b$c"-join'+'|iex;$b=$c;$c=$z}$b

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

Тривале нудне ітеративне рішення, яке робить прямі обчислення цифр у кожній forпетлі. Наприкінці циклу потрібне число, яке ми хочемо $b, тож, що залишилося на конвеєрі, а вихід непрямий. Зауважте, що якщо вхід є 0, то цикл не буде входити, оскільки умовна помилка, так і $bзалишається 0.


1

Пакет, 85 байт

@set/ax=0,y=1
@for /l %%i in (1,1,%1)do @set/az=x-x/10*9+y-y/10*9,x=y,y=z
@echo %x%

Мені було цікаво, як я збираюся переслати свою відповідь JavaScript на пакетну, але підказка була у рішенні Python @ Dennis.


1

Pyth, 20 байт

J,01VQ=+JssjRT>2J)@J

Програма, яка приймає введення нульового цілого числа та друкує результат.

Тестовий набір (перша частина для форматування)

Як це працює

[Пояснення, що надходить пізніше]


1

Рубін, 58 байт

->n{n<3?n<=>0:"9aa2358dc7a89hhgfda56b8a"[n%24].to_i(18)}

Просте жорстке рішення.



1

Октава, 148 байт

function f = fib(n)
  if (n <= 1)
    f = n;
  else
    f = sum(int2str((fib(n - 1)))-48) + sum(int2str((fib(n - 2)))-48);
  endif
endfunction

Ласкаво просимо в ppcg! Гарний перший пост!
Rɪᴋᴇʀ

1

Haskell, 151 байт

import Numeric
import Data.Char
s i=foldr(\c i->i+digitToInt c)0$showInt i""
d a b=a:d b(s a+s b)
f 0=0
f 1=1
f 2=1
f i=d 2 3!!fromIntegral(mod(i-3)24)

Викликати функцію за допомогою f 123456789012345678901234567890123456789012345678 , наприклад.

Код також працює з дуже великими показниками. Через реалізовану функціональність модуля 24 це дуже швидко.

Нестиснений код:

-- FibonacciDigital
-- Gerhard
-- 13 February 2017

module FibonacciDigital () where

import Numeric
import Data.Char

-- sum of digits
digitSum :: Int -> Int 
digitSum i = foldr (\c i -> i + digitToInt c) 0 $ showInt i ""

-- fibonacci digital sequence function with arbitrary starting values
fibonacciDigitals :: Int -> Int -> [Int]
fibonacciDigitals a b = a : fibonacciDigitals b (digitSum a + digitSum b)

-- index -> fibonacci digital value
f :: Integer -> Int 
f 0 = 0 
f 1 = 1 
f 2 = 1 
f i = fibonacciDigitals 2 3 !! fromIntegral (mod (i-3) 24) 

-- End

0

R, 90 байт

Страшенно довге рішення, але воно краще, ніж 108, які я мав спочатку. Я підозрюю, що існує набагато кращий спосіб зробити це, але наразі я не бачу цього.

function(n,x=0:1){repeat`if`(n,{x=c(x,sum(scan(t=gsub('',' ',x))))[-1];n=n-1},break);x[1]}

Це неназвана функція, яка використовує gsubі scan(t=ділити числа у векторі на цифри. Сума їх додається до вектора під час опускання першого елемента. repeatвикористовується для кроку через послідовність nразів, і результат є першим елементом вектора.



0

Математика, 67 байт

r=IntegerDigits;f@0=0;f@1=1;f[x_]:=f@x=Tr@r@f[x-1]+Tr@r@f[x-2];f@#&
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.