Added day 19
This commit is contained in:
parent
3f527bca93
commit
822b5241cf
210
src/day19/1.rs
210
src/day19/1.rs
|
@ -0,0 +1,210 @@
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
const INPUTS: [&[u8]; 2] = [
|
||||||
|
include_bytes!("./sample.txt"),
|
||||||
|
include_bytes!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn parse(input: &[u8]) -> Vec<Vec<usize>> {
|
||||||
|
input
|
||||||
|
.split(|&b| b == b'\n')
|
||||||
|
.filter(|c| !c.is_empty())
|
||||||
|
.map(|line| {
|
||||||
|
let mut out = vec![];
|
||||||
|
for set in line.split(|&c| c == b' ') {
|
||||||
|
let set: Vec<u8> = set
|
||||||
|
.iter()
|
||||||
|
.filter(|&c| (b'0'..=b'9').contains(c))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if set.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(set.iter().fold(0, |a, x| (a * 10) + (x - b'0') as usize));
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solution(input: Vec<Vec<usize>>) -> usize {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.map(|ip| {
|
||||||
|
let mut memo = HashMap::new();
|
||||||
|
solve(&mut memo, ip, (0, 0, 0, 0), (1, 0, 0, 0), 0) * ip[0]
|
||||||
|
})
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Store = (usize, usize, usize, usize);
|
||||||
|
|
||||||
|
const UPTO_MINUTE: usize = 24;
|
||||||
|
|
||||||
|
fn solve(
|
||||||
|
memo: &mut HashMap<(usize, Store, Store), usize>,
|
||||||
|
costs: &[usize],
|
||||||
|
(mut ia, mut ib, ic, id): Store,
|
||||||
|
(ra, rb, rc, rd): Store,
|
||||||
|
m: usize,
|
||||||
|
) -> usize {
|
||||||
|
if m >= UPTO_MINUTE {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(v) = memo.get(&(m, (ia, ib, ic, id), (ra, rb, rc, rd))) {
|
||||||
|
return *v;
|
||||||
|
}
|
||||||
|
|
||||||
|
let maximum_ore = std::cmp::max(
|
||||||
|
std::cmp::max(costs[1], costs[2]),
|
||||||
|
std::cmp::max(costs[3], costs[5]),
|
||||||
|
);
|
||||||
|
let maximum_clay = costs[4];
|
||||||
|
let maximum_obsidian = costs[6];
|
||||||
|
|
||||||
|
let mut answer = 0;
|
||||||
|
for min in m..=UPTO_MINUTE {
|
||||||
|
let oia = ia;
|
||||||
|
let oib = ib;
|
||||||
|
|
||||||
|
let mut built_a_robot = false;
|
||||||
|
|
||||||
|
// Geode robot
|
||||||
|
let [ore, _, obsidian] = find_cost(costs, 3);
|
||||||
|
let count = std::cmp::min(ia / ore, ic / obsidian);
|
||||||
|
let remain_ia = ia - (count * ore);
|
||||||
|
let remain_ic = ic - (count * obsidian);
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
built_a_robot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(remain_ia + ra, ib + rb, remain_ic + rc, id + rd),
|
||||||
|
(ra, rb, rc, rd + count),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if built_a_robot {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obsidian robot
|
||||||
|
if rc < maximum_obsidian {
|
||||||
|
let [ore, clay, _] = find_cost(costs, 2);
|
||||||
|
while ia >= ore && ib >= clay {
|
||||||
|
ia -= ore;
|
||||||
|
ib -= clay;
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra, rb, rc + 1, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
built_a_robot = true;
|
||||||
|
ia = oia;
|
||||||
|
ib = oib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if rb < maximum_clay {
|
||||||
|
let [ore, _, _] = find_cost(costs, 1);
|
||||||
|
while ia >= ore {
|
||||||
|
ia -= ore;
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra, rb + 1, rc, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ia = oia;
|
||||||
|
built_a_robot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make robots
|
||||||
|
if ra < maximum_ore {
|
||||||
|
let [ore, _, _] = find_cost(costs, 0);
|
||||||
|
while ia >= ore {
|
||||||
|
ia -= ore;
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra + 1, rb, rc, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ia = oia;
|
||||||
|
built_a_robot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !built_a_robot {
|
||||||
|
// Increase resource without doing any thing else
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra, rb, rc, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memo.insert((m, (ia, ib, ic, id), (ra, rb, rc, rd)), answer);
|
||||||
|
|
||||||
|
answer
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn find_cost(costs: &[usize], i: usize) -> [usize; 3] {
|
||||||
|
match i {
|
||||||
|
0 => [costs[1], 0, 0],
|
||||||
|
1 => [costs[2], 0, 0],
|
||||||
|
2 => [costs[3], costs[4], 0],
|
||||||
|
3 => [costs[5], 0, costs[6]],
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
let output = parse(input);
|
||||||
|
let score = solution(output);
|
||||||
|
println!("{}", score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[bench]
|
||||||
|
fn solution_bench(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let input = parse(INPUTS[1]);
|
||||||
|
let result = solution(input);
|
||||||
|
test::black_box(result);
|
||||||
|
})
|
||||||
|
}
|
210
src/day19/2.rs
210
src/day19/2.rs
|
@ -0,0 +1,210 @@
|
||||||
|
#![feature(test)]
|
||||||
|
extern crate test;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
const INPUTS: [&[u8]; 2] = [
|
||||||
|
include_bytes!("./sample.txt"),
|
||||||
|
include_bytes!("./input.txt"),
|
||||||
|
];
|
||||||
|
|
||||||
|
fn parse(input: &[u8]) -> Vec<Vec<usize>> {
|
||||||
|
input
|
||||||
|
.split(|&b| b == b'\n')
|
||||||
|
.filter(|c| !c.is_empty())
|
||||||
|
.map(|line| {
|
||||||
|
let mut out = vec![];
|
||||||
|
for set in line.split(|&c| c == b' ') {
|
||||||
|
let set: Vec<u8> = set
|
||||||
|
.iter()
|
||||||
|
.filter(|&c| (b'0'..=b'9').contains(c))
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
if set.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push(set.iter().fold(0, |a, x| (a * 10) + (x - b'0') as usize));
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn solution(input: Vec<Vec<usize>>) -> usize {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.take(3)
|
||||||
|
.map(|ip| {
|
||||||
|
let mut memo = HashMap::new();
|
||||||
|
solve(&mut memo, ip, (0, 0, 0, 0), (1, 0, 0, 0), 0)
|
||||||
|
})
|
||||||
|
.product()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Store = (usize, usize, usize, usize);
|
||||||
|
|
||||||
|
const UPTO_MINUTE: usize = 32;
|
||||||
|
|
||||||
|
fn solve(
|
||||||
|
memo: &mut HashMap<(usize, Store, Store), usize>,
|
||||||
|
costs: &[usize],
|
||||||
|
(mut ia, mut ib, ic, id): Store,
|
||||||
|
(ra, rb, rc, rd): Store,
|
||||||
|
m: usize,
|
||||||
|
) -> usize {
|
||||||
|
if m >= UPTO_MINUTE {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(v) = memo.get(&(m, (ia, ib, ic, id), (ra, rb, rc, rd))) {
|
||||||
|
return *v;
|
||||||
|
}
|
||||||
|
|
||||||
|
let maximum_ore = std::cmp::max(
|
||||||
|
std::cmp::max(costs[1], costs[2]),
|
||||||
|
std::cmp::max(costs[3], costs[5]),
|
||||||
|
);
|
||||||
|
let maximum_clay = costs[4];
|
||||||
|
let maximum_obsidian = costs[6];
|
||||||
|
|
||||||
|
let mut answer = 0;
|
||||||
|
for min in m..=UPTO_MINUTE {
|
||||||
|
let oia = ia;
|
||||||
|
let oib = ib;
|
||||||
|
|
||||||
|
let mut built_a_robot = false;
|
||||||
|
|
||||||
|
// Geode robot
|
||||||
|
let [ore, _, obsidian] = find_cost(costs, 3);
|
||||||
|
let count = std::cmp::min(ia / ore, ic / obsidian);
|
||||||
|
let remain_ia = ia - (count * ore);
|
||||||
|
let remain_ic = ic - (count * obsidian);
|
||||||
|
|
||||||
|
if count > 0 {
|
||||||
|
built_a_robot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(remain_ia + ra, ib + rb, remain_ic + rc, id + rd),
|
||||||
|
(ra, rb, rc, rd + count),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if built_a_robot {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obsidian robot
|
||||||
|
if rc < maximum_obsidian {
|
||||||
|
let [ore, clay, _] = find_cost(costs, 2);
|
||||||
|
while ia >= ore && ib >= clay {
|
||||||
|
ia -= ore;
|
||||||
|
ib -= clay;
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra, rb, rc + 1, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
built_a_robot = true;
|
||||||
|
ia = oia;
|
||||||
|
ib = oib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if rb < maximum_clay {
|
||||||
|
let [ore, _, _] = find_cost(costs, 1);
|
||||||
|
while ia >= ore {
|
||||||
|
ia -= ore;
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra, rb + 1, rc, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ia = oia;
|
||||||
|
built_a_robot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make robots
|
||||||
|
if ra < maximum_ore {
|
||||||
|
let [ore, _, _] = find_cost(costs, 0);
|
||||||
|
while ia >= ore {
|
||||||
|
ia -= ore;
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra + 1, rb, rc, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ia = oia;
|
||||||
|
built_a_robot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !built_a_robot {
|
||||||
|
// Increase resource without doing any thing else
|
||||||
|
answer = std::cmp::max(
|
||||||
|
answer,
|
||||||
|
solve(
|
||||||
|
memo,
|
||||||
|
costs,
|
||||||
|
(ia + ra, ib + rb, ic + rc, id + rd),
|
||||||
|
(ra, rb, rc, rd),
|
||||||
|
min + 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memo.insert((m, (ia, ib, ic, id), (ra, rb, rc, rd)), answer);
|
||||||
|
|
||||||
|
answer
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
const fn find_cost(costs: &[usize], i: usize) -> [usize; 3] {
|
||||||
|
match i {
|
||||||
|
0 => [costs[1], 0, 0],
|
||||||
|
1 => [costs[2], 0, 0],
|
||||||
|
2 => [costs[3], costs[4], 0],
|
||||||
|
3 => [costs[5], 0, costs[6]],
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
for input in INPUTS.iter() {
|
||||||
|
let output = parse(input);
|
||||||
|
let score = solution(output);
|
||||||
|
println!("{}", score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[bench]
|
||||||
|
fn solution_bench(b: &mut test::Bencher) {
|
||||||
|
b.iter(|| {
|
||||||
|
let input = parse(INPUTS[1]);
|
||||||
|
let result = solution(input);
|
||||||
|
test::black_box(result);
|
||||||
|
})
|
||||||
|
}
|
30
src/day19/input.txt
Normal file
30
src/day19/input.txt
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
Blueprint 1: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 18 clay. Each geode robot costs 4 ore and 9 obsidian.
|
||||||
|
Blueprint 2: 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 3: 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 4: 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 4 ore and 8 obsidian.
|
||||||
|
Blueprint 5: 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 6: 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 7: 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 4 ore and 14 obsidian.
|
||||||
|
Blueprint 8: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 14 obsidian.
|
||||||
|
Blueprint 9: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 6 clay. Each geode robot costs 2 ore and 16 obsidian.
|
||||||
|
Blueprint 10: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 19 clay. Each geode robot costs 2 ore and 18 obsidian.
|
||||||
|
Blueprint 11: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 14 clay. Each geode robot costs 4 ore and 10 obsidian.
|
||||||
|
Blueprint 12: 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 3 ore and 15 obsidian.
|
||||||
|
Blueprint 13: 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 14: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 16 clay. Each geode robot costs 4 ore and 17 obsidian.
|
||||||
|
Blueprint 15: 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 16: Each ore robot costs 4 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 18 clay. Each geode robot costs 4 ore and 20 obsidian.
|
||||||
|
Blueprint 17: Each ore robot costs 2 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 18: Each ore robot costs 3 ore. Each clay robot costs 4 ore. Each obsidian robot costs 2 ore and 14 clay. Each geode robot costs 3 ore and 14 obsidian.
|
||||||
|
Blueprint 19: 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 20: Each ore robot costs 4 ore. Each clay robot costs 3 ore. Each obsidian robot costs 2 ore and 19 clay. Each geode robot costs 3 ore and 10 obsidian.
|
||||||
|
Blueprint 21: 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 19 obsidian.
|
||||||
|
Blueprint 22: 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 23: 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 24: Each ore robot costs 2 ore. Each clay robot costs 4 ore. Each obsidian robot costs 4 ore and 13 clay. Each geode robot costs 3 ore and 11 obsidian.
|
||||||
|
Blueprint 25: Each ore robot costs 3 ore. Each clay robot costs 3 ore. Each obsidian robot costs 3 ore and 8 clay. Each geode robot costs 2 ore and 12 obsidian.
|
||||||
|
Blueprint 26: 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 27: 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 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 2 ore and 13 obsidian.
|
||||||
|
Blueprint 29: 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 30: 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.
|
2
src/day19/sample.txt
Normal file
2
src/day19/sample.txt
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.
|
Loading…
Reference in New Issue
Block a user