14
\$\begingroup\$

Following the theme of strange kitchen appliances, let's talk about my microwave.

Introduction

My microwave has a keypad that is laid out like this:

30  >  15
1   2   3
4   5   6
7   8   9
+/- 0 S/M
  • I can press the +/- and S/M keys to switch between adding and subtracting minutes or seconds.
  • The microwave starts in add minutes mode.
  • The 0-9 keys add or subtract 1-10 minutes/seconds to the time (0 adds 10.)
  • The 30 and 15 keys always add or subtract 30 or 15 seconds.
  • The > key starts the microwave.
  • The time cannot go below 0 seconds.

Example

If I pressed 0 3 +/- 15 S/M 4 > I would microwave my food for 12 minutes and 41 seconds:

  1. 0: Add 10 minutes
  2. 3: Add 3 minutes
  3. +/-: Switch to subtract mode
  4. 15: Subtract 15 seconds
  5. S/M: Switch to seconds
  6. 4: Subtract 4 seconds
  7. >: Start the microwave

Other test cases:

  • 0 3 +/- 15 S/M 4 S/M 1 S/M +/- 0 S/M 7 -/+ 30 > = 1101

The Challenge

Write me a program that takes as input a string of button presses (separator doesn't matter) and outputs how long my microwave will run for (in seconds). This is code-golf, so shortest code in bytes wins!

Button Codes

These are the button codes your program should accept: (I should be able to input exactly these strings):

  • 0 1 2 3 4 5 6 7 8 9 (0 equals 10)
  • 30
  • 15
  • +/-
  • S/M
  • >
\$\endgroup\$
12
  • 1
    \$\begingroup\$ @ovs Yes, you can take a list as input. Yes, there will always be a > at the end. \$\endgroup\$
    – Ginger
    Dec 6, 2021 at 14:18
  • 3
    \$\begingroup\$ The example 0 3 +/- 15 S/M 4 > should probably be 0 3 +/- S/M 15 4 > instead? Otherwise I end up with a negative time \$\endgroup\$
    – Stef
    Dec 6, 2021 at 16:08
  • 1
    \$\begingroup\$ @Stef You may have missed that part: The 30 and 15 keys always add or subtract 30 or 15 seconds \$\endgroup\$
    – Arnauld
    Dec 6, 2021 at 16:09
  • 1
    \$\begingroup\$ I think one extra test case in the challenge would be nice to assert that two and more mode toggles each of +/- and S/M works as expected. For example 0 3 +/- 15 S/M 4 S/M 1 S/M +/- 0 S/M 7 +/- 30 >1101. \$\endgroup\$
    – Kjetil S
    Dec 6, 2021 at 17:20
  • 1
    \$\begingroup\$ May i assume the output will always be positive, and the timer will not be negative in the middle of operating? For example, +/- 3 +/- 4 > will not happened. \$\endgroup\$
    – tsh
    Dec 7, 2021 at 5:15

10 Answers 10

5
\$\begingroup\$

PowerShell, 106 86 bytes

Big thanks to both @mazzy and @Julian for saving me an ENORMOUS 20 bytes!!!

$s=1
switch -r($args){\d{$t+=$s*(10*!+$_+$_)*(1+59*!$m*(9-ge$_))}-{$s=-$s}s{$m=!$m}}$t

Try it online!

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Nice one, I just removed a + Try it online! \$\endgroup\$
    – Julian
    Dec 7, 2021 at 2:16
  • 2
    \$\begingroup\$ And 106 bytes using |iex \$\endgroup\$
    – Julian
    Dec 7, 2021 at 3:50
  • 2
    \$\begingroup\$ Same + change \$\endgroup\$
    – Julian
    Dec 7, 2021 at 8:23
  • 2
    \$\begingroup\$ yes, of course! Thanks! -3 bytes more Try it online! \$\endgroup\$
    – mazzy
    Dec 7, 2021 at 9:01
  • 1
    \$\begingroup\$ Wow guys, you've really outdone yourself this time! \$\endgroup\$ Dec 7, 2021 at 13:08
4
\$\begingroup\$

Python 2, 112 109 bytes

Reads a list of instructions from STDIN. Prints duration in seconds.

t=0;d=1;r=60
for c in input()[:-1]:exec['k=int(c)or+10;t+=k*r**(k<11)*d','d=-d','r^=61'][hash(c)>>62]
print t

Try it online!

hash(c)>>62 maps all the numbers to 0, +/- to 1 and S/M to -1.

\$\endgroup\$
4
\$\begingroup\$

Batch, 192 bytes

@set/at=0,s=1,m=60
:l
@set/pb=
@if "%b%"==">" echo %t%&exit/b
@if %b%==+/- set/as=-s
@if %b%==S/M set/am=60/m
@if %b%==0 set b=10
@if %b% gtr 10 (set/at+=s*b)else set/at+=s*m*b
@goto l

Takes newline-terminated input on STDIN, as > is tricky to use on the command line. Explanation:

@set/at=0,s=1,m=60

Initialise the total and sign and minutes flags.

:l

Start a loop.

@set/pb=

Read in the next button.

@if "%b%"==">" echo %t%&exit/b

Output the total and finish if this is the > button.

@if %b%==+/- set/as=-s
@if %b%==S/M set/am=60/m

Update the flags for the +/- and S/M buttons.

@if %b%==0 set b=10

0 counts as 10.

@if %b% gtr 10 (set/at+=s*b)else set/at+=s*m*b
@goto l

Update the number of seconds and loop back. Note that non-numeric strings silently evaluate to 0, thus leaving the total undisturbed.

\$\endgroup\$
4
\$\begingroup\$

JavaScript (ES6), 68 bytes

Expects a list of commands. Returns a number of seconds. Assumes that the last command is >, as stated in the comments.

a=>a.map(c=>1/c?t+=s*(+c||10)*(c>9|a||60):c<','?s=-s:a^=1,t=0,s=1)|t

Try it online!

Commented

a =>               // a[] = input array, reused as a flag to figure out
                   //       if we are in 'seconds' mode
a.map(c =>         // for each command c in a[]:
  1 / c ?          //   if c is numerical:
    t +=           //     add to t:
      s *          //       the sign multiplied by
      (+c || 10) * //       either c, or 10 if c is 0
      (            //       multiplied by
        c > 9      //       1 if c is 15 or 30
        | a        //       or we are in seconds mode
        || 60      //       otherwise 60
      )            //
  :                //   else:
    c < ',' ?      //     if c is '+/-':
      s = -s       //       invert the sign
    :              //     else:
      a ^= 1,      //       switch between 'seconds' and 'minutes' mode
                   //       (c is either 'S/M' or '>')
  t = 0,           //   start with t = 0
  s = 1            //   start in 'add' mode
) | t              // end of map(); return t
\$\endgroup\$
3
  • \$\begingroup\$ 1 -/+ 1 -/+ 1 > should return 60 seconds I think. \$\endgroup\$
    – Kjetil S
    Dec 6, 2021 at 17:01
  • 1
    \$\begingroup\$ @KjetilS. It's +/-, not -/+. \$\endgroup\$
    – Arnauld
    Dec 6, 2021 at 17:14
  • \$\begingroup\$ I see now, my bad, 1 +/- 1 +/- 1 > works as expected. \$\endgroup\$
    – Kjetil S
    Dec 6, 2021 at 17:23
2
\$\begingroup\$

Charcoal, 53 51 bytes

≔⁶⁰η≔⁰ζWη«Sθ≡θ>≔⁰η+/-≦±ηS/M≦÷⁶⁰η≧⁺×∨Iθχ÷ηX↔η⊖Lθζ»Iζ

Try it online! Link is to verbose version of code. Takes input as either space or newline separated (but not both at the same time). Explanation:

≔⁶⁰η

Start in add minutes mode.

≔⁰ζ

Start with 0 seconds.

Wη«

Repeat until > has been processed.

Sθ≡θ

Input the next button and switch on it.

>≔⁰η

If this is the start button then clear the mode, allowing the loop to terminate. (If there are at least two button presses, then a byte could be saved by using a different termination condition.)

+/-≦±η

If this is the +/- button then flip between add and subtract mode.

S/M≦÷⁶⁰η

If this is the S/M button then flip between minutes and seconds mode. (I don't get to use much with binary operators. Both and work with unary operators but the deverbosifier always picks .)

≧⁺×∨Iθχ÷ηX↔η⊖Lθζ

Get the current value, change it to 10 if it is zero, multiply it by the mode, but if the value was greater than 10 then divide by the absolute value of the mode, so that the minute mode is ignored. Edit: Saved 2 bytes by porting this calculation from @tsh's Python answer.

»Iζ

Output the final number of seconds.

\$\endgroup\$
1
\$\begingroup\$

Perl 5 -apl, 81 bytes

$f=60;$S=0;$_||=10,/-/?$f=-$f:/S/?$f=60/$f:($S+=$_*$f/($_%15?1:abs$f))for@F;$_=$S

Try it online!

$f=60;            # starts in plus mode and minute mode (f=multiplying factor)
$S=0;             # reset output sum
$_||=10,          # convert 0 to 10 for current button in $_
/-/?$f=-$f:       # -/+ negates $f
/S/?$f=60/$f:     # S/M toggles $f between 1 and 60 or -1 and -60
($S+=$_*$f        # add button times $f (factor) to sum in $S
/($_%15?1:abs$f)) # force seconds as temporary unit if 15 or 30
for@F;            # for each button in input array @F (due to -a)
$_=$S             # print current sum in $S which is seconds to run
                  # (challenge just said "outputs how long" and I chose
                  # seconds as my unit of time).
\$\endgroup\$
1
\$\begingroup\$

Python 3, 112 bytes

c=60
t=0
for k in input().split():
	try:t+=c*int(k)/abs(c)**~-len(k)or 10*c
	except:c=(k>'0')*60/c or-c
print(t)

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 3, 178 bytes

l=eval(input());n=0;m=0;d=1;exec(";".join([['n+=15*d','d*=-1','m=1-m','n+=30*d',f"n+=(({x} or 10)*(60-59*m))*d"][[(sum(map(ord,x))%10)//3,4][len(x)<2]]for x in l[:-1]]));print(n)

Try it online!

longer than @ovs but should be more portable since it sums up the charcodes, mods by 10 and integer divides by 3 to distinct the inputs.

\$\endgroup\$
0
\$\begingroup\$

05AB1E, 33 bytes

ÎvyÐdigi0T.:¾È59*>*}X*+ë\нai¼ëX(U

Input as a list.

Try it online or verify all test cases.

Explanation:

Î                   # Push 0 and the input-list
 vy                 # Foreach over the items:
   Ð                #  Triplicate the current item
    di              #  Pop one, and if it's an integer:
      gi            #   Pop another, and if it's a single digit:
        0T.:        #    Replace the 0 with 10
            ¾       #    Push the counter_variable
                    #    (the counter_variable is 0 by default)
             È      #    Pop and check if it's is even (1 if even; 0 if not)
              59*   #    Multiply this by 59
                 >  #    Increase it by 1
                  * #    Multiply it to the current integer
       }            #   After the inner-most if-statement
        X*          #   Multiply the value by `X`
                    #   (`X` is 1 by default)
          +         #   And add it to the result
     ë              #  Else (it's not an integer):
      \             #   Discard one of the remaining copies
       н            #   Pop the last one, and push its first character
        ai          #   Pop, and if this is a letter:
          ¼         #    Increase the counter_variable by 1
         ë          #   Else (it's a '+' or '>' instead):
          X(U       #    Negate `X`, and store it as new `X`
\$\endgroup\$
0
\$\begingroup\$

JavaScript (Node.js), 68 bytes

f=A=>A.map(k=>1/k?t+=k>9?c%59*k:c*k||c*10:c=k>f?60/c:-c,c=60,t=0)&&t

Try it online!

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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