Решение на Шеста задача от Десислава Цветкова

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

Към профила на Десислава Цветкова

Резултати

  • 6 точки от тестове
  • 0 бонус точки
  • 6 точки общо
  • 14 успешни тест(а)
  • 0 неуспешни тест(а)

Код

class TurtleGraphics
class Position
DIRECTIONS = [:up, :right, :down, :left]
MOVEMENT = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
attr_accessor :current_position, :orientation
def initialize
@orientation = :right
end
def change_orientation(turn)
@orientation = DIRECTIONS[(DIRECTIONS.index(@orientation) + turn) % 4]
end
def move(dimensions)
way = MOVEMENT[@orientation]
@current_position = [(@current_position.first + way.first) % dimensions.first,
(@current_position.last + way.last) % dimensions.last]
end
end
class Canvas
attr_reader :width, :height, :matrix
def initialize(width, height)
@width = width
@height = height
@matrix = Array.new(height) { Array.new(width, 0) }
end
def change_density(new_position)
@matrix[new_position.first][new_position.last] += 1
@matrix
end
class ASCII
def initialize(symbols)
@symbols = symbols
end
def draw(density_matrix)
from_table_string(density_matrix)
end
private
def from_table_string(density_matrix)
from_table_symbols(density_matrix).map { |line| line.join }. join("\n")
end
def from_table_symbols(density_matrix)
range_length = 1.0 / (@symbols.size - 1)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
@symbols[(value.to_f / max / range_length).ceil]
end
end
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
end
class HTML
def initialize(size)
@size = size
end
def draw(density_matrix)
make_whole_html(density_matrix)
end
private
def make_whole_html(density_matrix)
"<!DOCTYPE html>
<html>#{make_head}#{make_body(density_matrix)}</html>"
end
def make_opacity_table(density_matrix)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
format('%.2f', value.to_f / max)
end
end
end
def make_html_table(density_matrix)
opacity_table = make_opacity_table(density_matrix)
string_html = opacity_table.map do |row|
table_row = row.map do |opacity|
'<td style="opacity: ' + opacity.to_s + '"></td>'
end.join
"<tr>#{table_row}</tr>"
end
.join
"<table>#{string_html}</table>"
end
def make_head
"<head>
<title>Turtle graphics</title>
<style>
table {
border-spacing: 0;
}
tr {
padding: 0;
}
td {
width: #{@size}px;
height: #{@size}px;
background-color: black;
padding: 0;
}
</style>
</head>"
end
def make_body(density_matrix)
"<body>#{make_html_table(density_matrix)}</body>"
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
end
end
class Turtle
attr_reader :position
def initialize(width, height)
@position = Position.new
@canvas = Canvas.new(width, height)
end
def draw(type = nil, &block)
instance_eval(&block)
return @canvas.matrix if type.nil?
type.draw(@canvas.matrix)
end
def move
spawn_at(0, 0) if @position.current_position.nil?
dimensions = [@canvas.height, @canvas.width]
@canvas.change_density(@position.move(dimensions))
end
def turn_left
@position.change_orientation(-1)
end
def turn_right
@position.change_orientation(1)
end
def spawn_at(row, column)
@position.current_position = [row, column]
@canvas.change_density(@position.current_position)
end
def look(orientation)
@position.orientation = orientation
end
end
end

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

..............

Finished in 0.01208 seconds
14 examples, 0 failures

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

Десислава обнови решението на 28.11.2015 11:49 (преди над 8 години)

