2022 day 19 part 1
This commit is contained in:
parent
614600f743
commit
d39ffafd11
|
@ -1,32 +1,131 @@
|
||||||
use regex::{CaptureMatches, Captures, Regex, SubCaptureMatches};
|
use std::collections::HashSet;
|
||||||
|
use regex::{Captures, Regex};
|
||||||
use crate::utils;
|
use crate::utils;
|
||||||
|
|
||||||
|
|
||||||
pub fn run() -> () {
|
pub fn run() -> () {
|
||||||
let data = parse_data(&utils::read_lines(utils::Source::Day(-1)));
|
let data = parse_data(&utils::read_lines(utils::Source::Day(19)));
|
||||||
|
|
||||||
println!("Day X");
|
println!("Day 19");
|
||||||
println!("Part 1: {}", solve1(&data));
|
println!("Part 1: {}", solve1(&data));
|
||||||
println!("Part 2: {}", solve2(&data));
|
println!("Part 2: {}", solve2(&data));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)] struct Ore(i32);
|
type Ore = i32;
|
||||||
#[derive(Debug)] struct Clay(i32);
|
type Clay = i32;
|
||||||
#[derive(Debug)] struct Obsidian(i32);
|
type Obsidian = i32;
|
||||||
|
type Geode = i32;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Blueprint {
|
struct Blueprint {
|
||||||
id: usize,
|
id: i32,
|
||||||
ore: Ore,
|
ore: Ore,
|
||||||
clay: Ore,
|
clay: Ore,
|
||||||
obsidian: (Ore, Clay),
|
obsidian: (Ore, Clay),
|
||||||
geode: (Ore, Obsidian),
|
geode: (Ore, Obsidian),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Default, PartialEq, Eq, Hash, Debug)]
|
||||||
|
struct State {
|
||||||
|
time_left: i32,
|
||||||
|
// Bot count
|
||||||
|
bot_ore: i32,
|
||||||
|
bot_cla: i32,
|
||||||
|
bot_obs: i32,
|
||||||
|
bot_geo: i32,
|
||||||
|
// Inventory count
|
||||||
|
inv_ore: Ore,
|
||||||
|
inv_cla: Clay,
|
||||||
|
inv_obs: Obsidian,
|
||||||
|
inv_geo: Geode,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn explore(blueprint: &Blueprint, start: State) -> i32 {
|
||||||
|
let mut visited: HashSet<State> = HashSet::new();
|
||||||
|
let mut pending: Vec<State> = Vec::new();
|
||||||
|
pending.push(start);
|
||||||
|
|
||||||
|
let max_req_ore = blueprint.geode.0.max(blueprint.obsidian.0).max(blueprint.clay).max(blueprint.ore);
|
||||||
|
let max_req_cla = blueprint.obsidian.1;
|
||||||
|
let max_req_obs = blueprint.geode.1;
|
||||||
|
|
||||||
|
let mut max_geodes = 0;
|
||||||
|
while let Some(state) = pending.pop() {
|
||||||
|
match visited.contains(&state) {
|
||||||
|
true => continue,
|
||||||
|
false => visited.insert(state),
|
||||||
|
};
|
||||||
|
if state.time_left == 0 {
|
||||||
|
max_geodes = max_geodes.max(state.inv_geo);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if state.inv_ore >= blueprint.geode.0 && state.inv_obs >= blueprint.geode.1 {
|
||||||
|
pending.push(State {
|
||||||
|
time_left: state.time_left - 1,
|
||||||
|
bot_geo: state.bot_geo + 1,
|
||||||
|
inv_ore: state.inv_ore + state.bot_ore - blueprint.geode.0,
|
||||||
|
inv_cla: state.inv_cla + state.bot_cla,
|
||||||
|
inv_obs: state.inv_obs + state.bot_obs - blueprint.geode.1,
|
||||||
|
inv_geo: state.inv_geo + state.bot_geo,
|
||||||
|
..state
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
if state.inv_ore >= blueprint.ore && state.bot_ore < max_req_ore {
|
||||||
|
pending.push(State {
|
||||||
|
time_left: state.time_left - 1,
|
||||||
|
bot_ore: state.bot_ore + 1,
|
||||||
|
inv_ore: state.inv_ore + state.bot_ore - blueprint.ore,
|
||||||
|
inv_cla: state.inv_cla + state.bot_cla,
|
||||||
|
inv_obs: state.inv_obs + state.bot_obs,
|
||||||
|
inv_geo: state.inv_geo + state.bot_geo,
|
||||||
|
..state
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if state.inv_ore >= blueprint.clay && state.bot_cla < max_req_cla {
|
||||||
|
pending.push(State {
|
||||||
|
time_left: state.time_left - 1,
|
||||||
|
bot_cla: state.bot_cla + 1,
|
||||||
|
inv_ore: state.inv_ore + state.bot_ore - blueprint.clay,
|
||||||
|
inv_cla: state.inv_cla + state.bot_cla,
|
||||||
|
inv_obs: state.inv_obs + state.bot_obs,
|
||||||
|
inv_geo: state.inv_geo + state.bot_geo,
|
||||||
|
..state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if state.inv_ore >= blueprint.obsidian.0 && state.inv_cla >= blueprint.obsidian.1 && state.bot_obs < max_req_obs {
|
||||||
|
pending.push(State {
|
||||||
|
time_left: state.time_left - 1,
|
||||||
|
bot_obs: state.bot_obs + 1,
|
||||||
|
inv_ore: state.inv_ore + state.bot_ore - blueprint.obsidian.0,
|
||||||
|
inv_cla: state.inv_cla + state.bot_cla - blueprint.obsidian.1,
|
||||||
|
inv_obs: state.inv_obs + state.bot_obs,
|
||||||
|
inv_geo: state.inv_geo + state.bot_geo,
|
||||||
|
..state
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if state.inv_ore < max_req_ore && state.inv_cla < max_req_cla && state.inv_obs < max_req_obs {
|
||||||
|
pending.push(State {
|
||||||
|
inv_ore: state.inv_ore + state.bot_ore,
|
||||||
|
inv_cla: state.inv_cla + state.bot_cla,
|
||||||
|
inv_obs: state.inv_obs + state.bot_obs,
|
||||||
|
inv_geo: state.inv_geo + state.bot_geo,
|
||||||
|
time_left: state.time_left - 1,
|
||||||
|
..state
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
max_geodes
|
||||||
|
}
|
||||||
|
|
||||||
fn solve1(data: &[Blueprint]) -> i32 {
|
fn solve1(data: &[Blueprint]) -> i32 {
|
||||||
println!("{:?}", data);
|
let start_state = State { time_left: 24, bot_ore: 1, ..Default::default() };
|
||||||
1
|
data.iter()
|
||||||
|
.map(|blueprint| blueprint.id * explore(blueprint, start_state))
|
||||||
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn solve2(data: &[Blueprint]) -> i32 {
|
fn solve2(data: &[Blueprint]) -> i32 {
|
||||||
|
@ -43,13 +142,13 @@ fn parse_data<T: AsRef<str>>(data: &[T]) -> Vec<Blueprint> {
|
||||||
).unwrap();
|
).unwrap();
|
||||||
data.iter()
|
data.iter()
|
||||||
.map(|line| {
|
.map(|line| {
|
||||||
let mut cap = re.captures(line.as_ref()).unwrap();
|
let cap = re.captures(line.as_ref()).unwrap();
|
||||||
Blueprint {
|
Blueprint {
|
||||||
id: extract(&cap, 1) as usize,
|
id: extract(&cap, 1),
|
||||||
ore: Ore(extract(&cap, 2)),
|
ore: extract(&cap, 2),
|
||||||
clay: Ore(extract(&cap, 3)),
|
clay: extract(&cap, 3),
|
||||||
obsidian: (Ore(extract(&cap, 4)), Clay(extract(&cap, 5))),
|
obsidian: (extract(&cap, 4), extract(&cap, 5)),
|
||||||
geode: (Ore(extract(&cap, 6)), Obsidian(extract(&cap, 7))),
|
geode: (extract(&cap, 6), extract(&cap, 7)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
@ -67,7 +166,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn part1() {
|
fn part1() {
|
||||||
assert_eq!(1, solve1(&parse_data(DATA)));
|
assert_eq!(33, solve1(&parse_data(DATA)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue