]> aoc.elinar.fr Git - aoc_2025/commitdiff
day02: part1
authoralex <>
Tue, 2 Dec 2025 12:49:06 +0000 (13:49 +0100)
committeralex <>
Tue, 2 Dec 2025 12:49:06 +0000 (13:49 +0100)
input/day02.txt [new file with mode: 0644]
src/day02.rs [new file with mode: 0644]
src/main.rs

diff --git a/input/day02.txt b/input/day02.txt
new file mode 100644 (file)
index 0000000..0acf68b
--- /dev/null
@@ -0,0 +1 @@
+245284-286195,797927-983972,4949410945-4949555758,115-282,8266093206-8266228431,1-21,483873-655838,419252-466133,6190-13590,3876510-4037577,9946738680-9946889090,99954692-100029290,2398820-2469257,142130432-142157371,9797879567-9798085531,209853-240025,85618-110471,35694994-35766376,4395291-4476150,33658388-33694159,680915-772910,4973452995-4973630970,52-104,984439-1009605,19489345-19604283,22-42,154149-204168,7651663-7807184,287903-402052,2244-5558,587557762-587611332,307-1038,16266-85176,422394377-422468141
diff --git a/src/day02.rs b/src/day02.rs
new file mode 100644 (file)
index 0000000..cc55d4f
--- /dev/null
@@ -0,0 +1,107 @@
+use std::error::Error;
+
+pub fn run(input: &str) -> Result<(), Box<dyn Error>> {
+    println!("part 1: {}", part1(input)?);
+    Ok(())
+}
+
+fn is_invalid(n: &str) -> bool {
+    if n.len() % 2 == 1 {
+        return false;
+    }
+    (0..(n.len() / 2)).all(|i| {
+        n.as_bytes()[i] == n.as_bytes()[i + n.len()/2]
+    })
+}
+
+fn next_value(s: &str) -> String {
+    if s.len() % 2 == 1 {
+        // increase by 1 digit and search the next value
+        let n = 10u64.pow(s.len().try_into().unwrap()).to_string();
+        return next_value(&n);
+    }
+    let mut out = String::new();
+    if !is_invalid(s) {
+        // duplicate the first part of the string
+        //   47 → 55
+        //   2279 → 2323
+        //   565653 → 566 653
+        let (p1, p2) = s.split_at(s.len()/2);
+        let n = p1.parse::<u64>().unwrap();
+        if n < p2.parse::<u64>().unwrap() {
+            out.push_str(&(n + 1).to_string());
+            out.push_str(&(n + 1).to_string());
+        } else {
+            out.push_str(p1);
+            out.push_str(p1);
+        }
+        return out;
+    }
+    // create the next invalid string
+    let (s1, _) = s.split_at(s.len() / 2);
+    let n = s1.parse::<u64>().unwrap() + 1;
+    out.push_str(&n.to_string());
+    out.push_str(&n.to_string());
+    out
+}
+
+fn part1(input: &str) -> Result<u64, Box<dyn Error>> {
+    let mut res: u64 = 0;
+    input.trim_end_matches("\n").split(',')
+        .map(|ranges| ranges.split_once('-').unwrap())
+        // keep only the ranges with an even number of digits
+        // => filter out when a and b have the same odd number of digits
+        .filter(|(a, b)| !(a.len() == b.len() && a.len() % 2 == 1))
+        .for_each(|(a, b)| {
+            //println!("{} → {}", a, b);
+            let bn = b.parse::<u64>().unwrap();
+            let mut n = a.to_string();
+            let mut nn = n.parse::<u64>().unwrap();
+            while nn <= bn {
+                if is_invalid(&n) {
+                    //println!("   invalid: {}", n);
+                    res += nn;
+                }
+                n = next_value(&n);
+                nn = n.parse::<u64>().unwrap();
+            }
+        });
+    Ok(res)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    static INPUT: &str = "\
+11-22,95-115,998-1012,1188511880-1188511890,222220-222224,\
+1698522-1698528,446443-446449,38593856-38593862,565653-565659,\
+824824821-824824827,2121212118-2121212124";
+
+    #[test]
+    fn test_is_invalid() {
+        assert_eq!(is_invalid("1"), false);
+        assert_eq!(is_invalid("10"), false);
+        assert_eq!(is_invalid("11"), true);
+        assert_eq!(is_invalid("55"), true);
+        assert_eq!(is_invalid("101"), false);
+        assert_eq!(is_invalid("446446"), true);
+        assert_eq!(is_invalid("2121212121"), false);
+    }
+    #[test]
+    fn test_next_value() {
+        assert_eq!(next_value("1"), "11");
+        assert_eq!(next_value("10"), "11");
+        assert_eq!(next_value("11"), "22");
+        assert_eq!(next_value("47"), "55");
+        assert_eq!(next_value("55"), "66");
+        assert_eq!(next_value("101"), "1010");
+        assert_eq!(next_value("2279"), "2323");
+        assert_eq!(next_value("446446"), "447447");
+        assert_eq!(next_value("565653"), "566566");
+        assert_eq!(next_value("2121212121"), "2121221212");
+    }
+    #[test]
+    fn test_part1() {
+        assert_eq!(1227775554, part1(INPUT).unwrap());
+    }
+}
index d64487eb0941552ae3d0560760b55d764428c975..e786b0b6980dd8367977d40165a8e6ec67df8294 100644 (file)
@@ -5,6 +5,7 @@ use std::fs::File;
 use std::io::Read;
 
 pub mod day01;
+pub mod day02;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -21,6 +22,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
 
     match day {
         "day01" => day01::run(&input)?,
+        "day02" => day02::run(&input)?,
         _ => return Err(format!("unknown or unimplemented day \"{day}\"").into()),
     }
     Ok(())