Решение на Трета задача от Георги Пурнаров

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

Към профила на Георги Пурнаров

Резултати

  • 4 точки от тестове
  • 1 отнета точка
  • 3 точки общо
  • 45 успешни тест(а)
  • 24 неуспешни тест(а)

Код

module Graphics
require 'digest/sha1'
class Canvas
attr_reader :width,:height
def initialize x,y
@width=x
@height=y
@panel=[]
y.times {@panel<<1.upto(x).each_with_object([]) { |e,a| a << 0}}
end
def set_pixel x,y
@panel[x][y]=1
end
def pixel_at? x,y
@panel[x][y]==1
end
def draw figure
if figure.class==Point
@panel[figure.y][figure.x]=1
elsif figure.class==Line
draw_line figure
else
draw_rectangle figure
end
end
def draw_line line
delta_x,delta_y = (line.from.x - line.to.x).abs,(line.from.y - line.to.y).abs
x = line.from.x<line.to.x ? line.from.x : line.to.x
y = line.from.y<line.to.y ? line.from.y : line.to.y
if delta_x > delta_y
draw_line_x x,y,delta_x,delta_y
else
draw_line_y x,y,delta_x,delta_y
end
end
def draw_line_y x,y,delta_x,delta_y
error = 0
delta_error = delta_x>0 ? delta_x*1.0 / delta_y : 0
y.upto(y+delta_y).each do |current_y|
@panel[current_y][x]=1
error = error + delta_error
x = x + 1 if (error-error.to_i) >= 0.5
end
end
def draw_line_x x,y,delta_x,delta_y
error = 0
delta_error = delta_y>0 ? delta_y*1.0 / delta_x : 0
x.upto(x+delta_x).each do |current_x|
@panel[y][current_x]=1
error = error + delta_error
y = y + 1 if (error-error.to_i) >= 0.5
end
end
def draw_rectangle figure
draw_line Line.new figure.top_left,figure.top_right
draw_line Line.new figure.top_left,figure.bottom_left
draw_line Line.new figure.bottom_right,figure.top_right
draw_line Line.new figure.bottom_right,figure.bottom_left
end
def render_as type
type.rendering_panel @panel
end
private :draw_rectangle,:draw_line,:draw_line_x,:draw_line_y
end
class Point
attr_reader :x,:y
def initialize x,y
@x=x
@y=y
end
def == point
x==point.x and y==point.y
end
alias_method('==', 'eql?')
def hash
hash="x is "+x.to_s+"y is "+y.to_s
Digest::SHA1.hexdigest(hash)
end
end
class Line
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def from
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def to
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
def == line
from==line.from and to==line.to
end
alias_method('==', 'eql?')
def hash
hash="x1 is "+to.x.to_s+"x2 is "+from.x.to_s+"y1 is "
hash << to.y.to_s+"y2 is "+from.y.to_s
Digest::SHA1.hexdigest(hash)
end
end
class Rectangle
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def left
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def right
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
def top_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def top_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def == rectangle
top_left==rectangle.top_left and bottom_right==rectangle.bottom_right
end
alias_method('==', 'eql?')
def hash
hash="x1 is "+top_left.x.to_s+"x2 is "+bottom_right.x.to_s+"y1 is "
hash << top_left.y.to_s+"y2 is "+bottom_right.y.to_s
Digest::SHA1.hexdigest(hash)
end
end
class Renderers
class Ascii
ASCII=['-','@',"\n"]
def self.rendering_panel panel
result = panel.each_with_object(''){|row,step| step<<"#{row.join('')}#{ASCII[2]}"}
result.gsub!('1',ASCII[1])
result.gsub!('0',ASCII[0])
result[0..-2]
end
end
class Html
HTML=['<i></i>','<b></b>','<br>','<!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">','</div>
</body>
</html>']
def self.rendering_panel panel
result = panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{HTML[2]}"}
result.gsub!('1',HTML[1])
result.gsub!('0',HTML[0])
result.insert(0,HTML[3])
result.insert(-2,HTML[4])
result[0..-2]
end
end
end
end

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

........FFF..FFF.......F..F.....F.F........FF.FFFF........FFFF...FFFF

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@@@@@@@@@@@@@@@"
       
       (compared using ==)
       
       Diff:
       
       @@ -2,10 +2,10 @@
        @-------------@
        @-@@@@@@@@@@@-@
        @-@---------@-@
       -@-@------@@-@-@
       -@-@---@@@---@-@
        @-@-@@------@-@
       -@-@---------@-@
       +@-@---@@@---@-@
       +@-@------@--@-@
       +@-@-------@-@-@
        @-@-@@@@----@-@
        @-@-@-------@-@
        @-@---------@-@
     # /tmp/d20131223-4637-ndeiyb/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-ndeiyb/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 a single one
     Failure/Error: canvas.pixel_at?(2, 4).should be_true
       expected: true value
            got: false
     # /tmp/d20131223-4637-ndeiyb/spec.rb:48: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 points works for multiple ones
     Failure/Error: canvas.set_pixel 4, 4
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-ndeiyb/solution.rb:13:in `set_pixel'
     # /tmp/d20131223-4637-ndeiyb/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: canvas.draw make_line(make_point(1, 1), make_point(8, 3))
     NoMethodError:
       undefined method `[]=' for nil:NilClass
     # /tmp/d20131223-4637-ndeiyb/solution.rb:55:in `block in draw_line_x'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:54:in `upto'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:54:in `each'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:54:in `draw_line_x'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:35:in `draw_line'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:24:in `draw'
     # /tmp/d20131223-4637-ndeiyb/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)>'

  5) 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----------"
       
       (compared using ==)
       
       Diff:
       
       @@ -2,10 +2,10 @@
        -@--------
        -@--------
        --@-------
       ---@-------
       ---@-------
       ---@-------
        ---@------
        ---@------
       +---@------
       +----@-----
       +-----@----
        ----------
     # /tmp/d20131223-4637-ndeiyb/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-ndeiyb/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)>'

  6) 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-ndeiyb/solution.rb:55:in `block in draw_line_x'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:54:in `upto'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:54:in `each'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:54:in `draw_line_x'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:35:in `draw_line'
     # /tmp/d20131223-4637-ndeiyb/solution.rb:24:in `draw'
     # /tmp/d20131223-4637-ndeiyb/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)>'

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

  8) Graphics Renderers Html renders simple canvases
     Failure/Error: html_rendering_of(canvas).should eq [
       
       expected: "<i></i><i></i><i></i><i></i><br><i></i><b></b><i></i><i></i><br><i></i><b></b><i></i><i></i>"
            got: "<i></i><i></i><i></i><i></i><br><i></i><b></b><b></b><i></i><br><i></i><i></i><i></i><i></i><br"
       
       (compared using ==)
     # /tmp/d20131223-4637-ndeiyb/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)>'

  9) 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-ndeiyb/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)>'

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

  11) Graphics shapes Line initialization with swapped points puts the top point of vertical lines in the from field
     Failure/Error: vertical_line.from.y.should eq 1
       
       expected: 1
            got: 8
       
       (compared using ==)
     # /tmp/d20131223-4637-ndeiyb/spec.rb:413: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)>'

  12) 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-ndeiyb/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)>'

  13) 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-ndeiyb/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)>'

  14) 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-ndeiyb/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)>'

  15) 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-ndeiyb/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)>'

  16) Graphics shapes Line comparison for equality works with eql? as well
     Failure/Error: a.should eql b
       
       expected: #<Graphics::Line:0xba0145e0 @point_1=#<Graphics::Point:0xba01475c @x=1, @y=1>, @point_2=#<Graphics::Point:0xba0146e4 @x=10, @y=14>>
            got: #<Graphics::Line:0xba0147c0 @point_1=#<Graphics::Point:0xba014874 @x=1, @y=1>, @point_2=#<Graphics::Point:0xba014838 @x=10, @y=14>>
       
       (compared using eql?)
       
       Diff:
       @@ -1,4 +1,4 @@
       -#<Graphics::Line:0xba0145e0
       - @point_1=#<Graphics::Point:0xba01475c @x=1, @y=1>,
       - @point_2=#<Graphics::Point:0xba0146e4 @x=10, @y=14>>
       +#<Graphics::Line:0xba0147c0
       + @point_1=#<Graphics::Point:0xba014874 @x=1, @y=1>,
       + @point_2=#<Graphics::Point:0xba014838 @x=10, @y=14>>
     # /tmp/d20131223-4637-ndeiyb/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)>'

  17) 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-ndeiyb/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)>'

  18) 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-ndeiyb/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)>'

  19) 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-ndeiyb/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)>'

  20) Graphics shapes Rectangle comparison for equality works with eql? as well
     Failure/Error: a.should eql b
       
       expected: #<Graphics::Rectangle:0xb9fd0840 @point_1=#<Graphics::Point:0xb9fd08e0 @x=1, @y=1>, @point_2=#<Graphics::Point:0xb9fd087c @x=10, @y=14>>
            got: #<Graphics::Rectangle:0xb9fd0930 @point_1=#<Graphics::Point:0xb9fd0994 @x=1, @y=1>, @point_2=#<Graphics::Point:0xb9fd0958 @x=10, @y=14>>
       
       (compared using eql?)
       
       Diff:
       @@ -1,4 +1,4 @@
       -#<Graphics::Rectangle:0xb9fd0840
       - @point_1=#<Graphics::Point:0xb9fd08e0 @x=1, @y=1>,
       - @point_2=#<Graphics::Point:0xb9fd087c @x=10, @y=14>>
       +#<Graphics::Rectangle:0xb9fd0930
       + @point_1=#<Graphics::Point:0xb9fd0994 @x=1, @y=1>,
       + @point_2=#<Graphics::Point:0xb9fd0958 @x=10, @y=14>>
     # /tmp/d20131223-4637-ndeiyb/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)>'

  21) Graphics shapes Rectangle corners top left
     Failure/Error: rect.top_left.y.should eq 2
       
       expected: 2
            got: 4
       
       (compared using ==)
     # /tmp/d20131223-4637-ndeiyb/spec.rb:578: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 Rectangle corners top right
     Failure/Error: rect.top_right.y.should eq 4
       
       expected: 4
            got: 6
       
       (compared using ==)
     # /tmp/d20131223-4637-ndeiyb/spec.rb:584: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)>'

  23) Graphics shapes Rectangle corners bottom right
     Failure/Error: rect.bottom_right.y.should eq 4
       
       expected: 4
            got: 2
       
       (compared using ==)
     # /tmp/d20131223-4637-ndeiyb/spec.rb:590: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 Rectangle corners bottom left
     Failure/Error: rect.bottom_left.y.should eq 8
       
       expected: 8
            got: 4
       
       (compared using ==)
     # /tmp/d20131223-4637-ndeiyb/spec.rb:596: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.09677 seconds
