Day Ten, Part One

This commit is contained in:
Lewis Dale 2023-12-16 10:27:51 +00:00
parent 14efab3450
commit ad781d6a6b
2 changed files with 132 additions and 0 deletions

24
src/day_ten.test.ts Normal file
View File

@ -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);
});
});

108
src/day_ten.ts Normal file
View File

@ -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<string>([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}`);
}