From 41ed3a934ec62adf2f4d5e859e8b2578b6d1c9e7 Mon Sep 17 00:00:00 2001 From: Reiner Herrmann Date: Wed, 28 Dec 2022 23:42:13 +0100 Subject: day22 part1 --- src/bin/day22.rs | 221 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 src/bin/day22.rs (limited to 'src') diff --git a/src/bin/day22.rs b/src/bin/day22.rs new file mode 100644 index 0000000..13322c6 --- /dev/null +++ b/src/bin/day22.rs @@ -0,0 +1,221 @@ +use std::collections::HashMap; + +static DAY: u8 = 22; + +fn main() { + let input = advent::read_lines(DAY); + println!("{DAY}a: {}", find_password(&input)); + println!("{DAY}b: {}", 0); +} + +#[derive(Clone,Copy)] +enum Object { + Floor, + Wall, +} + +enum Instruction { + Left, + Right, + Move { amount: isize }, +} + +enum Direction { + Left, + Right, + Up, + Down, +} + +impl Direction { + fn turn_left(&self) -> Direction { + match self { + Direction::Left => Direction::Down, + Direction::Right => Direction::Up, + Direction::Up => Direction::Left, + Direction::Down => Direction::Right, + } + } + + fn turn_right(&self) -> Direction { + match self { + Direction::Left => Direction::Up, + Direction::Right => Direction::Down, + Direction::Up => Direction::Right, + Direction::Down => Direction::Left, + } + } +} + +struct Map { + map: HashMap<(isize,isize),Object>, + instructions: Vec, + pos: (isize,isize), + direction: Direction, +} + +impl Map { + fn new(input: &[String]) -> Map { + let mut map = HashMap::new(); + let mut pos = None; + for (y, line) in input.iter().enumerate() { + if line.is_empty() { + break; + } + for (x, c) in line.chars().enumerate() { + let (x, y) = (x as isize, y as isize); + match c { + '.' => { + if pos.is_none() { + pos = Some((x, y)); + } + map.insert((x,y), Object::Floor); + } + '#' => { map.insert((x,y), Object::Wall); } + _ => continue, + } + } + } + + let mut instructions = Vec::new(); + let mut number = 0; + for c in input.last().unwrap().chars() { + if c.is_ascii_digit() { + number *= 10; + number += c.to_digit(10).unwrap() as isize; + } else { + if number > 0 { + instructions.push(Instruction::Move { amount: number }); + number = 0; + } + match c { + 'R' => instructions.push(Instruction::Right), + 'L' => instructions.push(Instruction::Left), + _ => unimplemented!(), + } + } + } + if number > 0 { + instructions.push(Instruction::Move { amount: number }); + } + + Map { map, instructions, pos: pos.unwrap(), direction: Direction::Right } + } + + fn opposite_position(&self, direction: Direction) -> Option<(isize,isize)> { + let mut old_pos = self.pos; + let mut old_object = Object::Floor; + loop { + let (x, y) = old_pos; + let check_pos = match direction { + Direction::Left => (x-1, y), + Direction::Right => (x+1, y), + Direction::Up => (x, y-1), + Direction::Down => (x, y+1), + }; + match self.map.get(&check_pos) { + None => return match old_object { + Object::Floor => Some(old_pos), + Object::Wall => None, + }, + Some(obj) => old_object = *obj, + } + old_pos = check_pos; + } + } + + fn step_forward(&self) -> (isize,isize) { + let (x, y) = self.pos; + return match self.direction { + Direction::Left => { + match self.map.get(&(x-1,y)) { + None => self.opposite_position(Direction::Right).unwrap_or(self.pos), + Some(Object::Wall) => self.pos, + Some(Object::Floor) => (x-1,y), + } + }, + Direction::Right => { + match self.map.get(&(x+1,y)) { + None => self.opposite_position(Direction::Left).unwrap_or(self.pos), + Some(Object::Wall) => self.pos, + Some(Object::Floor) => (x+1,y), + } + }, + Direction::Up => { + match self.map.get(&(x,y-1)) { + None => self.opposite_position(Direction::Down).unwrap_or(self.pos), + Some(Object::Wall) => self.pos, + Some(Object::Floor) => (x,y-1), + } + }, + Direction::Down => { + match self.map.get(&(x,y+1)) { + None => self.opposite_position(Direction::Up).unwrap_or(self.pos), + Some(Object::Wall) => self.pos, + Some(Object::Floor) => (x,y+1), + } + }, + } + } + + fn run(&mut self) { + for instruction in &self.instructions { + match instruction { + Instruction::Left => { + self.direction = self.direction.turn_left(); + }, + Instruction::Right => { + self.direction = self.direction.turn_right(); + }, + Instruction::Move { amount } => { + for _ in 0 .. *amount { + self.pos = self.step_forward(); + } + }, + } + } + } + + fn password(&self) -> isize { + let facing = match self.direction { + Direction::Right => 0, + Direction::Down => 1, + Direction::Left => 2, + Direction::Up => 3, + }; + 1000 * (self.pos.1 + 1) + 4 * (self.pos.0 + 1) + facing + } +} + +fn find_password(input: &[String]) -> isize { + let mut map = Map::new(input); + map.run(); + map.password() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + " ...#", + " .#..", + " #...", + " ....", + "...#.......#", + "........#...", + "..#....#....", + "..........#.", + " ...#....", + " .....#..", + " .#......", + " ......#.", + "", + "10R5L5R10L4R5L5", + ].iter().map(|&x| String::from(x)).collect::>(); + + assert_eq!(find_password(&input), 6032); + } +} -- cgit v1.2.3