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

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

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

Резултати

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

Код

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
@pixels = Array.new(width) { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
module ComparableFigure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
class Line
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
def delta_x
(to.x - from.x).abs
end
def delta_y
-(to.y - from.y).abs
end
def bresenham
[from, to] + bresenham_loop(from.x, from.y, to.x, to.y)
end
def bresenham_loop(current_x, current_y, to_x, to_y)
error = delta_x + delta_y
until current_x == to_x && current_y == to_y
error, current_x = error + delta_y, current_x + step_x if 2 * error >= delta_y
error, current_y = error + delta_x, current_y + step_y if 2 * error <= delta_x
(result ||= []) << Point.new(current_x, current_y)
end
result
end
end
include Bresenham
include ComparableFigure
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
class Rectangle
include ComparableFigure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
# FIXME: This is procedural programming. Forced by 2-level nesting limit
output << render_pixel_at(canvas, x, y)
end
output << new_line
end
output[0..-2].join
end
def render_pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end

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

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

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,9 +2,9 @@
        @-------------@
        @-@@@@@@@@@@@-@
        @-@---------@-@
       -@-@------@@-@-@
       -@-@---@@@---@-@
       -@-@-@@------@-@
       +@-@-----@@@-@-@
       +@-@--@@@----@-@
       +@-@-@-------@-@
        @-@---------@-@
        @-@-@@@@----@-@
        @-@-@-------@-@
     # /tmp/d20131223-4637-1n35lph/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1n35lph/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-1n35lph/solution.rb:15:in `set_pixel'
     # /tmp/d20131223-4637-1n35lph/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 lines with a small slope
     Failure/Error: ascii.should eq rendering(expected)
       
       expected: "----------\n-@@-------\n---@@@@---\n-------@@-\n----------"
            got: "----------\n-@--------\n--@@@@----\n------@@@-\n----------"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
        ----------
       --@@-------
       ----@@@@---
       --------@@-
       +-@--------
       +--@@@@----
       +------@@@-
        ----------
     # /tmp/d20131223-4637-1n35lph/spec.rb:624:in `check_rendering_of'
     # /tmp/d20131223-4637-1n35lph/spec.rb:100:in `block (5 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

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

  5) Graphics Canvas drawing of shapes and rasterization of lines draws lines with two equal ends as points
     Failure/Error: canvas.draw make_line(make_point(1, 1), make_point(1, 1))
     TypeError:
       no implicit conversion of nil into Array
     # /tmp/d20131223-4637-1n35lph/solution.rb:92:in `+'
     # /tmp/d20131223-4637-1n35lph/solution.rb:92:in `bresenham'
     # /tmp/d20131223-4637-1n35lph/solution.rb:119:in `to_points'
     # /tmp/d20131223-4637-1n35lph/solution.rb:23:in `draw'
     # /tmp/d20131223-4637-1n35lph/spec.rb:143: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 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))
     TypeError:
       no implicit conversion of nil into Array
     # /tmp/d20131223-4637-1n35lph/solution.rb:92:in `+'
     # /tmp/d20131223-4637-1n35lph/solution.rb:92:in `bresenham'
     # /tmp/d20131223-4637-1n35lph/solution.rb:119:in `to_points'
     # /tmp/d20131223-4637-1n35lph/solution.rb:140:in `map'
     # /tmp/d20131223-4637-1n35lph/solution.rb:140:in `to_points'
     # /tmp/d20131223-4637-1n35lph/solution.rb:23:in `draw'
     # /tmp/d20131223-4637-1n35lph/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)>'

  7) Graphics Canvas drawing of shapes and rasterization of rectangles works with rects with a zero width and height as a single point
     Failure/Error: canvas.draw make_rectangle(make_point(1, 1), make_point(1, 1))
     TypeError:
       no implicit conversion of nil into Array
     # /tmp/d20131223-4637-1n35lph/solution.rb:92:in `+'
     # /tmp/d20131223-4637-1n35lph/solution.rb:92:in `bresenham'
     # /tmp/d20131223-4637-1n35lph/solution.rb:119:in `to_points'
     # /tmp/d20131223-4637-1n35lph/solution.rb:140:in `map'
     # /tmp/d20131223-4637-1n35lph/solution.rb:140:in `to_points'
     # /tmp/d20131223-4637-1n35lph/solution.rb:23:in `draw'
     # /tmp/d20131223-4637-1n35lph/spec.rb:193: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.08783 seconds
69 examples, 7 failures

Failed examples:

