2016-06-13 9 views
-1

Я пытаюсь ответить на непростой вопрос о координатах в течение времени отклика 100 мс. Я получил следующие значения через STDIN, и мне сказали ответить направлением ("NE", "W" и т. Д.).Как я могу ускорить работу с помощью тернарного оператора?

@light_x, @light_y, @initial_tx, @initial_ty = gets.split(" ").collect {|x| x.to_i} 

Я пытаюсь понять, почему эта попытка таймаут:

print @light_y > @initial_ty ? "S" : "N" unless @light_y == @initial_ty 
print @light_x > @initial_tx ? "E" : "W" unless @light_x == @initial_tx 

в то время как эта попытка не будет:

if @light_x > @initial_tx && @light_y > @initial_ty 
    puts "SE" 
elsif @light_x < @initial_tx && @light_y > @initial_ty 
    puts "SW" 
elsif @light_x > @initial_tx && @light_y < @initial_ty 
    puts "NE" 
elsif @light_x < @initial_tx && @light_y < @initial_ty 
    puts "NW" 
elsif @light_x < @initial_tx && @light_y == @initial_ty 
    puts "W" 
elsif @light_x > @initial_tx && @light_y == @initial_ty 
    puts "E" 
elsif @light_y > @initial_ty && @light_x == @initial_tx 
    puts "S" 
elsif @light_y < @initial_ty && @light_x == @initial_tx 
    puts "N" 
else 
end 

Есть ли способ, чтобы ускорить мой тройного или я иду об этом неправильно?

+0

Это потому, что вы используете печать вместо того, чтобы помещать первый блок кода. Наслаждайтесь codeingame.com? – rwilliams

+0

Вы могли бы разместить образец ввода? Я подозреваю, что это из-за ключевых слов, кроме ключевых слов. Не уверен, хотя – oreoluwa

+2

Вы оценили, какая часть вашего кода на самом деле слишком медленная? 'split',' collect', условные обозначения или вывод? – spickermann

ответ

1

Я думаю, что основной проблемой является не скорость, это ясность логики. Я бы переписать эти:

print @light_y > @initial_ty ? "S" : "N" unless @light_y == @initial_ty 
print @light_x > @initial_tx ? "E" : "W" unless @light_x == @initial_tx 

к:

if @light_y > @initial_ty 
    print 'S' 
elsif @light_y < @initial_ty 
    print 'N' 
end 

if @light_x > @initial_tx 
    print 'E' 
elsif @light_x < @initial_tx 
    print 'W' 
end 

Тройная утверждение только уместно, когда существуют два возможных состояния, как правило, является результатом истинного/ложного состояния или результата теста. У вас есть три условия: <, > и ==, и вы хотите только вывести данные для первых двух, в результате чего логика не течет и запутывается.

Точно так же, я думаю, что вы можете уменьшить это:

if @light_x > @initial_tx && @light_y > @initial_ty 
    puts "SE" 
elsif @light_x < @initial_tx && @light_y > @initial_ty 
    puts "SW" 
elsif @light_x > @initial_tx && @light_y < @initial_ty 
    puts "NE" 
elsif @light_x < @initial_tx && @light_y < @initial_ty 
    puts "NW" 
elsif @light_x < @initial_tx && @light_y == @initial_ty 
    puts "W" 
elsif @light_x > @initial_tx && @light_y == @initial_ty 
    puts "E" 
elsif @light_y > @initial_ty && @light_x == @initial_tx 
    puts "S" 
elsif @light_y < @initial_ty && @light_x == @initial_tx 
    puts "N" 
else 
end 

к:

y_direction = if @light_y > @initial_ty 
       'S' 
       elsif @light_y < @initial_ty 
       'N' 
       else 
       '' 
       end 

x_direction = if @light_x > @initial_tx 
       'E' 
       elsif @light_x < @initial_tx 
       'W' 
       else 
       '' 
       end 

puts y_direction + x_direction    

Это все проверялось, но это выглядит примерно правильно.

Изменения в коде должны работать быстрее, потому что код сводится к меньшему количеству тестов. Это также легче понять, что будет ценить ваше будущее.

Наконец:

gets.split(" ") 

можно записать в виде:

gets.split 

поскольку поведение по умолчанию разделить на пробелы.

+1

Хорошая идея отделить два направления. Для удовольствия вы можете написать 'y_direction = ['', 'S', 'N'] [@ light_y <=> @initial_ty]'. –

+0

Да, но это нужно документировать, потому что поведение не интуитивно. 'y_direction = ['N', '', 'S'] [(@ light_y <=> @initial_ty) + 1]' будет почти таким же быстрым и немного интуитивным, но все равно потребуется секунда для разработки и может привести к введению дополнительных ошибок. –

0

Использование puts вместо print здесь

print @light_y > @initial_ty ? "S" : "N" unless @light_y == @initial_ty 
print @light_x > @initial_tx ? "E" : "W" unless @light_x == @initial_tx 
+0

Это то, что я изначально считал проблемой, но выход должен быть в одной строке. Вот почему я изначально решил использовать печать. ПРИМЕЧАНИЕ: puts не работает из-за проблемы с sameline. –

1

Возможно, было бы проще использовать операторы case, а не if/elsif/else/end, и вернуть направление, которое будет напечатано вне метода. Как правило, часто лучше печатать возвращаемые значения методов, а не печатать внутри метода, поскольку это делает метод более универсальным.

Эта реализация использует сравнение <=> (например,, Fixnum#<=>, String#<=>, Array#<=> и т. Д., В зависимости от класса, к которому относятся аргументы direction.

def direction(light_x, light_y, init_tx, init_ty) 
    case light_x <=> init_tx 
    when -1 # light_x < init_tx 
    case light_y <=> init_ty 
    when -1 then "NW" 
    when 0 then "W" 
    when 1 then "SW" 
    end 
    when 0 # light_x = init_tx 
    case light_y <=> init_ty 
    when -1 then "N" 
    when 1 then "S" 
    end 
    when 1 # light_x > init_tx 
    case light_y <=> init_ty 
    when -1 then "NE" 
    when 0 then "E" 
    when 1 then "SE" 
    end 
    end 
end 

puts direction(3,2,1,1) 
# SE 
puts direction(1,2,1,1) 
# S 
puts direction(1,2,3,4) 
# NW 

Другой вариант - использовать хэш.

h = { [-1,-1]=>"NW", [-1,0]=>"W", [-1,1]=>"SW", 
     [ 0,-1]=>"N", [ 0,1]=>"S", 
     [ 1,-1]=>"NE", [ 1,0]=>"E", [ 1,1]=>"SE" } 

light_x, light_y, init_tx, init_ty = 3, 2, 1, 1 
puts h[[light_x<=>init_tx, light_y<=>init_ty]] 
# SE 
light_x, light_y, init_tx, init_ty = 1, 2, 1, 1 
puts h[[light_x<=>init_tx, light_y<=>init_ty]] 
# S 
light_x, light_y, init_tx, init_ty = 1, 2, 3, 4 
puts h[[light_x<=>init_tx, light_y<=>init_ty]] 
# NW