69 examples, 24 failures

Failed examples:

rspec /tmp/d20131223-4637-ndeiyb/spec.rb:203 # Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:45 # Graphics Canvas drawing of shapes and rasterization of points works for a single one
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:96 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
rspec /tmp/d20131223-4637-ndeiyb/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-ndeiyb/spec.rb:127 # Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:252 # Graphics Renderers Ascii renders simple canvases
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:287 # Graphics Renderers Html renders simple canvases
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:347 # Graphics shapes Point comparison for equality is true if coordinates are the same
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:355 # Graphics shapes Point comparison for equality works for eql? as well
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:411 # Graphics shapes Line initialization with swapped points puts the top point of vertical lines in the from field
rspec /tmp/d20131223-4637-ndeiyb/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-ndeiyb/spec.rb:431 # Graphics shapes Line comparison for equality is true if line ends are the same
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:438 # Graphics shapes Line comparison for equality is true if line ends are the same, even if swapped
rspec /tmp/d20131223-4637-ndeiyb/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-ndeiyb/spec.rb:452 # Graphics shapes Line comparison for equality works with eql? as well
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:522 # Graphics shapes Rectangle comparison for equality is true if rectangle points are the same
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:529 # Graphics shapes Rectangle comparison for equality is true if rectangle points are the same, even if swapped
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:536 # Graphics shapes Rectangle comparison for equality is true for rectangles defined with different diagonal corners
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:543 # Graphics shapes Rectangle comparison for equality works with eql? as well
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:575 # Graphics shapes Rectangle corners top left
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:581 # Graphics shapes Rectangle corners top right
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:587 # Graphics shapes Rectangle corners bottom right
rspec /tmp/d20131223-4637-ndeiyb/spec.rb:593 # Graphics shapes Rectangle corners bottom left

