import fs from "node:fs"; import { printTime, now } from "../util"; const test = false; const data = fs.readFileSync( test ? "./inputs/testinput" : "./inputs/input", "utf8" ); let timer = now.instant(); console.log( "part one:", data .split("\n") .slice(0, -1) .reduce((coll, curr, index, array) => { // 2D string matching is a pain. Let's turn it into a 1D problem! // create the columns curr.split("").forEach((s, i) => { coll[i] = coll[i] ? coll[i] + s : s; }); // create the down-left-diagonals curr.split("").forEach((s, i) => { coll[i + array.length + index] = coll[i + array.length + index] ? coll[i + array.length + index] + s : s; }); // create the down-right-diagonals curr.split("").forEach((s, i) => { coll[array.length * 4 + index - i - 2] = coll[ array.length * 4 + index - i - 2 ] ? coll[array.length * 4 + index - i - 2] + s : s; }); // include the original row return [...coll, curr]; }, Array.from({ length: test ? 10 + (10 * 4 - 2) : 140 + 140 * 4 - 2 }) as string[]) .reduce((total, curr) => { // and now just do some regexes over the set of 1D strings let matchesForward = curr.match(/XMAS/g); let matchesBackward = curr.match(/SAMX/g); if (matchesForward) { total += matchesForward.length; } if (matchesBackward) { total += matchesBackward.length; } return total; }, 0), printTime(now.instant().since(timer)) ); timer = now.instant(); console.log( "part two:", data .split("\n") .slice(0, -1) .reduce((coll, curr, index, array) => { if (index === 0 || index === array.length - 1) { // we can entirely skip the first and last rows, since there's no way to get a cross started return coll; } // look for A's curr.split("").forEach((s, i, a) => { if (i === 0 || i === a.length - 1) { // same as above, edges are useless return; } if (s === "A") { // 1 2 // A // 3 4 coll = [ ...coll, array[index - 1][i - 1] + array[index - 1][i + 1] + array[index + 1][i - 1] + array[index + 1][i + 1], ]; } }); return coll; }, [] as string[]) .reduce((coll, curr) => { // we could have just done this check above, // but it's a little more clear, although slower, // to iterate again. switch (curr) { case "MSMS": case "SSMM": case "SMSM": case "MMSS": coll += 1; default: break; } return coll; }, 0), printTime(now.instant().since(timer)) );