advent_of_code/year2019/
day04.rs1use 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}