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**`.
|
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?**
|
**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> {
|
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(idx) = src_value.checked_sub(self.to_range.start) {
|
||||||
if let Some(new_idx) = self.from_range.start.checked_add(idx) {
|
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);
|
return Some(new_idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,6 +71,7 @@ type MapMap = HashMap<(DataType, DataType), Vec<DataMap>>;
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
struct Almanac {
|
struct Almanac {
|
||||||
seeds: Vec<u64>,
|
seeds: Vec<u64>,
|
||||||
|
seed_ranges: Vec<Range<u64>>,
|
||||||
maps: MapMap,
|
maps: MapMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,6 +90,22 @@ impl Almanac {
|
|||||||
.map(|s| s.parse::<u64>().unwrap())
|
.map(|s| s.parse::<u64>().unwrap())
|
||||||
.collect();
|
.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
|
let maps = data_chunks
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|chunk| {
|
.map(|chunk| {
|
||||||
@ -113,40 +134,26 @@ impl Almanac {
|
|||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Almanac { seeds, maps }
|
Almanac {
|
||||||
|
seeds,
|
||||||
|
seed_ranges,
|
||||||
|
maps,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn x_from_y(&self, x: DataType, y: DataType, search: u64) -> u64 {
|
fn x_from_y(&self, x: DataType, y: DataType, search: u64) -> u64 {
|
||||||
let maps = self
|
self.maps
|
||||||
.maps
|
|
||||||
.get(&(y, x))
|
.get(&(y, x))
|
||||||
.expect(&format!("Missing mapping from {:?} to {:?}", x, y));
|
.expect(&format!("Missing mapping from {:?} to {:?}", x, y))
|
||||||
let mut mapped_value: Vec<Option<u64>> = maps
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|dm| dm.get_dest_idx(search))
|
.filter(|dm| dm.to_range.contains(&search))
|
||||||
.filter(|r| r.is_some())
|
.find_map(|dm| dm.get_dest_idx(search))
|
||||||
.collect();
|
.unwrap_or_else(|| search)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn location_from_seed(&self, seed: u64) -> u64 {
|
fn location_from_seed(&self, seed: u64) -> u64 {
|
||||||
let soil = self.soil_from_seed(seed);
|
let soil = self.x_from_y(Soil, Seed, seed);
|
||||||
let fert = self.fertilizer_from_soil(soil);
|
let fert = self.x_from_y(Fertilizer, Soil, soil);
|
||||||
let water = self.x_from_y(Water, Fertilizer, fert);
|
let water = self.x_from_y(Water, Fertilizer, fert);
|
||||||
let light = self.x_from_y(Light, Water, water);
|
let light = self.x_from_y(Light, Water, water);
|
||||||
let temp = self.x_from_y(Temperature, Light, light);
|
let temp = self.x_from_y(Temperature, Light, light);
|
||||||
@ -169,15 +176,38 @@ impl Almanac {
|
|||||||
.min()
|
.min()
|
||||||
.unwrap()
|
.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() {
|
fn part_one(a: &Almanac) {
|
||||||
let almanac = Almanac::parse(FILE_STR);
|
println!("Part 1: Lowest seed location: {}", a.lowest_seed_location());
|
||||||
println!("Part 1: Lowest seed location: {}", almanac.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() {
|
fn main() {
|
||||||
part_one();
|
let almanac = Almanac::parse(FILE_STR);
|
||||||
|
part_one(&almanac);
|
||||||
|
part_two(&almanac);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -208,4 +238,22 @@ mod tests {
|
|||||||
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
let almanac = Almanac::parse(EXAMPLE_FILE_STR);
|
||||||
assert_eq!(35, almanac.lowest_seed_location());
|
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