day5/updates

1. Used the version from
   https://github.com/0e4ef622/aoc/blob/master/2023/day05/src/solution.rs
2. reduced allocations, in place updates to seed array
This commit is contained in:
Ishan Jain 2023-12-06 01:36:57 +05:30
parent 8b39941cb5
commit 1c007bf639
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27

View File

@ -1,3 +1,4 @@
#![feature(const_trait_impl)]
#![feature(test)] #![feature(test)]
use std::ops::Range; use std::ops::Range;
@ -40,79 +41,46 @@ fn process(data: &str) -> i64 {
.collect::<Vec<(Range<i64>, Range<i64>)>>() .collect::<Vec<(Range<i64>, Range<i64>)>>()
}); });
let mut out = Vec::with_capacity(seeds.len());
for map in maps { for map in maps {
let mut out = Vec::with_capacity(seeds.len()); for (src, dst) in map.iter() {
let mut i = 0;
while i < seeds.len() {
let seed = &seeds[i];
for seed in seeds { let [lno, overlap, rno] = intersect(src, &seed);
// split seed based on this rangemap
let splitted = split(&map, seed);
out.extend(splitted); if !overlap.is_empty() {
out.push(
overlap.start - src.start + dst.start..overlap.end - src.start + dst.start,
);
seeds.swap_remove(i);
if !lno.is_empty() {
seeds.push(lno);
}
if !rno.is_empty() {
seeds.push(rno);
}
} else {
i += 1;
}
}
} }
seeds = out seeds.append(&mut out);
} }
seeds.into_iter().map(|x| x.start).min().unwrap() seeds.into_iter().map(|x| x.start).min().unwrap()
} }
fn split(map: &[(Range<i64>, Range<i64>)], node: Range<i64>) -> Vec<Range<i64>> { #[inline]
let mut out = Vec::with_capacity(map.len()); fn intersect(node: &Range<i64>, src: &Range<i64>) -> [Range<i64>; 3] {
let mut stack = vec![node]; let overlap = src.start.max(node.start)..src.end.min(node.end);
let left_nonoverlap = src.start..overlap.start;
let right_nonoverlap = overlap.end..src.end;
while let Some(node) = stack.pop() { [left_nonoverlap, overlap, right_nonoverlap]
let mut found_match = false;
for (src, dst) in map
.iter()
.skip_while(|(src, _)| node.end.min(src.end) - node.start.max(src.start) <= 0)
{
let overlap = std::cmp::max(0, node.end.min(src.end) - node.start.max(src.start));
if overlap <= 0 {
break;
}
let dst = if node.start == src.start && node.end == src.end {
dst.clone()
} else if node.start >= src.start && node.end <= src.end {
// src engulfs node
let offset = std::cmp::max(0, node.start - src.start);
dst.start + offset..dst.start + offset + overlap
} else if node.start < src.start && node.end > src.end {
// node engulfs src
let r1_non = node.start..src.start;
let r2_non = src.end..node.end;
stack.extend([r1_non, r2_non]);
dst.clone()
} else {
// Partial overlap
let offset = std::cmp::max(0, node.start - src.start);
let dst_range = dst.start + offset..dst.start + offset + overlap;
let new_range = if node.start < src.start {
node.start..src.start
} else {
src.end..node.end
};
stack.push(new_range);
dst_range
};
found_match = true;
out.push(dst);
}
if !found_match {
out.push(node);
}
}
out
} }
fn main() { fn main() {