use structopt::StructOpt; #[derive(Debug, StructOpt)] #[structopt(name = "Day 4: Secure Container")] /// Calculates how many possible lock values there are /// /// See https://adventofcode.com/2019/day/4 for details. struct Opt { /// Repeated digits must be exactly 2 long #[structopt(long = "larger-range-rule")] larger_range_rule: bool, min: u32, max: u32, } fn main() { let opt = Opt::from_args(); println!( "{}", valid_combinations(opt.min, opt.max, opt.larger_range_rule) ) } fn valid_combinations(min: u32, max: u32, larger_range_rule: bool) -> u32 { (min..max) .filter(|x| { two_adjacent_identical_digits(*x, larger_range_rule) && digits_never_decrease(*x) }) .count() as u32 } fn two_adjacent_identical_digits(x: u32, larger_range_rule: bool) -> bool { if larger_range_rule { (0..5).any(|d| { digit(x, d) == digit(x, d + 1) && digit(x, d) != digit(x, d + 2) && digit(x, d) != digit(x, d - 1) }) } else { (0..5).any(|d| digit(x, d) == digit(x, d + 1)) } } fn digits_never_decrease(x: u32) -> bool { (0..5).all(|d| digit(x, d) >= digit(x, d + 1)) } fn digit(x: u32, digit: i32) -> u32 { if digit < 0 { 0 } else { (x / 10u32.pow(digit as u32)) % 10 } }