Given an input
$N, generate the first$Nnumbers for which the sum of their digits is a Fibonacci number.
f(20)=[0, 1, 2, 3, 5, 8, 10, 11, 12, 14, 17, 20, 21, 23, 26, 30, 32, 35, 41, 44]
This is sequence A028840 in The On-Line Encyclopedia of Integer Sequences.
We need to do two things: given a number, find the sum of its digits, and given a number, check whether that number if a Fibonacci number.
The first taks is similar to what was needed in week 133, so we can reuse the code.
First, we create a method which, given a (non-negative) integer, returns the sum of its digit. We do this by getting the digits one at a time, from the right, using modulus and integer division:
sub digitsum ($number) {
my $sum = 0;
my $base = 10;
while ($number > 0) {
use integer;
$sum += $number % $base;
$number /= $base;
}
return $sum;
}
To check whether a number is a Fibonacci number, we keep a hash which
contains Fibonacci numbers. If we have a number N of which we want
to know whether it's a Fibonacci number, we first check what the largest
number in our hash is. If it's less than N, we generate successive
numbers until we reach or exceed N. Then we do a simple look up.
sub is_fib ($n) {
state $fib = {0 => 1, 1 => 1};
state $fib_prev = 0;
state $fib_last = 1;
while ($fib_last < $n) {
($fib_prev, $fib_last) = ($fib_last, $fib_prev + $fib_last);
$$fib {$fib_last} = 1;
}
$$fib {$n}
}
We can then print the numbers in a simple loop:
while (<>) {
for (my ($k, $N) = (0, 0 + $_); $N > 0; $k ++) {
$N --, print "$k " if is_fib digitsum $k
}
print "\n";
}
Find the full program on GitHub.
bc doesn't have hashes. So, we keep the generated Fibonacci numbers in an array. Once we have generated enough, we will do a binary search to see whether the input number is a Fibonacci or not.
fib_prev = 1
fib_last = 1
fib [0] = 0
fib [1] = 1
fib_count = 2
define is_fib (n) {
auto t, min, max
while (fib_last < n) {
t = fib_last
fib_last = fib_prev + fib_last
fib_prev = t
fib [fib_count] = fib_last
fib_count = fib_count + 1
}
min = 0
max = fib_count
while (min < max) {
mid = (min + max) / 2
if (fib [mid] == n) {
return (1)
}
if (fib [mid] < n) {
min = mid + 1
} else {
max = mid
}
}
return (0)
}
Find the full program on GitHub.
For our Scheme solution, we use a recursive solution to calculate the sum of the digits of a number:
(define (digit_sum n)
(define base 10)
(if (= n 0) 0 (+ (modulo n base) (digit_sum (floor/ n base)))))
To check if a number is a Fibonacci number, this time, we're not storing numbers generated so far. We use pure recursion:
(define (_is_fib n prev last)
(cond ((= n prev) #t)
((< n prev) #f)
(else (_is_fib n last (+ last prev)))))
(define (is_fib n) (_is_fib n 0 1))
Since recursion is the name of the game in Scheme, we use recursion for the loop which prints out the numbers:
(define (digit_fib k n)
(cond ((= n 0) #f)
((is_fib (digit_sum k))
(begin (format #t "~d " k) (digit_fib (+ k 1) (- n 1))))
(else (digit_fib (+ k 1) n))))
Here, k is the first number to check, and n is the amount of
numbers we still want to check. The main program (also recursive)
looks like this:
(define (main)
(define n (read-line))
(define k 0)
(if (not (eof-object? n))
(begin
(digit_fib 0 (string->number n))
(newline)
(main))))
Find the full program on GitHub.
We also have implementations, all similar to the Perl one, in:
AWK, Bash, C, Go, Java, Lua, Node.js, Pascal, Python, R, Ruby, and Tcl.