day 14 task 2

This commit is contained in:
Johannes
2019-12-14 22:01:01 +01:00
parent 83dce003d8
commit 71d068ab2c

View File

@@ -1,6 +1,7 @@
use itertools::Itertools; use itertools::Itertools;
use std::collections::HashMap; use std::collections::HashMap;
#[allow(dead_code)]
pub fn run() { pub fn run() {
fn parser(s: &str) -> Chemical { fn parser(s: &str) -> Chemical {
let (n, t) = s.split(" ").collect_tuple().unwrap(); let (n, t) = s.split(" ").collect_tuple().unwrap();
@@ -25,6 +26,36 @@ pub fn run() {
) )
}) })
.collect(); .collect();
task1(&rules);
task2(&rules);
}
fn task1(rules: &HashMap<&str, (usize, Vec<Chemical>)>) {
println!("Task 1: {} ORE is needed", calc_ore_for_fuel(1, rules));
}
fn task2(rules: &HashMap<&str, (usize, Vec<Chemical>)>) {
const ORE_STORAGE: usize = 1_000_000_000_000;
// binary search max fuel
let (max_fuel, _) = std::iter::successors(Some((1, ORE_STORAGE)), |(min, max)| {
if max - min > 1 {
let middle = (max + min) / 2;
let ore = calc_ore_for_fuel(middle, rules);
if ore > ORE_STORAGE {
Some((*min, middle))
} else {
Some((middle, *max))
}
} else {
None
}
})
.last()
.unwrap();
println!("Task 2: the maximum amount of fuel is {}", max_fuel);
}
fn calc_ore_for_fuel(fuel: usize, rules: &HashMap<&str, (usize, Vec<Chemical>)>) -> usize {
/* /*
The idea is: the rules create a DAG of requirements. The idea is: the rules create a DAG of requirements.
We store for every chemical a list of the chemicals that rely on it. We store for every chemical a list of the chemicals that rely on it.
@@ -52,7 +83,7 @@ pub fn run() {
chem_used_by.insert("FUEL", vec![]); chem_used_by.insert("FUEL", vec![]);
// the amount of a not processed chemical C, which is needed by the chemicals that rely on C // the amount of a not processed chemical C, which is needed by the chemicals that rely on C
let mut requirements = HashMap::<&str, usize>::new(); let mut requirements = HashMap::<&str, usize>::new();
requirements.insert("FUEL", 1); requirements.insert("FUEL", fuel);
while let Some((name, amount)) = requirements while let Some((name, amount)) = requirements
.iter() .iter()
.find(|(name, _)| chem_used_by[*name].is_empty() && **name != "ORE") .find(|(name, _)| chem_used_by[*name].is_empty() && **name != "ORE")
@@ -77,7 +108,7 @@ pub fn run() {
} }
requirements.remove(name); requirements.remove(name);
} }
println!("Task 1: {} ORE is needed", requirements["ORE"]); requirements["ORE"]
} }
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]