Skip to content

Commit

Permalink
Day 13a
Browse files Browse the repository at this point in the history
  • Loading branch information
lpenz committed Dec 13, 2023
1 parent a47537d commit 8dcedcf
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ members = [
"day10",
"day11",
"day12",
"day13",
]

9 changes: 9 additions & 0 deletions day13/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "day13"
version = "0.1.0"
edition = "2021"

[dependencies]
aoc = { path = "../aoc" }
color-eyre = "0.6.2"
nom = "7.1.3"
109 changes: 109 additions & 0 deletions day13/src/bin/day13a.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (C) 2023 Leandro Lisboa Penz <lpenz@lpenz.org>
// This file is subject to the terms and conditions defined in
// file 'LICENSE', which is part of this source code package.

use std::collections::HashSet;
use std::io::{stdin, BufRead};

use day13::*;

pub type Xy = (usize, usize);

fn vecgrid2hashset(vecgrid: &VecGrid) -> (HashSet<Xy>, Xy) {
let size = (vecgrid[0].len(), vecgrid.len());
(
(0..size.1)
.flat_map(|y| (0..size.0).filter_map(move |x| vecgrid[y][x].then_some((x, y))))
.collect::<HashSet<Xy>>(),
size,
)
}

fn gridmatch_x(mirror: usize, size: &Xy, g: &HashSet<Xy>) -> bool {
let xmin = if 2 * mirror >= size.0 + 1 {
2 * mirror - size.0 + 2
} else {
0
};
for x in xmin..(mirror + 1) {
let xmirror = 2 * mirror + 1 - x;
if xmirror >= size.0 {
continue;
}
for y in 0..size.1 {
if g.contains(&(x, y)) != g.contains(&(xmirror, y)) {
return false;
}
}
}
true
}

fn gridmatch_y(mirror: usize, size: &Xy, g: &HashSet<Xy>) -> bool {
let ymin = if 2 * mirror >= size.1 + 1 {
2 * mirror - size.1 + 2
} else {
0
};
for y in ymin..(mirror + 1) {
let ymirror = 2 * mirror + 1 - y;
if ymirror >= size.1 {
continue;
}
for x in 0..size.0 {
if g.contains(&(x, y)) != g.contains(&(x, ymirror)) {
return false;
}
}
}
true
}

fn calc_summary(vecgrid: VecGrid) -> usize {
let (grid, size) = vecgrid2hashset(&vecgrid);
let max = std::cmp::max(size.0, size.1);
for mirror in (0..max - 1).rev() {
if mirror < size.0 - 1 && gridmatch_x(mirror, &size, &grid) {
return mirror + 1;
}
if mirror < size.1 - 1 && gridmatch_y(mirror, &size, &grid) {
return 100 * (mirror + 1);
}
}
panic!("no mirror found");
}

fn process(bufin: impl BufRead) -> Result<usize> {
let input = parser::parse(bufin)?;
Ok(input.into_iter().map(calc_summary).sum())
}

#[test]
fn test() -> Result<()> {
assert_eq!(process(EXAMPLE.as_bytes())?, 405);
Ok(())
}

// #[test]
// fn test2() -> Result<()> {
// pub const EXAMPLE: &str = "#..#...#.#..#
// #..#####.####
// #..######....
// .##...####.#.
// .##.##.#.####
// #..#.###.##.#
// .....###.#.#.
// .##..##..##..
// ....#.#####..
// ....###..##.#
// ....####.##.#
// ";
// assert_eq!(process(EXAMPLE.as_bytes())?, 0405);
// Ok(())
// }

fn main() -> Result<()> {
color_eyre::install()?;
println!("{}", process(stdin().lock())?);
Ok(())
}
61 changes: 61 additions & 0 deletions day13/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (C) 2023 Leandro Lisboa Penz <lpenz@lpenz.org>
// This file is subject to the terms and conditions defined in
// file 'LICENSE', which is part of this source code package.

pub use color_eyre::{eyre::eyre, Result};

pub const EXAMPLE: &str = "#.##..##.
..#.##.#.
##......#
##......#
..#.##.#.
..##..##.
#.#.##.#.
#...##..#
#....#..#
..##..###
#####.##.
#####.##.
..##..###
#....#..#
";

pub type VecGrid = Vec<Vec<bool>>;

pub mod parser {
use aoc::parser::*;

use super::*;

fn cell(input: &str) -> IResult<&str, bool> {
let (input, c) = character::one_of(".#")(input)?;
Ok((input, c == '#'))
}

fn line(input: &str) -> IResult<&str, Vec<bool>> {
let (input, cells) = multi::many1(cell)(input)?;
let (input, _) = character::newline(input)?;
Ok((input, cells))
}

fn grid(input: &str) -> IResult<&str, VecGrid> {
let (input, g) = multi::many1(line)(input)?;
Ok((input, g))
}

pub fn parse(mut bufin: impl BufRead) -> Result<Vec<VecGrid>> {
aoc::parse_with!(multi::separated_list1(character::newline, grid), bufin)
}
}

#[test]
fn test() -> Result<()> {
let input = parser::parse(EXAMPLE.as_bytes())?;
assert_eq!(input.len(), 2);
assert_eq!(input[0].len(), 7);
assert_eq!(input[0][1].len(), 9);
assert_eq!(input[1].len(), 7);
assert_eq!(input[1][1].len(), 9);
Ok(())
}

0 comments on commit 8dcedcf

Please sign in to comment.