13
\$\begingroup\$

I'm very lazy so I try to always program my microwave with the fewest possible button presses. My microwave has the following buttons:

  • A "minute plus" button which may only be pressed first and implies "start". It may be pressed multiple times for multiple minutes, but it will not add a minute to a manually entered time. Output +
  • A set of 0-9 buttons. Time entry is MMSS (i.e. "130" means 1 minute 30 seconds). Seconds may range from 0..99. So "130" and "90" are equivalent entries. Obviously each minute is 60 seconds even if the seconds part of the entry exceeds 59. Output 0..9
  • A "start" button which must be pressed to start the microwave if the time is entered manually. Output S

My food packages specify time in MM:SS and so the program must accept that input.

Examples

  • 1:00 is + (remember "minute plus" implies start)
  • 1:01 is 61S (seconds can exceed 59, but "minute plus" does not work in conjunction with digits -- I think this is a design flaw in my microwave)
  • 9:00 is 900S (shorter than +++++++++)
\$\endgroup\$
7
  • 7
    \$\begingroup\$ will the answers be verified with your dinner? \$\endgroup\$
    – ardnew
    Commented Oct 24, 2012 at 0:52
  • 1
    \$\begingroup\$ also which takes precedence: 400S or ++++ ? \$\endgroup\$
    – ardnew
    Commented Oct 24, 2012 at 1:54
  • 1
    \$\begingroup\$ @ardnew: I guess tiebreak should be minimum finger movement, thus ++++ wins. :) \$\endgroup\$ Commented Oct 24, 2012 at 2:03
  • \$\begingroup\$ finger movement? so is 888S shorter than 928S, but 900S shorter than 860S ? i'm gonna need precise geometry of your buttons and each of their positions. \$\endgroup\$
    – ardnew
    Commented Oct 24, 2012 at 2:10
  • 4
    \$\begingroup\$ If I had to microwave my "Pedant's Meal for One" for 1:59, I would press ++ (wait for 1:59) and then press "cancel" one second before the end. Three button presses, assuming you have a "cancel" button and consider standing staring at the timer to be a cheap process. Maybe you could consider this option for subsequent meals! (Or for a subsequent challenge) \$\endgroup\$
    – Johno
    Commented Oct 26, 2012 at 9:36

4 Answers 4

4
\$\begingroup\$

JavaScript

var x = /(\d+):(\d\d)/.exec('<time here>');
x[1] === '0' ? +x[2] + 'S' :
x[1] < 4 && x[2] === '00' ? (
    x[1] === '1' ? '+' :
    x[1] === '2' ? '++' : '+++') :
x[2] < 40 ?
    (x[1] - 1 ? x[1] - 1 : '') + '' + (6 + +x[2][0]) + x[2][1] + 'S' :
x[1] + x[2] + 'S'
\$\endgroup\$
3
\$\begingroup\$

APL

APL has a bad reputation that it's unreadable, which is totally not the case if it's not golfed.

The rules:

  • Whole minutes <= 4 get +, ++, +++, and ++++
  • 960-999 is preferred above 1000-1039. 9960-9999 is preferred above 10000-10039, etc.
  • If the time can be rewritten such that the seconds are 66, 77, 88, or 99 then this is done. (This never gives a worse solution and usually gives a better one, i.e. 888 instead of 928.)
∇ Microwave;time;secs;mins;fmt;⎕ML

 ⎕ML←3

 ⎕←'Enter the time (m+:ss)'
 time←⍞
 mins secs←⍎¨(time≠':')⊂time

⍝ 'minute plus' can only be used on whole minutes ≤ 4
 :If (secs=0)∧(mins≤4)
     ⎕←mins⍴'+'
     :Return
 :EndIf
⍝ If possible, save a keypress by using seconds > 60
⍝ if mins is a power of ten
 :If (mins>0)
     :If ((⌈10⍟mins)=(⌊10⍟mins))∧(secs<40)
         ⎕←('BI2'⎕FMT mins-1),(⎕FMT secs+60),'S'
         :Return
     :EndIf
 :EndIf
⍝ For the 'finger movement' requirement we want as many
⍝ of the keypresses as possible to be of the same key.
⍝ So 888S i.p.v. 928S.
 :If secs∊66 77 88 99-60
     ⎕←('BI2'⎕FMT mins-1),(⎕FMT secs+60),'S'
     :Return
 :EndIf
⍝ Otherwise, just output mmssS, there was no better alternative.
 :If mins>0
    ⍝ output seconds with leading zero
     ⎕←('BI2'⎕FMT mins),('G⊂99⊃'⎕FMT secs),'S'
 :Else
    ⍝ only output seconds, not with leading zero
     ⎕←('BI2'⎕FMT secs),'S'
 :EndIf
