Start solving day19 and break it after that
This commit is contained in:
parent
4443c683a8
commit
066ec8e569
101
Cargo.lock
generated
101
Cargo.lock
generated
|
@ -183,6 +183,49 @@ version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2875caafcad10de47ec09ead140f27a276a25b0b2f553cec9b2152194b96bf5d"
|
checksum = "2875caafcad10de47ec09ead140f27a276a25b0b2f553cec9b2152194b96bf5d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.13.4"
|
version = "0.13.4"
|
||||||
|
@ -353,6 +396,11 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "day19"
|
name = "day19"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"rayon",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "day20"
|
name = "day20"
|
||||||
|
@ -384,6 +432,12 @@ dependencies = [
|
||||||
name = "day25"
|
name = "day25"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -632,6 +686,25 @@ version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "numtoa"
|
name = "numtoa"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -746,6 +819,28 @@ dependencies = [
|
||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
@ -804,6 +899,12 @@ dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.151"
|
version = "1.0.151"
|
||||||
|
|
|
@ -8,3 +8,6 @@ build = true
|
||||||
app = true
|
app = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
rayon = "1.6.1"
|
||||||
|
regex = "1.7.0"
|
||||||
|
|
30
day19/input
Normal file
30
day19/input
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
Blueprint 1: 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 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 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 8 obsidian.
|
||||||
|
Blueprint 4: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 15 clay. Each geode robot costs 2 ore and 13 obsidian.
|
||||||
|
Blueprint 5: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 4 ore and 18 obsidian.
|
||||||
|
Blueprint 6: 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 7: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 12 clay. Each geode robot costs 4 ore and 19 obsidian.
|
||||||
|
Blueprint 8: 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 9: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 9 clay. Each geode robot costs 2 ore and 9 obsidian.
|
||||||
|
Blueprint 10: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 12 clay. Each geode robot costs 2 ore and 10 obsidian.
|
||||||
|
Blueprint 11: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 10 clay. Each geode robot costs 2 ore and 13 obsidian.
|
||||||
|
Blueprint 12: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 6 clay. Each geode robot costs 3 ore and 16 obsidian.
|
||||||
|
Blueprint 13: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 5 clay. Each geode robot costs 3 ore and 19 obsidian.
|
||||||
|
Blueprint 14: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 20 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 8 clay. Each geode robot costs 2 ore and 18 obsidian.
|
||||||
|
Blueprint 16: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 10 clay. Each geode robot costs 4 ore and 10 obsidian.
|
||||||
|
Blueprint 17: Each ore robot costs 2 ore. Each clay robot costs 2 ore. Each obsidian robot costs 2 ore and 17 clay. Each geode robot costs 2 ore and 10 obsidian.
|
||||||
|
Blueprint 18: 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 19: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 13 clay. Each geode robot costs 2 ore and 10 obsidian.
|
||||||
|
Blueprint 20: 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 2 ore and 10 obsidian.
|
||||||
|
Blueprint 21: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 14 clay. Each geode robot costs 4 ore and 15 obsidian.
|
||||||
|
Blueprint 22: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 4 ore and 20 clay. Each geode robot costs 2 ore and 15 obsidian.
|
||||||
|
Blueprint 23: 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 24: 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 25: Each ore robot costs 2 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 17 clay. Each geode robot costs 3 ore and 10 obsidian.
|
||||||
|
Blueprint 26: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 6 clay. Each geode robot costs 2 ore and 20 obsidian.
|
||||||
|
Blueprint 27: 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 28: 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 4 ore and 20 obsidian.
|
||||||
|
Blueprint 29: 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 3 ore and 17 obsidian.
|
||||||
|
Blueprint 30: 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.
|
2
day19/input.test
Normal file
2
day19/input.test
Normal file
|
@ -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,3 +1,283 @@
|
||||||
fn main() {
|
#![feature(const_trait_impl)]
|
||||||
println!("Hello, world!");
|
|
||||||
|
use std::{
|
||||||
|
collections::{hash_map::Entry, HashMap},
|
||||||
|
fs::File,
|
||||||
|
io::{BufRead, BufReader},
|
||||||
|
ops::Add,
|
||||||
|
};
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
type Ore = usize;
|
||||||
|
type Clay = usize;
|
||||||
|
type Obsidian = usize;
|
||||||
|
type Geode = usize;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref BLUEPRINT_RE: Regex = Regex::new(r"Blueprint (\d+): Each ore robot costs (\d+) ore. Each clay robot costs (\d+) ore. Each obsidian robot costs (\d+) ore and (\d+) clay. Each geode robot costs (\d+) ore and (\d+) obsidian.").unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, PartialEq, Eq)]
|
||||||
|
enum SolvePuzzle {
|
||||||
|
First,
|
||||||
|
#[default]
|
||||||
|
Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
||||||
|
struct ResourceState {
|
||||||
|
ore: Ore,
|
||||||
|
clay: Clay,
|
||||||
|
obsidian: Obsidian,
|
||||||
|
geodes: Geode,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ResourceState {
|
||||||
|
fn maximize(&mut self, other: Self) {
|
||||||
|
self.ore = self.ore.max(other.ore);
|
||||||
|
self.clay = self.clay.max(other.clay);
|
||||||
|
self.obsidian = self.obsidian.max(other.obsidian);
|
||||||
|
self.geodes = self.geodes.max(other.geodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
struct RobotState {
|
||||||
|
ore_robots: usize,
|
||||||
|
clay_robots: usize,
|
||||||
|
obisidian_robots: usize,
|
||||||
|
geode_robots: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RobotState {
|
||||||
|
fn successors(
|
||||||
|
self,
|
||||||
|
possible_resources: ResourceState,
|
||||||
|
blueprint: &Blueprint,
|
||||||
|
) -> Vec<(Self, ResourceState)> {
|
||||||
|
let mut ret = vec![];
|
||||||
|
let collected = possible_resources + self.collect_ores_for_one_minute();
|
||||||
|
if possible_resources.ore >= blueprint.ore_robot_cost {
|
||||||
|
ret.push((
|
||||||
|
Self {
|
||||||
|
ore_robots: self.ore_robots + 1,
|
||||||
|
..self
|
||||||
|
},
|
||||||
|
ResourceState {
|
||||||
|
ore: collected.ore - blueprint.ore_robot_cost,
|
||||||
|
..collected
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if possible_resources.ore >= blueprint.clay_robot_cost {
|
||||||
|
ret.push((
|
||||||
|
Self {
|
||||||
|
clay_robots: self.clay_robots + 1,
|
||||||
|
..self
|
||||||
|
},
|
||||||
|
ResourceState {
|
||||||
|
ore: collected.ore - blueprint.clay_robot_cost,
|
||||||
|
..collected
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if possible_resources.ore >= blueprint.obsidian_robot_cost.0
|
||||||
|
&& possible_resources.clay >= blueprint.obsidian_robot_cost.1
|
||||||
|
{
|
||||||
|
ret.push((
|
||||||
|
Self {
|
||||||
|
obisidian_robots: self.obisidian_robots + 1,
|
||||||
|
..self
|
||||||
|
},
|
||||||
|
ResourceState {
|
||||||
|
ore: collected.ore - blueprint.obsidian_robot_cost.0,
|
||||||
|
clay: collected.clay - blueprint.obsidian_robot_cost.1,
|
||||||
|
..collected
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if possible_resources.ore >= blueprint.geode_robot_cost.0
|
||||||
|
&& possible_resources.obsidian >= blueprint.geode_robot_cost.1
|
||||||
|
{
|
||||||
|
ret.push((
|
||||||
|
Self {
|
||||||
|
geode_robots: self.geode_robots + 1,
|
||||||
|
..self
|
||||||
|
},
|
||||||
|
ResourceState {
|
||||||
|
ore: collected.ore - blueprint.geode_robot_cost.0,
|
||||||
|
obsidian: collected.obsidian - blueprint.geode_robot_cost.1,
|
||||||
|
..collected
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// let we_can_afford_every_robot_or_will_never = self.ore >= blueprint.ore_robot_cost
|
||||||
|
// && self.ore >= blueprint.clay_robot_cost
|
||||||
|
// && self.ore >= blueprint.obsidian_robot_cost.0
|
||||||
|
// && (self.clay >= blueprint.obsidian_robot_cost.1 || self.clay_robots == 0)
|
||||||
|
// && self.ore >= blueprint.geode_robot_cost.0
|
||||||
|
// && (self.obsidian >= blueprint.geode_robot_cost.1 || self.obisidian_robots == 0);
|
||||||
|
// // Do nothing, just collect ores
|
||||||
|
// if !we_can_afford_every_robot_or_will_never {
|
||||||
|
ret.push((self, collected));
|
||||||
|
// }
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_ores_for_one_minute(&self) -> ResourceState {
|
||||||
|
ResourceState {
|
||||||
|
ore: self.ore_robots,
|
||||||
|
clay: self.clay_robots,
|
||||||
|
obsidian: self.obisidian_robots,
|
||||||
|
geodes: self.geode_robots,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Blueprint {
|
||||||
|
id: usize,
|
||||||
|
ore_robot_cost: Ore,
|
||||||
|
clay_robot_cost: Ore,
|
||||||
|
obsidian_robot_cost: (Ore, Clay),
|
||||||
|
geode_robot_cost: (Ore, Obsidian),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Blueprint {
|
||||||
|
fn parse_line<S: AsRef<str>>(line: S) -> Self {
|
||||||
|
let matches = BLUEPRINT_RE.captures(line.as_ref()).unwrap();
|
||||||
|
let match_nr = |nr| matches.get(nr).unwrap().as_str().parse().unwrap();
|
||||||
|
Self {
|
||||||
|
id: match_nr(1),
|
||||||
|
ore_robot_cost: match_nr(2),
|
||||||
|
clay_robot_cost: match_nr(3),
|
||||||
|
obsidian_robot_cost: (match_nr(4), match_nr(5)),
|
||||||
|
geode_robot_cost: (match_nr(6), match_nr(7)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn calculate_max_geode_openable(&self) -> usize {
|
||||||
|
const MAX_TIME: usize = 24;
|
||||||
|
let mut states: HashMap<RobotState, ResourceState> = HashMap::new();
|
||||||
|
states.insert(RobotState::default(), ResourceState::default());
|
||||||
|
for minute in 1..=MAX_TIME {
|
||||||
|
states = states
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|(state, res)| state.successors(res, self))
|
||||||
|
.fold(HashMap::new(), |mut map, (state, res)| {
|
||||||
|
match map.entry(state) {
|
||||||
|
Entry::Occupied(mut occ) => occ.get_mut().maximize(res),
|
||||||
|
Entry::Vacant(vac) => {
|
||||||
|
vac.insert(res);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
map
|
||||||
|
});
|
||||||
|
// if minute == 24 {
|
||||||
|
eprintln!("{minute} {}", states.len());
|
||||||
|
if minute < 6 {
|
||||||
|
states.iter().for_each(|x| eprintln!("{x:#?}"));
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
states
|
||||||
|
.into_values()
|
||||||
|
.map(|s| s.geodes)
|
||||||
|
.max()
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Blueprints(Vec<Blueprint>);
|
||||||
|
|
||||||
|
impl Blueprints {
|
||||||
|
fn parse_input<R: BufRead>(reader: R) -> Blueprints {
|
||||||
|
let inner = reader
|
||||||
|
.lines()
|
||||||
|
.map(Result::unwrap)
|
||||||
|
.map(Blueprint::parse_line)
|
||||||
|
.collect();
|
||||||
|
Self(inner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn total_score(&self) -> usize {
|
||||||
|
self.0
|
||||||
|
.par_iter()
|
||||||
|
.map(|bp| bp.calculate_max_geode_openable() * bp.id)
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_first_puzzle<R: BufRead>(reader: R) -> usize {
|
||||||
|
Blueprints::parse_input(reader).total_score()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solve_second_puzzle<R: BufRead>(reader: R) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut args = ::std::env::args().skip(1);
|
||||||
|
let file = args.next().unwrap_or_else(|| String::from("./input"));
|
||||||
|
let solve = args
|
||||||
|
.next()
|
||||||
|
.map(|arg| match arg.as_str() {
|
||||||
|
"first" => SolvePuzzle::First,
|
||||||
|
"second" => SolvePuzzle::Second,
|
||||||
|
_ => unreachable!(),
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
let file = BufReader::new(File::open(file).expect("Opening file"));
|
||||||
|
match solve {
|
||||||
|
SolvePuzzle::First => println!("{}", solve_first_puzzle(file)),
|
||||||
|
SolvePuzzle::Second => println!("{}", solve_second_puzzle(file)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl const Default for RobotState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
// Just one ore robot
|
||||||
|
ore_robots: 1,
|
||||||
|
clay_robots: 0,
|
||||||
|
obisidian_robots: 0,
|
||||||
|
geode_robots: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl const Add for ResourceState {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, rhs: Self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
ore: self.ore + rhs.ore,
|
||||||
|
clay: self.clay + rhs.clay,
|
||||||
|
obsidian: self.obsidian + rhs.obsidian,
|
||||||
|
geodes: self.geodes + rhs.geodes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example_on_first() {
|
||||||
|
let reader = Cursor::new(include_str!("../input.test"));
|
||||||
|
assert_eq!(solve_first_puzzle(reader), 33);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example_on_second() {
|
||||||
|
let reader = Cursor::new(include_str!("../input.test"));
|
||||||
|
assert_eq!(solve_second_puzzle(reader), 54);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue