import fs from "fs"; type Grid = Tile[][]; type Cell = [number, number]; type Tile = 'S' | 'F' | 'J' | 'L' | '7' | '-' | '|' | '.'; const isTile = (value: string): value is Tile => { return ['S', 'F', 'J', 'L', '7', '-', '|', '.'].includes(value); } const toString = (cell: Cell): string => { return cell.toString(); } const getStart = (grid: Grid): Cell => { const row = grid.findIndex(row => row.includes('S')); const col = grid[row].findIndex(cell => cell === 'S'); return [row, col]; } const getSurrounding = (grid: Grid, [row, col]: Cell): Cell[] => { return ([ [row - 1, col], [row + 1, col], [row, col - 1], [row, col + 1], [row - 1, col - 1], [row - 1, col + 1], [row + 1, col - 1], [row + 1, col + 1], ] as Cell[]).filter((cell) => { const valid = isValid(grid, cell); const neighbour = neighbours(grid, cell).map(toString); return valid && neighbour.includes([row, col].toString()); }); } const neighbours = (grid: Grid, [row, col]: Cell): Cell[] => { const value = grid[row][col]; switch (value) { case 'F': return [ [row, col + 1], [row + 1, col], ]; case 'J': return [ [row - 1, col], [row, col - 1] ]; case 'L': return [ [row, col + 1], [row - 1, col] ]; case '7': return [ [row + 1, col], [row, col - 1] ]; case '-': return [ [row, col + 1], [row, col - 1] ]; case '|': return [ [row - 1, col], [row + 1, col] ]; default: return []; } } const isValid = (grid: Grid, [row, col]: Cell): boolean => { return row >= 0 && row < grid.length && col >= 0 && col < grid[row].length && grid[row][col] !== '.'; } export const getFurthestDistance = (input: string): number => { const grid = input.split('\n').map(line => line.split('').filter(isTile)); const start = getStart(grid); const queue = getSurrounding(grid, start); console.log(start, queue); const visited = new Set([start.toString()]); while (queue.length > 0) { const current = queue.shift()!; const next = neighbours(grid, current); next.forEach(cell => { if (!visited.has(cell.toString()) && isValid(grid, cell)) { queue.push(cell); visited.add(cell.toString()); } }); } return visited.size / 2; } export const runDayTen = () => { const input = fs.readFileSync('./inputs/day_ten_input.txt', 'utf8').trimEnd(); const result = getFurthestDistance(input); console.log(`Day Ten: ${result}`); }