use std::env::args; use std::fs::File; use std::io::BufRead; use std::io::BufReader; fn split_once<'a>(s: &'a str, sep: &str) -> (&'a str, &'a str) { let i = s.find(sep).unwrap(); let left = &s[..i]; let right = &s[i+sep.len()..]; return (left, right); } fn get_data() -> (i16, i16, i16, i16) { let path = args().nth(1).unwrap(); let file = File::open(path).unwrap(); let line = BufReader::new(file).lines().next().unwrap().unwrap(); let (_, rest) = split_once(&line, "target area: "); let (x1, y1) = split_once(&rest, ", "); let (_, x2) = split_once(&x1, "="); let (_, y2) = split_once(&y1, "="); let (x21, x22) = split_once(&x2, ".."); let (y21, y22) = split_once(&y2, ".."); let x_min = x21.parse::().unwrap(); let x_max = x22.parse::().unwrap(); let y_min = y21.parse::().unwrap(); let y_max = y22.parse::().unwrap(); // inclusive return (x_min, x_max, y_min, y_max); } fn main() { let (x_min, x_max, y_min, y_max) = get_data(); assert!(x_min > 0); assert!(x_max > 0); assert!(y_min < 0); assert!(y_max < 0); let mut max_y = 0; // The probe reaches its heighest point after v steps // after v further steps it is back to 0. // The next step will take it to -(v + 1). // That means there is no chance of getting to the // target area if -(v + 1) < y_min. 'vy: for vy in (y_min..-y_min).rev() { for vx in 1..=x_max+1 { let mut x = 0; let mut y = 0; let mut mvx = vx; let mut mvy = vy; while x <= x_max && y >= y_min { x += mvx; y += mvy; if mvx > 0 { mvx -= 1; } mvy -= 1; if x >= x_min && x <= x_max && y >= y_min && y <= y_max { max_y = vy * (vy + 1) / 2; break 'vy; } } } } println!("{}", max_y); }