Решение на Втора задача от Николай Станев

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

Към профила на Николай Станев

Резултати

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

Код

def obstacle_ahead?(snake, direction, dimensions)
snake_head = [(snake.last[0] + direction[0]), (snake.last[1] + direction[1])]
obstacle_ahead = false
obstacle_ahead_width = check_borders(snake_head[0], dimensions[:width])
obstacle_ahead_height = check_borders(snake_head[1], dimensions[:height])
obstacle_ahead = is_inside(obstacle_ahead_width, obstacle_ahead_height)
if snake.include?(snake_head) then obstacle_ahead = true end
obstacle_ahead
end
def is_inside(obstacle_ahead_width, obstacle_ahead_height)
obstacle_ahead = false
if (obstacle_ahead_width or obstacle_ahead_height)
obstacle_ahead = true
end
obstacle_ahead
end
def check_borders(snake_head_coordinates, max_dimension)
if snake_head_coordinates < 0
outside = true
elsif snake_head_coordinates >= max_dimension
outside = true
else
outside = false
end
end
def danger?(snake, direction, dimensions)
if obstacle_ahead?(snake, direction, dimensions)
danger = true
elsif obstacle_ahead?(move(snake, direction), direction, dimensions)
danger = true
else
danger = false
end
end
def new_food(snake, dimensions)
random = Random.new
part = [random.rand(dimensions[:width]), random.rand(dimensions[:height])]
while snake.include?(part) do
part = [random.rand(dimensions[:width]), random.rand(dimensions[:height])]
end
part
end
def move(snake, direction)
if snake.size > 1 then snake.delete_at(0) end
snake_head = snake.last.dup
snake_head[0] += direction[0]
snake_head[1] += direction[1]
snake.push(snake_head.dup)
snake.dup
end
def grow(snake, direction)
snake_end = snake.first
new_snake = move(snake, direction)
new_snake.unshift(snake_end)
new_snake
end

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

FFFFFFFFFFFF.......F

