# The Golden Fibbonacci Ratio (#69)

**URL:** <https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002>\
**Category:** Ruby\
**Created:** [March 5, 2006, 8:48pm UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002 "2006-03-05T20:48:36Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 5, 2006, 8:48pm UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/1 "2006-03-05T20:48:36Z")

</div>

Here’s my solution. It’s fairly pedestrian, although the size and  
aspect ratio of the ASCII-art squares are configurable.

It builds the picture as an array of strings, appending alternately to  
the end of the array and to the end of each string. The dimensions of  
each added box are taken from the length of the edge to which it is to  
be added.

It takes one optional argument on the commandline: an iteration count.

-mental

— 8\< ----

#!/usr/bin/ruby

CELL\_WIDTH = 5  
CELL\_HEIGHT = 3

def box( size )  
width = size \* CELL\_WIDTH  
height = size \* CELL\_HEIGHT  
lines = ["#" \* width] + ["##{ " " \* ( width - 1 ) }"] \* ( height - 1 )  
lines.map! { |line| line.dup }  
end

lines = box( 1 )  
$\*[0].to\_i.times do  
width = lines.first.size \* CELL\_HEIGHT  
height = lines.size \* CELL\_WIDTH  
if width \> height  
lines.concat box( width / CELL\_WIDTH / CELL\_HEIGHT )  
else  
lines.zip box( height / CELL\_WIDTH / CELL\_HEIGHT ) do |line, box|  
line \<\< box  
end  
end  
end  
lines.each { |line| puts “#{ line }#” }  
puts “#{ lines.first }#”

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 6, 2006, 12:42am UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/2 "2006-03-06T00:42:17Z")

</div>

Here’s my solution. Pretty standard output, I didn’t try and do anything  
fancy like PostScript or OpenGL. I thought I ended up with a pretty good  
class design though.

#!/bin/env ruby

class Fibonacci  
DIRS = [:left, :down, :right, :up]

```
def initialize(num)
    @values = []
    Fibonacci.calc(num) { |x| @values << x }
end

def draw
    current_dir = 0
    main = nil
    @values.each do |v|
        next if 0 == v
        b = block_for(v)
        if ! main
            main = b
            next
        end
        main = add_block(main, b, DIRS[current_dir])
        current_dir = current_dir == 3 ? 0 : current_dir + 1
    end

    print_block(main)
end

# Linear Fibonacci calculation
def Fibonacci.calc(num)
    prev, result = -1, 1
    (0..num).each do
        yield sum = result + prev
        prev = result
        result = sum
    end
end

private
def block_for(num)
    return [] if num == 0

    top = []
    0.upto(num * 2) { top << "#" }

    middle = ["#"]
    2.upto(num * 2) { middle << " " }
    middle << "#"

    b = []
    b << top
    2.upto(num * 2) { b << middle }
    b << top
end

def add_block(main, b, dir)
    if :left == dir
        return add_left(b, main)
    elsif :right == dir
        return add_left(main, b)
    elsif :down == dir
        return add_bottom(main, b)
    elsif :up == dir
        return add_bottom(b, main)
    end
end

def add_left(left, right)
    0.upto(left.length - 1) { |i| left[i] = left[i].slice(0..-2) +

```

right[i] if right[i] }  
return left  
end

```
def add_bottom(top, bottom)
    1.upto(bottom.length - 1) { |i| top << bottom[i] }
    return top
end

def print_block(b)
    b.each { |x| print x; print "\n" }
end

```

end

if **FILE** == $0  
0.upto(ARGV.length - 1) do |i|  
puts "Fibonacci for: " + ARGV[i]  
f = Fibonacci.new(ARGV[i].to\_i)  
f.draw  
puts  
end  
end

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 5, 2006, 9:16pm UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/3 "2006-03-05T21:16:20Z")

</div>

No fancy output here, just a simple recursive version – build the  
largest  
rectangle as a matrix of characters, then recursively overwrite each  
smaller rectangle (from the origin).

----andrew

#!/usr/bin/ruby -w

Fib = Hash.new{|h,n|n\<2?h[n]=n:h[n]=h[n-1]+h[n-2]}

