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.

example with input 7
>> 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!

example with input 93
>> 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"
example with input 272
>> 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"
example with input 1001
>> 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"