Failures:

  1) #move moves snake up/right/left/down
     Failure/Error: expect(move(snake, [1, 0])).to eq([[2, 3], [2, 4], [2, 5], [3, 5]])
       
       expected: [[2, 3], [2, 4], [2, 5], [3, 5]]
            got: [[2, 4], [2, 5], [2, 6], [3, 6]]
       
       (compared using ==)
     # /tmp/d20151026-15631-vsilag/spec.rb:6:in `block (2 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) #move moves one-position-sized snake
     Failure/Error: expect(move([[2, 2]], [-1, 0])).to eq([[1, 2]])
       
       expected: [[1, 2]]
            got: [[2, 2], [1, 2]]
       
       (compared using ==)
     # /tmp/d20151026-15631-vsilag/spec.rb:12:in `block (2 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) #move does not mutate the given arguments
     Failure/Error: expect { move(snake, direction) }.not_to change { snake }
       result should not have changed, but did change from [[2, 2], [2, 3], [2, 4], [2, 5]] to [[2, 3], [2, 4], [2, 5], [2, 6]]
     # /tmp/d20151026-15631-vsilag/spec.rb:17:in `block (2 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) #grow grows snake up/right/left/down
     Failure/Error: expect(grow(snake, [1, 0])).to eq([[2, 2], [2, 3], [2, 4], [2, 5], [3, 5]])
       
       expected: [[2, 2], [2, 3], [2, 4], [2, 5], [3, 5]]
            got: [[2, 3], [2, 4], [2, 5], [2, 6], [3, 6]]
       
       (compared using ==)
     # /tmp/d20151026-15631-vsilag/spec.rb:27:in `block (2 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) #grow grows one-position-sized snake
     Failure/Error: expect(grow([[2, 2]], [-1, 0])).to eq([[2, 2], [1, 2]])
       
       expected: [[2, 2], [1, 2]]
            got: [[2, 2], [2, 2], [1, 2]]
       
       (compared using ==)
     # /tmp/d20151026-15631-vsilag/spec.rb:33:in `block (2 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) #grow does not mutate the given arguments
     Failure/Error: expect { grow(snake, direction) }.not_to change { snake }
       result should not have changed, but did change from [[2, 2], [2, 3], [2, 4], [2, 5]] to [[2, 3], [2, 4], [2, 5], [2, 6]]
     # /tmp/d20151026-15631-vsilag/spec.rb:38:in `block (2 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) #new_food generates food on empty position
     Failure/Error: let(:next_food) { new_food(food, snake, dimensions) }
     ArgumentError:
       wrong number of arguments (3 for 2)
     # /tmp/d20151026-15631-vsilag/solution.rb:39:in `new_food'
     # /tmp/d20151026-15631-vsilag/spec.rb:47:in `block (2 levels) in <top (required)>'
     # /tmp/d20151026-15631-vsilag/spec.rb:53:in `block (2 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) #new_food does not generate food outside of borders (width)
     Failure/Error: let(:next_food) { new_food(food, snake, dimensions) }
     ArgumentError:
       wrong number of arguments (3 for 2)
     # /tmp/d20151026-15631-vsilag/solution.rb:39:in `new_food'
     # /tmp/d20151026-15631-vsilag/spec.rb:47:in `block (2 levels) in <top (required)>'
     # /tmp/d20151026-15631-vsilag/spec.rb:57:in `block (2 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) #new_food does not generate food outside of borders (height)
     Failure/Error: let(:next_food) { new_food(food, snake, dimensions) }
     ArgumentError:
       wrong number of arguments (3 for 2)
     # /tmp/d20151026-15631-vsilag/solution.rb:39:in `new_food'
     # /tmp/d20151026-15631-vsilag/spec.rb:47:in `block (2 levels) in <top (required)>'
     # /tmp/d20151026-15631-vsilag/spec.rb:61:in `block (2 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) #new_food does not generate food on position where the snake is
     Failure/Error: let(:next_food) { new_food(food, snake, dimensions) }
     ArgumentError:
       wrong number of arguments (3 for 2)
     # /tmp/d20151026-15631-vsilag/solution.rb:39:in `new_food'
     # /tmp/d20151026-15631-vsilag/spec.rb:47:in `block (2 levels) in <top (required)>'
     # /tmp/d20151026-15631-vsilag/spec.rb:65:in `block (2 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) #new_food does not generate food on position where food is already present
     Failure/Error: let(:next_food) { new_food(food, snake, dimensions) }
     ArgumentError:
       wrong number of arguments (3 for 2)
     # /tmp/d20151026-15631-vsilag/solution.rb:39:in `new_food'
     # /tmp/d20151026-15631-vsilag/spec.rb:47:in `block (2 levels) in <top (required)>'
     # /tmp/d20151026-15631-vsilag/spec.rb:69:in `block (2 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) #new_food does not mutate the given arguments
     Failure/Error: expect { new_food(food, snake, dimensions) }.not_to change { snake }
     ArgumentError:
       wrong number of arguments (3 for 2)
     # /tmp/d20151026-15631-vsilag/solution.rb:39:in `new_food'
     # /tmp/d20151026-15631-vsilag/spec.rb:73:in `block (3 levels) in <top (required)>'
     # /tmp/d20151026-15631-vsilag/spec.rb:73:in `block (2 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) #danger? does not mutate the given arguments
     Failure/Error: expect { danger?(snake, direction, dimensions) }.not_to change { snake }
       result should not have changed, but did change from [[1, 2], [1, 3]] to [[1, 3], [1, 4]]
     # /tmp/d20151026-15631-vsilag/spec.rb:123:in `block (2 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.0113 seconds
20 examples, 13 failures

Failed examples:

