diff --git a/src/days/day5.rs b/src/days/day5.rs index c98e6bf..f92b6aa 100644 --- a/src/days/day5.rs +++ b/src/days/day5.rs @@ -19,6 +19,16 @@ impl RangeMap { None } } + + fn inverse_map(&self, input: u32) -> Option { + let upper_bound: u64 = self.dest as u64 + self.length as u64; + if input >= self.dest && (input as u64) < upper_bound { + Some(input - self.dest + self.start) + } + else { + None + } + } } #[derive(Debug)] @@ -36,6 +46,16 @@ impl Mapping { } input } + + fn inverse_map(self: &Self, input: u32) -> u32 { + for range_map in self.range_maps.iter() { + match range_map.inverse_map(input) { + Some(x) => return x, + None => continue + } + } + input + } } #[derive(Debug)] @@ -64,23 +84,41 @@ impl Almanac { } } - fn find_closest(self: &Self) -> u32 { - let total_mapping = vec![ + fn find_closest(self: &Self, forward: bool) -> Result { + let mut total_mapping = vec![ &self.seed_to_soil_map, &self.soil_to_fertilizer_map, &self.fertilizer_to_water_map, &self.water_to_light_map, &self.light_to_temperature_map, &self.temperature_to_humidity_map, - &self.humidity_to_location_map + &self.humidity_to_location_map, ]; - self.seeds.clone().into_iter().map(|seed| { - total_mapping - .iter() - .fold(seed, | input, map| { - map.map(input) - }) - }).min().unwrap() + + if forward { + self.seeds.iter().map(|seed| { + total_mapping + .iter() + .fold(*seed, | input, map| { + map.map(input) + }) + }).min().ok_or(AdventError("mapping procedure went wrong".into())) + } else { + total_mapping.reverse(); + for loc in 0..u32::MAX { + let seed = total_mapping + .iter() + .fold(loc, | input, map| { + map.inverse_map(input) + }); + match self.seeds.binary_search(&seed) { + Ok(_) => return Ok(loc), + Err(_) => continue + } + }; + Err(AdventError("Scanned location space, found nothing".into())) + } + } fn interpret_range(self: &mut Self) -> () { @@ -91,7 +129,8 @@ impl Almanac { vec.push(seed); } } - self.seeds = vec; + vec.sort(); + self.seeds = vec } } @@ -178,12 +217,12 @@ impl FromStr for Almanac { pub fn one() -> Result { let almanac = read_into::(Path::new("resources/input5.txt".into()))?; - Ok(almanac.find_closest()) + Ok(almanac.find_closest(true)?) } pub fn two() -> Result { let mut almanac = read_into::(Path::new("resources/input5.txt".into()))?; almanac.interpret_range(); - Ok(almanac.find_closest()) + Ok(almanac.find_closest(false)?) } \ No newline at end of file