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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
import { JSONHashMap } from "@/utils";
export type Pair = [number, number];
const getIntervals = (lines: string[]) => {
const maps: number[][][] = [];
for (const line of lines.slice(1, lines.length)) {
if (!line) continue;
if (line.includes("to")) {
maps.push([]);
continue;
}
const currMap = maps.at(-1);
const [dest, source, range] = line.split(" ").map((x) => parseInt(x));
if (currMap) {
currMap.push([dest, source, range]);
}
}
return maps;
};
const constructPiecewiseFn = (intervals: number[][]) => {
const fn: JSONHashMap<Pair, Pair> = new JSONHashMap();
let fromIntervals: Pair[] = [];
for (const [dest, source, range] of intervals) {
const fromI = [source, source + range - 1];
fromIntervals.push([source, source + range - 1]);
fn.set(fromI as Pair, [dest, dest + range - 1]);
}
fromIntervals = fromIntervals.sort(
([source_a], [source_b]) => source_a - source_b
);
for (let i = 0; i < fromIntervals.length - 1; i++) {
const [_start, end] = fromIntervals[i];
const [nextStart, _nextEnd] = fromIntervals[i + 1];
if (end !== nextStart - 1) {
fn.set([end + 1, nextStart - 1], [end + 1, nextStart - 1]);
}
}
if (fromIntervals[0][0] !== 0) {
const [start, _end] = fromIntervals[0];
fn.set([0, start - 1], [0, start - 1]);
}
const final: Pair = [fromIntervals.at(-1)![1] + 1, Infinity];
fn.set(final, final);
return fn
.keys()
.map((range) => [range, fn.get(range)!] as [Pair, Pair])
.sort(([[source_a]], [[source_b]]) => source_a - source_b);
};
export const compose = (f: [Pair, Pair][], g: [Pair, Pair][]) => {
const composed: [Pair, Pair][] = [];
for (const [fDomain, fRange] of f) {
const fOffset = fRange[0] - fDomain[0];
for (const [gDomain, gRange] of g) {
const gOffset = gRange[0] - gDomain[0];
const start = Math.max(fDomain[0], gDomain[0] - fOffset);
const end = Math.min(fDomain[1], gDomain[1] - fOffset);
if (start > end) continue;
composed.push([
[start, end],
[start + fOffset + gOffset, end + fOffset + gOffset],
]);
}
}
return composed;
};
export const main = async (lines: string[]): Promise<number | string> => {
const seeds = lines[0]
.split(":")
.at(1)!
.split(" ")
.filter((x) => x)
.map((x) => parseInt(x));
const intervals = getIntervals(lines);
intervals.forEach((interval, i) => {
console.log(" ==== ");
// console.log(interval);
console.log(constructPiecewiseFn(interval));
const [a, b] = [
constructPiecewiseFn(interval),
constructPiecewiseFn(intervals[i + 1]),
];
if (i === intervals.length - 1) return;
console.log(compose(a, b));
});
return 0;
};
//
const isrun = process.argv.length > 1 && process.argv[1] === import.meta.path;
if (isrun) {
const file = Bun.file("./problem.txt");
const text = await file.text();
const lines = text.split("\n").filter((x) => x && x.length);
console.log("=== COMPUTATION ===\n");
const answer = await main(lines);
console.log("\n=== /COMPUTATION ===\n");
console.log("=== ANSWER TO P2 ===");
console.log(answer);
}
|