Change integer sizes to significantly reduce memory footprint

This commit is contained in:
Tobias Marschner 2024-04-10 07:39:06 +02:00
parent 695d262a58
commit ede5141783

View File

@ -3,16 +3,16 @@ use std::{cmp::Ordering, collections::HashSet};
#[derive(Debug)]
struct Blueprint {
// The id and costs parsed from the input.
id: usize,
ore_robot_ore_cost: usize,
clay_robot_ore_cost: usize,
obsidian_robot_ore_cost: usize,
obsidian_robot_clay_cost: usize,
geode_robot_ore_cost: usize,
geode_robot_obsidian_cost: usize,
id: u16,
ore_robot_ore_cost: u16,
clay_robot_ore_cost: u16,
obsidian_robot_ore_cost: u16,
obsidian_robot_clay_cost: u16,
geode_robot_ore_cost: u16,
geode_robot_obsidian_cost: u16,
// The maximal number of geodes that can be collected by this blueprint.
// Initialized to 0 and overwritten by the solver, once it concludes.
optimal_geode_count: usize,
optimal_geode_count: u16,
}
impl Blueprint {
@ -123,7 +123,8 @@ impl Blueprint {
println!(" initial next_hs.len(): {}", next_hs.len());
// For the last few timesteps, pruning isn't worth it. Just calculate the rest in that case.
if ts > 3 {
let worst_case = next_hs.len() * 5usize.pow(ts as u32);
if worst_case > 100_000_000 && ts > 4 {
// Pruning runs in a nested loop over the elements of the set.
// In the inner loop we collect strictly inferior elements until we've met a
// threshold of the original count.
@ -159,8 +160,8 @@ impl Blueprint {
// Have we found enough elements yet?
// Or have we reached the limit in terms of comparisons?
if (strictly_inferior_hs.len() as f32) / initial_elems >= INNER_LOOP_CUTOFF
|| comp_count >= TOTAL_COMP_COUNT
{
|| comp_count >= TOTAL_COMP_COUNT {
// if comp_count >= TOTAL_COMP_COUNT {
break;
}
}
@ -185,7 +186,10 @@ impl Blueprint {
}
}
} else {
println!("Final 3 - no more pruning.");
println!(
"{} calculations left / timeslot {} - no need to prune.",
worst_case, ts
);
}
println!(" final next_hs.len(): {}\n", next_hs.len());
}
@ -203,27 +207,27 @@ impl Blueprint {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct RecursionState {
// The currently active fleet of robots.
ore_robots: usize,
clay_robots: usize,
obsidian_robots: usize,
geode_robots: usize,
ore_robots: u8,
clay_robots: u8,
obsidian_robots: u8,
geode_robots: u8,
// Our resources.
ore: usize,
clay: usize,
obsidian: usize,
geode: usize,
ore: u16,
clay: u16,
obsidian: u16,
geode: u16,
// How much time is left in the simulation.
remaining_time: usize,
remaining_time: u8,
}
impl RecursionState {
// Let one unit of time pass on this RecursionState.
// Collects all the resources from the currently active robots.
fn pass_time(&mut self) {
self.ore += self.ore_robots;
self.clay += self.clay_robots;
self.obsidian += self.obsidian_robots;
self.geode += self.geode_robots;
self.ore += self.ore_robots as u16;
self.clay += self.clay_robots as u16;
self.obsidian += self.obsidian_robots as u16;
self.geode += self.geode_robots as u16;
// One unit of time passes.
self.remaining_time -= 1;
}
@ -347,13 +351,13 @@ fn main() {
.collect::<Vec<_>>()
.iter()
.map(|l| Blueprint {
id: l[1].trim_end_matches(':').parse::<usize>().unwrap(),
ore_robot_ore_cost: l[6].parse::<usize>().unwrap(),
clay_robot_ore_cost: l[12].parse::<usize>().unwrap(),
obsidian_robot_ore_cost: l[18].parse::<usize>().unwrap(),
obsidian_robot_clay_cost: l[21].parse::<usize>().unwrap(),
geode_robot_ore_cost: l[27].parse::<usize>().unwrap(),
geode_robot_obsidian_cost: l[30].parse::<usize>().unwrap(),
id: l[1].trim_end_matches(':').parse::<u16>().unwrap(),
ore_robot_ore_cost: l[6].parse::<u16>().unwrap(),
clay_robot_ore_cost: l[12].parse::<u16>().unwrap(),
obsidian_robot_ore_cost: l[18].parse::<u16>().unwrap(),
obsidian_robot_clay_cost: l[21].parse::<u16>().unwrap(),
geode_robot_ore_cost: l[27].parse::<u16>().unwrap(),
geode_robot_obsidian_cost: l[30].parse::<u16>().unwrap(),
optimal_geode_count: 0,
})
.collect::<Vec<_>>();
@ -370,6 +374,6 @@ fn main() {
blueprints
.iter()
.map(|b| b.id * b.optimal_geode_count)
.sum::<usize>()
.sum::<u16>()
);
}