From 0838646973a1cd62d0c0c6286d8eebff21d2536f Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Wed, 13 Dec 2023 18:21:19 +0100 Subject: [PATCH] Implement 2023 day 13 part 1 --- 2023/src/common.rs | 8 ++++ 2023/src/day13.rs | 92 ++++++++++++++++++++++++++++++++++++++++- 2023/src/samples/13.txt | 15 +++++++ 3 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 2023/src/samples/13.txt diff --git a/2023/src/common.rs b/2023/src/common.rs index 1ee763d..a291dce 100644 --- a/2023/src/common.rs +++ b/2023/src/common.rs @@ -1,6 +1,8 @@ //! Common helper utilities to all days use std::cmp::Ordering; +use std::fmt; +use std::fmt::Display; use std::ops::Add; use std::ops::Div; use std::ops::Index; @@ -292,3 +294,9 @@ impl<'a> Index for Grid<'a> { &self.data[offset..(offset + self.width())] } } + +impl Display for Grid<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", String::from_utf8_lossy(self.data)) + } +} diff --git a/2023/src/day13.rs b/2023/src/day13.rs index 7c1760f..3fdd3a8 100644 --- a/2023/src/day13.rs +++ b/2023/src/day13.rs @@ -1,7 +1,95 @@ -pub fn part1(_input: &[u8]) -> anyhow::Result { - anyhow::bail!("Not implemented") +use crate::common::Grid; + +#[derive(Debug)] +enum Symmetry { + Horizontal(u32), + Vertical(u32), +} + +impl Symmetry { + fn value(self) -> u32 { + match self { + Symmetry::Horizontal(value) => 100 * value, + Symmetry::Vertical(value) => value, + } + } +} + +fn find_symmetry(grid: Grid<'_>) -> Option { + // Attempt to find a vertical line of reflection first + for c in 1..grid.width() { + if grid + .rows() + .all(|row| row[..c].iter().rev().zip(&row[c..]).all(|(a, b)| a == b)) + { + return Some(Symmetry::Vertical(c as u32)); + } + } + + for r in 1..grid.height() { + if (0..r) + .rev() + .zip(r..grid.height()) + .all(|(a, b)| grid[a] == grid[b]) + { + return Some(Symmetry::Horizontal(r as u32)); + } + } + + println!("Suspiciously did not find an axis of symmetry:\n\n{grid}\n"); + None +} + +fn parse_grids(input: &[u8]) -> anyhow::Result>> { + let mut result = Vec::new(); + let mut start = 0; + let mut last_newline = 0; + + for i in input + .iter() + .enumerate() + .filter_map(|(i, c)| (*c == b'\n').then_some(i)) + { + if last_newline == i - 1 { + result.push(Grid::new(&input[start..i])?); + start = i + 1; + } + last_newline = i; + } + + result.push(Grid::new(&input[start..])?); + + Ok(result) +} + +pub fn part1(input: &[u8]) -> anyhow::Result { + let grids = parse_grids(input)?; + + let sum: u32 = grids + .into_iter() + .filter_map(find_symmetry) + .map(Symmetry::value) + .sum(); + Ok(sum.to_string()) } pub fn part2(_input: &[u8]) -> anyhow::Result { anyhow::bail!("Not implemented") } + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLE: &[u8] = include_bytes!("samples/13.txt"); + + #[test] + fn sample_part1() { + assert_eq!("405", part1(SAMPLE).unwrap()); + } + + // #[test] + // fn sample_part2() { + // assert_eq!("525152", part2(SAMPLE).unwrap()); + // } +} diff --git a/2023/src/samples/13.txt b/2023/src/samples/13.txt new file mode 100644 index 0000000..3b6b5cc --- /dev/null +++ b/2023/src/samples/13.txt @@ -0,0 +1,15 @@ +#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#