solution: day 5 clean

This commit is contained in:
Matej Janezic 2023-12-06 00:48:46 +01:00
parent 00000110da
commit 000001200a
Signed by: janezicmatej
GPG Key ID: 4298E230ED37B2C0
1 changed files with 34 additions and 33 deletions

View File

@ -1,7 +1,12 @@
use std::{cmp::min, str::FromStr}; use std::{
cmp::{max, min},
str::FromStr,
};
use aoc::parsers::to_vec; use aoc::parsers::to_vec;
type PairRange = (u64, u64);
#[derive(Debug)] #[derive(Debug)]
struct Mapping { struct Mapping {
destination: u64, destination: u64,
@ -29,45 +34,37 @@ impl Mapping {
n >= self.source && n < self.source + self.range n >= self.source && n < self.source + self.range
} }
fn contains_any(&self, s: u64, r: u64) -> bool { fn contains_any(&self, (s, r): PairRange) -> bool {
s < self.source + self.range && s + r > self.source s < self.source + self.range && s + r > self.source
} }
fn map(&self, n: u64) -> u64 { fn map(&self, n: u64) -> u64 {
debug_assert!(self.contains(n));
let shift = n - self.source; let shift = n - self.source;
self.destination + shift self.destination + shift
} }
fn map_range(&self, s: u64, r: u64) -> ((u64, u64), Vec<(u64, u64)>) { fn split_range(&self, (s, r): PairRange) -> [Option<PairRange>; 3] {
debug_assert!(self.contains_any(s, r)); let mut fences = [
let shift = { s,
if self.contains(s) { s + r,
s - self.source max(self.source, s),
min(self.source + self.range, s + r),
];
fences.sort();
let mut v = Vec::new();
for i in 0..3 {
let f = fences[i];
let nf = fences[i + 1];
if f != nf {
v.push(Some((f, nf - f)))
} else { } else {
0 v.push(None)
} }
};
let neg_shift = {
if self.contains(s) {
0
} else {
self.source - s
}
};
let dest_start = self.destination + shift;
let dest_range = min(r - neg_shift, self.range - shift);
let mut rest = Vec::new();
if !self.contains(s) {
rest.push((s, self.source - s));
} }
if r - neg_shift > dest_range { v[..3].try_into().unwrap()
rest.push((self.source + self.range, r - dest_range))
}
((dest_start, dest_range), rest)
} }
} }
@ -125,10 +122,14 @@ pub fn part_two(input: &str) -> Option<u64> {
'queue: while let Some((s, r)) = seeds_ranges.pop() { 'queue: while let Some((s, r)) = seeds_ranges.pop() {
for map in mapping { for map in mapping {
if map.contains_any(s, r) { if map.contains_any((s, r)) {
let (rng, rest) = map.map_range(s, r); let [pre, to_map, post] = map.split_range((s, r));
new_ranges.push(rng); let to_map = to_map.unwrap();
seeds_ranges.extend_from_slice(&rest); let mapped = (map.map(to_map.0), to_map.1);
new_ranges.push(mapped);
for r in [pre, post].into_iter().flatten() {
seeds_ranges.push(r);
}
continue 'queue; continue 'queue;
} }
} }