+class Position
+ @@corresponding = {left: [:down, :up,],
+ up: [:left, :right],
+ right: [:up, :down],
+ down: [:right, :left]}
+
+ @@directions = {left: 0, right: 1}
+
+ @@movement = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
+ attr_accessor :current_position
+ def initialize
+ @orientation = :right
+ @current_position = nil
+ end
+
+ def change_orientation(direction)
+ @orientation = @@corresponding[@orientation][@@directions[direction]]
+ end
+
+ def move(dimensions)
+ @current_position.map!.with_index do |coordinate, index|
+ (coordinate + @@movement[@orientation][index]) % dimensions[index]
+ end
+ end
+end
+
+class TurtleGraphics
+end
+
+class Canvas
+ attr_reader :width, :heigth, :matrix
+ def initialize(width, heigth)
+ @width , @heigth = width, heigth
+ @matrix = make_matrix
+ end
+
+ def make_matrix
+ matrix, row = [], []
+ @width.times{ row << 0 }
+ @heigth.times{ matrix << row.dup }
+ matrix
+ end
+
+ def change_density(new_position)
+ @matrix[new_position.first][new_position.last] += 1
+ @matrix
+ end
+
+ private :make_matrix
+end
+
+
+class TurtleGraphics::Turtle
+
+ attr_reader :position
+ def initialize(width, heigth)
+ @position = Position.new
+ @canvas = Canvas.new(width, heigth)
+ end
+
+ def draw(type = nil, &block)
+ instance_eval(&block)
+ return @canvas.matrix if type.nil?
+ if type.instance_of?(TurtleGraphics::Canvas::ASCII)
+ type.from_table_string(@canvas.matrix ).strip
+ else
+ type.make_whole_html(@canvas.matrix )
+ end
+ end
+
+ def move
+ spawn_at(0, 0) if @position.current_position.nil?
+ dimensions = [@canvas.heigth, @canvas.width]
+ @canvas.change_density(@position.move(dimensions))
+ end
+
+ def turn_left
+ @position.change_orientation(:left)
+ end
+
+ def turn_right
+ @position.change_orientation(:right)
+ end
+
+ def spawn_at(row, column)
+ # да се променя ли интензитетът?
+ @position.current_position = [row, column]
+ @canvas.change_density(@position.current_position)
+ end
+
+ def look(orientation)
+ @position.orientation = orientation
+ end
+end
+
+class TurtleGraphics::Canvas::ASCII
+ def initialize(symbols)
+ @symbols = symbols
+ end
+
+ def from_table_string(density_matrix)
+ from_table_symbols(density_matrix).reduce("") do |result, line|
+ result + line.reduce("", :+) + "\n"
+ end
+ end
+
+ def from_table_symbols(density_matrix)
+ max = find_max(density_matrix)
+ ranges = make_ranges(density_matrix)
+ p ranges
+ density_matrix.map do |line|
+ line.map do |value|
+ @symbols[find_place(ranges, 1.0 * value / max)]
+ end
+ end
+ end
+
+ def find_max(density_matrix)
+ density_matrix.map { |x| x.max }.max
+ end
+
+ def find_place(array, value)
+ array.each_with_index do |element, index|
+ return index if value <= element
+ end
+ end
+
+ def make_ranges(density_matrix)
+ range_lenght = 1.0 / (@symbols.size - 1)
+ ranges = [0]
+ (@symbols.size - 1).times do
+ ranges << ranges.last + range_lenght
+ end
+ ranges
+ end
+
+ private :make_ranges, :find_max, :find_place, :from_table_symbols
+end
+
+class TurtleGraphics::Canvas::HTML
+ def initialize(size)
+ @size = size
+ end
+
+ def make_opacity_table(density_matrix)
+ max = find_max(density_matrix)
+ density_matrix.map do |line|
+ line.map do |value|
+ format('%.2f', 1.0 * value / max)
+ end
+ end
+ end
+
+ def make_whole_html(density_matrix)
+ "<!DOCTYPE html>
+<html>#{make_head}#{make_body(density_matrix)}</html>"
+ end
+
+ def make_html_table(density_matrix)
+ opacity_table = make_opacity_table(density_matrix)
+ string_html = opacity_table.reduce("") do |string, row|
+ table_row = row.map do |opacity|
+ '<td style="opacity: ' + opacity.to_s + '"></td>'
+ end
+ .reduce(:+)
+ string + "<tr>#{table_row}</tr>"
+ end
+ "<table>#{string_html}</table>"
+ end
+
+ def make_head
+ "<head>
+ <title>Turtle graphics</title>
+
+ <style>
+ table {
+ border-spacing: 0;
+ }
+
+ tr {
+ padding: 0;
+ }
+
+ td {
+ width: #{@size}px;
+ height: #{@size}px;
+
+ background-color: black;
+ padding: 0;
+ }
+ </style>
+</head>"
+ end
+
+ def make_body(density_matrix)
+ "<body>#{make_html_table(density_matrix)}</body>"
+ end
+
+ def find_max(density_matrix)
+ density_matrix.map { |x| x.max }.max
+ end
+
+ private :find_max, :make_head, :make_body, :make_html_table, :make_opacity_table
+end

