diff --git a/2018/rust/src/bin/day_07.rs b/2018/rust/src/bin/day_07.rs index 895b60b..6cbc0d8 100644 --- a/2018/rust/src/bin/day_07.rs +++ b/2018/rust/src/bin/day_07.rs @@ -1,6 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::error::Error; use std::io::{self, Read}; +use std::str::FromStr; use regex::Regex; @@ -15,27 +16,16 @@ fn main() -> Result<(), Box> { } fn solve(input: &str) -> Result> { - let re = Regex::new(r"^Step (\w).*step (\w)").unwrap(); - - let mut steps = HashMap::new(); - input - .trim() - .lines() - .flat_map(|x| re.captures(x)) - .map(|x| { - x.iter() - .flat_map(|x| x) - .map(|x| x.as_str()) - .collect::>() - }) - .map(|x| (x[1], x[2])) - .for_each(|(x, y)| { - steps.entry(x).or_insert_with(HashSet::new); - let entry = steps.entry(y).or_insert_with(HashSet::new); - entry.insert(x); - }); + let instructions: Instructions = input.parse()?; + let output = part_one(instructions).iter().map(char::to_string).collect(); + Ok(output) +} + +#[allow(dead_code)] +fn part_one(instructions: Instructions) -> Vec { + let mut steps = instructions.steps; - let mut output = String::new(); + let mut output = Vec::new(); while !steps.is_empty() { let mut ready: Vec<_> = steps .iter() @@ -43,21 +33,21 @@ fn solve(input: &str) -> Result> { .map(|(k, _)| k) .collect(); ready.sort(); - let done = ready[0].clone(); + let done = *ready[0]; - steps.remove(done); + steps.remove(&done); for dependencies in steps.values_mut() { - dependencies.remove(done); + dependencies.remove(&done); } - output.push_str(done); + output.push(done); } - Ok(output) + output } #[test] -fn test_solve() { +fn test_part_one() { let input = r" Step C must be finished before step A can begin. Step C must be finished before step F can begin. @@ -68,6 +58,39 @@ Step D must be finished before step E can begin. Step F must be finished before step E can begin. "; - let output = solve(input).unwrap(); - assert_eq!(output, "CABDFE".to_string()); + let instructions: Instructions = input.parse().unwrap(); + let output = part_one(instructions); + assert_eq!(output, vec!['C', 'A', 'B', 'D', 'F', 'E']); +} + +struct Instructions { + steps: HashMap>, +} + +impl FromStr for Instructions { + type Err = Box; + + fn from_str(s: &str) -> Result { + let re = Regex::new(r"^Step (\w).*step (\w)").unwrap(); + + let mut steps = HashMap::new(); + s + .trim() + .lines() + .flat_map(|x| re.captures(x)) + .map(|x| { + x.iter() + .flat_map(|x| x) + .map(|x| x.as_str().chars().next().unwrap()) + .collect::>() + }) + .map(|x| (x[1], x[2])) + .for_each(|(x, y)| { + steps.entry(x).or_insert_with(HashSet::new); + let entry = steps.entry(y).or_insert_with(HashSet::new); + entry.insert(x); + }); + + Ok(Instructions{steps}) + } }