Fractals (#125)

Here’s my solution… It’s the bare minimum of what I wanted to do.
I’ve been wanting to do some L-System type stuff for a while, so I
focused a bit on that. There’s lots more I want to put into it, like
fractional levels, and support for contextual grammars (this is
context-free).

The design was inspired by Dennis Ranke’s second solution to the dice
rolling quiz (#61). I had intended to reuse parts of the turtle
graphics quiz, but seeing as how I’ve also got “learn SVG” on my to-do
list, I did some quick and dirty SVG output. (Mozilla should be able
to open the file.)

class LSystem

def initialize(&block)
@rules = {}
instance_eval(&block)
end

def rule(var)
raise “Rule for #{var} must be unique!” if
@rules.include?(var.to_sym)
@rules[var.to_sym] = yield.map { |x| x.to_sym }
end

def start(var)
@start = var.to_sym
end

def evaluate(n)
product = [@start]
n.to_i.times do |i|
product.map! do |s|
@rules[s.to_sym] || s.to_sym
end.flatten!
end

product.each do |p|
  send(p)
end

end

end

koch = LSystem.new do
start :F
rule(:F) { %w(F + F - F - F + F) }

def F
nx, ny = @x + @dx, @y + @dy
puts <<-LINE

LINE
@x, @y = nx, ny
end

def +
@dx, @dy = -@dy, @dx
end

def -
@dx, @dy = @dy, -@dx
end

def evaluate(n)
raise “N must be non-negative” if n < 0
@x, @y = 0, 0
@dx, @dy = 900 / (3 ** n), 0

puts <<-HEADER
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>


HEADER

super

puts <<-FOOTER
FOOTER end end

koch.evaluate(ARGV[0].to_i)