advent of code 2025 in ts and nix
1const file = await Bun.file("../../shared/05/input.txt").text();
2const [freshRanges, ingredients] = file
3 .split("\n\n")
4 .map((line) => line.split("\n"));
5
6type Range = {
7 start: number;
8 end: number;
9};
10
11const parsedFreshRanges = (freshRanges as string[])
12 .map((range: string) => {
13 const [start, end] = range.split("-");
14 return {
15 start: Number.parseInt(start as string, 10),
16 end: Number.parseInt(end as string, 10),
17 };
18 })
19 .sort((a, b) => a.start - b.start) as Range[];
20
21const mergedRanges: Range[] = [];
22let current = { ...parsedFreshRanges[0] } as Range;
23
24for (let i = 1; i < parsedFreshRanges.length; i++) {
25 const next = parsedFreshRanges[i] as Range;
26
27 // check if overlapping or adjacent
28 if (current.end + 1 >= next.start) {
29 if (next.end > current.end) {
30 current.end = next.end;
31 }
32 } else {
33 mergedRanges.push(current);
34 current = { ...next };
35 }
36}
37
38mergedRanges.push(current);
39
40const parsedIngredients = ingredients
41 ?.map((incredient) => Number.parseInt(incredient, 10))
42 .sort((a, b) => a - b) as number[];
43
44(() => {
45 let freshCount = 0;
46
47 let rangeIndex = 0;
48 parsedIngredients.forEach((ingredient) => {
49 while (true) {
50 if (rangeIndex < mergedRanges.length) {
51 const range = mergedRanges.at(rangeIndex) as Range;
52
53 if (ingredient < range.start) return;
54 else if (ingredient <= range.end) {
55 freshCount++;
56 return;
57 } else {
58 rangeIndex++;
59 }
60 } else return;
61 }
62 });
63
64 // Part 1
65 console.log("part 1:", freshCount);
66})();
67
68(() => {
69 // we just need to get the distance each range covers
70 let totalFreshIds = 0;
71
72 mergedRanges.forEach((range) => {
73 totalFreshIds += range.end - range.start + 1;
74 });
75
76 // Part 2
77 console.log("part 2:", totalFreshIds);
78})();