Андрея обнови решението на 02.12.2015 15:40 (преди около 9 години)
+module MatrixHelper
+ def empty_matrix(width, height, fill)
+ Array.new(width) { Array.new(height) { fill } }
+ end
+end
+
+module TurtleGraphics
+ class Turtle
+ include MatrixHelper
+
+ def initialize(width, height)
+ @width = width
+ @height = height
+ spawn_at(0, 0)
+ look(:right)
+ end
+
+ def draw(canvas = TurtleGraphics::Canvas::Default.new, &block)
+ instance_eval(&block) if block_given?
+ canvas.result(@matrix)
+ end
+
+ private
+
+ DIRECTIONS = { left: [-1, 0], up: [0, -1], right: [1, 0], down: [0, 1] }
+
+ def move
+ direction_mask = DIRECTIONS[@orientation]
+ @x = new_position(@x + direction_mask.first, @matrix[@y].length)
+ @y = new_position(@y + direction_mask.last, @matrix.length)
+ mark_position
+ end
+
+ def new_position(position, length)
+ if position >= length
+ 0
+ elsif position < 0
+ length - 1
+ else
+ position
+ end
+ end
+
+ def turn_left
+ next_index = DIRECTIONS.keys.index(@orientation).pred
+ @orientation = DIRECTIONS.keys[next_index]
+ end
+
+ def turn_right
+ current_index = DIRECTIONS.keys.index(@orientation)
+ if current_index.next == DIRECTIONS.keys.length
+ @orientation = DIRECTIONS.keys[0]
+ else
+ @orientation = DIRECTIONS.keys[current_index.next]
+ end
+ end
+
+ def spawn_at(row, column)
+ @matrix = empty_matrix(@width, @height, 0)
+ @x = column
+ @y = row
+ mark_position
+ end
+
+ def look(orientation)
+ @orientation = orientation
+ end
+
+ def mark_position
+ @matrix[@y][@x] = @matrix[@y][@x].next
+ end
+ end
+
+ module Canvas
+ class Default
+ def result(matrix)
+ matrix
+ end
+ end
+
+ class ASCII
+ include MatrixHelper
+
+ def initialize(symbols)
+ symbols = symbols.dup
+ @symbols = {}
+ @zero_intensity_symbol = symbols.slice!(0)
+ step = 1.to_f / symbols.size
+ count = 0
+ while count < symbols.size
+ @symbols.store(((count * step)..((count + 1) * step)), symbols[count])
+ count = count.next
+ end
+ end
+
+ def result(matrix)
+ max_step = max_step(matrix)
+ if max_step == 0
+ empty_matrix(matrix.length, matrix[0].length, @zero_intensity_symbol)
+ else
+ generate_string(matrix, max_step)
+ end
+ end
+
+ private
+
+ def generate_string(matrix, max_step)
+ matrix.map { |row| row.map { |c| intensity(c.to_f / max_step) } }
+ .collect(&:join)
+ .join("\n")
+ end
+
+ def max_step(matrix)
+ matrix.max_by(&:max).max
+ end
+
+ def intensity(cell)
+ if cell == 0.0
+ @zero_intensity_symbol
+ else
+ @symbols.select { |range| range.include?(cell) }.values.first
+ end
+ end
+ end
+ end
+end