import { LoadInput } from "../common.ts"; /** * Calculate the sum of all calibration values in a document * * @param {string[]} document All lines of a document containing calibration values * @returns {number} The sum of all calibration values found in a document */ function CalculateCalibrationSum(document: string[]): number { return document.reduce((register, currVal) => register + extractCalibrationValue(currVal), 0); } /** * Extract a calibration value from a line of text * * Extracts the first and last digit from a string of text, * concatenates the two, and returns this as the calibration value. * * If only one digit is present, the one digit is concatenated to * itself. * * Uses a lookahead regex group to handle nested words * @see https://mtsknn.fi/blog/how-to-do-overlapping-matches-with-regular-expressions/#capturing-groups-inside-lookahead-lookbehind-assertions * * @param {string} line The line of text to extract the calibration value out of * @returns {number} The two-digit calibration value hidden in that string */ function extractCalibrationValue(line: string): number { const extracter = new RegExp("(?=(one|t(?:wo|hree)|f(?:our|ive)|s(?:ix|even)|eight|nine|[0-9]))", "g"); const digitsInString = Array.from(line.matchAll(extracter), (match) => match[1]) || []; if (digitsInString.length == 0) { console.error("No digits found on line!"); console.error(line); } const firstDigit = parseNumberWordToDigit(digitsInString[0]); const secondDigit = parseNumberWordToDigit(digitsInString[digitsInString.length - 1]); return Number(firstDigit + secondDigit); } /** * Turn the word representation of a digit into that digit * * @param {string|undefined} numberString A string containing either the word of a number, or the digit * @returns {string} A string of the digit that the input represents */ function parseNumberWordToDigit(numberString: string|undefined): string { switch (numberString) { case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": return numberString; case "one": return "1"; case "two": return "2"; case "three": return "3"; case "four": return "4"; case "five": return "5"; case "six": return "6"; case "seven": return "7"; case "eight": return "8"; case "nine": return "9"; default: return "0"; } } const tests: string[] = [ "two1nine", "eightwothree", "abcone2threexyz", "xtwone3four", "4nineeightseven2", "zoneight234", "7pqrstsixteen", "3pqrstsevenine", ]; const input = await LoadInput(1); console.log("Test Cases"); console.log("Expected: 320") console.log(`Actual: ${CalculateCalibrationSum(tests)}\n`); console.log("Input"); console.log(`Your *true* calibration sum: ${CalculateCalibrationSum(input)}`);