--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 argumentnd > 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 move > 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 replace 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 component at > level 0). Feel free to use the console for output or get fancy with RMagick or > something similar. > > _ <-- 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 = 1, seq = nil super() @path = [:fw] seq = [:fw, :left, :fw, :right, :fw, :right, :fw, :left, :fw] level.times do @path.map! { |el| el == :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 = :e @path = path @dir = initial_dir @canvas = Hash.new { |h,k| h[k] = Hash.new { |h2,k2| h2[k2] = ' '} @x = @y = @min_x = @min_y = @max_x = @max_y = 0 end def paint @path.each { |step| step == :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 private def draw case @dir when :n; @y -= 1 when :s; @y += 1 when :e; @x += 1 when :w; @x -= 1 end @canvas[@x][@y] = 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 -= 1; @min_y = @y if @y < @min_y when :s; @y += 1; @max_y = @y if @y > @max_y when :e; @x += 1; @max_x = @x if @x > @max_x when :w; @x -= 1; @min_x = @x if @x < @min_x end end TURNS = { :n => { :left => :w, :right => :e }, :w => { :left => :s, :right => :n }, :s => { :left => :e, :right => :w }, :e => { :left => :n, :right => :s }, } def turn dir @dir = TURNS[@dir][dir] end end if __FILE__ == $0 level = ARGV[0] ? ARGV[0].to_i.abs : 3 t = 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 :-) -- 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 g+ -----END PGP SIGNATURE----- --k+w/mQv8wyuph6w0--