Last active
December 15, 2019 15:06
-
-
Save svantelidman/9d4a4e7672bb09a14bf79dd4478f6675 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // Part 2 is pure brute force. Compiled in release mode it still takes | |
| // about 1 hour or so to get to the answer. There is of course a better way | |
| // to do it which could be looked at later, time permitting. | |
| // | |
| use std::collections::HashMap; | |
| fn main() { | |
| let prod = | |
| r#"1 HKCVW, 2 DFCT => 5 ZJZRN | |
| 8 TCPN, 7 XHTJF, 3 DFCT => 8 ZKCXK | |
| 1 ZJZRN, 4 NZVL, 1 NJFXK, 7 RHJCQ, 32 MCQS, 1 XFNPT => 5 ZWQX | |
| 10 DRWB, 16 JBHKV => 6 TCPN | |
| 3 MBFK => 7 DRWB | |
| 9 RHJCQ => 6 MBMKZ | |
| 1 BVFPF => 2 KRTGD | |
| 1 QNXC, 7 BKNQT, 1 XFNPT => 4 VNFJQ | |
| 2 TCPN, 1 WFSV => 2 TGJP | |
| 35 DFCT => 2 RHJCQ | |
| 1 SKBV, 7 CTRH => 8 QGDSV | |
| 8 VSRMJ, 1 BVFPF => 4 CTRH | |
| 1 WMCD => 3 FPZLF | |
| 13 CVJQG, 8 DXBZJ => 9 QBDQ | |
| 1 XSRWM => 5 GDJGV | |
| 132 ORE => 3 MBFK | |
| 2 BQGP => 9 LZKJZ | |
| 5 GZLHP => 7 WFSV | |
| 2 RXSZS, 10 MBFK, 1 BPNVK => 2 GZLHP | |
| 13 BZFH => 8 XSRWM | |
| 3 QLSVN => 3 SKBV | |
| 8 QBDQ => 4 VSRMJ | |
| 1 RXSZS => 9 CVJQG | |
| 3 MBFK => 3 BVFPF | |
| 7 GZLHP, 4 MBFK, 5 CVJQG => 8 XHTJF | |
| 1 GZLHP => 2 DFCT | |
| 4 SZDWB, 4 RHJCQ, 1 WMCD => 3 RGZDK | |
| 2 BRXLV => 8 DXBZJ | |
| 192 ORE => 7 RXSZS | |
| 1 PRMR, 6 DFCT => 5 SZDWB | |
| 104 ORE => 9 BPNVK | |
| 6 VLJWQ, 8 ZKCXK, 6 BKNQT, 26 JRXQ, 7 FPZLF, 6 HKCVW, 18 KRTGD => 4 RBFX | |
| 7 XFNPT, 1 GDJGV => 2 HJDB | |
| 15 SKBV, 8 DRWB, 12 RXSZS => 3 GHQPH | |
| 1 BZFH => 5 GCBR | |
| 1 TGJP, 6 SKBV => 1 BZFH | |
| 4 KRTGD, 1 ZJHKP, 1 LZKJZ, 1 VNFJQ, 6 QBDQ, 1 PRMR, 1 NJFXK, 1 HJDB => 8 TFQH | |
| 10 BVFPF, 1 RGZDK => 8 QNXC | |
| 1 XHTJF => 5 JRXQ | |
| 3 XKTMK, 4 QGDSV => 3 ZJHKP | |
| 2 BZFH => 7 PRMR | |
| 1 BPNVK, 1 RXSZS => 5 JBHKV | |
| 10 XHTJF => 9 BKNQT | |
| 1 JBHKV, 2 XHTJF => 8 QLSVN | |
| 24 VNFJQ, 42 TFQH, 39 RBFX, 1 ZWQX, 7 VBHVQ, 26 DRWB, 21 NJFXK => 1 FUEL | |
| 26 WBKQ, 14 XHTJF => 5 BQGP | |
| 5 WBKQ, 7 MBMKZ => 3 LQGC | |
| 6 LQGC => 5 NZVL | |
| 13 KRTGD, 5 GHQPH => 9 VLJWQ | |
| 117 ORE => 4 BRXLV | |
| 3 XKTMK, 1 PRMR => 2 MCQS | |
| 3 DRWB, 7 BVFPF, 4 TCPN => 7 NJFXK | |
| 10 VHFCR, 13 JZQJ => 5 XKTMK | |
| 17 CVJQG, 4 GCBR => 9 HKCVW | |
| 22 DFCT, 17 TGJP => 2 WBKQ | |
| 2 JZQJ, 12 XFNPT, 1 BQGP => 2 VBHVQ | |
| 12 HKCVW => 1 JZQJ | |
| 1 XSRWM => 3 WMCD | |
| 12 BZFH, 14 SKBV, 1 CTRH => 4 XFNPT | |
| 7 ZKCXK => 6 VHFCR"#; | |
| let producers = parse_producers(prod); | |
| let mut spare_units: HashMap<String, i64> = HashMap::new(); | |
| let mut remaining_ore: i64 = 1000000000000; | |
| let mut n_produced_fuel = 0; | |
| // Correct answer for production run is : 2876992 | |
| loop { | |
| let cost = produce(0, &String::from("FUEL"), 1, &producers, &mut spare_units); | |
| if cost > remaining_ore { | |
| break | |
| } else { | |
| remaining_ore -= cost; | |
| n_produced_fuel += 1 | |
| } | |
| println!("{}", remaining_ore); | |
| } | |
| println!("Produced fuel: {}", n_produced_fuel); | |
| } | |
| fn produce(indent: usize, required_material: &String, required_amount: i64, producers: &Vec<Producer>, spare_units: &mut HashMap<String, i64>) -> i64 { | |
| let mut remaining_needed_amount = required_amount; | |
| if let Some(v) = spare_units.get(required_material) { | |
| if *v > 0 { | |
| let remaining_v = 0.max(*v - required_amount); | |
| remaining_needed_amount = 0.max(required_amount - *v); | |
| spare_units.insert(required_material.clone(), remaining_v); | |
| } | |
| } | |
| let cost = if remaining_needed_amount == 0 { | |
| 0 | |
| } else { | |
| if required_material == "ORE" { | |
| remaining_needed_amount | |
| } else { | |
| let producer = producers.iter().find( |p| p.output.material == *required_material).unwrap(); | |
| let mut produced_amount = 0; | |
| let mut cost = 0; | |
| while produced_amount < remaining_needed_amount { | |
| produced_amount += producer.output.amount; | |
| cost += producer.inputs.iter().fold(0, |acc, inp| acc + produce(indent + 2, &inp.material, inp.amount, producers, spare_units)) | |
| } | |
| let spare_amount = produced_amount - remaining_needed_amount; | |
| if let Some(v) = spare_units.get(required_material) { | |
| spare_units.insert(required_material.clone(), v + spare_amount); | |
| } else { | |
| spare_units.insert(required_material.clone(), spare_amount); | |
| } | |
| cost | |
| } | |
| }; | |
| cost | |
| } | |
| fn parse_producers(defs: &str) -> Vec<Producer> { | |
| let mut producers: Vec<Producer> = vec!(); | |
| defs.trim().split('\n').for_each( | |
| |l| { | |
| let mut split_iter = l.split("=>"); | |
| let inp = split_iter.next().unwrap(); | |
| let res = split_iter.next().unwrap(); | |
| let output = parse_material_amount(res); | |
| let mut inputs: Vec<MaterialAmount> = vec!(); | |
| inp.split(',').for_each( | |
| |i| inputs.push(parse_material_amount(i.trim())) | |
| ); | |
| producers.push( | |
| Producer { | |
| inputs: inputs, | |
| output: output | |
| } | |
| ) | |
| } | |
| ); | |
| producers | |
| } | |
| fn parse_material_amount(d: &str) -> MaterialAmount { | |
| let mut splitter = d.trim().split_whitespace(); | |
| let amount: i64 = splitter.next().unwrap().parse().unwrap(); | |
| let material: String = String::from(splitter.next().unwrap()); | |
| MaterialAmount { | |
| amount: amount, | |
| material: material | |
| } | |
| } | |
| struct Producer { | |
| inputs: Vec<MaterialAmount>, | |
| output: MaterialAmount | |
| } | |
| struct MaterialAmount { | |
| amount: i64, | |
| material: String | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment