diff --git a/README.md b/README.md
index 4d94a50..27df0fa 100644
--- a/README.md
+++ b/README.md
@@ -42,7 +42,7 @@ My solutions to [Advent of Code](https://adventofcode.com) puzzles.
| 21 | [Step Counter](https://adventofcode.com/2023/day/21) | [day21.rs](aoc2023/src/day21.rs) |
| 22 | [Sand Slabs](https://adventofcode.com/2023/day/22) | [day22.rs](aoc2023/src/day22.rs) |
| 23 | [A Long Walk](https://adventofcode.com/2023/day/23) | [day23.rs](aoc2023/src/day23.rs) |
-| 24 | [Never Tell Me The ...](https://adventofcode.com/2023/day/24) | [day24.rs](aoc2023/src/day24.rs) |
+| 24 | [Never Tell Me The Odds](https://adventofcode.com/2023/day/24) | [day24.rs](aoc2023/src/day24.rs) |
| 25 | [Snowverload](https://adventofcode.com/2023/day/25) | [day25.rs](aoc2023/src/day25.rs) |
@@ -53,7 +53,7 @@ My solutions to [Advent of Code](https://adventofcode.com) puzzles.
| 112.7 µs | 1.056 µs |
| 5.884 µs | 508.0 µs |
| 92.21 µs | 27.78 µs |
-| 46.67 µs | 5.350 µs |
+| 21.77 µs | 5.197 µs |
| 16.90 µs | 0.248 µs |
| 170.1 µs | 76.89 µs |
| 181.6 µs | 323.7 µs |
@@ -83,7 +83,7 @@ My solutions to [Advent of Code](https://adventofcode.com) puzzles.
| 126.6 µs | 1.347 µs |
| 0.462 µs | 437.1 µs |
| 113.4 µs | 27.97 µs |
-| 47.31 µs | 22.520 s |
+| 17.87 µs | 108.7 µs |
| 0.666 µs | 0.659 µs |
| 177.0 µs | 66.30 µs |
| 153.8 µs | 1.069 ms |
diff --git a/aoc2023/src/day5.rs b/aoc2023/src/day5.rs
index a92bb1c..ad93c41 100644
--- a/aoc2023/src/day5.rs
+++ b/aoc2023/src/day5.rs
@@ -60,46 +60,84 @@ fn part1(input: &utils::Almanac) -> u64 {
#[aoc(day5, part2)]
fn part2(input: &utils::Almanac) -> u64 {
- use rayon::prelude::*;
-
let utils::Almanac { seeds, mappings } = input;
seeds
- .par_chunks(2)
- .map(|chunk| {
- let (seed_range_start, seed_range_end) = (chunk[0], chunk[0] + chunk[1]);
- seed_range_start..seed_range_end
- })
- .map(|seed_range| {
- let mut cached_index =
- smallvec::SmallVec::<[usize; 7]>::from_elem(usize::MAX, mappings.len());
- let mut cached_diff = smallvec::SmallVec::<[i64; 7]>::from_elem(0, mappings.len());
- seed_range
- .map(|seed| {
- mappings
- .iter()
- .enumerate()
- .fold(seed, |value, (i, mapping)| {
- if cached_index[i] != usize::MAX
- && mapping[cached_index[i]].from.contains(&value)
- {
- value.wrapping_add_signed(cached_diff[i])
- } else {
- mapping
- .iter()
- .enumerate()
- .find(|(_, range_map)| range_map.from.contains(&value))
- .map_or(value, |(j, range_map)| {
- cached_index[i] = j;
- cached_diff[i] = i64::try_from(range_map.to_start).unwrap()
- - i64::try_from(range_map.from.start).unwrap();
- value.wrapping_add_signed(cached_diff[i])
- })
- }
- })
- })
- .min()
- .unwrap()
+ .chunks(2)
+ .map(|nums| nums[0]..(nums[0] + nums[1]))
+ .flat_map(|seed_range| {
+ mappings.iter().fold(
+ smallvec::SmallVec::<[_; 32]>::from_elem(seed_range, 1),
+ |seed_ranges, mappings| {
+ let mut mapped_ranges = smallvec::SmallVec::new();
+ let leftover_ranges =
+ mappings.iter().fold(seed_ranges, |seed_ranges, mapping| {
+ seed_ranges
+ .into_iter()
+ .flat_map(|seed_range| {
+ if seed_range.start >= mapping.from.end
+ || seed_range.end <= mapping.from.start
+ {
+ [seed_range, std::ops::Range::default()]
+ } else if seed_range.start <= mapping.from.start
+ && seed_range.end >= mapping.from.end
+ {
+ let mapped = mapping.to_start
+ ..mapping.to_start + mapping.from.end
+ - mapping.from.start;
+ if mapped.start < mapped.end {
+ mapped_ranges.push(mapped);
+ }
+
+ [
+ seed_range.start..mapping.from.start,
+ mapping.from.end..seed_range.end,
+ ]
+ } else if seed_range.start >= mapping.from.start
+ && seed_range.end <= mapping.from.end
+ {
+ let mapped = seed_range.start - mapping.from.start
+ + mapping.to_start
+ ..seed_range.end - mapping.from.start
+ + mapping.to_start;
+ if mapped.start < mapped.end {
+ mapped_ranges.push(mapped);
+ }
+
+ [std::ops::Range::default(), std::ops::Range::default()]
+ } else {
+ let mapped = seed_range.start.max(mapping.from.start)
+ - mapping.from.start
+ + mapping.to_start
+ ..seed_range.end.min(mapping.from.end)
+ - mapping.from.start
+ + mapping.to_start;
+ if mapped.start < mapped.end {
+ mapped_ranges.push(mapped);
+ }
+
+ let leftover_start =
+ if seed_range.start < mapping.from.start {
+ seed_range.start
+ } else {
+ mapping.from.end
+ };
+ let leftover_end = if seed_range.end > mapping.from.end {
+ seed_range.end
+ } else {
+ mapping.from.start
+ };
+ [leftover_start..leftover_end, std::ops::Range::default()]
+ }
+ })
+ .filter(|range| range.start < range.end)
+ .collect()
+ });
+ mapped_ranges.extend(leftover_ranges);
+ mapped_ranges
+ },
+ )
})
+ .map(|range| range.start)
.min()
.unwrap()
}
|