day-14.rs (2900B)
1 use std::collections::HashMap; 2 use std::fs::File; 3 use std::io::prelude::*; 4 use std::io::BufReader; 5 6 fn main() { 7 let input = BufReader::new(File::open("input.txt").unwrap()) 8 .lines() 9 .map(|line| { 10 let line = line.unwrap(); 11 let mut line = line.split(" => "); 12 let mut material = line 13 .next() 14 .unwrap() 15 .split(", ") 16 .map(|term| { 17 let term = term.split(" ").collect::<Vec<_>>(); 18 (term[1].to_string(), term[0].parse::<u64>().unwrap()) 19 }) 20 .collect::<HashMap<_, _>>(); 21 let product = line.next().unwrap().split(" ").collect::<Vec<_>>(); 22 let product = (product[1].to_string(), product[0].parse::<u64>().unwrap()); 23 material.insert(product.0.clone(), product.1); 24 (product.0, material) 25 }) 26 .collect::<HashMap<String, HashMap<String, u64>>>(); 27 println!("Rust:"); 28 println!("Part 1: {}", part_1(&input)); 29 println!("Part 2: {}", part_2(&input)); 30 } 31 32 fn calc_fuel_cost(recipes: &HashMap<String, HashMap<String, u64>>, fuel_count: u64) -> u64 { 33 let mut chemicals = HashMap::new(); 34 chemicals.insert("FUEL".to_string(), fuel_count); 35 let mut leftovers = HashMap::new(); 36 let mut ore_count = 0; 37 while !chemicals.is_empty() { 38 let target = chemicals.keys().next().unwrap().to_string(); 39 let mut amount = chemicals.remove(&target).unwrap(); 40 if target == "ORE" { 41 ore_count += amount; 42 continue; 43 } 44 // Check leftovers before commiting to reaction. 45 let leftover_amount = *leftovers.entry(target.clone()).or_insert(0); 46 *leftovers.get_mut(&target).unwrap() -= amount.min(leftover_amount); 47 amount -= amount.min(leftover_amount); 48 if amount == 0 { 49 continue; 50 } 51 // Initiate new reaction. 52 let recipe = &recipes[&target]; 53 let reaction_count = (amount as f64 / recipe[&target] as f64).ceil() as u64; 54 for (k, v) in recipe { 55 if *k != target { 56 *chemicals.entry(k.clone()).or_insert(0) += v * reaction_count; 57 } else { 58 // Place excess product in leftovers. 59 *leftovers.entry(k.clone()).or_insert(0) += v * reaction_count - amount; 60 } 61 } 62 } 63 ore_count 64 } 65 66 fn part_1(input: &HashMap<String, HashMap<String, u64>>) -> u64 { 67 calc_fuel_cost(input, 1) 68 } 69 70 fn part_2(input: &HashMap<String, HashMap<String, u64>>) -> u64 { 71 // Binary search. 72 let ore_cargo = 1000000000000; 73 let mut lo = 1; 74 let mut hi = ore_cargo; 75 while lo + 1 < hi { 76 let mi = lo + (hi - lo) / 2; 77 if calc_fuel_cost(input, mi) > ore_cargo { 78 hi = mi; 79 } else { 80 lo = mi; 81 } 82 } 83 lo 84 }