rspec /tmp/d20151026-15631-vsilag/spec.rb:4 # #move moves snake up/right/left/down
rspec /tmp/d20151026-15631-vsilag/spec.rb:11 # #move moves one-position-sized snake
rspec /tmp/d20151026-15631-vsilag/spec.rb:15 # #move does not mutate the given arguments
rspec /tmp/d20151026-15631-vsilag/spec.rb:25 # #grow grows snake up/right/left/down
rspec /tmp/d20151026-15631-vsilag/spec.rb:32 # #grow grows one-position-sized snake
rspec /tmp/d20151026-15631-vsilag/spec.rb:36 # #grow does not mutate the given arguments
rspec /tmp/d20151026-15631-vsilag/spec.rb:49 # #new_food generates food on empty position
rspec /tmp/d20151026-15631-vsilag/spec.rb:56 # #new_food does not generate food outside of borders (width)
rspec /tmp/d20151026-15631-vsilag/spec.rb:60 # #new_food does not generate food outside of borders (height)
rspec /tmp/d20151026-15631-vsilag/spec.rb:64 # #new_food does not generate food on position where the snake is
rspec /tmp/d20151026-15631-vsilag/spec.rb:68 # #new_food does not generate food on position where food is already present
rspec /tmp/d20151026-15631-vsilag/spec.rb:72 # #new_food does not mutate the given arguments
rspec /tmp/d20151026-15631-vsilag/spec.rb:120 # #danger? does not mutate the given arguments

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

Николай обнови решението на 17.10.2015 00:44 (преди над 9 години)

+def obstacle_ahead?(snake, direction, dimensions)
+ arr = [(snake.last[0] + direction[0]), (snake.last[1] + direction[1])]
+ obstacle_ahead = false
+ if arr[0] < 0 or arr[0] >= dimensions[:width] then obstacle_ahead = true end
+ if arr[1] < 0 and arr[0] >= dimensions[:height] then obstacle_ahead = true end
+ if snake.include?(arr) then obstacle_ahead = true end
+ obstacle_ahead
+end
+
+def danger?(snake, direction, dimensions)
+ arr = [(snake.last[0] + direction[0] * 2), (snake.last[1] + direction[1] * 2)]
+ obstacle_ahead = false
+ if arr[0] < 0 or arr[0] >= dimensions[:width] then obstacle_ahead = true end
+ if arr[1] < 0 and arr[0] >= dimensions[:height] then obstacle_ahead = true end
+ if snake.include?(arr) then obstacle_ahead = true end
+ obstacle_ahead
+end
+
+def new_food(snake, dimensions)
+ random = Random.new
+ part = [random.rand(dimensions[:width]), random.rand(dimensions[:height])]
+ while snake.include?(part) do
+ part = [random.rand(dimensions[:width]), random.rand(dimensions[:height])]
+ end
+ part
+end
+
+def move(snake, direction)
+ reorder(snake)
+ snake.last[0] += direction[0]
+ snake.last[1] += direction[1]
+ Array.new(snake)
+end
+
+def reorder(snake)
+ for index in 0..(snake.size-2)
+ snake[index][0] = snake[index+1][0]
+ snake[index][1] = snake[index+1][1]
+ end
+end
+
+def grow(snake, direction)
+ snake_last_part = Array.new(snake[0])
+ reorder(snake)
+ snake.unshift(snake_last_part)
+ snake.last[0] += direction[0]
+ snake.last[1] += direction[1]
+ Array.new(snake)
+end
  • obstacle_ahead? и danger? изглеждат почти едни и същи. Не можеше ли да използваш единия, за имплементацията на другия. Също според условието danger? трябва да проверява за опасност след един или два хода, не само два. Можеше да дефинираш още няколко метода, за да може двата метода да не са стена от код.
  • Казали сме да не използвате for. Беше ли нужен целия reorder? Не е ли достатъчно само да се махне началото? Също move и grow правят повтарящи се операции, което се дължи в голяма степен на факта, че reorder не си е свършил изцяло работата за последния индекс.
  • Във форума има малка дискусия за детерминистичността на new_food.
  • Опитвай да измисляш имена по-близо до домейна на решавания проблем, а не имплементацията. Например arr казва, че има някакъв масив. А трябваше да казва, че съдържа новата глава/следващата позиция/нещо подобно.
  • Object#dup е по-ясен от Array.new, ако искаш да кажеш, че правиш копие.

