Jake Fenton 1 年之前
父节点
当前提交
5d0fa0ff5b
共有 2 个文件被更改,包括 130 次插入0 次删除
  1. 122 0
      src/bin/09.rs
  2. 8 0
      src/examples/09.txt

+ 122 - 0
src/bin/09.rs

@@ -0,0 +1,122 @@
+use std::{collections::HashSet};
+
+#[derive(Clone, Hash, Eq, PartialEq)]
+struct Point {
+    pub x: i32,
+    pub y: i32
+}
+
+struct RopeGrid {
+    head: Point,
+    tail: Point,
+    tail_positions: HashSet<(i32, i32)>
+}
+
+impl RopeGrid {
+    pub fn new() -> RopeGrid {
+        return RopeGrid { head: Point{x: 0, y: 0}, tail: Point{ x: 0, y: 0}, tail_positions: HashSet::from_iter([(0, 0)]) }
+    }
+
+    fn update_tail(&mut self) {
+        if self.head.x == self.tail.x && i32::abs(self.head.y - self.tail.y) == 2 {
+            // head 10, tail 8, head is above tail, dir is +
+            if self.head.y > self.tail.y {
+                self.tail.y += 1;
+            } else {
+                self.tail.y -= 1;
+            }
+        } else if self.head.y == self.tail.y && i32::abs(self.head.x - self.tail.x) == 2 {
+            if self.head.x > self.tail.x {
+                self.tail.x += 1;
+            } else {
+                self.tail.x -= 1;
+            }
+        } else if i32::abs(self.head.x - self.tail.x) + i32::abs(self.head.y - self.tail.y) > 2 {
+            let x_dir = if self.head.x > self.tail.x { 1 } else { -1 };
+            let y_dir = if self.head.y > self.tail.y { 1 } else { -1 };
+            self.tail.x += x_dir;
+            self.tail.y += y_dir;
+        }
+
+        // println!("Tail now at ({}, {})", self.tail.x, self.tail.y);
+        self.tail_positions.insert((self.tail.x, self.tail.y));
+    }
+
+    fn do_steps(&mut self, x_sign: i32, y_sign: i32, dist: i32) {
+        // println!("Moving x {} y {} steps {}", x_sign, y_sign, dist);
+        for _ in 0..dist {
+            self.head.x += x_sign;
+            self.head.y += y_sign;
+            self.update_tail();
+        }
+    }
+
+    pub fn move_head(&mut self, moov: Move) {
+        match moov {
+            Move::Up(distance) => { self.do_steps(0, 1, distance)},
+            Move::Down(distance) => { self.do_steps(0, -1, distance)},
+            Move::Left(distance) => { self.do_steps(-1, 0, distance)},
+            Move::Right(distance) => { self.do_steps(1, 0, distance)},
+        }
+    }
+
+    pub fn num_tail_positions(&self) -> usize {
+        self.tail_positions.len()
+    }
+}
+
+enum Move {
+    Right(i32),
+    Left(i32),
+    Up(i32),
+    Down(i32)
+}
+
+impl Move {
+    pub fn from_stirng(s: &str) -> Move {
+        let (direction, steps) = s.split_once(" ").unwrap();
+        match direction {
+            "U" => { Move::Up(steps.parse().unwrap())},
+            "D" => { Move::Down(steps.parse().unwrap())},
+            "L" => { Move::Left(steps.parse().unwrap())},
+            "R" => { Move::Right(steps.parse().unwrap())},
+            _ => panic!("Unknown direction {}", direction)
+        }
+    }
+}
+
+pub fn part_one(input: &str) -> Option<usize> {
+    let moves: Vec<Move> = input.lines().map(|line| Move::from_stirng(line)).collect();
+    let mut ropegrid = RopeGrid::new();
+    for moov in moves {
+        ropegrid.move_head(moov)
+    }
+    Some(ropegrid.num_tail_positions())
+}
+
+pub fn part_two(input: &str) -> Option<usize> {
+    None
+}
+
+fn main() {
+    let input = &advent_of_code::read_file("inputs", 9);
+    advent_of_code::solve!(1, part_one, input);
+    advent_of_code::solve!(2, part_two, input);
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_part_one() {
+        let input = advent_of_code::read_file("examples", 9);
+        assert_eq!(part_one(&input), Some(13));
+    }
+
+    #[test]
+    fn test_part_two() {
+        let input = advent_of_code::read_file("examples", 9);
+        assert_eq!(part_two(&input), None);
+    }
+}

+ 8 - 0
src/examples/09.txt

@@ -0,0 +1,8 @@
+R 4
+U 4
+L 3
+D 1
+R 4
+D 1
+L 5
+R 2