Решение на Трета задача от Михаил Господинов

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

Към профила на Михаил Господинов

Резултати

  • 3 точки от тестове
  • 0 бонус точки
  • 3 точки общо
  • 38 успешни тест(а)
  • 31 неуспешни тест(а)

Код

module Graphics
class Point
attr_reader :x, :y
def initialize(x,y)
@x = x
@y = y
end
def ==(other)
(@x == other.x) and (@y == other.y)
end
def hash
[@x , @y].hash
end
def self.topmost(first,second)
if first.y < second.y then first else second end
end
def self.leftmost(first,second)
if first.x < second.x then first else second end
end
def self.rightmost(first,second)
if first.y > second.y then first else second end
end
def self.bottommost(first,second)
if first.x > second.x then first else second end
end
def render_on(canvas)
canvas.set_pixel @x, @y
end
alias_method :==, :eql?
end
module PointsPair
attr_reader :first, :second
def initialize(start,finish)
if start.x == finish.x
@first = Point.topmost start, finish
@second = Point.bottommost start, finish
else
@first = Point.leftmost start, finish
@second = Point.bottommost start, finish
end
end
def hash
[@first, @second].hash
end
def ==(other)
(@first == other.first) and (@second == other.second)
end
alias_method :==, :eql?
end
class Line
include PointsPair
alias_method :from, :first
alias_method :to, :second
def rasterize_plot_x(delta_x,delta_y,x, y,max, offset_x, offset_y, &block)
error = delta_x / 2.0
while x != max
error, x = error - delta_y, x+offset_x
if error <= 0
y, error = y + offset_y, error + delta_x
end
yield Point.new x,y
end
end
def rasterize_plot_y(delta_x,delta_y,x, y,max, offset_x, offset_y, &block)
error = delta_y / 2.0
while y != max
error, y = error - delta_x, y + offset_y
if error <= 0
x, error = x + offset_x, error + delta_y
end
yield Point.new x,y
end
end
def rasterize(a, b,&block)
delta_x, delta_y, x, y = (b.x - a.x).abs, (b.y - a.y).abs, a.x, a.y
offset_x, offset_y = a.x > b.x ? -1 : 1 , a.y > b.y ? -1 : 1
yield Point.new x,y
if delta_x > delta_y
rasterize_plot_x delta_x,delta_y,x,y, b.x, offset_x, offset_y, &block
else
rasterize_plot_y delta_x,delta_y,x,y, b.y, offset_x, offset_y, &block
end
end
def render_on(canvas)
if @first.x == @second.x
min = [@first.y,@second.y].min
max = [@first.y,@second.y].max
(min .. max).each {|y| canvas.set_pixel @first.x, y}
else
rasterize(@first,@second) {|point| canvas.set_pixel point.x, point.y}
end
end
end
class Rectangle
include PointsPair
alias_method :left, :first
alias_method :right, :second
def top_left
@top_left ||= Point.new @first.x, [@first.y, @second.y].min
end
def top_right
@top_right ||= Point.new @second.x, [@first.y, @second.y].min
end
def bottom_left
@bottom_left ||= Point.new @first.x, [@first.y, @second.y].max
end
def bottom_right
@bottom_right ||= Point.new @second.x, [@first.y, @second.y].max
end
def render_on(canvas)
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x, top_left.y}
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x,bottom_left.y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_left.x,y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_right.x,y}
end
end
class Canvas
attr_reader :width, :height
def initialize(width,height)
@width = width
@height = height
@pane = Array.new(height) {Array.new width,false}
end
def draw(figure)
figure.render_on self
end
def set_pixel(x, y)
@pane[x][y] = true
end
def pixel_at?(x, y)
@pane[x][y]
end
def render_as(renderer)
renderer.render(self)
end
end
module Renderers
class Ascii
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "\n"
end
result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "@" else "-" end
end
end
class Html
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "<br/>"
end
DATA.read.sub ">FINDME",result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "<b></b>" else "<i></i>" end
end
end
end
end
__END__
<!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">
>FINDME
</div>
</body>
</html>

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

........F.FFFFFFFFFFFFFFFFFF....F.F.........F.FFFF........FFFF.F.....

Failures:

  1) 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@@@@@@@@@@@@@@@\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20131223-4637-1rf86mr/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/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)>'

  2) 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-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/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)>'

  3) Graphics Canvas drawing of shapes and rasterization of lines works with simple horizontal lines
     Failure/Error: canvas.draw make_line(make_point(3, 1), make_point(6, 1))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:111:in `block in render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:96:in `rasterize'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:111:in `render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:155:in `draw'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:71: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 vertical lines
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "-@------\n-@------\n-@------\n-@------\n-@------\n-@------\n-@------\n--------"
            got: "-@------\n-@------\n-@------\n-@------\n-@------\n-@------\n-@------\n--------\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20131223-4637-1rf86mr/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:84: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 lines with a small slope
     Failure/Error: canvas.draw make_line(make_point(1, 1), make_point(8, 3))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:111:in `block in render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:77:in `rasterize_plot_x'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:99:in `rasterize'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:111:in `render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:155:in `draw'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:98: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 Canvas drawing of shapes and rasterization of lines works with lines with a significant slope, with swapped ends
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@--------\n-@--------\n--@-------\n--@-------\n--@-------\n--@-------\n---@------\n---@------\n----------"
            got: "----------\n-@--------\n-@--------\n--@-------\n--@-------\n--@-------\n--@-------\n---@------\n---@------\n----------\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20131223-4637-1rf86mr/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:113: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)>'

  7) Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
     Failure/Error: canvas.draw make_line(make_point(1, 1), make_point(8, 3))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:111:in `block in render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:77:in `rasterize_plot_x'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:99:in `rasterize'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:111:in `render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:155:in `draw'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:129: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 Canvas drawing of shapes and rasterization of lines draws lines with two equal ends as points
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "---\n-@-\n---"
            got: "---\n-@-\n---\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20131223-4637-1rf86mr/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:145: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 Canvas drawing of shapes and rasterization of rectangles works with simple rects
     Failure/Error: canvas.draw make_rectangle(make_point(1, 1), make_point(8, 3))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `block in render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:155:in `draw'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:156: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)>'

  10) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects defined with their bottom left and top right points
     Failure/Error: canvas.draw make_rectangle(make_point(1, 3), make_point(8, 1))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `block in render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:155:in `draw'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:169: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)>'

  11) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero height as a line
     Failure/Error: canvas.draw make_rectangle(make_point(1, 1), make_point(8, 1))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `block in render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:139:in `render_on'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:155:in `draw'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:182: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)>'

  12) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero width and height as a single point
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "---\n-@-\n---"
            got: "---\n-@-\n---\n"
       
       (compared using ==)
       
       Diff:
     # /tmp/d20131223-4637-1rf86mr/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:195: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)>'

  13) Graphics Renderers Ascii renders a grid of the size of the canvas
     Failure/Error: lines = canvas.render_as(ascii).split("\n")
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:163:in `pixel_at?'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:185:in `print_character'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:177:in `block (2 levels) in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:176:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:176:in `block in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:175:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:175:in `render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:167:in `render_as'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:238: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)>'

  14) Graphics Renderers Ascii renders blank canvases
     Failure/Error: canvas.render_as(ascii).should eq rendering('
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:163:in `pixel_at?'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:185:in `print_character'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:177:in `block (2 levels) in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:176:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:176:in `block in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:175:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:175:in `render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:167:in `render_as'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:245: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)>'

  15) Graphics Renderers Ascii renders simple canvases
     Failure/Error: canvas.set_pixel 3, 2
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:159:in `set_pixel'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:254: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)>'

  16) Graphics Renderers Html returns html
     Failure/Error: rendering = normalize_html canvas.render_as(html)
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:163:in `pixel_at?'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:203:in `print_character'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:195:in `block (2 levels) in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `block in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:167:in `render_as'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:272: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)>'

  17) Graphics Renderers Html renders a grid of the size of the canvas
     Failure/Error: rendering = normalize_html canvas.render_as(html)
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:163:in `pixel_at?'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:203:in `print_character'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:195:in `block (2 levels) in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `block in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:167:in `render_as'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:309:in `html_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:281: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)>'

  18) Graphics Renderers Html renders simple canvases
     Failure/Error: rendering = normalize_html canvas.render_as(html)
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:163:in `pixel_at?'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:203:in `print_character'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:195:in `block (2 levels) in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `block in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:167:in `render_as'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:309:in `html_rendering_of'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:291: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)>'

  19) Graphics Renderers Html returns the same rendering when called twice
     Failure/Error: first_rendering  = normalize_html canvas.render_as(html)
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # /tmp/d20131223-4637-1rf86mr/solution.rb:163:in `pixel_at?'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:203:in `print_character'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:195:in `block (2 levels) in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:194:in `block in render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `each'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:193:in `render'
     # /tmp/d20131223-4637-1rf86mr/solution.rb:167:in `render_as'
     # /tmp/d20131223-4637-1rf86mr/spec.rb:302: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)>'

  20) Graphics shapes Point comparison for equality is true if coordinates are the same
     Failure/Error: (a1 == a2).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:348: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)>'

  21) Graphics shapes Point comparison for equality works for eql? as well
     Failure/Error: a1.should eql a2
       
       expected: #<Graphics::Point:0xb9ca5350 @x=4, @y=5>
            got: #<Graphics::Point:0xb9ca5378 @x=4, @y=5>
       
       (compared using eql?)
       
       Diff:
       @@ -1,2 +1,2 @@
       -#<Graphics::Point:0xb9ca5350 @x=4, @y=5>
       +#<Graphics::Point:0xb9ca5378 @x=4, @y=5>
     # /tmp/d20131223-4637-1rf86mr/spec.rb:356: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)>'

  22) Graphics shapes Line initialization with swapped points puts the bottom point of vertical lines in the to field
     Failure/Error: vertical_line.to.y.should eq 8
       
       expected: 8
            got: 1
       
       (compared using ==)
     # /tmp/d20131223-4637-1rf86mr/spec.rb:418:in `block (6 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)>'

  23) Graphics shapes Line comparison for equality is true if line ends are the same
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:435: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)>'

  24) Graphics shapes Line comparison for equality is true if line ends are the same, even if swapped
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:442: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)>'

  25) Graphics shapes Line comparison for equality is true if line is vertical and the bottom is given first
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:449: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)>'

  26) Graphics shapes Line comparison for equality works with eql? as well
     Failure/Error: a.should eql b
       
       expected: #<Graphics::Line:0xb9c752e0 @first=#<Graphics::Point:0xb9c7536c @x=1, @y=1>, @second=#<Graphics::Point:0xb9c75344 @x=10, @y=14>>
            got: #<Graphics::Line:0xb9c75394 @first=#<Graphics::Point:0xb9c753f8 @x=1, @y=1>, @second=#<Graphics::Point:0xb9c753d0 @x=10, @y=14>>
       
       (compared using eql?)
       
       Diff:
       @@ -1,4 +1,4 @@
       -#<Graphics::Line:0xb9c752e0
       - @first=#<Graphics::Point:0xb9c7536c @x=1, @y=1>,
       - @second=#<Graphics::Point:0xb9c75344 @x=10, @y=14>>
       +#<Graphics::Line:0xb9c75394
       + @first=#<Graphics::Point:0xb9c753f8 @x=1, @y=1>,
       + @second=#<Graphics::Point:0xb9c753d0 @x=10, @y=14>>
     # /tmp/d20131223-4637-1rf86mr/spec.rb:457: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)>'

  27) Graphics shapes Rectangle comparison for equality is true if rectangle points are the same
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:526: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)>'

  28) Graphics shapes Rectangle comparison for equality is true if rectangle points are the same, even if swapped
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:533: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)>'

  29) Graphics shapes Rectangle comparison for equality is true for rectangles defined with different diagonal corners
     Failure/Error: (a == b).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-1rf86mr/spec.rb:540: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)>'

  30) Graphics shapes Rectangle comparison for equality works with eql? as well
     Failure/Error: a.should eql b
       
       expected: #<Graphics::Rectangle:0xb9c4be04 @first=#<Graphics::Point:0xb9c4bef4 @x=1, @y=1>, @second=#<Graphics::Point:0xb9c4be40 @x=10, @y=14>>
            got: #<Graphics::Rectangle:0xb9c4bf44 @first=#<Graphics::Point:0xb9c52eac @x=1, @y=1>, @second=#<Graphics::Point:0xb9c4bfd0 @x=10, @y=14>>
       
       (compared using eql?)
       
       Diff:
       @@ -1,4 +1,4 @@
       -#<Graphics::Rectangle:0xb9c4be04
       - @first=#<Graphics::Point:0xb9c4bef4 @x=1, @y=1>,
       - @second=#<Graphics::Point:0xb9c4be40 @x=10, @y=14>>
       +#<Graphics::Rectangle:0xb9c4bf44
       + @first=#<Graphics::Point:0xb9c52eac @x=1, @y=1>,
       + @second=#<Graphics::Point:0xb9c4bfd0 @x=10, @y=14>>
     # /tmp/d20131223-4637-1rf86mr/spec.rb:548: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)>'

  31) 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: 46574126
            got: -452139842
       
       (compared using ==)
     # /tmp/d20131223-4637-1rf86mr/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.08612 seconds
