use std::env; use std::io::BufReader; use std::io::BufRead; use std::fs::File; use std::process; #[macro_use] extern crate text_io; struct BoundingBox { left: u32, top: u32, right: u32, bottom: u32 } struct Coordinate { x: u32, y: u32 } struct Point { coordinate: Coordinate, id: u32 } fn distance(a: &Coordinate, b: &Coordinate) -> u32 { let dx = (a.x as i32 - b.x as i32).abs(); let dy = (a.y as i32 - b.y as i32).abs(); (dx + dy) as u32 } fn find_closest(c: &Coordinate, points: &Vec) -> Option<(u32, u32)> { let mut shortest = std::u32::MAX; let mut point_id: Option = None; for point in points { let dist = distance(&point.coordinate, c); if dist < shortest { shortest = dist; point_id = Some(point.id); } else if dist == shortest { point_id = None; } } match point_id { Some(id) => Some((id, shortest)), None => None } } fn find_total_distance_to_points(c: &Coordinate, points: &Vec) -> u32 { let mut total: u32 = 0; for point in points { let dist = distance(c, &point.coordinate); total += dist; } total } fn draw_grid(grid: &Vec>>, bb: &BoundingBox) { let w = (bb.right - bb.left + 1) as usize; let h = (bb.bottom - bb.top + 1) as usize; for j in 0..h { for i in 0..w { let x = (i as u32 + bb.left) as u32; let y = (j as u32 + bb.top) as u32; let id_opt = grid[j][i]; match id_opt { Some(id) => { print!("{}", id); } None => { print!("."); } } } print!("\n"); } } fn find_largest_area(grid: &Vec>>, points: &Vec, bb: &BoundingBox) -> u32 { let w = (bb.right - bb.left + 1) as usize; let h = (bb.bottom - bb.top + 1) as usize; let mut largest_area = 0; for point in points { let mut area = 0; for j in 0..h { for i in 0..w { let id_opt = grid[j][i]; match id_opt { Some(id) => { if id == point.id { area += 1; } } None => {} } } } if area > largest_area { largest_area = area; } } largest_area } fn main() { let args: Vec = env::args().collect(); if args.len() != 2 { println!("Wrong number of arguments. Provide just a file name."); process::exit(1); } let filename = &args[1]; println!("Using file {} as input.", filename); let f = match File::open(filename) { Ok(file) => file, Err(e) => { println!("Failed to open file {}. {:?}", filename, e); process::exit(1); } }; let file = BufReader::new(&f); let lines: Vec = file.lines() .map(|line| line.expect("Could not parse line.")) .collect(); let mut points: Vec = Vec::new(); let mut bb: BoundingBox = BoundingBox { left: std::u32::MAX, top: std::u32::MAX, right: std::u32::MIN, bottom: std::u32::MIN }; for (i, line) in (&lines).iter().enumerate() { let (x, y): (u32, u32); scan!(line.bytes() => "{}, {}", x, y); if x < bb.left { bb.left = x; } if x > bb.right { bb.right = x; } if y < bb.top { bb.top = y; } if y > bb.bottom { bb.bottom = y; } let coordinate = Coordinate { x, y }; points.push(Point { coordinate, id: i as u32 }); println!("Add point {}, {}", &x, &y); } println!("BB: l: {}, r: {}, top: {}, bot: {}", bb.left, bb.right, bb.top, bb.bottom); let w = (bb.right - bb.left + 1) as usize; let h = (bb.bottom - bb.top + 1) as usize; let mut grid: Vec>> = vec![vec![None; w]; h]; for j in 0..h { for i in 0..w { let x = (i as u32 + bb.left) as u32; let y = (j as u32 + bb.top) as u32; let coord = Coordinate { x, y }; let opt: Option<(u32, u32)> = find_closest(&coord, &points); match opt { Some((id, shortest)) => { grid[j][i] = Some(id); } None => { grid[j][i] = None } } } } //draw_grid(&grid, &bb); let largest_area_1 = find_largest_area(&grid, &points, &bb); println!("1. Largest area: {}", largest_area_1); let threshold = 10000; let mut largest_area_2 = 0; for j in 0..h { for i in 0..w { let x = (i as u32 + bb.left) as u32; let y = (j as u32 + bb.top) as u32; let coord = Coordinate { x, y }; let total_dist = find_total_distance_to_points(&coord, &points); if total_dist < threshold { largest_area_2 += 1; } } } println!("2. Largest area: {}", largest_area_2); }