Десислава обнови решението на 28.11.2015 11:52 (преди над 8 години)

class Position
@@corresponding = {left: [:down, :up,],
up: [:left, :right],
right: [:up, :down],
down: [:right, :left]}
@@directions = {left: 0, right: 1}
@@movement = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
attr_accessor :current_position
def initialize
@orientation = :right
@current_position = nil
end
def change_orientation(direction)
@orientation = @@corresponding[@orientation][@@directions[direction]]
end
def move(dimensions)
@current_position.map!.with_index do |coordinate, index|
- (coordinate + @@movement[@orientation][index]) % dimensions[index]
- end
+ (coordinate + @@movement[@orientation][index]) % dimensions[index]
+ end
end
end
class TurtleGraphics
end
class Canvas
attr_reader :width, :heigth, :matrix
def initialize(width, heigth)
@width , @heigth = width, heigth
@matrix = make_matrix
end
def make_matrix
matrix, row = [], []
@width.times{ row << 0 }
@heigth.times{ matrix << row.dup }
matrix
end
def change_density(new_position)
@matrix[new_position.first][new_position.last] += 1
@matrix
end
private :make_matrix
end
class TurtleGraphics::Turtle
attr_reader :position
def initialize(width, heigth)
@position = Position.new
@canvas = Canvas.new(width, heigth)
end
def draw(type = nil, &block)
instance_eval(&block)
return @canvas.matrix if type.nil?
if type.instance_of?(TurtleGraphics::Canvas::ASCII)
type.from_table_string(@canvas.matrix ).strip
else
type.make_whole_html(@canvas.matrix )
end
end
def move
spawn_at(0, 0) if @position.current_position.nil?
dimensions = [@canvas.heigth, @canvas.width]
@canvas.change_density(@position.move(dimensions))
end
def turn_left
@position.change_orientation(:left)
end
def turn_right
@position.change_orientation(:right)
end
def spawn_at(row, column)
# да се променя ли интензитетът?
@position.current_position = [row, column]
@canvas.change_density(@position.current_position)
end
def look(orientation)
@position.orientation = orientation
end
end
class TurtleGraphics::Canvas::ASCII
def initialize(symbols)
@symbols = symbols
end
def from_table_string(density_matrix)
from_table_symbols(density_matrix).reduce("") do |result, line|
result + line.reduce("", :+) + "\n"
end
end
def from_table_symbols(density_matrix)
max = find_max(density_matrix)
ranges = make_ranges(density_matrix)
p ranges
density_matrix.map do |line|
line.map do |value|
@symbols[find_place(ranges, 1.0 * value / max)]
end
end
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
def find_place(array, value)
array.each_with_index do |element, index|
return index if value <= element
end
end
def make_ranges(density_matrix)
range_lenght = 1.0 / (@symbols.size - 1)
ranges = [0]
(@symbols.size - 1).times do
ranges << ranges.last + range_lenght
end
ranges
end
private :make_ranges, :find_max, :find_place, :from_table_symbols
end
class TurtleGraphics::Canvas::HTML
def initialize(size)
@size = size
end
def make_opacity_table(density_matrix)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
format('%.2f', 1.0 * value / max)
end
end
end
def make_whole_html(density_matrix)
"<!DOCTYPE html>
<html>#{make_head}#{make_body(density_matrix)}</html>"
end
def make_html_table(density_matrix)
opacity_table = make_opacity_table(density_matrix)
string_html = opacity_table.reduce("") do |string, row|
table_row = row.map do |opacity|
'<td style="opacity: ' + opacity.to_s + '"></td>'
end
.reduce(:+)
string + "<tr>#{table_row}</tr>"
end
"<table>#{string_html}</table>"
end
def make_head
"<head>
<title>Turtle graphics</title>
<style>
table {
border-spacing: 0;
}
tr {
padding: 0;
}
td {
width: #{@size}px;
height: #{@size}px;
background-color: black;
padding: 0;
}
</style>
</head>"
end
def make_body(density_matrix)
"<body>#{make_html_table(density_matrix)}</body>"
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
private :find_max, :make_head, :make_body, :make_html_table, :make_opacity_table
end

