From d93dc91117ac8dbb83bc74ddbd0ceb02d7c34e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moritz=20H=C3=B6lting?= <87192362+moritz-hoelting@users.noreply.github.com> Date: Thu, 14 Dec 2023 19:45:04 +0100 Subject: [PATCH] day 14 --- Cargo.lock | 7 ++ day-14/Cargo.toml | 7 ++ day-14/src/bin/input.txt | 100 ++++++++++++++++++++ day-14/src/bin/part1.rs | 109 ++++++++++++++++++++++ day-14/src/bin/part2.rs | 196 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 419 insertions(+) create mode 100644 day-14/Cargo.toml create mode 100644 day-14/src/bin/input.txt create mode 100644 day-14/src/bin/part1.rs create mode 100644 day-14/src/bin/part2.rs diff --git a/Cargo.lock b/Cargo.lock index ebd8d30..eb7f8fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,6 +159,13 @@ dependencies = [ "rayon", ] +[[package]] +name = "day-14" +version = "0.0.0" +dependencies = [ + "indoc", +] + [[package]] name = "deprecate-until" version = "0.1.1" diff --git a/day-14/Cargo.toml b/day-14/Cargo.toml new file mode 100644 index 0000000..c9c6079 --- /dev/null +++ b/day-14/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day-14" +version = "0.0.0" +edition = "2021" + +[dev-dependencies] +indoc.workspace = true diff --git a/day-14/src/bin/input.txt b/day-14/src/bin/input.txt new file mode 100644 index 0000000..a448a4d --- /dev/null +++ b/day-14/src/bin/input.txt @@ -0,0 +1,100 @@ +O.O#..O.#...#..O.O#..O#...O..O.#...O#.OO.O...#....#.O.##..####.OOO....OO......##..........#O.#O.O.#. +..O.#..#O...#..#.....O..O..OO..#.O..O#..#O#...#......O.O.O......#..OO##...O..#.O.O..#...#O....O.OO.. +....O#O#.O#...#..O.O#..#.....O....#.....OOO#OO.#....#...#.O.OOOO..#O.O##....##..O.....##.OOO.#..##.. +OO...OO...#..OOO..#....O.#.......##O....#..O.O#..#.O.#..O.#O.#.#..#....#...O.......O#O.....OOO###... +..#...#...O.O....#..O.....#...OO.##O...#O...#.#.O#O.OO.OO.O...#O#...#.#...#.....O..#..O##.##.OO..#.O +..#.#.O.#OO#...#.#O##O.OO..#......#OO....O........#OO#..O.O.....#.....O.O..O.#O#..O......O....O.##.# +.....O..O......O...#.#.#.....#OOO##O.#O...O...O.O..#...#O##.OO......O......OO..O#..##......#OO#..O.. +...#...O.#O.......#.O....#..#.....#.O.#.....#..O..#.....O#..O#.O.O......O###O#..O...OO..##........## +.......#O..O..O........#...#....O..#...#.....#.....#.#O.#.O...O#.....OO.O........#O#O.O..#.....O#O.. +OOO....OO..#O.O#....O#O....OO...O.O...O..O.#..O#........OO....#...#.....OO..O#....##OO#.O#O........O +#.#......O..O...O###O.OO..##......#........O........O......O..O..O.....O.##.O...O..O..OO.O##O.O..#O. +...O.............#.OO.O#.#.....O.O#..OO#.............O..OO.#.O.#O#.O....#..#........O.#.O.......O#.. +.............OO#.....O.O..O..O...O.O..#..#.#..O....OO#..OO..#.O..O#.....#.#....O.O...#.#O....#...O.# +..O..#O.#.#OOO.....#O..OO.##....O..##.O.....O....O..#.#...O.O..O##...O...O..#..O.#O.##.......O...#.. +...O#.....O#O...O....OOO...#.#....##O.....OOO.##...OO.........#.#.#..O....#O#.OO.O........O......... +.......#........#....OO........O...OO.##...O.#.....#....O..OO.O.#...OO..O...O..O....O.#....#.......# +..#....#...##O..#....O#..O.O....#....#..###.#.O.....###..OO....#...OO.OOO#O...##...O.#O#...O...O.O.. +O#..O#...OO..#.......#....OOO...OO.O...OO...##.O..O##.O......#....#O.O..O#OOO.#.O#O.......OO...OO... +OO.#.#...#..O.#.#.OO..OO.#O.#..O....OOO.#.....O.OO....O.#.#..##.....O.#...O......#OO#..O.O..#.....#. +O.....O..O..........O....O..#..#...........#.#O.......#....O.#..##....#O#...#O.O...O#O..#O#..OO.#.O. +.#.##....O.#...OO##O.#..O..OO........O...O......O#OO..OO.O...#..#.O#O.......O#...O.O#..#OOO.O...OO#. +..O..#OO#O#.O..O..#......#.O..#...O..O..O...##O.O..##.....#O.O.OOO.O..O...O...O..O..O....#......#OO. +...OOOO.#.#.O.OO#......#.#.O..O.#...O..O..#......#....##O.#.O.#O#O....###.#..#.....O#.O........O.... +..OO#.........OOO..........O...O..###...##...O........#....O.O#O....#...............#...O..O.O...#.. +.O......#O.OO.....O..#........O#OO.....O....O.O#.O.O...O....#..O#O....#.....O...O#O.O..#.OO..##.#.#. +....O.O#..#...O#.O.O.#......OO..O#..#..#..##...O.#..###.O#.O..O#....O.#..O.O#..##O#....#O.OO#.#..... +O##..#.....##...O......#..O....#O..#O...O.........O..OO......#.#OO##...#.....#......O.....O#..O..#.. +.##.O#O#O...O..#...........#OO....O.#.O.O.#.#O.#..#...O........O...#...#..OOO..##..O......O##O#..... +...O...O#.....#O..#..#..O.#.##O..........#.O..###.O..O#O....O...O#O....OO.O..#.#.O#O#.....#.#.O.OO#O +...O..#O.#O......O....O...O..O#......OO...#..O.OO.O.#..#..#......OOO..#.....OO....O..#.#O......O.... +.....#...##.....O#..O.....#O.#..OO..#.#..##....#.O.#......#.#O.O..O.O.......O......O#.O#O#...OO...#. +......##.O#....O#.....O......#OO#...O....O#....#....O...#..#.#....OO...##OO..#.....##..O..O.O...O..O +OO##..#...OO.......O...#..#..O.....O..OO.OO.#..#.#O.#O..#O.##..............O...O.#O..#..#.O......##. +..O.#.....O#O......O#O#..O.O.....#...OO.#.O.#....#.###....#.#...........O#O.....OO.#..O...#..OO...#O +#..O..O..O#..O...#O.#...###..O..#.O#.#OO.......OO..........O..OOO...#....OO......O..OO#.OO#...O.O.O. +O.O..O..##..O...O.#O#.O.#.O..#O.OO#.OO..O..#...O.........#OO.......O...OO..####O...O..O...#OOO..O.O. +O..#.O.#.OOO...#O.....O#O.#O#.OO...#OO.#.##.........O..O#O#.#.O#...O..O....O..#O...O#O...O..O.O..... +O.O..O...#.O#.#...O..#.O.#.O##.O..#..#...OO#...##.O.#.##.OOO.#.........O.O....#..O.O.....#......OOO. +O..#O.#....OO#..O.##........O...#.#.....OO.....#O...OO........OO.#OO.....#.......O.#..OO#..O.#O#.... +.OO..O.#..#...O.O.OOO#.O...O.O..OO.#O#..OO..#.....#.#..O....O.#O.##...O..O.....#...##...O.O#O...O..O +#....O.#......OO....#..O#.OOO..O.#...O.........###O.....##..O..O.O.O.O....##.....O...O.O..O.O.....O. +#...OO...O....##O........O.O..OO..#.....#.....OO...O...O.....#..O...#.....#.#...#................... +...O....O..OO.OO.......##...#OOO.....O..OO.O#.#........O..O.O....O.#.O#...#.#.........#......O....#. +O.........#..#..##..OO#....#..OO#O....O.O...O...................O.....O..OO.O.O.O..O.#...#...O.#.#O. +....#.O#.O..#..#..#...#OO.#.......O.#....O...O...#.##...O...O....O#.O.....O#....#.#......#.#..O.O.O. +#O##.#.....#.##O..#...O...###.OO......#......#O....#..#..O........#.O..O.....O#..O...OO#..OO.#.OO.OO +.O#.###O.O.#...####O....#.##O.O##.#..#.#..O........###.#....##O....O.O....OO.O...O.#O...OOO##...#.O. +....O..O....O............O.O......OO.##..#OO..#O...#.O.O..#..#O.O.........##.#..#..OO.....O.......#. +O....##.#O...O.OO..O#..O...#...O.OO.#..O.#......#.O..#.#..........O###...OOO.O..#.......O.O.O......O +.#......##...O.....#.O.....O.#.......O#O...O#.O.......O..#O..O#...O..O..OO#..#.O#...O.#.#.O...#.#.OO +...O.#.O.#......##..O..........OOO.....O.O......O.....O..#.O..#...#.OOO...O..#..#...#......O...#...O +..O..OO...#..#O....OO...#O...O#..O##....O#....#..#.#...#...........###...........#...OO...OO........ +OO....O...#OO..O..O.O.O..#.O.....O.#...O........OO...#......O.#....O..O.#.##.........OO.O#...O.OO... +.#.....O.O#O..O.....#.#...O.O##O.......#..O#.#.#.OO#.O.O.#O#..OO..O.#O..O.OOOO......O....O...#..#... +#......O..#...O..#.O....#..OO...#.........O.O...#..O......O.O.O.#.O.......O..##..O#.#..O..#....OO.#. +.O..##O#O.O.O....#...#..O#.#.#.......O........#..#OO.OO..O..O.#...O..OOOO.....O#....O####.......#... +.#OO#.O.#..........OO..O.......O#....#.OO#...##......####...O...OOO...#....O.#..O.......#..O.O...... +....O..#........#OO.......O.#..O...O..O..#.O....#.O.O.O..OO.O#O.O..O.###..O.#.#.......#.#...O#...O.. +OO....O#O.O.#.#.##O#.#O#....#....O.O.......O.O.OO....O#.....O.O.OO#.##.O.#..##O..O..O#O......O...O#O +.#...#O..##.##.OO....##.....#O...#.O.O..#.....##......OO#OO.#...O...#..O....O#.#.O..O.#.......O.#.#O +O.#OO#OOO..O.#..OO..O......#O...O....##..#..#O...OO#.#.OO........O.#...O..O#OOO.O....##.O.O........# +.###..O.O...O#O..OO.O....#...OO.OO.O..OO..O.O.O.........#.O#...#...#..O..#..O..OO..#.O.....OO#...... +.O#...O#..#.....O......O##..O.O.O..#..#.#.....#...#....#..#...O.O#..O...O..#...O......#.#...O.....O. +.O#..OO#.O.O...#O...O.....#....##..####.....O..O.....O...#O..#.......#OOO#.#....O.......O.#O.#..O#.. +......O.O#....O.......O.O...O..O#..O...#....#O..##OO.#O......OOO.....#.#O.O#.O#.O....O#O#O..###.#... +#.O....#O......OOO......##.O.OO....#O...#OO...OO.##...O.O..#OO..OOO#..#.O.........O#...O........#... +.O....#.......O#.O..##...O##OO......#..O.O#O.O.#...........#OO........O...O....#.............#.#..O. +....#O.#..#.#..........OO...O..........O....O#...#OO.......O...O.#OO..OOO....O.O#..O.O.###..O.O#...O +O...#..OO....O.......#.OO...O........O.OO..#..#..#.#.O..O.#....O.O......OO..OO.O..#..OOO#..OOO...... +.OO#.O.....O..#...O.....O....O#........#....#.....O..#..###...#.O.......OO......O..O.OO..O..#.O#O#.. +O....O...##.#....#O..O.#......................O..O#OOO..##....#.#..O.O.....O#..O.O.O...#.#.OOO...O.. +.......O..OO.O..O#.OO.#.O..#O....#.OOO.........##......#.O#.O..O....O....O.....#O.O...O.#.......O.#O +....O##.#...O.##...O#...OOOO...OO...#.O.#...O.#O.......#.O.....##....O.#O....#......##.O....O.OO#..O +OO...O#O#O#.#OO.#O.O..#.#.#.#.............#.O........#...O..O......O#.#OO.O...#.O..O...O#.O....O#..O +.#..O..#.OO.#O...O#.O.#.#..#.......#.......#O...#..#O#....O...#....OO.....O......O..#.....O..O..#.O# +...OO....O.#....#.O.#..#.#O.#.#O.....O..O##.......O..#O.#.O...OOO#O.#......O....#......#......O##... +...##.O.O.....##....O.....#O..O........#.#.O#O....O#..O...O#OO...O....O..O.O.#.#..#OO...O..#....OO.. +O...#OO.O.OO#..O....##O...#....#...#.O.O..O.........#..##.#O.#.OO..OO...#...O.O#.OO..#.O.OO#.#..##OO +..O.O#..O..#O...O.#.O.#....#....#.#O...O..O#O....#...#..#..##......#.O..........OOO........O.#...... +.....#....#....OO....#....O.#O..O...O#O..#...###....O.....O........##.#.#..#.O.OO.#O.O.O..#...O#O..O +.OO.....O.O.....#....O.O....O......O#O....O#.#..O....O.#............#..O.#.....OO....O...O....O.#.O. +.........O#OO.#O.....O......O...#..#O..O.#...O.O..OO.........#.O#OO.#.OO.........#.OO..O.O#O..O.O#.. +#...O...O....#O.###.....O.OO..O..OO.O#O....#O..#O..OO..O..#........O...#.....#..#...OO..O....#.....O +......O.O.OO#.O.......O#O.OO.#..O....O...#.O#..#....O.#....#..#O...#.OO.O#........#......O....O.O... +..#...##...#.O.O..#...O#.....##.......OO..O.#....O.O#O#..O...O#..OO...##O...O..O.....#.#...O.O...... +OOO.O.O#O......#..OO.O...OO...O............O..O#..##O...###.#......O#..#.O..O.OOO...#..O#......#OO.# +O###.......#.O.O.#.....#.OO..O.O...#..O#O..#O.O.#.O..O.O..O#.#....#..#...O#..###.#..O#.O.........OO. +.......#O#OO#...#.#...#.O...O.....O.O#.....O.O.O##.#...#O.#....OO...O.OO..O....O.O..#..#.....O...#.. +.O..###..OO#O.#.#OO.O#...#..O#...O.....O#.O......O...OO..O..O.....O..##.....OO.....O......O........O +..O..#.O.#..OO.O#..O#..O.....OO#O#....OO.OO#O...O...O.O......OO.#O#....O..#O.#.OO##.#....#O#.#...... +O.#O.O.O.O...OO.....O.#...##..#....O....O..#..#O#..O#.#.OO.#O..........#...O..##..O.##.O.O...#.#O..# +......O#...O.#..O#.O.........#.#....O.O....O.#..O..O##.#..O....#..#O#.OO.........#.O##O.....OO.OO.O. +#....#.#O.O.O............O.O.#.O..O.........O..O........O......O.....OO.OO..OO.#....OO.OO.#....#..## +.......#...O.O.#.O.....#.O#.#..O..O...O.O.#O..#...##.........O..#.OO..O........#.....#.......OO..... +...#....O...O...#O.OO...#....#..O.#.O.#......##.#.#.OO.O.O...#..#..O........O.##..O...O#O...OO.O.... +.......OO...O..O...........O###......#....O.......O..O.....O#...#.O.#.#......O..O.....#.#OO.......O. +.#..#.....#.O..O..O.....##..O.........O#.##O....OO...O...#..O.O.##OO......O.#..O....O..O.#.O.O...O.O +.O....O...O....#.O......#..##O.#..O..O.....O...OO..###....#..#..#..........#.#.#.#.#........O...O.O. +.OOO.#.#O....O.#...OO#.##...#...O.#...OO..###..OO.#.O....O..OO#..O..O....O#.#.O####..O....O..O#O.... +.OO.OO#......#....#..##O#O...OO....#....O......OO..OOO.....##.......O#.#.O.#O......O..#.#O..O.O..#.. \ No newline at end of file diff --git a/day-14/src/bin/part1.rs b/day-14/src/bin/part1.rs new file mode 100644 index 0000000..98c0c98 --- /dev/null +++ b/day-14/src/bin/part1.rs @@ -0,0 +1,109 @@ +use std::cmp::Ordering; + +fn main() { + println!("{}", part1(include_str!("./input.txt"))); +} + +fn part1(input: &str) -> usize { + let slid_lines = slide_north(input); + + slid_lines + .iter() + .enumerate() + .map(|(i, line)| line.iter().filter(|c| **c == 'O').count() * (slid_lines.len() - i)) + .sum() +} + +fn slide_north(input: &str) -> Vec> { + let lines = input.lines().collect::>(); + let columns = (0..lines[0].len()) + .map(|i| { + let mut column = lines + .iter() + .map(|row| row.chars().nth(i).unwrap()) + .collect::>(); + + // bubble sort + for n in (1..column.len()).rev() { + for j in 0..n { + if sort_slide_north(&column[j], &column[j + 1]) == Ordering::Greater { + column.swap(j, j + 1); + } + } + } + + column + }) + .collect::>(); + + (0..columns[0].len()) + .map(|i| { + columns + .iter() + .map(|column| *column.get(i).unwrap()) + .collect::>() + }) + .collect::>() +} + +fn sort_slide_north(a: &char, b: &char) -> Ordering { + if a == &'#' || b == &'#' { + Ordering::Equal + } else if a == &'.' && b == &'O' { + Ordering::Greater + } else if a == &'O' && b == &'.' { + Ordering::Less + } else { + a.cmp(b) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + const INPUT: &str = indoc!( + " + O....#.... + O.OO#....# + .....##... + OO.#O....O + .O.....O#. + O.#..O.#.# + ..O..#O..O + .......O.. + #....###.. + #OO..#.... + " + ); + + #[test] + fn test_part1() { + assert_eq!(part1(INPUT), 136); + } + + #[test] + fn test_slide_north() { + assert_eq!( + slide_north(INPUT) + .iter() + .map(|line| line.iter().collect::()) + .collect::>() + .join("\n"), + indoc!( + " + OOOO.#.O.. + OO..#....# + OO..O##..O + O..#.OO... + ........#. + ..#....#.# + ..O..#.O.O + ..O....... + #....###.. + #....#...." + ) + ); + } +} diff --git a/day-14/src/bin/part2.rs b/day-14/src/bin/part2.rs new file mode 100644 index 0000000..b436aa9 --- /dev/null +++ b/day-14/src/bin/part2.rs @@ -0,0 +1,196 @@ +use std::{cmp::Ordering, collections::HashMap}; + +const REPETITIONS: u32 = 1_000_000_000; + +fn main() { + println!("{}", part2(include_str!("./input.txt"))); +} + +fn part2(input: &str) -> usize { + let mut lines = input + .lines() + .map(|l| l.chars().collect()) + .collect::>>(); + + let mut seen = HashMap::new(); + seen.insert(lines.clone(), 0); + + let mut stop_at = None; + + for i in 1..REPETITIONS + 1 { + lines = cycle(lines); + // stop at correct iteration + if stop_at.is_some_and(|j| j == i) { + break; + } + // check if we've seen this before & calculate where to stop + if seen.contains_key(&lines) && stop_at.is_none() { + let repeat_period = i - seen.get(&lines).unwrap(); + stop_at = Some(i + ((REPETITIONS - i) % repeat_period)); + } + seen.insert(lines.clone(), i); + } + + lines + .iter() + .enumerate() + .map(|(i, line)| line.iter().filter(|c| **c == 'O').count() * (lines.len() - i)) + .sum() +} + +fn cycle(matrix: Vec>) -> Vec> { + let north_lines = transmute(slide_rows_left(transmute(matrix))); + + let west_lines = slide_rows_left(north_lines); + + let south_lines = transmute(reverse_rows(slide_rows_left(reverse_rows(transmute( + west_lines, + ))))); + + reverse_rows(slide_rows_left(reverse_rows(south_lines))) +} + +fn transmute(matrix: Vec>) -> Vec> { + (0..matrix[0].len()) + .map(|i| { + matrix + .iter() + .map(|row| *row.get(i).unwrap()) + .collect::>() + }) + .collect::>() +} + +fn reverse_rows(matrix: Vec>) -> Vec> { + matrix + .iter() + .map(|row| { + let mut row = row.clone(); + row.reverse(); + row + }) + .collect::>() +} + +fn slide_rows_left(lines: Vec>) -> Vec> { + lines + .into_iter() + .map(|mut row| { + for n in (1..row.len()).rev() { + for i in 0..n { + if sort_slide_line(&row[i], &row[i + 1]) == Ordering::Greater { + row.swap(i, i + 1); + } + } + } + + row + }) + .collect() +} + +fn sort_slide_line(a: &char, b: &char) -> Ordering { + if a == &'#' || b == &'#' { + Ordering::Equal + } else if a == &'.' && b == &'O' { + Ordering::Greater + } else if a == &'O' && b == &'.' { + Ordering::Less + } else { + a.cmp(b) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use indoc::indoc; + + const INPUT: &str = indoc!( + " + O....#.... + O.OO#....# + .....##... + OO.#O....O + .O.....O#. + O.#..O.#.# + ..O..#O..O + .......O.. + #....###.. + #OO..#.... + " + ); + + #[test] + fn test_part2() { + assert_eq!(part2(INPUT), 64); + } + + #[test] + fn test_cycle() { + let lines = INPUT + .lines() + .map(|l| l.chars().collect()) + .collect::>>(); + // one cycle + assert_eq!( + cycle(lines.clone()), + indoc!( + " + .....#.... + ....#...O# + ...OO##... + .OO#...... + .....OOO#. + .O#...O#.# + ....O#.... + ......OOOO + #...O###.. + #..OO#...." + ) + .lines() + .map(|l| l.chars().collect()) + .collect::>>() + ); + // two cycles + assert_eq!( + cycle(cycle(lines.clone())), + indoc!( + " + .....#.... + ....#...O# + .....##... + ..O#...... + .....OOO#. + .O#...O#.# + ....O#...O + .......OOO + #..OO###.. + #.OOO#...O" + ) + .lines() + .map(|l| l.chars().collect()) + .collect::>>() + ); + // three cycles + assert_eq!( + cycle(cycle(cycle(lines.clone()))), + indoc!( + " + .....#.... + ....#...O# + .....##... + ..O#...... + .....OOO#. + .O#...O#.# + ....O#...O + .......OOO + #...O###.O + #.OOO#...O" + ) + .lines() + .map(|l| l.chars().collect()) + .collect::>>() + ); + } +}