123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- import { DeepClone, Inspect, LoadInput } from "../common.ts";
- import { BuildSchematicsMap, ParseSchematics, ValidateEngineParts, SchematicsGear as SchematicsGear, EnginePart } from "./3_common.ts";
- const tests = [
- "467..114..",
- "...*......",
- "..35..633.",
- "......#...",
- "617*......",
- ".....+.58.",
- "..592.....",
- "......755.",
- "...$.*....",
- ".664.598..",
- ];
- /**
- * Test case from /u/i_have_no_biscuits
- * @see https://www.reddit.com/r/adventofcode/comments/189q9wv/2023_day_3_another_sample_grid_to_use/
- */
- const tests_reddit = [
- "12.......*..",
- "+.........34",
- ".......-12..",
- "..78........",
- "..*....60...",
- "78..........",
- ".......23...",
- "....90*12...",
- "............",
- "2.2......12.",
- ".*.........*",
- "1.1.......56",
- ];
- const input = await LoadInput(3);
- // Build the find
- const schematics = BuildSchematicsMap(input);
- // Find all possible parts
- let engineParts = ParseSchematics(schematics);
- // Validate those parts
- engineParts = ValidateEngineParts(engineParts, schematics);
- // Find all potential gears
- let gears = FindPotentialGears(schematics);
- // Validate those gears
- gears = ValidateGears(gears, engineParts);
- // Get our output
- const sumOfGearRatios = gears.reduce((accumulator, gear) => accumulator += gear.GearRatio, 0);
- console.log(`The sum of Gear Ratios is: ${sumOfGearRatios}`);
- /**
- * Find all potential gears within a set of schematics
- *
- * A gear is any * symbol. A valid gear is any gear thats adjacent to
- * exactly two part numbers.
- *
- * @param {string[][]} schematicsMap A 2D grid of characters making up a schematic
- * @returns {SchematicsGear[]} A list of potential gears
- */
- function FindPotentialGears(schematicsMap: string[][]): SchematicsGear[] {
- const gearsInSchematics: SchematicsGear[] = [];
- for (let y = 0; y < schematicsMap.length; y++) {
- for (let x = 0; x < schematicsMap[y].length; x++) {
- // Test if the current cell is a gear
- if (/[*]/.test(schematicsMap[y][x])) {
- gearsInSchematics.push({
- Symbol: "*",
- Coordinates: {
- X: x,
- Y: y,
- },
- GearRatio: -1,
- });
- }
- }
- }
- return gearsInSchematics;
- }
- /**
- * Validate a list of gears
- *
- * A valid gear is any gear thats adjacent to exactly two part numbers.
- *
- * @param {SchematicsGear[]} potentialGears A list of potential gears to validate
- * @param {EnginePart[]} engineParts A list of valid Engine Parts from the schematics
- * @returns {SchematicsGear[]} A list of valid gears
- */
- function ValidateGears(potentialGears: SchematicsGear[], engineParts: EnginePart[]): SchematicsGear[] {
- const validGears: SchematicsGear[] = [];
- for (const gear of potentialGears) {
- // Clone the parts list so we can freely modify it
- let partsClone = DeepClone(engineParts) as EnginePart[];
- // Filter for parts that are on the same Y level as the gear, or 1 above or below the gear
- partsClone = partsClone.filter((part) => {
- return part.Coordinates[0].Y == gear.Coordinates.Y
- || part.Coordinates[0].Y - 1 == gear.Coordinates.Y
- || part.Coordinates[0].Y + 1 == gear.Coordinates.Y;
- });
- // If there aren't at least two left, then it's definitely not valid
- if (partsClone.length < 2) { continue; }
- // Filter for parts that are on the same X-level, or 1 to the right or left of the gear
- partsClone = partsClone.filter((part) => {
- for(const coord of part.Coordinates) {
- if(gear.Coordinates.X == coord.X
- || gear.Coordinates.X + 1 == coord.X
- || gear.Coordinates.X - 1 == coord.X) {
- return true;
- }
- }
- return false;
- });
- // If there are exactly two left, it's valid
- if (partsClone.length == 2 ) {
- gear.GearRatio = partsClone.reduce((accumulator, part) => accumulator *= part.PartNumber, 1);
- validGears.push(gear);
- }
- }
- return validGears;
- }
|