Като цяло правиш доста неща излишно итеративно.

Николай обнови решението на 18.10.2015 17:53 (преди над 9 години)

def obstacle_ahead?(snake, direction, dimensions)
- arr = [(snake.last[0] + direction[0]), (snake.last[1] + direction[1])]
+ snake_head = [(snake.last[0] + direction[0]), (snake.last[1] + direction[1])]
obstacle_ahead = false
- if arr[0] < 0 or arr[0] >= dimensions[:width] then obstacle_ahead = true end
- if arr[1] < 0 and arr[0] >= dimensions[:height] then obstacle_ahead = true end
- if snake.include?(arr) then obstacle_ahead = true end
+ obstacle_ahead_width = check_borders(snake_head[0], dimensions[:width])
+ obstacle_ahead_height = check_borders(snake_head[1], dimensions[:height])
+ obstacle_ahead = is_inside(obstacle_ahead_width, obstacle_ahead_height)
+ if snake.include?(snake_head) then obstacle_ahead = true end
obstacle_ahead
end
-def danger?(snake, direction, dimensions)
- arr = [(snake.last[0] + direction[0] * 2), (snake.last[1] + direction[1] * 2)]
+def is_inside(obstacle_ahead_width, obstacle_ahead_height)
obstacle_ahead = false
- if arr[0] < 0 or arr[0] >= dimensions[:width] then obstacle_ahead = true end
- if arr[1] < 0 and arr[0] >= dimensions[:height] then obstacle_ahead = true end
- if snake.include?(arr) then obstacle_ahead = true end
+ if (obstacle_ahead_width or obstacle_ahead_height)
+ obstacle_ahead = true
+ end
obstacle_ahead
end
+def check_borders(snake_head_coordinates, max_dimension)
+ if snake_head_coordinates < 0
+ outside = true
+ elsif snake_head_coordinates >= max_dimension
+ outside = true
+ else
+ outside = false
+ end
+end
+
+def danger?(snake, direction, dimensions)
+ if obstacle_ahead?(snake, direction, dimensions)
+ danger = true
+ elsif obstacle_ahead?(move(snake, direction), direction, dimensions)
+ danger = true
+ else
+ danger = false
+ end
+end
+
def new_food(snake, dimensions)
random = Random.new
part = [random.rand(dimensions[:width]), random.rand(dimensions[:height])]
while snake.include?(part) do
part = [random.rand(dimensions[:width]), random.rand(dimensions[:height])]
end
part
end
def move(snake, direction)
- reorder(snake)
- snake.last[0] += direction[0]
- snake.last[1] += direction[1]
- Array.new(snake)
+ if snake.size > 1 then snake.delete_at(0) end
+ snake_head = snake.last.dup
+ snake_head[0] += direction[0]
+ snake_head[1] += direction[1]
+ snake.push(snake_head.dup)
+ snake.dup
end
-def reorder(snake)
- for index in 0..(snake.size-2)
- snake[index][0] = snake[index+1][0]
- snake[index][1] = snake[index+1][1]
- end
-end
-
def grow(snake, direction)
- snake_last_part = Array.new(snake[0])
- reorder(snake)
- snake.unshift(snake_last_part)
- snake.last[0] += direction[0]
- snake.last[1] += direction[1]
- Array.new(snake)
+ snake_end = snake.first
+ new_snake = move(snake, direction)
+ new_snake.unshift(snake_end)
+ new_snake
end