Skip to content

Commit

Permalink
2022: Day 19
Browse files Browse the repository at this point in the history
  • Loading branch information
connorslade committed Nov 29, 2023
1 parent d40296c commit 0d730c7
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 66 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Coming Soon!
- Day 15 Beacon Exclusion Zone [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_15.rs#L14), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_15.rs#L28)]
- Day 17 Pyroclastic Flow [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_17.rs#L14), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_17.rs#L20)]
- Day 18 Boiling Boulders [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_18.rs#L13), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_18.rs#L36)]
- Day 19 Not Enough Minerals [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_19.rs#L11), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_19.rs#L27)]
- Day 20 Grove Positioning System [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_20.rs#L10), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_20.rs#L17)]
- Day 21 Monkey Math [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_21.rs#L12), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_21.rs#L18)]
- Day 22 Monkey Map [[A](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_22.rs#L13), [B](https://github.com/Basicprogrammer10/advent-of-code/tree/master/aoc_2022/src/day_22.rs#L21)]
Expand Down
174 changes: 113 additions & 61 deletions aoc_2022/src/day_19.rs
Original file line number Diff line number Diff line change
@@ -1,68 +1,116 @@
use common::{Answer, Solution};

use std::mem;
use hashbrown::HashMap;

pub struct Day19;

impl Solution for Day19 {
fn name(&self) -> &'static str {
""
"Not Enough Minerals "
}

fn part_a(&self, input: &str) -> Answer {
let robots = parse(input);

let mut geodes = Vec::new();
for i in robots.into_iter().take(1) {
geodes.push(simulate(i));
for i in robots.into_iter() {
geodes.push(simulate(State::new(), 24, i, &mut HashMap::new(), &mut 0));
}

dbg!(&geodes);
geodes
.iter()
.enumerate()
.map(|(i, e)| e * (1 + i as u32))
.map(|(i, &e)| e as u32 * (1 + i as u32))
.sum::<u32>()
.into()
}

fn part_b(&self, _input: &str) -> Answer {
Answer::Unimplemented
fn part_b(&self, input: &str) -> Answer {
let robots = parse(input);

let mut result = 1;
for i in robots.into_iter().take(3) {
result *= simulate(State::new(), 32, i, &mut HashMap::new(), &mut 0) as u32;
}

result.into()
}
}

fn simulate(costs: [RobotType; 4]) -> u32 {
// [ore, clay, obsidian, geode]
let mut resources = [0, 0, 0, 0];
let mut robots = [1, 0, 0, 0];
let mut ticks = 24;

while ticks > 0 {
let mut new_robots = robots;
while let Some(i) = RobotType::best_buildable(&costs, &resources) {
println!("Shound build robot {:?}", i);
i.build(&mut resources);
println!(" ^ new resource count: {:?}", resources);
new_robots[i.index()] += 1;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct State {
resources: [u8; 4],
robots: [u8; 4],
}

impl State {
fn new() -> Self {
Self {
resources: [0, 0, 0, 0],
robots: [1, 0, 0, 0],
}
}

for r_type in 0..4 {
for _ in 0..robots[r_type] {
resources[r_type] += 1;
}
fn tick(self) -> Self {
let mut resources = self.resources;
for i in 0..4 {
resources[i] += self.robots[i];
}

println!(
"mins: {} | ores: {:?} | robots: {:?}",
24 - ticks,
resources,
robots
);
ticks -= 1;
mem::swap(&mut robots, &mut new_robots);
Self { resources, ..self }
}

fn cant_beat(&self, ticks: u8, max_geodes: u8) -> bool {
return self.resources[3] as u32
+ (ticks as u32 * self.robots[3] as u32 + ticks as u32 * (ticks as u32 - 1) / 2)
<= max_geodes as u32;
}
}

fn simulate(
state: State,
ticks: u8,
costs: [RobotType; 4],
cache: &mut HashMap<State, (u8, u8)>,
max: &mut u8,
) -> u8 {
if let Some(res) = cache.get(&state) {
if res.0 >= ticks {
return res.1;
}
}

if ticks == 0 {
cache.insert(state, (ticks, state.resources[3]));
return state.resources[3];
}

if state.cant_beat(ticks, *max) {
return 0;
}

resources[3]
let mut best = 0;

for i in costs {
let can_build = match i {
RobotType::Ore(c) => state.resources[0] >= c,
RobotType::Clay(c) => state.resources[0] >= c,
RobotType::Obsidian(o, c) => state.resources[0] >= o && state.resources[1] >= c,
RobotType::Geode(o, c) => state.resources[0] >= o && state.resources[2] >= c,
};

if can_build {
let mut new_state = state.tick();
i.build(&mut new_state.resources);
new_state.robots[i.index()] += 1;
best = best.max(simulate(new_state, ticks - 1, costs, cache, max));
}
}

best = best.max(simulate(state.tick(), ticks - 1, costs, cache, max));
*max = (*max).max(best);

cache.insert(state, (ticks, best));
best
}

#[derive(Debug, Clone, Copy)]
Expand Down Expand Up @@ -129,37 +177,41 @@ impl RobotType {
}
}

fn best_buildable(costs: &[Self; 4], resources: &[u32; 4]) -> Option<RobotType> {
let mut out = None;

for e in costs.iter() {
let can_build = match e {
Self::Ore(c) => resources[0] >= *c as u32,
Self::Clay(c) => resources[0] >= *c as u32,
Self::Obsidian(o, c) => resources[0] >= *o as u32 && resources[1] >= *c as u32,
Self::Geode(o, c) => resources[0] >= *o as u32 && resources[2] >= *c as u32,
};

if can_build {
out = Some(e);
}
}

out.copied()
}

fn build(&self, resources: &mut [u32; 4]) {
fn build(&self, resources: &mut [u8; 4]) {
match self {
Self::Ore(c) => resources[0] -= *c as u32,
Self::Clay(c) => resources[0] -= *c as u32,
Self::Ore(c) => resources[0] -= c,
Self::Clay(c) => resources[0] -= c,
Self::Obsidian(o, c) => {
resources[0] -= *o as u32;
resources[1] -= *c as u32;
resources[0] -= o;
resources[1] -= c;
}
Self::Geode(o, c) => {
resources[0] -= *o as u32;
resources[2] -= *c as u32;
resources[0] -= o;
resources[2] -= c;
}
}
}
}

#[cfg(test)]
mod test {
use indoc::indoc;

use super::Day19;
use common::Solution;

const CASE: &str = indoc! {"
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.
"};

#[test]
fn part_a() {
assert_eq!(Day19.part_a(CASE), 33.into());
}

#[test]
fn part_b() {
assert_eq!(Day19.part_b(CASE), 62.into());
}
}
4 changes: 1 addition & 3 deletions aoc_2022/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use common as problem;
use common::Solution;
use problem::DummySolution;

mod aoc_lib;
mod day_01;
Expand Down Expand Up @@ -48,7 +46,7 @@ pub const ALL: [&dyn Solution; 25] = [
&day_16::Day16,
&day_17::Day17,
&day_18::Day18,
&DummySolution,
&day_19::Day19,
&day_20::Day20,
&day_21::Day21,
&day_22::Day22,
Expand Down
32 changes: 30 additions & 2 deletions data/2022/19.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,30 @@
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 2 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 3 ore and 12 obsidian.
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 11 clay. Each geode robot costs 2 ore and 7 obsidian.
Blueprint 2: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 8 obsidian.
Blueprint 3: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 4 ore and 16 obsidian.
Blueprint 4: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 16 obsidian.
Blueprint 5: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 3 ore and 7 obsidian.
Blueprint 6: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 3 ore and 8 obsidian.
Blueprint 7: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 20 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 8: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 3 ore and 20 obsidian.
Blueprint 9: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 9 obsidian.
Blueprint 10: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 9 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 11: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 9 obsidian.
Blueprint 12: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 16 clay. Each geode robot costs 3 ore and 14 obsidian.
Blueprint 13: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 10 obsidian.
Blueprint 14: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 3 ore and 8 obsidian.
Blueprint 15: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 3 ore and 16 obsidian.
Blueprint 16: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 4 ore and 17 obsidian.
Blueprint 17: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 9 clay. Each geode robot costs 3 ore and 7 obsidian.
Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 8 clay. Each geode robot costs 3 ore and 19 obsidian.
Blueprint 19: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 4 ore and 15 obsidian.
Blueprint 20: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 3 ore and 19 obsidian.
Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 15 clay. Each geode robot costs 3 ore and 7 obsidian.
Blueprint 22: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 7 clay. Each geode robot costs 2 ore and 16 obsidian.
Blueprint 23: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 2 ore and 14 obsidian.
Blueprint 24: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 19 clay. Each geode robot costs 3 ore and 19 obsidian.
Blueprint 25: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 11 clay. Each geode robot costs 3 ore and 14 obsidian.
Blueprint 26: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 7 clay. Each geode robot costs 3 ore and 9 obsidian.
Blueprint 27: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 16 clay. Each geode robot costs 2 ore and 9 obsidian.
Blueprint 28: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 4 ore and 11 obsidian.
Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 5 clay. Each geode robot costs 2 ore and 10 obsidian.
Blueprint 30: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 20 clay. Each geode robot costs 2 ore and 17 obsidian.

0 comments on commit 0d730c7

Please sign in to comment.