# [SOLUTION] The Golden Fibbonacci Ratio (#69)

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

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 )
\$*.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 }#"

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[i] = i%2!=0?"_":" "} # top
(0..cols).each{|i|dia[rows][i] = i%2!=0?"_":" "} # bottom
dia[1..rows].each{|row| row,row[cols] = "|","|"} # sides
fibicle(n-1,dia)
end

fibicle(ARGV.to_i).each{|r|puts r.join}

__END__

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

if :left == dir
elsif :right == dir
elsif :down == dir
elsif :up == dir
end
end

0.upto(left.length - 1) { |i| left[i] = left[i].slice(0..-2) + right[i] if right[i] }
return left
end

1.upto(bottom.length - 1) { |i| top << bottom[i] }
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

EEEK! if __FILE__ == \$0
ARGV.each do |i|
puts "Fibonacci for: #{i}"
f = Fibonacci.new(i.to_i)
f.draw
puts
end
end

···

On Mar 5, 2006, at 6:40 PM, Geoff Lane 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

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.times { side = side + cell }
res.times { side = side + blank }
res.times { puts side }
puts clear
res = rect.call(res, res)
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.times { side = side + @cell }
rect.times { side = side + @blank }
rect.times { puts side }
puts @clear
rect = next_rectangle(rect, rect)
show_rectangles(rect, count - 1)
end
end
end

GoldenRectangles.new.show_rectangles([1,1], 5)
--- cut here ---

Have a nice day all,
Alex

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

Heh, good catch.

···

On Mar 5, 2006, at 7:28 PM, Logan Capaldo wrote:

On Mar 5, 2006, at 6:40 PM, Geoff Lane 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

--
Geoff Lane <geoff@zorched.net>