diff --git a/2023/Cargo.toml b/2023/Cargo.toml index d855299..7000a92 100644 --- a/2023/Cargo.toml +++ b/2023/Cargo.toml @@ -6,10 +6,10 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +aho-corasick = "1.1.2" anyhow = "1.0.75" clap = { version = "4.4.8", features = ["derive"] } nom = "7.1.3" -regex = "1.10.2" [dev-dependencies] criterion = "0.5.1" diff --git a/2023/src/day01.rs b/2023/src/day01.rs index e96597e..d6025f8 100644 --- a/2023/src/day01.rs +++ b/2023/src/day01.rs @@ -1,5 +1,5 @@ +use aho_corasick::AhoCorasick; use anyhow::Result; -use regex::bytes::Regex; pub fn part1(input: &[u8]) -> Result { let mut it = input.iter(); @@ -22,43 +22,35 @@ pub fn part1(input: &[u8]) -> Result { Ok(sum.to_string()) } -fn parse_string_digit(digit: &[u8]) -> Result { - Ok(match digit { - b"one" => 1, - b"two" => 2, - b"three" => 3, - b"four" => 4, - b"five" => 5, - b"six" => 6, - b"seven" => 7, - b"eight" => 8, - b"nine" => 9, - &[d] => u32::from(d - b'0'), - other => anyhow::bail!("invalid digit: {}", String::from_utf8_lossy(other)), - }) -} - -// 53255: too low pub fn part2(input: &[u8]) -> Result { - let parser = Regex::new(r"[1-9]|one|two|three|four|five|six|seven|eight|nine")?; + let parser = AhoCorasick::new([ + "1", "2", "3", "4", "5", "6", "7", "8", "9", "one", "two", "three", "four", "five", "six", + "seven", "eight", "nine", + ])?; + + fn convert_id(id: u32) -> Result { + Ok(match id { + 0..=8 => id + 1, + 9..=17 => id - 8, + _ => anyhow::bail!("unreachable"), + }) + } + let mut sum = 0; for line in input.split(|&c| c == b'\n') { let mut first = None; - let mut last = &b""[..]; - - let mut start = 0; + let mut last = 0; // Cannot use find_iter because it doesn't find overlapping matches. - while let Some(needle) = parser.find_at(line, start) { - start = needle.start() + 1; - let digit = needle.as_bytes(); + for needle in parser.find_overlapping_iter(line) { + let digit = convert_id(needle.pattern().as_u32())?; first.get_or_insert(digit); last = digit; } if let Some(first) = first { - sum += 10 * parse_string_digit(first)? + parse_string_digit(last)?; + sum += 10 * first + last; } }