История (6 версии и 2 коментара)

Георги обнови решението на 17.12.2013 18:09 (преди почти 11 години)

+result.insert(0,type[3])

Георги обнови решението на 17.12.2013 18:10 (преди почти 11 години)

-result.insert(0,type[3])
+module Graphics
+ class Canvas
+ attr_reader :width,:height
+ def initialize x,y
+ @width=x
+ @height=y
+ @panel=[]
+ y.times {@panel<<1.upto(x).each_with_object([]) { |e,a| a << 0}}
+ end
+ def set_pixel x,y
+ @panel[x][y]=1
+ end
+ def pixel_at? x,y
+ @panel[x][y]==1
+ end
+ def draw figure
+ if figure.class==Point
+ @panel[figure.y][figure.x]=1
+ elsif figure.class==Line
+ draw_line figure
+ else
+ draw_rectangle figure
+ end
+ end
+ def draw_line figure
+ delta_x,delta_y = (figure.from.x - figure.to.x).abs,(figure.from.y - figure.to.y).abs
+ x = figure.from.x<figure.to.x ? figure.from.x : figure.to.x
+ y = figure.from.y<figure.to.y ? figure.from.y : figure.to.y
+ if delta_x > delta_y
+ draw_line_x x,y,delta_x,delta_y
+ else
+ draw_line_y x,y,delta_x,delta_y
+ end
+ end
+ def draw_line_y x,y,delta_x,delta_y
+ error = 0
+ delta_error = delta_x>0 ? delta_x*1.0 / delta_y : 0
+ y.upto(y+delta_y).each do |current_y|
+ @panel[current_y][x]=1
+ error = error + delta_error
+ x = x + 1 if (error-error.to_int) >= 0.5
+ end
+ end
+ def draw_line_x x,y,delta_x,delta_y
+ error = 0
+ delta_error = delta_y>0 ? delta_y*1.0 / delta_x : 0
+ x.upto(x+delta_x).each do |current_x|
+ @panel[y][current_x]=1
+ error = error + delta_error
+ y = y + 1 if (error-error.to_int) >= 0.5
+ end
+ end
+ def draw_rectangle figure
+ draw_line Line.new figure.top_left,figure.top_right
+ draw_line Line.new figure.top_left,figure.bottom_left
+ draw_line Line.new figure.bottom_right,figure.top_right
+ draw_line Line.new figure.bottom_right,figure.bottom_left
+ end
+ def render_as type
+ result = @panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{type[2]}"}
+ result.gsub!('1',type[1])
+ result.gsub!('0',type[0])
+ result.insert(0,type[3]) if type[3]
+ result.insert(-2,type[4]) if type[4]
+ result[0..-2]
+ end
+
+ def print
+ @panel.each {|row| p row}
+ end
+ end
+
+
+
+ class Point
+ attr_reader :x,:y
+ def initialize x,y
+ @x=x
+ @y=y
+ end
+ end
+
+ class Line
+ def initialize point_1,point_2
+ @point_1=point_1
+ @point_2=point_2
+ end
+ def from
+ if @point_1.x>@point_2.x
+ @point_2
+ elsif @point_1.x<@point_2.x
+ @point_1
+ else
+ @point_1.y>@point_2.y ? @point_1 : @point_2
+ end
+ end
+ def to
+ if @point_1.x<@point_2.x
+ @point_2
+ elsif @point_1.x>@point_2.x
+ @point_1
+ else
+ @point_1.y<@point_2.y ? @point_1 : @point_2
+ end
+ end
+ end
+
+ class Rectangle
+ def initialize point_1,point_2
+ @point_1=point_1
+ @point_2=point_2
+ end
+ def left
+ if @point_1.x>@point_2.x
+ @point_2
+ elsif @point_1.x<@point_2.x
+ @point_1
+ else
+ @point_1.y>@point_2.y ? @point_1 : @point_2
+ end
+ end
+ def right
+ if @point_1.x<@point_2.x
+ @point_2
+ elsif @point_1.x>@point_2.x
+ @point_1
+ else
+ @point_1.y<@point_2.y ? @point_1 : @point_2
+ end
+ end
+ def top_left
+ x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
+ y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
+ Point.new x,y
+ end
+ def top_right
+ x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
+ y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
+ Point.new x,y
+ end
+ def bottom_left
+ x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
+ y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
+ Point.new x,y
+ end
+ def bottom_right
+ x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
+ y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
+ Point.new x,y
+ end
+ end
+ class Renderers
+ ASCII=['-','@',"\n"]
+ HTML=['<i></i>','<b></b>','<br>','<!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">','</div>
+ </body>
+ </html>']
+ end
+end

Георги обнови решението на 17.12.2013 18:19 (преди почти 11 години)

module Graphics
class Canvas
attr_reader :width,:height
def initialize x,y
@width=x
@height=y
@panel=[]
y.times {@panel<<1.upto(x).each_with_object([]) { |e,a| a << 0}}
end
def set_pixel x,y
@panel[x][y]=1
end
def pixel_at? x,y
@panel[x][y]==1
end
def draw figure
if figure.class==Point
@panel[figure.y][figure.x]=1
elsif figure.class==Line
draw_line figure
else
draw_rectangle figure
end
end
def draw_line figure
delta_x,delta_y = (figure.from.x - figure.to.x).abs,(figure.from.y - figure.to.y).abs
x = figure.from.x<figure.to.x ? figure.from.x : figure.to.x
y = figure.from.y<figure.to.y ? figure.from.y : figure.to.y
if delta_x > delta_y
draw_line_x x,y,delta_x,delta_y
else
draw_line_y x,y,delta_x,delta_y
end
end
def draw_line_y x,y,delta_x,delta_y
error = 0
delta_error = delta_x>0 ? delta_x*1.0 / delta_y : 0
y.upto(y+delta_y).each do |current_y|
@panel[current_y][x]=1
error = error + delta_error
x = x + 1 if (error-error.to_int) >= 0.5
end
end
def draw_line_x x,y,delta_x,delta_y
error = 0
delta_error = delta_y>0 ? delta_y*1.0 / delta_x : 0
x.upto(x+delta_x).each do |current_x|
@panel[y][current_x]=1
error = error + delta_error
y = y + 1 if (error-error.to_int) >= 0.5
end
end
def draw_rectangle figure
draw_line Line.new figure.top_left,figure.top_right
draw_line Line.new figure.top_left,figure.bottom_left
draw_line Line.new figure.bottom_right,figure.top_right
draw_line Line.new figure.bottom_right,figure.bottom_left
end
def render_as type
+ render_type=type::HTML ? type::HTML : type::ASCII
+ render_panel render_type
+
+ end
+
+ def render_panel type
result = @panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{type[2]}"}
result.gsub!('1',type[1])
result.gsub!('0',type[0])
result.insert(0,type[3]) if type[3]
result.insert(-2,type[4]) if type[4]
result[0..-2]
end
- def print
- @panel.each {|row| p row}
- end
end
class Point
attr_reader :x,:y
def initialize x,y
@x=x
@y=y
end
end
class Line
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def from
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def to
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
end
class Rectangle
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def left
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def right
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
def top_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def top_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
end
class Renderers
- ASCII=['-','@',"\n"]
- HTML=['<i></i>','<b></b>','<br>','<!DOCTYPE html>
+ class Ascii
+ ASCII=['-','@',"\n"]
+ HTML=nil
+ end
+ class Html
+ ASCII=nil
+ HTML=['<i></i>','<b></b>','<br>','<!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">','</div>
</body>
</html>']
+ end
end
-end
+end

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

module Graphics
class Canvas
attr_reader :width,:height
def initialize x,y
@width=x
@height=y
@panel=[]
y.times {@panel<<1.upto(x).each_with_object([]) { |e,a| a << 0}}
end
def set_pixel x,y
@panel[x][y]=1
end
def pixel_at? x,y
@panel[x][y]==1
end
def draw figure
if figure.class==Point
@panel[figure.y][figure.x]=1
elsif figure.class==Line
draw_line figure
else
draw_rectangle figure
end
end
def draw_line figure
delta_x,delta_y = (figure.from.x - figure.to.x).abs,(figure.from.y - figure.to.y).abs
x = figure.from.x<figure.to.x ? figure.from.x : figure.to.x
y = figure.from.y<figure.to.y ? figure.from.y : figure.to.y
if delta_x > delta_y
draw_line_x x,y,delta_x,delta_y
else
draw_line_y x,y,delta_x,delta_y
end
end
def draw_line_y x,y,delta_x,delta_y
error = 0
delta_error = delta_x>0 ? delta_x*1.0 / delta_y : 0
y.upto(y+delta_y).each do |current_y|
@panel[current_y][x]=1
error = error + delta_error
x = x + 1 if (error-error.to_int) >= 0.5
end
end
def draw_line_x x,y,delta_x,delta_y
error = 0
delta_error = delta_y>0 ? delta_y*1.0 / delta_x : 0
x.upto(x+delta_x).each do |current_x|
@panel[y][current_x]=1
error = error + delta_error
y = y + 1 if (error-error.to_int) >= 0.5
end
end
def draw_rectangle figure
draw_line Line.new figure.top_left,figure.top_right
draw_line Line.new figure.top_left,figure.bottom_left
draw_line Line.new figure.bottom_right,figure.top_right
draw_line Line.new figure.bottom_right,figure.bottom_left
end
def render_as type
render_type=type::HTML ? type::HTML : type::ASCII
- render_panel render_type
+ rendering_panel render_type
end
- def render_panel type
+ def rendering_panel type
result = @panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{type[2]}"}
result.gsub!('1',type[1])
result.gsub!('0',type[0])
result.insert(0,type[3]) if type[3]
result.insert(-2,type[4]) if type[4]
result[0..-2]
end
end
class Point
attr_reader :x,:y
def initialize x,y
@x=x
@y=y
end
end
class Line
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def from
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def to
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
end
class Rectangle
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def left
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def right
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
def top_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def top_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
end
class Renderers
class Ascii
ASCII=['-','@',"\n"]
HTML=nil
end
class Html
ASCII=nil
HTML=['<i></i>','<b></b>','<br>','<!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">','</div>
</body>
</html>']
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

Георги обнови решението на 18.12.2013 19:17 (преди почти 11 години)

module Graphics
class Canvas
attr_reader :width,:height
def initialize x,y
@width=x
@height=y
@panel=[]
y.times {@panel<<1.upto(x).each_with_object([]) { |e,a| a << 0}}
end
def set_pixel x,y
@panel[x][y]=1
end
def pixel_at? x,y
@panel[x][y]==1
end
def draw figure
if figure.class==Point
@panel[figure.y][figure.x]=1
elsif figure.class==Line
draw_line figure
else
draw_rectangle figure
end
end
def draw_line figure
delta_x,delta_y = (figure.from.x - figure.to.x).abs,(figure.from.y - figure.to.y).abs
x = figure.from.x<figure.to.x ? figure.from.x : figure.to.x
y = figure.from.y<figure.to.y ? figure.from.y : figure.to.y
if delta_x > delta_y
draw_line_x x,y,delta_x,delta_y
else
draw_line_y x,y,delta_x,delta_y
end
end
def draw_line_y x,y,delta_x,delta_y
error = 0
delta_error = delta_x>0 ? delta_x*1.0 / delta_y : 0
y.upto(y+delta_y).each do |current_y|
@panel[current_y][x]=1
error = error + delta_error
x = x + 1 if (error-error.to_int) >= 0.5
end
end
def draw_line_x x,y,delta_x,delta_y
error = 0
delta_error = delta_y>0 ? delta_y*1.0 / delta_x : 0
x.upto(x+delta_x).each do |current_x|
@panel[y][current_x]=1
error = error + delta_error
y = y + 1 if (error-error.to_int) >= 0.5
end
end
def draw_rectangle figure
draw_line Line.new figure.top_left,figure.top_right
draw_line Line.new figure.top_left,figure.bottom_left
draw_line Line.new figure.bottom_right,figure.top_right
draw_line Line.new figure.bottom_right,figure.bottom_left
end
def render_as type
render_type=type::HTML ? type::HTML : type::ASCII
rendering_panel render_type
end
def rendering_panel type
result = @panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{type[2]}"}
result.gsub!('1',type[1])
result.gsub!('0',type[0])
result.insert(0,type[3]) if type[3]
result.insert(-2,type[4]) if type[4]
result[0..-2]
end
end
class Point
attr_reader :x,:y
def initialize x,y
@x=x
@y=y
end
+ def == point
+ x==point.x and y==point.y
+ end
+ def eql? point
+ x==point.x and y==point.y
+ end
+ def hash
+ hash="x is "+x.to_s+"y is "+y.to_s
+ hash.to_i(36)
+ end
end
class Line
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def from
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def to
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
+ def == line
+ from==line.from and to==line.to
+ end
+ def eql? line
+ from==line.from and to==line.to
+ end
+ def hash
+ hash="x1 is "+@point_1.x.to_s+"x2 is "+@point_2.x.to_s+"y1 is "
+ hash << @point_1.y.to_s+"y2 is "+@point_2.y.to_s
+ hash.to_i(36)
+ end
end
class Rectangle
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
def left
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
def right
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
def top_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def top_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
def bottom_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
+ def == rectangle
+ left==rectangle.left and right==rectangle.right
+ end
+ def eql? rectangle
+ left==rectangle.left and right==rectangle.right
+ end
+ def hash
+ hash="x1 is "+@point_1.x.to_s+"x2 is "+@point_2.x.to_s+"y1 is "
+ hash << @point_1.y.to_s+"y2 is "+@point_2.y.to_s
+ hash.to_i(36)
+ end
+
end
class Renderers
class Ascii
ASCII=['-','@',"\n"]
HTML=nil
end
class Html
ASCII=nil
HTML=['<i></i>','<b></b>','<br>','<!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">','</div>
</body>
</html>']
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

Бележки:

  • Има нужда да поработиш над стила и визията си в решенията. Освен, че никъде не си оставял празни редове, което нарушава прегледността и четимостта на кода, на доста места пропускаш интервалите, което е кофти. Прегледай ръководството по стил, ако има нужда, прегледай наши примерни решения и примерен код и се постарай да вкараш конвенцията си в рамки, защото иначе рискуваш да ти вземем някоя друга точка за стил. В момента решението ти ми е много трудно за четене и осмисляне. Няма да оставям индивидуални бележки къде си изпуснал редове, интервали, или скоби. Прегледай ръководството, моля те.
  • Помисли дали няма друг по-оптимален начин в Ruby за реализация вътрешното представяне на пано от двумерен масив. Тъй като Ruby не е C, можем да ползваме и други, по-удобни типове данни :)
  • Помисли какво ще трябва да направиш, ако искаш да добавиш нова фигура в графичната библиотека – ще стане ли с промяна само на едно място, или ще трябва да пипнеш на поне две? Кое е по-добре? Има ли как това да се промени?
  • Аргументът на draw_line спокойно може да се казва line, вместо figure. По-конкретно е.
  • Целият метод draw_line е доста наблъскан и нечетим; ternary операторите не помагат. Помисли дали има начин да подобриш това положение някак. Това важи и за другите методи.
  • Допълнително, тези методи draw_line, draw_line_y и прочее са публични. Добра идея ли е това? Ако не се ползват отвън, може би не трябва да са част от публичния интерфейс на пано.
  • Не трябва да има празен ред на ред 62 и ред 73.
  • Рендерерите ти са класове, защото skeptic ограниченията са ти го наложили. Виж дали не можеш да използваш този факт някак, а не просто да ги ползваш тези две константи Html и Ascii като кофи за данни. Натовари ги с някаква логика – все пак това е основната идея на ОО-програмирането – да разпределиш различните отговорности между различни обекти. Стреми се всеки обект да отговаря за едно конкретно нещо и само за него. Напълно нормално е да имаш голям брой малки обекти в системата, с тясно специализирани отговорности. В момента, според мен, паното ти има прекалено много логика – да не кажа цялата логика на задачата. За растеризация на обекти, за рендериране на обекти... Опитай да я разпределиш.
  • Относно метода rendering_panel – пробвай да го преработиш така, че да ползва map и join и да нямаш нужда от променлива тип result.
  • to_int не се ползва; замени го с to_i където ти трябва
  • Виждам, че полагаш усилия да именуваш нещата добре, но мисля, че все още има място за чувствително подобрение на някои места.
  • Слагай по един празен ред между дефиниция на класове, а не по три (редове 75-77).
  • Ползвай синоними на методи за eql?.
  • Не съм убеден, че имплементацията ти на hash работи. Съветвам те да последваш съвета на условието и да стъпиш на съществуващи имплементации на hash от други Ruby класове.
  • Струва ми се, че можеш да опростиш Line#from и Line#to някак :) Същото важи и за Rectangle#from и to.
  • Погледни още веднъж дали равенството на правоъгълник ти работи правилно.

Георги обнови решението на 21.12.2013 14:25 (преди почти 11 години)

module Graphics
+ require 'digest/sha1'
class Canvas
attr_reader :width,:height
def initialize x,y
@width=x
@height=y
@panel=[]
y.times {@panel<<1.upto(x).each_with_object([]) { |e,a| a << 0}}
end
+
def set_pixel x,y
@panel[x][y]=1
end
+
def pixel_at? x,y
@panel[x][y]==1
end
+
def draw figure
if figure.class==Point
@panel[figure.y][figure.x]=1
elsif figure.class==Line
draw_line figure
else
draw_rectangle figure
end
end
- def draw_line figure
- delta_x,delta_y = (figure.from.x - figure.to.x).abs,(figure.from.y - figure.to.y).abs
- x = figure.from.x<figure.to.x ? figure.from.x : figure.to.x
- y = figure.from.y<figure.to.y ? figure.from.y : figure.to.y
- if delta_x > delta_y
- draw_line_x x,y,delta_x,delta_y
- else
- draw_line_y x,y,delta_x,delta_y
+
+ def draw_line line
+ delta_x,delta_y = (line.from.x - line.to.x).abs,(line.from.y - line.to.y).abs
+ x = line.from.x<line.to.x ? line.from.x : line.to.x
+ y = line.from.y<line.to.y ? line.from.y : line.to.y
+ if delta_x > delta_y
+ draw_line_x x,y,delta_x,delta_y
+ else
+ draw_line_y x,y,delta_x,delta_y
+ end
end
- end
+
def draw_line_y x,y,delta_x,delta_y
error = 0
delta_error = delta_x>0 ? delta_x*1.0 / delta_y : 0
y.upto(y+delta_y).each do |current_y|
@panel[current_y][x]=1
error = error + delta_error
- x = x + 1 if (error-error.to_int) >= 0.5
+ x = x + 1 if (error-error.to_i) >= 0.5
end
end
+
def draw_line_x x,y,delta_x,delta_y
error = 0
delta_error = delta_y>0 ? delta_y*1.0 / delta_x : 0
x.upto(x+delta_x).each do |current_x|
@panel[y][current_x]=1
error = error + delta_error
- y = y + 1 if (error-error.to_int) >= 0.5
+ y = y + 1 if (error-error.to_i) >= 0.5
end
end
+
def draw_rectangle figure
draw_line Line.new figure.top_left,figure.top_right
draw_line Line.new figure.top_left,figure.bottom_left
draw_line Line.new figure.bottom_right,figure.top_right
draw_line Line.new figure.bottom_right,figure.bottom_left
end
- def render_as type
- render_type=type::HTML ? type::HTML : type::ASCII
- rendering_panel render_type
+ def render_as type
+ type.rendering_panel @panel
end
- def rendering_panel type
- result = @panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{type[2]}"}
- result.gsub!('1',type[1])
- result.gsub!('0',type[0])
- result.insert(0,type[3]) if type[3]
- result.insert(-2,type[4]) if type[4]
- result[0..-2]
- end
-
+ private :draw_rectangle,:draw_line,:draw_line_x,:draw_line_y
end
-
-
class Point
attr_reader :x,:y
def initialize x,y
@x=x
@y=y
end
+
def == point
x==point.x and y==point.y
end
- def eql? point
- x==point.x and y==point.y
- end
+ alias_method('==', 'eql?')
+
def hash
hash="x is "+x.to_s+"y is "+y.to_s
- hash.to_i(36)
+ Digest::SHA1.hexdigest(hash)
end
end
class Line
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
+
def from
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
+
def to
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
+
def == line
from==line.from and to==line.to
end
- def eql? line
- from==line.from and to==line.to
- end
+
+ alias_method('==', 'eql?')
+
def hash
- hash="x1 is "+@point_1.x.to_s+"x2 is "+@point_2.x.to_s+"y1 is "
- hash << @point_1.y.to_s+"y2 is "+@point_2.y.to_s
- hash.to_i(36)
+ hash="x1 is "+to.x.to_s+"x2 is "+from.x.to_s+"y1 is "
+ hash << to.y.to_s+"y2 is "+from.y.to_s
+ Digest::SHA1.hexdigest(hash)
end
end
class Rectangle
def initialize point_1,point_2
@point_1=point_1
@point_2=point_2
end
+
def left
if @point_1.x>@point_2.x
@point_2
elsif @point_1.x<@point_2.x
@point_1
else
@point_1.y>@point_2.y ? @point_1 : @point_2
end
end
+
def right
if @point_1.x<@point_2.x
@point_2
elsif @point_1.x>@point_2.x
@point_1
else
@point_1.y<@point_2.y ? @point_1 : @point_2
end
end
+
def top_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
+
def top_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y>@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
+
def bottom_left
x=@point_1.x<@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
+
def bottom_right
x=@point_1.x>@point_2.x ? @point_1.x : @point_2.x
y=@point_1.y<@point_2.y ? @point_1.y : @point_2.y
Point.new x,y
end
+
def == rectangle
- left==rectangle.left and right==rectangle.right
+ top_left==rectangle.top_left and bottom_right==rectangle.bottom_right
end
- def eql? rectangle
- left==rectangle.left and right==rectangle.right
- end
+
+ alias_method('==', 'eql?')
+
def hash
- hash="x1 is "+@point_1.x.to_s+"x2 is "+@point_2.x.to_s+"y1 is "
- hash << @point_1.y.to_s+"y2 is "+@point_2.y.to_s
- hash.to_i(36)
+ hash="x1 is "+top_left.x.to_s+"x2 is "+bottom_right.x.to_s+"y1 is "
+ hash << top_left.y.to_s+"y2 is "+bottom_right.y.to_s
+ Digest::SHA1.hexdigest(hash)
end
end
class Renderers
class Ascii
ASCII=['-','@',"\n"]
- HTML=nil
+
+ def self.rendering_panel panel
+ result = panel.each_with_object(''){|row,step| step<<"#{row.join('')}#{ASCII[2]}"}
+ result.gsub!('1',ASCII[1])
+ result.gsub!('0',ASCII[0])
+ result[0..-2]
+ end
end
+
class Html
- ASCII=nil
HTML=['<i></i>','<b></b>','<br>','<!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">','</div>
</body>
</html>']
+ def self.rendering_panel panel
+ result = panel.each_with_object(''){ |row,step| step<<"#{row.join('')}#{HTML[2]}"}
+ result.gsub!('1',HTML[1])
+ result.gsub!('0',HTML[0])
+ result.insert(0,HTML[3])
+ result.insert(-2,HTML[4])
+ result[0..-2]
+ end
end
end
end
  • Решението ти е доста по-четимо с новите празни редове, но продължаваш да не спазваш важни неща от конвенциите и затова съм принуден да ти взема точки.
  • Май не си разбрал какво се очаква да прави методът hash. Виж моето решение за справка.
  • Не слагай скоби в случаи като този на ред 85, 123.
  • От друга страна, конвенциите, които спазваме в курса, изискват да има скоби при дефиниция на метод, който има аргументи.
  • Представяне на пано във вида на Hash с ключ точка (списък с две числа) и стойност true ми се струва по-удачно от твоя вариант. Пак, виж аз как съм решил проблема с представянето на пано.
  • Private методи не се дефинират така (стилово), слага се private над методите, които са такива.
  • Да ползваш мутиращи методи се счита за лоша практика в Ruby (например, gsub! в rendering_panel метода). Казвали сме го многократно на лекции и сме обяснявали защо.
  • result е лошо име на променлива (пак в същия метод). Ако ти е трудно да измислиш име, помисли дали това не е знак, че трбява да промениш дизайна някак (в случая може да се ползва map + join и да няма нужда от променливи като result или gsub!).

Като цяло, имаш нужда да поработиш доста над стила си, спазването на конвенци и именуването на неща. Не си успял да влезеш все още в духа на Ruby. Има какво да се желае и откъм идеите ти за дизайн. Работи над това :)