diff --git a/src/day13.rs b/src/day13.rs new file mode 100644 index 0000000..ff5a3b4 --- /dev/null +++ b/src/day13.rs @@ -0,0 +1,113 @@ +use std::collections::HashSet; +use aoc_runner_derive::{aoc, aoc_generator}; + +type Coordinates = (i32, i32); + +#[aoc_generator(day13)] +fn parse(input: &str) -> Vec> { + input.split("\n\n") + .map(|pattern| { + let mut map: HashSet = HashSet::new(); + for (y, line) in pattern.lines().into_iter().enumerate() { + for (x, char) in line.chars().enumerate() { + if char == '#' { + map.insert((x as i32 + 1, y as i32 + 1)); + } + } + } + map + }).collect::>() +} + +fn reflection((x, y): &Coordinates, pattern: &HashSet, max_x: i32, max_y: i32, axis: &i32, is_column: bool) -> bool { + if is_column { + x <= axis && (2 * axis - x + 1 > max_x || pattern.contains(&(2 * axis - x + 1, *y))) + || x > axis && (2 * axis - x + 1 < 1 || pattern.contains(&(2 * axis - x + 1, *y))) + } else { + y <= axis && (2 * axis - y + 1 > max_y || pattern.contains(&(*x, 2 * axis - y + 1))) + || y > axis && (2 * axis - y + 1 < 1 || pattern.contains(&(*x, 2 * axis - y + 1))) + } +} + + +fn calc_summary(pattern: &HashSet) -> usize { + let max_x = pattern.iter().max_by(|a, b| a.0.cmp(&b.0)).unwrap().0; + let max_y = pattern.iter().max_by(|a, b| a.1.cmp(&b.1)).unwrap().1; + + ((1..max_x) + .find(|column| { + pattern.iter() + .all(|coords| { + reflection(coords, pattern, max_x, max_y, column, true) + }) + }).unwrap_or(0) + + 100 * (1..max_y) + .find(|row| { + pattern.iter().all(|coordinates| { + reflection(coordinates, pattern, max_x, max_y, row, false) + }) + }) + .unwrap_or(0)) as usize +} + + +#[aoc(day13, part1)] +fn part1(input: &Vec>) -> usize { + input.iter().map(calc_summary).sum() +} + +fn calc_summary_part2(pattern: &HashSet) -> usize { + let max_x = pattern.iter().max_by(|a, b| a.0.cmp(&b.0)).unwrap().0; + let max_y = pattern.iter().max_by(|a, b| a.1.cmp(&b.1)).unwrap().1; + + ((1..max_x) + .find(|column| { + pattern.iter().filter(|coords| { + reflection(coords, pattern, max_x, max_y, column, true) + }).count() == pattern.len() - 1 + }).unwrap_or(0) + + 100 * (1..max_y) + .find(|row| { + pattern.iter().filter(|coordinates| { + reflection(coordinates, pattern, max_x, max_y, row, false) + }).count() == pattern.len() - 1 + }) + .unwrap_or(0)) as usize +} + +#[aoc(day13, part2)] +fn part2(input: &Vec>) -> usize { + input.iter().map(calc_summary_part2).sum() +} + + +#[cfg(test)] +mod tests { + use super::*; + + const EX: &str = r"#.##..##. +..#.##.#. +##......# +##......# +..#.##.#. +..##..##. +#.#.##.#. + +#...##..# +#....#..# +..##..### +#####.##. +#####.##. +..##..### +#....#..#"; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse(EX)), 405); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse(EX)), 400); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index b4a08a1..c5b3971 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day13; mod day12; mod day4; mod day2;