Somma digitale Fibonacci


30

Conosciamo tutti la sequenza di Fibonacci :

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

Tuttavia, invece di, f(n) = f(n-1) + f(n-2)prenderemo la somma digitale delle precedenti 2 voci.


La sequenza dovrebbe comunque iniziare con 0, 1, dopo che le differenze sono rapidamente evidenti. Questo elenco è indicizzato 0, è possibile utilizzare anche 1 indicizzato, stato utilizzato.

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)

Nota: non ho notato la ripetizione fino a quando non ho pubblicato la sfida stessa, e qui stavo pensando che sarebbe stato impossibile scrivere un'altra nuova sfida di Fibonacci.


Alla tua attività viene assegnato un numero ne genera l'ennesima cifra di questa sequenza.

Le prime 3 cifre: [0,1,1],

Schema ripetuto a 24 cifre: [2,3,5,8,13,12,7,10,8,9,17,17,16,15,13,10,5,6,11,8,10,9,10,10]

Suggerimento: potresti essere in grado di sfruttare questa ripetizione a tuo vantaggio.


Questo è , il conteggio di byte più basso è il vincitore.


BONUS: Se usi la ripetizione nella tua risposta, assegnerò alla risposta di conteggio byte più bassa che sfrutta la ripetizione nella sequenza un premio di 100 punti. Questo dovrebbe essere inviato come parte della risposta originale, dopo la risposta originale. Vedi questo post come esempio di ciò di cui sto parlando: https://codegolf.stackexchange.com/a/108972/59376

Per beneficiare di questo bonus, il codice deve essere eseguito a tempo costante ( O(1)) con una spiegazione.

Vincitore del bonus: Dennis https://codegolf.stackexchange.com/a/108967/59376 <Dennis ha vinto.

Implementazione più unica: https://codegolf.stackexchange.com/a/108970/59376
(Inoltre riceverà 100 punti, finalizzato dopo aver scelto la risposta corretta)


2
Possiamo usare l'indicizzazione basata su 1 o deve essere basata su 0?
Business Cat

1
@BusinessCat sì, certo, fanculo.
Magic Octopus Urn

1
Come si definisce sfrutta la ripetizione ? Deve essere hardcoded o aggiungo semplicemente %24a una soluzione "normale"?
Dennis,

1
@Dennis lo definisco approfittando della ripetizione per dire O(1). Il tuo codice dovrebbe essere in esecuzione a tempo costante, se sta sfruttando veramente la ripetizione.
Magic Octopus Urn,

1
@Dennis tecnicamente% 24 sull'input renderebbe il limite superiore a 27 iterazioni; mentre, non interessante, conta sicuramente.
Magic Octopus Urn

Risposte:


7

Oasi , 5 byte

Codice:

ScS+T

Provalo online!

Versione estesa:

ScS+10

Spiegazione:

ScS+   = a(n)
     0 = a(0)
    1  = a(1)
S      # Sum of digits on a(n-1)
 c     # Compute a(n-2)
  S    # Sum of digits
   +   # Add together

Oh amico ... Comincerò anche a imparare gli Oasis.
Magic Octopus Urn

28

JavaScript (ES6), 45 byte

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>

xe ynon possono essere entrambi 9, poiché ciò richiederebbe che il numero precedente fosse 0, quindi la loro somma digitale non può superare 17. Ciò significa che la radice digitale per numeri maggiori di 9è la stessa del modulo rimanente 9.


6
Questo, anche questo otterrà una taglia equivalente al leader della ripetizione ... Questa è una fantastica intuizione matematica.
Magic Octopus Urn

13

Python 2, 53 byte

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

Funzione ricorsiva. I casi base di n=0e n=1cedono n, numeri più grandi calcolano il valore chiamando f(n-1)e f(n-2)convertendo ciascuno in una stringa, concatenando le due stringhe, convertendo ciascun carattere in un numero intero usando a mapcon la intfunzione e quindi sommando l'elenco risultante.


