Sfoglia il codice sorgente

Add day 3 part ii solution

ApisNecros 1 anno fa
parent
commit
b0f8657c6a
1 ha cambiato i file con 130 aggiunte e 0 eliminazioni
  1. 130 0
      3/3_2.ts

+ 130 - 0
3/3_2.ts

@@ -0,0 +1,130 @@
+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;
+}