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() { 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); }