Skip to content

Commit

Permalink
Complete d19 part1
Browse files Browse the repository at this point in the history
  • Loading branch information
d2weber committed Apr 22, 2023
1 parent a6f65a8 commit 711b8fc
Show file tree
Hide file tree
Showing 4 changed files with 285 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/d19/input
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Blueprint 1: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 13 clay. Each geode robot costs 3 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 12 obsidian.
Blueprint 3: 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 4: 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 2 ore and 11 obsidian.
Blueprint 5: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 2 ore and 15 obsidian.
Blueprint 6: 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 7: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 17 clay. Each geode robot costs 3 ore and 11 obsidian.
Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 4 ore and 19 obsidian.
Blueprint 9: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 2 ore and 19 obsidian.
Blueprint 10: 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 17 obsidian.
Blueprint 11: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 11 clay. Each geode robot costs 3 ore and 8 obsidian.
Blueprint 12: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 17 clay. Each geode robot costs 2 ore and 13 obsidian.
Blueprint 13: 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 2 ore and 13 obsidian.
Blueprint 14: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 18 clay. Each geode robot costs 4 ore and 16 obsidian.
Blueprint 15: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 15 obsidian.
Blueprint 16: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 13 clay. Each geode robot costs 2 ore and 20 obsidian.
Blueprint 17: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 2 ore and 9 obsidian.
Blueprint 18: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 3 ore and 12 obsidian.
Blueprint 19: 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 20: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 7 clay. Each geode robot costs 4 ore and 13 obsidian.
Blueprint 21: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 4 ore and 8 obsidian.
Blueprint 22: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 8 obsidian.
Blueprint 23: 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 24: 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 13 obsidian.
Blueprint 25: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 15 clay. Each geode robot costs 2 ore and 20 obsidian.
Blueprint 26: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 4 ore and 20 obsidian.
Blueprint 27: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 2 ore and 13 obsidian.
Blueprint 28: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 2 ore and 8 obsidian.
Blueprint 29: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 4 ore and 12 obsidian.
Blueprint 30: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 2 ore and 16 obsidian.
252 changes: 252 additions & 0 deletions src/d19/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
use std::ops::{Add, AddAssign, Sub};

pub const SAMPLE: &str = include_str!("sample");
pub const INPUT: &str = include_str!("input");

#[derive(Debug)]
struct Blueprint {
n: u32,
ore_robot: Resources,
clay_robot: Resources,
obsidian_robot: Resources,
geode_robot: Resources,
}

#[derive(Clone, Debug, Default)]
struct Resources {
ore: u32,
clay: u32,
obsidian: u32,
geode: u32,
}

impl Resources {
fn checked_sub(&self, other: &Self) -> Option<Self> {
Some(Resources {
ore: self.ore.checked_sub(other.ore)?,
clay: self.clay.checked_sub(other.clay)?,
obsidian: self.obsidian.checked_sub(other.obsidian)?,
geode: self.geode.checked_sub(other.geode)?,
})
}
}

impl Sub for Resources {
type Output = Resources;

fn sub(self, rhs: Self) -> Self::Output {
Resources {
ore: self.ore - rhs.ore,
clay: self.clay - rhs.clay,
obsidian: self.obsidian - rhs.obsidian,
geode: self.geode - rhs.geode,
}
}
}

impl Add for Resources {
type Output = Resources;

fn add(self, rhs: Self) -> Self::Output {
Resources {
ore: self.ore + rhs.ore,
clay: self.clay + rhs.clay,
obsidian: self.obsidian + rhs.obsidian,
geode: self.geode + rhs.geode,
}
}
}

impl AddAssign for Resources {
fn add_assign(&mut self, rhs: Self) {
self.ore += rhs.ore;
self.clay += rhs.clay;
self.obsidian += rhs.obsidian;
self.geode += rhs.geode;
}
}

