Digital Sum Fibonacci


30

Nous connaissons tous la séquence de Fibonacci :

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

Cependant, au lieu de, f(n) = f(n-1) + f(n-2)nous prendrons la somme numérique des 2 entrées précédentes.


La séquence doit toujours commencer 0, 1, après quoi les différences sont rapidement apparentes. Cette liste est indexée 0, vous pouvez également utiliser l'index 1, indiquez celle que vous avez utilisée.

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)

Remarque: je n'ai pas remarqué la répétition jusqu'à ce que j'aie posté le défi lui-même, et ici je pensais qu'il serait impossible d'écrire un autre défi Fibonacci.


Votre tâche consiste, en fonction d'un nombre n, à sortir le nième chiffre de cette séquence.

Les 3 premiers chiffres: [0,1,1],

Motif répété à 24 chiffres: [2,3,5,8,13,12,7,10,8,9,17,17,16,15,13,10,5,6,11,8,10,9,10,10]

Astuce: Vous pourrez peut-être exploiter cette répétition à votre avantage.


C'est le , le nombre d'octets le plus bas est le gagnant.


BONUS: Si vous utilisez la répétition dans votre réponse, je vais attribuer à la réponse de décompte d'octets la plus basse qui profite de la répétition dans la séquence une prime de 100 points. Cela devrait être soumis dans le cadre de votre réponse d'origine, après votre réponse d'origine. Voir cet article comme un exemple de ce dont je parle: https://codegolf.stackexchange.com/a/108972/59376

Pour bénéficier de ce bonus, votre code doit être exécuté en temps constant ( O(1)) avec une explication.

Gagnant du bonus: Dennis https://codegolf.stackexchange.com/a/108967/59376 <Dennis a gagné.

Implémentation la plus unique: https://codegolf.stackexchange.com/a/108970/59376
(recevra également 100 points, finalisés après avoir choisi la bonne réponse)


2
Peut-on utiliser une indexation basée sur 1 ou doit-elle être basée sur 0?
Business Cat

1
@BusinessCat oui, bien sûr, vissez-le.
Magic Octopus Urn

1
Comment définissez-vous tire parti de la répétition ? Doit-il être codé en dur ou j'ajoute juste un %24à une solution "normale"?
Dennis

1
@Dennis Je veux dire profiter de la répétition O(1). Votre code doit être exécuté en temps constant, s'il exploite vraiment la répétition.
Magic Octopus Urn

1
@Dennis techniquement% 24 sur l'entrée rendrait la limite supérieure à 27 itérations; alors que ce n'est pas intéressant, ça compte vraiment.
Magic Octopus Urn

Réponses:



28

JavaScript (ES6), 45 octets

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>

xet yne peuvent pas être les deux 9, car cela nécessiterait que le nombre précédent soit 0, donc leur somme numérique ne peut pas dépasser 17. Cela signifie que la racine numérique pour les nombres supérieurs à 9est la même que le reste modulo 9.


6
Ceci, cela obtiendra également une prime équivalente au leader de répétition ... Ceci est un aperçu mathématique impressionnant.
Magic Octopus Urn

13

Python 2, 53 octets

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

Fonction récursive. Les cas de base n=0et n=1produisent ndes nombres plus grands calculent la valeur en appelant f(n-1)et en f(n-2)convertissant chacun en une chaîne, en concaténant les deux chaînes, en convertissant chaque caractère en un entier à l'aide de a mapavec la intfonction, puis en additionnant la liste résultante.


En utilisant les informations modulo-24, je peux actuellement obtenir une fonction non récursive non nommée de 56 octets:

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

1
Oui! Tellement +1! Une réponse répétée :). J'ai ajouté une section bonus en votre honneur monsieur, vous êtes maintenant le leader d'un concours de primes de 100 points!
Magic Octopus Urn

11

JavaScript (ES6), 34 octets

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

Peut geler votre navigateur pour les entrées supérieures à 27 environ, mais cela fonctionne pour toutes les valeurs d'entrée. Cela peut être vérifié avec un simple 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>

Comme indiqué dans la brillante réponse de Neil , la sortie ne peut jamais dépasser 17, de sorte que la somme numérique de toute sortie supérieure à 9 est égale à n%9. Cela fonctionne également avec des sorties inférieures à 9; nous pouvons aussi le faire fonctionner pour 9 en soustrayant 1 avec ~-avant le module, puis en rajoutant en 1 après.


Le mieux que je puisse faire avec le codage en dur est de 50 octets:

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

6

Gelée , 8 octets

;DFS
ç¡1

Essayez-le en ligne!

Comment ça marche

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

Solution alternative, 19 octets, temps constant

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

Essayez-le en ligne!

Comment ça marche

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 pour le chuzpe de «calculons simplement toute la section répétée en temps constant»: D
Felix Dombek

4

JavaScript (ES6), 52 46 45 octets

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

Usage

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

Sortie

13

Explication

Cette fonction vérifie si l'entrée est inférieure à 2, et si c'est le cas, elle renvoie l'entrée. Sinon, il crée un tableau de deux valeurs qui sont ajoutées l'une à l'autre sous forme de chaînes. Ces deux valeurs sont le résultat de l'appel de la fonction avecinput - 1 et input - 2.

le ... opérateur divise cette chaîne en un tableau de caractères, qui est ensuite converti à nouveau en chaîne, mais maintenant avec +es entre les valeurs. Cette chaîne est ensuite interprétée comme du code, de sorte que la somme est calculée, qui est ensuite renvoyée.

