diff --git a/src/day_ten.test.ts b/src/day_ten.test.ts new file mode 100644 index 0000000..879a79b --- /dev/null +++ b/src/day_ten.test.ts @@ -0,0 +1,24 @@ +import {getFurthestDistance} from "./day_ten"; + +describe('Day Ten', () => { + it.each([ + [`..... +.S-7. +.|.|. +.L-J. +.....`, 4], [ + `-L|F7 +7S-7| +L|7|| +-L-J| +L|-JF`, 4], + [`..F7. +.FJ|. +SJ.L7 +|F--J +LJ...`, 8] + ])('should calculate the number of steps to the exit', (input, expected) => { + const result = getFurthestDistance(input); + expect(result).toEqual(expected); + }); +}); \ No newline at end of file diff --git a/src/day_ten.ts b/src/day_ten.ts new file mode 100644 index 0000000..4bbc092 --- /dev/null +++ b/src/day_ten.ts @@ -0,0 +1,108 @@ +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}`); +} \ No newline at end of file