|
|
@ -16,29 +16,22 @@ fn main() -> Result<(), Box<Error>> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn solve(input: &str) -> Result<String, Box<Error>> {
|
|
|
|
fn solve(input: &str) -> Result<String, Box<Error>> {
|
|
|
|
let instructions: Instructions = input.parse()?;
|
|
|
|
let mut assembly: Assembly = input.parse()?;
|
|
|
|
let output = part_one(instructions).iter().map(char::to_string).collect();
|
|
|
|
let output = part_one(&mut assembly).iter().map(char::to_string).collect();
|
|
|
|
Ok(output)
|
|
|
|
Ok(output)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
fn part_two<F: Fn(char) -> usize>(assembly: Assembly, worker_count: usize, step_time: F) {}
|
|
|
|
fn part_one(instructions: Instructions) -> Vec<char> {
|
|
|
|
|
|
|
|
let mut steps = instructions.steps;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
|
|
|
fn part_one(assembly: &mut Assembly) -> Vec<char> {
|
|
|
|
let mut output = Vec::new();
|
|
|
|
let mut output = Vec::new();
|
|
|
|
while !steps.is_empty() {
|
|
|
|
while !assembly.is_done() {
|
|
|
|
let mut ready: Vec<_> = steps
|
|
|
|
let mut available = assembly.available_steps();
|
|
|
|
.iter()
|
|
|
|
available.sort();
|
|
|
|
.filter(|(_, v)| v.is_empty())
|
|
|
|
let done = *available[0];
|
|
|
|
.map(|(k, _)| k)
|
|
|
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
ready.sort();
|
|
|
|
|
|
|
|
let done = *ready[0];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
steps.remove(&done);
|
|
|
|
assembly.finish(&done);
|
|
|
|
for dependencies in steps.values_mut() {
|
|
|
|
|
|
|
|
dependencies.remove(&done);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output.push(done);
|
|
|
|
output.push(done);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -58,24 +51,44 @@ 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 instructions: Instructions = input.parse().unwrap();
|
|
|
|
let mut assembly: Assembly = input.parse().unwrap();
|
|
|
|
let output = part_one(instructions);
|
|
|
|
let output = part_one(&mut assembly);
|
|
|
|
assert_eq!(output, vec!['C', 'A', 'B', 'D', 'F', 'E']);
|
|
|
|
assert_eq!(output, vec!['C', 'A', 'B', 'D', 'F', 'E']);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct Instructions {
|
|
|
|
struct Assembly {
|
|
|
|
steps: HashMap<char, HashSet<char>>,
|
|
|
|
steps: HashMap<char, HashSet<char>>,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl FromStr for Instructions {
|
|
|
|
impl Assembly {
|
|
|
|
|
|
|
|
fn is_done(&self) -> bool {
|
|
|
|
|
|
|
|
self.steps.is_empty()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn available_steps(&self) -> Vec<&char> {
|
|
|
|
|
|
|
|
self.steps
|
|
|
|
|
|
|
|
.iter()
|
|
|
|
|
|
|
|
.filter(|(_, v)| v.is_empty())
|
|
|
|
|
|
|
|
.map(|(k, _)| k)
|
|
|
|
|
|
|
|
.collect()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn finish(&mut self, step: &char) {
|
|
|
|
|
|
|
|
self.steps.remove(step);
|
|
|
|
|
|
|
|
for dependencies in self.steps.values_mut() {
|
|
|
|
|
|
|
|
dependencies.remove(step);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl FromStr for Assembly {
|
|
|
|
type Err = Box<Error>;
|
|
|
|
type Err = Box<Error>;
|
|
|
|
|
|
|
|
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
|
|
let re = Regex::new(r"^Step (\w).*step (\w)").unwrap();
|
|
|
|
let re = Regex::new(r"^Step (\w).*step (\w)").unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
let mut steps = HashMap::new();
|
|
|
|
let mut steps = HashMap::new();
|
|
|
|
s
|
|
|
|
s.trim()
|
|
|
|
.trim()
|
|
|
|
|
|
|
|
.lines()
|
|
|
|
.lines()
|
|
|
|
.flat_map(|x| re.captures(x))
|
|
|
|
.flat_map(|x| re.captures(x))
|
|
|
|
.map(|x| {
|
|
|
|
.map(|x| {
|
|
|
@ -84,13 +97,13 @@ impl FromStr for Instructions {
|
|
|
|
.map(|x| x.as_str().chars().next().unwrap())
|
|
|
|
.map(|x| x.as_str().chars().next().unwrap())
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
.map(|x| (x[1], x[2]))
|
|
|
|
.map(|x| (x[1], x[2]))
|
|
|
|
.for_each(|(x, y)| {
|
|
|
|
.for_each(|(x, y)| {
|
|
|
|
steps.entry(x).or_insert_with(HashSet::new);
|
|
|
|
steps.entry(x).or_insert_with(HashSet::new);
|
|
|
|
let entry = steps.entry(y).or_insert_with(HashSet::new);
|
|
|
|
let entry = steps.entry(y).or_insert_with(HashSet::new);
|
|
|
|
entry.insert(x);
|
|
|
|
entry.insert(x);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
Ok(Instructions{steps})
|
|
|
|
Ok(Assembly { steps })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|