How to resolve the algorithm Zeckendorf number representation step by step in the Ruby programming language

Published on 12 May 2024 09:40 PM

How to resolve the algorithm Zeckendorf number representation step by step in the Ruby programming language

Table of Contents

Problem Statement

Just as numbers can be represented in a positional notation as sums of multiples of the powers of ten (decimal) or two (binary); all the positive integers can be represented as the sum of one or zero times the distinct members of the Fibonacci series. Recall that the first six distinct Fibonacci numbers are: 1, 2, 3, 5, 8, 13. The decimal number eleven can be written as 013 + 18 + 05 + 13 + 02 + 01 or 010100 in positional notation where the columns represent multiplication by a particular member of the sequence. Leading zeroes are dropped so that 11 decimal becomes 10100. 10100 is not the only way to make 11 from the Fibonacci numbers however; 013 + 18 + 05 + 03 + 12 + 11 or 010011 would also represent decimal 11. For a true Zeckendorf number there is the added restriction that no two consecutive Fibonacci numbers can be used which leads to the former unique solution.

Generate and show here a table of the Zeckendorf number representations of the decimal numbers zero to twenty, in order.
The intention in this task to find the Zeckendorf form of an arbitrary integer. The Zeckendorf form can be iterated by some bit twiddling rather than calculating each value separately but leave that to another separate task.

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Zeckendorf number representation step by step in the Ruby programming language

Ruby Code Explanation

The code snippet provided contains three implementations of the Zeckendorf representation for arbitrary non-negative integers.

Implementation 1: Generator Using Loop

def zeckendorf
 return to_enum(__method__) unless block_given?
 x = 0
 loop do
   bin = x.to_s(2)
   yield bin unless bin.include?("11") 
   x += 1
 end
end
  • This method defines an infinite generator that yields binary representations of non-negative integers that do not contain the substring "11". It takes advantage of Ruby's infinite lazy enumerators created by loop do.
  • The generator is called with block_given? to determine if a block is provided, and if not, it returns an enumerator.
  • If a block is provided, the generator iterates over binary representations, using to_s(2), and yields them if they do not contain "11".
  • The x variable is incremented to generate the next binary representation.

Implementation 2: Direct Conversion

def zeckendorf(n)
 return 0 if n.zero?
 fib = [1,2]
 fib << fib[-2] + fib[-1] while fib[-1] < n
 dig = ""
 fib.reverse_each do |f|
   if f <= n
     dig, n = dig + "1", n - f
   else
     dig += "0"
   end
 end
 dig.to_i
end
  • This method directly converts a non-negative integer n to its Zeckendorf representation.
  • It uses a Fibonacci sequence (fib) to find the largest Fibonacci number that is less than or equal to n.
  • It then builds the binary representation dig by iterating through the Fibonacci numbers in reverse order, representing each Fibonacci number that fits into n as a "1" and the rest as "0"s.
  • The final binary representation is converted back to an integer.

Implementation 3: Lazy Filtering

def zeckendorf(n)
 0.step.lazy.map { |x| x.to_s(2) }.reject { |z| z.include?("11") }.first(n)
  • This method combines lazy evaluation and filtering to generate the first n Zeckendorf representations.
  • It creates an infinite lazy sequence of binary representations (0.step.lazy.map { |x| x.to_s(2) }) and then filters out those containing "11" (reject { |z| z.include?("11") }).
  • Finally, it takes the first n elements of the filtered sequence using first(n).

Usage

The code sample includes usage examples for all three implementations:

  • Usage of Implementation 1:

    • zeckendorf.take(21).each_with_index{|x,i| puts "%3d: %8s"% [i, x]} generates the first 21 Zeckendorf representations.
  • Usage of Implementation 2:

    • for i in 0..20; puts '%3d: %8d' % [i, zeckendorf(i)] prints the Zeckendorf representations for integers 0 to 20.
  • Usage of Implementation 3:

    • zeckendorf(21).each_with_index{ |x,i| puts "%3d: %8s"% [i, x] } prints the first 21 Zeckendorf representations.

Source code in the ruby programming language

def zeckendorf
  return to_enum(__method__) unless block_given?
  x = 0
  loop do
    bin = x.to_s(2)
    yield bin unless bin.include?("11") 
    x += 1
  end
end

zeckendorf.take(21).each_with_index{|x,i| puts "%3d: %8s"% [i, x]}


def zeckendorf(n)
  return 0 if n.zero?
  fib = [1,2]
  fib << fib[-2] + fib[-1] while fib[-1] < n
  dig = ""
  fib.reverse_each do |f|
    if f <= n
      dig, n = dig + "1", n - f
    else
      dig += "0"
    end
  end
  dig.to_i
end

for i in 0..20
  puts '%3d: %8d' % [i, zeckendorf(i)]
end


def zeckendorf(n)
  0.step.lazy.map { |x| x.to_s(2) }.reject { |z| z.include?("11") }.first(n)
end

zeckendorf(21).each_with_index{ |x,i| puts "%3d: %8s"% [i, x] }


  

You may also check:How to resolve the algorithm Polynomial long division step by step in the Ruby programming language
You may also check:How to resolve the algorithm Quaternion type step by step in the Ruby programming language
You may also check:How to resolve the algorithm World Cup group stage step by step in the Ruby programming language
You may also check:How to resolve the algorithm Terminal control/Dimensions step by step in the Ruby programming language
You may also check:How to resolve the algorithm Averages/Root mean square step by step in the Ruby programming language