#[path = "../lib.rs"] mod lib; fn parse_numbers(s: &str) -> Vec { return s.split_whitespace().map(|s| s.parse().unwrap()).collect(); } fn range_intersect( a: (usize, usize), b: (usize, usize), ) -> Option<((usize, usize), Vec<(usize, usize)>)> { let a_start = a.0; let a_end = a.0 + a.1; let b_start = b.0; let b_end = b.0 + b.1; if a_start >= b_end || b_start >= a_end { return None; } else { let mut rest = vec![]; let mut intersection_start = a_start; if a_start < b_start { rest.push((a_start, b_start - a_start)); intersection_start = b_start; } let mut intersection_end = a_end; if a_end > b_end { rest.push((b_end, a_end - b_end)); intersection_end = b_end; } let intersection = (intersection_start, intersection_end - intersection_start); return Some((intersection, rest)); } } fn multirange_intersect( ranges: &Vec<(usize, usize)>, other: (usize, usize), ) -> (Vec<(usize, usize)>, Vec<(usize, usize)>) { let mut intersections = vec![]; let mut rest = vec![]; for range in ranges.iter() { match range_intersect(*range, other) { Some((intersection, mut r)) => { intersections.push(intersection); rest.append(&mut r); } None => { rest.push(*range); } } } return (intersections, rest); } fn apply_map( ranges: &Vec<(usize, usize)>, map: &Vec<(usize, usize, usize)>, ) -> Vec<(usize, usize)> { let mut result = vec![]; for i in 0..ranges.len() { let mut multirange = vec![ranges[i]]; for (dest_start, src_start, len) in map.iter() { let (intersections, rest) = multirange_intersect(&multirange, (*src_start, *len)); for (intersection_start, intersection_len) in intersections.iter() { result.push(( *intersection_start + dest_start - src_start, *intersection_len, )); } multirange = rest; } result.append(&mut multirange); } return result; } fn main() { let mut ranges1 = vec![]; let mut ranges2 = vec![]; let mut map = vec![]; let mut state = 0; for line in lib::iter_input() { match state { 0 => { let (_, tail) = line.split_once(": ").unwrap(); let numbers = parse_numbers(&tail); ranges1 = numbers.iter().map(|x| (*x, 1)).collect(); ranges2 = (0..numbers.len()) .step_by(2) .map(|i| (numbers[i], numbers[i + 1])) .collect(); state = 1; } 1 => { if line == "" { ranges1 = apply_map(&ranges1, &map); ranges2 = apply_map(&ranges2, &map); map = vec![]; state = 2; } else { let n = parse_numbers(&line); map.push((n[0], n[1], n[2])); } } 2 => { state = 1; } _ => unreachable!(), } } ranges1 = apply_map(&ranges1, &map); ranges2 = apply_map(&ranges2, &map); let min1 = ranges1.iter().map(|(start, _)| start).min().unwrap(); let min2 = ranges2.iter().map(|(start, _)| start).min().unwrap(); println!("part1: {}", min1); println!("part2: {}", min2); }