-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday9.js
70 lines (59 loc) · 1.74 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
import { asLines } from './util.js';
const data = asLines('../input/9.txt')[0].split('').map(c => Number(c));
const buildBlocks = (data) => {
let idCounter = 0;
return data.flatMap((_, i) => new Array(data[i]).fill(i % 2 ? '.' : idCounter++));
}
const compact = (blocks) => {
let p1 = 0;
let p2 = blocks.length - 1;
while(p1 < p2) {
while (blocks[p1] != '.' && p1 < p2 && p1 < blocks.length - 1) p1++;
while (blocks[p2] == '.' && p1 < p2 && p2 > 0) p2--;
if (p1 >= p2 || blocks[p1] != '.' || blocks[p2] == '.') break;
blocks[p1] = blocks[p2];
blocks[p2] = '.';
}
return blocks;
};
const compacted = compact(buildBlocks(data));
const checksum = (blocks) => blocks.reduce((a, b, i) => a + (b == '.' ? 0 : (i * b)));
console.log(`day9a: ${checksum(compacted)}`);
const findFile = (blocks, p) => {
if (p < 0) return [-1, -1, -1];
while(p > 0 && blocks[p] == '.') p--;
const end = p;
const id = blocks[end];
while(p > 0 && blocks[p-1] == id) p--;
const len = end - p + 1;
return [id, p, len];
}
const findFirstFit = (blocks, len, max) => {
let p = 0;
let found = 0;
while (p < max) {
if (blocks[p] == '.') found++;
else found = 0;
if (found == len) return p - found + 1;
p++;
}
return -1;
}
const compact2 = (blocks) => {
let p = blocks.length;
while(true) {
const [id, fileStart, len] = findFile(blocks, p - 1);
if (id == -1) break;
const fit = findFirstFit(blocks, len, fileStart);
if (fit != -1) {
for (let i = 0; i < len; i++) {
blocks[fit + i] = blocks[fileStart + i];
blocks[fileStart + i] = '.';
}
}
p = fileStart;
}
return blocks;
};
const compacted2 = compact2(buildBlocks(data));
console.log(`day9b: ${checksum(compacted2)}`);