Math::N...tations(3)
๐ Math::NumSeq::FibonacciRepresentations ๐
okay so bestie, this page comes straight from the User Contributed Perl Documentation, and it is lowkey one of the cutest little sequences in Math::NumSeq. It's the Fibonacci representations thing. Yes, the name is long. Yes, it slays. Sit down, grab a snack ๐, we're doing number theory in the group chat.
โจ NAME โจ
Math::NumSeq::FibonacciRepresentations โ it counts how many ways you can write a number as a sum of Fibonacci numbers. That's the whole vibe. ๐
๐ SYNOPSIS ๐
use Math::NumSeq::FibonacciRepresentations;
my $seq = Math::NumSeq::FibonacciRepresentations->new;
my ($i, $value) = $seq->next;
that's it. three lines. iconic. โจ
๐ธ DESCRIPTION ๐ธ
So this is the Fibonacci representations function R(i), and it's literally the number of ways i can be written as a sum of distinct Fibonacci numbers. Distinct!! no reusing, that's the rule bestie ๐
1, 1, 1, 2, 1, 2, 2, 1, 3, 2, 2, 3, 1, 3, 3, 2, 4, 2, 3, 3, ...
starting i=0 (OEIS A000119)
For example, R(11)=3 because 11 can be built from Fibonacci numbers in these three different ways:
11 = 8 + 3 R(11)=3 sums
= 8 + 2 + 1
= 5 + 3 + 2 + 1
three totally different fits, one number. it's giving main character energy ๐
๐ข Array ๐ข
The way to see the pattern is to stack the values in rows of an array. Look:
1 i=0 to 0
1 1 i=0 to 1
1 1 i=1 to 2
1 2 1 i=2 to 4
1 2 2 1 i=4 to 7
1 3 2 2 3 1 i=7 to 12
1 3 3 2 4 2 3 3 1 i=12 to 20
1 4 3 3 5 2 4 4 2 5 3 3 4 1 i=20 to 33
1 4 4 3 6 3 5 5 2 6 4 4 6 2 5 5 3 6 3 4 4 1 i=33 to 54
F[y]-1 to F[y+1]-1
Each row has Fibonacci F[y-1] many values in it, running from i=F[y]-1 to i=F[y+1]-1. Notice the ranges overlap โ so every "1" at the right end is a repeat of the "1" at the left end. There's just a single 1 in the sequence for each block, no duplicates in the actual sequence. ๐
New values in row y are the sum of adjacent values in row y-2 โ or, same thing said differently, they come from a pattern of duplications and sums from row y-1. For example, in the third row the "2" has duplicated to be 2,2, then in the fourth row the adjacent 1,2 values sum to give a new "3". Row y-2 is basically a Fibonacci-style delay to when values get summed, and that's what results in F many values in each row. ๐ฆ
โ๏ธ FUNCTIONS โ๏ธ
Peep "FUNCTIONS" in Math::NumSeq for the behaviour that's common to all sequence classes, bestie.
$seq = Math::NumSeq::FibonacciRepresentations->new ()โ makes you a brand new sequence object and hands it over. ๐
๐ฒ Random Access ๐ฒ
$value = $seq->ith($i)โ gimme the$i'th value of the sequence, bestie.($v0, $v1) = $seq->ith_pair($i)โ gimme two values,ith($i)andith($i+1). And here's the tea: as described down in "Ith Pair" below, two values can be calculated with the same work as one. efficiency queen ๐$bool = $seq->pred($value)โ returns true if$valueshows up in the sequence at all, which simply means integer$value>=1. that's it, that's the whole test. โจ
๐งฎ FORMULAS ๐งฎ
๐ซ Ith Pair ๐ซ
For ith_pair() the two sequence values at an arbitrary i,i+1 can be calculated from the Zeckendorf form of i+1 (peep "Zeckendorf Base" in Math::NumSeq::Fibbinary) as per:
Jean Berstel, "An Exercise on Fibonacci Representations", Theoretical Informatics and Applications, volume 35, 2001, pages 491-498. <http://archive.numdam.org/numdam-bin/fitem?id=ITA_2001__35_6_491_0>
Berstel uses a state machine which results in matrices based on runs of consecutive 0-bits in the Zeckendorf form. If you're making the Zeckendorf breakdown by some sort of logarithm or high binary bit, then those would be Fibonacci number indices and their differences are the run lengths. ๐
If you're making the Zeckendorf breakdown by individual Fibonacci number comparisons to give the fibbinary form, then it's convenient to take each bit individually rather than in runs. In the algorithm below, runs of 0-bits do r += rprev every second time, and hence become r += rprev*floor(run/2), which is per the M matrices of Berstel.
rprev = 1 = R(0) will become R[i]
r = 1 = R(1) will become R[i+1]
zeros = 0 how many consecutive bit=0 seen
for each bit of fibbinary(i+1) from high to low
if bit=0 then
if zeros odd then r += rprev
zeros ^= 1
if bit=1 then
if zeros odd then rprev += r
else rprev = r
zeros = 0
result R[i]=rprev, R[i+1]=r
The loop maintains r=R[bits] where "bits" is those bits of fibbinary(i+1) which have been processed so far. rprev is the immediately preceding sequence value.
The loop action is to append either a 0-bit or 1-bit Zeckendorf term to the bits processed so far and step r,rprev accordingly.
"zeros" is the count of 0-bits seen since the last 1-bit. This is kept only modulo 2, since the test is just for odd or even run of zeros, not the full count. ๐
For a 1-bit, the zeros count becomes 0 since there are now no 0-bits since the last 1-bit seen. In the Zeckendorf form a 1-bit always has a 0-bit immediately below it. That bit can be worked into the bit=1 case:
if bit=1 then
if zeros odd then rprev += r
else rprev = r
next lower bit of fibbinary(i+1) is 0-bit, so skip it
zeros = 1
This is as if the bit=0 code is done immediately after the bit=1. zeros=0 is even after the bit=1, so there's no change to r,rprev by the bit=0 code โ simply skip the 0-bit and record zeros=1. ๐ฏ
When calculating Fibonacci numbers for fibbinary(i+1), it's desirable to use integers <=i only, so as not to overflow a finite number type. This can be done by finding the biggest Fibonacci f1<=i and subtracting it before doing the +1, giving i+1-f1 without overflow. If the biggest Fibonacci <=i+1 is in fact f2=f1+f0<=i+1 then will have i+1-f1 >= f0 and should subtract that too for i+1-(f1+f0). The loop begins at the f1 bit in this case, or at the f0 bit if not.
When the high 1-bit is handled like this to avoid overflow, the second highest bit is always a 0-bit the same as above. So the loop can begin one lower โ so f0 if f2 was subtracted, or the Fibonacci below f0 if not. Initial zero=1 so as to record the 0-bit skipped.
f1<=i and f1+f0<=i+1 only occurs when i+1=f1+f0 exactly, so it has all 0-bits. This can be treated explicitly by floor(count/2) which is the 0-bit cases in the loop. i+1=Fibonacci won't occur very often, but returning count/2 is about the amount code as an i-=f0 and setup to loop from f1.
The effect of the algorithm in each case is to descend through the array above ("Array") by taking or not taking mediant r+rprev or duplication rprev=r. You can compare this to the Stern diatomic sequence calculation, which goes by taking or not taking the mediant โ no duplicating rprev=r case. ๐ง
๐ Stern Diatomic ๐
The Fibonacci representations sequence contains the Stern diatomic sequence (eg. Math::NumSeq::SternDiatomic) as a subset, per:
Marjorie Bicknell-Johnson, "Stern's Diatomic Array Applied to Fibonacci Representations", Fibonacci Quarterly, volume 41, number 2, May 2003, pages 169-180.<http://www.fq.math.ca/41-2.html><http://www.fq.math.ca/Scanned/41-2/bicknell.pdf>
Taking the R(i) at indices i for which i in Zeckendorf form uses only even Fibonaccis gives the Stern diatomic sequence. ๐ฅ
These indices have fibbinary value (Math::NumSeq::Fibbinary) with 1-bits only at even bit positions (counting the least significant bit position as 0 and going up from there). Even positions are either 0 or 1. Odd positions are always 0. The highest bit is always a 1-bit and it must be at an even position.
fibbinary(i) = 10a0b0c...0z
^ ^ ^ ^
even bits a,b,c,etc 0 or 1,
odd bits always 0
In the "Ith Pair" calculation above, this kind of i always has an odd number of 0-bits between each 1-bit. So the 1-bit step is always rprev+=r, and the 0-bit step at the even positions is r+=prev. Those two steps are the same as the Stern diatomic calculation per "Ith Pair" in Math::NumSeq::SternDiatomic. ๐
๐ SEE ALSO ๐
Math::NumSeq::FibonacciMath::NumSeq::SternDiatomic
๐ HOME PAGE ๐
<http://user42.tuxfamily.org/math-numseq/index.html>
๐ LICENSE ๐
Copyright 2014, 2016, 2019, 2020, 2021 Kevin Ryde
Math-NumSeq is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Math-NumSeq is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Math-NumSeq. If not, see <http://www.gnu.org/licenses/>.
fr fr read the license, bestie, it's the whole point of the fine print ๐
and that's a wrap on this page from perl v5.42.0, dated 2025-07-25 ๐ซถ go forth and count your Fibonacci representations, queen. periodt. ๐ โจ๐
๐ฆ where this page comes from
- fedora 43: perl-Math-NumSeq 75-11.fc43 ยท GPL-3.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms