···
const file = await Bun.file("../../shared/06/input.txt").text();
2
-
const problems: string[][] = file
5
-
.map((row) => row.split(/\s+/));
2
+
const problemsArray: (string | ("*" | "+"))[][] = (() => {
3
+
const rows = file.trimEnd().split("\n");
4
+
const dataRows = rows.slice(0, rows.length - 1); // exclude operator row when detecting split columns
7
-
const problemsArray: (number | ("*" | "+"))[][] = [];
9
-
for (let i = 0; i < (problems.at(0)?.length as number); i++) {
10
-
const localArray: (number | ("*" | "+"))[] = [];
12
-
for (let j = 0; j < problems.length; j++) {
13
-
localArray.push(problems.at(j)?.at(i) as number | ("*" | "+"));
6
+
// 1) Find whitespace columns across all data rows
7
+
const maxLen = Math.max(...dataRows.map((r) => r.length));
8
+
const splitCols: number[] = [];
9
+
for (let i = 0; i < maxLen; i++) {
11
+
for (const row of dataRows) {
12
+
const ch = i < row.length ? row[i] : " "; // virtual pad short rows
13
+
if (ch !== " " && ch !== "\t") {
18
+
if (allWS) splitCols.push(i);
16
-
problemsArray.push(localArray);
21
+
// 2) Split each row at those columns, including the split whitespace in the left segment
22
+
const cuts = Array.from(new Set(splitCols)).sort((a, b) => a - b);
23
+
const segmentedRows: string[][] = rows.map((row) => {
24
+
const segs: string[] = [];
26
+
for (const cut of cuts) {
27
+
const end = Math.min(cut + 1, row.length); // keep the whitespace column with the left segment
28
+
segs.push(row.slice(start, end));
31
+
segs.push(row.slice(start)); // remainder
35
+
// 3) Transpose rows -> columns
36
+
return segmentedRows.reduce<(string | ("*" | "+"))[][]>((cols, row) => {
37
+
row.forEach((cell, i) => {
38
+
(cols[i] ??= []).push(cell as string | ("*" | "+"));
problemsArray.forEach((problem) => {
22
-
const operator = problem.pop() as "*" | "+";
47
+
const localProblem = [...problem];
48
+
const operator = localProblem.pop()?.trim() as "*" | "+";
24
-
const nums = problem.map((val) => Number.parseInt(val as string, 10));
50
+
const nums = localProblem.map((val) =>
51
+
Number.parseInt(val.trim() as string, 10),
26
-
total += nums.reduce((acc, curr) =>
54
+
const value = nums.reduce((acc, curr) =>
operator === "*" ? acc * curr : acc + curr,
···
67
+
problemsArray.forEach((problem) => {
68
+
const localProblem = [...problem];
69
+
const operator = localProblem.pop()?.trim() as "*" | "+";
71
+
const maxWidth = localProblem.reduce((m, s) => Math.max(m, s.length), 0);
73
+
const cephNums: number[] = [];
74
+
for (let colR = 0; colR <= maxWidth; colR++) {
77
+
for (let r = 0; r < localProblem.length; r++) {
78
+
const s = localProblem[r] as string;
79
+
const idx = maxWidth - colR;
81
+
if (idx <= s.length - 1) {
83
+
if (ch !== " ") digits += ch;
87
+
if (digits.length > 0) {
88
+
cephNums.push(Number.parseInt(digits, 10));
94
+
? cephNums.reduce((p, n) => p * n, 1)
95
+
: cephNums.reduce((p, n) => p + n, 0);
37
-
console.log("part 2:", 0);
101
+
console.log("part 2:", total);