1- (* Read the lines of the file into a string list*)
2- let lines name = In_channel. input_lines (open_in name)
3- let is_digit d = d > = '0' && d < = '9'
1+ (* read_lines reads each line in the file into a string list*)
2+ let read_lines file = In_channel. input_lines (In_channel. open_text file)
3+ let first_digit line = line.[Str. search_forward (Str. regexp " [0-9]" ) line 0 ]
4+
5+ let last_digit line =
6+ line.[Str. search_backward (Str. regexp " [0-9]" ) line (String. length line - 1 )]
7+
8+ let is_digit c = Char. code c > = Char. code '0' && Char. code c < = Char. code '9'
49let to_digit c = Char. code c - Char. code '0'
510
6- (* First digit and last digit *)
7- let fst_lst s =
8- let rec first_digit s i =
9- if is_digit s.[i] then s.[i] else first_digit s (i + 1 )
11+ let part1_calibration_sum file =
12+ let calibration_value line =
13+ (10 * to_digit (first_digit line)) + to_digit (last_digit line)
1014 in
11- let rec last_digit s i =
12- if is_digit s.[i] then s.[i] else last_digit s (i - 1 )
13- in
14- (first_digit s 0 , last_digit s (String. length s - 1 ))
15-
16- let calib_value s =
17- let fst, lst = fst_lst s in
18- (10 * to_digit fst) + to_digit lst
15+ let calibration_list file = List. map calibration_value (read_lines file) in
16+ List. fold_left ( + ) 0 (calibration_list file)
1917
20- let digit_words =
18+ let word_to_digit =
2119 [
2220 (" zero" , 0 );
2321 (" one" , 1 );
@@ -31,26 +29,42 @@ let digit_words =
3129 (" nine" , 9 );
3230 ]
3331
34- (* iterate through the string character by character and find the possible numbers*)
32+ let rec check_start line word_map i =
33+ match word_map with
34+ | [] -> None
35+ | h :: t ->
36+ if
37+ String. starts_with ~prefix: (fst h)
38+ (String. sub line i (String. length line - i))
39+ then Some (snd h)
40+ else check_start line t i
3541
36- let substr s i = String. sub s i (String. length s - i)
42+ let rec check_end line word_map i =
43+ match word_map with
44+ | [] -> None
45+ | h :: t ->
46+ if String. ends_with ~suffix: (fst h) (String. sub line 0 (i + 1 )) then
47+ Some (snd h)
48+ else check_end line t i
3749
38- let string_begins_with s i =
39- List. find_map
40- (fun (word , value ) ->
41- if String. starts_with ~prefix: word (substr s i) then Some value else None )
42- digit_words
50+ let rec parse_first_digit line i =
51+ if is_digit line.[i] then to_digit line.[i]
52+ else
53+ match check_start line word_to_digit i with
54+ | None -> parse_first_digit line (i + 1 )
55+ | Some a -> a
4356
44- let match_digit s i =
45- if is_digit s.[i] then Some (to_digit s.[i]) else string_begins_with s i
57+ let rec parse_last_digit line i =
58+ if is_digit line.[i] then to_digit line.[i]
59+ else
60+ match check_end line word_to_digit i with
61+ | None -> parse_last_digit line (i - 1 )
62+ | Some a -> a
4663
47- let find_vals line =
48- let rec first i =
49- match match_digit line i with Some digit -> digit | None -> first (i + 1 )
50- in
51- let rec last i =
52- match match_digit line i with Some digit -> digit | None -> last (i - 1 )
53- in
54- let first_digit = first 0 in
55- let last_digit = last (String. length line - 1 ) in
56- (first_digit * 10 ) + last_digit
64+ let vals line =
65+ (parse_first_digit line 0 , parse_last_digit line (String. length line - 1 ))
66+
67+ let part2_calibration_sum file =
68+ let calibration_value line = (10 * fst (vals line)) + snd (vals line) in
69+ let calibration_list file = List. map calibration_value (read_lines file) in
70+ List. fold_left ( + ) 0 (calibration_list file)
0 commit comments