import {Range, Seq, Set} from "immutable"; import fs from "fs"; type Position = [number, number]; type GalaxyPair = [Position, Position]; export class Observatory { private grid: string[][] = []; private expandedRows: number[] = []; private expandedColumns: number[] = []; constructor(input: string) { this.grid = input.split('\n').map(line => line.split('')); this.expandGrid(); } private expandGrid() { this.expandedColumns = Range(0, this.grid[0].length).filter(column => this.grid.every(row => row[column] === '.')).toArray(); this.expandedRows = Range(0, this.grid.length).filter(row => this.grid[row].every(column => column === '.')).toArray(); } public get shortestPaths(): number { const distances = this.pairs.map(pair => this.distanceBetween(pair[0], pair[1])); return distances.reduce((sum, distance) => sum + distance, 0); } private get pairs(): GalaxyPair[] { const galaxies = this.grid.reduce((galaxies, row, rowIndex) => { row.forEach((galaxy, columnIndex) => { if (galaxy === '#') { galaxies.push([rowIndex, columnIndex]); } }); return galaxies; }, [] as Position[]); return galaxies.reduce((pairs, galaxy, index) => { return pairs.withMutations(pairs => { galaxies.slice(index + 1).forEach(otherGalaxy => { pairs.add([galaxy, otherGalaxy]); }); }) }, Set()).toArray(); } private range = (a: number, b: number): Seq.Indexed => { return Range(Math.min(a, b), Math.max(a, b) + 1); } public distanceBetween(galaxyOne: Position, galaxyTwo: Position): number { const expansion = 999_999; const xRange = this.range(galaxyOne[0], galaxyTwo[0]).filter(row => this.expandedRows.includes(row)).toArray().length; const yRange = this.range(galaxyOne[1], galaxyTwo[1]).filter(column => this.expandedColumns.includes(column)).toArray().length; const expansions = expansion * (xRange + yRange) return Math.abs(galaxyOne[0] - galaxyTwo[0]) + Math.abs(galaxyOne[1] - galaxyTwo[1]) + expansions; } } export const runDayEleven = () => { const input = fs.readFileSync('./inputs/day_eleven_input.txt', 'utf-8').trimEnd(); const observatory = new Observatory(input); console.log(`The shortest path between every galaxy is ${observatory.shortestPaths}`); }