Решение на Втора задача от Александрина Каракехайова

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

Към профила на Александрина Каракехайова

Резултати

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

Код

def move(snake, direction)
new_snake = Array.new(snake)
new_snake.delete_at(0)
length = new_snake.length
new_snake[length] = next_position(new_snake, direction)
new_snake
end
def next_position(snake, direction)
[snake.last, direction].transpose.map { |x| x.reduce :+ }
end
def grow(snake, direction)
new_snake = Array.new(snake)
length = new_snake.length
new_snake[length] = next_position(new_snake, direction)
new_snake
end
def new_food(food, snake, dimensions)
generated_food = [rand(dimensions[:width]), rand(dimensions[:height])]
part_of_the_snake = snake.include? generated_food
already_exists = (food - generated_food).empty?
if !part_of_the_snake and !already_exists
generated_food
else new_food(food, snake, dimensions)
end
end
def obstacle_ahead?(snake, direction, dimensions)
move = next_position(snake, direction)
if snake.include? move or move[0] < 0 or move[1] < 0
true
elsif move[0] >= dimensions[:width] or move[1] >= dimensions[:height]
true
else false
end
end
def danger? (snake, direction, dimensions)
dead_after_one_move = obstacle_ahead?(snake, direction, dimensions)
new_snake = move(snake,direction)
dead_after_two_moves = obstacle_ahead?(new_snake, direction, dimensions)
dead_after_one_move or dead_after_two_moves
end

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

.F..................

Failures:

  1) #move moves one-position-sized snake
     Failure/Error: expect(move([[2, 2]], [-1, 0])).to eq([[1, 2]])
     TypeError:
       no implicit conversion of nil into Array
     # /tmp/d20151026-15631-rt52uy/solution.rb:10:in `transpose'
     # /tmp/d20151026-15631-rt52uy/solution.rb:10:in `next_position'
     # /tmp/d20151026-15631-rt52uy/solution.rb:5:in `move'
     # /tmp/d20151026-15631-rt52uy/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)>'

Finished in 0.01469 seconds
20 examples, 1 failure

Failed examples:

rspec /tmp/d20151026-15631-rt52uy/spec.rb:11 # #move moves one-position-sized snake

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

Александрина обнови решението на 16.10.2015 00:46 (преди над 9 години)

+def move(snake, direction)
+ new_snake = Array.new(snake)
+ new_snake.delete_at(0)
+ length = new_snake.length
+ movement = [new_snake[length-1], direction].transpose.map{|x| x.reduce :+}
+ new_snake[length] = movement
+ new_snake
+end
+
+def grow(snake, direction)
+ new_snake=Array.new(snake)
+ length=new_snake.length
+ growth=[new_snake[length-1], direction].transpose.map{|x| x.reduce :+}
+ new_snake[length]=growth
+ new_snake
+end
+
+def new_food(food, snake, dimensions)
+ generated_food = [rand(dimensions[:width]), rand(dimensions[:height])]
+ problem_one = snake.include? generated_food
+ problem_two = (food - generated_food).empty?
+ if(problem_one == false && problem_two == false)
+ generated_food
+ else new_food(food, snake, dimensions)
+ end
+end
+
+def obstacle_ahead?(snake, direction, dimensions)
+ length = snake.length
+ move = [snake[length-1], direction].transpose.map{|x| x.reduce :+}
+ if(snake.include? move || move[0] < 0 || move[1] < 0)
+ true
+ elsif (move[0] >= dimensions[:width] || move[1] >= dimensions[:height])
+ true
+ else false
+ end
+end
+
+def danger? (snake, direction, dimensions)
+ after_one = obstacle_ahead?(snake, direction, dimensions)
+ new_snake = move(snake,direction)
+ after_two = obstacle_ahead?(new_snake, direction, dimensions)
+ if(after_one == true || after_two == true)
+ true
+ else false
+ end
+end
  • Индентирай правилно, на тази задача ще отнемаме точки за това. Оставяй място около операторите (визирам =, -).

  • Не сравнявай неща в условието на if с true или false.

    Например 22-ри ред може да се запише така:

    if !problem_one and !problem_two 
    

    А 43-ти ред може да се запише така:

    if after_one or after_two
    

    Общо взето сравнявайки булев израз с true получаваш същия булев израз. Сравнявайки булев израз с false получаваш отрицанието на булевия израз.

    Другото е, че имаш разни места в кода (31-ви и 43-ти ред), където имаш if булев_израз и после връщаш true, ако булевия израз е true и false, ако булевия израз е false. Това е безсмислено. Връщай си стойността на булевия израз, която е true, ако той е true, или false, ако той е false.

    Например целия код от 43-ти до 45-ти ред може да се замени от единствения ред със следния булев израз:

    after_one or after_two
    
  • Нека направим този 43-ти ред още по-четим :) Змията е в danger?, ако after_one or after_two. Това не звучи много смислено. Ако преименуваме променливите, може да стане например така:

    def danger?(...)
      ...
      dead_after_one_move or dead_after_two_moves
    end
    

    Ахаа.. Сега вече разбирам какво се случва. Неоспоримо по-ясно е от:

    if(after_one == true || after_two == true)
      true
    else 
      false
    end
    

    Руби е един от езиците, които ти дават много свобода на изразяване, затова и го обичаме толкова. Възползвай се от възможностите му ! :blush:

    Като си говорим за имена... problem_one и problem_two не са ок. Нищо не ми казват... Можеш ли да измислиш по-добри ?

    Несъмнено имената са много важни. С тях много по-лесно се разбират намеренията на кода. В Руби това е залегнало дълбоко в езика. Някои методи от Array например дори си имат синоними, защото една дума звучи по-добре от друга в различен контекст. Използвай имената, които звучат добре. Например snake.last за достъпване на последен елемент, вместо да правиш snake[snake.length - 1]. Доста по-кратко и ясно е. Разгледай подробно документацията на Array, ще ти бъде супер полезно.

    Когато имаш някаква сложна конструкция (като тази на 5-ти, 13-ти, 30-ти ред), която на всичкото и отгоре се повтаря, може да я скриеш зад фунция с ясно име. Помисли какво точно прави въпросната конструкция. Дай ѝ име. Така всеки път някой друг като я погледне ще разбере какво се случва, вместо да трябва да интерпретира кода.

    Булевите изрази на 31-ви и на 33-ти ред също може да се именуват подобаващо. Успех !

