Function Repository Resource:

DualZeckendorfRepresentation

Source Notebook

Give the 0–1 list that is free of consecutive zeros and indicates the unique Fibonacci numbers that sum to the positive integer

Contributed by: Shenghui Yang

ResourceFunction["DualZeckendorfRepresentation"][n]

gives the dual Zeckendorf representation of the input positive integer n.

ResourceFunction["DualZeckendorfRepresentation"]["Reset"]

releases memory used for an internal hash table.

Details

Zeckendorf representation uses a greedy algorithm; the dual representation, instead, uses a lazy algorithm.
Both representations use a shifted Fibonacci sequence: u1=1, u2=2 and un+2=un+1+un.
The computation of the dual representation differs from Zeckendorf only in the first steps: here we choose the largest index i such that ∑j=1i-1uj<n.
The Zeckendorf representation has no neighboring Fibonacci indices. The dual Zeckendorf representation has no neighboring missing Fibonacci indices.
The function uses an iterative call of LengthWhile with a dynamically reduced list to accelerate computation. Thus the complexity is around O(log(nlog(log(n))), or roughly the number of binary digits of the input, n, times the logarithm of n.
The function uses a "HashTable" data structure to accelerate the speed of computation. Use ResourceFunction["DualZeckendorfRepresentation"]["Reset"] to release memory.

Examples

Basic Examples (1) 

The dual Zeckendorf representation of first 20 integers (OEIS: A104326):

In[1]:=
data = Array[ResourceFunction["DualZeckendorfRepresentation"][#] &, 20, 1]
Out[1]=
In[2]:=
ResourceFunction["NiceGrid"][Transpose@{Row /@ data}, {"Dual Rep."}, Range[20]]
Out[2]=

Scope (6) 

By definition, one can directly find dual Zeckendorf representation by eliminating binary string with "00":

In[3]:=
Map[FromDigits, Select[IntegerString[Range[0, 100], 2], StringFreeQ[#, "00"] &]][[
 2 ;; 21]]
Out[3]=

Recover a number from its dual representation:

In[4]:=
data = ResourceFunction["DualZeckendorfRepresentation"][10^10]
Out[4]=
In[5]:=
Position[Reverse[data], 1] // Flatten
Out[5]=
In[6]:=
Total[Fibonacci[% + 1]]
Out[6]=
In[7]:=
Log10[%]
Out[7]=

In the dual representation, the largest index of Fibonacci number has the following property:

In[8]:=
input = 10^6 - 1;
data = ResourceFunction["DualZeckendorfRepresentation"][input]
Out[9]=
In[10]:=
Position[Reverse[data], 1] // Flatten
Out[10]=

Thus input falls precisely the gap between the sum of Fi for i = 2 to 28 and from 2 to 29=28+1:

In[11]:=
Sum[Fibonacci[i], {i, 2, 28}] < input <= Sum[Fibonacci[i], {i, 2, 29}]
Out[11]=

The second largest value, 26, is found in the similar way by definition:

In[12]:=
Sum[Fibonacci[i + 1], {i, 2, 26}] < input - Fibonacci[28] < Sum[Fibonacci[i + 1], {i, 2, 27}]
Out[12]=

For any input n, its dual Zeckendorf representation is {1,1, ,1} or zero-free if and only if n= Fk-2, where Fk is the k-th item in regular Fibonacci sequence with k>=4:

In[13]:=
ResourceFunction["DualZeckendorfRepresentation"][Fibonacci[#] - 2] & /@
  Range[4, 12]
Out[13]=

For any input n, its dual Zeckendorf representation is {1,0,1,0 ,0|1} or alternating pattern (the ending in 0 or 1 depends on the parity of bit length) if and only if n= Fk-1, where Fk is the k-th item in regular Fibonacci sequence with k>=4:

In[14]:=
ResourceFunction["DualZeckendorfRepresentation"][Fibonacci[#] - 1] & /@
  Range[4, 12]
Out[14]=

On modern computers, it takes around 3 seconds to finding the dual Zeckendorf representation for the first 100K numbers:

In[15]:=
ResourceFunction["DualZeckendorfRepresentation"]["Reset"];
ResourceFunction["DualZeckendorfRepresentation"] /@ Range[100000]; // AbsoluteTiming
Out[16]=

Applications (2) 

Recover a Fibonacci number from the dual Zeckendorf representation by counting the number of k-bit vectors. For instance F(17)-2 = F(2)+F(3)++ F(15) where 15 = 17 -2:

In[17]:=
With[{k = 17}, {Fibonacci[k] - 2, Sum[Fibonacci[i], {i, 2, k - 2}]}]
Out[17]=
In[18]:=
g = Length /@ GroupBy[Array[ResourceFunction["DualZeckendorfRepresentation"], 1595], Length]
Out[18]=

Note that the numbers on the RHS of the rules are exactly the Fibonacci numbers:

In[19]:=
Column@{
  Values[g],
  Keys@KeyMap[Fibonacci[# + 1] &, g]
  }
Out[19]=

This observation can be proved with a combinatorics argument.

Properties and Relations (3) 

The dual Zeckendorf representation vs. Zeckendorf representation: the former does not allow consecutive zeros, meanwhile the latter does not allow consecutive ones. Check the fact with the first twenty numbers:

In[20]:=
brData = Array[ResourceFunction["DualZeckendorfRepresentation"][#] &, 20, 1];
In[21]:=
zrData = Array[ResourceFunction["ZeckendorfRepresentation"][#] &, 20, 1];
In[22]:=
ResourceFunction["NiceGrid"][
 Transpose@{Row /@ brData, Row /@ zrData}, {"Dual", "Zeckendorf"}, Range[20]]
Out[22]=

Fibonacci terms minus one:

In[23]:=
FibMinus = Fibonacci[Range[3, 20]] - 1
Out[23]=

The two representations for the numbers above 4, 7, 12, 20,… are identical:

In[24]:=
(ResourceFunction["DualZeckendorfRepresentation"][#] == ResourceFunction["ZeckendorfRepresentation"][#]) & /@ FibMinus
Out[24]=

Possible Issues (1) 

The input must be a positive integer. Otherwise the function returns unevaluated:

In[25]:=
ResourceFunction["DualZeckendorfRepresentation"][-10]
Out[25]=

Neat Examples (4) 

The number of ones in the dual Zeckendorf representation for first 120 numbers:

In[26]:=
DiscretePlot[
 Total[ResourceFunction["DualZeckendorfRepresentation"][k]], {k, 1, 120}]
Out[26]=

Compare the ones in the Zeckendorf and the dual representation for Fibonacci numbers:

In[27]:=
Table[Labeled[
  ResourceFunction["DualZeckendorfRepresentation"][Fibonacci[k]], Fibonacci[k], Top], {k, 1, 8}]
Out[27]=
In[28]:=
Table[Labeled[
  ResourceFunction["ZeckendorfRepresentation"][Fibonacci[k]], Fibonacci[k], Top], {k, 1, 8}]
Out[28]=

Visualize the number of ones in the dual representation for Fibonacci number:

In[29]:=
Table[Total[
  ResourceFunction["DualZeckendorfRepresentation"][Fibonacci[k]]], {k,
   1, 30}]
Out[29]=
In[30]:=
DiscretePlot[
 Total[ResourceFunction["DualZeckendorfRepresentation"][
   Fibonacci[k]]], {k, 1, 30}]
Out[30]=

The sequence is OEIS A065033:

In[31]:=
asso = ResourceFunction["OEISSequenceData"]["A065033", "Dataset"] // Normal;
asso["Name"]
Out[32]=

Because no consecutive zeros are allowed, all dual Zeckendorf representations are compact Huffman code:

In[33]:=
ResourceFunction["DualZeckendorfRepresentation"][1234]
Out[33]=
In[34]:=
ResourceFunction["DistinctCompactBinaryHuffmanCode"][%, "TreeForm"]
Out[34]=

This function can handle very large input:

In[35]:=
ResourceFunction["DualZeckendorfRepresentation"]["Reset"];
(data = ResourceFunction["DualZeckendorfRepresentation"][10^99]; Length[data]) // AbsoluteTiming
Out[36]=

Visualize the binary code with ArrayPlot:

In[37]:=
ArrayPlot[Partition[data, 43], ColorRules -> {1 -> RGBColor["#101820"], 0 -> RGBColor["#FEE715"]}]
Out[37]=

Find the closed form for the average density of 1's in k-bit dual Zeckendorf representations as k approaches infinity:

In[38]:=
With[{k = 21}, {Fibonacci[k] - 2, Sum[Fibonacci[i], {i, 2, k - 2}]}]
Out[38]=
In[39]:=
gbl = Total[#, 2] & /@ GroupBy[Array[ResourceFunction["DualZeckendorfRepresentation"], 10944], Length]
Out[39]=

The sum on the RHS of these rules has the following closed form expression (OEIS A023610):

In[40]:=
phi = (1 + Sqrt[5])/2;
Column[{
  Values[gbl],
  Table[(1/
      5)*((n + 2)*Fibonacci[n + 4] + (n - 1)*Fibonacci[n + 2]), {n, 0,
     17}]
  }]
Out[41]=
In[42]:=
N[Values[gbl]/Table[(k) Fibonacci[k + 1], {k, 1, 18}]]
Out[42]=

Shift indices and find the limit as the bit length approaches infinity:

In[43]:=
Limit[((1/5)*((k + 1)*Fibonacci[k + 3] + (k - 2)*Fibonacci[k + 1]))/(
 k*Fibonacci[k + 1]), k -> Infinity]
Out[43]=

The result is simply +2)/5 where ϕ is the golden ratio (use Binet's formula and ϕ2=ϕ+1 for proof):

In[44]:=
N[{%, (\[Phi] + 2)/5} /. \[Phi] -> GoldenRatio]
Out[44]=

Publisher

Shenghui Yang

Requirements

Wolfram Language 14.0 (January 2024) or above

Version History

  • 1.1.0 – 26 February 2025
  • 1.0.0 – 07 February 2025

Source Metadata

Related Resources

License Information