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")];
fn process(data: &str) -> u64 {
fn process(data: &str) -> i64 {
let mut lines = data.split("\n\n");
let seeds: Vec<u64> = lines
let seeds = lines
.next()
.map(|x| x.split(' ').skip(1).map(|y| y.parse::<u64>().unwrap()))
.unwrap()
.collect();
let maps: Vec<Vec<(Range<u64>, Range<u64>)>> = lines
.map(|x| x.split(' ').skip(1).map(|y| y.parse::<i64>().unwrap()))
.unwrap();
let maps: Vec<Vec<(Range<i64>, Range<i64>)>> = lines
.map(|lines| {
lines
.lines()
.skip(1)
.map(|line| {
let y: Vec<u64> = line
let y: Vec<i64> = line
.split_ascii_whitespace()
.map(|y| y.parse::<u64>().unwrap())
.map(|y| y.parse::<i64>().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() {

View File

@ -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<u64> = lines
let mut seeds: Vec<Range<i64>> = lines
.next()
.map(|x| {
let v: Vec<u64> = x
let v: Vec<i64> = x
.split(' ')
.skip(1)
.map(|y| y.parse::<u64>().unwrap())
.map(|y| y.parse::<i64>().unwrap())
.collect();
v.chunks(2)
.flat_map(|x| (x[0]..x[0] + x[1]).collect::<Vec<u64>>())
.collect::<Vec<u64>>()
.map(|x| (x[0]..x[0] + x[1]))
.collect::<Vec<Range<i64>>>()
})
.unwrap();
let maps: Vec<Vec<(Range<u64>, Range<u64>)>> = lines
let maps: Vec<Vec<(Range<i64>, Range<i64>)>> = lines
.map(|lines| {
lines
.lines()
.skip(1)
.map(|line| {
let y: Vec<u64> = line
.split_ascii_whitespace()
.map(|y| y.parse::<u64>().unwrap())
.collect();
let size = y[2];
line.split_ascii_whitespace()
.map(|y| y.parse::<i64>().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<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() {