Day 17 part 1
authorGreg Burri <greg.burri@gmail.com>
Thu, 22 Dec 2022 19:52:44 +0000 (20:52 +0100)
committerGreg Burri <greg.burri@gmail.com>
Thu, 22 Dec 2022 19:52:44 +0000 (20:52 +0100)
src/day17.rs [new file with mode: 0644]
src/days.rs
src/main.rs

diff --git a/src/day17.rs b/src/day17.rs
new file mode 100644 (file)
index 0000000..07a145d
--- /dev/null
@@ -0,0 +1,95 @@
+use std::collections::HashSet;
+
+#[derive(Debug)]
+pub enum Movement {
+    Left,
+    Right,
+}
+
+pub fn parse(input: &str) -> Vec<Movement> {
+    input
+        .chars()
+        .map(|c| match c {
+            '>' => Movement::Right,
+            '<' => Movement::Left,
+            other => panic!("Uknown movement: {}", other),
+        })
+        .collect()
+}
+
+fn rock_collide(pos: (i32, i32), rock: &[(i32, i32)], pile: &HashSet<(i32, i32)>) -> bool {
+    for (x, y) in rock {
+        let (x, y) = (x + pos.0, y + pos.1);
+        if x <= 0 || x >= 8 || y <= 0 || pile.contains(&(x, y)) {
+            return true;
+        }
+    }
+    false
+}
+
+pub fn height(number_of_rocks: i32, movements: &[Movement]) -> i32 {
+    let types_of_rock = [
+        vec![(0, 0), (1, 0), (2, 0), (3, 0)],         // '-'.
+        vec![(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)], // '+'.
+        vec![(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)], // '⅃'.
+        vec![(0, 0), (0, 1), (0, 2), (0, 3)],         // '|'.
+        vec![(0, 0), (0, 1), (1, 0), (1, 1)],         // '□'.
+    ];
+
+    let mut pile = HashSet::<(i32, i32)>::new();
+    let mut current_movement = 0;
+    let mut highest_point = 0;
+    for i in 0..number_of_rocks {
+        let rock = &types_of_rock[i as usize % types_of_rock.len()];
+
+        let mut pos = (3, highest_point + 4);
+        loop {
+            let m = &movements[current_movement];
+            current_movement = (current_movement + 1) % movements.len();
+
+            //println!("Rock: {:?}, pos: {:?}, m: {:?}", rock, pos, m);
+
+            let new_pos = match m {
+                Movement::Left => (pos.0 - 1, pos.1),
+                Movement::Right => (pos.0 + 1, pos.1),
+            };
+
+            if !rock_collide(new_pos, rock, &pile) {
+                pos = new_pos;
+            }
+
+            let new_pos = (pos.0, pos.1 - 1);
+            if rock_collide(new_pos, rock, &pile) {
+                let mut h = 0;
+                for p in rock {
+                    h = h.max(p.1);
+                    pile.insert((p.0 + pos.0, p.1 + pos.1));
+                }
+
+                // println!("Rock piled up: {:?}, pos: {:?}", rock, pos);
+                highest_point = highest_point.max(pos.1 + h);
+                break;
+            }
+
+            pos = new_pos
+        }
+    }
+
+    highest_point
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    static JET_PATTERN: &str = ">>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>";
+
+    #[test]
+    fn part1() {
+        let movements = parse(JET_PATTERN);
+        assert_eq!(height(2022, &movements), 3068);
+    }
+
+    #[test]
+    fn part2() {}
+}
index bfe185d..4f0a9f9 100644 (file)
@@ -169,3 +169,8 @@ pub fn day16() -> String {
         day16::most_pressure(start, 26, 2, &valves)
     )
 }
+
+pub fn day17() -> String {
+    let movements = day17::parse(&fs::read_to_string("data/day17.input").unwrap());
+    format!("part1: {}, part2: {}", day17::height(2022, &movements), 0)
+}
index 1086131..c030be0 100644 (file)
@@ -19,6 +19,7 @@ mod day13;
 mod day14;
 mod day15;
 mod day16;
+mod day17;
 mod days;
 
 #[derive(Parser, Debug)]
@@ -51,6 +52,7 @@ fn main() {
         days::day14,
         days::day15,
         days::day16,
+        days::day17,
     ];
 
     let args = Args::parse();