My electric garage door works like this:

  • There is just one push button to control the door
  • If the door is fully closed and I hit the button, the door starts to open. It takes 10 seconds to open fully
  • If the door is fully open and I hit the button, the door starts to close. It takes 10 seconds to close fully
  • If the door is part way through opening or closing and I hit the button, then the door stops and is left partially open.
  • Whenever the door stops moving, either from automatic completion of an open or close action, or from manual interruption by pushing the button partway through an action, then the mechanism will reverse and remember its direction for the next action.
  • If the button is pushed when the door is stopped but partially open, then the amount of time for it to complete its action will be a fraction of 10 seconds in proportion to the amount it needs to move to complete the action.

Assume the door is fully closed at the start.

An input list of integers will be given. These integers are the number of seconds I wait between successive pushes of the control button.

Output two things:

  • a percentage indicating the state of the door once all button pushes are completed and the door has reached a steady state. Output of % symbol is optional.
  • an unambiguous indication of what direction the door will travel on the next button push. This may be up/down, U/D, +/-, 1/0 or whatever you choose.

You may assume the door takes infinitesimally less than 10 seconds to complete an open or close action.

Example inputs:

<empty list>  # button was pushed just once
20            # button was pushed twice with 20 seconds between
20 20
10 10
5 5
1 2 3
8 9 10 11
11 10 9 8 7

Expected outputs corresponding to above inputs

100% D
0% U
0% U
50% D
100% D
100% D
0% U
100% D
0% U
20% U

Worked example of the last test

  • Door starts off closed. Button is pushed
  • Wait 11 seconds. Door ends up fully opened. Button is pushed.
  • Wait 10 seconds. Door ends up fully closed. Button is pushed.
  • Wait 9 seconds. Button is pushed. Door stops at 90% open.
  • Wait 8 seconds. Button is pushed. Door starts to close.
  • Wait 7 seconds. Button is pushed. Door stops at 20% open. Next direction will be up.
  • \$\begingroup\$ You garage door stops at half-open, if you press the button, while closing? Mine doesn't, only for opening. \$\endgroup\$
    – Bálint
    May 9, 2016 at 19:13
  • \$\begingroup\$ @Bálint both way for mine. \$\endgroup\$ May 9, 2016 at 20:00
  • \$\begingroup\$ @Maltysen lets stick with percentage now. \$\endgroup\$ May 9, 2016 at 21:18
  • \$\begingroup\$ Is it okay if a floating point number is output if the input also consists of floating point number(s)? \$\endgroup\$
    – R. Kap
    May 11, 2016 at 21:35
  • \$\begingroup\$ @R.Kap yes, that's fine. \$\endgroup\$ May 11, 2016 at 21:36

6 Answers 6


Lua, 258 248 242 bytes

u,s,p=1>0,0>1,0;io.read():gsub("%d+",function(a)if(not s)then p=u and p+a or p-a;if(p>=10 or p<=0)then s,p=1>0,p>0 and 10 or 0;end;u,s=not u,not s else s=0>1;end end)if(not s)then p=u and 10 or 0;u=not u;end;print(10*p.."% "..(u and"U"or"D"))


