diff --git a/Cargo.lock b/Cargo.lock index e294d10..5a4b742 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,6 +15,7 @@ dependencies = [ name = "day1" version = "0.1.0" dependencies = [ + "aho-corasick", "regex", ] diff --git a/day1/Cargo.toml b/day1/Cargo.toml index 6f98620..29b373a 100644 --- a/day1/Cargo.toml +++ b/day1/Cargo.toml @@ -6,4 +6,5 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +aho-corasick = "1.1.2" regex = "1.10.2" diff --git a/day1/src/main.rs b/day1/src/main.rs index 1825136..db278f6 100644 --- a/day1/src/main.rs +++ b/day1/src/main.rs @@ -1,6 +1,7 @@ mod part1; +mod part2; fn main() { println!("Part1: {}", part1::main()); - println!("Part2: TODO"); + println!("Part2: {}", part2::main()); } diff --git a/day1/src/part1.rs b/day1/src/part1.rs index c649f17..29cdf08 100644 --- a/day1/src/part1.rs +++ b/day1/src/part1.rs @@ -1,17 +1,17 @@ use regex::Regex; -pub(crate) fn main() -> i32 { +pub fn main() -> i32 { parse(include_str!("input.txt")) } -pub(crate) fn parse(input: &str) -> i32 { +pub fn parse(input: &str) -> i32 { input .lines() .map(|m| calibration_values(num_from_line(m))) .sum() } -pub(crate) fn num_from_line(line: &str) -> Vec { +pub fn num_from_line(line: &str) -> Vec { Regex::new(r"(\d){1}") .unwrap() .find_iter(line) @@ -23,7 +23,7 @@ pub(crate) fn num_from_line(line: &str) -> Vec { .collect() } -pub(crate) fn calibration_values(num_vec: Vec) -> i32 { +pub fn calibration_values(num_vec: Vec) -> i32 { ([num_vec[0], num_vec[num_vec.len() - 1]]) .iter() .fold(String::new(), |a, b| a + &b.to_string()) diff --git a/day1/src/part2.rs b/day1/src/part2.rs new file mode 100644 index 0000000..ce4c758 --- /dev/null +++ b/day1/src/part2.rs @@ -0,0 +1,54 @@ +use crate::part1::calibration_values; +use aho_corasick::AhoCorasick; + +pub fn main() -> i32 { + parse(include_str!("input.txt")) +} + +pub fn parse(input: &str) -> i32 { + input + .lines() + .map(|m| calibration_values(num_from_line(m))) + .sum() +} + +pub fn num_from_line(line: &str) -> Vec { + // Convert word versions of numbers to i32, preserving order + let patterns = [ + "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "1", "2", "3", "4", + "5", "6", "7", "8", "9", + ]; + AhoCorasick::new(patterns) + .unwrap() + .find_overlapping_iter(line) + .map(|m| match patterns[m.pattern()] { + "one" => 1, + "two" => 2, + "three" => 3, + "four" => 4, + "five" => 5, + "six" => 6, + "seven" => 7, + "eight" => 8, + "nine" => 9, + any => any.parse().expect("Should work due to previous filtering"), + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn example() { + let input = "two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen"; + assert_eq!(parse(input), 281) + } +}