use itertools::Itertools; use std::env; fn is_increasing(n:u32) -> bool { for (l, r) in (0..5).rev().map(|e| n/10u32.pow(e)%10) .zip((1..6).rev().map(|e| n/10u32.pow(e)%10)) { if l < r { return false; } } true } fn has_repeated(n:u32) -> bool { for (l, r) in (0..5).rev().map(|e| n/10u32.pow(e)%10) .zip((1..6).rev().map(|e| n/10u32.pow(e)%10)) { if l == r { return true; } } false } fn has_double(n:u32) -> bool { #[derive(Debug, PartialEq)] enum State { NoMatch, Matching, TooLong, Verified }; let mut state = State::NoMatch; for (l, r) in (0..5).rev().map(|e| n/10u32.pow(e)%10) .zip((1..6).rev().map(|e| n/10u32.pow(e)%10)) { state = match state { State::NoMatch => if l == r { State::Matching } else { State::NoMatch }, State::Matching => if l == r { State::TooLong } else { State::Verified }, State::TooLong => if l == r { State::TooLong } else { State::NoMatch }, State::Verified => State::Verified, }; if state == State::Verified { break; } } state == State::Verified || state == State::Matching } fn first_puzzle(input:String) -> usize { let ( start, end ) = input.split("-") .map(|s| s.parse::().unwrap()) .next_tuple().unwrap(); (start..=end) .filter(|n| is_increasing(*n)) .filter(|n| has_repeated(*n)) .count() } fn second_puzzle(input:String) -> usize { let ( start, end ) = input.split("-") .map(|s| s.parse::().unwrap()) .next_tuple().unwrap(); (start..=end) .filter(|n| is_increasing(*n)) .filter(|n| has_double(*n)) .count() } fn main() { let input = env::args().nth(1).expect("Please provide a valid range as first argument."); let first = first_puzzle(input.clone()); println!("Solution to first part: {}.", first); let second = second_puzzle(input); println!("Solution to second part: {}.", second); }