128 lines
2.7 KiB
TypeScript
128 lines
2.7 KiB
TypeScript
import { sumBy } from '../../utils/array.ts';
|
|
|
|
export function replace(arr: string[], x: number, y: number, char: string) {
|
|
arr[y] = arr[y].substring(0, x) + char + arr[y].substring(x + 1);
|
|
}
|
|
|
|
const directions = [
|
|
{ d: '^', x: 0, y: -1 },
|
|
{ d: '>', x: 1, y: 0 },
|
|
{ d: 'v', x: 0, y: 1 },
|
|
{ d: '<', x: -1, y: 0 }
|
|
] as const;
|
|
|
|
export function solveFirst(input: string): number {
|
|
const rows = input.split('\n');
|
|
|
|
const columnCount = rows[0].length;
|
|
const rowCount = rows.length;
|
|
|
|
let y = rows.findIndex((r) => r.indexOf('^') >= 0);
|
|
let x = rows[y].indexOf('^');
|
|
let direction = 0;
|
|
|
|
while (x >= 0 && x < columnCount && y >= 0 && y < rowCount) {
|
|
const nextX = x + directions[direction].x;
|
|
const nextY = y + directions[direction].y;
|
|
if (rows[nextY]?.[nextX] === '#') {
|
|
direction = (direction + 1) % 4;
|
|
}
|
|
|
|
replace(rows, x, y, 'X');
|
|
x += directions[direction].x;
|
|
y += directions[direction].y;
|
|
}
|
|
return sumBy(rows, (r) => [...r.matchAll(/X/g)].length);
|
|
}
|
|
|
|
export function getNextObstacle(
|
|
rows: string[],
|
|
startX: number,
|
|
startY: number,
|
|
d: number
|
|
): false | { x: number; y: number } {
|
|
let x = startX;
|
|
let y = startY;
|
|
|
|
while (true) {
|
|
const nextX = x + directions[d].x;
|
|
const nextY = y + directions[d].y;
|
|
const next = rows[nextY]?.[nextX];
|
|
if (!next) {
|
|
return false;
|
|
}
|
|
if (next === '#') {
|
|
return { x, y };
|
|
}
|
|
x = nextX;
|
|
y = nextY;
|
|
}
|
|
}
|
|
|
|
export function finishes(
|
|
rows: string[],
|
|
startX: number,
|
|
startY: number,
|
|
d: number
|
|
): boolean {
|
|
let x = startX;
|
|
let y = startY;
|
|
|
|
let i = 0;
|
|
do {
|
|
const next = getNextObstacle(rows, x, y, (d + i) % 4);
|
|
if (!next) {
|
|
return true;
|
|
}
|
|
x = next.x;
|
|
y = next.y;
|
|
i++;
|
|
|
|
// TODO: be smarter
|
|
} while (i < 1_000_000);
|
|
|
|
return false;
|
|
}
|
|
|
|
export function solveRow(
|
|
rows: string[],
|
|
row: number,
|
|
startX: number,
|
|
startY: number,
|
|
startDirection: number
|
|
) {
|
|
let found = 0;
|
|
|
|
for (let column = 0; column < rows[0].length; column++) {
|
|
if ((row === startX && column === startY) || rows[row][column] === '#') {
|
|
continue;
|
|
}
|
|
|
|
replace(rows, column, row, '#');
|
|
if (!finishes(rows, startX, startY, startDirection)) {
|
|
found++;
|
|
}
|
|
|
|
replace(rows, column, row, '.');
|
|
}
|
|
return found;
|
|
}
|
|
|
|
export function solveSecond(input: string): number {
|
|
const rows = input.split('\n');
|
|
const rowCount = rows.length;
|
|
|
|
const y = rows.findIndex((r) => r.indexOf('^') >= 0);
|
|
const x = rows[y].indexOf('^');
|
|
const direction = 0;
|
|
|
|
let found = 0;
|
|
|
|
for (let row = 0; row < rowCount; row++) {
|
|
found += solveRow(rows, row, x, y, direction);
|
|
console.log('row:', row, 'found', found);
|
|
}
|
|
|
|
return found;
|
|
}
|