Il s'agit d'un algorithme à double récursivité, ce qui le rend assez inefficace. Il a besoin de 2 n-2appels de fonction pour l'entrée n. En tant que tel, voici une solution plus longue mais plus rapide. Merci à ETHproductions de l'avoir proposé.

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

Cela ne fonctionne pas pour les grandes valeurs comme 27, cela fige le navigateur (du moins c'est le cas pour moi)
Kritixi Lithos

Cela prend du temps, mais ça y arrivera ... finalement. Je vais y jeter un œil, mais les performances ne sont pas importantes pour ce défi ...
Luke

Eh bien, Jésus, ce n'est pas si intense en termes de calcul, votre programme devrait fonctionner pour des valeurs au-delà de 27 ... Mais si cela fonctionne pour 1-28, cela prouve techniquement qu'il fonctionne pour plus.
Magic Octopus Urn

1
@KritixiLithos C'est la récursivité qui est le problème. Le calcul du n ème nombre dans la séquence nécessite environ 2 ^ (n-2) appels de fonction, qui s'accumulent assez rapidement.
ETHproductions

Vous pouvez enregistrer un octet avec [..._(--$)+[_(--$)]]:-)
ETHproductions

4

05AB1E , 8 octets

XÎF‚¤sSO

Essayez-le en ligne!

Explication

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 octets

Enregistré 2 octets grâce à Martin Ender

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

Algorithme récursif simple, rien d'extraordinaire. 0 indexé.

Essayez-le en ligne! ou tester pour 0-50 (fonctionne en fait assez rapidement).

Explication

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 octets

Solution utilisant la répétition. Algorithme similaire à la solution de Jonathan Allan.

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

Essayez-le en ligne!


3

Perl 6 ,  41  37 octets

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

Essayez-le

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

Essayez-le

{ # 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
Vous pouvez écrire le lambda intérieur comme *.comb.sum+*.comb.sum.
smls

2

MATL , 15 octets

lOi:"yyhFYAss]&

Essayez-le en ligne!

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 octets

ou 61 octets comptant les codes d'échappement comme 1 octet chacun

0 indexé. Semblable à certaines des autres réponses, j'indexe une table de recherche de valeurs mais je l'ai compressée en blocs de 4 octets. Je n'ai pas pris la peine d'étudier la version mod 24 parce que je ne pensais pas que c'était aussi intéressant puisque les autres l'ont déjà fait mais avouons-le, C ne va pas gagner de toute façon.

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

explication:

#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

Essayez-le en ligne!


Je compte les codes d'échappement comme 1 octet chacun! Excellent travail
Albert Renshaw



2

Mathematica, 49 octets

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

Définition récursive simple. Obtient assez lent après un certain temps.

Mathematica, 79 71 octets

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

Codage en dur du modèle périodique. Rapide comme l'éclair et abusivement satisfaisant pour Mathematica :) Merci à JungHwan Min pour avoir économisé 8 octets!


Pour votre deuxième code LetterNumber@"JJBCEHMLGJHIQQPOMJEFKHJ"est 8 octets plus court que 43626804920391712116157158790~IntegerDigits~18.
JungHwan Min

tu as raison! Un de ces jours, je m'en souviendrai LetterNumber...
Greg Martin

1

Python 2 , 56 octets

Solution itérative simple.

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

Essayez-le en ligne!

L'utilisation (a%9or a)+(b%9or b)s'est avérée être plus courte que sum(map(int(`a`+`b`)))!


Je pense que vous voulez dire sum(map(int,a+b))(ne peut pas comprendre comment utiliser `dans les commentaires)

1

PowerShell , 79 octets

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

Essayez-le en ligne!

Longue solution itérative ennuyeuse qui effectue des calculs de somme de chiffres directs à chaque forboucle. À la fin de la boucle, le nombre que nous voulons est $b, donc il reste sur le pipeline et la sortie est implicite. Notez que si l'entrée est 0, alors la boucle n'entrera pas car le conditionnel est faux, donc ça $breste 0.


1

Lot, 85 octets

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

Je me demandais comment j'allais porter ma réponse JavaScript en batch mais l'indice était dans la solution Python de @ Dennis.


1

Pyth, 20 octets

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

Un programme qui prend en entrée un entier indexé zéro et imprime le résultat.

Suite de tests (première partie pour le formatage)

Comment ça marche

[Explication à venir plus tard]


1

Rubis, 58 octets

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

La solution simple en dur.



1

Octave, 148 octets

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

Bienvenue à ppcg! Bon premier post!
Rɪᴋᴇʀ

1

Haskell, 151 octets

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)

Appelez la fonction avec f 123456789012345678901234567890123456789012345678 , par exemple.

Le code fonctionne également avec de très gros indices. En raison de la fonctionnalité modulo 24 implémentée, elle est très rapide.

Le code non compressé:

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

Une solution horriblement longue, mais elle est meilleure que la 108 que j'avais à l'origine. Je soupçonne qu'il existe une bien meilleure façon de procéder, mais je ne peux pas le voir pour le moment.

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

Il s'agit d'une fonction sans nom qui utilise gsubet scan(t=pour diviser les chiffres du vecteur en chiffres. La somme de ceux-ci est ajoutée au vecteur pendant que le premier élément est supprimé. repeatest utilisé pour parcourir les ntemps de séquence et le résultat est le premier élément du vecteur.



0

Mathematica, 67 octets

r=IntegerDigits;f@0=0;f@1=1;f[x_]:=f@x=Tr@r@f[x-1]+Tr@r@f[x-2];f@#&
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.