Skip to content

Commit a7c4a5e

Browse files
feat(2020-day-12): navigate by waypoints
Part 2 uses a new navigation method
1 parent a40b56a commit a7c4a5e

File tree

2 files changed

+165
-59
lines changed

2 files changed

+165
-59
lines changed

2020/day-12/ferry.js

Lines changed: 162 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,75 +11,181 @@ const move = ({
1111
y: 0,
1212
d: 90 // Default to facing east
1313
},
14-
command
14+
waypoint = {
15+
x: 10,
16+
y: 1
17+
},
18+
command,
19+
mode = 'normal'
1520
}) => {
1621
// Movement subfunctions
1722
const mv = {
18-
N: (u) => { // North
19-
position.y += u
20-
},
21-
S: (u) => { // South
22-
position.y -= u
23-
},
24-
E: (u) => { // East
25-
position.x += u
26-
},
27-
W: (u) => { // West
28-
position.x -= u
29-
},
30-
L: (u) => { // Turn Left
31-
position.d -= u
32-
position.d = position.d % 360
33-
// prevent negative angles
34-
if (position.d < 0) {
35-
position.d += 360
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+
}
3672
}
3773
},
38-
R: (u) => { // Turn Right
39-
position.d += u
40-
position.d = position.d % 360
41-
// prevent negative angles
42-
if (position.d < 0) {
43-
position.d += 360
44-
}
45-
},
46-
F: (u) => { // Forward
47-
// TODO: replace with vector positioning of arbitrary angles
48-
switch (position.d) {
49-
case 0 :
50-
mv.N(u)
51-
break
52-
case 90 :
53-
mv.E(u)
54-
break
55-
case 180 :
56-
mv.S(u)
57-
break
58-
case 270 :
59-
mv.W(u)
60-
break
61-
default :
62-
console.debug('Position', position)
63-
console.debug('Forward', u)
64-
throw new Error('Non-cardinal compass direction')
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+
})
65152
}
66153
}
67154
}
68155

69156
console.debug('Received', command, position)
70157
const operation = parseCommand(command)
71-
mv[operation.cmd](operation.unit)
72-
return position
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+
}
73170
}
74171

75-
const route = ({ instructions }) => {
76-
return instructions.reduce(
77-
(position, command) => {
78-
console.debug('Routing position', position)
79-
console.debug('Routing command', command)
80-
return move({ position, command })
81-
}, { x: 0, y: 0, d: 90 }
82-
)
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
83189
}
84190

85191
module.exports = {

2020/day-12/ferry.test.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ describe('--- Day 11: Seating System ---', () => {
168168
move({ position: origin, waypoint, command, mode })
169169
).to.deep.equal({
170170
position: { x: 0, y: 0, d: 90 },
171-
waypoint: { x: 1, y: 10 }
171+
waypoint: { x: 1, y: -10 }
172172
})
173173
})
174174
it('waypoint: can move forward in the direction it is pointing', () => {
@@ -197,9 +197,9 @@ describe('--- Day 11: Seating System ---', () => {
197197
]
198198
const result = route({ instructions, mode })
199199
expect(result)
200-
.to.deep.equal({ x: 214, y: 72, d: 90 })
200+
.to.deep.equal({ x: 214, y: -72, d: 90 })
201201
// manhattan distance from origin
202-
expect(distance({ x: 0, y: 0 }, result)).to.equal(72)
202+
expect(distance({ x: 0, y: 0 }, result)).to.equal(286)
203203
})
204204
})
205205
})

0 commit comments

Comments
 (0)