aoc-2024/day_5/solve_1.ts

109 lines
3.4 KiB
TypeScript
Raw Permalink Normal View History

2024-12-05 16:33:19 +09:00
export async function readFormat(path: string) {
const data = await Deno.readTextFile(path);
// assume LF line endings.
// TODO: handle CRLF line endings.
const [orderTxt, pageNumbersTxt] = data.split("\n\n");
const order = orderTxt.split("\n").map((line) => {
const [left, right] = line.split("|");
return {
left: parseInt(left.trim()),
right: parseInt(right.trim()),
};
});
const pageNumbers = pageNumbersTxt.split("\n").map((line) => {
const numbers = line.split(",");
return numbers.map((num) => parseInt(num.trim()));
});
return { order, pageNumbers };
}
// topology sort order
export function makeTopologySortOrder(
orderMap: Map<number, Set<number>>,
): number[] {
const visited = new Set<number>();
const sorted = new Array<number>();
for (const key of orderMap.keys()) {
if (!visited.has(key)) {
visit(key);
}
}
function visit(node: number) {
if (visited.has(node)) return;
visited.add(node);
const set = orderMap.get(node);
if (set) {
for (const next of set) {
visit(next);
}
}
sorted.push(node);
}
return sorted;
}
async function main() {
const path = new URL("input.txt", import.meta.url).pathname;
const { order, pageNumbers } = await readFormat(path);
// create order map
const orderMap = new Map<number, Set<number>>();
for (const { left, right } of order) {
const leftSet = orderMap.get(left) ?? new Set<number>();
leftSet.add(right);
orderMap.set(left, leftSet);
}
// it's not transitive closure...
//
// apply transitive closure
// const topologySortOrder = makeTopologySortOrder(orderMap);
// const completedSetMap = new Map<number, Set<number>>();
// for (const num of topologySortOrder) {
// // console.log(num, "\n===");
// const set = orderMap.get(num) ?? new Set<number>();
// const completedSet = completedSetMap.get(num) ?? new Set<number>();
// set.forEach((elem) => completedSet.add(elem));
// for (const next of set) {
// const nextSet = completedSetMap.get(next) ?? new Set<number>();
// nextSet.forEach((elem) => completedSet.add(elem));
// }
// console.log(completedSet);
// // console.log("===");
// completedSetMap.set(num, completedSet);
// }
const completedSetMap = orderMap;
// check order is valid or not by comparing with pageNumbers
function checkPageNumberOrder(pageNumbers: number[]): boolean {
const notAllowed = new Set<number>();
for (let i = pageNumbers.length - 1; i >= 0; i--) {
const current = pageNumbers[i];
if (notAllowed.has(current)) {
return false;
}
notAllowed.add(current);
const biggerThanCurrent = completedSetMap.get(current);
biggerThanCurrent?.forEach((elem) => notAllowed.add(elem));
}
return true;
}
let sum = 0;
for (const pages of pageNumbers) {
if (!checkPageNumberOrder(pages)) {
// console.log("invalid order", pages);
} else {
// get middle number
const middle = pages[pages.length >> 1];
sum += middle;
}
}
console.log(sum);
}
if (import.meta.main) {
main();
}