def fibicle(n,dia=[])  
return dia if n == 0  
cols, rows = Fib[n+1], Fib[n]  
cols, rows = rows, cols if n%2 != 0  
cols \*= 2  
(0…rows).each{dia \<\< [" “]\*cols} if dia.empty?  
(0…cols).each{|i|dia[0][i] = i%2!=0?”_":" “} # top  
(0…cols).each{|i|dia[rows][i] = i%2!=0?”_":" “} # bottom  
dia[1…rows].each{|row| row[0],row[cols] = “|”,”|"} # sides  
fibicle(n-1,dia)  
end

fibicle(ARGV[0].to\_i).each{|r|puts r.join}

**END**

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 6, 2006, 2:30am UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/4 "2006-03-06T02:30:44Z")

</div>

On Mar 5, 2006, at 6:40 PM, Geoff L. wrote:

> if **FILE** == $0  
> 0.upto(ARGV.length - 1) do |i|  
> puts "Fibonacci for: " + ARGV[i]  
> f = Fibonacci.new(ARGV[i].to\_i)  
> f.draw  
> puts  
> end  
> end

EEEK! 😉

if **FILE** == $0  
ARGV.each do |i|  
puts “Fibonacci for: #{i}”  
f = Fibonacci.new(i.to\_i)  
f.draw  
puts  
end  
end

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 6, 2006, 3:15am UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/5 "2006-03-06T03:15:59Z")

</div>

Here is my solution. I decided to go with RMagick for my output, since  
I figured it would be easier than ascii. Then I got the idea to write  
an ascii “Magick” module to do the output in ascii. It is pretty  
limited, but it has enough functionality to handle this quiz. Just  
change “require ‘RMagick’” to “require ‘asciiMagick’”.

# file: golden\_fibbonacci.rb

require ‘RMagick’  
#require ‘asciiMagick’  
include Magick

def fib(n)  
x,y = 1,1  
n.times do  
yield x  
x, y = y, x + y  
end  
end

def points(n,multiplier=2)  
x1,y1 = 0,0

fib(n) do |fib|  
fib \*= multiplier  
x2,y2 = (fib + x1),(fib + y1)  
yield x1,y1,x2, y2  
if x1 == 0  
x1,y1 = fib,0  
else  
x1,y1 = 0,fib  
end  
end  
end

img = Draw.new  
img.stroke(‘black’)  
img.fill= ‘white’  
points(9){|x,y,@x,@y| img.rectangle(x,y,@x,@y)}  
canvas = Image.new(@x + 1,@y + 1)  
img.draw(canvas)

canvas.write(‘golden\_fibbonacci.jpg’)

# file: asciiMagick.rb

module Magick  
class Image  
attr\_accessor :args

```
def initialize(x,y)
  @a = Array.new(y)
  @a.map! do |i|
    i = Array.new(x,' ')
  end
  @a
end

def draw_rectangle
  x1,y1,x2,y2 = @args
  x1.upto(x2) do |i|
    @a[y1][i] = '#'
    @a[y2][i] = '#'
  end
  y1.upto(y2) do |i|
    @a[i][x1] = '#'
    @a[i][x2] = '#'
  end
end

def write(string)
  puts @a.map!{|i| i.join('')}
end

```

end

class Draw

```
def initialize
  @cache = Array.new
end

def stroke(str)
  ## this isn't used
end

def fill=(str)
  ## this isn't used
end

def draw(canvas)
  @cache.each do |hash|
    hash.each do|method_name,args|
      canvas.args = args
      canvas.method(method_name).call
    end
  end
end

def rectangle(x1,y1,x2,y2)
  @cache << {:draw_rectangle => [x1,y1,x2,y2]}
end

end

```

end

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 6, 2006, 3:25am UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/6 "2006-03-06T03:25:00Z")

</div>

Heh, good catch.

---

<div class="post-metadata">

**Author:** ![MenTaLguY](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/439d5e/32.png) [@MenTaLguY](https://www.ruby-forum.com/u/MenTaLguY)\
**Post date:** [March 6, 2006, 10:03am UTC](https://www.ruby-forum.com/t/the-golden-fibbonacci-ratio-69/77002/7 "2006-03-06T10:03:42Z")

</div>

Hi all,

Nothing fancy here either, I just tried to solve this in the simplest  
way  
I could (first). Then I tried ‘the Ruby way’ (at least how I see it  
after  
only 10 hours of playing with Ruby…).

The output uses a two characters to display one cell of data, that is  
“##” not “#”. Since a single character is 8x16 bits, two chars together  
make a pretty good square, and thus the proportions in the final output  
are more close to the reality. The blue rectangle is the current  
rectangle, while the white square is the part that gets cut from it.

Needs ANSI capable terminal, don’t know if it would work or not on  
Windows…

— cut here —  
cell, blank, clear = “\033[34;1m##”, “\033[37;1m##”, “\033[30;0m”

next\_rect = lambda { |a,b| [[a,b].max, [a,b].min + [a,b].max] }  
rect = next\_rect

res = [1, 1]  
(1…6).each do  
p res  
side = ‘’  
res[0].times { side = side + cell }  
res[1].times { side = side + blank }  
res[1].times { puts side }  
puts clear  
res = rect.call(res[0], res[1])  
end  
— cut here —

the OO solution, using recursion

— cut here —  
class GoldenRectangles  
def initialize  
@cell, @blank, @clear = “\033[34;1m##”, “\033[37;1m##”, “\033[30;0m”  
end

def next\_rectangle(a, b)  
[[a,b].max, [a,b].min + [a,b].max]  
end

def show\_rectangles(rect, count)  
if count \> 0  
p rect  
side = ‘’  
rect[0].times { side = side + @cell }  
rect[1].times { side = side + @blank }  
rect[1].times { puts side }  
puts @clear  
rect = next\_rectangle(rect[0], rect[1])  
show\_rectangles(rect, count - 1)  
end  
end  
end

GoldenRectangles.new.show\_rectangles([1,1], 5)  
— cut here —

Have a nice day all,  
Alex
