[2018][rust][07] refactor
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<Error>> {
}
fn solve(input: &str) -> Result<String, Box<Error>> {
- 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::<Vec<_>>()
- })
- .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<char> {
+ 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<String, Box<Error>> {
.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<char, HashSet<char>>,
+}
+
+impl FromStr for Instructions {
+ type Err = Box<Error>;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ 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::<Vec<_>>()
+ })
+ .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})
+ }
}