69 examples, 31 failures

Failed examples:

rspec /tmp/d20131223-4637-1rf86mr/spec.rb:203 # Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:69 # Graphics Canvas drawing of shapes and rasterization of lines works with simple horizontal lines
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:80 # Graphics Canvas drawing of shapes and rasterization of lines works with vertical lines
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:96 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:109 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a significant slope, with swapped ends
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:127 # Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:141 # Graphics Canvas drawing of shapes and rasterization of lines draws lines with two equal ends as points
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:154 # Graphics Canvas drawing of shapes and rasterization of rectangles works with simple rects
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:167 # Graphics Canvas drawing of shapes and rasterization of rectangles works with rects defined with their bottom left and top right points
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:180 # Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero height as a line
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:191 # Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero width and height as a single point
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:237 # Graphics Renderers Ascii renders a grid of the size of the canvas
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:244 # Graphics Renderers Ascii renders blank canvases
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:252 # Graphics Renderers Ascii renders simple canvases
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:271 # Graphics Renderers Html returns html
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:280 # Graphics Renderers Html renders a grid of the size of the canvas
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:287 # Graphics Renderers Html renders simple canvases
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:298 # Graphics Renderers Html returns the same rendering when called twice
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:347 # Graphics shapes Point comparison for equality is true if coordinates are the same
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:355 # Graphics shapes Point comparison for equality works for eql? as well
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:416 # Graphics shapes Line initialization with swapped points puts the bottom point of vertical lines in the to field
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:431 # Graphics shapes Line comparison for equality is true if line ends are the same
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:438 # Graphics shapes Line comparison for equality is true if line ends are the same, even if swapped
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:445 # Graphics shapes Line comparison for equality is true if line is vertical and the bottom is given first
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:452 # Graphics shapes Line comparison for equality works with eql? as well
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:522 # Graphics shapes Rectangle comparison for equality is true if rectangle points are the same
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:529 # Graphics shapes Rectangle comparison for equality is true if rectangle points are the same, even if swapped
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:536 # Graphics shapes Rectangle comparison for equality is true for rectangles defined with different diagonal corners
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:543 # Graphics shapes Rectangle comparison for equality works with eql? as well
rspec /tmp/d20131223-4637-1rf86mr/spec.rb:559 # Graphics shapes Rectangle comparison for equality returns the same hash for rectangles defined with different diagonal corners

История (5 версии и 1 коментар)

Михаил обнови решението на 22.12.2013 01:13 (преди почти 11 години)

