diff options
| -rw-r--r-- | src/bin/day22.rs | 170 |
1 files changed, 147 insertions, 23 deletions
diff --git a/src/bin/day22.rs b/src/bin/day22.rs index 13322c6..3a2b6ec 100644 --- a/src/bin/day22.rs +++ b/src/bin/day22.rs @@ -4,8 +4,8 @@ static DAY: u8 = 22; fn main() { let input = advent::read_lines(DAY); - println!("{DAY}a: {}", find_password(&input)); - println!("{DAY}b: {}", 0); + println!("{DAY}a: {}", find_password(&input, false)); + println!("{DAY}b: {}", find_password(&input, true)); } #[derive(Clone,Copy)] @@ -20,6 +20,7 @@ enum Instruction { Move { amount: isize }, } +#[derive(Clone,Copy)] enum Direction { Left, Right, @@ -45,6 +46,15 @@ impl Direction { Direction::Down => Direction::Left, } } + + fn opposite(&self) -> Direction { + match self { + Direction::Left => Direction::Right, + Direction::Right => Direction::Left, + Direction::Up => Direction::Down, + Direction::Down => Direction::Up, + } + } } struct Map { @@ -52,10 +62,11 @@ struct Map { instructions: Vec<Instruction>, pos: (isize,isize), direction: Direction, + cube_wrapping: bool, } impl Map { - fn new(input: &[String]) -> Map { + fn new(input: &[String], cube_wrapping: bool) -> Map { let mut map = HashMap::new(); let mut pos = None; for (y, line) in input.iter().enumerate() { @@ -99,10 +110,11 @@ impl Map { instructions.push(Instruction::Move { amount: number }); } - Map { map, instructions, pos: pos.unwrap(), direction: Direction::Right } + Map { map, instructions, pos: pos.unwrap(), direction: Direction::Right, cube_wrapping } } - fn opposite_position(&self, direction: Direction) -> Option<(isize,isize)> { + fn opposite_position(&self) -> Option<((isize,isize),Direction)> { + let direction = self.direction.opposite(); let mut old_pos = self.pos; let mut old_object = Object::Floor; loop { @@ -115,7 +127,7 @@ impl Map { }; match self.map.get(&check_pos) { None => return match old_object { - Object::Floor => Some(old_pos), + Object::Floor => Some((old_pos,self.direction)), Object::Wall => None, }, Some(obj) => old_object = *obj, @@ -124,35 +136,146 @@ impl Map { } } - fn step_forward(&self) -> (isize,isize) { + fn next_cube_position(&self) -> Option<((isize,isize),Direction)> { + let (new_pos, new_direction) = match self.direction { + Direction::Left => { + match self.pos.0 { + 0 => { + if (100..150).contains(&self.pos.1) { + // 100 -> 49, 149 -> 0 + ((50, 49 - (self.pos.1 - 100)), Direction::Right) + } else if (150..200).contains(&self.pos.1) { + // 150 -> 50, 199 -> 99 + ((self.pos.1 - 100, 0), Direction::Down) + } else { panic!("no wrapping expected"); } + }, + 50 => { + if (0..50).contains(&self.pos.1) { + // 49 -> 100, 0 -> 149 + ((0, 149 - self.pos.1), Direction::Right) + } else if (50..100).contains(&self.pos.1) { + // 50 -> 0, 99 -> 49 + ((self.pos.1 - 50, 100), Direction::Down) + } else { panic!("no wrapping expected"); } + }, + _ => panic!("no wrapping expected"), + } + }, + Direction::Right => { + match self.pos.0 { + 49 => { + if (150..200).contains(&self.pos.1) { + // 150 -> 50, 199 -> 99 + ((self.pos.1 - 100, 149), Direction::Up) + } else { panic!("no wrapping expected"); } + }, + 99 => { + if (50..100).contains(&self.pos.1) { + // 50 -> 100, 99 -> 149 + ((self.pos.1 + 50, 49), Direction::Up) + } else if (100..150).contains(&self.pos.1) { + // 149 -> 0, 100 -> 49 + ((149, 49 - (self.pos.1 - 100)), Direction::Left) + } else { panic!("no wrapping expected"); } + }, + 149 => { + if (0..50).contains(&self.pos.1) { + // 0 -> 149, 49 -> 100 + ((99, 149 - self.pos.1), Direction::Left) + } else { panic!("no wrapping expected"); } + }, + _ => panic!("no wrapping expected"), + } + }, + Direction::Up => { + match self.pos.1 { + 0 => { + if (50..100).contains(&self.pos.0) { + // 50 -> 150, 99 -> 199 + ((0, self.pos.0 + 100), Direction::Right) + } else if (100..150).contains(&self.pos.0) { + // 100 -> 0, 149 -> 49 + ((self.pos.0 - 100, 199), Direction::Up) + } else { panic!("no wrapping expected"); } + }, + 100 => { + if (0..50).contains(&self.pos.0) { + // 0 -> 50, 49 -> 99 + ((50, self.pos.0 + 50), Direction::Right) + } else { panic!("no wrapping expected"); } + }, + _ => panic!("no wrapping expected"), + } + }, + Direction::Down => { + match self.pos.1 { + 49 => { + if (100..150).contains(&self.pos.0) { + // 100 -> 50, 149 -> 99 + ((99, self.pos.0 - 50), Direction::Left) + } else { panic!("no wrapping expected"); } + }, + 149 => { + if (50..100).contains(&self.pos.0) { + // 50 -> 150, 99 -> 199 + ((49, self.pos.0 + 100), Direction::Left) + } else { panic!("no wrapping expected"); } + }, + 199 => { + if (0..50).contains(&self.pos.0) { + // 0 -> 100, 49 -> 149 + ((self.pos.0 + 100, 0), Direction::Down) + } else { panic!("no wrapping expected"); } + }, + _ => panic!("no wrapping expected"), + } + } + }; + if let Some(Object::Wall) = self.map.get(&new_pos) { + None + } else { + Some((new_pos, new_direction)) + } + } + + fn wrapped_position(&self) -> Option<((isize,isize),Direction)> { + if self.cube_wrapping { + self.next_cube_position() + } else { + self.opposite_position() + } + } + + fn step_forward(&self) -> ((isize,isize),Direction) { let (x, y) = self.pos; + let default = (self.pos, self.direction); 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), + None => self.wrapped_position().unwrap_or(default), + Some(Object::Wall) => (self.pos, Direction::Left), + Some(Object::Floor) => ((x-1,y), Direction::Left), } }, 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), + None => self.wrapped_position().unwrap_or(default), + Some(Object::Wall) => (self.pos, Direction::Right), + Some(Object::Floor) => ((x+1,y), Direction::Right), } }, 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), + None => self.wrapped_position().unwrap_or(default), + Some(Object::Wall) => (self.pos, Direction::Up), + Some(Object::Floor) => ((x,y-1), Direction::Up), } }, 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), + None => self.wrapped_position().unwrap_or(default), + Some(Object::Wall) => (self.pos, Direction::Down), + Some(Object::Floor) => ((x,y+1), Direction::Down), } }, } @@ -169,7 +292,7 @@ impl Map { }, Instruction::Move { amount } => { for _ in 0 .. *amount { - self.pos = self.step_forward(); + (self.pos, self.direction) = self.step_forward(); } }, } @@ -187,8 +310,8 @@ impl Map { } } -fn find_password(input: &[String]) -> isize { - let mut map = Map::new(input); +fn find_password(input: &[String], cube_wrapping: bool) -> isize { + let mut map = Map::new(input, cube_wrapping); map.run(); map.password() } @@ -216,6 +339,7 @@ mod tests { "10R5L5R10L4R5L5", ].iter().map(|&x| String::from(x)).collect::<Vec<_>>(); - assert_eq!(find_password(&input), 6032); + assert_eq!(find_password(&input, false), 6032); + //assert_eq!(find_password(&input, true), 5031); } } |
