I am attempting to answer a challenge question about coordinates within 100ms response time. I am given the following values through STDIN
and am told to respond with a direction ("NE"
, "W"
, etc).
@light_x, @light_y, @initial_tx, @initial_ty = gets.split(" ").collect {|x| x.to_i}
I am trying to figure out why this attempt times out:
print @light_y > @initial_ty ? "S" : "N" unless @light_y == @initial_ty
print @light_x > @initial_tx ? "E" : "W" unless @light_x == @initial_tx
while this attempt does not:
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
Is there any way to speed up my ternary, or am I going about this the wrong way?
I think the primary issue isn't speed, it's clarity of the logic. I'd rewrite these:
print @light_y > @initial_ty ? "S" : "N" unless @light_y == @initial_ty
print @light_x > @initial_tx ? "E" : "W" unless @light_x == @initial_tx
to:
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
A ternary statement is only appropriate when there are two possible conditions, typically the result of a true/false condition or test result. You've got three conditions: <
, >
and ==
and you only want to output for the first two, resulting in logic that doesn't flow and is confusing.
Similarly, I think you can reduce this:
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
to:
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
That's all untested, but it looks about right.
The changes to the code should run faster because the code is reduced to fewer tests. It's also easier to understand, which your future self will appreciate.
Finally:
gets.split(" ")
can be written as:
gets.split
since the default behavior is to split on whitespace.