Day 22, part 1
This commit is contained in:
parent
a0fa5256e9
commit
5e6870d092
18
src/bin/d22p1.rs
Normal file
18
src/bin/d22p1.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
use aoc22::{day22, util};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let (grid, instructions) = day22::parse_map_and_path(&util::parse_input());
|
||||||
|
|
||||||
|
// dbg!(&grid);
|
||||||
|
// dbg!(&instructions);
|
||||||
|
|
||||||
|
let mut pose = day22::Pose::new(&grid);
|
||||||
|
// dbg!(&pose);
|
||||||
|
for inst in &instructions {
|
||||||
|
pose = day22::exec_instruction(&grid, &pose, inst);
|
||||||
|
// dbg!(&pose);
|
||||||
|
}
|
||||||
|
|
||||||
|
let pass = 1000 * (pose.pos.0 + 1) + 4 * (pose.pos.1 + 1) + (pose.orientation as usize);
|
||||||
|
println!("Passowrd: {}", pass);
|
||||||
|
}
|
188
src/day22.rs
Normal file
188
src/day22.rs
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
use crate::util::Dir;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TurnDir {
|
||||||
|
CW,
|
||||||
|
CCW,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Instruction {
|
||||||
|
Move(isize),
|
||||||
|
Turn(TurnDir),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Grid {
|
||||||
|
pub grid: Vec<Vec<Option<bool>>>,
|
||||||
|
pub height: usize,
|
||||||
|
pub width: usize,
|
||||||
|
pub row_bounds: Vec<(usize, usize)>,
|
||||||
|
pub col_bounds: Vec<(usize, usize)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_map_and_path(input: &str) -> (Grid, Vec<Instruction>) {
|
||||||
|
let lines = input.lines().collect_vec();
|
||||||
|
|
||||||
|
let mut grid: Vec<Vec<Option<bool>>> = Vec::new();
|
||||||
|
let mut width = 0;
|
||||||
|
for line in &lines[..lines.len() - 2] {
|
||||||
|
width = width.max(line.len());
|
||||||
|
let grid_line = line
|
||||||
|
.chars()
|
||||||
|
.map(|c| match c {
|
||||||
|
' ' => None,
|
||||||
|
'.' => Some(false),
|
||||||
|
'#' => Some(true),
|
||||||
|
_ => panic!("Unknown grid character {}", c),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
grid.push(grid_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
let height = grid.len();
|
||||||
|
let mut row_bounds = vec![(0, 0); height];
|
||||||
|
for row in 0..height {
|
||||||
|
let row_width = grid[row].len();
|
||||||
|
if row_width < width {
|
||||||
|
grid[row].extend((row_width..width).map(|_| None));
|
||||||
|
}
|
||||||
|
let lower = grid[row].iter().position(Option::is_some).unwrap();
|
||||||
|
let upper = width - 1 - grid[row].iter().rev().position(Option::is_some).unwrap();
|
||||||
|
row_bounds[row] = (lower, upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut col_bounds = vec![(0, 0); width];
|
||||||
|
for col in 0..width {
|
||||||
|
let col_it = (0..height).map(|row| grid[row][col]);
|
||||||
|
let lower = col_it.clone().position(|t| t.is_some()).unwrap();
|
||||||
|
let upper = height - 1 - col_it.rev().position(|t| t.is_some()).unwrap();
|
||||||
|
col_bounds[col] = (lower, upper);
|
||||||
|
}
|
||||||
|
|
||||||
|
let grid = Grid {
|
||||||
|
grid,
|
||||||
|
height,
|
||||||
|
width,
|
||||||
|
row_bounds,
|
||||||
|
col_bounds,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut instructions = Vec::new();
|
||||||
|
let mut inst_begin = 0;
|
||||||
|
let inst_line = lines[lines.len() - 1].as_bytes();
|
||||||
|
while inst_begin < inst_line.len() {
|
||||||
|
let mut i = inst_begin;
|
||||||
|
let c = inst_line[i];
|
||||||
|
if c.is_ascii_digit() {
|
||||||
|
while i < inst_line.len() && inst_line[i].is_ascii_digit() {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
let dist = std::str::from_utf8(&inst_line[inst_begin..i])
|
||||||
|
.unwrap()
|
||||||
|
.parse()
|
||||||
|
.unwrap();
|
||||||
|
instructions.push(Instruction::Move(dist));
|
||||||
|
inst_begin = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let dir = match c {
|
||||||
|
b'L' => TurnDir::CCW,
|
||||||
|
b'R' => TurnDir::CW,
|
||||||
|
_ => panic!("Unknown turn direction {}", c),
|
||||||
|
};
|
||||||
|
instructions.push(Instruction::Turn(dir));
|
||||||
|
inst_begin += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(grid, instructions)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Pose {
|
||||||
|
pub pos: (usize, usize),
|
||||||
|
pub orientation: Dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Pose {
|
||||||
|
pub fn new(grid: &Grid) -> 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 fn exec_instruction(grid: &Grid, pose: &Pose, instr: &Instruction) -> Pose {
|
||||||
|
match instr {
|
||||||
|
Instruction::Turn(turn_dir) => Pose {
|
||||||
|
pos: pose.pos,
|
||||||
|
orientation: match turn_dir {
|
||||||
|
TurnDir::CW => pose.orientation.cw(),
|
||||||
|
TurnDir::CCW => pose.orientation.ccw(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Instruction::Move(n) => {
|
||||||
|
let mut pos = pose.pos;
|
||||||
|
|
||||||
|
for _ in 0..*n {
|
||||||
|
let next_pos = match pose.orientation {
|
||||||
|
Dir::Left => {
|
||||||
|
let bounds = &grid.row_bounds[pos.0];
|
||||||
|
let next_col = if pos.1 == 0 || pos.1 == bounds.0 {
|
||||||
|
bounds.1
|
||||||
|
} else {
|
||||||
|
pos.1 - 1
|
||||||
|
};
|
||||||
|
(pos.0, next_col)
|
||||||
|
}
|
||||||
|
Dir::Up => {
|
||||||
|
let bounds = &grid.col_bounds[pos.1];
|
||||||
|
let next_row = if pos.0 == 0 || pos.0 == bounds.0 {
|
||||||
|
bounds.1
|
||||||
|
} else {
|
||||||
|
pos.0 - 1
|
||||||
|
};
|
||||||
|
(next_row, pos.1)
|
||||||
|
}
|
||||||
|
Dir::Right => {
|
||||||
|
let bounds = &grid.row_bounds[pos.0];
|
||||||
|
let next_col = if pos.1 == bounds.1 {
|
||||||
|
bounds.0
|
||||||
|
} else {
|
||||||
|
pos.1 + 1
|
||||||
|
};
|
||||||
|
(pos.0, next_col)
|
||||||
|
}
|
||||||
|
Dir::Down => {
|
||||||
|
let bounds = &grid.col_bounds[pos.1];
|
||||||
|
let next_row = if pos.0 == bounds.1 {
|
||||||
|
bounds.0
|
||||||
|
} else {
|
||||||
|
pos.0 + 1
|
||||||
|
};
|
||||||
|
(next_row, pos.1)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if grid.grid[next_pos.0][next_pos.1].unwrap() {
|
||||||
|
// We're about to hit a wall
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos = next_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pose {
|
||||||
|
pos,
|
||||||
|
orientation: pose.orientation,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,6 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[derive(Debug)]
|
use crate::util::Dir;
|
||||||
pub enum Dir {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Motion = (Dir, usize);
|
pub type Motion = (Dir, usize);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ pub mod day19;
|
|||||||
pub mod day2;
|
pub mod day2;
|
||||||
pub mod day20;
|
pub mod day20;
|
||||||
pub mod day21;
|
pub mod day21;
|
||||||
|
pub mod day22;
|
||||||
pub mod day3;
|
pub mod day3;
|
||||||
pub mod day4;
|
pub mod day4;
|
||||||
pub mod day5;
|
pub mod day5;
|
||||||
|
31
src/util.rs
31
src/util.rs
@ -122,3 +122,34 @@ where
|
|||||||
|
|
||||||
best
|
best
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Dir {
|
||||||
|
Right = 0,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
Up,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Dir {
|
||||||
|
pub fn from_usize(n: usize) -> Option<Dir> {
|
||||||
|
match n {
|
||||||
|
0 => Some(Dir::Right),
|
||||||
|
1 => Some(Dir::Down),
|
||||||
|
2 => Some(Dir::Left),
|
||||||
|
3 => Some(Dir::Up),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cw(&self) -> Dir {
|
||||||
|
let d = *self as usize;
|
||||||
|
Self::from_usize((d + 1) % 4).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ccw(&self) -> Dir {
|
||||||
|
let d = *self as usize;
|
||||||
|
// Add 3 instead of subtracting one to avoid negative numbers
|
||||||
|
Self::from_usize((d + 3) % 4).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user