use std::io::{self, Read}; #[derive(Clone, Copy)] enum State { Group, Garbage, Ignore, } fn scan(input: &str) -> (usize, usize) { let mut score = 0; let mut garbage = 0; let mut indendation = 0; let mut states = Vec::new(); for ch in input.chars() { let state = *states.last().unwrap_or(&State::Group); match (state, ch) { // Group (State::Group, '{') => { indendation += 1; } (State::Group, '}') => { score += indendation; indendation -= 1; states.pop(); } (State::Group, '<') => { states.push(State::Garbage); } (State::Group, '!') => { states.push(State::Ignore); } // Garbage (State::Garbage, '>') => { states.pop(); } (State::Garbage, '!') => { states.push(State::Ignore); } (State::Garbage, _) => { garbage += 1; } // Ignore (State::Ignore, _) => { states.pop(); } _ => (), } } (score, garbage) } fn main() { let mut input = String::new(); io::stdin() .read_to_string(&mut input) .expect("faild to read input"); let (score, garbage) = scan(&input); println!("part_one={}", score); println!("part_two={}", garbage); } #[cfg(test)] mod tests { use super::*; #[test] fn test_score() { assert_eq!(scan("{}"), (1, 0)); assert_eq!(scan("{{{}}}"), (6, 0)); assert_eq!(scan("{{},{}}"), (5, 0)); assert_eq!(scan("{{{},{},{{}}}}"), (16, 0)); assert_eq!(scan("{,,,}"), (1, 4)); assert_eq!(scan("{{},{},{},{}}"), (9, 8)); assert_eq!(scan("{{},{},{},{}}"), (9, 0)); assert_eq!(scan("{{},{},{},{}}"), (3, 17)); } #[test] fn test_garbage() { assert_eq!(scan("<>"), (0, 0)); assert_eq!(scan(""), (0, 17)); assert_eq!(scan("<<<<>"), (0, 3)); assert_eq!(scan("<{!>}>"), (0, 2)); assert_eq!(scan(""), (0, 0)); assert_eq!(scan(">"), (0, 0)); assert_eq!(scan(r#"<{o"i!a,<{i"#), (0, 10)); } }