Здравей :)

След като си накарала кода да работи, хайде да го подобрим, разкрасим и полираме :)

  • Хубаво е класовете да са в един общ клас/модул. Така се предпазваш от случайни сблъсквания на имена с класове/модули от друг код. Например, има вероятност да съществува друг клас Position, дефиниран преди твоя код. Ако е така, вместо да създадеш нов, без да искаш ще отвориш съществуващия клас и най-вероятно ще се счупи твоят и чуждият код едновременно. Затова дефинирай всички класове в TurtleGraphics.
    Самото дефиниране е препоръчително да го правиш като ги нестваш:
module TurtleGraphics
  class Position
    ...
  end

  class Turtle
    ...
  end
end

вместо

module TurtleGraphics
end

class TurtleGraphics::Position
  ...
end

class TurtleGraphics::Turtle
  ...
end

Разликата е в начина, по който се търсят константи от кода на мястото на многоточието. При първия вариант се търси първо в Turtle, после в TurtleGraphics и накрая в Object. Във втория случай се търси само в Turtle и Object. Например, ако някъде в кода използваш класа Position, в първия случай ще го намери, а във втория - не.

  • Идеята с клас Position е интересна, но имам няколко забележки за него:
    • Използваш класови променливи вместо константи. Щом не се променят и са едни и същи за всички инстанции на класа - трябва да са константи. Също, поведението на класовите променливи е странно на моменти и се избягват.
    • Сякаш си го направила по-сложно от необходимото :) Опитай да го опростиш. Не е нужно да имаш толкова сложни променливи. Например, @@corresponding може да се замени от един масив с подходящо наредени елементи: [:left, :up, :right, :down]. Как се завъртаме сега? Ами, просто вървиш напред и назад по елементите в масива :) Така и directions става излишен.
    • Трябваше ми доста умствено усилие да разбера какво правиш в move. Предполагам и на теб да го измислиш :) Това всичко го правиш за два елемента. Защо не разделиш position на x и y, и да ги промениш директно? Да, ще има два приличащи си реда, но ще е много по-ясно какво се случва. Същото важи и за dimensions и аргументите на функции, които приемат позиция.
    • В initialize не е нужно да задаваш @current_position = nil. Всички инстанционни променливи са nil по подразбиране.
    • След като адресираш тези коментари, може да се окаже, че този клас не е нужен, защото кодът е достатъчно малко, че да отиде в Turtle :)
  • @width , @heigth = width, heigth е прекалено overused начин за присвояване. Не печелиш нищо от това, че са направени на един ред. Даже губиш четимост и производителност, защото така се създава един масив ([width, height]), който веднага се "разпакетира" и става излишен. Просто ги направи на различни редове. Колкото по-ясно - толкова по-добре :)
    Между другото, правилното е height, не heigth. Вероятно си се объркала заради width - различни са :)
  • make_matrix може да се напише по-елегантно, използвайки Array.new с блок или със следния трик: число.times.map { код }.
  • Конвенцията за дефиниране на private методи, е да напишеш private и да ги дефинираш след това така:
class Star
  ...

  private

  def метод1
    ...
  end

  def метод2
    ...
  end
end

Хубавото на този начин е, че веднага става ясно, че започват дефиниции на private методи. По другия начин чак накрая на класа разбирам, че някои методи са private, и трябва да сравнявам един по един по име, за да разбера кои са private и кои - public. Става по-ясно :)

  • # да се променя ли интензитетът? - прецени какво ще стане ако не го променяш в spawn_at. Имаш два варианта - да го променяш преди всяка стъпка и в края, или в началото и след всяка стъпка. В момента работиш с втория => трябва да го промениш в spawn_at.
  • reduce не е подходящата функция за конкатениране на низове от масив. За целта има map и join. Първо променяш всеки елемент и накрая ги залепяш. :)
  • Метода draw не трябва да се интересува от това какъв вид canvas му подаваш. Помисли как да използва приетата инстанция, без да знае коя е. Целта ти трябва да е да можеш да напишеш нов клас, който като се подаде на draw да може да рендерира рисунката по съвсем различен начин от сегашните, без да променяш Turtle. Какво би му било необходимо на такъв клас, за да си свърши работата?
    Duck typing :)

  • Имаш забравено принтиране - p ranges. Внимавай, че Митьо взима точки за такива неща :P

  • find_place и make_ranges може да се замени с малко математика. Помисли как да превърнеш интензитета в индекс на елемент от масива със символи. :)
  • Вместо да умножаваш с 1.0, за да обърнеш цяло число в число с плаваща точка, можеш да използваш метода to_f. Така си личи какво искаш да направиш - а именно, да превърнеш нещо във Float.
  • Генерирането на HTML-а би било по-ясно, ако отделиш нещата, които не се повтарят, в някаква константа - шаблон (темплейт), в който просто да insert-неш нещата от таблицата.
  • lenght -> length :)

