use super::util; use regex::{Regex, Captures}; use std::ops::BitXor; pub fn solve() { let lines = util::read_file("input/day2.txt"); let passwords: Vec = lines.iter().map(|p| parse(p)).collect(); let part1 = passwords.iter().filter(|p| p.is_valid()).count(); println!("Day 2 Part 1: {}", part1); let part2 = passwords.iter().filter(|p| p.is_valid2()).count(); println!("Day 2 Part 2: {}", part2); } fn parse(line: &String) -> Password { lazy_static! { static ref RE: Regex = Regex::new(r"^(\d+)-(\d+) ([a-zA-Z]): ([a-zA-Z]+)$").unwrap(); } if !RE.is_match(line.as_str()) { panic!("Invalid line: {}", line); } let caps = RE.captures(line).unwrap(); return Password { min: get_capture(&caps, 1).parse::().unwrap(), max: get_capture(&caps, 2).parse::().unwrap(), c: get_capture(&caps, 3).chars().next().unwrap(), password: String::from(get_capture(&caps, 4)) } } fn get_capture(caps: &Captures, id: usize) -> String { return caps.get(id).map_or(String::from(""), |m| String::from(m.as_str())); } // #[derive(Debug)] struct Password { pub min: u32, pub max: u32, pub c: char, pub password: String } impl Password { fn is_valid(&self) -> bool { let occ = self.password.chars().filter(|pc| pc == &self.c).count() as u32; return occ >= self.min && occ <= self.max; } fn is_valid2(&self) -> bool { return (self.password.chars().nth((self.min - 1) as usize) == Option::from(self.c)).bitxor( self.password.chars().nth((self.max - 1) as usize) == Option::from(self.c)); } }