Skip to content

Commit 11e880e

Browse files
feat(2018 day-10): track the beacons and animate them across frames
1 parent 87fc7d2 commit 11e880e

File tree

3 files changed

+214
-0
lines changed

3 files changed

+214
-0
lines changed

2018/day-10/beacons.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
class Beacon {
2+
constructor (start) {
3+
this.start = start
4+
this.time = 0
5+
this.frameMeta = []
6+
}
7+
8+
/**
9+
* Interpolates data to calculate a given frame
10+
* @param {Number} frame number
11+
* @returns {Object} frame contents
12+
*/
13+
getFrame (frame) {
14+
let data = {}
15+
// Calculate the position of all the beacons
16+
data.contents = this.start.map((beacon) => {
17+
var point = {}
18+
Object.keys(beacon.position).forEach((key) => {
19+
point[key] = beacon.position[key] + (frame * beacon.velocity[key])
20+
})
21+
return point
22+
})
23+
24+
if (this.frameMeta[frame]) {
25+
// Get cached metadata
26+
data.meta = this.frameMeta[frame]
27+
} else {
28+
// cache metadata for this frame if we haven't already
29+
let meta = {
30+
focus: this._getFocus(data.contents)
31+
}
32+
this.frameMeta[frame] = meta
33+
data.meta = this.frameMeta[frame]
34+
}
35+
36+
return data
37+
}
38+
39+
/**
40+
* Calculates the area occupied by the points in a given frame.
41+
* The mimimum area in an animation should indicate the frame
42+
* that is most in focus.
43+
*/
44+
_getFocus (points) {
45+
// Find min/max values
46+
let ranges = points.reduce((acc, cur) => {
47+
return {
48+
maxX: Math.max(acc.maxX, cur.x),
49+
maxY: Math.max(acc.maxY, cur.y),
50+
minX: Math.min(acc.minX, cur.x),
51+
minY: Math.min(acc.minX, cur.x)
52+
}
53+
}, { maxX: 0, maxY: 0, minX: 0, minY: 0 })
54+
55+
return (ranges.maxX - ranges.minX) * (ranges.maxY - ranges.minY)
56+
}
57+
}
58+
59+
module.exports = {
60+
Beacon
61+
}

