From b478bfaf9db85b139e11ce6216a065ccc3065922 Mon Sep 17 00:00:00 2001 From: Ishan Jain Date: Tue, 5 Dec 2023 16:38:21 +0530 Subject: [PATCH] day5: wip optimize --- src/day5/1.rs | 18 ++++----- src/day5/2.rs | 104 +++++++++++++++++++++++++++++++++++++------------- 2 files changed, 86 insertions(+), 36 deletions(-) diff --git a/src/day5/1.rs b/src/day5/1.rs index 77867e0..7fea732 100644 --- a/src/day5/1.rs +++ b/src/day5/1.rs @@ -7,24 +7,22 @@ extern crate test; const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; -fn process(data: &str) -> u64 { +fn process(data: &str) -> i64 { let mut lines = data.split("\n\n"); - let seeds: Vec = lines + let seeds = lines .next() - .map(|x| x.split(' ').skip(1).map(|y| y.parse::().unwrap())) - .unwrap() - .collect(); - - let maps: Vec, Range)>> = lines + .map(|x| x.split(' ').skip(1).map(|y| y.parse::().unwrap())) + .unwrap(); + let maps: Vec, Range)>> = lines .map(|lines| { lines .lines() .skip(1) .map(|line| { - let y: Vec = line + let y: Vec = line .split_ascii_whitespace() - .map(|y| y.parse::().unwrap()) + .map(|y| y.parse::().unwrap()) .collect(); let size = y[2]; @@ -34,7 +32,7 @@ fn process(data: &str) -> u64 { }) .collect(); - let mut answer = std::u64::MAX; + let mut answer = std::i64::MAX; for mut src in seeds { for map in maps.iter() { diff --git a/src/day5/2.rs b/src/day5/2.rs index 20ede3f..20e26a0 100644 --- a/src/day5/2.rs +++ b/src/day5/2.rs @@ -1,4 +1,4 @@ -#![feature(slice_split_once)] +#![feature(iter_array_chunks)] #![feature(test)] use std::ops::Range; @@ -7,59 +7,111 @@ extern crate test; const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; -fn process(data: &str) -> u64 { +fn process(data: &str) -> i64 { let mut lines = data.split("\n\n"); - let seeds: Vec = lines + let mut seeds: Vec> = lines .next() .map(|x| { - let v: Vec = x + let v: Vec = x .split(' ') .skip(1) - .map(|y| y.parse::().unwrap()) + .map(|y| y.parse::().unwrap()) .collect(); v.chunks(2) - .flat_map(|x| (x[0]..x[0] + x[1]).collect::>()) - .collect::>() + .map(|x| (x[0]..x[0] + x[1])) + .collect::>>() }) .unwrap(); - let maps: Vec, Range)>> = lines + let maps: Vec, Range)>> = lines .map(|lines| { lines .lines() .skip(1) .map(|line| { - let y: Vec = line - .split_ascii_whitespace() - .map(|y| y.parse::().unwrap()) - .collect(); - let size = y[2]; + line.split_ascii_whitespace() + .map(|y| y.parse::().unwrap()) + .array_chunks::<2>() + .map(|y| { + let size = y[2]; - (y[1]..y[1] + size, y[0]..y[0] + size) + (y[1]..y[1] + size, y[0]..y[0] + size) + }) + .collect() }) .collect() }) .collect(); + for map in maps { + let mut out = vec![]; - let mut answer = std::u64::MAX; + for seed in seeds.drain(..) { + // split seed based on this rangemap + let splitted = split(&map, seed); - for mut src in seeds { - for map in maps.iter() { - let dst = map - .iter() - .find(|x| x.0.contains(&src)) - .map(|x| src + x.1.start - x.0.start) - .unwrap_or(src); - - src = dst; + out.extend(splitted); } - answer = std::cmp::min(answer, src); + seeds.extend_from_slice(&out); } - answer + seeds.into_iter().map(|x| x.start).min().unwrap() +} + +fn split(map: &[(Range, Range)], node: Range) -> Vec> { + let mut out = vec![]; + + let mut stack = vec![node]; + + while let Some(node) = stack.pop() { + let mut found_match = false; + + for (src, dst) in map.iter() { + let overlap = std::cmp::max(0, node.end.min(src.end) - node.start.max(src.start)); + + if overlap == 0 { + continue; + } else if node.start > src.start && node.end < src.end { + let offset = std::cmp::max(0, node.start - src.start); + let dst = dst.start + offset..dst.start + offset + overlap; + found_match = true; + out.push(dst); + } else if node.start < src.start && node.end > src.end { + let r1_non = node.start..src.start; + let r2_non = src.end..node.end; + + found_match = true; + + out.push(dst.clone()); + stack.push(r1_non); + stack.push(r2_non); + } else { + // Partial overlap + + let offset = std::cmp::max(0, node.start - src.start); + + let dst_range = dst.start + offset..dst.start + offset + overlap; + + found_match = true; + let new_range = if node.start < src.start { + node.start..src.start + } else { + src.end..node.end + }; + + stack.push(new_range); + out.push(dst_range); + } + } + + if !found_match { + out.push(node); + } + } + + out } fn main() {