use std::env; use std::fs::File; use std::io::{BufReader, BufRead}; use std::cmp::{min, max}; use std::collections::HashSet; fn parse_num(s: &[u8]) -> (i64, usize) { let mut num: i64 = 0; let negative = s[0] == '-' as u8; let start = if negative {1} else {0}; let mut len = if negative {1} else {0}; for i in start..s.len() { if s[i].is_ascii_digit() { num = num*10 + (s[i] as i64 - '0' as i64); len += 1; } else { break; } } (if negative {-num} else {num}, len) } fn combine(ranges: &mut Vec<(i64, i64)>, l: i64, r: i64) { for (l0, r0) in ranges.iter_mut() { if *l0 <= r && l <= *r0 { *l0 = min(*l0, l); *r0 = max(*r0, r); return; } } if ranges.len() > 0 { let (_, last_r) = ranges.last_mut().unwrap(); if l == *last_r + 1 { *last_r = r; return; } } ranges.push((l, r)); } fn main() { let file = File::open(&env::args().nth(1).expect("input")).expect("io err"); let lines = BufReader::new(file).lines(); let mut sensors: Vec<(i64, i64, u64)> = Vec::new(); let mut beacons: HashSet<(i64, i64)> = HashSet::new(); for line in lines.flatten() { let l_bytes = line.as_bytes(); let (sx, e1) = parse_num(&l_bytes[12..]); let (sy, e2) = parse_num(&l_bytes[12 + e1 + 4..]); let (bx, e3) = parse_num(&l_bytes[12 + e1 + 4 + e2 + 25..]); let (by, _) = parse_num(&l_bytes[12 + e1 + 4 + e2 + 25 + e3 + 4..]); sensors.push((sx, sy, ((bx - sx).abs() + (by - sy).abs()) as u64)); beacons.insert((bx, by)); } sensors.sort_by_key(|(x, _, _)| *x); println!("{:?}", sensors); println!("{:?}", beacons); let max_y = &env::args().nth(2).expect("max y").parse::().unwrap(); for target_y in 0..=*max_y { let mut line_coverages: Vec<(i64, i64)> = Vec::new(); for (sx, sy, range) in &sensors { let clip = (*range as i64) - (sy - target_y).abs(); if clip < 0 { continue; } let startx = sx - clip; let endx = sx + clip; line_coverages.push((startx, endx)); } line_coverages.sort_by_key(|(x, _)| *x); let mut coverage: Vec<(i64, i64)> = Vec::new(); for (startx, endx) in line_coverages { combine(&mut coverage, startx, endx); } if coverage.len() > 1 { let score = 4000000 * (coverage[0].1 + 1) + target_y; println!("{:?} --> {:?}", coverage, score); break; } } }