2018/day-10/beacons.test.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/* eslint-env mocha */
2+
const expect = require('chai').expect
3+
const {
4+
parseLine
5+
} = require('./helpers')
6+
const {
7+
Beacon
8+
} = require('./beacons')
9+
10+
const testData = `position=< 9, 1> velocity=< 0, 2>
11+
position=< 7, 0> velocity=<-1, 0>
12+
position=< 3, -2> velocity=<-1, 1>
13+
position=< 6, 10> velocity=<-2, -1>
14+
position=< 2, -4> velocity=< 2, 2>
15+
position=<-6, 10> velocity=< 2, -2>
16+
position=< 1, 8> velocity=< 1, -1>
17+
position=< 1, 7> velocity=< 1, 0>
18+
position=<-3, 11> velocity=< 1, -2>
19+
position=< 7, 6> velocity=<-1, -1>
20+
position=<-2, 3> velocity=< 1, 0>
21+
position=<-4, 3> velocity=< 2, 0>
22+
position=<10, -3> velocity=<-1, 1>
23+
position=< 5, 11> velocity=< 1, -2>
24+
position=< 4, 7> velocity=< 0, -1>
25+
position=< 8, -2> velocity=< 0, 1>
26+
position=<15, 0> velocity=<-2, 0>
27+
position=< 1, 6> velocity=< 1, 0>
28+
position=< 8, 9> velocity=< 0, -1>
29+
position=< 3, 3> velocity=<-1, 1>
30+
position=< 0, 5> velocity=< 0, -1>
31+
position=<-2, 2> velocity=< 2, 0>
32+
position=< 5, -2> velocity=< 1, 2>
33+
position=< 1, 4> velocity=< 2, 1>
34+
position=<-2, 7> velocity=< 2, -2>
35+
position=< 3, 6> velocity=<-1, -1>
36+
position=< 5, 0> velocity=< 1, 0>
37+
position=<-6, 0> velocity=< 2, 0>
38+
position=< 5, 9> velocity=< 1, -2>
39+
position=<14, 7> velocity=<-2, 0>
40+
position=<-3, 6> velocity=< 2, -1>`.split('\n').map(parseLine)
41+
42+
describe('--- Day 10: The Stars Align ---', () => {
43+
describe('Beacons:', () => {
44+
describe('new Beacons()', () => {
45+
it('initializes a beacon tracker object, cacheing the input data', () => {
46+
const expected = [
47+
{ position: { x: 9, y: 1 }, velocity: { x: 0, y: 2 } },
48+
{ position: { x: 7, y: 0 }, velocity: { x: -1, y: 0 } },
49+
{ position: { x: 3, y: -2 }, velocity: { x: -1, y: 1 } },
50+
{ position: { x: 6, y: 10 }, velocity: { x: -2, y: -1 } },
51+
{ position: { x: 2, y: -4 }, velocity: { x: 2, y: 2 } },
52+
{ position: { x: -6, y: 10 }, velocity: { x: 2, y: -2 } },
53+
{ position: { x: 1, y: 8 }, velocity: { x: 1, y: -1 } },
54+
{ position: { x: 1, y: 7 }, velocity: { x: 1, y: 0 } },
55+
{ position: { x: -3, y: 11 }, velocity: { x: 1, y: -2 } },
56+
{ position: { x: 7, y: 6 }, velocity: { x: -1, y: -1 } },
57+
{ position: { x: -2, y: 3 }, velocity: { x: 1, y: 0 } },
58+
{ position: { x: -4, y: 3 }, velocity: { x: 2, y: 0 } },
59+
{ position: { x: 10, y: -3 }, velocity: { x: -1, y: 1 } },
60+
{ position: { x: 5, y: 11 }, velocity: { x: 1, y: -2 } },
61+
{ position: { x: 4, y: 7 }, velocity: { x: 0, y: -1 } },
62+
{ position: { x: 8, y: -2 }, velocity: { x: 0, y: 1 } },
63+
{ position: { x: 15, y: 0 }, velocity: { x: -2, y: 0 } },
64+
{ position: { x: 1, y: 6 }, velocity: { x: 1, y: 0 } },
65+
{ position: { x: 8, y: 9 }, velocity: { x: 0, y: -1 } },
66+
{ position: { x: 3, y: 3 }, velocity: { x: -1, y: 1 } },
67+
{ position: { x: 0, y: 5 }, velocity: { x: 0, y: -1 } },
68+
{ position: { x: -2, y: 2 }, velocity: { x: 2, y: 0 } },
69+
{ position: { x: 5, y: -2 }, velocity: { x: 1, y: 2 } },
70+
{ position: { x: 1, y: 4 }, velocity: { x: 2, y: 1 } },
71+
{ position: { x: -2, y: 7 }, velocity: { x: 2, y: -2 } },
72+
{ position: { x: 3, y: 6 }, velocity: { x: -1, y: -1 } },
73+
{ position: { x: 5, y: 0 }, velocity: { x: 1, y: 0 } },
74+
{ position: { x: -6, y: 0 }, velocity: { x: 2, y: 0 } },
75+
{ position: { x: 5, y: 9 }, velocity: { x: 1, y: -2 } },
76+
{ position: { x: 14, y: 7 }, velocity: { x: -2, y: 0 } },
77+
{ position: { x: -3, y: 6 }, velocity: { x: 2, y: -1 } }
78+
]
79+
const beaconTracker = new Beacon(testData)
80+
const actual = beaconTracker.start
81+
expect(actual).to.deep.equal(expected)
82+
})
83+
})
84+
describe('get(frame)', () => {
85+
it('Calculates the positions of the beacons for the specified frame', () => {
86+
const expected = [
87+
{ x: 9, y: 13 },
88+
{ x: 1, y: 0 },
89+
{ x: -3, y: 4 },
90+
{ x: -6, y: 4 },
91+
{ x: 14, y: 8 },
92+
{ x: 6, y: -2 },
93+
{ x: 7, y: 2 },
94+
{ x: 7, y: 7 },
95+
{ x: 3, y: -1 },
96+
{ x: 1, y: 0 },
97+
{ x: 4, y: 3 },
98+
{ x: 8, y: 3 },
99+
{ x: 4, y: 3 },
100+
{ x: 11, y: -1 },
101+
{ x: 4, y: 1 },
102+
{ x: 8, y: 4 },
103+
{ x: 3, y: 0 },
104+
{ x: 7, y: 6 },
105+
{ x: 8, y: 3 },
106+
{ x: -3, y: 9 },
107+
{ x: 0, y: -1 },
108+
{ x: 10, y: 2 },
109+
{ x: 11, y: 10 },
110+
{ x: 13, y: 10 },
111+
{ x: 10, y: -5 },
112+
{ x: -3, y: 0 },
113+
{ x: 11, y: 0 },
114+
{ x: 6, y: 0 },
115+
{ x: 11, y: -3 },
116+
{ x: 2, y: 7 },
117+
{ x: 9, y: 0 }
118+
]
119+
const beaconTracker = new Beacon(testData)
120+
const actual = beaconTracker.getFrame(6).contents
121+
expect(actual).to.deep.equal(expected)
122+
})
123+
it('Calculates the focus value for the frame', () => {
124+
const expected = 756
125+
const beaconTracker = new Beacon(testData)
126+
const actual = beaconTracker.getFrame(8).meta.focus
127+
expect(actual).to.equal(expected)
128+
})
129+
})
130+
})
131+
})

2018/day-10/solution.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
const { loadInput } = require('./helpers')
2+
const display = require('./display')
3+
const {
4+
Beacon
5+
} = require('./beacons')
6+
7+
const init = (data) => {
8+
let beaconTracker = new Beacon(data)
9+
for (let x = 0; x < 5; x++) {
10+
display.show(beaconTracker.getFrame(x), [22, 16], [-6, -4])
11+
}
12+
13+
// data = parseData(data)
14+
// const answer = sumMetadata(data)
15+
// const answer2 = data.value
16+
// console.log(`-- Part 1 --`)
17+
// console.log(`Answer: ${answer}`)
18+
// console.log(`-- Part 2 --`)
19+
// console.log(`Answer: ${answer2}`)
20+
}
21+
22+
loadInput(init)

0 commit comments

Comments
 (0)