+module Graphics
+ class Point
+
+ def initialize(x,y)
+ @x = x
+ @y = y
+ end
+
+ def x
+ @x
+ end
+
+ def y
+ @y
+ end
+
+ def ==(other)
+ (@x == other.x) and (@y == other.y)
+ end
+
+ def hash
+ [@x , @y].hash
+ end
+
+ def self.topmost(first,second)
+ if first.y < second.y then first else second end
+ end
+
+ def self.leftmost(first,second)
+ if first.x < second.x then first else second end
+ end
+
+ def self.rightmost(first,second)
+ if first.y > second.y then first else second end
+ end
+
+ def self.bottommost(first,second)
+ if first.x > second.x then first else second end
+ end
+
+ def modify(canvas)
+ canvas.set_pixel @x, @y
+ end
+
+ alias_method :==, :eql?
+ end
+
+ class PointDouble
+ def initialize(start,finish)
+ if start.x == finish.x
+ @first = Point.topmost start, finish
+ @second = Point.bottommost start, finish
+ else
+ @first = Point.leftmost start, finish
+ @second = Point.bottommost start, finish
+ end
+ end
+
+ def first
+ @first
+ end
+
+ def second
+ @second
+ end
+
+ def hash
+ [@first, @second].hash
+ end
+
+ def ==(other)
+ (@first == other.first) and (@second == other.second)
+ end
+
+ alias_method :==, :eql?
+ end
+
+ class Line < PointDouble
+ alias_method :from, :first
+ alias_method :to, :second
+
+ def bresenham_plot(x_start,x_end,y,delta_x,delta_y,error)
+ x_start.upto(x_end) do |x|
+ if error > 0
+ y , error = y + 1 , error + 2 * delta_y - 2 * delta_x
+ yield Point.new x,y
+ else
+ yield Point.new x,y
+ error = error + 2*delta_y
+ end
+ end
+ end
+
+ def bresenham(first, second, &block)
+ delta_x, delta_y = second.x - first.x, second.y - first.y
+ error, y = 2*delta_y - delta_x , first.y
+ yield Point.new first.x,first.y
+ bresenham_plot first.x,second.x,y,delta_x,delta_y,error,&block
+ end
+
+ def modify(canvas)
+ if @first.x == @second.x
+ min = [@first.y,@second.y].min
+ max = [@first.y,@second.y].max
+ (min .. max).each {|y| canvas.set_pixel @first.x, y}
+ else
+ bresenham(@first,@second) {|point| canvas.set_pixel point.x, point.y}
+ end
+ end
+ end
+
+ class Rectangle < PointDouble
+ alias_method :left, :first
+ alias_method :right, :second
+
+ def top_left
+ if @top_left.nil?
+ left = @first.x
+ top = [@first.y, @second.y].min
+ @top_left = Point.new left, top
+ end
+ @top_left
+ end
+
+ def top_right
+ if @top_right.nil?
+ right = @second.x
+ top = [@first.y, @second.y].min
+ @top_right = Point.new right, top
+ end
+ @top_right
+ end
+
+ def bottom_left
+ if @bottom_left.nil?
+ left = @first.x
+ bottom = [@first.y, @second.y].max
+ @bottom_left = Point.new left, bottom
+ end
+ @bottom_left
+ end
+
+ def bottom_right
+ if @bottom_right.nil?
+ right = @second.x
+ bottom = [@first.y, @second.y].max
+ @bottom_right = Point.new right, bottom
+ end
+ @bottom_right
+ end
+
+ def modify(canvas)
+ (top_left.x .. top_right.x).each {|x| canvas.set_pixel x, top_left.y}
+ (top_left.x .. top_right.x).each {|x| canvas.set_pixel x,bottom_left.y}
+ (top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_left.x,y}
+ (top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_right.x,y}
+ end
+ end
+
+ class Canvas
+ def initialize(width,height)
+ @width = width
+ @height = height
+ @pane = Array.new(height) {Array.new width,false}
+ end
+
+ def width
+ @width
+ end
+ def height
+ @height
+ end
+ def draw(figure)
+ figure.modify self
+ end
+
+ def set_pixel(x, y)
+ @pane[x][y] = true
+ end
+
+ def pixel_at?(x, y)
+ @pane[x][y]
+ end
+
+ def render_as(renderer)
+ renderer.render(self)
+ end
+ end
+
+ module Renderers
+
+ class Ascii
+
+ def self.render(canvas)
+ result = ""
+ (0 .. canvas.height-1).each do |y|
+ (0 .. canvas.width-1).each do |x|
+ result = result + (print_character canvas, x, y)
+ end
+ result = result + "\n"
+ end
+ result
+ end
+
+ def self.print_character(canvas,x,y)
+ if canvas.pixel_at? x, y then "@" else "-" end
+ end
+
+ end
+
+ class Html
+ def self.render(canvas)
+ end
+ end
+ end
+end
+
+module Graphics
+ canvas = Canvas.new 30, 30
+
+ # Door frame and window
+ canvas.draw Rectangle.new(Point.new(3, 3), Point.new(18, 12))
+ canvas.draw Rectangle.new(Point.new(1, 1), Point.new(20, 28))
+
+ # Door knob
+ canvas.draw Line.new(Point.new(4, 15), Point.new(7, 15))
+ canvas.draw Point.new(4, 16)
+
+ # Big "R"
+ canvas.draw Line.new(Point.new(8, 5), Point.new(8, 10))
+ canvas.draw Line.new(Point.new(9, 5), Point.new(12, 5))
+ canvas.draw Line.new(Point.new(9, 7), Point.new(12, 7))
+ canvas.draw Point.new(13, 6)
+ canvas.draw Line.new(Point.new(12, 8), Point.new(13, 10))
+
+ puts canvas.render_as(Renderers::Ascii)
+end
+
+__END__
+
+<!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">
+ >FINDME
+ </div>
+ </body>
+ </html>

Михаил обнови решението на 22.12.2013 01:20 (преди почти 11 години)

