+use std::cmp::Ordering;\r
\r
+pub fn parse_range(raw: &str) -> (i32, i32) {\r
+ let nums: Vec<i32> = raw.trim().split('-').map(|n| n.parse::<i32>().unwrap()).collect();\r
+ (nums[0], nums[1])\r
+}\r
+\r
+type Digits = Vec<u8>;\r
+\r
+fn get_digits(value: i32) -> Digits {\r
+ let mut digits = Vec::<u8>::new();\r
+ let mut value = value;\r
+ while value > 0 {\r
+ digits.push((value % 10) as u8);\r
+ value /= 10;\r
+ }\r
+ digits\r
+}\r
\r
-fn find_password(min: i32) {\r
- ;\r
+pub fn nb_passwords_part1(min: i32, max: i32) -> i32 {\r
+ nb_passwords(\r
+ min,\r
+ max,\r
+ &|digits: &Digits| {\r
+ for i in 1 .. digits.len() {\r
+ if digits[i - 1] == digits[i] { return true; }\r
+ }\r
+ false\r
+ }\r
+ )\r
}\r
\r
+pub fn nb_passwords_part2(min: i32, max: i32) -> i32 {\r
+ nb_passwords(\r
+ min,\r
+ max,\r
+ &|digits: &Digits| {\r
+ let mut last = digits[0];\r
+ let mut n = 1;\r
+ for i in 1 .. digits.len() {\r
+ if digits[i] == last {\r
+ n += 1;\r
+ } else {\r
+ if n == 2 { return true; }\r
+ n = 1;\r
+ }\r
+ last = digits[i];\r
+ }\r
+ n == 2\r
+ }\r
+ )\r
+}\r
+\r
+fn nb_passwords(min: i32, max: i32, valid_password: &dyn Fn(&Digits) -> bool) -> i32 {\r
+ let mut digits = get_digits(min);\r
+ let digits_max = get_digits(max);\r
+ let l = digits.len();\r
+\r
+ fn set_range(from: usize, to: usize, value: u8, digits: &mut Digits) {\r
+ for i in from .. to { digits[i] = value; }\r
+ };\r
+\r
+ for i in (1 .. l).rev() {\r
+ if digits[i - 1] < digits[i] {\r
+ set_range(0, i, digits[i], &mut digits);\r
+ break;\r
+ }\r
+ }\r
+\r
+ let mut n = 0;\r
\r
+ loop {\r
+ if valid_password(&digits) { n += 1; }\r
\r
-#[cfg(test)]\r
-mod tests {\r
- use super::*;\r
+ for i in 0 .. l {\r
+ if i == l - 1 || digits[i + 1] <= digits[i] && digits[i] != 9 {\r
+ set_range(0, i + 1, digits[i] + 1, &mut digits);\r
+ break;\r
+ }\r
+ }\r
\r
- #[test]\r
- fn part1() {\r
+ for i in (0 .. l).rev() {\r
+ match digits[i].cmp(&digits_max[i]) {\r
+ Ordering::Greater => return n,\r
+ Ordering::Less => break,\r
+ Ordering::Equal => ()\r
+ }\r
+ }\r
}\r
}
\ No newline at end of file
mod day01;
mod day02;
mod day03;
+mod day04;
mod day06;
mod day07;
mod day08;
mod day15;
mod day16;
mod day17;
+mod day18;
fn day01() -> String {
let masses = common::read_list_of_numbers("data/day01.input", "\n");
}
fn day04() -> String {
- format!("")
+ let raw = fs::read_to_string("data/day04.input").unwrap();
+ let (min, max) = day04::parse_range(&raw);
+ format!("part1: {:?}, part2: {}", day04::nb_passwords_part1(min, max), day04::nb_passwords_part2(min, max))
}
fn day05() -> String {
}
+fn day18() -> String {
+ format!("part1: {}, part2: {}", "", "")
+}
+
fn format_micros(t: u128) -> String {
if t < 10_000 {
format!("{} μs", t)
day15,
day16,
day17,
+ day18,
);
let args: Vec<String> = env::args().skip(1).collect();