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() }