use itertools::Itertools; #[derive(Copy, Clone)] pub struct Point { pub x: usize, pub y: usize, } impl Point { fn get_bounds(points: &[Point]) -> Point { let x = points.iter().map(|p| p.x).max().unwrap_or_default(); let y = points.iter().map(|p| p.y).max().unwrap_or_default(); Point { x, y } } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Fold { X(usize), Y(usize), } #[derive(Clone)] pub struct Grid { pub grid: Vec>, } impl Grid { pub fn new(points: &[Point]) -> Self { let bounds = Point::get_bounds(points); let mut line = Vec::new(); for _ in 0..=bounds.x { line.push(false) } let mut grid = Vec::new(); for _ in 0..=bounds.y { grid.push(line.clone()) } for Point { x, y } in points { grid[*y][*x] = true; } Self { grid } } pub fn fold(&mut self, instruction: Fold) { match instruction { Fold::X(fold) => { for y in 0..self.grid.len() { for x in fold + 1..self.grid[y].len() { self.grid[y][fold - (x - fold)] |= self.grid[y][x]; } self.grid[y].truncate(fold) } } Fold::Y(fold) => { for y in fold + 1..self.grid.len() { for x in 0..self.grid[0].len() { self.grid[fold - (y - fold)][x] |= self.grid[y][x]; } } self.grid.truncate(fold) } } } pub fn count(&self) -> usize { self.grid .iter() .flat_map(|line| line.iter()) .filter(|val| **val) .count() } } impl ToString for Grid { fn to_string(&self) -> String { self.grid .iter() .map(|line| { line.iter() .map(|val| if *val { "#" } else { "." }) .collect::() }) .join("\n") } } #[derive(Clone)] pub struct Input { pub grid: Grid, pub instructions: Vec, }