89 lines
2.2 KiB
Rust
89 lines
2.2 KiB
Rust
|
use std::cmp::min;
|
||
|
|
||
|
use aoc_2023::*;
|
||
|
use itertools::iproduct;
|
||
|
|
||
|
type Output1 = i32;
|
||
|
type Output2 = Output1;
|
||
|
|
||
|
struct Pattern {
|
||
|
map: Vec<Vec<char>>,
|
||
|
}
|
||
|
|
||
|
impl From<&[String]> for Pattern {
|
||
|
fn from(value: &[String]) -> Self {
|
||
|
Self {
|
||
|
map: value.iter().map(|l| l.chars().collect_vec()).collect_vec(),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Pattern {
|
||
|
fn check_vertically(&self, allowed_error: usize) -> Option<i32> {
|
||
|
(0..self.map[0].len() - 1)
|
||
|
.find(|&x| {
|
||
|
let d = min(x + 1, self.map[0].len() - x - 1);
|
||
|
|
||
|
iproduct!(0..self.map.len(), (0..d))
|
||
|
.filter(|&(y, dx)| self.map[y][x - dx] != self.map[y][x + dx + 1])
|
||
|
.count()
|
||
|
== allowed_error
|
||
|
})
|
||
|
.map(|x| (x + 1) as i32)
|
||
|
}
|
||
|
|
||
|
fn check_horizontally(&self, allowed_error: usize) -> Option<i32> {
|
||
|
(0..self.map.len() - 1)
|
||
|
.find(|&y| {
|
||
|
let d = min(y + 1, self.map.len() - y - 1);
|
||
|
|
||
|
iproduct!(0..self.map[y].len(), (0..d))
|
||
|
.filter(|&(x, dy)| self.map[y - dy][x] != self.map[y + dy + 1][x])
|
||
|
.count()
|
||
|
== allowed_error
|
||
|
})
|
||
|
.map(|y| 100 * (y + 1) as i32)
|
||
|
}
|
||
|
|
||
|
fn score(&self, allowed_error: usize) -> i32 {
|
||
|
if let Some(s) = self.check_vertically(allowed_error) {
|
||
|
s
|
||
|
} else if let Some(s) = self.check_horizontally(allowed_error) {
|
||
|
s
|
||
|
} else {
|
||
|
unreachable!()
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct Day13 {
|
||
|
patterns: Vec<Pattern>,
|
||
|
}
|
||
|
impl Solution<Output1, Output2> for Day13 {
|
||
|
fn new<P: AsRef<Path>>(pathname: P) -> Self {
|
||
|
let lines: Vec<String> = file_to_lines(pathname);
|
||
|
|
||
|
let patterns = lines
|
||
|
.split(|l| l.is_empty())
|
||
|
.map(|m| m.into())
|
||
|
.collect_vec();
|
||
|
|
||
|
Self { patterns }
|
||
|
}
|
||
|
|
||
|
fn part_1(&mut self) -> Output1 {
|
||
|
self.patterns.iter().map(|p| p.score(0)).sum()
|
||
|
}
|
||
|
|
||
|
fn part_2(&mut self) -> Output2 {
|
||
|
self.patterns.iter().map(|p| p.score(1)).sum()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn main() -> Result<()> {
|
||
|
// Day13::run("sample")
|
||
|
Day13::main()
|
||
|
}
|
||
|
|
||
|
test_sample!(day_13, Day13, 405, 400);
|