diff options
Diffstat (limited to 'src/day_14.rs')
-rw-r--r-- | src/day_14.rs | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/day_14.rs b/src/day_14.rs new file mode 100644 index 0000000..27d9f63 --- /dev/null +++ b/src/day_14.rs @@ -0,0 +1,138 @@ +use std::collections::HashMap; + +use crate::{Problem, Solution}; + +pub struct Day14; + +impl Problem for Day14 { + const DAY: u8 = 14; + + const INPUT: &'static str = include_str!("../input/day_14.txt"); +} + +impl Solution for Day14 { + type Answer1 = usize; + + type Answer2 = usize; + + fn part_1(input: &str) -> anyhow::Result<Self::Answer1> { + let mut grid = input + .lines() + .map(|s| s.chars().collect::<Vec<_>>()) + .collect::<Vec<_>>(); + + print_grid(&grid); + + tilt_grid(&mut grid); + + print_grid(&grid); + + Ok(grid_load(grid)) + } + + fn part_2(input: &str) -> anyhow::Result<Self::Answer2> { + let grid = input + .lines() + .map(|s| s.chars().collect::<Vec<_>>()) + .collect::<Vec<_>>(); + + Ok(process_grid(grid, 1000000000)) + // 105606 == + } +} + +type Grid = Vec<Vec<char>>; + +fn process_grid(mut grid: Grid, count: usize) -> usize { + let mut cache = HashMap::new(); + for i in 0..=count { + for _ in 0..4 { + tilt_grid(&mut grid); + grid = rotate_grid(&grid); + } + + if let Some(cycle) = cache.insert(grid.clone(), i).map(|n| n + 1) { + println!("\rcycle found: {cycle} - {i}"); + return process_grid(grid, count % (i - cycle)); + } + } + + print_grid(&grid); + + grid_load(grid) +} + +fn print_grid(grid: &Grid) { + println!( + "{}\n", + grid.iter() + .map(|v| v.iter().collect::<String>()) + .collect::<Vec<_>>() + .join("\n") + ) +} + +fn tilt_grid(grid: &mut Grid) { + for col in 0..grid[0].len() { + for mut row in 0..grid.len() { + if grid[row][col] == 'O' { + grid[row][col] = '.'; + while row > 0 && grid[row - 1][col] == '.' { + row -= 1; + } + grid[row][col] = 'O'; + } + } + } +} + +fn rotate_grid(grid: &Grid) -> Vec<Vec<char>> { + let mut rot: Vec<Vec<char>> = vec![vec!['.'; grid.len()]; grid[0].len()]; + for (col, v) in rot.iter_mut().enumerate() { + for (row, c) in v.iter_mut().rev().enumerate() { + *c = grid[row][col]; + } + } + rot +} + +fn grid_load(grid: Grid) -> usize { + grid.iter() + .rev() + .enumerate() + .map(|(row, v)| { + v.iter() + .filter(|&&c| c == 'O') + .map(|_| row + 1) + .sum::<usize>() + }) + .sum() +} + +#[cfg(test)] +mod tests { + use super::*; + + const INPUT: &str = indoc::indoc! {" + O....#.... + O.OO#....# + .....##... + OO.#O....O + .O.....O#. + O.#..O.#.# + ..O..#O..O + .......O.. + #....###.. + #OO..#.... + "}; + + #[test] + fn test_part_1() -> anyhow::Result<()> { + Ok(assert_eq!(136, Day14::part_1(INPUT)?)) + } + + #[test] + fn test_part_2() -> anyhow::Result<()> { + Ok(assert_eq!(64, Day14::part_2(INPUT)?)) + } +} |