advent_of_code/year2019/
day04.rs

1use crate::input::Input;
2use std::cmp::Ordering;
3
4fn parse_input(input_string: &str) -> Result<(i32, i32), String> {
5    let (from_str, to_str) = input_string
6        .trim()
7        .split_once('-')
8        .ok_or_else(|| "Invalid parts - should be in FROM-TO form".to_string())?;
9    let from = from_str.parse::<i32>().or(Err("Invalid range"))?;
10    let to = to_str.parse::<i32>().or(Err("Invalid range"))?;
11    Ok((from, to))
12}
13
14pub fn solve(input: &Input) -> Result<u32, String> {
15    let (from, to) = parse_input(input.text)?;
16
17    let mut meeting_criteria_count: u32 = 0;
18    'outer: for i in from..=to {
19        let mut divider = 1;
20        let mut last_digit = 10;
21        let mut two_digits_adjacent = false;
22
23        let mut digits_adjacent_streak = 1;
24
25        while divider <= 100_000 {
26            let digit = (i / divider) % 10;
27            match digit.cmp(&last_digit) {
28                Ordering::Greater => {
29                    continue 'outer;
30                }
31                Ordering::Equal => {
32                    if input.is_part_one() {
33                        two_digits_adjacent = true;
34                    } else {
35                        digits_adjacent_streak += 1;
36                    }
37                }
38                Ordering::Less => {
39                    if digits_adjacent_streak == 2 {
40                        two_digits_adjacent = true;
41                    }
42                    digits_adjacent_streak = 1;
43                }
44            }
45
46            last_digit = digit;
47            divider *= 10;
48        }
49
50        if digits_adjacent_streak == 2 {
51            two_digits_adjacent = true;
52        }
53
54        if two_digits_adjacent {
55            meeting_criteria_count += 1;
56        }
57    }
58
59    Ok(meeting_criteria_count)
60}
61
62#[test]
63pub fn tests() {
64    use crate::input::{test_part_one, test_part_two};
65
66    test_part_one!("100010-100011" => 0);
67    test_part_one!("111110-111111" => 1);
68
69    test_part_two!("112233-112233" => 1);
70    test_part_two!("123444-123444" => 0);
71    test_part_two!("111122-111122" => 1);
72
73    let input = include_str!("day04_input.txt");
74    test_part_one!(input => 1675);
75    test_part_two!(input => 1142);
76}