2023-12-02 01:01:55 +00:00
/ *
2023-12-02 01:11:44 +00:00
-- - Day 1 : Trebuchet? ! -- -
2023-12-02 01:01:55 +00:00
2023-12-02 01:11:44 +00:00
Something is wrong with global snow production , and you 've been selected to take a look. The Elves have even given you a map; on it, they' ve used stars to mark the top fifty locations that are likely to be having problems .
You ' ve been doing this long enough to know that to restore snow operations , you need to check all fifty stars by December 25 th .
Collect stars by solving puzzles . Two puzzles will be made available on each day in the Advent calendar ; the second puzzle is unlocked when you complete the first . Each puzzle grants one star . Good luck !
You try to ask why they can 't just use a weather machine ("not powerful enough") and where they' re even sending you ( "the sky" ) and why your map looks mostly blank ( "you sure ask a lot of questions" ) and hang on did you just say the sky ( "of course, where do you think snow comes from" ) when you realize that the Elves are already loading you into a trebuchet ( "please hold still, we need to strap you in" ) .
As they ' re making the final adjustments , they discover that their calibration document ( your puzzle input ) has been amended by a very young Elf who was apparently just excited to show off her art skills . Consequently , the Elves are having trouble reading the values on the document .
The newly - improved calibration document consists of lines of text ; each line originally contained a specific calibration value that the Elves now need to recover . On each line , the calibration value can be found by combining the first digit and the last digit ( in that order ) to form a single two - digit number .
For example :
1 abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet
In this example , the calibration values of these four lines are 12 , 38 , 15 , and 77 . Adding these together produces 142 .
Consider your entire calibration document . What is the sum of all of the calibration values ?
2023-12-02 01:01:55 +00:00
* /
2023-12-02 01:11:44 +00:00
2023-12-02 01:57:47 +00:00
import { sum , allIndicesOf } from "../../_utils" ;
2023-12-02 01:11:44 +00:00
const extractDigits = ( s : string ) : string = > s . replaceAll ( /[a-zA-Z]/g , "" ) ;
const firstLast = ( s : string ) : number = > + ` ${ s [ 0 ] } ${ s [ s . length - 1 ] } ` ;
2023-12-02 01:01:55 +00:00
export function part1_solver ( lines : string [ ] ) : number {
2023-12-02 01:11:44 +00:00
return lines
. map ( extractDigits )
. map ( firstLast )
. filter ( ( x ) = > ! isNaN ( x ) )
. reduce ( sum , 0 ) ;
2023-12-02 01:01:55 +00:00
}
/ *
2023-12-02 01:11:44 +00:00
-- - Part Two -- -
Your calculation isn ' t quite right . It looks like some of the digits are actually spelled out with letters : one , two , three , four , five , six , seven , eight , and nine also count as valid "digits" .
Equipped with this new information , you now need to find the real first and last digit on each line . For example :
2023-12-02 01:01:55 +00:00
2023-12-02 01:11:44 +00:00
two1nine
eightwothree
abcone2threexyz
xtwone3four
4 nineeightseven2
zoneight234
7 pqrstsixteen
In this example , the calibration values are 29 , 83 , 13 , 24 , 42 , 14 , and 76 . Adding these together produces 281 .
What is the sum of all of the calibration values ?
2023-12-02 01:01:55 +00:00
* /
2023-12-02 01:11:44 +00:00
const digits = [
"one" ,
"two" ,
"three" ,
"four" ,
"five" ,
"six" ,
"seven" ,
"eight" ,
"nine" ,
] ;
type Match = {
digitNum : number ;
startPos : number ;
} ;
const wordsToDigits = ( s : string ) : string = > {
let res = "" ;
// Find the starting indices of all word numbers in the string
const matches : Match [ ] = digits . reduce ( ( indices , digitStr , i ) = > {
const digitNum = i + 1 ;
const matchedIndices = allIndicesOf ( s , digitStr ) ;
return [
. . . indices ,
. . . matchedIndices . map ( ( startPos ) = > ( { digitNum , startPos } ) ) ,
] ;
} , [ ] as Match [ ] ) ;
// Sort the starting indices so we process the matches in order
matches . sort ( ( a , b ) = > a . startPos - b . startPos ) ;
// For each match...
// 1. Append the characters between the last match to the current match, unmodified.
// 2. Append the numerical value of the digit string to the result.
// 3. Update the last match value for the next iteration.
let lastmatch = 0 ;
matches . forEach ( ( match ) = > {
res = res + s . slice ( lastmatch , match . startPos ) ;
res = res + match . digitNum ;
lastmatch = match . startPos + digits [ match . digitNum - 1 ] . length ;
} ) ;
// In case there are no more matches, but the string contains more random characters...
// append the rest of them to the result.
if ( lastmatch < s . length ) {
res = res + s . slice ( lastmatch , s . length ) ;
}
return res ;
} ;
2023-12-02 01:01:55 +00:00
export function part2_solver ( lines : string [ ] ) : number {
2023-12-02 01:11:44 +00:00
return part1_solver ( lines . map ( wordsToDigits ) ) ;
2023-12-02 01:01:55 +00:00
}