Skip to content

Commit d2b2d94

Browse files
Merge pull request #134 from amclin/feat/2020-day-12
2020-day-12
2 parents 1472997 + a7c4a5e commit d2b2d94

File tree

6 files changed

+1227
-22
lines changed

6 files changed

+1227
-22
lines changed

2020/day-12/ferry.js

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
const parseCommand = (command) => {
2+
return {
3+
cmd: command.slice(0, 1),
4+
unit: Number(command.slice(1))
5+
}
6+
}
7+
8+
const move = ({
9+
position = {
10+
x: 0,
11+
y: 0,
12+
d: 90 // Default to facing east
13+
},
14+
waypoint = {
15+
x: 10,
16+
y: 1
17+
},
18+
command,
19+
mode = 'normal'
20+
}) => {
21+
// Movement subfunctions
22+
const mv = {
23+
normal: {
24+
N: (u) => { // North
25+
position.y += u
26+
},
27+
S: (u) => { // South
28+
position.y -= u
29+
},
30+
E: (u) => { // East
31+
position.x += u
32+
},
33+
W: (u) => { // West
34+
position.x -= u
35+
},
36+
L: (u) => { // Turn Left
37+
position.d -= u
38+
position.d = position.d % 360
39+
// prevent negative angles
40+
if (position.d < 0) {
41+
position.d += 360
42+
}
43+
},
44+
R: (u) => { // Turn Right
45+
position.d += u
46+
position.d = position.d % 360
47+
// prevent negative angles
48+
if (position.d < 0) {
49+
position.d += 360
50+
}
51+
},
52+
F: (u) => { // Forward
53+
// TODO: replace with vector positioning of arbitrary angles
54+
switch (position.d) {
55+
case 0 :
56+
mv[mode].N(u)
57+
break
58+
case 90 :
59+
mv[mode].E(u)
60+
break
61+
case 180 :
62+
mv[mode].S(u)
63+
break
64+
case 270 :
65+
mv[mode].W(u)
66+
break
67+
default :
68+
console.debug('Position', position)
69+
console.debug('Forward', u)
70+
throw new Error('Non-cardinal compass direction')
71+
}
72+
}
73+
},
74+
waypoint: {
75+
N: (u) => { // Waypoint North
76+
waypoint.y += u
77+
},
78+
S: (u) => { // Waypoint South
79+
waypoint.y -= u
80+
},
81+
E: (u) => { // Waypoint East
82+
waypoint.x += u
83+
},
84+
W: (u) => { // Waypoint West
85+
waypoint.x -= u
86+
},
87+
L: (u) => { // Waypoint Turn Left
88+
// Luckily we can be lazy and not involve trig since all the rotations
89+
// are multiples of 90 degrees
90+
91+
// Rotate around an origin since it's easier
92+
let oldWaypoint = {
93+
x: waypoint.x - position.x,
94+
y: waypoint.y - position.y
95+
}
96+
let tmpWaypoint = {}
97+
// Figure out the number of quarter-turns
98+
const qtr = u / 90
99+
// Rotate each quarter turn
100+
for (let r = 1; r <= qtr; r++) {
101+
tmpWaypoint = {
102+
x: oldWaypoint.y * -1,
103+
y: oldWaypoint.x
104+
}
105+
// Prep for next rotation
106+
oldWaypoint = JSON.parse(JSON.stringify(tmpWaypoint))
107+
}
108+
// Update the waypoint with the new position
109+
Object.assign(waypoint, {
110+
x: position.x + tmpWaypoint.x,
111+
y: position.y + tmpWaypoint.y
112+
})
113+
},
114+
R: (u) => { // Waypoint Turn Right
115+
// Rotate around an origin since it's easier
116+
let oldWaypoint = {
117+
x: waypoint.x - position.x,
118+
y: waypoint.y - position.y
119+
}
120+
let tmpWaypoint = {}
121+
// Figure out the number of quarter-turns
122+
const qtr = u / 90
123+
// Rotate each quarter turn
124+
for (let r = 1; r <= qtr; r++) {
125+
tmpWaypoint = {
126+
x: oldWaypoint.y,
127+
y: oldWaypoint.x * -1
128+
}
129+
// Prep for next rotation
130+
oldWaypoint = JSON.parse(JSON.stringify(tmpWaypoint))
131+
}
132+
// Update the waypoint with the new position
133+
Object.assign(waypoint, {
134+
x: position.x + tmpWaypoint.x,
135+
y: position.y + tmpWaypoint.y
136+
})
137+
},
138+
F: (u) => { // Forward
139+
const distance = {
140+
x: waypoint.x - position.x,
141+
y: waypoint.y - position.y
142+
}
143+
144+
Object.assign(position, {
145+
x: position.x + (distance.x * u),
146+
y: position.y + (distance.y * u)
147+
})
148+
Object.assign(waypoint, {
149+
x: waypoint.x + (distance.x * u),
150+
y: waypoint.y + (distance.y * u)
151+
})
152+
}
153+
}
154+
}
155+
156+
console.debug('Received', command, position)
157+
const operation = parseCommand(command)
158+
mv[mode][operation.cmd](operation.unit)
159+
160+
if (mode === 'normal') {
161+
return position
162+
}
163+
console.debug('-------------------')
164+
console.debug('position:', position)
165+
console.debug('waypoint:', waypoint)
166+
return {
167+
position,
168+
waypoint
169+
}
170+
}
171+
172+
const route = ({ instructions, mode }) => {
173+
let position = { x: 0, y: 0, d: 90 }
174+
let waypoint = { x: 10, y: 1 }
175+
instructions.forEach((command) => {
176+
console.debug('Routing position', position)
177+
console.debug('Routing command', command)
178+
console.debug('Routing method', mode)
179+
if (mode === 'waypoint') {
180+
const tmp = move({ position, waypoint, command, mode })
181+
position = tmp.position
182+
waypoint = tmp.waypoint
183+
} else {
184+
position = move({ position, command, mode })
185+
}
186+
})
187+
188+
return position
189+
}
190+
191+
module.exports = {
192+
move,
193+
route
194+
}

0 commit comments

Comments
 (0)