use std::str::FromStr; use crate::Day; pub struct Day10(Vec>, Vec<(usize, Bracket)>); impl Day for Day10 { fn init(content: String) -> anyhow::Result { let l = content.lines().map(|x| x.chars().map(|x| x.to_string().parse().unwrap()).collect::>()).collect::>(); Ok(Self(l.clone(), gather_part1(l))) } fn part1(&self) -> anyhow::Result { Ok(format!("{}", self.1.iter().map(|&(_, b)| { match b { Bracket::Round => 3, Bracket::Square => 57, Bracket::Curly => 1197, Bracket::Angle => 25137, } }).sum::())) } fn part2(&self) -> anyhow::Result { let mut wrongs = self.1.clone(); let mut zz = self.0.clone(); wrongs.sort_unstable(); wrongs.iter().rev().for_each(|&(x, _)| std::mem::drop(zz.remove(x))); let mut scores = Vec::new(); for z in zz { let mut stack = Vec::new(); for bracket in z { match bracket { BracketType::Open(x) => stack.push(x), BracketType::Close(x) => { if let Some(y) = stack.pop() { assert_eq!(y, x); } } } } stack.reverse(); let mut score = 0_u64; for b in stack { score *= 5; score += match b { Bracket::Round => 1, Bracket::Square => 2, Bracket::Curly => 3, Bracket::Angle => 4, } } scores.push(score); } scores.sort_unstable(); Ok(format!("{:?}", scores[scores.len() / 2])) } } fn gather_part1(v: Vec>) -> Vec<(usize, Bracket)> { let mut wrongs = Vec::new(); for (idx, brackets) in v.iter().enumerate() { let mut stack = Vec::new(); for &bracket in brackets { match bracket { BracketType::Open(x) => stack.push(x), BracketType::Close(x) => { if let Some(y) = stack.pop() { if x != y { wrongs.push((idx, x)); break; } } } } } } wrongs } impl FromStr for BracketType { type Err = (); fn from_str(s: &str) -> Result { match s { "(" => Ok(BracketType::Open(Bracket::Round)), "[" => Ok(BracketType::Open(Bracket::Square)), "{" => Ok(BracketType::Open(Bracket::Curly)), "<" => Ok(BracketType::Open(Bracket::Angle)), ")" => Ok(BracketType::Close(Bracket::Round)), "]" => Ok(BracketType::Close(Bracket::Square)), "}" => Ok(BracketType::Close(Bracket::Curly)), ">" => Ok(BracketType::Close(Bracket::Angle)), _ => Err(()), } } } #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)] pub enum BracketType { Open(Bracket), Close(Bracket), } #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone, Debug)] pub enum Bracket { Round, Square, Curly, Angle, } #[cfg(test)] mod tests { use crate::{Day, day_tests}; use crate::day10::Day10; const INPUT: &str = r"[({(<(())[]>[[{[]{<()<>> [(()[<>])]({[<{<<[]>>( {([(<{}[<>[]}>{[]{[(<()> (((({<>}<{<{<>}{[]{[]{} [[<[([]))<([[{}[[()]]] [{[{({}]{}}([{[{{{}}([] {<[[]]>}<{[{[{[]{()[[[] [<(<(<(<{}))><([]([]() <{([([[(<>()){}]>(<<{{ <{([{{}}[<[[[<>{}]]]>[]]"; #[test] fn part1_test() -> anyhow::Result<()> { let d = Day10::init(INPUT.to_string())?; assert_eq!("26397", d.part1()?); Ok(()) } #[test] fn part2_test() -> anyhow::Result<()> { let d = Day10::init(INPUT.to_string())?; assert_eq!("288957", d.part2()?); Ok(()) } day_tests!(Day10, "10", "392421", "2769449099"); }