Skip to content

Commit d5a5f8b

Browse files
committed
feat: Day 18: Settlers of The North Pole (part 1)
1 parent be5b697 commit d5a5f8b

File tree

4 files changed

+273
-0
lines changed

4 files changed

+273
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Collect stars by solving puzzles. Two puzzles will be made available on each day
2929
- [Day 14: Chocolate Charts](day-14-chocolate-charts/)
3030
- [Day 15: Beverage Bandits](day-15-beverage-bandits/)
3131
- [Day 16: Chronal Classification](day-16-chronal-classification/)
32+
- [Day 18: Settlers of The North Pole](day-18-settlers-of-the-north-pole/)
3233

3334
## Running Tests
3435

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# Day 18: Settlers of The North Pole
2+
3+
On the outskirts of the North Pole base construction project, many Elves are collecting lumber.
4+
5+
The lumber collection area is 50 acres by 50 acres; each acre can be either **open ground** (`.`), **trees** (`|`), or a **lumberyard** (`#`). You take a scan of the area (your puzzle input).
6+
7+
Strange magic is at work here: each minute, the landscape looks entirely different. In exactly **one minute**, an open acre can fill with trees, a wooded acre can be converted to a lumberyard, or a lumberyard can be cleared to open ground (the lumber having been sent to other projects).
8+
9+
The change to each acre is based entirely on the contents of that acre as well as the number of open, wooded, or lumberyard acres adjacent to it at the start of each minute. Here, "adjacent" means any of the eight acres surrounding that acre. (Acres on the edges of the lumber collection area might have fewer than eight adjacent acres; the missing acres aren't counted.)
10+
11+
In particular:
12+
13+
- An **open** acre will become filled with **trees** if **three or more** adjacent acres contained trees. Otherwise, nothing happens.
14+
- An acre filled with **trees** will become a **lumberyard** if **three or more** adjacent acres were lumberyards. Otherwise, nothing happens.
15+
- An acre containing a **lumberyard** will remain a **lumberyard** if it was adjacent to **at least one other lumberyard and at least one acre containing trees**. Otherwise, it becomes **open**.
16+
17+
These changes happen across all acres **simultaneously**, each of them using the state of all acres at the beginning of the minute and changing to their new form by the end of that same minute. Changes that happen during the minute don't affect each other.
18+
19+
For example, suppose the lumber collection area is instead only 10 by 10 acres with this initial configuration:
20+
21+
```
22+
Initial state:
23+
.#.#...|#.
24+
.....#|##|
25+
.|..|...#.
26+
..|#.....#
27+
#.#|||#|#|
28+
...#.||...
29+
.|....|...
30+
||...#|.#|
31+
|.||||..|.
32+
...#.|..|.
33+
34+
After 1 minute:
35+
.......##.
36+
......|###
37+
.|..|...#.
38+
..|#||...#
39+
..##||.|#|
40+
...#||||..
41+
||...|||..
42+
|||||.||.|
43+
||||||||||
44+
....||..|.
45+
46+
After 2 minutes:
47+
.......#..
48+
......|#..
49+
.|.|||....
50+
..##|||..#
51+
..###|||#|
52+
...#|||||.
53+
|||||||||.
54+
||||||||||
55+
||||||||||
56+
.|||||||||
57+
58+
After 3 minutes:
59+
.......#..
60+
....|||#..
61+
.|.||||...
62+
..###|||.#
63+
...##|||#|
64+
.||##|||||
65+
||||||||||
66+
||||||||||
67+
||||||||||
68+
||||||||||
69+
70+
After 4 minutes:
71+
.....|.#..
72+
...||||#..
73+
.|.#||||..
74+
..###||||#
75+
...###||#|
76+
|||##|||||
77+
||||||||||
78+
||||||||||
79+
||||||||||
80+
||||||||||
81+
82+
After 5 minutes:
83+
....|||#..
84+
...||||#..
85+
.|.##||||.
86+
..####|||#
87+
.|.###||#|
88+
|||###||||
89+
||||||||||
90+
||||||||||
91+
||||||||||
92+
||||||||||
93+
94+
After 6 minutes:
95+
...||||#..
96+
...||||#..
97+
.|.###|||.
98+
..#.##|||#
99+
|||#.##|#|
100+
|||###||||
101+
||||#|||||
102+
||||||||||
103+
||||||||||
104+
||||||||||
105+
106+
After 7 minutes:
107+
...||||#..
108+
..||#|##..
109+
.|.####||.
110+
||#..##||#
111+
||##.##|#|
112+
|||####|||
113+
|||###||||
114+
||||||||||
115+
||||||||||
116+
||||||||||
117+
118+
After 8 minutes:
119+
..||||##..
120+
..|#####..
121+
|||#####|.
122+
||#...##|#
123+
||##..###|
124+
||##.###||
125+
|||####|||
126+
||||#|||||
127+
||||||||||
128+
||||||||||
129+
130+
After 9 minutes:
131+
..||###...
132+
.||#####..
133+
||##...##.
134+
||#....###
135+
|##....##|
136+
||##..###|
137+
||######||
138+
|||###||||
139+
||||||||||
140+
||||||||||
141+
142+
After 10 minutes:
143+
.||##.....
144+
||###.....
145+
||##......
146+
|##.....##
147+
|##.....##
148+
|##....##|
149+
||##.####|
150+
||#####|||
151+
||||#|||||
152+
||||||||||
153+
```
154+
155+
After 10 minutes, there are `37` wooded acres and `31` lumberyards. Multiplying the number of wooded acres by the number of lumberyards gives the total **resource value** after ten minutes: `37 * 31 = 1147`.
156+
157+
**What will the total resource value of the lumber collection area be after 10 minutes?**
158+
159+
## References
160+
- https://adventofcode.com/2018/day/18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
const countTrees = (acres) => acres.filter((a) => a === '|').length;
2+
const countLumberyards = (acres) => acres.filter((a) => a === '#').length;
3+
4+
const computeNextState = (currentState, adjacentAcres) => {
5+
const trees = countTrees(adjacentAcres);
6+
const lumberyards = countLumberyards(adjacentAcres);
7+
8+
if (currentState === '.' && trees >= 3) {
9+
return '|';
10+
}
11+
12+
if (currentState === '|' && lumberyards >= 3) {
13+
return '#';
14+
}
15+
16+
if (currentState === '#') {
17+
return lumberyards >= 1 && trees >= 1 ? '#' : '.';
18+
}
19+
20+
return currentState;
21+
};
22+
23+
const simulate = (area) => {
24+
const getAdjacentAcres = (x, y) => {
25+
const minimumX = x - 1 < 0 ? 0 : x - 1;
26+
const maximumX = x + 2 > area.length ? area.length : x + 2;
27+
const acres = [
28+
...(area[y - 1] || []).slice(minimumX, maximumX),
29+
area[y][x - 1],
30+
area[y][x + 1],
31+
...(area[y + 1] || []).slice(minimumX, maximumX),
32+
];
33+
34+
return acres.filter((acre) => acre);
35+
};
36+
37+
const output = Array
38+
.from({ length: area.length })
39+
.map(() => Array.from({ length: area.length }));
40+
41+
for (let y = 0; y < area.length; y++) {
42+
for (let x = 0; x < area.length; x++) {
43+
const adjacentAcres = getAdjacentAcres(x, y);
44+
const nextState = computeNextState(area[y][x], adjacentAcres);
45+
46+
output[y][x] = nextState;
47+
}
48+
}
49+
50+
return output;
51+
};
52+
53+
module.exports = (input, simulations = 10) => {
54+
const simulationArea = input
55+
.split('\n')
56+
.map((line) => line
57+
.trim()
58+
.split('')
59+
);
60+
61+
let output = simulationArea;
62+
63+
for (let i = 0; i < simulations; i++) {
64+
output = simulate(output);
65+
}
66+
67+
const flattenedOutput = [].concat.apply([], output);
68+
69+
const trees = countTrees(flattenedOutput);
70+
const lumberyards = countLumberyards(flattenedOutput);
71+
72+
return trees * lumberyards;
73+
};
+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const assert = require('assert');
2+
3+
const settlers = require('./settlers');
4+
5+
const displayHelper = (expectedOutput) => expectedOutput.replace(/^ +/gm, '');
6+
7+
describe('Day 18: Settlers of The North Pole', () => {
8+
it('should simulate 1 minute', () => {
9+
const input = displayHelper(
10+
`.#.#...|#.
11+
.....#|##|
12+
.|..|...#.
13+
..|#.....#
14+
#.#|||#|#|
15+
...#.||...
16+
.|....|...
17+
||...#|.#|
18+
|.||||..|.
19+
...#.|..|.`);
20+
21+
assert.strictEqual(settlers(input, 1), 480);
22+
});
23+
24+
it('should simulate 10 minutes', () => {
25+
const input = displayHelper(
26+
`.#.#...|#.
27+
.....#|##|
28+
.|..|...#.
29+
..|#.....#
30+
#.#|||#|#|
31+
...#.||...
32+
.|....|...
33+
||...#|.#|
34+
|.||||..|.
35+
...#.|..|.`);
36+
37+
assert.strictEqual(settlers(input, 10), 1147);
38+
});
39+
});

0 commit comments

Comments
 (0)