Решение на Трета задача от Христо Хърсев

Обратно към всички решения

Към профила на Христо Хърсев

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 60 успешни тест(а)
  • 9 неуспешни тест(а)

Код

module Graphics
class Canvas
attr_accessor :width, :height
def initialize width, height
@width = width
@height = height
@canvas = Array.new(height) { Array.new(width, 0) }
end
def set_pixel x, y
@canvas[y][x] = 1
end
def pixel_at? x, y
@canvas[y][x].eql? 1
end
def draw figure
return set_pixel(figure.x, figure.y) if figure.instance_of?(Point)
figure.points.each do |point|
set_pixel(point.x, point.y)
end
end
def render_as renderer
renderer.render @canvas
end
end
class Point
include Comparable
attr_accessor :x, :y
def initialize x, y
@x = x
@y = y
end
def <=>(other)
x == other.x ? y <=> other.y : x <=> other.x
end
def hash
[@x, @y].hash
end
def ==(other)
other.class == self.class and other.x == x and other.y == y
end
alias_method :eql?, :==
end
class Line
attr_accessor :from, :to
def initialize point_a, point_b
@from = [point_a, point_b].min
@to = [point_a, point_b].max
end
def points
algorithm = Bresenham.new(from, to)
algorithm.draw_line
end
def hash
[@from, @to].hash
end
def ==(other)
other.class == self.class and other.points == points
end
alias_method :eql?, :==
end
class Rectangle
def initialize point_a, point_b
@point_a = point_a
@point_b = point_b
end
def left
[@point_a, @point_b].min
end
def right
[@point_a, @point_b].max
end
def up
@point_a.y > @point_b.y ? @point_a : @point_b
end
def down
@point_a.y < @point_b.y ? @point_a : @point_b
end
def top_left
points.first
end
def top_right
points.group_by(&:x).max[1].first
end
def bottom_left
points.group_by(&:y).max[1].first
end
def bottom_right
points.last
end
def points
(
(left.x..right.x).map { |x| [Point.new(x, right.y), Point.new(x, left.y)] } +
(down.y..up.y) .map { |y| [Point.new(down.x, y), Point.new(up.x, y)] }
).flatten.uniq.sort
end
def hash
[@point_a, @point_b].hash
end
def ==(other)
other.class == self.class and other.points == points
end
alias_method :eql?, :==
private :up, :down
end
class Bresenham
def initialize from, to
@start_x, @start_y = from.x, from.y
@end_x, @end_y = to.x, to.y
@delta_x, @delta_y = (to.x - from.x).abs, -(to.y - from.y).abs
@step_x, @step_y = from.x < to.x ? 1 : -1, from.y < to.y ? 1 : -1
@error = @delta_x + @delta_y
end
def go_x_axis
@error += @delta_y
@start_x += @step_x
end
def go_y_axis
@error += @delta_x
@start_y += @step_y
end
def draw_line
points = [Point.new(@start_x, @start_y)]
while @start_x != @end_x or @start_y != @end_y
go_x_axis if @error * 2 >= @delta_y
go_y_axis if @error * 2 <= @delta_x
points << Point.new(@start_x, @start_y)
end
points
end
end
module Renderers
class Ascii
def self.render_rules
{'0' => '-', '1' => '@', "\n" => "\n"}
end
def self.render canvas
canvas.map { |row| row.join('') }.join("\n").gsub(/(1|0|\n)/, render_rules)
end
end
class Html
def self.render_rules
html = {'0' => '<i></i>', '1' => '<b></b>', "\n" => '<br>'}
html['BEFORE'] = <<-BEFORE
<!DOCTYPE html>
<html>
<head>
<title>Rendered Canvas</title>
<style type="text/css">
.canvas {
font-size: 1px;
line-height: 1px;
}
.canvas * {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 5px;
}
.canvas i {
background-color: #eee;
}
.canvas b {
background-color: #333;
}
</style>
</head>
<body>
<div class="canvas">
BEFORE
html['AFTER'] = <<-AFTER
</div>
</body>
</html>
AFTER
html
end
def self.render canvas
result = 'BEFORE' + canvas.map { |row| row.join('') }.join("\n") + 'AFTER'
result.gsub(/(BEFORE|AFTER|1|0|\n)/, render_rules)
end
end
end
end

