-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday9.js
102 lines (88 loc) · 2.5 KB
/
day9.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
import { parseLinesFromFile, writeAnswer } from './helpers.js';
function persistPosition([x, y], moves) {
moves.set(`${x}_${y}`, true);
}
function initialState(numHeads = 1) {
const state = {
tailMoves: new Map(),
heads: new Array(numHeads).fill([0,0]),
tail: [0,0],
};
persistPosition(state.tail, state.tailMoves);
return state;
}
function moveCoord(dir, [x, y]) {
switch (dir) {
case 'R':
return [x+1, y];
case 'L':
return [x-1, y];
case 'U':
return [x, y-1];
case 'D':
return [x, y+1];
}
}
function isTouching([tailX, tailY], [headX, headY]) {
return Math.abs(headX - tailX) <= 1 && Math.abs(headY - tailY) <= 1;
}
function catchUp([tailX, tailY], [headX, headY]) {
let newTailX = tailX;
let newTailY = tailY;
if (Math.abs(headX - tailX) >= 1) {
const adj = headX > tailX ? 1 : -1;
newTailX = tailX + adj;
}
if (Math.abs(headY - tailY) >= 1) {
const adj = headY > tailY ? 1 : -1;
newTailY = tailY + adj;
}
return [newTailX, newTailY];
}
function moveRope(direction, state) {
let lastKnot;
let rope = [...state.heads, state.tail];
let newHeads = rope.map((knot, i) => {
if (i === 0) {
lastKnot = moveCoord(direction, knot);
return lastKnot;
}
let tail = [...knot];
if (!isTouching(tail, lastKnot)) {
tail = catchUp(tail, lastKnot);
}
lastKnot = tail;
return tail;
});
state.tail = newHeads.pop();
state.heads = newHeads;
persistPosition(state.tail, state.tailMoves);
}
function processMove(direction, count, state) {
for (let i=0; i<count; i++) {
moveRope(direction, state);
}
}
function countUniqueMoves(moves) {
return moves.size;
}
function solveProblem(filename, numHeads) {
const input = parseLinesFromFile(filename);
const state = input.reduce((current, instruction) => {
const [dir, countStr] = instruction.split(' ');
processMove(dir, parseInt(countStr, 10), current);
return current;
}, initialState(numHeads));
return countUniqueMoves(state.tailMoves);
}
function solveProblem1(filename) {
const answer = solveProblem(filename, 1);
writeAnswer(answer);
}
function solveProblem2(filename) {
const answer = solveProblem(filename, 9);
writeAnswer(answer, 2);
}
const filename = './day9.puzzle.txt';
solveProblem1(filename);
solveProblem2(filename);