day5: wip optimize

This commit is contained in:
Ishan Jain 2023-12-05 16:38:21 +05:30
parent 75841ecc80
commit b478bfaf9d
Signed by: ishan
GPG Key ID: 0506DB2A1CC75C27
2 changed files with 86 additions and 36 deletions

View File

@ -7,24 +7,22 @@ extern crate test;
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; 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 mut lines = data.split("\n\n");
let seeds: Vec<u64> = lines let seeds = lines
.next() .next()
.map(|x| x.split(' ').skip(1).map(|y| y.parse::<u64>().unwrap())) .map(|x| x.split(' ').skip(1).map(|y| y.parse::<i64>().unwrap()))
.unwrap() .unwrap();
.collect(); let maps: Vec<Vec<(Range<i64>, Range<i64>)>> = lines
let maps: Vec<Vec<(Range<u64>, Range<u64>)>> = lines
.map(|lines| { .map(|lines| {
lines lines
.lines() .lines()
.skip(1) .skip(1)
.map(|line| { .map(|line| {
let y: Vec<u64> = line let y: Vec<i64> = line
.split_ascii_whitespace() .split_ascii_whitespace()
.map(|y| y.parse::<u64>().unwrap()) .map(|y| y.parse::<i64>().unwrap())
.collect(); .collect();
let size = y[2]; let size = y[2];
@ -34,7 +32,7 @@ fn process(data: &str) -> u64 {
}) })
.collect(); .collect();
let mut answer = std::u64::MAX; let mut answer = std::i64::MAX;
for mut src in seeds { for mut src in seeds {
for map in maps.iter() { for map in maps.iter() {

View File

@ -1,4 +1,4 @@
#![feature(slice_split_once)] #![feature(iter_array_chunks)]
#![feature(test)] #![feature(test)]
use std::ops::Range; use std::ops::Range;
@ -7,59 +7,111 @@ extern crate test;
const INPUTS: [&str; 2] = [include_str!("./sample.txt"), include_str!("./input.txt")]; 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 mut lines = data.split("\n\n");
let seeds: Vec<u64> = lines let mut seeds: Vec<Range<i64>> = lines
.next() .next()
.map(|x| { .map(|x| {
let v: Vec<u64> = x let v: Vec<i64> = x
.split(' ') .split(' ')
.skip(1) .skip(1)
.map(|y| y.parse::<u64>().unwrap()) .map(|y| y.parse::<i64>().unwrap())
.collect(); .collect();
v.chunks(2) v.chunks(2)
.flat_map(|x| (x[0]..x[0] + x[1]).collect::<Vec<u64>>()) .map(|x| (x[0]..x[0] + x[1]))
.collect::<Vec<u64>>() .collect::<Vec<Range<i64>>>()
}) })
.unwrap(); .unwrap();
let maps: Vec<Vec<(Range<u64>, Range<u64>)>> = lines let maps: Vec<Vec<(Range<i64>, Range<i64>)>> = lines
.map(|lines| { .map(|lines| {
lines lines
.lines() .lines()
.skip(1) .skip(1)
.map(|line| { .map(|line| {
let y: Vec<u64> = line line.split_ascii_whitespace()
.split_ascii_whitespace() .map(|y| y.parse::<i64>().unwrap())
.map(|y| y.parse::<u64>().unwrap()) .array_chunks::<2>()
.collect(); .map(|y| {
let size = y[2]; 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()
}) })
.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 { out.extend(splitted);
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;
} }
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<i64>, Range<i64>)], node: Range<i64>) -> Vec<Range<i64>> {
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() { fn main() {