This commit is contained in:
MaxJa4
2023-12-06 22:53:23 +01:00
parent 737572af89
commit 79719bbb10
3 changed files with 412 additions and 0 deletions

166
src/bin/part05.rs Normal file
View File

@@ -0,0 +1,166 @@
use std::time;
use rayon::prelude::*;
struct Almanac {
seeds: Vec<u32>,
seed_to_soil: Vec<Mapping>,
soil_to_fertilizer: Vec<Mapping>,
fertilizer_to_water: Vec<Mapping>,
water_to_light:Vec<Mapping>,
light_to_temperature: Vec<Mapping>,
temperature_to_humidity: Vec<Mapping>,
humidity_to_location: Vec<Mapping>,
}
impl Almanac {
fn new() -> Almanac {
Almanac {
seeds: Vec::new(),
seed_to_soil: Vec::new(),
soil_to_fertilizer: Vec::new(),
fertilizer_to_water: Vec::new(),
water_to_light: Vec::new(),
light_to_temperature: Vec::new(),
temperature_to_humidity: Vec::new(),
humidity_to_location: Vec::new(),
}
}
fn get_soil(&self, seed: u32) -> u32 {
map(seed, &self.seed_to_soil)
}
fn get_fertilizer(&self, seed: u32) -> u32 {
map(self.get_soil(seed), &self.soil_to_fertilizer)
}
fn get_water(&self, seed: u32) -> u32 {
map(self.get_fertilizer(seed), &self.fertilizer_to_water)
}
fn get_light(&self, seed: u32) -> u32 {
map(self.get_water(seed), &self.water_to_light)
}
fn get_temperature(&self, seed: u32) -> u32 {
map(self.get_light(seed), &self.light_to_temperature)
}
fn get_humidity(&self, seed: u32) -> u32 {
map(self.get_temperature(seed), &self.temperature_to_humidity)
}
fn get_location(&self, seed: u32) -> u32 {
map(self.get_humidity(seed), &self.humidity_to_location)
}
}
struct Mapping {
dst_range_start: u64,
src_range_start: u64,
range_length: u64
}
fn main() {
let s = time::Instant::now();
let almanac = load_input();
let mut locations: Vec<u32> = Vec::new();
// for seed in &almanac.seeds {
// let location = almanac.get_location(*seed);
// locations.push(location);
// println!("Seed: {}", seed);
// println!("Location: {}", location);
// println!();
// }
// println!("Lowest location #1: {}", locations.iter().min().unwrap());
// locations.clear();
let mut seeds = almanac.seeds.iter();
loop {
let seed_start = seeds.next().unwrap_or(&0);
if *seed_start == 0 {
break;
}
let seed_end = seed_start + seeds.next().unwrap();
let seed_count = seed_end - seed_start;
let s1 = time::Instant::now();
let locs = (*seed_start..seed_end).into_par_iter().map(|seed| {
almanac.get_location(seed)
});
locations.push(locs.min().unwrap());
let d1 = time::Instant::now().duration_since(s1);
println!("Parsed {} seeds in {:?} ({} seeds/s)", seed_count, d1, seed_count as f64 / d1.as_secs_f64());
}
let d = time::Instant::now().duration_since(s);
println!("Parsed in {:?}", d);
println!("Lowest location #2: {}", locations.iter().min().unwrap());
}
fn load_input() -> Almanac {
let mut almanac = Almanac::new();
let data = std::fs::read_to_string("src/bin/part05.txt")
.expect("Could not read file");
let mut lines = data.lines();
almanac.seeds = lines.next().unwrap().split(": ").last().unwrap().split_whitespace().map(|s| s.parse::<u32>().unwrap()).collect::<Vec<_>>();
almanac.seed_to_soil = parse_map(&mut lines);
almanac.soil_to_fertilizer = parse_map(&mut lines);
almanac.fertilizer_to_water = parse_map(&mut lines);
almanac.water_to_light = parse_map(&mut lines);
almanac.light_to_temperature = parse_map(&mut lines);
almanac.temperature_to_humidity = parse_map(&mut lines);
almanac.humidity_to_location = parse_map(&mut lines);
almanac
}
fn parse_map(line_iter: &mut dyn Iterator<Item=&str>) -> Vec<Mapping> {
let mut mappings = Vec::new();
line_iter.nth(0);
loop {
let line = line_iter.next().unwrap_or("");
if line.is_empty() {
break;
} else if line.ends_with(":") {
continue;
}
let mut raw_mapping = line.split_whitespace();
mappings.push(Mapping {
dst_range_start: raw_mapping.next().unwrap().parse::<u64>().unwrap(),
src_range_start: raw_mapping.next().unwrap().parse::<u64>().unwrap(),
range_length: raw_mapping.next().unwrap().parse::<u64>().unwrap()
});
}
mappings.sort_by(|a, b| b.src_range_start.cmp(&a.src_range_start));
mappings
}
fn map(src: u32, mappings: &Vec<Mapping>) -> u32 {
let src = src as u64;
let mut dst = src;
let mapping = mappings.iter().find(|mapping| {
src >= mapping.src_range_start && src < mapping.src_range_start + mapping.range_length
});
if let Some(mapping) = mapping {
dst = (mapping.dst_range_start + src) - mapping.src_range_start;
}
dst as u32
}