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

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

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

Резултати

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

Код

def move(snake, direction)
moved_snake = grow(snake, direction)
moved_snake.shift
moved_snake
end
def grow(snake, direction)
snake + [(snake.last.zip(direction)).map { |x| x.reduce(:+) }]
end
def obstacle_ahead?(snake, direction, dimensions)
next_position = (snake.last.zip(direction)).map { |x| x.reduce(:+) }
wall_ahead?(next_position, dimensions) or snake.include?(next_position)
end
def wall_ahead?(next_position, dimensions)
next_position.all? { |x| x < 0 } or
next_position.first >= dimensions[:width] or
next_position.last >= dimensions[:height]
end
def danger?(snake, direction, dimensions)
obstacle_ahead?(snake, direction, dimensions) or
obstacle_ahead(grow(snake, direction), direction, dimensions)
end
def new_food(food, snake, dimensions)
invalid_points = food + snake
new_food_coordinates = [Random.rand(0...dimensions[:width]),
Random.rand(0...dimensions[:height])]
unless valid_food_position?(new_food_coordinates, invalid_points, dimensions)
new_food_coordinates = new_food(food, snake, dimensions)
end
new_food_coordinates
end
def valid_food_position?(new_food_coordinates, invalid_points, dimensions)
not invalid_points.include?(new_food_coordinates) and
point_on_field(new_food_coordinates, dimensions)
end
def point_on_field(point, dimensions)
point.all? { |x| x >= 0 } and point.first < dimensions[:width] and
point.last < dimensions[:height]
end

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

.................FFF

Failures:

  1) #danger? returns true if obstacle in two turns
     Failure/Error: expect(danger?([[6, 6], [7, 6], [8, 6]], [1, 0], dimensions)).to eq true
     NoMethodError:
       undefined method `obstacle_ahead' for #<RSpec::Core::ExampleGroup::Nested_5:0x007f6a943c4e38>
     # /tmp/d20151026-15631-1x1acvw/solution.rb:24:in `danger?'
     # /tmp/d20151026-15631-1x1acvw/spec.rb:113: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) #danger? returns false if obstacle in three turns
     Failure/Error: expect(danger?([[5, 6], [6, 6], [7, 6]], [1, 0], dimensions)).to eq false
     NoMethodError:
       undefined method `obstacle_ahead' for #<RSpec::Core::ExampleGroup::Nested_5:0x007f6a943c2098>
     # /tmp/d20151026-15631-1x1acvw/solution.rb:24:in `danger?'
     # /tmp/d20151026-15631-1x1acvw/spec.rb:117: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) #danger? does not mutate the given arguments
     Failure/Error: expect { danger?(snake, direction, dimensions) }.not_to change { snake }
     NoMethodError:
       undefined method `obstacle_ahead' for #<RSpec::Core::ExampleGroup::Nested_5:0x007f6a943b2558>
     # /tmp/d20151026-15631-1x1acvw/solution.rb:24:in `danger?'
     # /tmp/d20151026-15631-1x1acvw/spec.rb:123:in `block (3 levels) in <top (required)>'
     # /tmp/d20151026-15631-1x1acvw/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.01467 seconds
20 examples, 3 failures

Failed examples:

rspec /tmp/d20151026-15631-1x1acvw/spec.rb:112 # #danger? returns true if obstacle in two turns
rspec /tmp/d20151026-15631-1x1acvw/spec.rb:116 # #danger? returns false if obstacle in three turns
rspec /tmp/d20151026-15631-1x1acvw/spec.rb:120 # #danger? does not mutate the given arguments

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

Николай обнови решението на 14.10.2015 23:59 (преди над 9 години)

+def sum_arrays(array_a, array_b)
+ result_array = []
+ array_a.each_with_index do |element, index|
+ result_array[index] = element + array_b[index]
+ end
+ result_array
+end
+
+def move(snake, direction)
+ moved_snake = grow(snake, direction)
+ moved_snake.shift
+ moved_snake
+end
+
+def grow(snake, direction)
+ grown_snake = snake.clone
+ grown_snake << sum_arrays(grown_snake.last, direction)
+end
+
+def obstacle_ahead?(snake, direction, dimensions)
+ next_position = sum_arrays(snake.last, direction)
+ wall_ahead?(next_position, dimensions) or snake.include?(next_position)
+end
+
+def wall_ahead?(next_position, dimensions)
+ next_position.all? { |x| x < 0 } or
+ next_position.first >= dimensions[:width] or
+ next_position.last >= dimensions[:height]
+end
+
+def danger?(snake, direction, dimensions)
+ obstacle_ahead?(snake, direction, dimensions) or
+ obstacle_ahead(grow(snake, direction), direction, dimensions)
+end
+
+def new_food(food, snake, dimensions)
+ invalid_points = food + snake
+ new_food_coordinates = [Random.rand(0...dimensions[:width]),
+ Random.rand(0...dimensions[:height])]
+ unless valid_food_position?(new_food_coordinates, invalid_points, dimensions)
+ new_food_coordinates = new_food(food, snake, dimensions)
+ end
+ new_food_coordinates
+end
+
+def valid_food_position?(new_food_coordinates, invalid_points, dimensions)
+ not invalid_points.include?(new_food_coordinates) and
+ point_on_field(new_food_coordinates, dimensions)
+end
+
+def point_on_field(point, dimensions)
+ point.all? { |x| x >= 0 } and point.first < dimensions[:width] and
+ point.last < dimensions[:height]
+end

Надявам се възможно най-скоро да имам възможността да рефакторирам части от кода. Също така изцяло ще пренапиша new_food, но докато проверявах, дали skeptic ще измрънка за нещо подобно, забелязах че това минава и реших да го споделя с вас.

Всъщност ок решение, има няколко забележки поне: sum_arrays, може да ползваш по-елегантен метод от each_with_index и пълнене на масив, ако искаш да ти описва n-мерен случай(макар че тук е достатъчно просто да събереш двата координата, понякога по-ясното решение е по-добро).

Това събиране на масиви го правиш в точно определен случай, за да получиш една и съща информация. Замисли се коя е тя и изнеси направо нея в helper.

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

-def sum_arrays(array_a, array_b)
- result_array = []
- array_a.each_with_index do |element, index|
- result_array[index] = element + array_b[index]
- end
- result_array
-end
-
def move(snake, direction)
moved_snake = grow(snake, direction)
moved_snake.shift
moved_snake
end
def grow(snake, direction)
- grown_snake = snake.clone
- grown_snake << sum_arrays(grown_snake.last, direction)
+ snake + [(snake.last.zip(direction)).map { |x| x.reduce(:+) }]
end
def obstacle_ahead?(snake, direction, dimensions)
- next_position = sum_arrays(snake.last, direction)
+ next_position = (snake.last.zip(direction)).map { |x| x.reduce(:+) }
wall_ahead?(next_position, dimensions) or snake.include?(next_position)
end
def wall_ahead?(next_position, dimensions)
next_position.all? { |x| x < 0 } or
next_position.first >= dimensions[:width] or
next_position.last >= dimensions[:height]
end
def danger?(snake, direction, dimensions)
obstacle_ahead?(snake, direction, dimensions) or
obstacle_ahead(grow(snake, direction), direction, dimensions)
end
def new_food(food, snake, dimensions)
invalid_points = food + snake
new_food_coordinates = [Random.rand(0...dimensions[:width]),
Random.rand(0...dimensions[:height])]
unless valid_food_position?(new_food_coordinates, invalid_points, dimensions)
new_food_coordinates = new_food(food, snake, dimensions)
end
new_food_coordinates
end
def valid_food_position?(new_food_coordinates, invalid_points, dimensions)
not invalid_points.include?(new_food_coordinates) and
point_on_field(new_food_coordinates, dimensions)
end
def point_on_field(point, dimensions)
point.all? { |x| x >= 0 } and point.first < dimensions[:width] and
point.last < dimensions[:height]
end