Files
advent-of-code/day-6/day6.ts
2024-12-06 15:10:38 +01:00

195 lines
3.8 KiB
TypeScript

enum Direction {
UP = 0,
DOWN = 1,
LEFT = 2,
RIGHT = 3,
}
type Coordinates = [number, number];
type Grid = string[][];
function getNextCellCoordinates(
coordinates: Coordinates,
direction: Direction,
): Coordinates {
const [x, y] = coordinates;
if (direction === Direction.UP) {
return [x - 1, y];
}
if (direction === Direction.DOWN) {
return [x + 1, y];
}
if (direction === Direction.LEFT) {
return [x, y - 1];
}
return [x, y + 1];
}
function isPathFinished(
coordinates: Coordinates,
height: number,
width: number,
) {
const [x, y] = coordinates;
if (x === -1 || y === -1 || x === height || y === width) {
return true;
}
return false;
}
function getNewDirection(prev: Direction) {
switch (prev) {
case Direction.LEFT:
return Direction.UP;
case Direction.RIGHT:
return Direction.DOWN;
case Direction.DOWN:
return Direction.LEFT;
case Direction.UP:
return Direction.RIGHT;
}
}
export function day6(input: string) {
const grid = input.split("\n").map((line) => line.split(""));
const HEIGHT = grid.length;
const WIDTH = grid[0].length;
let direction = Direction.UP;
let startCoords: Coordinates | null = null;
const path: Coordinates[] = [];
for (let i = 0; i < grid.length; i++) {
const line = grid[i];
for (let j = 0; j < line.length; j++) {
const cell = line[j];
if (cell !== "^") {
continue;
}
startCoords = [i, j];
break;
}
}
if (!startCoords) {
throw new Error("no starting point");
}
path.push(startCoords);
let isFinished = false;
while (!isFinished) {
const prev = path.at(-1);
if (!prev) {
throw new Error("never");
}
const [nextX, nextY] = getNextCellCoordinates(prev, direction);
isFinished = isPathFinished([nextX, nextY], HEIGHT, WIDTH);
if (isFinished) {
break;
}
const nextCellContent = grid[nextX][nextY];
if (nextCellContent === "#") {
direction = getNewDirection(direction);
} else {
path.push([nextX, nextY]);
}
}
const filtered = path.filter(
(o, index, arr) =>
arr.findIndex((item) => item[0] === o[0] && item[1] === o[1]) === index,
);
return filtered.length;
}
export function day6part2(input: string) {
let count = 0;
const grid = input.split("\n").map((line) => line.split(""));
for (let i = 0; i < grid.length; i++) {
const line = grid[i];
for (let j = 0; j < line.length; j++) {
const newGrid = structuredClone(grid);
const currentValue = newGrid[i][j];
if (currentValue === "#" || currentValue === "^") {
continue;
}
newGrid[i][j] = "#";
const isLoop = checkInput(newGrid);
if (isLoop) count++;
}
}
return count;
}
export function checkInput(grid: Grid) {
const HEIGHT = grid.length;
const WIDTH = grid[0].length;
let direction = Direction.UP;
let startCoords: Coordinates | null = null;
const path: Coordinates[] = [];
const seen = new Set();
for (let i = 0; i < grid.length; i++) {
const line = grid[i];
for (let j = 0; j < line.length; j++) {
const cell = line[j];
if (cell !== "^") {
continue;
}
startCoords = [i, j];
break;
}
}
if (!startCoords) {
throw new Error("no starting point");
}
path.push(startCoords);
const s = sc(startCoords, direction);
seen.add(s);
let isFinished = false;
while (!isFinished) {
const prev = path.at(-1);
if (!prev) {
throw new Error("never");
}
const [nextX, nextY] = getNextCellCoordinates(prev, direction);
isFinished = isPathFinished([nextX, nextY], HEIGHT, WIDTH);
if (isFinished) {
isFinished = true;
break;
}
const nextCellContent = grid[nextX][nextY];
if (nextCellContent === "#") {
direction = getNewDirection(direction);
} else {
const s = sc([nextX, nextY], direction);
const x = seen.has(s);
if (x) {
return true;
}
seen.add(s);
path.push([nextX, nextY]);
}
}
}
function sc(c: Coordinates, dir: Direction) {
return [...c, dir].join(",");
}