Ехе, какъв роман написах :) Надявам се коментарите да са били полезни. Питай, ако не си съгласна с нещо, или не съм доизяснил нещо. :)

Ще очаквам нова версия :)

Десислава обнови решението на 29.11.2015 16:11 (преди над 8 години)

-class Position
- @@corresponding = {left: [:down, :up,],
- up: [:left, :right],
- right: [:up, :down],
- down: [:right, :left]}
+class TurtleGraphics
+ class Position
+ DIRECTIONS = [:up, :right, :down, :left]
- @@directions = {left: 0, right: 1}
+ MOVEMENT = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
- @@movement = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
- attr_accessor :current_position
- def initialize
- @orientation = :right
- @current_position = nil
- end
+ attr_accessor :current_position
- def change_orientation(direction)
- @orientation = @@corresponding[@orientation][@@directions[direction]]
- end
+ def initialize
+ @orientation = :right
+ end
- def move(dimensions)
- @current_position.map!.with_index do |coordinate, index|
- (coordinate + @@movement[@orientation][index]) % dimensions[index]
+ def change_orientation(turn)
+ @orientation = DIRECTIONS[(DIRECTIONS.index(@orientation) + turn) % 4]
end
+
+ def move(dimensions)
+ way = MOVEMENT[@orientation]
+ @current_position = [(@current_position.first + way.first) % dimensions.first,
+ (@current_position.last + way.last) % dimensions.last]
+ end
end
-end
-class TurtleGraphics
-end
-class Canvas
- attr_reader :width, :heigth, :matrix
- def initialize(width, heigth)
- @width , @heigth = width, heigth
- @matrix = make_matrix
- end
+ class Canvas
+ attr_reader :width, :height, :matrix
+ def initialize(width, height)
+ @width = width
+ @height = height
+ @matrix = Array.new(height) {Array.new(width, 0)}
+ end
- def make_matrix
- matrix, row = [], []
- @width.times{ row << 0 }
- @heigth.times{ matrix << row.dup }
- matrix
- end
+ def change_density(new_position)
+ @matrix[new_position.first][new_position.last] += 1
+ @matrix
+ end
- def change_density(new_position)
- @matrix[new_position.first][new_position.last] += 1
- @matrix
- end
- private :make_matrix
-end
+ class ASCII
+ def initialize(symbols)
+ @symbols = symbols
+ end
+ def draw(density_matrix)
+ from_table_string(density_matrix)
+ end
-class TurtleGraphics::Turtle
+ private
- attr_reader :position
- def initialize(width, heigth)
- @position = Position.new
- @canvas = Canvas.new(width, heigth)
- end
+ def from_table_string(density_matrix)
+ from_table_symbols(density_matrix).map {|line| line.join}. join("\n")
+ end
- def draw(type = nil, &block)
- instance_eval(&block)
- return @canvas.matrix if type.nil?
- if type.instance_of?(TurtleGraphics::Canvas::ASCII)
- type.from_table_string(@canvas.matrix ).strip
- else
- type.make_whole_html(@canvas.matrix )
- end
- end
+ def from_table_symbols(density_matrix)
+ range_length = 1.0 / (@symbols.size - 1)
+ max = find_max(density_matrix)
+ density_matrix.map do |line|
+ line.map do |value|
+ @symbols[(value.to_f / max / range_length).ceil]
+ end
+ end
+ end
- def move
- spawn_at(0, 0) if @position.current_position.nil?
- dimensions = [@canvas.heigth, @canvas.width]
- @canvas.change_density(@position.move(dimensions))
- end
+ def find_max(density_matrix)
+ density_matrix.map { |x| x.max }.max
+ end
- def turn_left
- @position.change_orientation(:left)
- end
+ def make_ranges(density_matrix, range_length)
+ ranges = [0]
+ (@symbols.size - 1).times do
+ ranges << ranges.last + range_length
+ end
+ ranges
+ end
+ end
- def turn_right
- @position.change_orientation(:right)
- end
- def spawn_at(row, column)
- # да се променя ли интензитетът?
- @position.current_position = [row, column]
- @canvas.change_density(@position.current_position)
- end
+ class HTML
+ def initialize(size)
+ @size = size
+ end
- def look(orientation)
- @position.orientation = orientation
- end
-end
+ def draw(density_matrix)
+ make_whole_html(density_matrix)
+ end
-class TurtleGraphics::Canvas::ASCII
- def initialize(symbols)
- @symbols = symbols
- end
+ private
- def from_table_string(density_matrix)
- from_table_symbols(density_matrix).reduce("") do |result, line|
- result + line.reduce("", :+) + "\n"
- end
- end
+ def make_whole_html(density_matrix)
+ "<!DOCTYPE html>
+ <html>#{make_head}#{make_body(density_matrix)}</html>"
+ end
- def from_table_symbols(density_matrix)
- max = find_max(density_matrix)
- ranges = make_ranges(density_matrix)
- p ranges
- density_matrix.map do |line|
- line.map do |value|
- @symbols[find_place(ranges, 1.0 * value / max)]
+ def make_opacity_table(density_matrix)
+ max = find_max(density_matrix)
+ density_matrix.map do |line|
+ line.map do |value|
+ format('%.2f', value.to_f / max)
+ end
+ end
end
- end
- end
- def find_max(density_matrix)
- density_matrix.map { |x| x.max }.max
- end
+ def make_html_table(density_matrix)
+ opacity_table = make_opacity_table(density_matrix)
+ string_html = opacity_table.map do |row|
+ table_row = row.map do |opacity|
+ '<td style="opacity: ' + opacity.to_s + '"></td>'
+ end
+ .join
+ "<tr>#{table_row}</tr>"
+ end
+ .join
+ "<table>#{string_html}</table>"
+ end
- def find_place(array, value)
- array.each_with_index do |element, index|
- return index if value <= element
- end
- end
+ def make_head
+ "<head>
+ <title>Turtle graphics</title>
- def make_ranges(density_matrix)
- range_lenght = 1.0 / (@symbols.size - 1)
- ranges = [0]
- (@symbols.size - 1).times do
- ranges << ranges.last + range_lenght
- end
- ranges
- end
+ <style>
+ table {
+ border-spacing: 0;
+ }
- private :make_ranges, :find_max, :find_place, :from_table_symbols
-end
+ tr {
+ padding: 0;
+ }
-class TurtleGraphics::Canvas::HTML
- def initialize(size)
- @size = size
- end
+ td {
+ width: #{@size}px;
+ height: #{@size}px;
- def make_opacity_table(density_matrix)
- max = find_max(density_matrix)
- density_matrix.map do |line|
- line.map do |value|
- format('%.2f', 1.0 * value / max)
+ background-color: black;
+ padding: 0;
+ }
+ </style>
+ </head>"
end
- end
- end
- def make_whole_html(density_matrix)
- "<!DOCTYPE html>
-<html>#{make_head}#{make_body(density_matrix)}</html>"
- end
+ def make_body(density_matrix)
+ "<body>#{make_html_table(density_matrix)}</body>"
+ end
- def make_html_table(density_matrix)
- opacity_table = make_opacity_table(density_matrix)
- string_html = opacity_table.reduce("") do |string, row|
- table_row = row.map do |opacity|
- '<td style="opacity: ' + opacity.to_s + '"></td>'
+ def find_max(density_matrix)
+ density_matrix.map { |x| x.max }.max
end
- .reduce(:+)
- string + "<tr>#{table_row}</tr>"
end
- "<table>#{string_html}</table>"
end
- def make_head
- "<head>
- <title>Turtle graphics</title>
- <style>
- table {
- border-spacing: 0;
- }
+ class Turtle
+ attr_reader :position
- tr {
- padding: 0;
- }
+ def initialize(width, height)
+ @position = Position.new
+ @canvas = Canvas.new(width, height)
+ end
- td {
- width: #{@size}px;
- height: #{@size}px;
+ def draw(type = nil, &block)
+ instance_eval(&block)
+ return @canvas.matrix if type.nil?
+ type.draw(@canvas.matrix)
+ end
- background-color: black;
- padding: 0;
- }
- </style>
-</head>"
- end
+ def move
+ spawn_at(0, 0) if @position.current_position.nil?
+ dimensions = [@canvas.height, @canvas.width]
+ @canvas.change_density(@position.move(dimensions))
+ end
- def make_body(density_matrix)
- "<body>#{make_html_table(density_matrix)}</body>"
- end
+ def turn_left
+ @position.change_orientation(-1)
+ end
- def find_max(density_matrix)
- density_matrix.map { |x| x.max }.max
- end
+ def turn_right
+ @position.change_orientation(1)
+ end
- private :find_max, :make_head, :make_body, :make_html_table, :make_opacity_table
+ def spawn_at(row, column)
+ @position.current_position = [row, column]
+ @canvas.change_density(@position.current_position)
+ end
+
+ def look(orientation)
+ @position.orientation = orientation
+ end
+ end
end

