Lucas Vs. The Garage Door Remote
Javascript (ES6), 277 275 263 253 250 247 234 bytes
_=>(d=[0,0],l=s='',[...Array(60)].map(_=>(s+=`
${c=Math.random()*3|0}:(`,l+=c,d=d.map((v,i)=>(v=v&8?v&16?v-27?v+1:20:v-9?v-1:0:v,v^=c+~i?0:v&8||24,s+='LR'[i]+`:${(v&7)*25}% `+(v&8?v&16?'opening':'closing':'stopped')+',)'[i],v)))),l+s)
Ungolfed and commented
_ => (
// Initialize array:
// - d = door states as integers
// - bits 0 to 2: door opening state (from 0b000 = 0% to 0b100 = 100%)
// - bit #3: door in motion (0: no, 1: yes)
// - bit #4: door direction (0: closing, 1: opening)
d = [0, 0],
// Initialize strings:
// - l = list of commands
// - s = door states in plain text
l = s = '',
// Iterate on an array of 60 entries.
[...Array(60)].map(_ => (
// c = new random command (0, 1 or 2)
// Append new line and new command to s.
s += `\n${c = Math.random() * 3 | 0}:(`,
// Append new command to l.
l += c,
// For each door ...
d = d.map((v, i) => (
// If the door is in motion, update its opening state.
// Clear the 'in motion' bit if a bound is reached (either closed or fully open).
v = v & 8 ? v & 16 ? v - 27 ? v + 1 : 20 : v - 9 ? v - 1 : 0 : v,
// If the current command is intended for this door, update its direction and
// 'in motion' bit. Direction is changed on the 'stopped => moving' transition.
v ^= c + ~i ? 0 : v & 8 || 24,
// Translate the door state in plain text and append it to s
s +=
'LR'[i] +
`:${(v & 7) * 25}% ` +
(v & 8 ? v & 16 ? 'opening' : 'closing' : 'stopped') +
',)'[i],
// Value to be taken into account by map()
v
))
)),
// Final result to be returned
l + s
)
Demo
let f =
_=>(d=[0,0],l=s='',[...Array(60)].map(_=>(s+=`
${c=Math.random()*3|0}:(`,l+=c,d=d.map((v,i)=>(v=v&8?v&16?v-27?v+1:20:v-9?v-1:0:v,v^=c+~i?0:v&8||24,s+='LR'[i]+`:${(v&7)*25}% `+(v&8?v&16?'opening':'closing':'stopped')+',)'[i],v)))),l+s)
console.log(f())
Python 2, 377 370 361 357 345 335 326 316 312 306 304 bytes
The second indent level is a raw tab (\t
), which plays really badly with Markdown, so it's been replaced by two spaces.
from random import*
p=[randint(0,2)for d in[[0]*3]*60]
print`p`[1::3]
v=[-1]*3
c=[0]*3
f=lambda y:str(c[y]*25)+'% '+'csoltpooespnipinengdg'[d[y]+1::3]
for x in p:
for i in 1,2:
q=d[i];c[i]+=q
if(2*-~q==c[i])*q:v[i]=q;d[i]=0
z=d[x]
if z:v[x]=z
d[x]=-v[x]*(z==0);print'%d: (L:%s, R:%s)'%(x,f(1),f(2))
I'm almost certain this can be golfed further.
Ungolfed, with comments:
import random
# Generate the random string - represented as a list of ints
presses = [random.randint(0, 2) for _ in range(60)]
print ''.join(map(str, presses))
# Constants for door states used for easier reading
CLOSING = -1
STOPPED = 0
OPENING = 1
# Variables representing the state of the garage doors
# There's a third element in these so that x[0] resolves to a dummy slot
# (this way, we can avoid a conditional down the road)
prev_states = [CLOSING, CLOSING, 0]
door_states = [STOPPED, STOPPED, 0]
door_pcts = [0, 0, 0] # delta 1 = 25%
for press in presses:
# Close/open the door 1 more
for i in 1, 2:
if door_states[i] != STOPPED:
delta_pct, stop_pct = (-1, 0) if door_states[i] == CLOSING else (1, 4)
door_pcts[i] += delta_pct
if door_pcts[i] == stop_pct:
prev_states[i] = door_states[i]
door_states[i] = STOPPED
# Handle pressing a button
# If the press is 0 (no press), the 0th element resolves to a dummy
# door, thus saving us an expensive conditional
if door_states[press] == STOPPED:
door_states[press] = -prev_states[press]
else:
prev_states[press] = door_states[press]
door_states[press] = STOPPED
# Print the status update
print '%d: (L:%d%% %s, R:%d%% %s)' % (
press,
door_pcts[0]*25,
['closing', 'stopped', 'opening'][door_states[0]+1],
door_pcts[1]*25,
['closing', 'stopped', 'opening'][door_states[1]+1],
)
Saved 4 14 15 bytes thanks to @TheBikingViking!
Saved 6 bytes thanks to @ValueInk!
C, 420 433 424 374 bytes
#define F(X,x) X=x==1?X+1:x==2?X-1:X;X=X<0?0:X>4?4:X;x=X==0?0:X==4?3:x
#define G(x) x=x==1?3:x==2?0:x==3?2:x+1
#define H(X,x) X*25,x==0||x==3?"stopped":x==1?"opening":"closing"
c,i,l,r,L,R,x[60];main(){while(i<60)printf("%d",x[i++]=random()%3);while(c<60){if(x[c]==1)G(l);else if(x[c]==2)G(r);printf("\n%d: (L:%d%% %s, R:%d%% %s)",x[c++],H(L,l),H(R,r));F(L,l);F(R,r);}}
Doesn't seed the random generator but does use random for a better distribution. There must be a better way to golf this logic though...
110121100121212100112200222111200020111100022122202112202211002
1: (L:0% opening, R:0% stopped)
1: (L:25% stopped, R:0% stopped)
0: (L:25% stopped, R:0% stopped)
1: (L:25% closing, R:0% stopped)
2: (L:0% stopped, R:0% opening)
1: (L:0% opening, R:25% opening)
1: (L:25% stopped, R:50% opening)
0: (L:25% stopped, R:75% opening)
0: (L:25% stopped, R:100% stopped)
1: (L:25% closing, R:100% stopped)
2: (L:0% stopped, R:100% closing)
1: (L:0% opening, R:75% closing)
2: (L:25% opening, R:50% stopped)
1: (L:50% stopped, R:50% stopped)
2: (L:50% stopped, R:50% opening)
1: (L:50% closing, R:75% opening)
0: (L:25% closing, R:100% stopped)
0: (L:0% stopped, R:100% stopped)
1: (L:0% opening, R:100% stopped)
1: (L:25% stopped, R:100% stopped)
2: (L:25% stopped, R:100% closing)
2: (L:25% stopped, R:75% stopped)
0: (L:25% stopped, R:75% stopped)
0: (L:25% stopped, R:75% stopped)
2: (L:25% stopped, R:75% opening)
2: (L:25% stopped, R:100% closing)
2: (L:25% stopped, R:75% stopped)
1: (L:25% closing, R:75% stopped)
1: (L:0% opening, R:75% stopped)
1: (L:25% stopped, R:75% stopped)
2: (L:25% stopped, R:75% opening)
0: (L:25% stopped, R:100% stopped)
0: (L:25% stopped, R:100% stopped)
0: (L:25% stopped, R:100% stopped)
2: (L:25% stopped, R:100% closing)
0: (L:25% stopped, R:75% closing)
1: (L:25% closing, R:50% closing)
1: (L:0% opening, R:25% closing)
1: (L:25% stopped, R:0% stopped)
1: (L:25% closing, R:0% stopped)
0: (L:0% stopped, R:0% stopped)
0: (L:0% stopped, R:0% stopped)
0: (L:0% stopped, R:0% stopped)
2: (L:0% stopped, R:0% opening)
2: (L:0% stopped, R:25% stopped)
1: (L:0% opening, R:25% stopped)
2: (L:25% opening, R:25% closing)
2: (L:50% opening, R:0% opening)
2: (L:75% opening, R:25% stopped)
0: (L:100% stopped, R:25% stopped)
2: (L:100% stopped, R:25% closing)
1: (L:100% closing, R:0% stopped)
1: (L:75% stopped, R:0% stopped)
2: (L:75% stopped, R:0% opening)
2: (L:75% stopped, R:25% stopped)
0: (L:75% stopped, R:25% stopped)
2: (L:75% stopped, R:25% closing)
2: (L:75% stopped, R:0% opening)
1: (L:75% opening, R:25% opening)
1: (L:100% closing, R:50% opening)
Older version 1:
c,i,l,r,L,R,x[60];main(){while(i<60)printf("%d",x[i++]=random()%3);while(c<60){if(x[c]==1)l=l==1?3:l==2?0:l==3?2:l+1;else if(x[c]==2)r=r==1?3:r==2?0:r==3?2:r+1;printf("\n%d: (L:%d%% %s, R:%d%% %s)",x[c++],L*25,l==0||l==3?"stopped":l==1?"opening":"closing",R*25,r==0||r==3?"stopped":r==1?"opening":"closing");L=l==1?L+1:l==2?L-1:L;R=r==1?R+1:r==2?R-1:R;L=L<0?0:L>4?4:L;R=R<0?0:R>4?4:R;l=L==0?0:L==4?3:l;r=R==0?0:R==4?3:r;}}
Older version 2:
c,i,l,r,L,R,x[60];g(){while(i<60)printf("%d",x[i++]=random()%3);}main(){g();while(c<60){if(x[c]==1)l=l==1?3:l==2?0:l==3?2:l+1;else if(x[c]==2)r=r==1?3:r==2?0:r==3?2:r+1;printf("%d: (L:%d%% %s, R:%d%% %s)\n",x[c++],L*25,l==0||l==3?"stopped":l==1?"opening":"closing",R*25,r==0||r==3?"stopped":r==1?"opening":"closing");L=l==1?L+1:l==2?L-1:L;R=r==1?R+1:r==2?R-1:R;L=L<0?0:L>4?4:L;R=R<0?0:R>4?4:R;l=L==0?0:L==4?3:l;r=R==0?0:R==4?3:r;}}