Function Repository Resource:

DualZeckendorfRepresentation (1.0.0) current version: 1.1.0 »

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.

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 iterative call of ResourceFunction["BinarySearch"] to accelerate computation. Thus the complexity is around O(log(nlog(log(n))), roughly the number of binary digits of input n times the logarithm of the value.

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 (5) 

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]=

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[15]:=
brData = Array[ResourceFunction["DualZeckendorfRepresentation"][#] &, 20, 1];
In[16]:=
zrData = Array[ResourceFunction["ZeckendorfRepresentation"][#] &, 20, 1];
In[17]:=
ResourceFunction["NiceGrid"][
 Transpose@{Row /@ brData, Row /@ zrData}, {"Dual", "Zeckendorf"}, Range[20]]
Out[17]=

Fibonacci terms minus one:

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

The identical representations for 4, 7, 12, 20, ..., continue:

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

Possible Issues (1) 

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

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

Neat Examples (2) 

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

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

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

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

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

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

The sequence is OEIS A065033:

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

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

In[28]:=
ResourceFunction["DualZeckendorfRepresentation"][1234]
Out[28]=
In[29]:=
ResourceFunction["DistinctCompactBinaryHuffmanCode"][%, "TreeForm"]
Out[29]=

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