expeditaet
Version:
Advent of Code Solutions
66 lines (59 loc) • 1.96 kB
text/typescript
import { task } from '@alexaegis/advent-of-code-lib';
import { Graph, GraphNode } from '@alexaegis/advent-of-code-lib/model';
import packageJson from '../package.json';
const pathContains = (
path: GraphNode<string, number>[],
node: GraphNode<string, number>,
atMost = 1,
): boolean => {
return path.count((pathNode) => pathNode.value === node.value) >= atMost;
};
const getPaths = (
current: GraphNode<string, number>,
until: (node: GraphNode<string, number>) => boolean,
allPaths: GraphNode<string, number>[][],
visitTwice: string | undefined,
path: GraphNode<string, number>[] = [],
): void => {
path.push(current);
if (until(current)) {
allPaths.push(path);
return;
}
for (const neighbour of current) {
if (
neighbour.to.value === 'start' ||
(neighbour.to.value.isLowerCase() &&
pathContains(path, neighbour.to, neighbour.to.value === visitTwice ? 2 : 1))
) {
continue;
}
getPaths(neighbour.to, until, allPaths, visitTwice, [...path]);
}
};
/**
* Find all unique paths from start to end
* @param input
* @returns
*/
export const p2 = (input: string): number => {
const valueEdges = input.lines().map((line) => {
const [from, to] = line.splitIntoStringPair('-');
return { from, to };
});
const graph = Graph.fromUniqueValueEdges<string>(valueEdges, (t) => t, true);
const start = graph.getNode('start');
if (!start) {
throw new Error('No start node!');
}
const smallCaves = [...graph.nodes.values()].filter((node) => node.value.isLowerCase());
const allPaths: GraphNode<string, number>[][] = smallCaves.flatMap((smallCave) => {
const paths: GraphNode<string, number>[][] = [];
getPaths(start, (node) => node.value === 'end', paths, smallCave.value);
return paths;
});
const renderedPaths = allPaths.map((p) => p.map((e) => e.value).join(','));
const uniqueRenderedPaths = renderedPaths.unique();
return uniqueRenderedPaths.length;
};
await task(p2, packageJson.aoc); // 98441 ~42s