From 8481a5007c415e5549c173c52faec3702ab6fdc4 Mon Sep 17 00:00:00 2001 From: Reiner Herrmann Date: Thu, 19 Dec 2024 11:38:44 +0100 Subject: day15 solution 1 --- src/bin/day15.rs | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/bin/day15.rs (limited to 'src') diff --git a/src/bin/day15.rs b/src/bin/day15.rs new file mode 100644 index 0000000..c55a3f1 --- /dev/null +++ b/src/bin/day15.rs @@ -0,0 +1,198 @@ +use std::collections::HashSet; + +static DAY: u8 = 15; + +fn main() { + let input = advent::read_lines(DAY); + println!("{DAY}a: {}", box_coordinates(&input)); + println!("{DAY}b: {}", 0); +} + +#[derive(Eq, PartialEq, Hash, Clone, Copy)] +struct Position { + x: isize, + y: isize, +} + +impl Position { + fn next(&self, direction: Direction) -> Position { + let (x, y) = match direction { + Direction::Up => (self.x, self.y - 1), + Direction::Down => (self.x, self.y + 1), + Direction::Left => (self.x - 1, self.y), + Direction::Right => (self.x + 1, self.y), + }; + Position { x, y } + } +} + +#[derive(Clone, Copy)] +enum Direction { + Up, + Down, + Left, + Right, +} + +impl Direction { + fn new(input: char) -> Direction { + match input { + '^' => Direction::Up, + 'v' => Direction::Down, + '<' => Direction::Left, + '>' => Direction::Right, + _ => unimplemented!(), + } + } +} + +struct Map { + floor: HashSet, + boxes: HashSet, + robot: Position, + directions: Vec, +} + +impl Map { + fn new(input: &[String]) -> Map { + let mut floor = HashSet::new(); + let mut boxes = HashSet::new(); + let mut robot = Position { x: 0, y: 0 }; + let mut split_line = 0; + for (y, line) in input.iter().enumerate() { + if line.is_empty() { + split_line = y; + break; + } + for (x, c) in line.chars().enumerate() { + let pos = Position { x: x as isize, y: y as isize }; + match c { + '.' => { + floor.insert(pos); + }, + 'O' => { + floor.insert(pos); + boxes.insert(pos); + }, + '@' => { + floor.insert(pos); + robot = pos; + }, + _ => {} + } + } + } + let mut directions = Vec::new(); + for line in input.iter().skip(split_line) { + for direction in line.chars().map(Direction::new) { + directions.push(direction); + } + } + Map { floor, boxes, robot, directions } + } + + fn _print_map(&self) { + let max_x = self.floor.iter().map(|pos| pos.x).max().unwrap(); + let max_y = self.floor.iter().map(|pos| pos.y).max().unwrap(); + for y in 0 ..= max_y { + for x in 0 ..= max_x { + let pos = Position { x, y }; + if self.robot == pos { + print!("@"); + } else if self.boxes.contains(&pos) { + print!("O"); + } else if self.floor.contains(&pos) { + print!("."); + } else { + print!("#"); + } + } + println!(); + } + println!(); + } + + fn coordinates(&self) -> isize { + self.boxes.iter() + .map(|pos| pos.y * 100 + pos.x) + .sum() + } + + fn move_to(&mut self, pos: &Position, direction: Direction) -> bool { + if !self.floor.contains(pos) { + return false; + } + if self.boxes.contains(pos) { + let next_pos = pos.next(direction); + if self.move_to(&next_pos, direction) { + self.boxes.remove(pos); + self.boxes.insert(next_pos); + } else { + return false; + } + } + true + } + + fn move_robot(&mut self) { + for direction in self.directions.clone().iter() { + let next_pos = self.robot.next(*direction); + if self.move_to(&next_pos, *direction) { + self.robot = next_pos; + } + } + } +} + +fn box_coordinates(input: &[String]) -> isize { + let mut map = Map::new(input); + map.move_robot(); + map.coordinates() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + "########", + "#..O.O.#", + "##@.O..#", + "#...O..#", + "#.#.O..#", + "#...O..#", + "#......#", + "########", + "", + "<^^>>>vv>v<<", + ].iter().map(|&x| String::from(x)).collect::>(); + assert_eq!(box_coordinates(&input), 2028); + + let input = [ + "##########", + "#..O..O.O#", + "#......O.#", + "#.OO..O.O#", + "#..O@..O.#", + "#O#..O...#", + "#O..O..O.#", + "#.OO.O.OO#", + "#....O...#", + "##########", + "", + "^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^", + "vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv<", + "<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^", + "^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^><", + "^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^", + "<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>", + "^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><", + "v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^", + ].iter().map(|&x| String::from(x)).collect::>(); + assert_eq!(box_coordinates(&input), 10092); + } +} -- cgit v1.2.3