Readme

https://adventofcode.com/2023/day/5

Oh boy, what a tedious one. I don't see any quick and easy optimization strategies here. the parsing is the most tedious part of this.

The first part went way more smoothly than I initially thought, by splitting the different steps into smaller pieces.

But the second part is a hard nut to crack. So many runtime/performance issues because the numbers are so "big" that my intail approach no longer works.

Last nut I finally cracked was in v28 by running the following on a powerful desktop machine for nearly an hour: deno run https://esm.town/v/karfau/aoc23_05?v=28 (that is the module URL) to get the correct solution.

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
import { expect } from "https://esm.town/v/karfau/chai";
type MapMap = Record<number, { dest: number; last: number; len: number }>;
const toInt = (s: string) => parseInt(s);
const extractNumbers = (line: string) => line.match(/\d+/g).map(toInt);
const parseMap = (lines: string) =>
lines.split("\n")
.map(extractNumbers)
.sort(([, s1], [, s2]) => s1 - s2)
.reduce<MapMap>((acc, [dest, source_start, len]) => {
acc[source_start] = { last: source_start + len - 1, dest, len };
return acc;
}, {});
const useMap = (numbers: number[], map: MapMap) => {
const starts = Object.keys(map).map(toInt);
return numbers.map(num => {
const start = starts.find(start => start <= num && map[start].last >= num);
if (start === undefined) return num;
return map[start].dest - start + num;
});
};
const sample = `seeds: 79 14 55 13
seed-to-soil map:
50 98 2
52 50 48
soil-to-fertilizer map:
0 15 37
37 52 2
39 0 15
fertilizer-to-water map:
49 53 8
0 11 42
42 0 7
57 7 4
water-to-light map:
88 18 7
18 25 70
light-to-temperature map:
45 77 23
81 45 19
68 64 13
temperature-to-humidity map:
0 69 1
1 0 69
humidity-to-location map:
60 56 37
56 93 4`;
expect(
firstStar(sample),
"*1 sample 1",
).to.equal(35);
// expect(firstStar(``), "*1 sample 2").to.equal("?");
function firstStar(input: string) {
const [, seedsInput, ...mapsInput] = input.split(/\s*[a-z -]+:\s*/m);
const seeds = extractNumbers(seedsInput);
const maps = mapsInput.map(parseMap);
return Math.min(...maps.reduce(useMap, seeds));
}
// as as soon as the assertions pass, the solution is calculated
console.log("solution *1:", firstStar(input()));
expect(secondStar(sample), "*2 sample 1").to.equal(46);
// expect(secondStar(``), "*1 sample 2").to.equal("?");
function secondStar(input: string) {
const [, seedsInput, ...mapsInput] = input.split(/\s*[a-z -]+:\s*/m);
const maps = mapsInput.map(parseMap);
const seedPairs = extractNumbers(seedsInput);
let seedsMin = Number.MAX_SAFE_INTEGER;
for (let i = 0; i < seedPairs.length; i += 2) {
const start = seedPairs[i], len = seedPairs[i + 1], stop = start + len;
const batchsize = 100_000;
let arr = Array(batchsize);
for (let j = start; j < stop; j += batchsize) {
const s = debug(Math.min(batchsize, stop - 1 - j), `seeds ${j} / ${stop} (#${i}/${seedPairs.length})`);
const seeds = (arr.length !== s ? Array(s) : arr).fill(j).map((v, i) => v + i);
seedsMin = Math.min(seedsMin, ...maps.reduce(useMap, seeds));
}
}
return seedsMin;
}
console.log("solution *2:", secondStar(input()));
function input() {
return `seeds: 3121711159 166491471 3942191905 154855415 3423756552 210503354 2714499581 312077252 1371898531 165242002 752983293 93023991 3321707304 21275084 949929163 233055973 3626585 170407229 395618482 226312891
seed-to-soil map:
522866878 679694818 556344137
1206934522 1236038955 57448427
2572695651 3529213882 270580892
1082547209 29063229 124387313
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
December 7, 2023