Program my microwave oven

12

2

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 +++++++++)

Ben Jackson

Posted 2012-10-24T00:24:50.533

Reputation: 332

Question was closed 2017-01-12T17:35:04.843

6will the answers be verified with your dinner? – ardnew – 2012-10-24T00:52:11.997

1also which takes precedence: 400S or ++++ ? – ardnew – 2012-10-24T01:54:14.267

1@ardnew: I guess tiebreak should be minimum finger movement, thus ++++ wins. :) – Ben Jackson – 2012-10-24T02:03:35.860

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. – ardnew – 2012-10-24T02:10:31.960

Could your second example of 61S also be 1S+? – Matt – 2012-10-24T17:50:42.067

The result for 10:39 is 999S? It is shorter then 1039S. Or breaks the microwave with this entry? – knut – 2012-10-24T21:20:02.003

4If 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) – Johno – 2012-10-26T09:36:53.700

Answers

3

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
∇

marinus

Posted 2012-10-24T00:24:50.533

Reputation: 30 224

@BenJackson Challenges require an objective winning criterion. See the description of the [code-challenge] tag you used. – mbomb007 – 2017-01-12T17:04:23.490

I didn't specify a winning criteria, so I will retroactively choose the one that teaches me the most about APL. – Ben Jackson – 2014-05-20T21:45:16.863

4

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'

undefined

Posted 2012-10-24T00:24:50.533

Reputation: 141

3

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

ardnew

Posted 2012-10-24T00:24:50.533

Reputation: 2 177

1

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)

knut

Posted 2012-10-24T00:24:50.533

Reputation: 269