use std::io::{self, Read};
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
fn main() -> Result<()> {
let mut input = String::new();
io::stdin().read_to_string(&mut input)?;
let replaced_input = input.replace("-", " ").replace(":", "");
part1(&replaced_input)?;
part2(&replaced_input)?;
Ok(())
}
fn part1(input: &str) -> Result<()> {
let mut valid = 0;
for line in input.lines() {
let splited: Vec<&str> = line.split_whitespace().collect();
let lower_limit: u32 = splited[0].parse().expect("This must be a number");
let upper_limit: u32 = splited[1].parse().expect("This must be a number");
let alphabet: char = splited[2].parse().expect("This must be a char");
let count: u32 = splited[3].chars().filter(|&char| char == alphabet).count() as u32;
if count >= lower_limit && count <= upper_limit {
valid += 1;
}
}
println!("{}", valid);
Ok(())
}
fn part2(input: &str) -> Result<()> {
let mut valid = 0;
for line in input.lines() {
let splited: Vec<&str> = line.split_whitespace().collect();
let lower_limit: u32 = splited[0].parse().expect("This must be a number");
let upper_limit: u32 = splited[1].parse().expect("This must be a number");
let alphabet: char = splited[2].parse().expect("This must be a char");
let password: Vec<char> = splited[3].chars().collect();
let char_at_lower: char = password[(lower_limit - 1) as usize];
let char_at_upper: char = password[(upper_limit - 1) as usize];
if (char_at_lower == alphabet) ^ (char_at_upper == alphabet) {
valid += 1;
}
}
println!("{}", valid);
Ok(())
}