Александрина обнови решението на 18.10.2015 14:18 (преди над 9 години)

def move(snake, direction)
new_snake = Array.new(snake)
new_snake.delete_at(0)
length = new_snake.length
- movement = [new_snake[length-1], direction].transpose.map{|x| x.reduce :+}
- new_snake[length] = movement
+ new_snake[length] = next_position(new_snake, direction)
new_snake
end
+def next_position(snake, direction)
+ [snake.last, direction].transpose.map { |x| x.reduce :+ }
+end
+
+
def grow(snake, direction)
- new_snake=Array.new(snake)
- length=new_snake.length
- growth=[new_snake[length-1], direction].transpose.map{|x| x.reduce :+}
- new_snake[length]=growth
+ new_snake = Array.new(snake)
+ length = new_snake.length
+ new_snake[length] = next_position(new_snake, direction)
new_snake
end
def new_food(food, snake, dimensions)
generated_food = [rand(dimensions[:width]), rand(dimensions[:height])]
- problem_one = snake.include? generated_food
- problem_two = (food - generated_food).empty?
- if(problem_one == false && problem_two == false)
+ part_of_the_snake = snake.include? generated_food
+ already_exists = (food - generated_food).empty?
+ if !part_of_the_snake and !already_exists
generated_food
else new_food(food, snake, dimensions)
end
end
def obstacle_ahead?(snake, direction, dimensions)
- length = snake.length
- move = [snake[length-1], direction].transpose.map{|x| x.reduce :+}
- if(snake.include? move || move[0] < 0 || move[1] < 0)
+ move = next_position(snake, direction)
+ if snake.include? move or move[0] < 0 or move[1] < 0
true
- elsif (move[0] >= dimensions[:width] || move[1] >= dimensions[:height])
- true
+ elsif move[0] >= dimensions[:width] or move[1] >= dimensions[:height]
+ true
else false
end
end
def danger? (snake, direction, dimensions)
- after_one = obstacle_ahead?(snake, direction, dimensions)
+ dead_after_one_move = obstacle_ahead?(snake, direction, dimensions)
new_snake = move(snake,direction)
- after_two = obstacle_ahead?(new_snake, direction, dimensions)
- if(after_one == true || after_two == true)
- true
- else false
- end
+ dead_after_two_moves = obstacle_ahead?(new_snake, direction, dimensions)
+ dead_after_one_move or dead_after_two_moves
end