diff --git a/2025/09.rs b/2025/09.rs index 8397215..d1a2249 100644 --- a/2025/09.rs +++ b/2025/09.rs @@ -1,8 +1,26 @@ ---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(); @@ -12,17 +30,124 @@ fn main() { (first, second) }).collect(); - println!("Points:\n{:?}", points); + // println!("Points:\n{:?}", points); - let mut rects: Vec<((usize, usize), (usize, usize), usize)> = points.iter() - .flat_map(|p| core::iter::repeat(*p).zip(points.iter().copied())) + 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))) - .collect(); + .filter(|(f, s, _)| { + let x0 = f.0.min(s.0); + let x1 = f.0.max(s.0); - rects.sort_by_key(|(_, _, a)| *a); + 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!("Rectangle: {:?}", rects); - println!("Largest: {:?}", rects.last().unwrap()); + 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, + } + } + } }