Десислава обнови решението на 29.11.2015 17:10 (преди над 8 години)

class TurtleGraphics
class Position
DIRECTIONS = [:up, :right, :down, :left]
MOVEMENT = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
attr_accessor :current_position
def initialize
@orientation = :right
end
def change_orientation(turn)
@orientation = DIRECTIONS[(DIRECTIONS.index(@orientation) + turn) % 4]
end
def move(dimensions)
way = MOVEMENT[@orientation]
@current_position = [(@current_position.first + way.first) % dimensions.first,
(@current_position.last + way.last) % dimensions.last]
end
end
class Canvas
attr_reader :width, :height, :matrix
def initialize(width, height)
@width = width
- @height = height
+ @height = height
@matrix = Array.new(height) {Array.new(width, 0)}
end
def change_density(new_position)
@matrix[new_position.first][new_position.last] += 1
@matrix
end
class ASCII
def initialize(symbols)
@symbols = symbols
end
def draw(density_matrix)
from_table_string(density_matrix)
end
private
def from_table_string(density_matrix)
from_table_symbols(density_matrix).map {|line| line.join}. join("\n")
end
def from_table_symbols(density_matrix)
range_length = 1.0 / (@symbols.size - 1)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
@symbols[(value.to_f / max / range_length).ceil]
end
end
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
- end
-
- def make_ranges(density_matrix, range_length)
- ranges = [0]
- (@symbols.size - 1).times do
- ranges << ranges.last + range_length
- end
- ranges
end
end
class HTML
def initialize(size)
@size = size
end
def draw(density_matrix)
make_whole_html(density_matrix)
end
private
def make_whole_html(density_matrix)
"<!DOCTYPE html>
<html>#{make_head}#{make_body(density_matrix)}</html>"
end
def make_opacity_table(density_matrix)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
format('%.2f', value.to_f / max)
end
end
end
def make_html_table(density_matrix)
opacity_table = make_opacity_table(density_matrix)
string_html = opacity_table.map do |row|
table_row = row.map do |opacity|
'<td style="opacity: ' + opacity.to_s + '"></td>'
end
.join
"<tr>#{table_row}</tr>"
end
.join
"<table>#{string_html}</table>"
end
def make_head
"<head>
<title>Turtle graphics</title>
<style>
table {
border-spacing: 0;
}
tr {
padding: 0;
}
td {
width: #{@size}px;
height: #{@size}px;
background-color: black;
padding: 0;
}
</style>
</head>"
end
def make_body(density_matrix)
"<body>#{make_html_table(density_matrix)}</body>"
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
end
end
class Turtle
attr_reader :position
def initialize(width, height)
@position = Position.new
@canvas = Canvas.new(width, height)
end
def draw(type = nil, &block)
instance_eval(&block)
return @canvas.matrix if type.nil?
type.draw(@canvas.matrix)
end
def move
spawn_at(0, 0) if @position.current_position.nil?
dimensions = [@canvas.height, @canvas.width]
@canvas.change_density(@position.move(dimensions))
end
def turn_left
@position.change_orientation(-1)
end
def turn_right
@position.change_orientation(1)
end
def spawn_at(row, column)
@position.current_position = [row, column]
@canvas.change_density(@position.current_position)
end
def look(orientation)
@position.orientation = orientation
end
end
end

