Microwave
Ruby
Solution 1
This solution involves some string surgery. It works but there is probably a more mathy and elegant (and probably shorter) approach we can try.
Microwave = Class.new do
def initialize(seconds)
@seconds = seconds
end
##
# Convert an input in seconds to a timer display hh:mm.
#
# @return [String]
#
def timer
secs = @seconds.to_s
if secs.size <= 2
hours, seconds = @seconds.divmod(60)
return pad(hours) << ':' << pad(seconds)
else
overflow_hours, remaining_seconds = seconds(secs).divmod(60)
pad(hours(secs) + overflow_hours) << ':' << pad(remaining_seconds)
end
end
private
##
# Get the seconds of a three-or-more-digit string.
#
# @param secs [String]
# @return [Integer]
#
def seconds(secs)
#
# This range returns the last two digits of the digit string,
# which are the seconds. For example, in '257', 2 is the hour,
# and 57 is the seconds.
#
secs[-2 .. -1].to_i
end
##
# Get the hours from a three-or-more-digit string.
#
def hours(secs)
hours_len = secs.size - 2
##
# If we have seconds like '257', and 57 is the seconds, then we
# have a range from 0...1, which returns 2. Since 257 has three
# digits, 3 - 2 is 1, which we use in the range.
#
# If we have seconds like '1001', then the seconds is 01 and the
# hours is the range from 0...2, which will return 10. Since
# 1001 has four digits, 4 - 2 is 2, which we use in the range.
#
secs[0...hours_len].to_i
end
##
# Pad n with 0 to make sure it is always a two digit string.
#
# Simply return the number as string if no padding needed.
#
# @param n [Integer]
# @return [String]
#
def pad(n)
s = n.to_s
s.size < 2 ? '0' << s : s
end
end
Solution 2
The first solution used modular division for the seconds, but the idea can be extended so it also satisfy cases where the input is something like 272.
272.divmod(10)
results in 2, 72
.
So we have 2 hours and 72 seconds.
We can then get those 72 seconds and do modular division in base 60.
72.divmod(60)
results in 1, 12
, which means 72 seconds is actually 1 hour and 12 seconds.
We then simply add the 2 hours from the first modular division by 100 to the 1 hour we got from the modular division by 60. It in the end, it gives us 3 hours and 12 seconds.
The same approach works with other inputs like 7, 93, 272, or 1001. Let’s see some IRB session examples.
>> tmp_hours, tmp_seconds = 7.divmod(100)
=> [0, 7]
# 7
>> overflow_hours, remaining_seconds = tmp_seconds.divmod(60)
=> [0, 7]
# 0 0 7
>> '%02d:%02d' % [tmp_hours + overflow_hours, remaining_seconds]
=> "00:07"
Both tmp_hours
and overflow_hours
are 0, and 0 + 0 is still 0.
The remaining seconds is still 7, and the resulting string is "00:07", which is 100% the expected result!
>> tmp_hours, tmp_seconds = 93.divmod(100)
=> [0, 93]
# 93
>> overflow_hours, remaining_seconds = tmp_seconds.divmod(60)
=> [1, 33]
# 0 + 1 , 33
>> '%02d:%02d' % [tmp_hours + overflow_hours, remaining_seconds]
=> "01:33"
>> tmp_hours, tmp_seconds = 272.divmod(100)
=> [2, 72]
# 72
>> overflow_hours, remaining_seconds = tmp_seconds.divmod(60)
=> [1, 12]
# 2 + 1 , 12
>> '%02d:%02d' % [tmp_hours + overflow_hours, remaining_seconds]
=> "03:12"
>> tmp_hours, tmp_seconds = 1001.divmod(100)
=> [10, 1]
# 1
>> overflow_hours, remaining_seconds = tmp_seconds.divmod(60)
=> [0, 1]
# 10 + 0 , 1
>> '%02d:%02d' % [tmp_hours + overflow_hours, remaining_seconds]
=> "10:01"