module Graphics
class Point
def initialize(x,y)
@x = x
@y = y
end
def x
@x
end
def y
@y
end
def ==(other)
(@x == other.x) and (@y == other.y)
end
def hash
[@x , @y].hash
end
def self.topmost(first,second)
if first.y < second.y then first else second end
end
def self.leftmost(first,second)
if first.x < second.x then first else second end
end
def self.rightmost(first,second)
if first.y > second.y then first else second end
end
def self.bottommost(first,second)
if first.x > second.x then first else second end
end
def modify(canvas)
canvas.set_pixel @x, @y
end
alias_method :==, :eql?
end
class PointDouble
def initialize(start,finish)
if start.x == finish.x
@first = Point.topmost start, finish
@second = Point.bottommost start, finish
else
@first = Point.leftmost start, finish
@second = Point.bottommost start, finish
end
end
def first
@first
end
def second
@second
end
def hash
[@first, @second].hash
end
def ==(other)
(@first == other.first) and (@second == other.second)
end
alias_method :==, :eql?
end
class Line < PointDouble
alias_method :from, :first
alias_method :to, :second
def bresenham_plot(x_start,x_end,y,delta_x,delta_y,error)
x_start.upto(x_end) do |x|
if error > 0
y , error = y + 1 , error + 2 * delta_y - 2 * delta_x
yield Point.new x,y
else
yield Point.new x,y
error = error + 2*delta_y
end
end
end
def bresenham(first, second, &block)
delta_x, delta_y = second.x - first.x, second.y - first.y
error, y = 2*delta_y - delta_x , first.y
yield Point.new first.x,first.y
bresenham_plot first.x,second.x,y,delta_x,delta_y,error,&block
end
def modify(canvas)
if @first.x == @second.x
min = [@first.y,@second.y].min
max = [@first.y,@second.y].max
(min .. max).each {|y| canvas.set_pixel @first.x, y}
else
bresenham(@first,@second) {|point| canvas.set_pixel point.x, point.y}
end
end
end
class Rectangle < PointDouble
alias_method :left, :first
alias_method :right, :second
def top_left
if @top_left.nil?
left = @first.x
top = [@first.y, @second.y].min
@top_left = Point.new left, top
end
@top_left
end
def top_right
if @top_right.nil?
right = @second.x
top = [@first.y, @second.y].min
@top_right = Point.new right, top
end
@top_right
end
def bottom_left
if @bottom_left.nil?
left = @first.x
bottom = [@first.y, @second.y].max
@bottom_left = Point.new left, bottom
end
@bottom_left
end
def bottom_right
if @bottom_right.nil?
right = @second.x
bottom = [@first.y, @second.y].max
@bottom_right = Point.new right, bottom
end
@bottom_right
end
def modify(canvas)
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x, top_left.y}
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x,bottom_left.y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_left.x,y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_right.x,y}
end
end
class Canvas
def initialize(width,height)
@width = width
@height = height
@pane = Array.new(height) {Array.new width,false}
end
def width
@width
end
def height
@height
end
def draw(figure)
figure.modify self
end
def set_pixel(x, y)
@pane[x][y] = true
end
def pixel_at?(x, y)
@pane[x][y]
end
def render_as(renderer)
renderer.render(self)
end
end
module Renderers
class Ascii
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "\n"
end
result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "@" else "-" end
end
end
class Html
def self.render(canvas)
+ result = ""
+ (0 .. canvas.height-1).each do |y|
+ (0 .. canvas.width-1).each do |x|
+ result = result + (print_character canvas, x, y)
+ end
+ result = result + "<br/>"
+ end
+ DATA.read.sub ">FINDME",result
end
+
+ def self.print_character(canvas,x,y)
+ if canvas.pixel_at? x, y then "<b></b>" else "<i></i>" end
+ end
end
end
end
module Graphics
canvas = Canvas.new 30, 30
# Door frame and window
canvas.draw Rectangle.new(Point.new(3, 3), Point.new(18, 12))
canvas.draw Rectangle.new(Point.new(1, 1), Point.new(20, 28))
# Door knob
canvas.draw Line.new(Point.new(4, 15), Point.new(7, 15))
canvas.draw Point.new(4, 16)
# Big "R"
canvas.draw Line.new(Point.new(8, 5), Point.new(8, 10))
canvas.draw Line.new(Point.new(9, 5), Point.new(12, 5))
canvas.draw Line.new(Point.new(9, 7), Point.new(12, 7))
canvas.draw Point.new(13, 6)
canvas.draw Line.new(Point.new(12, 8), Point.new(13, 10))
- puts canvas.render_as(Renderers::Ascii)
+ puts canvas.render_as(Renderers::Html)
end
__END__
<!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">
>FINDME
</div>
</body>
</html>

Михаил обнови решението на 22.12.2013 01:20 (преди почти 11 години)

