Skip to content

Commit f24dbc0

Browse files
committed
Added 2017 day 19
1 parent 8daa743 commit f24dbc0

File tree

4 files changed

+147
-1
lines changed

4 files changed

+147
-1
lines changed

2017/14/code.mjs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export default class {
3030
return keyString;
3131
}
3232

33-
3433
/**
3534
* Finds the number of used grid squares (part 1) or the number of regions (part 2).
3635
* @param {number} part Puzzle part.

2017/19/code.mjs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import { delay, Console, Vector2D, PixelMap } from "../../utility.mjs";
2+
3+
const pathColorIndex = 1;
4+
const pathColor = "#999999";
5+
const packetColorIndex = 2;
6+
const packetColor = "#ffffff";
7+
const letterColorIndex = 3;
8+
const letterColor = "#ffff00";
9+
10+
export default class {
11+
/**
12+
* @param {Console} solConsole Solution console.
13+
* @param {HTMLElement} visContainer Visualization container.
14+
*/
15+
constructor(solConsole, visContainer) {
16+
this.isSolving = false;
17+
this.isStopping = false;
18+
this.solConsole = typeof solConsole !== "undefined" ? solConsole : new Console();
19+
this.visContainer = visContainer;
20+
}
21+
22+
/**
23+
* Parses the puzzle input.
24+
* @param {string} input Puzzle input.
25+
* @returns {{
26+
* map: number[][],
27+
* letters: object<string,Vector2D>,
28+
* }} Map and letters.
29+
*/
30+
parse(input) {
31+
let consoleLine = this.solConsole.addLine("Parsing...");
32+
33+
let letters = {};
34+
let map = input.split(/\r?\n/).filter(e => e != "").map((line, index, lines) => {
35+
if (line.length != lines[0].length)
36+
throw new Error(`Invalid length of line ${index + 1}`);
37+
if (!/^[A-Z\-\|\+\s]+$/.test(line))
38+
throw new Error(`Invalid data in line ${index + 1}`);
39+
let symbols = line.split("");
40+
for (let x = 0; x < symbols.length; x++) {
41+
if (/[A-Z]/.test(symbols[x]))
42+
letters[symbols[x]] = new Vector2D(x, index);
43+
}
44+
return symbols.map(e => e != " " ? pathColorIndex : 0);
45+
});
46+
47+
if (map.length == 0)
48+
throw new Error("Invalid input data");
49+
50+
if (map[0].every(e => e == 0))
51+
throw new Error("Start not found");
52+
53+
consoleLine.innerHTML += " done.";
54+
return { map, letters };
55+
}
56+
57+
/**
58+
* Finds the sequence of letters along the path (part 1) or the number of steps (part 2).
59+
* @param {number} part Puzzle part.
60+
* @param {string} input Puzzle input.
61+
* @param {boolean} visualization Enable visualization.
62+
* @returns {string|number} Sequence of letters along the path (part 1) or the number of steps (part 2).
63+
*/
64+
async solve(part, input, visualization) {
65+
try {
66+
this.isSolving = true;
67+
68+
let {map, letters} = this.parse(input);
69+
70+
let mapWidth = map[0].length, mapHeight = map.length;
71+
72+
let solConsoleLine;
73+
let pixelMap = new PixelMap(mapWidth, mapHeight);
74+
if (visualization) {
75+
solConsoleLine = this.solConsole.addLine(part == 1 ? "Letter sequence: ." : "Step: 1.");
76+
this.visContainer.append(pixelMap.container);
77+
pixelMap.palette[pathColorIndex] = pathColor;
78+
pixelMap.palette[packetColorIndex] = packetColor;
79+
pixelMap.palette[letterColorIndex] = letterColor;
80+
pixelMap.draw(map);
81+
for (let letter in letters)
82+
pixelMap.drawPixel(letters[letter].x, letters[letter].y, letterColorIndex);
83+
}
84+
85+
let letterSequence = "", step = 1;
86+
let position = new Vector2D(map[0].indexOf(pathColorIndex), 0);
87+
let letter = Object.keys(letters).find(e => letters[e].equals(position));
88+
if (letter != undefined)
89+
letterSequence += letter;
90+
if (visualization)
91+
pixelMap.drawPixel(position.x, position.y, packetColorIndex);
92+
93+
let direction = new Vector2D(0, 1);
94+
let directions = [new Vector2D(1, 0), new Vector2D(0, 1), new Vector2D(-1, 0), new Vector2D(0, -1)];
95+
96+
while (1) {
97+
if (this.isStopping)
98+
return;
99+
100+
let nextPosition = [direction, ...directions.filter(e => !e.equals(direction) && !e.equals(direction.clone().multiply(-1)))]
101+
.map(dir => position.clone().add(dir))
102+
.filter(nextPosition => nextPosition.x >= 0 && nextPosition.x < mapWidth && nextPosition.y >= 0 && nextPosition.y < mapHeight && map[nextPosition.y][nextPosition.x] != 0)[0];
103+
104+
if (nextPosition == undefined)
105+
return part == 1 ? letterSequence : step;
106+
107+
step++;
108+
direction = nextPosition.clone().subtract(position);
109+
position = nextPosition;
110+
111+
letter = Object.keys(letters).find(e => letters[e].equals(position));
112+
if (letter != undefined)
113+
letterSequence += letter;
114+
115+
if (visualization && pixelMap.image[position.y][position.x] == pathColorIndex) {
116+
pixelMap.drawPixel(position.x, position.y, packetColorIndex);
117+
solConsoleLine.innerHTML = part == 1 ? `Letter sequence: ${letterSequence}.` : `Step: ${step}.`;
118+
await delay(1);
119+
}
120+
}
121+
}
122+
123+
finally {
124+
this.isSolving = false;
125+
}
126+
}
127+
128+
/**
129+
* Stops solving the puzzle.
130+
*/
131+
async stopSolving() {
132+
this.isStopping = true;
133+
while (this.isSolving)
134+
await(delay(10));
135+
this.isStopping = false;
136+
}
137+
}

2017/19/testInput.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
|
2+
| +--+
3+
A | C
4+
F---|----E|--+
5+
| | | D
6+
+B-+ +--+

tree.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,10 @@ export const years = [
470470
{
471471
name: "Day 18: Duet", path: "./2017/18", taskUrl: "https://adventofcode.com/2017/day/18",
472472
answers: {part1: 4, part2: 1}
473+
},
474+
{
475+
name: "Day 19: A Series of Tubes", path: "./2017/19", taskUrl: "https://adventofcode.com/2017/day/19",
476+
answers: {part1: "ABCDEF", part2: 38}
473477
}
474478
]
475479
},

0 commit comments

Comments
 (0)