From 000002900781dd1f62d1dd7170c15c1482e1874e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Jane=C5=BEi=C4=8D?= Date: Fri, 15 Dec 2023 12:20:27 +0100 Subject: [PATCH] solution: day 14 --- data/examples/14.txt | 10 ++++ src/bin/14.rs | 115 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 data/examples/14.txt create mode 100644 src/bin/14.rs diff --git a/data/examples/14.txt b/data/examples/14.txt new file mode 100644 index 000000000..5a24dce --- /dev/null +++ b/data/examples/14.txt @@ -0,0 +1,10 @@ +O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#.... diff --git a/src/bin/14.rs b/src/bin/14.rs new file mode 100644 index 000000000..a0db97f --- /dev/null +++ b/src/bin/14.rs @@ -0,0 +1,115 @@ +use std::{collections::HashMap, iter::once}; + +enum Tilt { + North, + West, + South, + East, +} + +fn get_load(floor: &[Vec]) -> usize { + floor + .iter() + .enumerate() + .flat_map(|(i, x)| x.iter().map(move |y| (i, y))) + .filter(|x| *x.1 == 'O') + .map(|x| floor.len() - x.0) + .sum() +} + +fn swap(floor: &mut [Vec], from: (usize, usize), to: (usize, usize)) { + let a = floor[from.0][from.1]; + let b = floor[to.0][to.1]; + floor[from.0][from.1] = b; + floor[to.0][to.1] = a; +} + +fn tilt(floor: &mut Vec>, tilt: Tilt) { + let (inner, outer) = match tilt { + Tilt::North | Tilt::South => (floor[0].len(), floor.len()), + Tilt::West | Tilt::East => (floor.len(), floor[0].len()), + }; + let inx_n = |(i, j)| (j, i); + let inx_s = |(i, j)| (inner - 1 - j, i); + let inx_w = |(i, j)| (i, j); + let inx_e = |(i, j)| (i, inner - 1 - j); + for i in 0..outer { + let mut ptr = 0; + for j in 0..inner { + let ((ii, jj), (pi, pj)) = match tilt { + Tilt::North => (inx_n((i, j)), inx_n((i, ptr))), + Tilt::South => (inx_s((i, j)), inx_s((i, ptr))), + Tilt::East => (inx_e((i, j)), inx_e((i, ptr))), + Tilt::West => (inx_w((i, j)), inx_w((i, ptr))), + }; + match floor[ii][jj] { + 'O' => { + swap(floor, (ii, jj), (pi, pj)); + ptr += 1; + } + '#' => ptr = j + 1, + _ => (), + } + } + } +} + +fn tilt_cycle(floor: &mut Vec>) { + use Tilt::*; + tilt(floor, North); + tilt(floor, West); + tilt(floor, South); + tilt(floor, East); +} + +pub fn part_one(input: &str) -> Option { + let mut f: Vec> = input.lines().map(|x| x.chars().collect()).collect(); + tilt(&mut f, Tilt::North); + Some(get_load(&f)) +} + +pub fn part_two(input: &str) -> Option { + let mut f: Vec> = input.lines().map(|x| x.chars().collect()).collect(); + let mut memo: HashMap = HashMap::new(); + + for i in 1.. { + tilt_cycle(&mut f); + let repr = f + .iter() + .flat_map(|x| x.iter().chain(once(&'\n'))) + .collect::(); + + if let Some(ii) = memo.insert(repr, i) { + let m = i - ii; + let shift = (1_000_000_000 - ii) % m; + + for _ in 0..shift { + tilt_cycle(&mut f); + } + break; + } + } + + Some(get_load(&f)) +} + +aoc::solution!(14); + +#[cfg(test)] +mod tests { + use super::*; + #[test] + fn test_part_one() { + assert_eq!( + part_one(&aoc::template::read_file("examples", 14)), + Some(136) + ); + } + #[test] + fn test_part_two() { + assert_eq!( + part_two(&aoc::template::read_file("examples", 14)), + Some(64) + ); + } +}