Skip to content

Commit 5b2e83f

Browse files
feat(2018 day-13): advance all carts each turn and correctly handle intersection rotation logic
1 parent d9d8489 commit 5b2e83f

File tree

3 files changed

+84
-55
lines changed

3 files changed

+84
-55
lines changed

2018/day-13/solution.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@ const {
22
Track
33
} = require('./tracks')
44

5-
/* eslint-disable */
65
const data = `/->-\\
76
| | /----\\
87
| /-+--+-\\ |
98
| | | | v |
109
\\-+-/ \\-+--/
1110
\\------/ `
12-
/* eslint-enable */
1311

14-
const mytrack = new Track(data)
15-
const actual = mytrack.display()
16-
console.log(actual)
12+
const track = new Track(data)
13+
while (track.collision === false) {
14+
track.advance()
15+
}
16+
17+
console.error(`Reached a collision at ${track.collision.x},${track.collision.y} on frame ${track.frame}`)
18+
console.log(`Track state:`)
19+
console.log(track.display())

2018/day-13/tracks.js

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
const { dynamicSortMultiple } = require('../day-04/helpers')
2+
13
class Track {
24
constructor (track) {
35
this.layout = []
46
this.carts = []
57
this.cartDirections = ['^', '>', 'v', '<']
6-
this.trackTurns = ['\\', '/']
7-
this.trackTypes = this.trackTurns.concat(['-', '|', '+'])
88
this.collision = false
99
this.frame = 0
10+
this.trackTurns = ['\\', '/']
11+
this.trackTypes = this.trackTurns.concat(['-', '|', '+'])
1012
this.setLayout(track)
1113
}
1214

@@ -16,21 +18,18 @@ class Track {
1618

1719
/**
1820
* Determines the next direction for a cart rotating at an intersection
19-
* Order of rotations is left (counterclockwise), right (clockwise), straight
21+
* Order of rotations is left (counterclockwise), straigh, right (clockwise), straight
2022
* @private
2123
* @param {Object} cart the cart being turned
2224
* @returns {String} value of new direction
2325
*/
2426
_intersect (cart) {
25-
let r = 0
26-
if (typeof cart.lastIntersection === 'undefined') {
27-
r = -1
28-
}
29-
if (cart.lastIntersection === -1) {
30-
r = 1
31-
}
27+
let l = cart.lastIntersections
28+
let r = (l[0] !== 0) ? 0 : l[1] * -1
29+
// Track the intersections
30+
cart.lastIntersections.pop()
31+
cart.lastIntersections.splice(0, 0, r)
3232

33-
cart.lastIntersection = r
3433
return this.cartDirections[this._roationDirection(this.cartDirections.indexOf(cart.direction), r)]
3534
}
3635

@@ -50,7 +49,6 @@ class Track {
5049
// (this.trackTurns.indexOf(s) === 0 && a === 'x') // horizontal turns counter-clockwise
5150
// (this.trackTurns.indexOf(s) === 1 && a === 'y') // vertical turns counter-clockwise
5251
) ? 1 : -1
53-
console.log(`${s} for ${a} is turning ${r}`)
5452
// Find the value of the new direction
5553
return this.cartDirections[this._roationDirection(d, r)]
5654
}
@@ -63,17 +61,30 @@ class Track {
6361
* @returns {Number} Index of new direction
6462
*/
6563
_roationDirection (d, r) {
66-
console.log(`rotating ${d}, ${r}`)
6764
if (d + r > this.cartDirections.length - 1) {
6865
return 0
6966
}
7067
if (d + r < 0) {
7168
return this.cartDirections.length - 1
7269
}
73-
console.log(`new direction is ${d + r}`)
7470
return d + r
7571
}
7672

73+
/**
74+
* Advances the state of the entire layout
75+
*/
76+
advance () {
77+
this.frame++
78+
this.carts.sort(dynamicSortMultiple('y', 'x')).forEach((c) => {
79+
try {
80+
this.moveCart(c)
81+
} catch (err) {
82+
console.error(`Problem moving cart in frame ${this.frame}`)
83+
console.error(err)
84+
}
85+
})
86+
}
87+
7788
/**
7889
* Displays the current state of the track with the carts placed
7990
*/
@@ -108,7 +119,8 @@ class Track {
108119
this.carts.push({
109120
x: idx,
110121
y: idy,
111-
direction: x
122+
direction: x,
123+
lastIntersections: [0, 1] // Assume the first intersection the cart will turn left
112124
})
113125
// Replace the cart on the track with a track segment
114126
// (Assuming cart initial states aren't on instersections)
@@ -124,7 +136,7 @@ class Track {
124136
* @param {*} x Number
125137
* @param {*} y Number
126138
*/
127-
getSegmentType (x, y) {
139+
getSegment (x, y) {
128140
return this.layout[y][x]
129141
}
130142

@@ -139,22 +151,20 @@ class Track {
139151
const l = (d % 3 === 0) ? -1 : 1 // (+/-) distance of travel on the axis
140152
// move the cart
141153
cart[a] = cart[a] + l
142-
const s = this.layout[cart.y][cart.x] // Segment of track the cart is now on
154+
const s = this.getSegment(cart.x, cart.y) // Segment of track the cart is now on
143155

144156
// Make sure cart hasn't run off the rails
145157
if (this.trackTypes.indexOf(this.layout[cart.y][cart.x]) < 0) {
146-
return new Error(`cart ran off the track at ${cart.x}, ${cart.y}`)
158+
throw new Error(`cart ran off the track at ${cart.x}, ${cart.y}`)
147159
}
148160
// Check for collision
149161
if (this._isCollision(cart.x, cart.y)) {
150162
this.collision = { x: cart.x, y: cart.y }
151-
return new Error(`collision at ${cart.x}, ${cart.y}`) // Stop everything
163+
throw new Error(`collision at ${cart.x}, ${cart.y}`) // Stop everything
152164
}
153165
// rotate the cart when entering a turn
154166
if (this._isTurn(s)) {
155-
console.log(`Cart direction was ${cart.direction}`)
156167
cart.direction = this._rotate(s, a, d)
157-
console.log(`Cart direction is ${cart.direction}`)
158168
return
159169
}
160170
// rotate (or not) the cart when entering an intersection

2018/day-13/tracks.test.js

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ describe('--- Day 13: Mine Cart Madness ---', () => {
2222
const expected = [{
2323
x: 2,
2424
y: 0,
25-
direction: '>'
25+
direction: '>',
26+
lastIntersections: [0, 1]
2627
}, {
2728
x: 9,
2829
y: 3,
29-
direction: 'v'
30+
direction: 'v',
31+
lastIntersections: [0, 1]
3032
}]
3133
const track = new Track(data)
3234
const actual = track.carts
@@ -35,22 +37,23 @@ describe('--- Day 13: Mine Cart Madness ---', () => {
3537
})
3638
describe('advance()', () => {
3739
it('moves forward all carts on the layout', () => {
38-
const test = `/---v
40+
const test = `/---\\
3941
| | /----\\
40-
| /-+--+-\\ |
41-
| | | | | |
42-
\\-+-/ \\-+>-/
42+
| /-+>-+-\\ |
43+
| | | | | ^
44+
\\-+-/ \\-+--/
4345
\\------/ `
44-
const expected = `/---\
45-
| v /----\\
46-
| /-+--+-\\ |
46+
const expected = `/---\\
47+
| | /----\\
48+
| /-+->+-\\ ^
4749
| | | | | |
48-
\\-+-/ \\-+->/
50+
\\-+-/ \\-+--/
4951
\\------/ `.trim()
5052
const track = new Track(test)
51-
track.moveCart()
53+
track.advance()
5254
const actual = track.display()
5355
expect(actual).to.equal(expected)
56+
expect(track.frame).to.equal(1)
5457
})
5558
})
5659
describe('moveCart(cart)', () => {
@@ -124,19 +127,26 @@ describe('--- Day 13: Mine Cart Madness ---', () => {
124127
const actual = track.display()
125128
expect(actual).to.equal(expected)
126129
})
127-
it('tracks the direction through multiple intersections following the sequential rotation rules: left, straight, right', () => {
128-
const test = `
130+
it('tracks the direction through multiple intersections following the sequential rotation rules: left, straight, right, straight', () => {
131+
const expected = `
132+
^
133+
|
134+
+-+-+
129135
|
130-
-+-+--
136+
+
131137
|
132-
->-+-`
133-
const track = new Track(test)
134-
const expected = `
138+
---+`.trim()
139+
const test = `
140+
|
141+
|
142+
+-+-+
135143
|
136-
-+-+->
144+
+
137145
|
138-
---+-`.trim()
139-
for (let i = 0; i < 8; i++) {
146+
->-+`
147+
const track = new Track(test)
148+
149+
for (let i = 0; i < 12; i++) {
140150
track.moveCart(track.carts[0])
141151
}
142152
const actual = track.display()
@@ -154,18 +164,24 @@ describe('--- Day 13: Mine Cart Madness ---', () => {
154164
it('throws an error if the cart runs off the rails', () => {
155165
const test = `->- -`
156166
const track = new Track(test)
157-
track.moveCart(track.carts[0])
158-
expect(track.moveCart(track.carts[0])).to.be.an('error')
167+
try {
168+
track.moveCart(track.carts[0])
169+
} catch (err) {
170+
expect(err).to.be.an('error')
171+
}
159172
})
160173
it('registers a collision', () => {
161174
const test = `->-<-`
162175
const expected = `---X-`
163176
const track = new Track(test)
164-
track.moveCart(track.carts[0])
165-
track.moveCart(track.carts[0])
166-
const actual = track.display()
167-
expect(actual).to.equal(expected)
168-
expect(track.collision).to.deep.equal({ x: 3, y: 0 })
177+
try {
178+
track.moveCart(track.carts[0])
179+
track.moveCart(track.carts[0])
180+
} catch (err) {
181+
const actual = track.display()
182+
expect(actual).to.equal(expected)
183+
expect(track.collision).to.deep.equal({ x: 3, y: 0 })
184+
}
169185
})
170186
})
171187
describe('display()', () => {
@@ -176,11 +192,11 @@ describe('--- Day 13: Mine Cart Madness ---', () => {
176192
expect(actual).to.equal(expected)
177193
})
178194
})
179-
describe('getSegmentType(x,y)', () => {
195+
describe('getSegment(x,y)', () => {
180196
it('queries the type of segment at location x,y', () => {
181197
const expected = '-'
182198
const track = new Track(data)
183-
const actual = track.getSegmentType(5, 2)
199+
const actual = track.getSegment(5, 2)
184200
expect(actual).to.equal(expected)
185201
})
186202
})

0 commit comments

Comments
 (0)