Сега стана супер :) Предполагам и на теб ти изглежда по-добре?

Остават само някои дребни проблеми във форматирането - трябва да има празно място в скобите на едноредов блок и да няма празни места след точката като chain-ваш неща.

Десислава обнови решението на 02.12.2015 17:26 (преди над 8 години)

class TurtleGraphics
class Position
DIRECTIONS = [:up, :right, :down, :left]
MOVEMENT = {left: [0, -1], right: [0, 1], up: [-1, 0], down: [1, 0]}
- attr_accessor :current_position
+ attr_accessor :current_position, :orientation
def initialize
@orientation = :right
end
def change_orientation(turn)
@orientation = DIRECTIONS[(DIRECTIONS.index(@orientation) + turn) % 4]
end
def move(dimensions)
way = MOVEMENT[@orientation]
@current_position = [(@current_position.first + way.first) % dimensions.first,
(@current_position.last + way.last) % dimensions.last]
end
end
class Canvas
attr_reader :width, :height, :matrix
def initialize(width, height)
@width = width
@height = height
- @matrix = Array.new(height) {Array.new(width, 0)}
+ @matrix = Array.new(height) { Array.new(width, 0) }
end
def change_density(new_position)
@matrix[new_position.first][new_position.last] += 1
@matrix
end
class ASCII
def initialize(symbols)
@symbols = symbols
end
def draw(density_matrix)
from_table_string(density_matrix)
end
private
def from_table_string(density_matrix)
- from_table_symbols(density_matrix).map {|line| line.join}. join("\n")
+ from_table_symbols(density_matrix).map { |line| line.join }. join("\n")
end
def from_table_symbols(density_matrix)
range_length = 1.0 / (@symbols.size - 1)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
@symbols[(value.to_f / max / range_length).ceil]
end
end
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
end
class HTML
def initialize(size)
@size = size
end
def draw(density_matrix)
make_whole_html(density_matrix)
end
private
def make_whole_html(density_matrix)
"<!DOCTYPE html>
<html>#{make_head}#{make_body(density_matrix)}</html>"
end
def make_opacity_table(density_matrix)
max = find_max(density_matrix)
density_matrix.map do |line|
line.map do |value|
format('%.2f', value.to_f / max)
end
end
end
def make_html_table(density_matrix)
opacity_table = make_opacity_table(density_matrix)
string_html = opacity_table.map do |row|
table_row = row.map do |opacity|
'<td style="opacity: ' + opacity.to_s + '"></td>'
- end
- .join
+ end.join
"<tr>#{table_row}</tr>"
end
.join
"<table>#{string_html}</table>"
end
def make_head
"<head>
<title>Turtle graphics</title>
<style>
table {
border-spacing: 0;
}
tr {
padding: 0;
}
td {
width: #{@size}px;
height: #{@size}px;
background-color: black;
padding: 0;
}
</style>
</head>"
end
def make_body(density_matrix)
"<body>#{make_html_table(density_matrix)}</body>"
end
def find_max(density_matrix)
density_matrix.map { |x| x.max }.max
end
end
end
class Turtle
attr_reader :position
def initialize(width, height)
@position = Position.new
@canvas = Canvas.new(width, height)
end
def draw(type = nil, &block)
instance_eval(&block)
return @canvas.matrix if type.nil?
type.draw(@canvas.matrix)
end
def move
spawn_at(0, 0) if @position.current_position.nil?
dimensions = [@canvas.height, @canvas.width]
@canvas.change_density(@position.move(dimensions))
end
def turn_left
@position.change_orientation(-1)
end
def turn_right
@position.change_orientation(1)
end
def spawn_at(row, column)
@position.current_position = [row, column]
@canvas.change_density(@position.current_position)
end
def look(orientation)
@position.orientation = orientation
end
end
end