|
|
@ -1,6 +1,7 @@
|
|
|
|
use std::collections::{HashMap, HashSet};
|
|
|
|
use std::collections::{HashMap, HashSet};
|
|
|
|
use std::error::Error;
|
|
|
|
use std::error::Error;
|
|
|
|
use std::io::{self, Read};
|
|
|
|
use std::io::{self, Read};
|
|
|
|
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
|
|
|
|
use regex::Regex;
|
|
|
|
use regex::Regex;
|
|
|
|
|
|
|
|
|
|
|
@ -15,27 +16,16 @@ fn main() -> Result<(), Box<Error>> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn solve(input: &str) -> Result<String, Box<Error>> {
|
|
|
|
fn solve(input: &str) -> Result<String, Box<Error>> {
|
|
|
|
let re = Regex::new(r"^Step (\w).*step (\w)").unwrap();
|
|
|
|
let instructions: Instructions = input.parse()?;
|
|
|
|
|
|
|
|
let output = part_one(instructions).iter().map(char::to_string).collect();
|
|
|
|
|
|
|
|
Ok(output)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let mut steps = HashMap::new();
|
|
|
|
#[allow(dead_code)]
|
|
|
|
input
|
|
|
|
fn part_one(instructions: Instructions) -> Vec<char> {
|
|
|
|
.trim()
|
|
|
|
let mut steps = instructions.steps;
|
|
|
|
.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 mut output = String::new();
|
|
|
|
let mut output = Vec::new();
|
|
|
|
while !steps.is_empty() {
|
|
|
|
while !steps.is_empty() {
|
|
|
|
let mut ready: Vec<_> = steps
|
|
|
|
let mut ready: Vec<_> = steps
|
|
|
|
.iter()
|
|
|
|
.iter()
|
|
|
@ -43,21 +33,21 @@ fn solve(input: &str) -> Result<String, Box<Error>> {
|
|
|
|
.map(|(k, _)| k)
|
|
|
|
.map(|(k, _)| k)
|
|
|
|
.collect();
|
|
|
|
.collect();
|
|
|
|
ready.sort();
|
|
|
|
ready.sort();
|
|
|
|
let done = ready[0].clone();
|
|
|
|
let done = *ready[0];
|
|
|
|
|
|
|
|
|
|
|
|
steps.remove(done);
|
|
|
|
steps.remove(&done);
|
|
|
|
for dependencies in steps.values_mut() {
|
|
|
|
for dependencies in steps.values_mut() {
|
|
|
|
dependencies.remove(done);
|
|
|
|
dependencies.remove(&done);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
output.push_str(done);
|
|
|
|
output.push(done);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Ok(output)
|
|
|
|
output
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[test]
|
|
|
|
fn test_solve() {
|
|
|
|
fn test_part_one() {
|
|
|
|
let input = r"
|
|
|
|
let input = r"
|
|
|
|
Step C must be finished before step A can begin.
|
|
|
|
Step C must be finished before step A can begin.
|
|
|
|
Step C must be finished before step F 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.
|
|
|
|
Step F must be finished before step E can begin.
|
|
|
|
";
|
|
|
|
";
|
|
|
|
|
|
|
|
|
|
|
|
let output = solve(input).unwrap();
|
|
|
|
let instructions: Instructions = input.parse().unwrap();
|
|
|
|
assert_eq!(output, "CABDFE".to_string());
|
|
|
|
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})
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|