expeditaet
Version:
Advent of Code Solutions
142 lines (126 loc) • 3.85 kB
text/typescript
import { task } from '@alexaegis/advent-of-code-lib';
import { Graph, GraphNode, Vec2, type Vec2String } from '@alexaegis/advent-of-code-lib/model';
import packageJson from '../package.json';
import {
TileColor,
hexagonalAxialDirections,
invertedHexagonalDirections,
parse,
type HexagonalDirection,
} from './parse.function.js';
export const p2 = (input: string): number => {
const tilesToFlip = parse(input);
const g = new Graph<TileColor, HexagonalDirection>();
const center = new GraphNode<TileColor, HexagonalDirection>(
Vec2.ORIGIN.toString(),
TileColor.WHITE,
);
g.nodes.set(center.key, center);
const expandNode = (
g: Graph<TileColor, HexagonalDirection>,
node: GraphNode<TileColor, HexagonalDirection>,
key?: Vec2String,
) => {
const vs = key ?? g.nodes.findKey(node);
if (vs) {
const atCoord = new Vec2(vs as Vec2String);
for (const instruction in invertedHexagonalDirections) {
const cursor = atCoord
.clone()
.addMut(hexagonalAxialDirections[instruction as HexagonalDirection]);
// console.log('argare', cursor.toString());
const nextEdge = node.neighbours.getOrAdd(
instruction as HexagonalDirection,
() => ({
from: node,
to: g.nodes.getOrAdd(
cursor.toString(),
() =>
new GraphNode<TileColor, HexagonalDirection>(
cursor.toString(),
TileColor.WHITE,
),
),
weight: 1,
direction: instruction as HexagonalDirection,
}),
);
const nextNode = nextEdge.to;
const inv = invertedHexagonalDirections[instruction as HexagonalDirection];
nextNode.neighbours.getOrAdd(inv, () => ({
from: nextNode,
to: node,
weight: 1,
direction: inv,
}));
}
}
};
/*
const expandAllBlack = (g: Graph<TileColor, HexaDirs>) => {
for (const [key, node] of g.nodes.entries()) {
if (node.value === TileColor.BLACK) {
expandNode(g, node, key);
}
}
};*/
const flipTile = (
g: Graph<TileColor, HexagonalDirection>,
node: GraphNode<TileColor, HexagonalDirection>,
key?: Vec2String,
) => {
if (node.value === TileColor.BLACK) {
node.setValue(TileColor.WHITE);
} else {
node.setValue(TileColor.BLACK);
expandNode(g, node, key);
}
};
for (const ttf of tilesToFlip) {
let currentNode = center;
const cursor = Vec2.ORIGIN.clone();
for (const instruction of ttf) {
cursor.addMut(hexagonalAxialDirections[instruction]);
const nextEdge = currentNode.neighbours.getOrAdd(instruction, () => ({
from: currentNode,
to: g.nodes.getOrAdd(
cursor.toString(),
() =>
new GraphNode<TileColor, HexagonalDirection>(
cursor.toString(),
TileColor.WHITE,
),
),
weight: 1,
direction: instruction,
}));
const nextNode = nextEdge.to;
const inv = invertedHexagonalDirections[instruction];
nextNode.neighbours.getOrAdd(inv, () => ({
from: nextNode,
to: currentNode,
weight: 1,
direction: inv,
}));
currentNode = nextNode;
}
flipTile(g, currentNode, cursor.toString());
}
// let blackCount = [...g.nodes.values()].count((node) => node.value === TileColor.BLACK);
for (let i = 0; i < 100; i++) {
const toFlip = [...g.nodes.entries()].filter(([, node]) => {
const blackNeighbours = [...node.neighbours.values()].filter(
(neighbour) => neighbour.to.value === TileColor.BLACK,
).length;
return node.value === TileColor.BLACK
? blackNeighbours === 0 || blackNeighbours > 2
: blackNeighbours === 2;
});
for (const [key, currentNode] of toFlip) {
flipTile(g, currentNode, key as Vec2String);
}
// blackCount = [...g.nodes.values()].count((node) => node.value === TileColor.BLACK);
}
return [...g.nodes.values()].count((node) => node.value === TileColor.BLACK);
};
await task(p2, packageJson.aoc); // 4135 ~391.98ms