5_1.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { ExtractNumbers, Inspect } from "../common.ts";
  2. const tests = [
  3. "seeds: 79 14 55 13",
  4. "",
  5. "seed-to-soil map:",
  6. "50 98 2",
  7. "52 50 48",
  8. "",
  9. "soil-to-fertilizer map:",
  10. "0 15 37",
  11. "37 52 2",
  12. "39 0 15",
  13. "",
  14. "fertilizer-to-water map:",
  15. "49 53 8",
  16. "0 11 42",
  17. "42 0 7",
  18. "57 7 4",
  19. "",
  20. "water-to-light map:",
  21. "88 18 7",
  22. "18 25 70",
  23. "",
  24. "light-to-temperature map:",
  25. "45 77 23",
  26. "81 45 19",
  27. "68 64 13",
  28. "",
  29. "temperature-to-humidity map:",
  30. "0 69 1",
  31. "1 0 69",
  32. "",
  33. "humidity-to-location map:",
  34. "60 56 37",
  35. "56 93 4",
  36. ];
  37. const maps = ParseInput(tests);
  38. const demoSeed = FindObjectByID(14, maps.Seeds);
  39. Inspect(demoSeed);
  40. const demoSoil = FindObjectByID(demoSeed?.ID || 0, maps.SeedToSoil);
  41. Inspect(demoSoil);
  42. function ParseInput(almanac: string[]): RangeMaps {
  43. /** An empty initializer for our output */
  44. const output: RangeMaps = {
  45. Seeds: [],
  46. SeedToSoil: [],
  47. SoilToFertilizer: [],
  48. FertilizerToWater: [],
  49. WaterToLight: [],
  50. LightToTemperature: [],
  51. TemperatureToHumidity: [],
  52. HumidityToLocation: [],
  53. };
  54. /** A translation map for range titles to RangeMap keys*/
  55. for (let i = 0; i < almanac.length; i++) {
  56. let line = almanac[i];
  57. // Parse the seed ID's
  58. if (/^seeds:/.test(line)) {
  59. // Extract all numbers from the line
  60. const seedIDs = ExtractNumbers(line);
  61. // Add to the output's Seeds array a new Seed for each number
  62. seedIDs.forEach((id) => { output.Seeds.push({ID: id}); });
  63. // Skip the next blank
  64. i++;
  65. }
  66. // Parse the Seed to Soil ranges
  67. else if (/^seed\-to/.test(line)) {
  68. output.SeedToSoil = ParseSourceDestinationRange(++i, almanac);
  69. }
  70. // Parse the Soil to Fertilizer ranges
  71. else if (/^soil\-to/.test(line)) {
  72. output.SoilToFertilizer = ParseSourceDestinationRange(++i, almanac);
  73. }
  74. // Parse the Fertilizer to Water ranges
  75. else if (/^fertilizer\-to/.test(line)) {
  76. output.FertilizerToWater = ParseSourceDestinationRange(++i, almanac);
  77. }
  78. // Parse the Water to Light ranges
  79. else if (/^water\-to/.test(line)) {
  80. output.WaterToLight = ParseSourceDestinationRange(++i, almanac);
  81. }
  82. // Parse the Light to Temperature ranges
  83. else if (/^light\-to/.test(line)) {
  84. output.LightToTemperature = ParseSourceDestinationRange(++i, almanac);
  85. }
  86. // Parse the Temperature to Humidity ranges
  87. else if (/^temperature\-to/.test(line)) {
  88. output.TemperatureToHumidity = ParseSourceDestinationRange(++i, almanac);
  89. }
  90. // Parse the Humidity to Location ranges
  91. else if (/^humidity\-to/.test(line)) {
  92. output.HumidityToLocation = ParseSourceDestinationRange(++i, almanac);
  93. }
  94. }
  95. return output;
  96. }
  97. /**
  98. * Helper function to parse the ranges for each mappable section
  99. *
  100. * @param {number} lineNumber The line number to begin parsing from
  101. * @param {string[]} almanac The complete almanac
  102. * @returns {MappableObject[]} A list of mapped indices
  103. */
  104. function ParseSourceDestinationRange(lineNumber: number, almanac: string[]): MappableObject[] {
  105. const rangeMap: MappableObject[] = [];
  106. do {
  107. // Get the values out of the line
  108. const [destinationRangeStart, sourceRangeStart, rangeLength] = ExtractNumbers(almanac[lineNumber]);
  109. // Create the ranges
  110. for (let idx = 0; idx < rangeLength; idx++) {
  111. rangeMap.push({
  112. ID: sourceRangeStart + idx,
  113. PointsTo: destinationRangeStart + idx,
  114. });
  115. }
  116. } while(almanac[++lineNumber]);
  117. return rangeMap;
  118. }
  119. function FindObjectByID(needle: number, haystack: IdentifiableObject[]): IdentifiableObject|undefined {
  120. return haystack.find((obj) => obj.ID == needle);
  121. }
  122. interface IdentifiableObject {
  123. ID: number,
  124. };
  125. interface Seed extends IdentifiableObject {};
  126. interface MappableObject extends IdentifiableObject {
  127. PointsTo: number,
  128. };
  129. type RangeMaps = {
  130. Seeds: Seed[],
  131. SeedToSoil: MappableObject[],
  132. SoilToFertilizer: MappableObject[],
  133. FertilizerToWater: MappableObject[],
  134. WaterToLight: MappableObject[],
  135. LightToTemperature: MappableObject[],
  136. TemperatureToHumidity: MappableObject[],
  137. HumidityToLocation: MappableObject[],
  138. }