Part 05
This commit is contained in:
166
src/bin/part05.rs
Normal file
166
src/bin/part05.rs
Normal 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
|
||||
}
|
||||
Reference in New Issue
Block a user