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