module Graphics
class Point
def initialize(x,y)
@x = x
@y = y
end
def x
@x
end
def y
@y
end
def ==(other)
(@x == other.x) and (@y == other.y)
end
def hash
[@x , @y].hash
end
def self.topmost(first,second)
if first.y < second.y then first else second end
end
def self.leftmost(first,second)
if first.x < second.x then first else second end
end
def self.rightmost(first,second)
if first.y > second.y then first else second end
end
def self.bottommost(first,second)
if first.x > second.x then first else second end
end
def modify(canvas)
canvas.set_pixel @x, @y
end
alias_method :==, :eql?
end
class PointDouble
def initialize(start,finish)
if start.x == finish.x
@first = Point.topmost start, finish
@second = Point.bottommost start, finish
else
@first = Point.leftmost start, finish
@second = Point.bottommost start, finish
end
end
def first
@first
end
def second
@second
end
def hash
[@first, @second].hash
end
def ==(other)
(@first == other.first) and (@second == other.second)
end
alias_method :==, :eql?
end
class Line < PointDouble
alias_method :from, :first
alias_method :to, :second
def bresenham_plot(x_start,x_end,y,delta_x,delta_y,error)
x_start.upto(x_end) do |x|
if error > 0
y , error = y + 1 , error + 2 * delta_y - 2 * delta_x
yield Point.new x,y
else
yield Point.new x,y
error = error + 2*delta_y
end
end
end
def bresenham(first, second, &block)
delta_x, delta_y = second.x - first.x, second.y - first.y
error, y = 2*delta_y - delta_x , first.y
yield Point.new first.x,first.y
bresenham_plot first.x,second.x,y,delta_x,delta_y,error,&block
end
def modify(canvas)
if @first.x == @second.x
min = [@first.y,@second.y].min
max = [@first.y,@second.y].max
(min .. max).each {|y| canvas.set_pixel @first.x, y}
else
bresenham(@first,@second) {|point| canvas.set_pixel point.x, point.y}
end
end
end
class Rectangle < PointDouble
alias_method :left, :first
alias_method :right, :second
def top_left
if @top_left.nil?
left = @first.x
top = [@first.y, @second.y].min
@top_left = Point.new left, top
end
@top_left
end
def top_right
if @top_right.nil?
right = @second.x
top = [@first.y, @second.y].min
@top_right = Point.new right, top
end
@top_right
end
def bottom_left
if @bottom_left.nil?
left = @first.x
bottom = [@first.y, @second.y].max
@bottom_left = Point.new left, bottom
end
@bottom_left
end
def bottom_right
if @bottom_right.nil?
right = @second.x
bottom = [@first.y, @second.y].max
@bottom_right = Point.new right, bottom
end
@bottom_right
end
def modify(canvas)
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x, top_left.y}
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x,bottom_left.y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_left.x,y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_right.x,y}
end
end
class Canvas
def initialize(width,height)
@width = width
@height = height
@pane = Array.new(height) {Array.new width,false}
end
def width
@width
end
def height
@height
end
def draw(figure)
figure.modify self
end
def set_pixel(x, y)
@pane[x][y] = true
end
def pixel_at?(x, y)
@pane[x][y]
end
def render_as(renderer)
renderer.render(self)
end
end
module Renderers
class Ascii
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "\n"
end
result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "@" else "-" end
end
end
class Html
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "<br/>"
end
DATA.read.sub ">FINDME",result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "<b></b>" else "<i></i>" end
end
end
end
end
-module Graphics
- canvas = Canvas.new 30, 30
-
- # Door frame and window
- canvas.draw Rectangle.new(Point.new(3, 3), Point.new(18, 12))
- canvas.draw Rectangle.new(Point.new(1, 1), Point.new(20, 28))
-
- # Door knob
- canvas.draw Line.new(Point.new(4, 15), Point.new(7, 15))
- canvas.draw Point.new(4, 16)
-
- # Big "R"
- canvas.draw Line.new(Point.new(8, 5), Point.new(8, 10))
- canvas.draw Line.new(Point.new(9, 5), Point.new(12, 5))
- canvas.draw Line.new(Point.new(9, 7), Point.new(12, 7))
- canvas.draw Point.new(13, 6)
- canvas.draw Line.new(Point.new(12, 8), Point.new(13, 10))
-
- puts canvas.render_as(Renderers::Html)
-end
-
__END__
<!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">
>FINDME
</div>
</body>
</html>

Михаил обнови решението на 22.12.2013 15:24 (преди почти 11 години)

