2020-12-03 14:10:04 +00:00
|
|
|
use aoc_runner_derive::{aoc, aoc_generator};
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Ord, PartialOrd)]
|
|
|
|
pub struct Rule {
|
|
|
|
min: usize,
|
|
|
|
max: usize,
|
|
|
|
ch: char,
|
|
|
|
pw: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Rule {
|
|
|
|
fn is_valid_part1(&self) -> bool {
|
|
|
|
let n = self.pw.chars().filter(|c| *c == self.ch).count();
|
|
|
|
return n >= self.min && n <= self.max;
|
|
|
|
}
|
|
|
|
fn is_valid_part2(&self) -> bool {
|
|
|
|
let idx_1 = self.min - 1;
|
|
|
|
let idx_2 = self.max - 1;
|
|
|
|
let chars: Vec<char> = self.pw.chars().collect();
|
|
|
|
return (chars.get(idx_1) == Some(&self.ch)) ^ (chars.get(idx_2) == Some(&self.ch));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc_generator(day2)]
|
|
|
|
pub fn input_generator(input: &str) -> Vec<Rule> {
|
|
|
|
input
|
|
|
|
.lines()
|
|
|
|
.map(|l| {
|
|
|
|
let mut ws = l.trim().split_whitespace();
|
|
|
|
let range = ws.next().unwrap();
|
|
|
|
let ch = ws
|
|
|
|
.next()
|
|
|
|
.unwrap()
|
|
|
|
.trim_end_matches(|c| c == ':')
|
|
|
|
.chars()
|
|
|
|
.next()
|
|
|
|
.unwrap();
|
|
|
|
let pw = ws.next().unwrap().to_owned();
|
|
|
|
let (r_min, r_max) = {
|
|
|
|
let mut r = range.split('-');
|
|
|
|
let r_min = r.next().unwrap().parse().unwrap();
|
|
|
|
let r_max = r.next().unwrap().parse().unwrap();
|
|
|
|
(r_min, r_max)
|
|
|
|
};
|
|
|
|
Rule {
|
|
|
|
min: r_min,
|
|
|
|
max: r_max,
|
|
|
|
ch,
|
|
|
|
pw,
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collect::<Vec<Rule>>()
|
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day2, part1)]
|
|
|
|
pub fn solve_part1(input: &Vec<Rule>) -> usize {
|
2020-12-06 02:20:11 +00:00
|
|
|
return input.iter().filter(|v| v.is_valid_part1()).count();
|
2020-12-03 14:10:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[aoc(day2, part2)]
|
|
|
|
pub fn solve_part2(input: &Vec<Rule>) -> usize {
|
2020-12-06 02:20:11 +00:00
|
|
|
return input.iter().filter(|v| v.is_valid_part2()).count();
|
2020-12-03 14:10:04 +00:00
|
|
|
}
|