Day 8: Resonant Collinearity
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
TypeScript
I was a little confuzzled with this one, but I managed to get it. :) Happy to know that I managed to reuse more of my code from previous days. I should write something to handle Vectors. It was sad to write my own basic, non-reusable thing.
Solution
import { AdventOfCodeSolutionFunction } from "./solutions"; // imported code: export const check_coords = (grid: Array<Array<any>>, x: number, y: number) => { return y >= grid.length || y < 0 || x >= grid[y].length || x < 0 } export const makeGridFromMultilineString = (input: string) => input.split("\n").map(st => st.trim()).map(v => v.split("")); export const MakeEmptyGenericArray = <T>(length: number, fn: (index: number) => T) => { const newArray = []; let i = 0; while (i++ < length) newArray.push(fn(i)); return newArray; } export const MakeEmptyArray = (length: number) => MakeEmptyGenericArray(length, () => 0); export const MakeEmpty2DArray = (x: number, y: number) => MakeEmptyArray(y).map(() => MakeEmptyArray(x)); // solution code type v2 = [x: number, y: number]; const Sub = (x1: number, y1: number, x2: number, y2: number): v2 => { return [x1 - x2, y1 - y2]; } const Add = (x1: number, y1: number, x2: number, y2: number): v2 => { return [x1 + x2, y1 + y2]; } export const solution_8: AdventOfCodeSolutionFunction = (input) => { const grid = makeGridFromMultilineString(input); const nodes = new Map<string, Array<v2>>(); const nodeKinds: Array<string> = []; const singleAntinodeLocations = MakeEmpty2DArray(grid.length, grid[0].length); const resonantAntinodeLocations = MakeEmpty2DArray(grid.length, grid[0].length); // find all the nodes grid.forEach((row, y) => row.forEach((item, x) => { if (item == ".") return; if (nodes.has(item)) nodes.get(item)!.push([x, y]); else { nodes.set(item, [[x, y]]); nodeKinds.push(item); } })); nodeKinds.forEach((nodeKind) => { const nodesOfKind = nodes.get(nodeKind)!; for (let bunn = 0; bunn < nodesOfKind.length; bunn++) { const first = nodesOfKind[bunn]; for (let tort = bunn + 1; tort < nodesOfKind.length; tort++) { // find antinode const second = nodesOfKind[tort]; const diff = Sub(...first, ...second); const [x1, y1] = Add(...first, ...diff); const [x2, y2] = Sub(...second, ...diff); if(!check_coords(singleAntinodeLocations, x1, y1)) singleAntinodeLocations[y1][x1]++; if(!check_coords(singleAntinodeLocations, x2, y2)) singleAntinodeLocations[y2][x2]++; // find all resonances // starting resonantAntinodeLocations[first[1]][first[0]]++; resonantAntinodeLocations[second[1]][second[0]]++; // go forward let newFirst = [x1, y1] as v2; while(!check_coords(resonantAntinodeLocations, ...newFirst)) { let [x, y] = newFirst; resonantAntinodeLocations[y][x]++; newFirst = Add(...newFirst, ...diff); } // go back newFirst = [x2, y2] as v2; while(!check_coords(resonantAntinodeLocations, ...newFirst)) { let [x, y] = newFirst; resonantAntinodeLocations[y][x]++; newFirst = Sub(...newFirst, ...diff); } } } }); const antinodeCount = (prev: number, curr: Array<number>) => prev + curr.reduce((prev, curr) => prev + (curr > 0 ? 1 : 0), 0); const part_1 = singleAntinodeLocations.reduce<number>(antinodeCount, 0); const part_2 = resonantAntinodeLocations.reduce<number>(antinodeCount, 0); return { part_1, //390 part_2, //1246 } }
Loops on loops on loops on loops…