module Graphics
class Point
def initialize(x,y)
@x = x
@y = y
end
def x
@x
end
def y
@y
end
def ==(other)
(@x == other.x) and (@y == other.y)
end
def hash
[@x , @y].hash
end
def self.topmost(first,second)
if first.y < second.y then first else second end
end
def self.leftmost(first,second)
if first.x < second.x then first else second end
end
def self.rightmost(first,second)
if first.y > second.y then first else second end
end
def self.bottommost(first,second)
if first.x > second.x then first else second end
end
def modify(canvas)
canvas.set_pixel @x, @y
end
alias_method :==, :eql?
end
class PointDouble
def initialize(start,finish)
if start.x == finish.x
@first = Point.topmost start, finish
@second = Point.bottommost start, finish
else
@first = Point.leftmost start, finish
@second = Point.bottommost start, finish
end
end
def first
@first
end
def second
@second
end
def hash
[@first, @second].hash
end
def ==(other)
(@first == other.first) and (@second == other.second)
end
alias_method :==, :eql?
end
class Line < PointDouble
alias_method :from, :first
alias_method :to, :second
- def bresenham_plot(x_start,x_end,y,delta_x,delta_y,error)
- x_start.upto(x_end) do |x|
- if error > 0
- y , error = y + 1 , error + 2 * delta_y - 2 * delta_x
+ def rasterize_plot_x(delta_x,delta_y,x, y,max, offset_x, offset_y, &block)
+ error = delta_x / 2.0
+ while x != max
+ error, x = error - delta_y, x+offset_x
+ if error <= 0
+ y, error = y + offset_y, error + delta_x
+ end
yield Point.new x,y
- else
+ end
+ end
+
+ def rasterize_plot_y(delta_x,delta_y,x, y,max, offset_x, offset_y, &block)
+ error = delta_y / 2.0
+ while y != max
+ error, y = error - delta_x, y + offset_y
+ if error <= 0
+ x, error = x + offset_x, error + delta_y
+ end
yield Point.new x,y
- error = error + 2*delta_y
end
- end
end
- def bresenham(first, second, &block)
- delta_x, delta_y = second.x - first.x, second.y - first.y
- error, y = 2*delta_y - delta_x , first.y
- yield Point.new first.x,first.y
- bresenham_plot first.x,second.x,y,delta_x,delta_y,error,&block
+ def rasterize(a, b,&block)
+ delta_x, delta_y, x, y = (b.x - a.x).abs, (b.y - a.y).abs, a.x, a.y
+ offset_x, offset_y = a.x > b.x ? -1 : 1 , a.y > b.y ? -1 : 1
+
+ yield Point.new x,y
+
+ if delta_x > delta_y
+ rasterize_plot_x delta_x,delta_y,x,y, b.x, offset_x, offset_y, &block
+ else
+ rasterize_plot_y delta_x,delta_y,x,y, b.y, offset_x, offset_y, &block
+ end
end
def modify(canvas)
if @first.x == @second.x
min = [@first.y,@second.y].min
max = [@first.y,@second.y].max
(min .. max).each {|y| canvas.set_pixel @first.x, y}
else
- bresenham(@first,@second) {|point| canvas.set_pixel point.x, point.y}
+ rasterize(@first,@second) {|point| canvas.set_pixel point.x, point.y}
end
end
end
class Rectangle < PointDouble
alias_method :left, :first
alias_method :right, :second
def top_left
if @top_left.nil?
left = @first.x
top = [@first.y, @second.y].min
@top_left = Point.new left, top
end
@top_left
end
def top_right
if @top_right.nil?
right = @second.x
top = [@first.y, @second.y].min
@top_right = Point.new right, top
end
@top_right
end
def bottom_left
if @bottom_left.nil?
left = @first.x
bottom = [@first.y, @second.y].max
@bottom_left = Point.new left, bottom
end
@bottom_left
end
def bottom_right
if @bottom_right.nil?
right = @second.x
bottom = [@first.y, @second.y].max
@bottom_right = Point.new right, bottom
end
@bottom_right
end
def modify(canvas)
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x, top_left.y}
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x,bottom_left.y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_left.x,y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_right.x,y}
end
end
class Canvas
def initialize(width,height)
@width = width
@height = height
@pane = Array.new(height) {Array.new width,false}
end
def width
@width
end
def height
@height
end
def draw(figure)
figure.modify self
end
def set_pixel(x, y)
@pane[x][y] = true
end
def pixel_at?(x, y)
@pane[x][y]
end
def render_as(renderer)
renderer.render(self)
end
end
module Renderers
class Ascii
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "\n"
end
result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "@" else "-" end
end
end
class Html
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "<br/>"
end
DATA.read.sub ">FINDME",result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "<b></b>" else "<i></i>" end
end
end
end
end
__END__
<!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">
>FINDME
</div>
</body>
</html>

Смятам, че си напипал правилната посока откъм дизайн. Ето малко бележки за неща, които би могъл да подобриш:

  • Помисли дали няма друг по-оптимален начин в Ruby за реализация вътрешното представяне на пано, от масив от масиви. Ruby не е C и има по-удобни структури от данни :)
  • Така имплементирани, методите x и y е по-нормално да се дефинират през attr_reader :x, :y. Това важи и за други подобни методи.
  • По конвенция не трябва да има интервал на редове 3, 191, 193... Освен това си неконсистентен в спазването на тази твоя конвенция, понеже в други класове нямаш интервал след началото на дефиницията на класа.
  • Няма нужда от скобите на ред 18.
  • Добре си се сетил как да имплементираш hash методите. Само че не трябва да има интервал преди запетаята на ред 22.
  • За *most методите в Point като че ли е по-удачно да ползваш ternary оператора. Между другото, не съм убеден в смисъла от тези методи. Виждам как ги ползваш, но все пак. Това го казвам просто за размисъл, не означава, че трбява да ги махнеш.
  • modify е много неподходящо име. Може би render_on? Или rasterize_on?
  • Ако искаш да кешираш (мемоизираш) стойностите на методите за ъгли на правоъгълник, ползвай следната конструкция:

      def top_left
        @top_left ||= begin
          left = @first.x
          top  = [@first.y, @second.y].min
    
          Point.new left, top
        end
      end
    

    Или направо нещо от рода на:

      def top_left
        @top_left ||= Point.new @first.x, [@first.y, @second.y].min
      end
    

    Смятам, че горното е достатъчно четимо.

  • Не съм убеден, че класът PointDouble е смислена и необходима абстракция. Дори името му не ми помага да разбера защо съществува. Така написано, го разбирам като "двойник на точката". Може би си търсил нещо от рода на PointsPair, PairOfPoints, TwoPoints или нещо такова. И все пак, помисли има ли нужда от него в този му вид.
  • Имаш проблеми с идентацията на места. Оправи я преди крайния срок, иначе ще ти взема наказателни точки. На немалко места нарушаваш конвенциите за поставяне на интервали около операторите. От по-фрапантните примери са методите bresenham_plot, bresenham и други.
  • Пробвай да напишеш логиката за рендериране с map и join, вместо да буташ резултата в един низ.
  • Предполагам, че ще разкараш този тестов код от края на решението си преди окончателния му вариант.

Михаил обнови решението на 22.12.2013 21:37 (преди почти 11 години)