rspec /tmp/d20131223-4637-1n35lph/spec.rb:203 # Graphics Canvas drawing of shapes and rasterization renders multiple drawn shapes
rspec /tmp/d20131223-4637-1n35lph/spec.rb:51 # Graphics Canvas drawing of shapes and rasterization of points works for multiple ones
rspec /tmp/d20131223-4637-1n35lph/spec.rb:96 # Graphics Canvas drawing of shapes and rasterization of lines works with lines with a small slope
rspec /tmp/d20131223-4637-1n35lph/spec.rb:127 # Graphics Canvas drawing of shapes and rasterization of lines works with multiple lines
rspec /tmp/d20131223-4637-1n35lph/spec.rb:141 # Graphics Canvas drawing of shapes and rasterization of lines draws lines with two equal ends as points
rspec /tmp/d20131223-4637-1n35lph/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-1n35lph/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

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

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

+module Graphics
+ class Canvas
+ EMPTY_PIXEL = 0
+ FULL_PIXEL = 1
+
+ attr_reader :width, :height
+
+ def initialize(width, height)
+ @width, @height = width, height
+
+ @pixels = Array.new(width)
+ @pixels.map! { Array.new(height, EMPTY_PIXEL) }
+ end
+
+ def set_pixel(x, y)
+ @pixels[x][y] = FULL_PIXEL
+ end
+
+ def pixel_at?(x, y)
+ @pixels[x][y] == FULL_PIXEL
+ end
+
+ def draw(figure)
+ figure.to_points.each { |point| set_pixel(point.x, point.y) }
+ end
+
+ def render_as(renderer)
+ renderer.render(self)
+ end
+ end
+
+ class Point
+ include Comparable
+ attr_reader :x, :y
+
+ def initialize(x, y)
+ @x, @y = x, y
+ end
+
+ def <=>(other)
+ comparison = x <=> other.x
+
+ if comparison.nonzero?
+ comparison
+ else
+ y <=> other.y
+ end
+ end
+
+ alias :eql? :==
+
+ def hash
+ [@x, @y].hash
+ end
+
+ def to_points
+ [self]
+ end
+ end
+
+ class Figure
+ def ==(other)
+ sorted_vertices == other.sorted_vertices
+ end
+
+ alias :eql? :==
+
+ def hash
+ sorted_vertices.hash
+ end
+ end
+
+ class Line < Figure
+ module Bresenham
+ private
+
+ def step_x
+ from.x < to.x ? 1 : -1
+ end
+
+ def step_y
+ from.y < to.y ? 1 : -1
+ end
+
+ def bresenham
+ delta_x, delta_y = (to.x - from.x).abs, -(to.y - from.y).abs
+ error = delta_x + delta_y
+ [from, to] + bresenham_loop(from.x, to.x, from.y, to.y, delta_x, delta_y, error)
+ end
+
+ def bresenham_loop(from_x, to_x, from_y, to_y, delta_x, delta_y, error)
+ until from_x == to_x && from_y == to_y
+ error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
+ error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
+ (result ||= []) << Point.new(from_x, from_y)
+ end
+
+ result
+ end
+ end
+
+ include Bresenham
+ attr_reader :from, :to
+
+ # point1, point2 makes more sense to me for naming the arguments below
+ # skeptic forbids that
+ def initialize(first, second)
+ @from, @to = [first, second].sort
+ end
+
+ def to_points
+ bresenham
+ end
+
+ protected
+
+ def sorted_vertices
+ [from, to].sort
+ end
+ end
+
+ class Rectangle < Figure
+ attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
+
+ def initialize(first, second)
+ @left, @right = [first, second].sort
+ @top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
+ @top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
+ end
+
+ def to_points
+ edges.map(&:to_points).flatten(1)
+ end
+
+ def edges
+ [Line.new(top_left, top_right),
+ Line.new(top_left, bottom_left),
+ Line.new(bottom_right, bottom_left),
+ Line.new(bottom_right, top_right)]
+ end
+
+ protected
+
+ def sorted_vertices
+ [top_left, top_right, bottom_left, bottom_right].sort
+ end
+ end
+
+ module Renderers
+ module Render
+ def render_output(canvas)
+ output = []
+ 0.upto(canvas.height - 1).each do |y|
+ 0.upto(canvas.width - 1).each do |x|
+ output << pixel_at(canvas, x, y)
+ end
+ output << new_line
+ end
+
+ output[0..-2].to_a.join
+ end
+
+ def pixel_at(canvas, x, y)
+ canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
+ end
+ end
+
+ class Ascii
+ class << self
+ include Render
+
+ def full_pixel
+ '@'.freeze
+ end
+
+ def blank_pixel
+ '-'.freeze
+ end
+
+ def new_line
+ "\n".freeze
+ end
+
+ alias :render :render_output
+ end
+ end
+
+ class Html
+ class << self
+ HTML_BEGINNING = '
+ <!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">
+ '.freeze
+
+ HTML_ENDING = '
+ </div>
+ </body>
+ </html>
+ '.freeze
+
+ include Render
+
+ def full_pixel
+ '<b></b>'.freeze
+ end
+
+ def blank_pixel
+ '<i></i>'.freeze
+ end
+
+ def new_line
+ '<br>'.freeze
+ end
+
+ def render(canvas)
+ HTML_BEGINNING + render_output(canvas) + HTML_ENDING
+ end
+ end
+ end
+ end
+end

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

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
@pixels = Array.new(width)
@pixels.map! { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
+ alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
- alias :eql? :==
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
class Figure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
class Line < Figure
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
def bresenham
- delta_x, delta_y = (to.x - from.x).abs, -(to.y - from.y).abs
+ delta_x = (to.x - from.x).abs
+ delta_y = -(to.y - from.y).abs
error = delta_x + delta_y
+
[from, to] + bresenham_loop(from.x, to.x, from.y, to.y, delta_x, delta_y, error)
end
def bresenham_loop(from_x, to_x, from_y, to_y, delta_x, delta_y, error)
until from_x == to_x && from_y == to_y
error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
(result ||= []) << Point.new(from_x, from_y)
end
result
end
end
include Bresenham
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
class Rectangle < Figure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
+ # FIXME: This is procedural programming. Forced by 2-level nesting limit
output << pixel_at(canvas, x, y)
end
output << new_line
end
output[0..-2].to_a.join
end
def pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end

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

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
@pixels = Array.new(width)
@pixels.map! { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
-
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
class Figure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
class Line < Figure
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
- def bresenham
- delta_x = (to.x - from.x).abs
- delta_y = -(to.y - from.y).abs
- error = delta_x + delta_y
+ def delta_x
+ (to.x - from.x).abs
+ end
- [from, to] + bresenham_loop(from.x, to.x, from.y, to.y, delta_x, delta_y, error)
+ def delta_y
+ -(to.y - from.y).abs
end
- def bresenham_loop(from_x, to_x, from_y, to_y, delta_x, delta_y, error)
+ def bresenham
+ [from, to] + bresenham_loop(from.x, to.x, from.y, to.y)
+ end
+
+ def bresenham_loop(from_x, to_x, from_y, to_y)
+ error = delta_x + delta_y
+
until from_x == to_x && from_y == to_y
error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
(result ||= []) << Point.new(from_x, from_y)
end
result
end
end
include Bresenham
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
class Rectangle < Figure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
# FIXME: This is procedural programming. Forced by 2-level nesting limit
output << pixel_at(canvas, x, y)
end
output << new_line
end
output[0..-2].to_a.join
end
def pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end

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

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
@pixels = Array.new(width)
@pixels.map! { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
class Figure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
class Line < Figure
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
def delta_x
(to.x - from.x).abs
end
def delta_y
-(to.y - from.y).abs
end
def bresenham
[from, to] + bresenham_loop(from.x, to.x, from.y, to.y)
end
def bresenham_loop(from_x, to_x, from_y, to_y)
error = delta_x + delta_y
until from_x == to_x && from_y == to_y
error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
(result ||= []) << Point.new(from_x, from_y)
end
result
end
end
include Bresenham
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
class Rectangle < Figure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
# FIXME: This is procedural programming. Forced by 2-level nesting limit
- output << pixel_at(canvas, x, y)
+ output << render_pixel_at(canvas, x, y)
end
output << new_line
end
- output[0..-2].to_a.join
+ output[0..-2].join
end
- def pixel_at(canvas, x, y)
+ def render_pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end

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

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
@pixels = Array.new(width)
@pixels.map! { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
- class Figure
+ module ComparableFigure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
- class Line < Figure
+ class Line
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
def delta_x
(to.x - from.x).abs
end
def delta_y
-(to.y - from.y).abs
end
def bresenham
[from, to] + bresenham_loop(from.x, to.x, from.y, to.y)
end
def bresenham_loop(from_x, to_x, from_y, to_y)
error = delta_x + delta_y
until from_x == to_x && from_y == to_y
error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
(result ||= []) << Point.new(from_x, from_y)
end
result
end
end
include Bresenham
+ include ComparableFigure
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
- class Rectangle < Figure
+ class Rectangle
+ include ComparableFigure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
# FIXME: This is procedural programming. Forced by 2-level nesting limit
output << render_pixel_at(canvas, x, y)
end
output << new_line
end
output[0..-2].join
end
def render_pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end

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

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
- @pixels = Array.new(width)
- @pixels.map! { Array.new(height, EMPTY_PIXEL) }
+ @pixels = Array.new(width) { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
module ComparableFigure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
class Line
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
def delta_x
(to.x - from.x).abs
end
def delta_y
-(to.y - from.y).abs
end
def bresenham
[from, to] + bresenham_loop(from.x, to.x, from.y, to.y)
end
def bresenham_loop(from_x, to_x, from_y, to_y)
error = delta_x + delta_y
until from_x == to_x && from_y == to_y
error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
(result ||= []) << Point.new(from_x, from_y)
end
result
end
end
include Bresenham
include ComparableFigure
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
class Rectangle
include ComparableFigure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
# FIXME: This is procedural programming. Forced by 2-level nesting limit
output << render_pixel_at(canvas, x, y)
end
output << new_line
end
output[0..-2].join
end
def render_pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end

Георги обнови решението на 22.12.2013 15:32 (преди почти 11 години)

module Graphics
class Canvas
EMPTY_PIXEL = 0
FULL_PIXEL = 1
attr_reader :width, :height
def initialize(width, height)
@width, @height = width, height
@pixels = Array.new(width) { Array.new(height, EMPTY_PIXEL) }
end
def set_pixel(x, y)
@pixels[x][y] = FULL_PIXEL
end
def pixel_at?(x, y)
@pixels[x][y] == FULL_PIXEL
end
def draw(figure)
figure.to_points.each { |point| set_pixel(point.x, point.y) }
end
def render_as(renderer)
renderer.render(self)
end
end
class Point
include Comparable
attr_reader :x, :y
alias :eql? :==
def initialize(x, y)
@x, @y = x, y
end
def <=>(other)
comparison = x <=> other.x
if comparison.nonzero?
comparison
else
y <=> other.y
end
end
def hash
[@x, @y].hash
end
def to_points
[self]
end
end
module ComparableFigure
def ==(other)
sorted_vertices == other.sorted_vertices
end
alias :eql? :==
def hash
sorted_vertices.hash
end
end
class Line
module Bresenham
private
def step_x
from.x < to.x ? 1 : -1
end
def step_y
from.y < to.y ? 1 : -1
end
def delta_x
(to.x - from.x).abs
end
def delta_y
-(to.y - from.y).abs
end
def bresenham
- [from, to] + bresenham_loop(from.x, to.x, from.y, to.y)
+ [from, to] + bresenham_loop(from.x, from.y, to.x, to.y)
end
- def bresenham_loop(from_x, to_x, from_y, to_y)
+ def bresenham_loop(current_x, current_y, to_x, to_y)
error = delta_x + delta_y
- until from_x == to_x && from_y == to_y
- error, from_x = error + delta_y, from_x + step_x if 2 * error >= delta_y
- error, from_y = error + delta_x, from_y + step_y if 2 * error <= delta_x
- (result ||= []) << Point.new(from_x, from_y)
+ until current_x == to_x && current_y == to_y
+ error, current_x = error + delta_y, current_x + step_x if 2 * error >= delta_y
+ error, current_y = error + delta_x, current_y + step_y if 2 * error <= delta_x
+ (result ||= []) << Point.new(current_x, current_y)
end
result
end
end
include Bresenham
include ComparableFigure
attr_reader :from, :to
# point1, point2 makes more sense to me for naming the arguments below
# skeptic forbids that
def initialize(first, second)
@from, @to = [first, second].sort
end
def to_points
bresenham
end
protected
def sorted_vertices
[from, to].sort
end
end
class Rectangle
include ComparableFigure
attr_reader :left, :right, :top_left, :top_right, :bottom_left, :bottom_right
def initialize(first, second)
@left, @right = [first, second].sort
@top_left, @bottom_left = [@left, Point.new(left.x, right.y)].sort
@top_right, @bottom_right = [@right, Point.new(right.x, left.y)].sort
end
def to_points
edges.map(&:to_points).flatten(1)
end
def edges
[Line.new(top_left, top_right),
Line.new(top_left, bottom_left),
Line.new(bottom_right, bottom_left),
Line.new(bottom_right, top_right)]
end
protected
def sorted_vertices
[top_left, top_right, bottom_left, bottom_right].sort
end
end
module Renderers
module Render
def render_output(canvas)
output = []
0.upto(canvas.height - 1).each do |y|
0.upto(canvas.width - 1).each do |x|
# FIXME: This is procedural programming. Forced by 2-level nesting limit
output << render_pixel_at(canvas, x, y)
end
output << new_line
end
output[0..-2].join
end
def render_pixel_at(canvas, x, y)
canvas.pixel_at?(x, y) ? full_pixel : blank_pixel
end
end
class Ascii
class << self
include Render
def full_pixel
'@'.freeze
end
def blank_pixel
'-'.freeze
end
def new_line
"\n".freeze
end
alias :render :render_output
end
end
class Html
class << self
HTML_BEGINNING = '
<!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">
'.freeze
HTML_ENDING = '
</div>
</body>
</html>
'.freeze
include Render
def full_pixel
'<b></b>'.freeze
end
def blank_pixel
'<i></i>'.freeze
end
def new_line
'<br>'.freeze
end
def render(canvas)
HTML_BEGINNING + render_output(canvas) + HTML_ENDING
end
end
end
end
end