]> aoc.elinar.fr Git - aoc_2023/commitdiff
Day03 - part 1
authoralex <null>
Sun, 3 Dec 2023 13:05:21 +0000 (14:05 +0100)
committeralex <null>
Sun, 3 Dec 2023 13:05:21 +0000 (14:05 +0100)
src/day03.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day03.rs b/src/day03.rs
new file mode 100644 (file)
index 0000000..12a9b0f
--- /dev/null
@@ -0,0 +1,118 @@
+use std::io::Read;
+use std::error::Error;
+use std::fs::File;
+
+use regex::Regex;
+
+pub fn run(input_file: &str) -> Result<(), Box<dyn Error>> {
+    let mut f = File::open(input_file)?;
+    let mut input = String::new();
+    f.read_to_string(&mut input)?;
+
+    let res = run_part1(&input)?;
+    println!("{res}");
+
+    let res = run_part2(&input)?;
+    println!("{res}");
+
+    Ok(())
+}
+
+fn run_part1(input: &str) -> Result<i32, Box<dyn Error>> {
+    println!("Running day03 - part 1");
+
+    // faire une première passe à la recherche de l'index de chaque symbole
+    // pour chaque ligne stocker true/false à chaque index
+    // au final on a un vecteur de ligne qui contient un vecteur de bool
+    // indiquant la présence ou non d'un symbole à l'index
+    let mut symbols: Vec<Vec<bool>> = Vec::new();
+    input.lines()
+        .for_each(|l| {
+            let mut symbol: Vec<bool> = Vec::new();
+            l.chars()
+                .for_each(|c| symbol.push(c != '.' && !c.is_ascii_digit()));
+            symbols.push(symbol);
+        });
+    //println!("{:?}", symbols);
+
+    // seconde passe où les nombres sont extraits ainsi que les index de début
+    // et de fin
+    // puis recherche d'un symbole adjacent
+    // si un symbole est trouvé, on ajoute le nombre au résultat
+    let re = Regex::new(r"\d+").unwrap();
+
+    fn is_next_to_symbol(line_number: usize, idx_start: usize, idx_end: usize, symbols: &Vec<Vec<bool>>) -> bool {
+        let n_lines = symbols.len() - 1; // 0-based value
+        let n_cols = symbols[0].len() - 1; // 0-based value
+        let start = if idx_start > 0 { idx_start - 1 } else { 0 };
+        let end = if idx_end < n_cols { idx_end + 1 } else { n_cols };
+
+        for i in start..end {
+            if line_number > 0 {
+                if symbols[line_number - 1][i] {
+                    return true;
+                }
+            }
+            if line_number < n_lines {
+                if symbols[line_number + 1][i] {
+                    return true;
+                }
+            }
+            if symbols[line_number][i] {
+                return true;
+            }
+        }
+
+        false
+    }
+
+    let mut res = 0;
+    input.lines().enumerate()
+        .for_each(|(idx, l)| {
+            re.captures_iter(l)
+                .for_each(|c| {
+                    //println!("{idx}: {:?}", c);
+                    let m = c.get(0).unwrap();
+                    if is_next_to_symbol(idx, m.start(), m.end(), &symbols) {
+                        res += m.as_str().parse::<i32>().unwrap();
+                    }
+                })
+        });
+
+    Ok(res)
+}
+
+fn run_part2(input: &str) -> Result<i32, Box<dyn Error>> {
+    println!("Running day03 - part 2");
+    let res = 0;
+    Ok(res)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn day03_part1() {
+        let input = "\
+467..114..
+...*......
+..35..633.
+......#...
+617*......
+.....+.58.
+..592.....
+......755.
+...$.*....
+.664.598..";
+        let res = run_part1(&input);
+        assert_eq!(4361, res.unwrap());
+    }
+
+    #[test]
+    fn day03_part2() {
+        let input = "";
+        let res = run_part2(&input);
+        assert_eq!(0, res.unwrap());
+    }
+}
index 96d6d6efa202ac6d44b6d7a8f31808ebe3157990..2c9b7c0013c6e2fa28f8b256ad2705f7e335a744 100644 (file)
@@ -5,6 +5,7 @@ use std::error::Error;
 pub mod day00;
 pub mod day01;
 pub mod day02;
+pub mod day03;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -25,6 +26,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
         "day00" => day00::run(input_file)?,
         "day01" => day01::run(input_file)?,
         "day02" => day02::run(input_file)?,
+        "day03" => day03::run(input_file)?,
         _ => return Err(format!("unknown day \"{day}\"").into()),
     }
     Ok(())