Utilizzando le informazioni del modulo 24 attualmente posso ottenere una funzione senza nome non ricorsiva a 56 byte:

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

1
Sì! Tanto +1! Una risposta ripetitiva :). Ho aggiunto una sezione bonus in tuo onore, signore, ora sei il leader in un concorso di taglie da 100 punti!
Magic Octopus Urn,

11

JavaScript (ES6), 34 byte

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

Può bloccare il browser per input superiori a 27 o giù di lì, ma funziona con tutti i valori di input. Questo può essere verificato con una semplice cache:

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>

Come sottolineato nella brillante risposta di Neil , l'output non può mai superare 17, quindi la somma digitale di qualsiasi output superiore a 9 è uguale a n%9. Questo funziona anche con output inferiori a 9; possiamo farlo funzionare anche per 9 sottraendo 1 con~- prima del modulo, quindi aggiungendolo di nuovo in 1 dopo.


Il meglio che potrei fare con hardcoding è di 50 byte:

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

6

Gelatina , 8 byte

;DFS
ç¡1

Provalo online!

Come funziona

ç¡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.

Soluzione alternativa, 19 byte, tempo costante

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

Provalo online!

Come funziona

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 per il chuzpe di "calcoliamo l'intera sezione ripetuta in tempo costante": D
Felix Dombek,

4

JavaScript (ES6), 52 46 45 byte

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

uso

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

Produzione

13

Spiegazione

Questa funzione controlla se l'ingresso è inferiore a 2 e, in tal caso, restituisce l'ingresso. Altrimenti, crea una matrice di due valori che vengono aggiunti l'uno all'altro come stringhe. Questi due valori sono il risultato della chiamata della funzione con input - 1e input - 2.

Il ... operatore divide questa stringa in una matrice di caratteri, che viene quindi nuovamente convertita in una stringa, ma ora con +es tra valori. Questa stringa viene quindi interpretata come codice, quindi viene calcolata la somma, che viene quindi restituita.

Questo è un algoritmo a doppia ricorsione, che lo rende abbastanza inefficiente. Ha bisogno di 2 n-2chiamate di funzione per l'input n. Pertanto, ecco una soluzione più lunga ma più rapida. Grazie a ETHproductions per averlo inventato.

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

Questo non funziona per grandi valori come 27, congela il browser (almeno per me)
Kritixi Lithos

Ci vuole del tempo, ma ci arriverà ... alla fine. Ci penserò, ma le prestazioni non sono importanti per questa sfida ...
Luca,

Bene, Gesù, non è così intenso dal punto di vista computazionale, il tuo programma dovrebbe funzionare per valori oltre i 27 ... Ma se funziona per 1-28, ciò dimostra tecnicamente che funziona per livelli più alti.
Magic Octopus Urn

1
@KritixiLithos Il problema è la ricorsione. Calcolare il n esimo numero della sequenza richiede circa 2 ^ (n-2) chiamate di funzione, che si accumula abbastanza rapidamente.
ETHproductions

Puoi salvare un byte con [..._(--$)+[_(--$)]]:-)
ETHproductions

4

05AB1E , 8 byte

XÎF‚¤sSO

Provalo online!

Spiegazione

XÎ        # push 1,0,input
  F       # input_no times do:
   ‚      # pair the top 2 elements of the stack
    ¤     # push a copy of the 2nd element to the stack
     s    # swap the pair to the top of the stack
      S   # convert to list of digits
       O  # sum

3

CJam, 22 20 byte

Salvato 2 byte grazie a Martin Ender

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

Semplice algoritmo ricorsivo, niente di speciale. 0-indicizzati.

Provalo online! o prova per 0-50 (in realtà funziona abbastanza velocemente).

Spiegazione

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 byte

Soluzione usando la ripetizione. Algoritmo simile alla soluzione di Jonathan Allan.

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

Provalo online!


3

Perl 6 ,  41  37 byte

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

Provalo

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

Provalo

