use itertools::Itertools; const ROWS: usize = 6; const COLS: usize = 50; fn generate_grid(input: &str) -> [[bool; N]; M] { let mut grid = [[false; N]; M]; for line in input.lines() { let (inst, rest) = line.split_once(" ").unwrap(); match inst { "rect" => { let (a, b) = rest .split('x') .filter_map(|x| x.parse().ok()) .next_tuple() .unwrap(); for col in grid.iter_mut().take(a) { for cell in col.iter_mut().take(b) { *cell = true; } } } "rotate" => { let (inst, rest) = rest.split_once(" ").unwrap(); match inst { "row" => { let rest = rest.strip_prefix("y=").unwrap(); let (a, b) = rest .split(" by ") .filter_map(|x| x.parse().ok()) .next_tuple() .unwrap(); for _ in 0..b { let placeholder = grid[COLS - 1][a]; for i in (1..COLS).rev() { grid[i][a] = grid[i - 1][a]; } grid[0][a] = placeholder; } } "column" => { let rest = rest.strip_prefix("x=").unwrap(); let (a, b) = rest .split(" by ") .filter_map(|x| x.parse().ok()) .next_tuple() .unwrap(); for _ in 0..b { let placeholder = grid[a][ROWS - 1]; for i in (1..ROWS).rev() { grid[a][i] = grid[a][i - 1]; } grid[a][0] = placeholder; } } _ => unreachable!(), } } _ => unreachable!(), } } grid } pub fn part_one(input: &str) -> Option { let mut count = 0; for col in generate_grid::(input).iter() { for cell in col.iter().copied() { if cell { count += 1; } } } Some(count) } pub fn part_two(input: &str) -> Option { let grid = generate_grid::(input); let mut s = String::with_capacity((ROWS + 1) * COLS); for row in 0..ROWS { for col in grid.iter() { if col[row] { s.push('#'); } else { s.push('.'); } } s.push('\n'); } Some(s) } fn main() { let input = &aoc::read_file("inputs", 8); aoc::solve!(part_one, part_two, input); } #[cfg(test)] mod tests { use super::*; #[test] fn test_part_one() { let input = aoc::read_file("examples", 8); assert_eq!(part_one(&input), Some(6)); } }