---cargo [profile.dev] opt-level = 3 [dependencies] rayon = "1" --- use rayon::prelude::*; static CONTENT: &'static str = include_str!("./inputs/09_1.txt"); const PRINT: bool = false; #[derive(Debug, PartialEq, Clone, Copy)] enum Cell { Empty, Red, Green, } const _T: () = assert!(1 == core::mem::size_of::()); fn main() { let points: Vec<(usize, usize)> = CONTENT.lines().map(|l| l.trim()).filter(|l| !l.is_empty()).map(|l| { let (first, second) = l.split_once(',').unwrap(); let first = first.parse::().unwrap(); let second = second.parse::().unwrap(); (first, second) }).collect(); // println!("Points:\n{:?}", points); let grid_width: usize = points.iter().map(|(x, _)| *x).max().unwrap()+1; let grid_height: usize = points.iter().map(|(y, _)| *y).max().unwrap()+1; let mut grid = vec![Cell::Empty;grid_width*grid_height]; for parts in points.windows(2).chain(core::iter::once(&[points.last().copied().unwrap(), points.first().copied().unwrap()] as &[(usize, usize)])) { let start = parts[0]; let end = parts[1]; let g_points = line_point_iter(start, end); grid[start.1 *grid_width+ start.0] = Cell::Red; for (x,y) in g_points { grid[y*grid_width+x] = Cell::Green; } } print_grid(&grid, grid_width, grid_height); let inner_point = points.windows(2) .filter(|p| { let start = p[0]; let end = p[1]; start.0 == end.0 }).filter_map(|p| { let start = p[0]; let end = p[1]; line_point_iter(start, end).next() }).flat_map(|(x, y)| { [(x-1, y), (x+1, y)] }).filter(|(x, y)| { (0..grid_width).contains(x) }).find(|(x, y)| { let c = (0..*x).map(|x| grid[y*grid_width + x]).filter(|c| *c == Cell::Green).count(); c == 1 }).unwrap(); println!("After filling"); print_grid(&grid, grid_width, grid_height); let largest = points.par_iter() .flat_map_iter(|p| core::iter::repeat(*p).zip(points.iter().copied())) .filter(|(f, s)| f != s) .map(|(f, s)| (f, s, (f.0.abs_diff(s.0)+1) * (f.1.abs_diff(s.1)+1))) .filter(|(f, s, _)| { let x0 = f.0.min(s.0); let x1 = f.0.max(s.0); let y0 = f.1.min(s.1); let y1 = f.1.max(s.1); (x0..=x1).flat_map(|x| { core::iter::repeat(x).zip(y0..=y1) }).all(|(x, y)| in_grid(&grid, grid_width, grid_height, (x,y))) }) .reduce(|| ((0,0), (0,0), 0), |acc, (f, s, a)| { if a > acc.2 { return (f, s, a); } acc }); println!("Largest: {:?}", largest); } fn print_grid(grid: &[Cell], width: usize, height: usize) { if !PRINT { return; } for y in 0..height { for x in 0..width { match grid[y*width+x] { Cell::Empty => print!("."), Cell::Red => print!("#"), Cell::Green => print!("X"), }; } println!(); } } fn line_point_iter(start: (usize, usize), end: (usize, usize)) -> Box> { if start.0 == end.0 { let s = start.1.min(end.1); let e = start.1.max(end.1); Box::new(core::iter::repeat(start.0).zip(s..e).skip(1)) } else { let s = start.0.min(end.0); let e = start.0.max(end.0); Box::new((s..e).zip(core::iter::repeat(start.1)).skip(1)) } } fn in_grid(grid: &[Cell], width: usize, height: usize, (x, y): (usize, usize)) -> bool { if grid[y*width+x] != Cell::Empty { return true; } let c = (0..x).map(|x| grid[y*width + x]).filter(|c| *c != Cell::Empty).count(); match c { 0 => false, 1 => true, 2 => false, _ => { let c = (0..y).map(|y| grid[y*width + x]).filter(|c| *c != Cell::Empty).count(); match c { 1 => true, _ => false, } } } }