{ # 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
Puoi scrivere il lambda interno come *.comb.sum+*.comb.sum.
smls

2

MATL , 15 byte

lOi:"yyhFYAss]&

Provalo online!

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 byte

o 61 byte contando i codici di escape come 1 byte ciascuno

0 indicizzato. Simile ad alcune delle altre risposte, sto indicizzando una tabella di valori di ricerca, ma l'ho compresso in blocchi di 4 byte. Non mi sono preoccupato di indagare sulla versione mod 24 perché non pensavo che fosse così interessante poiché gli altri l'hanno già fatto, ma ammettiamolo, C non vincerà comunque.

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

spiegazione:

#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

Provalo online!


Conto i codici di escape come 1 byte ciascuno! Ottimo lavoro
Albert Renshaw,

2

Japt , 27 25 byte

U<2?U:~-ß´U %9+~-ß´U %9+2

Provalo online!

Risparmiato 2 byte grazie a ETHproductions.


Ehi, grazie per aver usato Japt :-) Puoi usare ´al posto di --per salvare due byte.
ETHproductions


2

Mathematica, 49 byte

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

Definizione ricorsiva semplice. Diventa piuttosto lento dopo un po '.

Mathematica, 79 71 byte

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

Hardcoding del modello periodico. Veloci e soddisfacenti in modo soddisfacente per Mathematica :) Grazie a JungHwan Min per aver salvato 8 byte!


Per il tuo secondo codice LetterNumber@"JJBCEHMLGJHIQQPOMJEFKHJ"è di 8 byte più corto di 43626804920391712116157158790~IntegerDigits~18.
JungHwan Min

hai ragione! Uno di questi giorni lo ricorderò LetterNumber...
Greg Martin,

1

Python 2 , 56 byte

Soluzione iterativa semplice.

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

Provalo online!

L'uso in (a%9or a)+(b%9or b)realtà si è rivelato più breve di sum(map(int(`a`+`b`)))!


Penso che intendi sum(map(int,a+b))(non riesco a capire come usare `nei commenti)

1

PowerShell , 79 byte

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

Provalo online!

Lunga noiosa soluzione iterativa che dirige i calcoli della somma delle cifre per ogni forciclo. Alla fine del ciclo, il numero che vogliamo è in $b, quindi è rimasto sulla pipeline e l'output è implicito. Nota che se l'input è 0, allora il loop non entrerà poiché il condizionale è falso, quindi $brimane 0.


1

Lotto, 85 byte

@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%

Mi chiedevo come avrei portato la mia risposta JavaScript al batch, ma la chiave era nella soluzione Python di @ Dennis.


1

Pyth, 20 byte

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

Un programma che accetta l'input di un numero intero con indice zero e stampa il risultato.

Suite di test (prima parte per la formattazione)

Come funziona

[Spiegazione che verrà dopo]


1

Rubino, 58 byte

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

La semplice soluzione hardcoded.



1

Ottava, 148 byte

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

Benvenuto in ppcg! Bel primo post!
Rɪᴋᴇʀ

1

Haskell, 151 byte

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)

Richiamare la funzione con f 123456789012345678901234567890123456789012345678 , ad esempio.

Il codice funziona anche con indici molto grandi. Grazie alla funzionalità modulo 24 implementata è molto veloce.

Il codice non compresso:

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

Una soluzione orribilmente lunga, ma è migliore della 108 che avevo originariamente. Sospetto che ci sia un modo molto migliore per farlo, ma al momento non riesco a vederlo.

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

Questa è una funzione senza nome che utilizza gsube scan(t=per dividere i numeri nel vettore in cifre. La somma di questi viene aggiunta al vettore mentre il primo elemento viene eliminato. repeatviene utilizzato per scorrere i ntempi della sequenza e il risultato è il primo elemento del vettore.



0

Mathematica, 67 byte

r=IntegerDigits;f@0=0;f@1=1;f[x_]:=f@x=Tr@r@f[x-1]+Tr@r@f[x-2];f@#&
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.