generated from fspoettel/advent-of-code-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
01.rs
127 lines (115 loc) · 3.8 KB
/
01.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use std::collections::HashMap;
use regex::Regex;
advent_of_code::solution!(1);
fn add_digit(digits: &mut Vec<String>, new_digit: String) {
if digits.is_empty() {
digits.push(new_digit.clone());
digits.push(new_digit.clone());
return;
}
if digits.len() == 2 {
digits.pop();
}
digits.push(new_digit.clone());
}
// split input by newline
// inspect each line
// for each line, iterate through each character
// for each character, check if it is a digit
// if it is, store it as:
// 1) the first digit (if it's the first digit)
// 2) the last digit (the most recent last digit)
// after all characters are inspected, combine the first and last digit to get the answer for that line
// sum all of the digits for each line to get the result
pub fn part_one(input: &str) -> Option<u32> {
let lines = input.split('\n');
let all_digits_summed: u32 = lines
.map(|l| -> u32 {
let characters = l.chars();
let mut digits: Vec<String> = vec![];
for c in characters {
if !c.is_numeric() {
continue;
}
add_digit(&mut digits, c.to_string());
}
digits.join("").parse::<u32>().unwrap()
})
.sum();
Some(all_digits_summed)
}
fn get_digit_from_word(word: &str) -> Option<&str> {
let word_to_digit_map = HashMap::from([
("one", "1"),
("two", "2"),
("three", "3"),
("four", "4"),
("five", "5"),
("six", "6"),
("seven", "7"),
("eight", "8"),
("nine", "9"),
]);
return word_to_digit_map.get(word).copied();
}
fn extract_digit_and_update_curr_substring(curr_substring: &mut String) -> String {
while get_digit_from_word(curr_substring).is_none() {
// pop left-most character
let chars = &mut curr_substring.chars();
chars.next();
*curr_substring = chars.as_str().to_string();
}
let digit = get_digit_from_word(&curr_substring.clone())
.unwrap()
.to_string();
digit.to_string()
}
// sliding window?
// build a substring until a digit is encountered
// once a digit is encountered, check the substring for all occurrences of digits
pub fn part_two(input: &str) -> Option<u32> {
let digits_re = Regex::new(r"(one|two|three|four|five|six|seven|eight|nine)").unwrap();
let lines = input.split('\n');
let all_digits_summed: u32 = lines
.map(|l| -> u32 {
let characters = l.chars();
let mut digits: Vec<String> = vec![];
let mut curr_substring: String = "".to_string();
for c in characters {
if c.is_numeric() {
add_digit(&mut digits, c.to_string());
continue;
}
curr_substring += &c.to_string();
while digits_re.is_match(&curr_substring) {
let digit = extract_digit_and_update_curr_substring(&mut curr_substring);
add_digit(&mut digits, digit);
// pop left-most character
let mut chars = curr_substring.chars();
chars.next();
curr_substring = chars.as_str().to_string();
}
}
digits.join("").parse::<u32>().unwrap()
})
.sum();
Some(all_digits_summed)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part_one() {
let result = part_one(&advent_of_code::template::read_file_part(
"examples", DAY, 1,
));
assert_eq!(result, Some(142));
}
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file_part(
"examples", DAY, 2,
));
assert_eq!(result, Some(281));
}
}