1_2.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import { LoadInput } from "../common.ts";
  2. /**
  3. * Calculate the sum of all calibration values in a document
  4. *
  5. * @param {string[]} document All lines of a document containing calibration values
  6. * @returns {number} The sum of all calibration values found in a document
  7. */
  8. function CalculateCalibrationSum(document: string[]): number {
  9. return document.reduce((register, currVal) => register + extractCalibrationValue(currVal), 0);
  10. }
  11. /**
  12. * Extract a calibration value from a line of text
  13. *
  14. * Extracts the first and last digit from a string of text,
  15. * concatenates the two, and returns this as the calibration value.
  16. *
  17. * If only one digit is present, the one digit is concatenated to
  18. * itself.
  19. *
  20. * Uses a lookahead regex group to handle nested words
  21. * @see https://mtsknn.fi/blog/how-to-do-overlapping-matches-with-regular-expressions/#capturing-groups-inside-lookahead-lookbehind-assertions
  22. *
  23. * @param {string} line The line of text to extract the calibration value out of
  24. * @returns {number} The two-digit calibration value hidden in that string
  25. */
  26. function extractCalibrationValue(line: string): number {
  27. const extracter = new RegExp("(?=(one|t(?:wo|hree)|f(?:our|ive)|s(?:ix|even)|eight|nine|[0-9]))", "g");
  28. const digitsInString = Array.from(line.matchAll(extracter), (match) => match[1]) || [];
  29. if (digitsInString.length == 0) {
  30. console.error("No digits found on line!");
  31. console.error(line);
  32. }
  33. const firstDigit = parseNumberWordToDigit(digitsInString[0]);
  34. const secondDigit = parseNumberWordToDigit(digitsInString[digitsInString.length - 1]);
  35. return Number(firstDigit + secondDigit);
  36. }
  37. /**
  38. * Turn the word representation of a digit into that digit
  39. *
  40. * @param {string|undefined} numberString A string containing either the word of a number, or the digit
  41. * @returns {string} A string of the digit that the input represents
  42. */
  43. function parseNumberWordToDigit(numberString: string|undefined): string {
  44. switch (numberString) {
  45. case "0":
  46. case "1":
  47. case "2":
  48. case "3":
  49. case "4":
  50. case "5":
  51. case "6":
  52. case "7":
  53. case "8":
  54. case "9":
  55. return numberString;
  56. case "one":
  57. return "1";
  58. case "two":
  59. return "2";
  60. case "three":
  61. return "3";
  62. case "four":
  63. return "4";
  64. case "five":
  65. return "5";
  66. case "six":
  67. return "6";
  68. case "seven":
  69. return "7";
  70. case "eight":
  71. return "8";
  72. case "nine":
  73. return "9";
  74. default:
  75. return "0";
  76. }
  77. }
  78. const tests: string[] = [
  79. "two1nine",
  80. "eightwothree",
  81. "abcone2threexyz",
  82. "xtwone3four",
  83. "4nineeightseven2",
  84. "zoneight234",
  85. "7pqrstsixteen",
  86. "3pqrstsevenine",
  87. ];
  88. const input = await LoadInput(1);
  89. console.log("Test Cases");
  90. console.log("Expected: 320")
  91. console.log(`Actual: ${CalculateCalibrationSum(tests)}\n`);
  92. console.log("Input");
  93. console.log(`Your *true* calibration sum: ${CalculateCalibrationSum(input)}`);