--k+w/mQv8wyuph6w0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On 2007-05-25 22:18:32 +0900 (Fri, May), Ruby Quiz wrote:
> The goal is to create a ruby program which takes the level as an argument=
 and
> then draws the fractal shown below to the specified level. The fractal is
> created by drawing the first level, then repeating the pattern such that =
each
> base piece is replaced with the fractal from the higher level. Thus, to m=
ove
> from level 1 to level 2, we replace each line with the shape at level 1. =
Notice
> that the position changes as well, meaning if the line is vertical we rep=
lace it
> with a vertically positioned shape of level 1 (right and left facing also
> matter). I have shown the first 3 levels below (including the base compon=
ent at
> level 0). Feel free to use the console for output or get fancy with RMagi=
ck or
> something similar.
>=20
> 	                          _                  <-- Level 0
> 	                          _
> 	                        _| |_                <-- Level 1
> 	                          _
> 	                        _| |_
> 	                      _|     |_              <-- Level 2
> 	                    _|_       _|_
> 	                  _| |_|     |_| |_


#!/usr/bin/ruby -w

# The Fractal objects are a sequence of steps to draw
# an image. In Logo the drawing would be extremely easy.
class Fractal
  attr_reader :path

  # +level+ may be 0 or greater, and should be something like an integer.
  #
  # +seq+ is an array with a sequence of steps (:fw, :right, or :left) which
  # will replace each :fw (means: forward) part of the path.
  # A nice default is provided.
  def initialize level =3D 1, seq =3D nil
    super()
    @path =3D [:fw]
    seq =3D [:fw, :left, :fw, :right, :fw, :right, :fw, :left, :fw]
    level.times do
      @path.map! { |el| el =3D=3D :fw ? seq.dup : el }.flatten!
    end
  end
end

# AsciiArtCanvas draws a given Fractal.path on an array of strings.
class AsciiArtCanvas

  def initialize path, initial_dir =3D :e
    @path =3D path
    @dir =3D initial_dir
    @canvas =3D Hash.new { |h,k| h[k] =3D Hash.new { |h2,k2| h2[k2] =3D ' '=
 }}
    @x =3D @y =3D @min_x =3D @min_y =3D @max_x =3D @max_y =3D 0
  end

  def paint
    @path.each { |step| step =3D=3D :fw ? draw : turn(step) }
    (@min_y..@max_y).inject([]) do |arr,y|
      arr << (@min_x..@max_x).inject('') do |row,x|
        row + @canvas[x][y]
      end
    end
  end
 =20
  private
    def draw
      case @dir
      when :n;  @y -=3D 1
      when :s;  @y +=3D 1
      when :e;  @x +=3D 1
      when :w;  @x -=3D 1
      end

      @canvas[@x][@y] =3D case @canvas[@x][@y]
                        when '+'; '+'
                        when '-'; [:n,:s].include?( @dir ) ? '+' : '-'
                        when '|'; [:w,:e].include?( @dir ) ? '+' : '|'
                        else      [:n,:s].include?( @dir ) ? '|' : '-'
                        end
      case @dir
      when :n;  @y -=3D 1; @min_y =3D @y if @y < @min_y
      when :s;  @y +=3D 1; @max_y =3D @y if @y > @max_y
      when :e;  @x +=3D 1; @max_x =3D @x if @x > @max_x
      when :w;  @x -=3D 1; @min_x =3D @x if @x < @min_x
      end
    end

    TURNS =3D {
      :n =3D> { :left =3D> :w, :right =3D> :e },
      :w =3D> { :left =3D> :s, :right =3D> :n },
      :s =3D> { :left =3D> :e, :right =3D> :w },
      :e =3D> { :left =3D> :n, :right =3D> :s },
    }
    def turn dir
      @dir =3D TURNS[@dir][dir]
    end
     =20
end

if __FILE__ =3D=3D $0
  level =3D ARGV[0] ? ARGV[0].to_i.abs : 3

  t =3D Fractal.new level
  puts( *AsciiArtCanvas.new(t.path, :e).paint )
end


It's terribly inefficient for high levels:

$ time ./fract.rb 4
[...]
real    0m0.297s

for level 4:  0.297s
for level 5:  1.917s
for level 6: 37.449s
I'm too scared to run it with level 7 :-)

--=20
No virus found in this outgoing message.
Checked by 'grep -i virus $MESSAGE'
Trust me.

--k+w/mQv8wyuph6w0
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7-ecc0.1.6 (GNU/Linux)

iD8DBQFGWZDDsnU0scoWZKARAghFAKDOmQ9rFq4FPhq3mpaNACVkQ+LRdwCeOtFH
7Xvp1dPsQ5OU8y0Bylsyzg8=
=iZg+
-----END PGP SIGNATURE-----

--k+w/mQv8wyuph6w0--