diff --git a/day_10/src/lib.rs b/day_10/src/lib.rs index df1bda0..00f191c 100644 --- a/day_10/src/lib.rs +++ b/day_10/src/lib.rs @@ -8,7 +8,7 @@ pub mod day_10 { parse(include_str!("../input.txt")) } - fn closing(c: char) -> Option { + const fn closing(c: char) -> Option { if c == '[' { Some(']') } else if c == '{' { @@ -23,7 +23,11 @@ pub mod day_10 { } /// Return Ok(first illegal char), or Err(ending) for an incomplete string. - fn syntax_error(s: &str) -> Result> { + /// The function takes the stack with the earliest element being the first one pushed. + fn syntax_error(s: &str, incomplete_handle: F) -> Result + where + F: FnOnce(Vec) -> T, + { let mut stack = Vec::new(); for c in s.chars() { match closing(c) { @@ -42,13 +46,13 @@ pub mod day_10 { }, } } - stack.reverse(); - Err(stack) + let answer = incomplete_handle(stack); + Err(answer) } pub fn part_1(data: &[&str]) -> u32 { data.iter() - .map(|line| match syntax_error(line) { + .map(|line| match syntax_error(line, |_| {}) { Ok(')') => 3, Ok(']') => 57, Ok('}') => 1197, @@ -62,24 +66,30 @@ pub mod day_10 { pub fn part_2(data: &[&str]) -> u64 { let mut scores: Vec = data .iter() - .filter_map(|line| match syntax_error(line) { - Err(completion) => Some( - completion - .iter() - .map(|c| match c { - ')' => 1, - ']' => 2, - '}' => 3, - '>' => 4, - _ => { - panic!("Unexpected"); - } - }) - .fold(0, |state, new_val| state * 5 + new_val), - ), - Ok(_) => None, + .filter_map(|line| { + match syntax_error(line, |completion| { + Some( + completion + .iter() + .rev() + .map(|c| match c { + ')' => 1, + ']' => 2, + '}' => 3, + '>' => 4, + _ => { + panic!("Unexpected"); + } + }) + .fold(0, |state, new_val| state * 5 + new_val), + ) + }) { + Ok(_) => None, + Err(v) => v, + } }) .collect(); + // This can be done in linear time using two heaps, but life is too short scores.sort_unstable(); scores[scores.len() / 2] }