Эх сурвалжийг харах

Preserve copy of failed solution

ApisNecros 1 жил өмнө
parent
commit
00c13cbe05
1 өөрчлөгдсөн 267 нэмэгдсэн , 0 устгасан
  1. 267 0
      5/failed_5_1.ts

+ 267 - 0
5/failed_5_1.ts

@@ -0,0 +1,267 @@
+import { ExtractNumbers, Inspect, LoadInput } from "../common.ts";
+
+/**
+ * While this script does work for the test case, the challenge input
+ * is too large, and causes the JS engine to run out of memory.
+ */
+
+const tests = [
+    "seeds: 79 14 55 13",
+    "",
+    "seed-to-soil map:",
+    "50 98 2",
+    "52 50 48",
+    "",
+    "soil-to-fertilizer map:",
+    "0 15 37",
+    "37 52 2",
+    "39 0 15",
+    "",
+    "fertilizer-to-water map:",
+    "49 53 8",
+    "0 11 42",
+    "42 0 7",
+    "57 7 4",
+    "",
+    "water-to-light map:",
+    "88 18 7",
+    "18 25 70",
+    "",
+    "light-to-temperature map:",
+    "45 77 23",
+    "81 45 19",
+    "68 64 13",
+    "",
+    "temperature-to-humidity map:",
+    "0 69 1",
+    "1 0 69",
+    "",
+    "humidity-to-location map:",
+    "60 56 37",
+    "56 93 4",
+];
+
+const input = await LoadInput(5);
+
+// Parse the input
+const maps = ParseInput(input);
+
+// Map the seeds
+const seeds = maps.Seeds.map((seed) => MapSeed(seed.ID, maps));
+
+// Get the output
+let closestLocationID = Number.MAX_SAFE_INTEGER;
+if (isSeedMapArray(seeds)) {
+     seeds.forEach((seed) => {
+        if (seed.LocationID < closestLocationID) { closestLocationID = seed.LocationID; }
+    });
+}
+
+console.log(`The lowest location ID found is: ${closestLocationID}`);
+
+function ParseInput(almanac: string[]): RangeMaps {
+    /** An empty initializer for our output */
+    const output: RangeMaps = {
+        Seeds: [],
+        SeedToSoil: [],
+        SoilToFertilizer: [],
+        FertilizerToWater: [],
+        WaterToLight: [],
+        LightToTemperature: [],
+        TemperatureToHumidity: [],
+        HumidityToLocation: [],
+    };
+
+    for (let i = 0; i < almanac.length; i++) {
+        let line = almanac[i];
+
+        // Parse the seed ID's
+        if (/^seeds:/.test(line)) {
+            // Extract all numbers from the line
+            const seedIDs = ExtractNumbers(line);
+            // Add to the output's Seeds array a new Seed for each number
+            seedIDs.forEach((id) => { output.Seeds.push({ID: id}); });
+            // Skip the next blank
+            i++;
+        }
+        // Parse the Seed to Soil ranges
+        else if (/^seed\-to/.test(line)) {
+            output.SeedToSoil = ParseSourceDestinationRange(++i, almanac);
+        }
+        // Parse the Soil to Fertilizer ranges
+        else if (/^soil\-to/.test(line)) {
+            output.SoilToFertilizer = ParseSourceDestinationRange(++i, almanac);
+        }
+        // Parse the Fertilizer to Water ranges
+        else if (/^fertilizer\-to/.test(line)) {
+            output.FertilizerToWater = ParseSourceDestinationRange(++i, almanac);
+        }
+        // Parse the Water to Light ranges
+        else if (/^water\-to/.test(line)) {
+            output.WaterToLight = ParseSourceDestinationRange(++i, almanac);
+        }
+        // Parse the Light to Temperature ranges
+        else if (/^light\-to/.test(line)) {
+            output.LightToTemperature = ParseSourceDestinationRange(++i, almanac);
+        }
+        // Parse the Temperature to Humidity ranges
+        else if (/^temperature\-to/.test(line)) {
+            output.TemperatureToHumidity = ParseSourceDestinationRange(++i, almanac);
+        }
+        // Parse the Humidity to Location ranges
+        else if (/^humidity\-to/.test(line)) {
+            output.HumidityToLocation = ParseSourceDestinationRange(++i, almanac);
+        }
+    }
+
+    return output;
+}
+
+/**
+ * Helper function to parse the ranges for each mappable section
+ *
+ * @param {number} lineNumber The line number to begin parsing from
+ * @param {string[]} almanac The complete almanac
+ * @returns {MappableObject[]} A list of mapped indices
+ */
+function ParseSourceDestinationRange(lineNumber: number, almanac: string[]): MappableObject[] {
+    const rangeMap: MappableObject[] = [];
+    do {
+        // Get the values out of the line
+        const [destinationRangeStart, sourceRangeStart, rangeLength] = ExtractNumbers(almanac[lineNumber]);
+        
+        // Create the ranges
+        for (let idx = 0; idx < rangeLength; idx++) {
+            rangeMap.push({
+                ID: sourceRangeStart + idx,
+                PointsTo: destinationRangeStart + idx,
+            });
+        }
+    } while(almanac[++lineNumber]);
+    
+    return rangeMap;
+}
+
+/**
+ * Find an IdentifiableObject by its ID number
+ *
+ * @param needle The ID number to find
+ * @param haystack The list to find the ID in
+ * @returns {IdentifiableObject|undefined} The object by that ID if found, or undefined
+ */
+function FindObjectByID(needle: number, haystack: IdentifiableObject[]|MappableObject[]): IdentifiableObject|MappableObject|undefined {
+    return haystack.find((obj) => obj.ID == needle);
+}
+
+/**
+ * Map a Seed ID to all of its other attributes
+ *
+ * Given a seed ID, finds its soil type, fertilizer type, water type,
+ * light type, temperature type, humidity type, and location ID.
+ *
+ * @param {number} seedID 
+ * @param {RangeMaps} rangeMaps A parsed map of ranges
+ * @returns 
+ */
+function MapSeed(seedID: number, rangeMaps: RangeMaps): SeedMap|undefined {
+    // Make sure the seed with that ID exists before continueing
+    if(!FindObjectByID(seedID, rangeMaps.Seeds)) { return undefined; }
+    
+    // Initialize our seed map object
+    const seed: SeedMap = {
+        ID: seedID,
+        SoilID: 0,
+        FertilizerID: 0,
+        WaterID: 0,
+        LightID: 0,
+        TemperatureID: 0,
+        HumidityID: 0,
+        LocationID: 0,
+    };
+
+    seed.SoilID =        (FindObjectByID(seedID, rangeMaps.SeedToSoil) as MappableObject)?.PointsTo || seedID;
+    seed.FertilizerID =  (FindObjectByID(seed.SoilID, rangeMaps.SoilToFertilizer) as MappableObject)?.PointsTo || seed.SoilID;
+    seed.WaterID =       (FindObjectByID(seed.FertilizerID, rangeMaps.FertilizerToWater) as MappableObject)?.PointsTo || seed.FertilizerID;
+    seed.LightID =       (FindObjectByID(seed.WaterID, rangeMaps.WaterToLight) as MappableObject)?.PointsTo || seed.WaterID;
+    seed.TemperatureID = (FindObjectByID(seed.LightID, rangeMaps.LightToTemperature) as MappableObject)?.PointsTo|| seed.LightID;
+    seed.HumidityID =    (FindObjectByID(seed.TemperatureID, rangeMaps.TemperatureToHumidity) as MappableObject)?.PointsTo || seed.TemperatureID;
+    seed.LocationID =    (FindObjectByID(seed.HumidityID, rangeMaps.HumidityToLocation) as MappableObject)?.PointsTo || seed.HumidityID;
+
+    return seed;
+}
+
+/**
+ * Type guard function to ensure an array is an array of SeedMaps
+ *
+ * @param {any[]} valueArray The array to check
+ * @returns {boolean} Whether the input is an array of SeedMaps or not
+ */
+function isSeedMapArray(valueArray: any[]): valueArray is SeedMap[] {
+    const value = valueArray.shift();
+
+    if (!value || typeof value !== "object") { return false; }
+
+    return Object.hasOwn(value, "ID")
+        && Object.hasOwn(value, "SoilID")
+        && Object.hasOwn(value, "FertilizerID")
+        && Object.hasOwn(value, "WaterID")
+        && Object.hasOwn(value, "LightID")
+        && Object.hasOwn(value, "TemperatureID")
+        && Object.hasOwn(value, "HumidityID")
+        && Object.hasOwn(value, "LocationID");
+}
+
+/** Any object with a unique identifier */
+interface IdentifiableObject {
+    /** The ID number for this object */
+    ID: number,
+};
+
+/** A seed */
+interface Seed extends IdentifiableObject {};
+
+/** An IdentifiableObject that points to another IdentifiableObject */
+interface MappableObject extends IdentifiableObject {
+    /** The ID that this object points to */
+    PointsTo: number,
+};
+
+/** A complete map of all object IDs and where they point to */
+type RangeMaps = {
+    /** The list of seed IDs */
+    Seeds: Seed[],
+    /** The map of seed to soil IDs */
+    SeedToSoil: MappableObject[],
+    /** The map of soil to fertilizer IDs */
+    SoilToFertilizer: MappableObject[],
+    /** The map of fertilizer to water IDs */
+    FertilizerToWater: MappableObject[],
+    /** The map of water to light IDs */
+    WaterToLight: MappableObject[],
+    /** The map of light to temperature IDs */
+    LightToTemperature: MappableObject[],
+    /** The map of temperature to humidity IDs */
+    TemperatureToHumidity: MappableObject[],
+    /** The map of humidity to location IDs */
+    HumidityToLocation: MappableObject[],
+}
+
+/** A completed map of a seed's property IDs */
+type SeedMap = {
+    /** The ID of the seed */
+    ID: number,
+    /** The ID of the soil type the seed needs planted in */
+    SoilID: number,
+    /** The ID of the fertilizer type the soil needs */
+    FertilizerID: number,
+    /** The ID of the water type the fertilizer needs */
+    WaterID: number,
+    /** The ID of the light type the water needs */
+    LightID: number,
+    /** The ID of the temperature type the light needs */
+    TemperatureID: number,
+    /** The ID of the humidity type the temperature needs */
+    HumidityID: number,
+    /** The ID of the location the humidity needs */
+    LocationID: number,
+}