From 66ddb140f254513b4e38d9b4c9c80db77364f51b Mon Sep 17 00:00:00 2001 From: Justin Wernick Date: Fri, 9 Dec 2022 08:03:56 +0200 Subject: Day 9 --- 2022/src/bin/day_9.rs | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 2022/src/bin/day_9.rs (limited to '2022/src/bin') 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> { + 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); + +#[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, + tail_visited: BTreeSet, +} + +#[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()); + } + } +} -- cgit v1.2.3