fn parse<'a>(lines: impl Iterator<Item = &'a str>) -> Vec<Blueprint> {
lines
.map(|bp| {
let (n, s) = bp
.strip_prefix("Blueprint ")
.unwrap()
.split_once(": Each ore robot costs ")
.unwrap();
let n = n.parse().unwrap();
let (ore_robot_ore, s) = s.split_once(" ore. Each clay robot costs ").unwrap();
let (clay_robot_ore, s) = s.split_once(" ore. Each obsidian robot costs ").unwrap();
let (obsidian_robot_ore, s) = s.split_once(" ore and ").unwrap();
let (obsidian_robot_clay, s) = s.split_once(" clay. Each geode robot costs ").unwrap();
let (geode_robot_ore, s) = s.split_once(" ore and ").unwrap();
let geode_robot_obsidian = s.strip_suffix(" obsidian.").unwrap();
Blueprint {
n,
ore_robot: Resources {
ore: ore_robot_ore.parse().unwrap(),
..Default::default()
},
clay_robot: Resources {
ore: clay_robot_ore.parse().unwrap(),
..Default::default()
},
obsidian_robot: Resources {
ore: obsidian_robot_ore.parse().unwrap(),
clay: obsidian_robot_clay.parse().unwrap(),
..Default::default()
},
geode_robot: Resources {
ore: geode_robot_ore.parse().unwrap(),
obsidian: geode_robot_obsidian.parse().unwrap(),
..Default::default()
},
}
})
.collect()
}

fn max_geodes(
bp: &Blueprint,
mut inventory: Resources,
n_robots: Resources,
minutes_left: u32,
mut skip_ore: bool,
mut skip_clay: bool,
) -> u32 {
if minutes_left == 1 {
return inventory.geode + n_robots.geode;
}
let mut geodes = 0;
let new_robot = if let Some(inven) = inventory.checked_sub(&bp.geode_robot) {
inventory = inven;
skip_clay = false;
skip_ore = false;
Resources {
geode: 1,
..Default::default()
}
} else if let Some(inven) = inventory.checked_sub(&bp.obsidian_robot) {
inventory = inven;
skip_clay = false;
skip_ore = false;
Resources {
obsidian: 1,
..Default::default()
}
} else {
if !skip_clay {
if let Some(inven) = inventory.checked_sub(&bp.clay_robot) {
skip_ore = false;
geodes = geodes.max(max_geodes(
bp,
inven + n_robots.clone(),
n_robots.clone()
+ Resources {
clay: 1,
..Default::default()
},
minutes_left - 1,
skip_ore,
skip_clay,
));
skip_clay = true;
}
}
if !skip_ore {
if let Some(inven) = inventory.checked_sub(&bp.ore_robot) {
skip_clay = false;
geodes = geodes.max(max_geodes(
bp,
inven + n_robots.clone(),
n_robots.clone()
+ Resources {
ore: 1,
..Default::default()
},
minutes_left - 1,
skip_ore,
skip_clay,
));
skip_ore = true;
}
}
Resources::default()
};
geodes.max(max_geodes(
bp,
inventory + n_robots.clone(),
n_robots + new_robot,
minutes_left - 1,
skip_ore,
skip_clay,
))
}

pub mod part1 {
use super::*;

pub fn solution(s: &str) -> u32 {
let bps = parse(s.lines());
bps.iter()
.map(|bp| {
bp.n * max_geodes(
bp,
Resources::default(),
Resources {
ore: 1,
..Default::default()
},
24,
false,
false,
)
})
.inspect(|q| {
dbg!(q);
})
.sum()
}
#[test]
fn sample() {
assert_eq!(solution(SAMPLE), 33);
}
#[test]
fn actual() {
assert_eq!(solution(INPUT), 1382);
}
}

pub mod part2 {
use super::*;

pub fn solution(s: &str) -> u32 {
let bps = parse(s.lines().take(3));
bps.iter()
.map(|bp| {
max_geodes(
bp,
Resources::default(),
Resources {
ore: 1,
..Default::default()
},
32,
false,
false,
)
})
.inspect(|q| {
dbg!(q);
})
.product()
}
#[test]
fn sample() {
assert_eq!(solution(SAMPLE), 33);
}
// #[test]
// fn actual() {
// assert_eq!(solution(INPUT), 1382);
// }
}
2 changes: 2 additions & 0 deletions src/d19/sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
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.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,6 @@ pub mod d15;
pub mod d16;
pub mod d17;
pub mod d18;
pub mod d19;

pub mod y2021;

0 comments on commit 711b8fc

Please sign in to comment.