~janbaudisch/aoc-2019

347d45cc1003a7feb22e45adb9f51329effab338 — Jan Baudisch 4 years ago d9ec111
add day_04
5 files changed, 180 insertions(+), 1 deletions(-)

M Cargo.lock
M Cargo.toml
A day_04/Cargo.toml
A day_04/src/checks.rs
A day_04/src/main.rs
M Cargo.lock => Cargo.lock +7 -0
@@ 17,3 17,10 @@ version = "1.0.0"
dependencies = [
 "common 1.0.0",
]

[[package]]
name = "day_04"
version = "1.0.0"
dependencies = [
 "common 1.0.0",
]

M Cargo.toml => Cargo.toml +2 -1
@@ 2,7 2,8 @@
members = [
    "common",
    "day_01",
    "day_02"
    "day_02",
    "day_04"
]

[profile.release]

A day_04/Cargo.toml => day_04/Cargo.toml +12 -0
@@ 0,0 1,12 @@
[package]
name = "day_04"
version = "1.0.0"
description = "Day 4 - Advent of Code 2019"
authors = ["Jan Baudisch <dev@baudisch.xyz>"]
license = "GPL-3.0-or-later"
readme = "../README.md"
edition = "2018"
workspace = ".."

[dependencies]
common = { path = "../common" }

A day_04/src/checks.rs => day_04/src/checks.rs +130 -0
@@ 0,0 1,130 @@
pub trait AdjacentGroup {
    fn has_adjacent_group(&self) -> bool;
}

impl AdjacentGroup for u32 {
    fn has_adjacent_group(&self) -> bool {
        let digits: Vec<char> = self.to_string().chars().collect();
        let mut has_group = false;

        for (i, digit) in digits.iter().enumerate() {
            if i == digits.len() - 1 {
                break;
            }

            if *digit == digits[i + 1] {
                has_group = true;
                break;
            }
        }

        has_group
    }
}

pub trait AdjacentPair {
    fn has_adjacent_pair(&self) -> bool;
}

impl AdjacentPair for u32 {
    fn has_adjacent_pair(&self) -> bool {
        let digits: Vec<char> = self.to_string().chars().collect();

        if digits.len() < 2 {
            return false;
        }

        if digits.len() == 2 {
            return digits[0] == digits[1];
        }

        let mut has_pair = false;

        for (i, digit) in digits.iter().enumerate() {
            if i == digits.len() - 2 {
                if *digit == digits[i + 1] && *digit != digits[i - 1] {
                    has_pair = true;
                }

                break;
            }

            if i == 0 {
                if *digit == digits[1] && *digit != digits[2] {
                    has_pair = true;
                    break;
                }

                continue;
            }

            if *digit != digits[i - 1] && *digit == digits[i + 1] && *digit != digits[i + 2] {
                has_pair = true;
                break;
            }
        }

        has_pair
    }
}

pub trait AlwaysIncreases {
    fn always_increases(&self) -> bool;
}

impl AlwaysIncreases for u32 {
    fn always_increases(&self) -> bool {
        let digits: Vec<u32> = self
            .to_string()
            .chars()
            .map(|x| x.to_digit(10).unwrap())
            .collect();

        let mut increases = true;

        for (i, digit) in digits.iter().enumerate() {
            if i == digits.len() - 1 {
                break;
            }

            if *digit > digits[i + 1] {
                increases = false;
                break;
            }
        }

        increases
    }
}

#[cfg(test)]
mod tests {
    use super::{AdjacentGroup, AdjacentPair, AlwaysIncreases};

    #[test]
    fn adjacent_group() {
        assert!(1234556789.has_adjacent_group());
        assert!(1111111111.has_adjacent_group());
        assert!(!123456789.has_adjacent_group());
        assert!(!123789.has_adjacent_group());
    }

    #[test]
    fn adjacent_pair() {
        assert!(1234556789.has_adjacent_pair());
        assert!(112233.has_adjacent_pair());
        assert!(111122.has_adjacent_pair());
        assert!(!1111111111.has_adjacent_pair());
        assert!(!123456789.has_adjacent_pair());
        assert!(!123444.has_adjacent_pair());
    }

    #[test]
    fn always_increases() {
        assert!(123456789.always_increases());
        assert!(111111111.always_increases());
        assert!(!987654321.always_increases());
        assert!(!1234567890.always_increases());
        assert!(!223450.always_increases());
    }
}

A day_04/src/main.rs => day_04/src/main.rs +29 -0
@@ 0,0 1,29 @@
mod checks;

use checks::{AdjacentGroup, AdjacentPair, AlwaysIncreases};
use common::input;

fn main() {
    let input = input::read_line();

    let range: Vec<&str> = input.split('-').collect();
    let lower = u32::from_str_radix(range[0], 10)
        .unwrap_or_else(|_| panic!("invalid lower bound: {}", range[0]));
    let upper = u32::from_str_radix(range[1], 10)
        .unwrap_or_else(|_| panic!("invalid upper bound: {}", range[1]));

    let passwords: Vec<u32> = (lower..=upper).collect();
    let passwords: Vec<&u32> = passwords
        .iter()
        .filter(|password| password.has_adjacent_group() && password.always_increases())
        .collect();

    println!("[PART ONE] number of passwords: {}", passwords.len());

    let passwords: Vec<&&u32> = passwords
        .iter()
        .filter(|password| password.has_adjacent_pair())
        .collect();

    println!("[PART TWO] number of passwords: {}", passwords.len());
}