summaryrefslogtreecommitdiff
path: root/2022/src/bin/day_9.rs
diff options
context:
space:
mode:
Diffstat (limited to '2022/src/bin/day_9.rs')
-rw-r--r--2022/src/bin/day_9.rs134
1 files changed, 134 insertions, 0 deletions
diff --git a/2022/src/bin/day_9.rs b/2022/src/bin/day_9.rs
new file mode 100644
index 0000000..ccbb66a
--- /dev/null
+++ b/2022/src/bin/day_9.rs
@@ -0,0 +1,134 @@
+use nom::{
+ branch::alt,
+ bytes::complete::tag,
+ character::complete::{i32, line_ending},
+ combinator::{map, value},
+ multi::separated_list1,
+ sequence::tuple,
+ IResult,
+};
+use std::{collections::BTreeSet, fs};
+
+fn main() -> Result<(), Box<dyn std::error::Error>> {
+ let input = fs::read_to_string("inputs/day_9.txt")?;
+ let movements = Movements::parser(&input).unwrap().1;
+
+ let mut game_board_part_1 = GameBoard::new(2);
+ for instruction in &movements.0 {
+ game_board_part_1.step(instruction);
+ }
+ dbg!(game_board_part_1.tail_visited.len());
+
+ let mut game_board_part_2 = GameBoard::new(10);
+ for instruction in &movements.0 {
+ game_board_part_2.step(instruction);
+ }
+ dbg!(game_board_part_2.tail_visited.len());
+
+ Ok(())
+}
+
+#[derive(Debug)]
+struct Movements(Vec<Instruction>);
+
+#[derive(Debug)]
+struct Instruction {
+ direction: Direction,
+ distance: i32,
+}
+
+#[derive(Debug, Clone, Copy)]
+enum Direction {
+ Down,
+ Up,
+ Left,
+ Right,
+}
+
+impl Movements {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ map(separated_list1(line_ending, Instruction::parser), Movements)(input)
+ }
+}
+
+impl Instruction {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ map(
+ tuple((Direction::parser, tag(" "), i32)),
+ |(direction, _, distance)| Instruction {
+ direction,
+ distance,
+ },
+ )(input)
+ }
+}
+
+impl Direction {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ alt((
+ value(Direction::Down, tag("D")),
+ value(Direction::Up, tag("U")),
+ value(Direction::Left, tag("L")),
+ value(Direction::Right, tag("R")),
+ ))(input)
+ }
+}
+
+#[derive(Debug)]
+struct GameBoard {
+ rope: Vec<Position>,
+ tail_visited: BTreeSet<Position>,
+}
+
+#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
+struct Position {
+ x: i32,
+ y: i32,
+}
+
+impl GameBoard {
+ fn new(length: usize) -> GameBoard {
+ let mut tail_visited = BTreeSet::new();
+ tail_visited.insert(Position::default());
+ GameBoard {
+ rope: vec![Position::default(); length],
+ tail_visited,
+ }
+ }
+
+ fn step(&mut self, instruction: &Instruction) {
+ for _ in 0..instruction.distance {
+ match instruction.direction {
+ Direction::Down => self.rope[0].y -= 1,
+ Direction::Up => self.rope[0].y += 1,
+ Direction::Left => self.rope[0].x -= 1,
+ Direction::Right => self.rope[0].x += 1,
+ };
+
+ for tail_i in 1..self.rope.len() {
+ let head_i = tail_i - 1;
+ let head = self.rope[head_i].clone();
+ let tail = &mut self.rope[tail_i];
+
+ let tail_must_move = (head.x - tail.x).abs() > 1 || (head.y - tail.y).abs() > 1;
+
+ if tail_must_move {
+ if head.x > tail.x {
+ tail.x += 1;
+ } else if head.x < tail.x {
+ tail.x -= 1;
+ }
+
+ if head.y > tail.y {
+ tail.y += 1;
+ } else if head.y < tail.y {
+ tail.y -= 1;
+ }
+ }
+ }
+
+ self.tail_visited
+ .insert(self.rope[self.rope.len() - 1].clone());
+ }
+ }
+}