Day 13
This commit is contained in:
parent
72f7b2b42c
commit
3109c3f918
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,265 @@
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
pub fn run() {
|
||||||
|
let input = include_str!("../input/day13.txt");
|
||||||
|
// let input = r#"#.##..##.
|
||||||
|
// ..#.##.#.
|
||||||
|
// ##......#
|
||||||
|
// ##......#
|
||||||
|
// ..#.##.#.
|
||||||
|
// ..##..##.
|
||||||
|
// #.#.##.#.
|
||||||
|
|
||||||
|
// #...##..#
|
||||||
|
// #....#..#
|
||||||
|
// ..##..###
|
||||||
|
// #####.##.
|
||||||
|
// #####.##.
|
||||||
|
// ..##..###
|
||||||
|
// #....#..#"#;
|
||||||
|
|
||||||
|
dbg!(count_reflections(input, false));
|
||||||
|
dbg!(count_reflections(input, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn count_reflections(s: &str, fixing_smudges: bool) -> usize {
|
||||||
|
let grids: Vec<Grid> = s.split("\n\n").map(|s| s.into()).collect();
|
||||||
|
let mut horiz = 0;
|
||||||
|
let mut vert = 0;
|
||||||
|
for g in grids {
|
||||||
|
vert += g
|
||||||
|
.find_vertical_mirrors(fixing_smudges)
|
||||||
|
.iter()
|
||||||
|
.sum::<usize>();
|
||||||
|
horiz += g
|
||||||
|
.find_horizontal_mirrors(fixing_smudges)
|
||||||
|
.iter()
|
||||||
|
.sum::<usize>();
|
||||||
|
}
|
||||||
|
(horiz * 100) + vert
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum Tile {
|
||||||
|
Ash,
|
||||||
|
Rock,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Grid {
|
||||||
|
tiles: Vec<Vec<Tile>>,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for Grid {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
let tiles = value
|
||||||
|
.trim()
|
||||||
|
.lines()
|
||||||
|
.map(|l| {
|
||||||
|
l.trim()
|
||||||
|
.chars()
|
||||||
|
.map(|c| match c {
|
||||||
|
'.' => Tile::Ash,
|
||||||
|
'#' => Tile::Rock,
|
||||||
|
_ => panic!("invalid char {:?}", c),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let width = tiles[0].len();
|
||||||
|
let height = tiles.len();
|
||||||
|
Self {
|
||||||
|
tiles,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Debug for Grid {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let s = self
|
||||||
|
.tiles
|
||||||
|
.iter()
|
||||||
|
.map(|row| {
|
||||||
|
row.iter()
|
||||||
|
.map(|t| match t {
|
||||||
|
Tile::Ash => '.',
|
||||||
|
Tile::Rock => '#',
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
write!(f, "Grid(\n{})", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Grid {
|
||||||
|
fn find_vertical_mirrors(&self, fixing_smudges: bool) -> Vec<usize> {
|
||||||
|
find_mirrors(&self.tiles, fixing_smudges)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_horizontal_mirrors(&self, fixing_smudges: bool) -> Vec<usize> {
|
||||||
|
let transposed = transpose(&self.tiles);
|
||||||
|
find_mirrors(&transposed, fixing_smudges)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_mirrors<T: Eq>(v: &Vec<Vec<T>>, fixing_smudges: bool) -> Vec<usize> {
|
||||||
|
(1..v[0].len())
|
||||||
|
.filter(|&mirror_idx| {
|
||||||
|
let mut mismatched_indices = 0;
|
||||||
|
for inner in v.iter() {
|
||||||
|
let (before, after) = inner.split_at(mirror_idx);
|
||||||
|
let len = before.len().min(after.len());
|
||||||
|
let inner_mismatched =
|
||||||
|
find_mismatched_indices(before.iter().rev().take(len), after.iter().take(len));
|
||||||
|
if fixing_smudges {
|
||||||
|
mismatched_indices += inner_mismatched.len();
|
||||||
|
} else if !inner_mismatched.is_empty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if fixing_smudges {
|
||||||
|
mismatched_indices == 1
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_mismatched_indices<T: Eq>(
|
||||||
|
a: impl Iterator<Item = T>,
|
||||||
|
b: impl Iterator<Item = T>,
|
||||||
|
) -> Vec<usize> {
|
||||||
|
let mut mismatched = vec![];
|
||||||
|
for (i, (a, b)) in a.zip(b).enumerate() {
|
||||||
|
if a != b {
|
||||||
|
mismatched.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mismatched
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transpose<T: Copy>(orig: &Vec<Vec<T>>) -> Vec<Vec<T>> {
|
||||||
|
let mut new = vec![];
|
||||||
|
for col in 0..orig[0].len() {
|
||||||
|
let mut new_row = vec![];
|
||||||
|
for row in 0..orig.len() {
|
||||||
|
new_row.push(orig[row][col]);
|
||||||
|
}
|
||||||
|
new.push(new_row);
|
||||||
|
}
|
||||||
|
new
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vertical_reflection() {
|
||||||
|
let g: Grid = r#"#.##..##.
|
||||||
|
..#.##.#.
|
||||||
|
##......#
|
||||||
|
##......#
|
||||||
|
..#.##.#.
|
||||||
|
..##..##.
|
||||||
|
#.#.##.#."#
|
||||||
|
.into();
|
||||||
|
assert_eq!(g.find_vertical_mirrors(false), vec![5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_horizontal_reflection() {
|
||||||
|
let g: Grid = r#"#...##..#
|
||||||
|
#....#..#
|
||||||
|
..##..###
|
||||||
|
#####.##.
|
||||||
|
#####.##.
|
||||||
|
..##..###
|
||||||
|
#....#..#"#
|
||||||
|
.into();
|
||||||
|
assert_eq!(g.find_horizontal_mirrors(false), vec![4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_count() {
|
||||||
|
let input = r#"#.##..##.
|
||||||
|
..#.##.#.
|
||||||
|
##......#
|
||||||
|
##......#
|
||||||
|
..#.##.#.
|
||||||
|
..##..##.
|
||||||
|
#.#.##.#.
|
||||||
|
|
||||||
|
#...##..#
|
||||||
|
#....#..#
|
||||||
|
..##..###
|
||||||
|
#####.##.
|
||||||
|
#####.##.
|
||||||
|
..##..###
|
||||||
|
#....#..#"#;
|
||||||
|
assert_eq!(count_reflections(input, false), 405);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_count_fixing_smudges() {
|
||||||
|
let input = r#"#.##..##.
|
||||||
|
..#.##.#.
|
||||||
|
##......#
|
||||||
|
##......#
|
||||||
|
..#.##.#.
|
||||||
|
..##..##.
|
||||||
|
#.#.##.#.
|
||||||
|
|
||||||
|
#...##..#
|
||||||
|
#....#..#
|
||||||
|
..##..###
|
||||||
|
#####.##.
|
||||||
|
#####.##.
|
||||||
|
..##..###
|
||||||
|
#....#..#"#;
|
||||||
|
assert_eq!(count_reflections(input, true), 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_grid2() {
|
||||||
|
let g: Grid = r#"
|
||||||
|
..#.###
|
||||||
|
#.#####
|
||||||
|
#.#####
|
||||||
|
..#..##
|
||||||
|
#......
|
||||||
|
##..###
|
||||||
|
..#....
|
||||||
|
"#
|
||||||
|
.into();
|
||||||
|
assert_eq!(g.find_vertical_mirrors(false), vec![6]);
|
||||||
|
assert_eq!(g.find_horizontal_mirrors(false), vec![]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_transpose() {
|
||||||
|
let orig = vec![vec![1, 2, 3], vec![3, 4, 5]];
|
||||||
|
assert_eq!(transpose(&orig), vec![vec![1, 3], vec![2, 4], vec![3, 5]]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_fixing_smudges() {
|
||||||
|
let g: Grid = r#"#.##..##.
|
||||||
|
..#.##.#.
|
||||||
|
##......#
|
||||||
|
##......#
|
||||||
|
..#.##.#.
|
||||||
|
..##..##.
|
||||||
|
#.#.##.#."#
|
||||||
|
.into();
|
||||||
|
assert_eq!(g.find_horizontal_mirrors(true), vec![3]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,8 @@ mod day09;
|
||||||
mod day10;
|
mod day10;
|
||||||
mod day11;
|
mod day11;
|
||||||
mod day12;
|
mod day12;
|
||||||
|
mod day13;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
day12::run();
|
day13::run();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue