Day 22, part 2
This commit is contained in:
		@ -9,7 +9,7 @@ pub fn main() {
 | 
				
			|||||||
    // dbg!(&grid);
 | 
					    // dbg!(&grid);
 | 
				
			||||||
    // dbg!(&instructions);
 | 
					    // dbg!(&instructions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut pose = day22::Pose::new(&grid);
 | 
					    let mut pose = grid.initial_pose();
 | 
				
			||||||
    // dbg!(&pose);
 | 
					    // dbg!(&pose);
 | 
				
			||||||
    for inst in &instructions {
 | 
					    for inst in &instructions {
 | 
				
			||||||
        pose = grid.exec_instruction(&pose, inst).0;
 | 
					        pose = grid.exec_instruction(&pose, inst).0;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										40
									
								
								src/bin/d22p2.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/bin/d22p2.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use aoc22::{
 | 
				
			||||||
 | 
					    day22::{self, CubeSide, Navigable},
 | 
				
			||||||
 | 
					    util,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn main() {
 | 
				
			||||||
 | 
					    let (grid, instructions) = day22::parse_map_and_path(&util::parse_input());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut pattern = HashMap::new();
 | 
				
			||||||
 | 
					    pattern.insert(CubeSide::Top, (0, 1));
 | 
				
			||||||
 | 
					    pattern.insert(CubeSide::Fore, (1, 1));
 | 
				
			||||||
 | 
					    pattern.insert(CubeSide::Left, (2, 0));
 | 
				
			||||||
 | 
					    pattern.insert(CubeSide::Back, (3, 0));
 | 
				
			||||||
 | 
					    pattern.insert(CubeSide::Bottom, (2, 1));
 | 
				
			||||||
 | 
					    pattern.insert(CubeSide::Right, (0, 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Pattern for example input
 | 
				
			||||||
 | 
					    // WARNING: CubeGrid::wrap_around is hardcoded for the pattern above
 | 
				
			||||||
 | 
					    // pattern.insert(CubeSide::Top, (0, 2));
 | 
				
			||||||
 | 
					    // pattern.insert(CubeSide::Fore, (1, 2));
 | 
				
			||||||
 | 
					    // pattern.insert(CubeSide::Left, (1, 1));
 | 
				
			||||||
 | 
					    // pattern.insert(CubeSide::Back, (1, 0));
 | 
				
			||||||
 | 
					    // pattern.insert(CubeSide::Bottom, (2, 2));
 | 
				
			||||||
 | 
					    // pattern.insert(CubeSide::Right, (2, 3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let grid = day22::CubeGrid::from(&grid, &pattern);
 | 
				
			||||||
 | 
					    let mut pose = grid.initial_pose();
 | 
				
			||||||
 | 
					    for inst in &instructions {
 | 
				
			||||||
 | 
					        pose = grid.exec_instruction(&pose, inst).0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    let pos = pose.1.pos;
 | 
				
			||||||
 | 
					    let row_add = pattern[&pose.0].0 * grid.side_height;
 | 
				
			||||||
 | 
					    let col_add = pattern[&pose.0].1 * grid.side_width;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let pass =
 | 
				
			||||||
 | 
					        1000 * (row_add + pos.0 + 1) + 4 * (col_add + pos.1 + 1) + (pose.1.orientation as usize);
 | 
				
			||||||
 | 
					    println!("Passowrd: {}", pass);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										397
									
								
								src/day22.rs
									
									
									
									
									
								
							
							
						
						
									
										397
									
								
								src/day22.rs
									
									
									
									
									
								
							@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					use std::collections::HashMap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use itertools::Itertools;
 | 
					use itertools::Itertools;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::util::Dir;
 | 
					use crate::util::Dir;
 | 
				
			||||||
@ -20,19 +22,7 @@ pub struct Pose {
 | 
				
			|||||||
    pub orientation: Dir,
 | 
					    pub orientation: Dir,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Pose {
 | 
					#[derive(Debug)]
 | 
				
			||||||
    pub fn new(grid: &SparseGrid) -> Pose {
 | 
					 | 
				
			||||||
        let col = grid.grid[0]
 | 
					 | 
				
			||||||
            .iter()
 | 
					 | 
				
			||||||
            .position(|t| if let Some(occ) = t { !occ } else { false })
 | 
					 | 
				
			||||||
            .unwrap();
 | 
					 | 
				
			||||||
        Pose {
 | 
					 | 
				
			||||||
            pos: (0, col),
 | 
					 | 
				
			||||||
            orientation: Dir::Right,
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub enum MoveResult {
 | 
					pub enum MoveResult {
 | 
				
			||||||
    Blocked,
 | 
					    Blocked,
 | 
				
			||||||
    BlockedByWrapping,
 | 
					    BlockedByWrapping,
 | 
				
			||||||
@ -63,6 +53,7 @@ pub trait Navigable {
 | 
				
			|||||||
        from: &Self::Pose,
 | 
					        from: &Self::Pose,
 | 
				
			||||||
        inst: &Self::NavigationInstruction,
 | 
					        inst: &Self::NavigationInstruction,
 | 
				
			||||||
    ) -> (Self::Pose, MoveResult);
 | 
					    ) -> (Self::Pose, MoveResult);
 | 
				
			||||||
 | 
					    fn initial_pose(&self) -> Self::Pose;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
@ -74,6 +65,40 @@ pub struct SparseGrid {
 | 
				
			|||||||
    pub col_bounds: Vec<(usize, usize)>,
 | 
					    pub col_bounds: Vec<(usize, usize)>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl SparseGrid {
 | 
				
			||||||
 | 
					    fn print(&self, pose: Option<&Pose>) {
 | 
				
			||||||
 | 
					        let check_pos = |y, x| {
 | 
				
			||||||
 | 
					            if let Some(pose) = pose {
 | 
				
			||||||
 | 
					                pose.pos.0 == y && pose.pos.1 == x
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (y, row) in self.grid.iter().enumerate() {
 | 
				
			||||||
 | 
					            for (x, col) in row.iter().enumerate() {
 | 
				
			||||||
 | 
					                let c = if check_pos(y, x) {
 | 
				
			||||||
 | 
					                    assert!(*col == Some(false));
 | 
				
			||||||
 | 
					                    match pose.unwrap().orientation {
 | 
				
			||||||
 | 
					                        Dir::Right => '>',
 | 
				
			||||||
 | 
					                        Dir::Down => 'v',
 | 
				
			||||||
 | 
					                        Dir::Left => '<',
 | 
				
			||||||
 | 
					                        Dir::Up => '^',
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                } else if col.is_none() {
 | 
				
			||||||
 | 
					                    ' '
 | 
				
			||||||
 | 
					                } else if *col == Some(true) {
 | 
				
			||||||
 | 
					                    '#'
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    '.'
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                print!("{}", c);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            print!("\n");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Navigable for SparseGrid {
 | 
					impl Navigable for SparseGrid {
 | 
				
			||||||
    type Pose = Pose;
 | 
					    type Pose = Pose;
 | 
				
			||||||
    type NavigationInstruction = PassInstr;
 | 
					    type NavigationInstruction = PassInstr;
 | 
				
			||||||
@ -159,6 +184,352 @@ impl Navigable for SparseGrid {
 | 
				
			|||||||
            ),
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn initial_pose(&self) -> Self::Pose {
 | 
				
			||||||
 | 
					        let col = self.grid[0]
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .position(|t| if let Some(occ) = t { !occ } else { false })
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        Pose {
 | 
				
			||||||
 | 
					            pos: (0, col),
 | 
				
			||||||
 | 
					            orientation: Dir::Right,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy)]
 | 
				
			||||||
 | 
					pub enum CubeSide {
 | 
				
			||||||
 | 
					    Top,
 | 
				
			||||||
 | 
					    Bottom,
 | 
				
			||||||
 | 
					    Left,
 | 
				
			||||||
 | 
					    Right,
 | 
				
			||||||
 | 
					    Fore,
 | 
				
			||||||
 | 
					    Back,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct CubeGrid {
 | 
				
			||||||
 | 
					    // The side grids don't have to be sparse, but we don't have a dense
 | 
				
			||||||
 | 
					    // implementation...
 | 
				
			||||||
 | 
					    pub sides: HashMap<CubeSide, SparseGrid>,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub side_height: usize,
 | 
				
			||||||
 | 
					    pub side_width: usize,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl CubeGrid {
 | 
				
			||||||
 | 
					    pub fn from(sparse: &SparseGrid, pattern: &HashMap<CubeSide, (usize, usize)>) -> CubeGrid {
 | 
				
			||||||
 | 
					        let fold_width = pattern.values().map(|(_, col)| col).max().unwrap() + 1;
 | 
				
			||||||
 | 
					        let fold_height = pattern.values().map(|(row, _)| row).max().unwrap() + 1;
 | 
				
			||||||
 | 
					        let side_width = sparse.width / fold_width;
 | 
				
			||||||
 | 
					        assert!(sparse.width % fold_width == 0);
 | 
				
			||||||
 | 
					        let side_height = sparse.height / fold_height;
 | 
				
			||||||
 | 
					        assert!(sparse.height % fold_height == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut sides = HashMap::new();
 | 
				
			||||||
 | 
					        for (side, (fold_row, fold_col)) in pattern {
 | 
				
			||||||
 | 
					            let mut grid = Vec::new();
 | 
				
			||||||
 | 
					            for r in 0..side_height {
 | 
				
			||||||
 | 
					                let mut row = Vec::new();
 | 
				
			||||||
 | 
					                for c in 0..side_width {
 | 
				
			||||||
 | 
					                    let tile = sparse.grid[fold_row * side_height + r][fold_col * side_width + c];
 | 
				
			||||||
 | 
					                    assert!(tile.is_some());
 | 
				
			||||||
 | 
					                    row.push(tile);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                grid.push(row);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            let grid = SparseGrid {
 | 
				
			||||||
 | 
					                grid,
 | 
				
			||||||
 | 
					                height: side_height,
 | 
				
			||||||
 | 
					                width: side_width,
 | 
				
			||||||
 | 
					                row_bounds: vec![(0, side_width - 1); side_height],
 | 
				
			||||||
 | 
					                col_bounds: vec![(0, side_height - 1); side_width],
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            assert!(sides.insert(*side, grid).is_none());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        CubeGrid {
 | 
				
			||||||
 | 
					            sides,
 | 
				
			||||||
 | 
					            side_height,
 | 
				
			||||||
 | 
					            side_width,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn print(&self, pose: &(CubeSide, Pose)) {
 | 
				
			||||||
 | 
					        for (side, grid) in &self.sides {
 | 
				
			||||||
 | 
					            if pose.0 != *side {
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            println!("{:?}:", side);
 | 
				
			||||||
 | 
					            grid.print(Some(&pose.1));
 | 
				
			||||||
 | 
					            println!("");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn wrap_around(&self, side: CubeSide, pose: &Pose) -> (CubeSide, Pose) {
 | 
				
			||||||
 | 
					        // FIXME: This is hardcoded for the folding pattern of the actual input.
 | 
				
			||||||
 | 
					        // It won't work for the example input.
 | 
				
			||||||
 | 
					        assert_eq!(self.side_height, self.side_width);
 | 
				
			||||||
 | 
					        let dir = pose.orientation;
 | 
				
			||||||
 | 
					        let pos = pose.pos;
 | 
				
			||||||
 | 
					        let row = pos.0;
 | 
				
			||||||
 | 
					        let last = self.side_height - 1;
 | 
				
			||||||
 | 
					        let row_inv = last - row;
 | 
				
			||||||
 | 
					        let col = pos.1;
 | 
				
			||||||
 | 
					        match side {
 | 
				
			||||||
 | 
					            CubeSide::Top => match dir {
 | 
				
			||||||
 | 
					                Dir::Right => (
 | 
				
			||||||
 | 
					                    CubeSide::Right,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row, 0),
 | 
				
			||||||
 | 
					                        orientation: Dir::Right,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Down => (
 | 
				
			||||||
 | 
					                    CubeSide::Fore,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (0, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Down,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Left => (
 | 
				
			||||||
 | 
					                    CubeSide::Left,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row_inv, 0),
 | 
				
			||||||
 | 
					                        orientation: Dir::Right,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Up => (
 | 
				
			||||||
 | 
					                    CubeSide::Back,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (col, 0),
 | 
				
			||||||
 | 
					                        orientation: Dir::Right,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            CubeSide::Bottom => match dir {
 | 
				
			||||||
 | 
					                Dir::Right => (
 | 
				
			||||||
 | 
					                    CubeSide::Right,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row_inv, last),
 | 
				
			||||||
 | 
					                        orientation: Dir::Left,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Down => (
 | 
				
			||||||
 | 
					                    CubeSide::Back,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (col, last),
 | 
				
			||||||
 | 
					                        orientation: Dir::Left,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Left => (
 | 
				
			||||||
 | 
					                    CubeSide::Left,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row, last),
 | 
				
			||||||
 | 
					                        orientation: Dir::Left,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Up => (
 | 
				
			||||||
 | 
					                    CubeSide::Fore,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (last, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Up,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            CubeSide::Left => match dir {
 | 
				
			||||||
 | 
					                Dir::Right => (
 | 
				
			||||||
 | 
					                    CubeSide::Bottom,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row, 0),
 | 
				
			||||||
 | 
					                        orientation: Dir::Right,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Down => (
 | 
				
			||||||
 | 
					                    CubeSide::Back,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (0, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Down,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Left => (
 | 
				
			||||||
 | 
					                    CubeSide::Top,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row_inv, 0),
 | 
				
			||||||
 | 
					                        orientation: Dir::Right,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Up => (
 | 
				
			||||||
 | 
					                    CubeSide::Fore,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (col, 0),
 | 
				
			||||||
 | 
					                        orientation: Dir::Right,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            CubeSide::Right => match dir {
 | 
				
			||||||
 | 
					                Dir::Right => (
 | 
				
			||||||
 | 
					                    CubeSide::Bottom,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row_inv, last),
 | 
				
			||||||
 | 
					                        orientation: Dir::Left,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Down => (
 | 
				
			||||||
 | 
					                    CubeSide::Fore,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (col, last),
 | 
				
			||||||
 | 
					                        orientation: Dir::Left,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Left => (
 | 
				
			||||||
 | 
					                    CubeSide::Top,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (row, last),
 | 
				
			||||||
 | 
					                        orientation: Dir::Left,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Up => (
 | 
				
			||||||
 | 
					                    CubeSide::Back,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (last, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Up,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            CubeSide::Fore => match dir {
 | 
				
			||||||
 | 
					                Dir::Right => (
 | 
				
			||||||
 | 
					                    CubeSide::Right,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (last, row),
 | 
				
			||||||
 | 
					                        orientation: Dir::Up,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Down => (
 | 
				
			||||||
 | 
					                    CubeSide::Bottom,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (0, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Down,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Left => (
 | 
				
			||||||
 | 
					                    CubeSide::Left,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (0, row),
 | 
				
			||||||
 | 
					                        orientation: Dir::Down,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Up => (
 | 
				
			||||||
 | 
					                    CubeSide::Top,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (last, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Up,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            CubeSide::Back => match dir {
 | 
				
			||||||
 | 
					                Dir::Right => (
 | 
				
			||||||
 | 
					                    CubeSide::Bottom,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (last, row),
 | 
				
			||||||
 | 
					                        orientation: Dir::Up,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Down => (
 | 
				
			||||||
 | 
					                    CubeSide::Right,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (0, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Down,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Left => (
 | 
				
			||||||
 | 
					                    CubeSide::Top,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (0, row),
 | 
				
			||||||
 | 
					                        orientation: Dir::Down,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                Dir::Up => (
 | 
				
			||||||
 | 
					                    CubeSide::Left,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: (last, col),
 | 
				
			||||||
 | 
					                        orientation: Dir::Up,
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Navigable for CubeGrid {
 | 
				
			||||||
 | 
					    type Pose = (CubeSide, Pose);
 | 
				
			||||||
 | 
					    type NavigationInstruction = PassInstr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn forward(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        (from_side, from_pose): &Self::Pose,
 | 
				
			||||||
 | 
					        steps: usize,
 | 
				
			||||||
 | 
					    ) -> (Self::Pose, MoveResult) {
 | 
				
			||||||
 | 
					        let mut side = from_side.clone();
 | 
				
			||||||
 | 
					        let mut pose = from_pose.clone();
 | 
				
			||||||
 | 
					        let mut status = MoveResult::Success;
 | 
				
			||||||
 | 
					        for _ in 0..steps {
 | 
				
			||||||
 | 
					            let (next_pose, res) = self.sides[&side].forward(&pose, 1);
 | 
				
			||||||
 | 
					            if res.wrapped_around() {
 | 
				
			||||||
 | 
					                let (next_side, next_pose) = self.wrap_around(side, &pose);
 | 
				
			||||||
 | 
					                if self.sides[&next_side].grid[next_pose.pos.0][next_pose.pos.1] == Some(true) {
 | 
				
			||||||
 | 
					                    // Can't wrap around, we're blocked
 | 
				
			||||||
 | 
					                    return ((side, pose), MoveResult::BlockedByWrapping);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                side = next_side;
 | 
				
			||||||
 | 
					                pose = next_pose;
 | 
				
			||||||
 | 
					                status = MoveResult::WrappedAround;
 | 
				
			||||||
 | 
					            } else if res.was_blocked() {
 | 
				
			||||||
 | 
					                return ((side, pose), MoveResult::Blocked);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                pose = next_pose;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ((side, pose), status)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn exec_instruction(
 | 
				
			||||||
 | 
					        &self,
 | 
				
			||||||
 | 
					        from: &Self::Pose,
 | 
				
			||||||
 | 
					        inst: &Self::NavigationInstruction,
 | 
				
			||||||
 | 
					    ) -> (Self::Pose, MoveResult) {
 | 
				
			||||||
 | 
					        match inst {
 | 
				
			||||||
 | 
					            PassInstr::Move(n) => self.forward(from, *n),
 | 
				
			||||||
 | 
					            PassInstr::Turn(dir) => (
 | 
				
			||||||
 | 
					                (
 | 
				
			||||||
 | 
					                    from.0,
 | 
				
			||||||
 | 
					                    Pose {
 | 
				
			||||||
 | 
					                        pos: from.1.pos,
 | 
				
			||||||
 | 
					                        orientation: match dir {
 | 
				
			||||||
 | 
					                            TurnDir::CW => from.1.orientation.cw(),
 | 
				
			||||||
 | 
					                            TurnDir::CCW => from.1.orientation.ccw(),
 | 
				
			||||||
 | 
					                        },
 | 
				
			||||||
 | 
					                    },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                MoveResult::Success,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn initial_pose(&self) -> Self::Pose {
 | 
				
			||||||
 | 
					        let col = self.sides[&CubeSide::Top].grid[0]
 | 
				
			||||||
 | 
					            .iter()
 | 
				
			||||||
 | 
					            .position(|t| *t == Some(false))
 | 
				
			||||||
 | 
					            .unwrap();
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            CubeSide::Top,
 | 
				
			||||||
 | 
					            Pose {
 | 
				
			||||||
 | 
					                pos: (0, col),
 | 
				
			||||||
 | 
					                orientation: Dir::Right,
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn parse_map_and_path(input: &str) -> (SparseGrid, Vec<PassInstr>) {
 | 
					pub fn parse_map_and_path(input: &str) -> (SparseGrid, Vec<PassInstr>) {
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user