diff --git a/2017/12/src/main.rs b/2017/12/src/main.rs index 6d3f037..27c3eaa 100644 --- a/2017/12/src/main.rs +++ b/2017/12/src/main.rs @@ -1,14 +1,18 @@ -use std::io::{self, Read}; use std::collections::{HashMap, HashSet}; - +use std::io::{self, Read}; fn parse(input: &str) -> (usize, Vec) { let parts = input.split("<->").collect::>(); - let from = parts[0].trim().parse::() + let from = parts[0] + .trim() + .parse::() .expect("faild to parse from"); - let to = parts[1].split(',').filter_map(|to| to.trim().parse::().ok()).collect::>(); + let to = parts[1] + .split(',') + .filter_map(|to| to.trim().parse::().ok()) + .collect::>(); (from, to) } @@ -16,59 +20,61 @@ fn parse(input: &str) -> (usize, Vec) { fn main() { let mut input = String::new(); - io::stdin().read_to_string(&mut input) + io::stdin() + .read_to_string(&mut input) .expect("faild to read input"); - let pipes = input.lines().filter(|line| !line.is_empty()).map(parse).collect::>(); + let pipes = input + .lines() + .filter(|line| !line.is_empty()) + .map(parse) + .collect::>>(); - let mut groups = HashMap::new(); + let mut groups = Vec::new(); + let mut visited = HashSet::new(); - groups.entry(0).or_insert_with(HashSet::new).insert(0); - - loop { - let mut done = true; - - pipes.iter().for_each(|&(from, ref to)| { - let mut create = true; - - for group in groups.values_mut() { - if group.contains(&from) { - create = false; - - for id in to { - if group.insert(*id) { - done = false; - } - } - } - } - - if create { - let group = groups.entry(from).or_insert_with(HashSet::new); - - group.insert(from); - - for id in to { - group.insert(*id); - } - } - }); - - if done { - break; + for (to, from) in &pipes { + if visited.contains(&to) { + continue; } + + let mut group = HashSet::new(); + let mut visit = Vec::new(); + + group.insert(to); + visited.insert(to); + + for id in from { + visit.push(id); + } + + while let Some(id) = visit.pop() { + group.insert(id); + visited.insert(id); + + for id in pipes.get(&id).unwrap() { + if !group.contains(&id) { + visit.push(id); + } + } + } + + groups.push(group); } - println!("part_one={}", groups[&0].len()); - println!("part_two={}", groups.len()); -} + let group_0 = groups + .iter() + .find(|group| group.contains(&0)) + .expect("found no group"); + println!("part.one={}", group_0.len()); + println!("part.two={}", groups.len()); +} #[cfg(test)] mod tests { use super::*; - #[test] fn test_parse() { assert_eq!(parse("0 <-> 2"), (0, vec![2]));