u,s,p=true,false,0;                          -- Up direction, Stopped, Position
io.read():gsub("%d+",function(t)             -- For each number in input
    if(not s)then                            -- If door wasn't stopped
        p=u and p+t or p-t;                  -- Position = Moving up ? +t : -t
        if(p>=10 or p<=0)then                -- If door fully opened or closed
            s,p=true,p>0 and 10 or 0;        -- Then door stopped at 0 or 10
        u,s=not u,not s;                     -- Toggle direction and toggle stopped
        s=false;                             -- If stopped, nothing happened, un-stop.
-------------------- Done pressing the button --------------------
if(not s)then                                -- If left off moving
    p=u and 10 or 0;                         -- Finish movement
    u=not u;                                 -- Toggle direction
print(10*p.."% "..(u and"U"or"D"))           -- Output answer

I don't see how your test cases can be right...

20 20 -- Initial push, after 20, garage is at 100, push to start it down, after 20, garage is at 0, push to start it up, garage finishes up.
10 10 -- Same as above
1 2 3 -- 0 U Moving, wait 1, 1 D Stopped, wait 2, 0 U stopped, wait 3, 100 D stopped

OP Fixed

  • \$\begingroup\$ I've just finished my entry and I agree with your results too. \$\endgroup\$
    – Neil
    May 10, 2016 at 0:15

Pyth, 50 45 39 bytes

6 bytes thanks to Sp3000.


Test suite.


JavaScript (ES6), 109 106 bytes

a=>a.map(e=>(s^=1)?(r-=e*(d=-d))>9?(s=0,r=10):r<1?(r=s=0):r:r,r=s=0,d=1)&&(s?r:5*++d)*10+(d-s?"% D":"% U")
  • \$\begingroup\$ @DigitalTrauma Must have been an optimisation error. I've reoptimised it and somehow managed to save 3 further bytes this time! \$\endgroup\$
    – Neil
    May 11, 2016 at 23:06

Ruby, 152 bytes

->v{u,s,a=!!1,!0,0;v.map{|w|!s ?(a=u ? a+w : a-w;a>=10 ?(s,a=!!1,10):a<=0 ?(s,a=!!1,0):0;u,s=!u,!s):s=!0};!s ?(a=(u=!u)?0:10):0;p"#{10*a}% #{u ??U:?D}"}

Test cases:

f=->v{u,s,a=!!1,!0,0;v.map{|w|!s ?(a=u ? a+w : a-w;a>=10 ?(s,a=!!1,10):a<=0 ?(s,a=!!1,0):0;u,s=!u,!s):s=!0};!s ?(a=(u=!u)?0:10):0;p"#{10*a}% #{u ??U:?D}"}

f[[]]            # => "100% D"
f[[20]]          # => "0% U"
f[[10]]          # => "0% U"
f[[5]]           # => "50% D"
f[[20,20]]       # => "100% D"
f[[10,10]]       # => "100% D"
f[[5,5]]         # => "0% U"
f[[1,2,3]]       # => "100% D"
f[[8,9,10,11]]   # => "0% U"
f[[11,10,9,8,7]] # => "20% U"
  • \$\begingroup\$ As a fun side note, you can remove the requirement for extra brackets at the cost of one byte, by changing ->v{ to ->*v{ (I think). Also, do you need the spaces before the : as well as after? And are you sure that the :a<=0 doesn't parse to (:a) <= 0? \$\endgroup\$
    – anon
    May 11, 2016 at 18:54
  • \$\begingroup\$ Nice tip! Would need to be weighed up with access to the var though. As for :a<=0, I'd get an ArgumentError: comparison of Symbol with 0 failed if it didn't work. I think because it parsed the ? and knows it's in a ternary operator, it just works. The rules are indeed strange. I've put spaces or brackets in places that are needed to avoid syntax errors like SyntaxError: unexpected tLABEL and NoMethodError: undefined method u?'`. \$\endgroup\$
    – br3nt
    May 11, 2016 at 23:44
  • \$\begingroup\$ Feel free to do an edit if you can see any improvements. I was hoping to be able to get rid of a=u ? a+w : a-w and change it to a=a+w*d where d is 1 or -1 depending on direction, but I haven't worked it out yet. \$\endgroup\$
    – br3nt
    May 11, 2016 at 23:46
  • \$\begingroup\$ From what I understand, editing to make code better is generally discouraged; instead, you should comment. As for your idea for improvement, I dunno; it seems like it could work, but I dunno for sure. \$\endgroup\$
    – anon
    May 12, 2016 at 2:31

Python 3.5, 193 187 185 181 175 173 172 bytes:

def G(*p):
 for g in[*p,O]:
  if v=='G':Q=O*g//10;y=min(max(0,[Q,y-Q][z=='D']),O);l=min(10,g);z='UD'[z=='U']

Takes input in the form of comma separated numbers, for instance 1,2,3,4,5 or even 1.2,3.4,7.8,9.2. Outputs whether the door in the next step is going up or down with U or D, respectively. Will golf more over time.

Try It Online! (Ideone) (Here the input is taken in the form of a list consisting of comma separated numbers, e.g. [1,2,3,4,5].)


PHP, 128 120 bytes

foreach($argv as$a)
echo"$p% ".DU[$d>0];

The code is wrapped here to fit in the code box. Put everything on a single line, put the PHP open marker in front of it and save it into a file. Or run it from the command line using php -d error_reporting=0 -r '...the code...' [arguments].

The ungolfed source code, the test suite and examples of usage can be found on github.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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