Лог от изпълнението

....F...F.F..F.F...............F........F.....................FF.....

Failures:

  1) Graphics Canvas does not expose setters for the width or height
     Failure/Error: canvas.should_not respond_to :width=
       expected #<Graphics::Canvas:0xba77e100 @width=30, @height=20, @canvas=[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]> not to respond to :width=
     # /tmp/d20131223-4637-6zhphg/spec.rb:23:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "@@@@@@@@@@@@@@@\n@-------------@\n@-@@@@@@@@@@@-@\n@-@---------@-@\n@-@------@@-@-@\n@-@---@@@---@-@\n@-@-@@------@-@\n@-@---------@-@\n@-@-@@@@----@-@\n@-@-@-------@-@\n@-@---------@-@\n@-@---------@-@\n@-@@@@@@@@@@@-@\n@-------------@\n@@@@@@@@@@@@@@@"
            got: "@@@@@@@@@@@@@@@\n@-------------@\n@-@@@@@@@@@@@-@\n@-@---------@-@\n@-@-----@@@-@-@\n@-@--@@@----@-@\n@-@-@-------@-@\n@-@---------@-@\n@-@-@@@@----@-@\n@-@-@-------@-@\n@-@---------@-@\n@-@---------@-@\n@-@@@@@@@@@@@-@\n@-------------@\n@@@@@@@@@@@@@@@"
       
       (compared using ==)
       
       Diff:
       @@ -2,9 +2,9 @@
        @-------------@
        @-@@@@@@@@@@@-@
        @-@---------@-@
       -@-@------@@-@-@
       -@-@---@@@---@-@
       -@-@-@@------@-@
       +@-@-----@@@-@-@
       +@-@--@@@----@-@
       +@-@-@-------@-@
        @-@---------@-@
        @-@-@@@@----@-@
        @-@-@-------@-@
     # /tmp/d20131223-4637-6zhphg/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-6zhphg/spec.rb:211:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
     Failure/Error: canvas.set_pixel 4, 4
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-6zhphg/solution.rb:12:in `set_pixel'
     # /tmp/d20131223-4637-6zhphg/spec.rb:57:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@@-------\n---@@@@---\n-------@@-\n----------"
            got: "----------\n-@--------\n--@@@@----\n------@@@-\n----------"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
        ----------
       --@@-------
       ----@@@@---
       --------@@-
       +-@--------
       +--@@@@----
       +------@@@-
        ----------
     # /tmp/d20131223-4637-6zhphg/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-6zhphg/spec.rb:100:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "-@--------\n-@@-------\n-@-@@@@---\n-@-----@@-\n----------"
            got: "-@--------\n-@--------\n-@@@@@----\n-@----@@@-\n----------"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
        -@--------
       --@@-------
       --@-@@@@---
       --@-----@@-
       +-@--------
       +-@@@@@----
       +-@----@@@-
        ----------
     # /tmp/d20131223-4637-6zhphg/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-6zhphg/spec.rb:132:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Graphics shapes Point does not allow setting its x and y
     Failure/Error: point.should_not respond_to :x=
       expected #<Graphics::Point:0xba6a2254 @x=1, @y=2> not to respond to :x=
     # /tmp/d20131223-4637-6zhphg/spec.rb:337:in `block (4 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Graphics shapes Line initialization does not allow setting its from and to
     Failure/Error: line.should_not respond_to :from=
       expected #<Graphics::Line:0xba688020 @from=#<Graphics::Point:0xba688034 @x=1, @y=5>, @to=#<Graphics::Point:0xba68a014 @x=25, @y=2>> not to respond to :from=
     # /tmp/d20131223-4637-6zhphg/spec.rb:390:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Graphics shapes Rectangle comparison for equality returns the same hash if the rectangles are the same
     Failure/Error: a.hash.should eq b.hash
       
       expected: 317439998
            got: 291174878
       
       (compared using ==)
     # /tmp/d20131223-4637-6zhphg/spec.rb:556:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  9) Graphics shapes Rectangle comparison for equality returns the same hash for rectangles defined with different diagonal corners
     Failure/Error: a.hash.should eq b.hash
       
       expected: -375716916
            got: 645341044
       
       (compared using ==)
     # /tmp/d20131223-4637-6zhphg/spec.rb:563:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.09738 seconds
69 examples, 9 failures

Failed examples:

rspec /tmp/d20131223-4637-6zhphg/spec.rb:22 # Graphics Canvas does not expose setters for the width or height
rspec /tmp/d20131223-4637-6zhphg/spec.rb:203 # Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
rspec /tmp/d20131223-4637-6zhphg/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-6zhphg/spec.rb:96 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
rspec /tmp/d20131223-4637-6zhphg/spec.rb:127 # Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
rspec /tmp/d20131223-4637-6zhphg/spec.rb:335 # Graphics shapes Point does not allow setting its x and y
rspec /tmp/d20131223-4637-6zhphg/spec.rb:389 # Graphics shapes Line initialization does not allow setting its from and to
rspec /tmp/d20131223-4637-6zhphg/spec.rb:552 # Graphics shapes Rectangle comparison for equality returns the same hash if the rectangles are the same
rspec /tmp/d20131223-4637-6zhphg/spec.rb:559 # Graphics shapes Rectangle comparison for equality returns the same hash for rectangles defined with different diagonal corners

История (3 версии и 0 коментара)

Христо обнови решението на 22.12.2013 20:18 (преди почти 11 години)

+module Graphics
+ class Canvas
+ attr_accessor :width, :height
+
+ def initialize width, height
+ @width = width
+ @height = height
+ @canvas = Array.new(height) { Array.new(width, '0') }
+ end
+
+ def set_pixel x, y
+ @canvas[y][x] = '1'
+ end
+
+ def pixel_at? x, y
+ @canvas[y][x].eql? '1'
+ end
+
+ def draw figure
+ return set_pixel(figure.x, figure.y) if figure.instance_of?(Point)
+ figure.points.each do |point|
+ set_pixel(point.x, point.y)
+ end
+ end
+
+ def render_as renderer
+ result = 'BEFORE'
+ result += @canvas.map { |row| row.join('') }.join("\n")
+ result += 'AFTER'
+ result.gsub(/(BEFORE|AFTER|1|0|\n)/, renderer.render_rules)
+ end
+ end
+
+ class Point
+ include Comparable
+ attr_accessor :x, :y
+
+ def initialize x, y
+ @x = x
+ @y = y
+ end
+
+ def <=>(other)
+ x == other.x ? y <=> other.y : x <=> other.x
+ end
+
+ def hash
+ [@x, @y].hash
+ end
+
+ def ==(other)
+ other.class == self.class and other.x == x and other.y == y
+ end
+ alias_method :eql?, :==
+ end
+
+ class Line
+ attr_accessor :from, :to
+
+ def initialize point_a, point_b
+ @from = [point_a, point_b].min
+ @to = [point_a, point_b].max
+ end
+
+ def points
+ algorithm = Bresenham.new(from, to)
+ algorithm.draw_line
+ end
+
+ def hash
+ [@from, @to].hash
+ end
+
+ def ==(other)
+ other.class == self.class and other.points == points
+ end
+ alias_method :eql?, :==
+ end
+
+ class Rectangle
+ def initialize point_a, point_b
+ @point_a = point_a
+ @point_b = point_b
+ end
+
+ def left
+ [@point_a, @point_b].min
+ end
+
+ def right
+ [@point_a, @point_b].max
+ end
+
+ def up
+ @point_a.y > @point_b.y ? @point_a : @point_b
+ end
+
+ def down
+ @point_a.y < @point_b.y ? @point_a : @point_b
+ end
+
+ def top_left
+ points.first
+ end
+
+ def top_right
+ points.group_by(&:x).max[1].first
+ end
+
+ def bottom_left
+ points.group_by(&:y).max[1].first
+ end
+
+ def bottom_right
+ points.last
+ end
+
+ def points
+ (
+ (left.x..right.x).map { |x| [Point.new(x, right.y), Point.new(x, left.y)] } +
+ (down.y..up.y) .map { |y| [Point.new(down.x, y), Point.new(up.x, y)] }
+ ).flatten.uniq.sort
+ end
+
+ def hash
+ [@point_a, @point_b].hash
+ end
+
+ def ==(other)
+ other.class == self.class and other.points.sort == points.sort
+ end
+ alias_method :eql?, :==
+
+ private :up, :down
+ end
+
+ class Bresenham
+ def initialize from, to
+ @start_x, @start_y = from.x, from.y
+ @end_x, @end_y = to.x, to.y
+ @delta_x, @delta_y = (to.x - from.x).abs, -(to.y - from.y).abs
+ @step_x, @step_y = from.x < to.x ? 1 : -1, from.y < to.y ? 1 : -1
+ @error = @delta_x + @delta_y
+ end
+
+ def go_x_axis
+ @error += @delta_y
+ @start_x += @step_x
+ end
+
+ def go_y_axis
+ @error += @delta_x
+ @start_y += @step_y
+ end
+
+ def draw_line
+ points = [Point.new(@start_x, @start_y)]
+ while @start_x != @end_x or @start_y != @end_y
+ go_x_axis if @error * 2 >= @delta_y
+ go_y_axis if @error * 2 <= @delta_x
+ points << Point.new(@start_x, @start_y)
+ end
+ points
+ end
+ end
+
+ module Renderers
+
+ class Ascii
+ def self.render_rules
+ {"0" => "-", "1" => "@", "\n" => "\n", "BEFORE" => '', "AFTER" => '' }
+ end
+ end
+
+ class Html
+ def self.render_rules
+ html = {"0" => "<i></i>", "1" => "<b></b>", "\n" => "<br>" }
+ html['BEFORE'] = <<-BEFORE
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Rendered Canvas</title>
+ <style type="text/css">
+ .canvas {
+ font-size: 1px;
+ line-height: 1px;
+ }
+ .canvas * {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ border-radius: 5px;
+ }
+ .canvas i {
+ background-color: #eee;
+ }
+ .canvas b {
+ background-color: #333;
+ }
+ </style>
+</head>
+<body>
+ <div class="canvas">
+BEFORE
+ html['AFTER'] = <<-AFTER
+ </div>
+</body>
+</html>
+AFTER
+ html
+ end
+ end
+ end
+end

Христо обнови решението на 22.12.2013 21:11 (преди почти 11 години)

module Graphics
class Canvas
attr_accessor :width, :height
def initialize width, height
@width = width
@height = height
- @canvas = Array.new(height) { Array.new(width, '0') }
+ @canvas = Array.new(height) { Array.new(width, 0) }
end
def set_pixel x, y
- @canvas[y][x] = '1'
+ @canvas[y][x] = 1
end
def pixel_at? x, y
- @canvas[y][x].eql? '1'
+ @canvas[y][x].eql? 1
end
def draw figure
return set_pixel(figure.x, figure.y) if figure.instance_of?(Point)
figure.points.each do |point|
set_pixel(point.x, point.y)
end
end
def render_as renderer
- result = 'BEFORE'
- result += @canvas.map { |row| row.join('') }.join("\n")
- result += 'AFTER'
- result.gsub(/(BEFORE|AFTER|1|0|\n)/, renderer.render_rules)
+ renderer.render @canvas
end
end
class Point
include Comparable
attr_accessor :x, :y
def initialize x, y
@x = x
@y = y
end
def <=>(other)
x == other.x ? y <=> other.y : x <=> other.x
end
def hash
[@x, @y].hash
end
def ==(other)
other.class == self.class and other.x == x and other.y == y
end
alias_method :eql?, :==
end
class Line
attr_accessor :from, :to
def initialize point_a, point_b
@from = [point_a, point_b].min
@to = [point_a, point_b].max
end
def points
algorithm = Bresenham.new(from, to)
algorithm.draw_line
end
def hash
[@from, @to].hash
end
def ==(other)
other.class == self.class and other.points == points
end
alias_method :eql?, :==
end
class Rectangle
def initialize point_a, point_b
@point_a = point_a
@point_b = point_b
end
def left
[@point_a, @point_b].min
end
def right
[@point_a, @point_b].max
end
def up
@point_a.y > @point_b.y ? @point_a : @point_b
end
def down
@point_a.y < @point_b.y ? @point_a : @point_b
end
def top_left
points.first
end
def top_right
points.group_by(&:x).max[1].first
end
def bottom_left
points.group_by(&:y).max[1].first
end
def bottom_right
points.last
end
def points
(
(left.x..right.x).map { |x| [Point.new(x, right.y), Point.new(x, left.y)] } +
(down.y..up.y) .map { |y| [Point.new(down.x, y), Point.new(up.x, y)] }
).flatten.uniq.sort
end
def hash
[@point_a, @point_b].hash
end
def ==(other)
other.class == self.class and other.points.sort == points.sort
end
alias_method :eql?, :==
private :up, :down
end
class Bresenham
def initialize from, to
@start_x, @start_y = from.x, from.y
@end_x, @end_y = to.x, to.y
@delta_x, @delta_y = (to.x - from.x).abs, -(to.y - from.y).abs
@step_x, @step_y = from.x < to.x ? 1 : -1, from.y < to.y ? 1 : -1
@error = @delta_x + @delta_y
end
def go_x_axis
@error += @delta_y
@start_x += @step_x
end
def go_y_axis
@error += @delta_x
@start_y += @step_y
end
def draw_line
points = [Point.new(@start_x, @start_y)]
while @start_x != @end_x or @start_y != @end_y
go_x_axis if @error * 2 >= @delta_y
go_y_axis if @error * 2 <= @delta_x
points << Point.new(@start_x, @start_y)
end
points
end
end
module Renderers
-
class Ascii
def self.render_rules
- {"0" => "-", "1" => "@", "\n" => "\n", "BEFORE" => '', "AFTER" => '' }
+ {'0' => '-', '1' => '@', "\n" => "\n"}
end
+
+ def self.render canvas
+ canvas.map { |row| row.join('') }.join("\n").gsub(/(1|0|\n)/, render_rules)
+ end
end
class Html
def self.render_rules
- html = {"0" => "<i></i>", "1" => "<b></b>", "\n" => "<br>" }
+ html = {'0' => '<i></i>', '1' => '<b></b>', "\n" => '<br>'}
+
html['BEFORE'] = <<-BEFORE
<!DOCTYPE html>
<html>
<head>
<title>Rendered Canvas</title>
<style type="text/css">
.canvas {
font-size: 1px;
line-height: 1px;
}
.canvas * {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 5px;
}
.canvas i {
background-color: #eee;
}
.canvas b {
background-color: #333;
}
</style>
</head>
<body>
<div class="canvas">
BEFORE
+
html['AFTER'] = <<-AFTER
</div>
</body>
</html>
AFTER
html
+ end
+
+ def self.render canvas
+ result = 'BEFORE' + canvas.map { |row| row.join('') }.join("\n") + 'AFTER'
+ result.gsub(/(BEFORE|AFTER|1|0|\n)/, render_rules)
end
end
end
end

Христо обнови решението на 22.12.2013 21:17 (преди почти 11 години)

module Graphics
class Canvas
attr_accessor :width, :height
def initialize width, height
@width = width
@height = height
@canvas = Array.new(height) { Array.new(width, 0) }
end
def set_pixel x, y
@canvas[y][x] = 1
end
def pixel_at? x, y
@canvas[y][x].eql? 1
end
def draw figure
return set_pixel(figure.x, figure.y) if figure.instance_of?(Point)
figure.points.each do |point|
set_pixel(point.x, point.y)
end
end
def render_as renderer
renderer.render @canvas
end
end
class Point
include Comparable
attr_accessor :x, :y
def initialize x, y
@x = x
@y = y
end
def <=>(other)
x == other.x ? y <=> other.y : x <=> other.x
end
def hash
[@x, @y].hash
end
def ==(other)
other.class == self.class and other.x == x and other.y == y
end
alias_method :eql?, :==
end
class Line
attr_accessor :from, :to
def initialize point_a, point_b
@from = [point_a, point_b].min
@to = [point_a, point_b].max
end
def points
algorithm = Bresenham.new(from, to)
algorithm.draw_line
end
def hash
[@from, @to].hash
end
def ==(other)
other.class == self.class and other.points == points
end
alias_method :eql?, :==
end
class Rectangle
def initialize point_a, point_b
@point_a = point_a
@point_b = point_b
end
def left
[@point_a, @point_b].min
end
def right
[@point_a, @point_b].max
end
def up
@point_a.y > @point_b.y ? @point_a : @point_b
end
def down
@point_a.y < @point_b.y ? @point_a : @point_b
end
def top_left
points.first
end
def top_right
points.group_by(&:x).max[1].first
end
def bottom_left
points.group_by(&:y).max[1].first
end
def bottom_right
points.last
end
def points
(
(left.x..right.x).map { |x| [Point.new(x, right.y), Point.new(x, left.y)] } +
(down.y..up.y) .map { |y| [Point.new(down.x, y), Point.new(up.x, y)] }
).flatten.uniq.sort
end
def hash
[@point_a, @point_b].hash
end
def ==(other)
- other.class == self.class and other.points.sort == points.sort
+ other.class == self.class and other.points == points
end
alias_method :eql?, :==
private :up, :down
end
class Bresenham
def initialize from, to
@start_x, @start_y = from.x, from.y
@end_x, @end_y = to.x, to.y
@delta_x, @delta_y = (to.x - from.x).abs, -(to.y - from.y).abs
@step_x, @step_y = from.x < to.x ? 1 : -1, from.y < to.y ? 1 : -1
@error = @delta_x + @delta_y
end
def go_x_axis
@error += @delta_y
@start_x += @step_x
end
def go_y_axis
@error += @delta_x
@start_y += @step_y
end
def draw_line
points = [Point.new(@start_x, @start_y)]
while @start_x != @end_x or @start_y != @end_y
go_x_axis if @error * 2 >= @delta_y
go_y_axis if @error * 2 <= @delta_x
points << Point.new(@start_x, @start_y)
end
points
end
end
module Renderers
class Ascii
def self.render_rules
{'0' => '-', '1' => '@', "\n" => "\n"}
end
def self.render canvas
canvas.map { |row| row.join('') }.join("\n").gsub(/(1|0|\n)/, render_rules)
end
end
class Html
def self.render_rules
html = {'0' => '<i></i>', '1' => '<b></b>', "\n" => '<br>'}
html['BEFORE'] = <<-BEFORE
<!DOCTYPE html>
<html>
<head>
<title>Rendered Canvas</title>
<style type="text/css">
.canvas {
font-size: 1px;
line-height: 1px;
}
.canvas * {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 5px;
}
.canvas i {
background-color: #eee;
}
.canvas b {
background-color: #333;
}
</style>
</head>
<body>
<div class="canvas">
BEFORE
html['AFTER'] = <<-AFTER
</div>
</body>
</html>
AFTER
html
end
def self.render canvas
result = 'BEFORE' + canvas.map { |row| row.join('') }.join("\n") + 'AFTER'
result.gsub(/(BEFORE|AFTER|1|0|\n)/, render_rules)
end
end
end
end