Andrew Swistak %!s(int64=6) %!d(string=hai) anos
pai
achega
04f239571a
Modificáronse 2 ficheiros con 227 adicións e 0 borrados
  1. 225 0
      src/day_4/mod.rs
  2. 2 0
      src/main.rs

+ 225 - 0
src/day_4/mod.rs

@@ -0,0 +1,225 @@
+/*
+--- Day 4: Secure Container ---
+
+You arrive at the Venus fuel depot only to discover it's protected by a password. The Elves had written the password on a sticky note, but someone threw it out.
+
+However, they do remember a few key facts about the password:
+
+    It is a six-digit number.
+    The value is within the range given in your puzzle input.
+    Two adjacent digits are the same (like 22 in 122345).
+    Going from left to right, the digits never decrease; they only ever increase or stay the same (like 111123 or 135679).
+
+Other than the range rule, the following are true:
+
+    111111 meets these criteria (double 11, never decreases).
+    223450 does not meet these criteria (decreasing pair of digits 50).
+    123789 does not meet these criteria (no double).
+
+How many different passwords within the range given in your puzzle input meet these criteria?
+
+Your puzzle input is 402328-864247.
+
+--- Part Two ---
+
+An Elf just remembered one more important detail: the two adjacent matching digits are not part of a larger group of matching digits.
+
+Given this additional criterion, but still ignoring the range rule, the following are now true:
+
+    112233 meets these criteria because the digits never decrease and all repeated digits are exactly two digits long.
+    123444 no longer meets the criteria (the repeated 44 is part of a larger group of 444).
+    111122 meets the criteria (even though 1 is repeated more than twice, it still contains a double 22).
+
+How many different passwords within the range given in your puzzle input meet all of the criteria?
+*/
+
+use std::collections::VecDeque;
+use std::io::stdin;
+
+use crate::puzzle::options::Options;
+use crate::puzzle::traits::{Create, Solve};
+
+pub struct Puzzle {
+    options: Options,
+    lower_bound: i32,
+    upper_bound: i32,
+}
+
+impl Create for Puzzle {
+    fn new(opt: Options) -> Box<dyn Solve> {
+        Box::new(Self {
+            options: opt,
+            lower_bound: if opt.prompt {
+                Self::prompt_for_bound()
+            } else {
+                Self::default_lower_bound()
+            },
+            upper_bound: if opt.prompt {
+                Self::prompt_for_bound()
+            } else {
+                Self::default_upper_bound()
+            },
+        })
+    }
+}
+
+impl Solve for Puzzle {
+    fn solve(&self) -> i32 {
+        match self.options.puzzle {
+            1 => self.solve_p1(),
+            2 => self.solve_p2(),
+            x => panic!("Unknown puzzle {}", x),
+        }
+    }
+}
+
+impl Puzzle {
+    pub fn solve_p1(&self) -> i32 {
+        let mut num_matches = 0;
+        for value in (&self).lower_bound..(&self).upper_bound + 1 {
+            if Self::is_matching_pattern_1(value) {
+                num_matches += 1;
+            }
+        }
+        num_matches
+    }
+
+    pub fn solve_p2(&self) -> i32 {
+        let mut num_matches = 0;
+        for value in (&self).lower_bound..(&self).upper_bound + 1 {
+            if Self::is_matching_pattern_2(value) {
+                num_matches += 1;
+            }
+        }
+        num_matches
+    }
+
+    fn is_matching_pattern_1(i: i32) -> bool {
+        let mut previous = 0;
+        let mut has_pair = false;
+        let mut digits: VecDeque<i32> = VecDeque::new();
+
+        {
+            let mut num = i;
+
+            while num > 0 {
+                let mod_num = num % 10;
+                digits.push_front(mod_num);
+                num /= 10;
+            }
+        }
+
+        for digit in digits {
+            if digit < previous {
+                return false;
+            } else if digit == previous {
+                has_pair = true;
+            } else {
+                previous = digit;
+            }
+        }
+
+        has_pair
+    }
+
+    fn is_matching_pattern_2(i: i32) -> bool {
+        let mut previous = 0;
+        let mut has_pair = false;
+        let mut subsequent_dupes = 0;
+        let mut digits: VecDeque<i32> = VecDeque::new();
+
+        {
+            let mut num = i;
+
+            while num > 0 {
+                let mod_num = num % 10;
+                digits.push_front(mod_num);
+                num /= 10;
+            }
+        }
+
+        for digit in digits {
+            if digit < previous {
+                return false;
+            } else if digit == previous {
+                subsequent_dupes += 1;
+            } else {
+                if subsequent_dupes == 1 {
+                    has_pair = true;
+                }
+                previous = digit;
+                subsequent_dupes = 0;
+            }
+        }
+
+        // one last check since abcdXX won't match otherwise
+        if subsequent_dupes == 1 {
+            has_pair = true;
+        }
+
+        has_pair
+    }
+
+    fn prompt_for_bound() -> i32 {
+        println!("enter boundry: ");
+        let mut input = String::new();
+
+        match stdin().read_line(&mut input) {
+            Ok(_) => {}
+            Err(e) => panic!("Failed to read input: {}", e),
+        }
+
+        match input.trim().parse::<i32>() {
+            Ok(i) => i,
+            Err(e) => panic!("failed to parse {}: {}", input, e),
+        }
+    }
+
+    fn default_lower_bound() -> i32 {
+        402328
+    }
+
+    fn default_upper_bound() -> i32 {
+        864247
+    }
+}
+
+#[cfg(test)]
+mod puzzle_1 {
+    use super::Puzzle;
+
+    #[test]
+    fn match_sample_1() {
+        assert_eq!(Puzzle::is_matching_pattern_1(111111), true)
+    }
+
+    #[test]
+    fn match_sample_2() {
+        assert_eq!(Puzzle::is_matching_pattern_1(223450), false)
+    }
+
+    #[test]
+    fn match_sample_3() {
+        assert_eq!(Puzzle::is_matching_pattern_1(123789), false)
+    }
+}
+
+#[cfg(test)]
+mod puzzle_2 {
+    use super::Puzzle;
+
+    #[test]
+    fn match_sample_1() {
+        assert_eq!(Puzzle::is_matching_pattern_2(112233), true)
+    }
+
+    #[test]
+    fn match_sample_2() {
+        assert_eq!(Puzzle::is_matching_pattern_2(123444), false)
+    }
+
+    #[test]
+    fn match_sample_3() {
+        assert_eq!(Puzzle::is_matching_pattern_2(111122), true)
+    }
+}

+ 2 - 0
src/main.rs

@@ -4,6 +4,7 @@ extern crate clap;
 mod day_1;
 mod day_2;
 mod day_3;
+mod day_4;
 
 mod puzzle;
 use crate::puzzle::options::Options;
@@ -26,6 +27,7 @@ fn main() {
         1 => day_1::Puzzle::new(options),
         2 => day_2::Puzzle::new(options),
         3 => day_3::Puzzle::new(options),
+        4 => day_4::Puzzle::new(options),
         e => panic!("unknown day {}", e),
     };