day 4 done
This commit is contained in:
103
04/index.ts
Normal file
103
04/index.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
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 down rows
|
||||
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 crosses
|
||||
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))
|
||||
);
|
Reference in New Issue
Block a user