Improve perf of day 10 (#10)

This commit is contained in:
Patrick Stevens
2021-12-10 07:03:27 +00:00
committed by GitHub
parent 894746e8ae
commit d4ac9f7888

View File

@@ -8,7 +8,7 @@ pub mod day_10 {
parse(include_str!("../input.txt"))
}
fn closing(c: char) -> Option<char> {
const fn closing(c: char) -> Option<char> {
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<char, Vec<char>> {
/// The function takes the stack with the earliest element being the first one pushed.
fn syntax_error<F, T>(s: &str, incomplete_handle: F) -> Result<char, T>
where
F: FnOnce(Vec<char>) -> 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,10 +66,12 @@ pub mod day_10 {
pub fn part_2(data: &[&str]) -> u64 {
let mut scores: Vec<u64> = data
.iter()
.filter_map(|line| match syntax_error(line) {
Err(completion) => Some(
.filter_map(|line| {
match syntax_error(line, |completion| {
Some(
completion
.iter()
.rev()
.map(|c| match c {
')' => 1,
']' => 2,
@@ -76,10 +82,14 @@ pub mod day_10 {
}
})
.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]
}