diff --git a/day05.rs b/day05.rs new file mode 100644 index 0000000..4768a97 --- /dev/null +++ b/day05.rs @@ -0,0 +1,77 @@ +use std::collections::HashSet; +use std::io::{self, BufRead}; + +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::().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>, mut ranges: Vec<(u64, u64)>) -> u64 { + for map in maps { + ranges = transform_ranges(&map, &ranges); + } + ranges.iter().min().unwrap().0 +} + +fn main() -> io::Result<()> { + let mut lines = include_str!("day05.in").lines(); + + let line = lines.next().unwrap(); + let (_, seeds) = line.trim().split_once(": ").unwrap(); + let seeds: Vec = seeds + .split_ascii_whitespace() + .map(|n| n.parse().unwrap()) + .collect(); + + lines.next(); + lines.next(); + + let maps: 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); + + Ok(()) +}