import fs from "node:fs"; import { printTime, now } from "../util"; type Coord = [number, number]; const test = false; const data = fs.readFileSync( test ? "./inputs/testinput" : "./inputs/input", "utf8" ); let timer = now.instant(); console.log( "part one:", Object.entries( data .split("\n") .slice(0, -1) .reduce((m, curr, row) => { curr.split("").forEach((v, col) => { if (v !== ".") { m[v] = m[v] ? [...m[v], [row, col]] : [[row, col]]; } }); return m; }, {} as Record>) ) .map(([_, locations]) => { return locations.reduce((antinodes, curr, i, array) => { return [ ...antinodes, ...array.slice(i + 1).reduce((total, next) => { return [ ...total, [ curr[0] - Math.abs(curr[0] - next[0]), curr[1] > next[1] ? curr[1] + Math.abs(curr[1] - next[1]) : curr[1] - Math.abs(curr[1] - next[1]), ] as Coord, [ next[0] + Math.abs(curr[0] - next[0]), curr[1] < next[1] ? next[1] + Math.abs(curr[1] - next[1]) : next[1] - Math.abs(curr[1] - next[1]), ] as Coord, ]; }, [] as Array), ]; }, [] as Array); }) .map((antinodes) => { return antinodes.filter((antinode) => { let maxWidth = test ? 12 : 50; return !( antinode[0] < 0 || antinode[1] < 0 || antinode[0] >= maxWidth || antinode[1] >= maxWidth ); }); }) .flat() // merge the frequencies // because arrays are not comparable, we need to filter out duplicates after strigifying them .map((v) => JSON.stringify(v)) .reduce((total, v, i, a) => { return a.indexOf(v) === i ? total + 1 : total; }, 0), printTime(now.instant().since(timer)) ); timer = now.instant(); console.log( "part two:", Object.entries( data .split("\n") .slice(0, -1) .reduce((m, curr, row) => { curr.split("").forEach((v, col) => { if (v !== ".") { m[v] = m[v] ? [...m[v], [row, col]] : [[row, col]]; } }); return m; }, {} as Record>) ) .map(([_, locations]) => { return locations.reduce((antinodes, curr, i, array) => { return [ ...antinodes, curr, // include the antennas themselves ...array.slice(i + 1).reduce((total, next) => { // draw the line north... let localCurr = curr; while (localCurr[0] > 0 && localCurr[1] > 0) { let k = total.push([ localCurr[0] - Math.abs(localCurr[0] - next[0]), localCurr[1] > next[1] ? localCurr[1] + Math.abs(localCurr[1] - next[1]) : localCurr[1] - Math.abs(localCurr[1] - next[1]), ]); next = localCurr; localCurr = total[k - 1]; } return total; }, [] as Array), ...array.slice(i + 1).reduce((total, next) => { // ...and south let localCurr = curr; while (next[0] < (test ? 12 : 50) && next[1] < (test ? 12 : 50)) { let k = total.push([ next[0] + Math.abs(localCurr[0] - next[0]), localCurr[1] < next[1] ? next[1] + Math.abs(localCurr[1] - next[1]) : next[1] - Math.abs(localCurr[1] - next[1]), ]); localCurr = next; next = total[k - 1]; } return total; }, [] as Array), ]; }, [] as Array); }) .map((antinodes) => { return antinodes.filter((antinode) => { let maxWidth = test ? 12 : 50; return !( antinode[0] < 0 || antinode[1] < 0 || antinode[0] >= maxWidth || antinode[1] >= maxWidth ); }); }) .flat() .map((v) => JSON.stringify(v)) .reduce((total, v, i, a) => { return a.indexOf(v) === i ? total + 1 : total; }, 0), printTime(now.instant().since(timer)) );