2023/day05.rs
2023-12-06 03:11:21 +01:00

78 lines
2.1 KiB
Rust

fn parse_map(lines: &mut std::str::Lines<'_>) -> Vec<(u64, u64, u64)> {
let mut map = Vec::new();
loop {
let line = lines.next();
if line.is_none() {
break map;
}
let line = line.unwrap();
if line.is_empty() {
lines.next();
break map;
}
let mut tokens = line
.split_ascii_whitespace()
.map(|n| n.parse::<u64>().unwrap());
let numbers = (
tokens.next().unwrap(),
tokens.next().unwrap(),
tokens.next().unwrap(),
);
map.push(numbers);
}
}
fn transform_ranges(map: &[(u64, u64, u64)], ranges: &[(u64, u64)]) -> Vec<(u64, u64)> {
let mut output_ranges = Vec::new();
for (start, length) in ranges {
let (dst_start, src_start, len) = map
.iter()
.find(|(_dst, src, len)| src <= start && *start < (src + len))
.unwrap_or(&(0u64, 0u64, u64::MAX));
let end = start + length;
let src_end = src_start + len;
output_ranges.push((
dst_start + start - src_start,
u64::min(src_end, end) - start,
));
if end > src_end {
output_ranges.extend(transform_ranges(map, &[(src_end, end - src_end)]));
}
}
output_ranges
}
fn do_the_thing(maps: &Vec<Vec<(u64, u64, u64)>>, mut ranges: Vec<(u64, u64)>) -> u64 {
for map in maps {
ranges = transform_ranges(map, &ranges);
}
ranges.iter().min().unwrap().0
}
fn main() {
let mut lines = include_str!("day05.in").lines();
let line = lines.next().unwrap();
let (_, seeds) = line.trim().split_once(": ").unwrap();
let seeds: Vec<u64> = seeds
.split_ascii_whitespace()
.map(|n| n.parse().unwrap())
.collect();
lines.next();
lines.next();
let maps: Vec<Vec<_>> = (0..7).map(|_| parse_map(&mut lines)).collect();
let part1 = do_the_thing(&maps, seeds.iter().map(|&seed| (seed, 1)).collect());
let part2 = do_the_thing(
&maps,
seeds.chunks(2).map(|chunk| (chunk[0], chunk[1])).collect(),
);
dbg!(part1, part2);
}