module Graphics
class Point
-
+ attr_reader :x, :y
def initialize(x,y)
@x = x
@y = y
end
- def x
- @x
- end
-
- def y
- @y
- end
-
def ==(other)
(@x == other.x) and (@y == other.y)
end
def hash
[@x , @y].hash
end
def self.topmost(first,second)
if first.y < second.y then first else second end
end
def self.leftmost(first,second)
if first.x < second.x then first else second end
end
def self.rightmost(first,second)
if first.y > second.y then first else second end
end
def self.bottommost(first,second)
if first.x > second.x then first else second end
end
- def modify(canvas)
+ def render_on(canvas)
canvas.set_pixel @x, @y
end
alias_method :==, :eql?
end
- class PointDouble
+ module PointsPair
+ attr_reader :first, :second
+
def initialize(start,finish)
if start.x == finish.x
@first = Point.topmost start, finish
@second = Point.bottommost start, finish
else
@first = Point.leftmost start, finish
@second = Point.bottommost start, finish
end
end
- def first
- @first
- end
-
- def second
- @second
- end
-
def hash
[@first, @second].hash
end
def ==(other)
(@first == other.first) and (@second == other.second)
end
alias_method :==, :eql?
end
- class Line < PointDouble
+ class Line
+ include PointsPair
+
alias_method :from, :first
alias_method :to, :second
def rasterize_plot_x(delta_x,delta_y,x, y,max, offset_x, offset_y, &block)
error = delta_x / 2.0
while x != max
error, x = error - delta_y, x+offset_x
if error <= 0
y, error = y + offset_y, error + delta_x
end
yield Point.new x,y
end
end
def rasterize_plot_y(delta_x,delta_y,x, y,max, offset_x, offset_y, &block)
error = delta_y / 2.0
while y != max
error, y = error - delta_x, y + offset_y
if error <= 0
x, error = x + offset_x, error + delta_y
end
yield Point.new x,y
end
end
def rasterize(a, b,&block)
delta_x, delta_y, x, y = (b.x - a.x).abs, (b.y - a.y).abs, a.x, a.y
offset_x, offset_y = a.x > b.x ? -1 : 1 , a.y > b.y ? -1 : 1
yield Point.new x,y
if delta_x > delta_y
rasterize_plot_x delta_x,delta_y,x,y, b.x, offset_x, offset_y, &block
else
rasterize_plot_y delta_x,delta_y,x,y, b.y, offset_x, offset_y, &block
end
end
- def modify(canvas)
+ def render_on(canvas)
if @first.x == @second.x
- min = [@first.y,@second.y].min
- max = [@first.y,@second.y].max
- (min .. max).each {|y| canvas.set_pixel @first.x, y}
+ min = [@first.y,@second.y].min
+ max = [@first.y,@second.y].max
+ (min .. max).each {|y| canvas.set_pixel @first.x, y}
else
- rasterize(@first,@second) {|point| canvas.set_pixel point.x, point.y}
+ rasterize(@first,@second) {|point| canvas.set_pixel point.x, point.y}
end
end
end
- class Rectangle < PointDouble
+ class Rectangle
+ include PointsPair
+
alias_method :left, :first
alias_method :right, :second
def top_left
- if @top_left.nil?
- left = @first.x
- top = [@first.y, @second.y].min
- @top_left = Point.new left, top
- end
- @top_left
+ @top_left ||= Point.new @first.x, [@first.y, @second.y].min
end
def top_right
- if @top_right.nil?
- right = @second.x
- top = [@first.y, @second.y].min
- @top_right = Point.new right, top
- end
- @top_right
+ @top_right ||= Point.new @second.x, [@first.y, @second.y].min
end
def bottom_left
- if @bottom_left.nil?
- left = @first.x
- bottom = [@first.y, @second.y].max
- @bottom_left = Point.new left, bottom
- end
- @bottom_left
+ @bottom_left ||= Point.new @first.x, [@first.y, @second.y].max
end
def bottom_right
- if @bottom_right.nil?
- right = @second.x
- bottom = [@first.y, @second.y].max
- @bottom_right = Point.new right, bottom
- end
- @bottom_right
+ @bottom_right ||= Point.new @second.x, [@first.y, @second.y].max
end
- def modify(canvas)
+ def render_on(canvas)
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x, top_left.y}
(top_left.x .. top_right.x).each {|x| canvas.set_pixel x,bottom_left.y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_left.x,y}
(top_left.y .. bottom_left.y).each {|y| canvas.set_pixel top_right.x,y}
end
end
class Canvas
+ attr_reader :width, :height
def initialize(width,height)
@width = width
@height = height
@pane = Array.new(height) {Array.new width,false}
end
- def width
- @width
- end
- def height
- @height
- end
def draw(figure)
- figure.modify self
+ figure.render_on self
end
def set_pixel(x, y)
@pane[x][y] = true
end
def pixel_at?(x, y)
@pane[x][y]
end
def render_as(renderer)
- renderer.render(self)
+ renderer.render(self)
end
end
module Renderers
-
class Ascii
-
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "\n"
end
result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "@" else "-" end
end
end
class Html
def self.render(canvas)
result = ""
(0 .. canvas.height-1).each do |y|
(0 .. canvas.width-1).each do |x|
result = result + (print_character canvas, x, y)
end
result = result + "<br/>"
end
DATA.read.sub ">FINDME",result
end
def self.print_character(canvas,x,y)
if canvas.pixel_at? x, y then "<b></b>" else "<i></i>" end
end
end
end
end
__END__
<!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">
>FINDME
</div>
</body>
</html>