generated from janezicmatej/aoc-template
solution: day 5 clean
This commit is contained in:
parent
00000110da
commit
000001200a
|
@ -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),
|
||||||
} else {
|
min(self.source + self.range, s + r),
|
||||||
0
|
];
|
||||||
}
|
fences.sort();
|
||||||
};
|
|
||||||
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) {
|
let mut v = Vec::new();
|
||||||
rest.push((s, self.source - s));
|
|
||||||
|
for i in 0..3 {
|
||||||
|
let f = fences[i];
|
||||||
|
let nf = fences[i + 1];
|
||||||
|
if f != nf {
|
||||||
|
v.push(Some((f, nf - f)))
|
||||||
|
} else {
|
||||||
|
v.push(None)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue