mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
76 lines
1.6 KiB
Rust
76 lines
1.6 KiB
Rust
use std::io::Read;
|
|
|
|
use regex::Regex;
|
|
|
|
use crate::common::Lines;
|
|
use crate::Solution;
|
|
|
|
fn matches1(min: usize, max: usize, c: char, sample: &str) -> bool {
|
|
let occurrences = sample.matches(c).count();
|
|
|
|
occurrences >= min && occurrences <= max
|
|
}
|
|
|
|
fn matches2(first: usize, second: usize, c: char, sample: &str) -> bool {
|
|
let c = c as u8;
|
|
let s = sample.as_bytes();
|
|
|
|
(s[first - 1] == c) ^ (s[second - 1] == c)
|
|
}
|
|
|
|
fn read_rules<M>(input: &mut dyn Read, matcher: M) -> usize
|
|
where
|
|
M: for<'r> Fn(usize, usize, char, &'r str) -> bool,
|
|
{
|
|
let parser = Regex::new(r"^(\d+)-(\d+) ([a-z]): ([a-z]+)$").unwrap();
|
|
|
|
let mut matching = 0;
|
|
|
|
for line in Lines::new(input) {
|
|
let cap = parser.captures(&line).unwrap();
|
|
|
|
let first = cap[1].parse().unwrap();
|
|
let second = cap[2].parse().unwrap();
|
|
let c = cap[3].chars().next().unwrap();
|
|
let sample = &cap[4];
|
|
|
|
if matcher(first, second, c, sample) {
|
|
matching += 1
|
|
}
|
|
}
|
|
|
|
matching
|
|
}
|
|
|
|
#[derive(Default)]
|
|
pub struct Day02;
|
|
|
|
impl Solution for Day02 {
|
|
fn part1(&mut self, input: &mut dyn Read) -> String {
|
|
read_rules(input, matches1).to_string()
|
|
}
|
|
|
|
fn part2(&mut self, input: &mut dyn Read) -> String {
|
|
read_rules(input, matches2).to_string()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::test_implementation;
|
|
|
|
use super::*;
|
|
|
|
const SAMPLE: &[u8] = include_bytes!("../samples/02.txt");
|
|
|
|
#[test]
|
|
fn sample_part1() {
|
|
test_implementation!(Day02, 1, SAMPLE, 2);
|
|
}
|
|
|
|
#[test]
|
|
fn sample_part2() {
|
|
test_implementation!(Day02, 2, SAMPLE, 1);
|
|
}
|
|
}
|