day5: optimized

This commit is contained in:
Ishan Jain 2023-12-05 18:52:42 +05:30
parent dbe738c17e
commit 8b39941cb5
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27

View File

@ -1,4 +1,3 @@
#![feature(iter_array_chunks)]
#![feature(test)] #![feature(test)]
use std::ops::Range; use std::ops::Range;
@ -20,79 +19,80 @@ fn process(data: &str) -> i64 {
.collect(); .collect();
v.chunks(2) v.chunks(2)
.map(|x| (x[0]..x[0] + x[1])) .map(|x| x[0]..x[0] + x[1])
.collect::<Vec<Range<i64>>>() .collect::<Vec<Range<i64>>>()
}) })
.unwrap(); .unwrap();
let maps: Vec<Vec<(Range<i64>, Range<i64>)>> = lines let maps = lines.map(|lines| {
.map(|lines| { lines
lines .lines()
.lines() .skip(1)
.skip(1) .map(|line| {
.map(|line| { let y: Vec<i64> = line
let y: Vec<i64> = line .split_ascii_whitespace()
.split_ascii_whitespace() .map(|y| y.parse::<i64>().unwrap())
.map(|y| y.parse::<i64>().unwrap()) .collect();
.collect(); let size = y[2];
let size = y[2];
(y[1]..y[1] + size, y[0]..y[0] + size)
})
.collect::<Vec<(Range<i64>, Range<i64>)>>()
});
(y[1]..y[1] + size, y[0]..y[0] + size)
})
.collect()
})
.collect();
for map in maps { for map in maps {
let mut out = vec![]; let mut out = Vec::with_capacity(seeds.len());
for seed in seeds.drain(..) { for seed in seeds {
// split seed based on this rangemap // split seed based on this rangemap
let splitted = split(&map, seed); let splitted = split(&map, seed);
out.extend(splitted); out.extend(splitted);
} }
seeds.extend_from_slice(&out); seeds = 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>> { fn split(map: &[(Range<i64>, Range<i64>)], node: Range<i64>) -> Vec<Range<i64>> {
let mut out = vec![]; let mut out = Vec::with_capacity(map.len());
let mut stack = vec![node]; let mut stack = vec![node];
while let Some(node) = stack.pop() { while let Some(node) = stack.pop() {
let mut found_match = false; let mut found_match = false;
for (src, dst) in map.iter() { 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)); let overlap = std::cmp::max(0, node.end.min(src.end) - node.start.max(src.start));
if overlap <= 0 {
break;
}
if overlap == 0 { let dst = if node.start == src.start && node.end == src.end {
continue; dst.clone()
} else if node.start > src.start && node.end < src.end { } else if node.start >= src.start && node.end <= src.end {
// src engulfs node
let offset = std::cmp::max(0, node.start - src.start); let offset = std::cmp::max(0, node.start - src.start);
let dst = dst.start + offset..dst.start + offset + overlap;
found_match = true; dst.start + offset..dst.start + offset + overlap
out.push(dst);
} else if node.start < src.start && node.end > src.end { } else if node.start < src.start && node.end > src.end {
// node engulfs src
let r1_non = node.start..src.start; let r1_non = node.start..src.start;
let r2_non = src.end..node.end; let r2_non = src.end..node.end;
found_match = true; stack.extend([r1_non, r2_non]);
out.push(dst.clone()); dst.clone()
stack.push(r1_non);
stack.push(r2_non);
} else { } else {
// Partial overlap // Partial overlap
let offset = std::cmp::max(0, node.start - src.start); let offset = std::cmp::max(0, node.start - src.start);
let dst_range = dst.start + offset..dst.start + offset + overlap; let dst_range = dst.start + offset..dst.start + offset + overlap;
found_match = true;
let new_range = if node.start < src.start { let new_range = if node.start < src.start {
node.start..src.start node.start..src.start
} else { } else {
@ -100,8 +100,11 @@ fn split(map: &[(Range<i64>, Range<i64>)], node: Range<i64>) -> Vec<Range<i64>>
}; };
stack.push(new_range); stack.push(new_range);
out.push(dst_range); dst_range
} };
found_match = true;
out.push(dst);
} }
if !found_match { if !found_match {
@ -114,12 +117,12 @@ fn split(map: &[(Range<i64>, Range<i64>)], node: Range<i64>) -> Vec<Range<i64>>
fn main() { fn main() {
for input in INPUTS.iter() { for input in INPUTS.iter() {
println!("total = {}", process(input)); println!("answer = {}", process(input));
} }
} }
#[bench] #[bench]
fn part1(b: &mut test::Bencher) { fn part2(b: &mut test::Bencher) {
b.iter(|| { b.iter(|| {
let v = process(INPUTS[1]); let v = process(INPUTS[1]);
test::black_box(v); test::black_box(v);