∇
\$\endgroup\$
2
  • \$\begingroup\$ I didn't specify a winning criteria, so I will retroactively choose the one that teaches me the most about APL. \$\endgroup\$ Commented May 20, 2014 at 21:45
  • \$\begingroup\$ @BenJackson Challenges require an objective winning criterion. See the description of the [code-challenge] tag you used. \$\endgroup\$
    – mbomb007
    Commented Jan 12, 2017 at 17:04
3
\$\begingroup\$

Perl

meets the requirements, but it isn't how I would enter the buttons (e.g. "860S" vs "900S") handles exactly 60 seconds as a special case

use strict;
use warnings;

sub cook
{
  my ($mins, $secs) = @_;

  my $plus = $secs =~ /00/ ? $mins : undef;

  my $secs_total = $mins * 60 + $secs;
  my $mins_total = 0;

  while ($secs_total > 99)
  {
    ++$mins_total;
    $secs_total -= 60;
  }

  $plus = "+" x $plus if defined $plus;

  my $nums = "";
  my $even = ($mins_total > 0 and $secs_total == 60);

  $secs_total *= not $even;
  $mins_total += $even;

  if ($mins_total > 0)
  {
    $nums = sprintf "%s%02dS", $mins_total, $secs_total;
  }
  else
  {
    $nums = sprintf "%2dS", $secs_total;
  }

  return ($nums, $plus)
    [defined $plus and length $plus < length $nums];
}

die "usage:$/\tperl $0 <MINUTES>:<SECONDS>$/"
  unless @ARGV > 0 and shift =~ /([0-9]{1,2}):([0-9]{1,2})/;

print cook($1, $2), $/;

Output

andrew@gidget:~$ perl mic.pl 9:00
900S
andrew@gidget:~$ perl mic.pl 1:00
+
andrew@gidget:~$ perl mic.pl 1:01
61S
andrew@gidget:~$ perl mic.pl 1:30
90S
andrew@gidget:~$ perl mic.pl 0:07
 7S
andrew@gidget:~$ perl mic.pl 4:00
400S
\$\endgroup\$
1
\$\begingroup\$

ruby

#Build a string for the microwave
def build_result(minutes, seconds)
  duration = minutes * 60 + seconds  
  if duration < 99
    result = "%iS" % [ duration]    #shortcut '90S' instead '130S'
  else
    result = "%i%02iS" % [ minutes, seconds]
  end  
  result
end

#Call microwave optimizer
def microwave( input )
  minutes  = input.split(/:/).first.to_i 
  seconds = input.split(/:/).last.to_i

  #build result
  result = build_result(minutes, seconds)
  #try a shorter result, make 999S out of '10:39':
  if seconds < 40 and minutes > 0
    result2 = build_result(minutes - 1, seconds + 60)   #try a 
    result = ( result.size <= result2.size ? result : result2 )
  end

  #Check if a version with only '+' is shorter
  if seconds == 0 and minutes <= result.size
    result = '+' * minutes
  end
  result
end

#Test if called with an argument
if ARGV.empty?
  require 'test/unit'   #Exceute a test
  class MicrowaveTest < Test::Unit::TestCase
    def test_007
      assert_equal('7S', microwave('0:07'))
    end  
    def test_100
      assert_equal('+', microwave('1:00'))
    end
    def test_101
      assert_equal('61S', microwave('1:01'))
    end  
    def test_130
      assert_equal('90S', microwave('1:30'))
    end  
    def test_400
      #~ assert_equal('400S', microwave('4:00'))
      assert_equal('++++', microwave('4:00'))
    end  
    def test_500
      assert_equal('500S', microwave('5:00'))
    end  
    def test_900
      assert_equal('900S', microwave('9:00'))
    end 
    def test_1000
      #~ assert_equal('1000S', microwave('10:00'))
      assert_equal('960S', microwave('10:00'))
    end 
    def test_1015
      #~ assert_equal('1015S', microwave('10:15'))
      assert_equal('975S', microwave('10:15'))
    end 
    def test_1039
      #~ assert_equal('1039S', microwave('10:39'))
      assert_equal('999S', microwave('10:39'))
    end 
  end
else  #started via shell, evaluate input
  puts microwave(ARGV.first)
end

Remarks:

  • Start it with ruby program-my-microwave-oven.rb and a unit test is evaluated.
  • Start it with ruby program-my-microwave-oven.rb 10:00 and it writes 960S

Some remarks on the rules (and my interpretation):

  • The shortest for 10:00 is 960S (9 minutes and 60 seconds -> 10 minutes).
  • The shortest for 10:39 is 999S (9 minutes and 99 seconds -> 10 minutes and 39 seconds).
  • for 4:00 it prefers ++++ (less finger movements)
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.