]> aoc.elinar.fr Git - aoc_2024/commitdiff
Day12 - part 1
authoralex <>
Thu, 12 Dec 2024 11:52:30 +0000 (12:52 +0100)
committeralex <>
Thu, 12 Dec 2024 11:52:30 +0000 (12:52 +0100)
src/day12.rs [new file with mode: 0644]
src/main.rs

diff --git a/src/day12.rs b/src/day12.rs
new file mode 100644 (file)
index 0000000..e819537
--- /dev/null
@@ -0,0 +1,137 @@
+use std::error::Error;
+use std::path::Path;
+
+struct Puzzle {
+    map: Vec<Vec<u8>>,
+    visited: Vec<Vec<bool>>,
+}
+
+impl Puzzle {
+    pub fn new(input: &str) -> Self {
+        let mut map: Vec<Vec<u8>> = Vec::new();
+        input.lines()
+            .for_each(|l| {
+                let mut row: Vec<u8> = l.as_bytes().iter().map(|v| *v).collect();
+                row.insert(0, b' ');
+                row.push(b' ');
+                map.push(row);
+            });
+        map.insert(0, vec![b' '; map[0].len()]);
+        map.push(vec![b' '; map[0].len()]);
+
+        let visited: Vec<Vec<bool>> = vec![vec![false; map[0].len()]; map.len()];
+
+        Self { map, visited }
+    }
+
+    fn count_perimeter(&self, pos: (isize, isize), plant: u8) -> u32 {
+        let (row, col) = pos;
+        [(-1, 0), (0, 1), (1, 0), (0, -1)].iter()
+            .filter(|(dr, dc)| self.map[(row + dr) as usize][(col + dc) as usize] != plant)
+            .count() as u32
+    }
+
+    fn area_perimeter(&mut self, pos: (usize, usize), plant: u8) -> (u32, u32) {
+        let (mut area, mut perimeter) = (0, 0);
+
+        let mut region: Vec<(isize, isize)> = Vec::new();
+        region.push((pos.0 as isize, pos.1 as isize));
+
+        while let Some((row, col)) = region.pop() {
+            area += 1;
+            perimeter += self.count_perimeter((row, col), plant);
+            [(-1, 0), (0, 1), (1, 0), (0, -1)].iter()
+                .for_each(|(dr, dc)| {
+                    let (r, c) = ((row + dr) as usize, (col + dc) as usize);
+                    if !self.visited[r][c] && self.map[r][c] == plant {
+                        self.visited[r][c] = true;
+                        region.push((r as isize, c as isize));
+                    }
+                });
+        }
+
+        (area, perimeter)
+    }
+}
+
+fn run_part1(input: &str) -> Result<u32, Box<dyn Error>> {
+    println!("Running {} - part 1", get_day());
+
+    let mut puzzle = Puzzle::new(input);
+
+    let mut res = 0;
+    for r in 1..(puzzle.map.len()-1) {
+        for c in 1..(puzzle.map[0].len()-1) {
+            if !puzzle.visited[r][c] {
+                puzzle.visited[r][c] = true;
+                let plant = puzzle.map[r][c];
+                let pos = (r, c);
+                let (area, perimeter) = puzzle.area_perimeter(pos, plant);
+                res += area * perimeter;
+            }
+        }
+    }
+
+    Ok(res)
+}
+
+fn run_part2(input: &str) -> Result<u32, Box<dyn Error>> {
+    println!("Running {} - part 2", get_day());
+
+    Ok(0)
+}
+
+pub fn run(input: &str) -> Result<(), Box<dyn Error>> {
+    let res = run_part1(input)?;
+    println!("{res}");
+
+    let res = run_part2(input)?;
+    println!("{res}");
+
+    Ok(())
+}
+
+fn get_day() -> String {
+    let filename = file!();
+    Path::new(filename).file_stem().unwrap().to_str().unwrap().to_string()
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    static TEXT_INPUT_0: &str = "\
+AAAA
+BBCD
+BBCC
+EEEC";
+    static TEXT_INPUT_1: &str = "\
+OOOOO
+OXOXO
+OOOOO
+OXOXO
+OOOOO";
+    static TEXT_INPUT_2: &str = "\
+RRRRIICCFF
+RRRRIICCCF
+VVRRRCCFFF
+VVRCCCJFFF
+VVVVCJJCFE
+VVIVCCJJEE
+VVIIICJJEE
+MIIIIIJJEE
+MIIISIJEEE
+MMMISSJEEE";
+
+    #[test]
+    fn test_part1() {
+        assert_eq!(140, run_part1(TEXT_INPUT_0).unwrap());
+        assert_eq!(772, run_part1(TEXT_INPUT_1).unwrap());
+        assert_eq!(1930, run_part1(TEXT_INPUT_2).unwrap());
+    }
+
+    #[test]
+    fn test_part2() {
+        assert_eq!(0, run_part2(TEXT_INPUT_2).unwrap());
+    }
+}
index dd9eed2c18ce8b98f46591f4ee4b969503f65e71..0e0f455cd6fd0cee5410852ee1fc6eaec349db5f 100644 (file)
@@ -15,6 +15,7 @@ pub mod day08;
 pub mod day09;
 pub mod day10;
 pub mod day11;
+pub mod day12;
 
 fn main() {
     let args: Vec<String> = env::args().collect();
@@ -48,6 +49,7 @@ fn run(day: &str, input_file: &str) -> Result<(), Box<dyn Error>> {
         "day09" => day09::run(&input)?,
         "day10" => day10::run(&input)?,
         "day11" => day11::run(&input)?,
+        "day12" => day12::run(&input)?,
         _ => return Err(format!("unknown or unimplemented day \"{day}\"").into()),
     }
     Ok(())