Skip to content

Commit df4c97c

Browse files
committed
feat: completed day 14
1 parent 21e1676 commit df4c97c

File tree

2 files changed

+78
-53
lines changed

2 files changed

+78
-53
lines changed

day_14/src/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
pub type Item = (String, u8);
1+
use std::collections::HashMap;
2+
3+
pub type Item = (String, i64);
24

35
fn split(input: String) -> Item {
46
let mut iter = input.split(" ").map(str::trim).map(str::to_owned);
@@ -29,3 +31,21 @@ pub fn parse_input(input: &str) -> Vec<(Item, Vec<Item>)> {
2931
})
3032
.collect()
3133
}
34+
35+
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
36+
pub struct Output {
37+
pub quantity: i64,
38+
pub required: Vec<Item>,
39+
}
40+
41+
pub fn to_map(input: &Vec<(Item, Vec<Item>)>) -> HashMap<String, Output> {
42+
let mut map = HashMap::new();
43+
44+
for (key, value) in input {
45+
let (key, quantity) = (key.0.to_owned(), key.1.to_owned());
46+
let required = value.clone();
47+
map.insert(key, Output { quantity, required });
48+
}
49+
50+
map
51+
}

day_14/src/main.rs

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,69 @@
1-
use ::day_14::{parse_input, Item};
2-
use std::collections::{HashMap, LinkedList};
1+
use ::day_14::{parse_input, to_map, Item, Output};
2+
use std::{collections::HashMap, mem::replace};
33

4-
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
5-
struct Output {
6-
pub quantity: u8,
7-
pub required: Vec<Item>,
8-
}
4+
fn get_requirements(reactions: &HashMap<String, Output>, quantity: i64) -> i64 {
5+
let mut reserves: HashMap<String, i64> = HashMap::new();
6+
let mut required = HashMap::new();
7+
required.insert("FUEL".to_owned(), quantity.to_owned());
98

10-
fn to_map(input: &Vec<(Item, Vec<Item>)>) -> HashMap<String, Output> {
11-
let mut map = HashMap::new();
12-
13-
for (key, value) in input {
14-
map.insert(
15-
key.0.to_owned(),
16-
Output {
17-
quantity: key.1,
18-
required: value.to_owned(),
19-
},
20-
);
21-
}
9+
while required.len() != 1 || !required.contains_key("ORE") {
10+
let mut new_rec = HashMap::new();
2211

23-
map
24-
}
12+
for (chemical, quantity) in required.clone() {
13+
if chemical == "ORE" {
14+
*new_rec.entry("ORE".to_owned()).or_insert(0) += quantity.to_owned();
15+
continue;
16+
}
17+
18+
let quantity = quantity as f64;
19+
let reaction = reactions.get(&chemical).unwrap();
20+
let reaction_quantity = reaction.quantity.to_owned() as f64;
21+
let reserve_ref = reserves.entry(chemical.to_owned()).or_insert(0);
22+
let reserve = reserve_ref.to_owned() as f64;
23+
let reaction_count = (quantity - reserve) / reaction_quantity;
24+
let reaction_count = reaction_count.ceil() as f64;
2525

26-
fn get_requirements(map: &HashMap<String, Output>) -> Vec<Vec<String>> {
27-
let fuel = &map.get("FUEL").unwrap();
28-
let mut paths = vec![];
29-
for item in &fuel.required {
30-
let mut req = LinkedList::new();
31-
req.push_front((item.clone(), vec![item.0.to_owned()]));
32-
while req.len() > 0 {
33-
if let Some(((key, _value), tree)) = req.pop_back() {
34-
match map.get(&key) {
35-
Some(item) => {
36-
for required in &item.required {
37-
let mut tree = tree.clone();
38-
if !tree.contains(&key) {
39-
tree.insert(0, key.to_owned());
40-
}
41-
if !tree.contains(&required.0) {
42-
tree.insert(0, required.0.to_owned());
43-
}
44-
req.push_back((required.clone(), tree.to_owned()));
45-
}
46-
}
47-
None => paths.push(tree.clone()),
48-
};
49-
};
26+
for (ingredient, amount) in &reaction.required {
27+
let ingredient_ref = new_rec.entry(ingredient.to_owned()).or_insert(0);
28+
let ingredient_pre = ingredient_ref.to_owned() as f64;
29+
let amount = amount.to_owned() as f64;
30+
31+
*ingredient_ref = (ingredient_pre + reaction_count * amount) as i64;
32+
}
33+
34+
*reserve_ref = (reserve + reaction_count * reaction_quantity - quantity).ceil() as i64;
5035
}
36+
37+
required = replace(&mut new_rec, HashMap::new());
5138
}
5239

53-
paths
40+
required.entry("ORE".to_owned()).or_insert(0).to_owned()
5441
}
5542

56-
fn part_01(input: &Vec<(Item, Vec<Item>)>) -> u32 {
57-
let map = to_map(input);
58-
let requirements = get_requirements(&map);
43+
type Input = Vec<(Item, Vec<Item>)>;
5944

60-
for req in requirements {
61-
println!("{:?}", req);
45+
fn part_01(input: &Input) -> i64 {
46+
get_requirements(&to_map(input), 1)
47+
}
48+
49+
fn part_02(input: &Input) -> i64 {
50+
let map = to_map(input);
51+
let total_ore: i64 = 1_000_000_000_000;
52+
let mut new_estimate = ((total_ore as f64) / (get_requirements(&map, 1) as f64)).floor() as i64;
53+
let mut estimate = 0;
54+
while new_estimate > estimate {
55+
estimate = new_estimate.to_owned();
56+
let needed = get_requirements(&map, estimate.to_owned());
57+
new_estimate = ((estimate as f64) * (total_ore as f64) / (needed as f64)).floor() as i64;
6258
}
63-
0
59+
60+
estimate
6461
}
6562

6663
fn main() {
6764
let input = parse_input(include_str!("../../input/day_14"));
6865
println!("part_01: {}", part_01(&input));
66+
println!("part_02: {:?}", part_02(&input));
6967
}
7068

7169
#[cfg(test)]
@@ -137,4 +135,11 @@ mod tests {
137135
assert_eq!(part_01(&parse_input(&EXAMPLE_03)), 180697);
138136
assert_eq!(part_01(&parse_input(&EXAMPLE_04)), 2210736);
139137
}
138+
139+
#[test]
140+
fn it_gets_same_same_results_as_the_second_part() {
141+
assert_eq!(part_02(&parse_input(&EXAMPLE_02)), 82892753);
142+
assert_eq!(part_02(&parse_input(&EXAMPLE_03)), 5586022);
143+
assert_eq!(part_02(&parse_input(&EXAMPLE_04)), 460664);
144+
}
140145
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy