167 lines
4.8 KiB
Rust
167 lines
4.8 KiB
Rust
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
|
|
}
|