Create unusably inefficient solution to 2023 day5 part 2
This commit is contained in:
parent
ba4e489cdb
commit
6d9aaf081d
@ -130,3 +130,26 @@ number**. In this example, the corresponding types are:
|
||||
So, the lowest location number in this example is `**35**`.
|
||||
|
||||
**What is the lowest location number that corresponds to any of the initial seed numbers?**
|
||||
|
||||
## Part 2
|
||||
|
||||
Everyone will starve if you only plant such a small number of seeds. Re-reading the almanac, it looks like the seeds:
|
||||
line actually describes ranges of seed numbers.
|
||||
|
||||
The values on the initial seeds: line come in pairs. Within each pair, the first value is the start of the range and
|
||||
the second value is the length of the range. So, in the first line of the example above:
|
||||
|
||||
`seeds: 79 14 55 13`
|
||||
|
||||
This line describes two ranges of seed numbers to be planted in the garden. The first range starts with seed number `79`
|
||||
and contains 14 values: `79`, `80`, ..., `91`, `92`. The second range starts with seed number `55` and contains `13`
|
||||
values: `55`, `56`, ..., `66`, `67`.
|
||||
|
||||
Now, rather than considering four seed numbers, you need to consider a total of **27** seed numbers.
|
||||
|
||||
In the above example, the lowest location number can be obtained from seed number `82`, which corresponds to soil `84`,
|
||||
fertilizer `84`, water `84`, light `77`, temperature `45`, humidity `46`, and location `46`.
|
||||
So, the lowest location number is `46`.
|
||||
|
||||
Consider all of the initial seed numbers listed in the ranges on the first line of the almanac.
|
||||
**What is the lowest location number that corresponds to any of the initial seed numbers?**
|
||||
|
@ -50,9 +50,13 @@ impl DataMap {
|
||||
}
|
||||
|
||||
fn get_dest_idx(&self, src_value: u64) -> Option<u64> {
|
||||
if !self.to_range.contains(&src_value) {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(idx) = src_value.checked_sub(self.to_range.start) {
|
||||
if let Some(new_idx) = self.from_range.start.checked_add(idx) {
|
||||
if new_idx < self.from_range.end {
|
||||
if self.from_range.contains(&new_idx) {
|
||||
return Some(new_idx);
|
||||
}
|
||||
}
|
||||
@ -67,6 +71,7 @@ type MapMap = HashMap<(DataType, DataType), Vec<DataMap>>;
|
||||
#[derive(Debug, Default)]
|
||||
struct Almanac {
|
||||
seeds: Vec<u64>,
|
||||
seed_ranges: Vec<Range<u64>>,
|
||||
maps: MapMap,
|
||||
}
|
||||
|
||||
@ -85,6 +90,22 @@ impl Almanac {
|
||||
.map(|s| s.parse::<u64>().unwrap())
|
||||
.collect();
|
||||
|
||||
let even_seeds: Vec<_> = seeds
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, s)| if i % 2 == 0 { Some(*s) } else { None })
|
||||
.collect();
|
||||
let odd_seeds: Vec<_> = seeds
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, s)| if i % 2 == 1 { Some(*s) } else { None })
|
||||
.collect();
|
||||
let seed_ranges = even_seeds
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, s)| s..(s + odd_seeds[i]))
|
||||
.collect();
|
||||
|
||||
let maps = data_chunks
|
||||
.into_iter()
|
||||
.map(|chunk| {
|
||||
@ -113,40 +134,26 @@ impl Almanac {
|
||||
})
|
||||
.collect();
|
||||
|
||||
Almanac { seeds, maps }
|
||||
Almanac {
|
||||
seeds,
|
||||
seed_ranges,
|
||||
maps,
|
||||
}
|
||||
}
|
||||
|
||||
fn x_from_y(&self, x: DataType, y: DataType, search: u64) -> u64 {
|
||||
let maps = self
|
||||
.maps
|
||||
self.maps
|
||||
.get(&(y, x))
|
||||
.expect(&format!("Missing mapping from {:?} to {:?}", x, y));
|
||||
let mut mapped_value: Vec<Option<u64>> = maps
|
||||
.expect(&format!("Missing mapping from {:?} to {:?}", x, y))
|
||||
.into_iter()
|
||||
.map(|dm| dm.get_dest_idx(search))
|
||||
.filter(|r| r.is_some())
|
||||
.collect();
|
||||
|
||||
if mapped_value.is_empty() {
|
||||
return search;
|
||||
}
|
||||
|
||||
mapped_value.pop().unwrap().unwrap()
|
||||
}
|
||||
|
||||
fn soil_from_seed(&self, seed: u64) -> u64 {
|
||||
use DataType::*;
|
||||
|
||||
self.x_from_y(Soil, Seed, seed)
|
||||
}
|
||||
|
||||
fn fertilizer_from_soil(&self, soil: u64) -> u64 {
|
||||
self.x_from_y(Fertilizer, Soil, soil)
|
||||
.filter(|dm| dm.to_range.contains(&search))
|
||||
.find_map(|dm| dm.get_dest_idx(search))
|
||||
.unwrap_or_else(|| search)
|
||||
}
|
||||
|
||||
fn location_from_seed(&self, seed: u64) -> u64 {
|
||||
let soil = self.soil_from_seed(seed);
|
||||
let fert = self.fertilizer_from_soil(soil);
|
||||
let soil = self.x_from_y(Soil, Seed, seed);
|
||||
let fert = self.x_from_y(Fertilizer, Soil, soil);
|
||||
let water = self.x_from_y(Water, Fertilizer, fert);
|
||||
let light = self.x_from_y(Light, Water, water);
|
||||
let temp = self.x_from_y(Temperature, Light, light);
|
||||
@ -169,15 +176,38 @@ impl Almanac {
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn lowest_seed_range_location(&self) -> u64 {
|
||||
self.seed_ranges
|
||||
.iter()
|
||||
.map(|r| {
|
||||
r.clone()
|
||||
.into_iter()
|
||||
.map(|s| self.location_from_seed(s))
|
||||
.min()
|
||||
.unwrap()
|
||||
})
|
||||
.min()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
let almanac = Almanac::parse(FILE_STR);
|
||||
println!("Part 1: Lowest seed location: {}", almanac.lowest_seed_location());
|
||||
fn part_one(a: &Almanac) {
|
||||
println!("Part 1: Lowest seed location: {}", a.lowest_seed_location());
|
||||
}
|
||||
|
||||
fn part_two(a: &Almanac) {
|
||||
/* println!("{:#?}", a.seed_ranges); */
|
||||
println!(
|
||||
"Part 2: Lowest seed range location: {}",
|
||||
a.lowest_seed_range_location()
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
part_one();
|
||||
let almanac = Almanac::parse(FILE_STR);
|
||||
part_one(&almanac);
|
||||
part_two(&almanac);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -208,4 +238,22 @@ mod tests {
|
||||
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||
assert_eq!(35, almanac.lowest_seed_location());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_seed_ranges() {
|
||||
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||
let range1 = 79u64..93;
|
||||
let range2 = 55u64..68;
|
||||
|
||||
assert!(almanac.seed_ranges.contains(&range1));
|
||||
assert!(almanac.seed_ranges.contains(&range2))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lowest_seed_range_location() {
|
||||
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||
assert_ne!(45, almanac.lowest_seed_range_location());
|
||||
assert_eq!(46, almanac.lowest_seed_range_location());
|
||||
assert_ne!(47, almanac.lowest_seed_range_location());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user