struct Point(i32, i32);
impl Point {
- fn in_bounds(&self, bound: usize) -> bool {
- let bound: i32 = bound.try_into().unwrap();
- self.0 >= 0 && self.1 >= 0 && self.0 < bound && self.1 < bound
- }
-
fn move_in(&self, dir: Dir) -> Point {
match dir {
Dir::N => *self + Point(-1, 0),
}
}
+ fn moved_from(&self, dir: Dir) -> Point {
+ self.move_in(match dir {
+ Dir::N => Dir::S,
+ Dir::E => Dir::W,
+ Dir::S => Dir::N,
+ Dir::W => Dir::E,
+ })
+ }
+
fn gps(&self) -> u64 {
(100 * self.0 + self.1).try_into().unwrap()
}
struct RobotPrediction {
map: Map<Tile>,
robot: Point,
+ wide: bool,
}
impl RobotPrediction {
fn new(map: Map<Tile>) -> Self {
let robot = map.find(Tile::Robot).next().unwrap();
- RobotPrediction { map, robot }
+ RobotPrediction {
+ map,
+ robot,
+ wide: false,
+ }
+ }
+
+ fn new_wide(map: Map<Tile>) -> Self {
+ let robot = map.find(Tile::Robot).next().unwrap();
+ RobotPrediction {
+ map,
+ robot,
+ wide: true,
+ }
+ }
+
+ fn one_box(&mut self, inst: Dir, np: Point) {
+ let mut mp = np.move_in(inst);
+ loop {
+ mp = match self.map[mp] {
+ Tile::Space => {
+ self.map[self.robot] = Tile::Space;
+ self.map[np] = Tile::Robot;
+ self.map[mp] = Tile::Box;
+ self.robot = np;
+ break;
+ }
+ Tile::Wall => break,
+ Tile::Box => mp.move_in(inst),
+ Tile::BoxL => unreachable!(),
+ Tile::BoxR => unreachable!(),
+ Tile::Robot => unreachable!(),
+ }
+ }
+ }
+
+ fn two_box(&mut self, inst: Dir, mover: Tile, np: Point, lp: Point, rp: Point) {
+ match (self.map[lp], self.map[rp]) {
+ (Tile::Space, Tile::Space) => {
+ self.map[np] = mover;
+ self.map[lp] = Tile::BoxL;
+ self.map[rp] = Tile::BoxR;
+ if mover == Tile::Robot {
+ self.map[self.robot] = Tile::Space;
+ self.robot = np;
+ }
+ todo!()
+ }
+ (Tile::Wall, _) | (_, Tile::Wall) => (),
+ (Tile::BoxL, Tile::BoxR) => {
+ self.two_box(inst, (), np, lp.move_in(inst), rp.move_in(inst));
+ todo!()
+ }
+ (Tile::BoxR, Tile::BoxL) => todo!(),
+ (Tile::BoxL, Tile::Space) | (Tile::Space, Tile::BoxL) => {
+ let lp = np.move_in(inst);
+ let rp = lp + Point(0, 1);
+ self.two_box(inst, (), np, lp, rp);
+ todo!()
+ }
+ (Tile::BoxR, Tile::Space) | (Tile::Space, Tile::BoxR) => {
+ let rp = np.move_in(inst);
+ let lp = rp - Point(0, 1);
+ self.two_box(inst, (), np, lp, rp);
+ todo!()
+ }
+ _ => unreachable!(),
+ }
}
fn apply(&mut self, inst: Dir) {
self.robot = np;
}
Tile::Wall => (),
- Tile::Box => {
- let mut mp = np.move_in(inst);
- loop {
- mp = match self.map[mp] {
- Tile::Space => {
- self.map[self.robot] = Tile::Space;
- self.map[np] = Tile::Robot;
- self.map[mp] = Tile::Box;
- self.robot = np;
- break;
- }
- Tile::Wall => break,
- Tile::Box => mp.move_in(inst),
- Tile::Robot => unreachable!(),
- Tile::BoxL => todo!(),
- Tile::BoxR => todo!(),
- }
- }
+ Tile::Box => self.one_box(inst, np),
+ Tile::BoxL => {
+ let lp = np.move_in(inst);
+ let rp = lp + Point(0, 1);
+ self.two_box(inst, Tile::Robot, np, lp, rp);
+ }
+ Tile::BoxR => {
+ let rp = np.move_in(inst);
+ let lp = rp - Point(0, 1);
+ self.two_box(inst, Tile::Robot, np, lp, rp);
}
Tile::Robot => unreachable!(),
- Tile::BoxL => todo!(),
- Tile::BoxR => todo!(),
}
}
// println!("{:?} -> {:?}\n{:#?}", self.robot, np, self.map);
}
pub fn part2(input: &str) -> u64 {
- 0
+ let (map, inst) = parse(input);
+ let mut pred = RobotPrediction::new_wide(map.biggerify());
+ pred.simulate(&inst);
+ pred.map.find(Tile::BoxL).map(|p| p.gps()).sum()
}
#[cfg(test)]
#[test]
fn test_gps_sum() {
- assert_eq!(part1(INPUT_STR), 10092)
+ assert_eq!(part1(INPUT_STR), 10092);
+ assert_eq!(part2(INPUT_STR), 9021);
}
#[rustfmt::skip]
assert_eq!(
map.biggerify(),
Map(vec![
- vec![
- Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall,
- Wall, Wall, Wall, Wall, Wall, Wall, Wall
- ],
- vec![
- Wall, Wall, Space, Space, Space, Space, BoxL, BoxR, Space, Space, Space, Space,
- BoxL, BoxR, Space, Space, BoxL, BoxR, Wall, Wall
- ],
- vec![
- Wall, Wall, Space, Space, Space, Space, Space, Space, Space, Space, Space,
- Space, Space, Space, BoxL, BoxR, Space, Space, Wall, Wall
- ],
- vec![
- Wall, Wall, Space, Space, BoxL, BoxR, BoxL, BoxR, Space, Space, Space, Space,
- BoxL, BoxR, Space, Space, BoxL, BoxR, Wall, Wall
- ],
- vec![
- Wall, Wall, Space, Space, Space, Space, BoxL, BoxR, Robot, Space, Space, Space,
- Space, Space, BoxL, BoxR, Space, Space, Wall, Wall
- ],
- vec![
- Wall, Wall, BoxL, BoxR, Wall, Wall, Space, Space, Space, Space, BoxL, BoxR,
- Space, Space, Space, Space, Space, Space, Wall, Wall
- ],
- vec![
- Wall, Wall, BoxL, BoxR, Space, Space, Space, Space, BoxL, BoxR, Space, Space,
- Space, Space, BoxL, BoxR, Space, Space, Wall, Wall
- ],
- vec![
- Wall, Wall, Space, Space, BoxL, BoxR, BoxL, BoxR, Space, Space, BoxL, BoxR,
- Space, Space, BoxL, BoxR, BoxL, BoxR, Wall, Wall
- ],
- vec![
- Wall, Wall, Space, Space, Space, Space, Space, Space, Space, Space, BoxL, BoxR,
- Space, Space, Space, Space, Space, Space, Wall, Wall
- ],
- vec![
- Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall,
- Wall, Wall, Wall, Wall, Wall, Wall, Wall
- ]
+ vec![Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall,
+ Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall],
+ vec![Wall, Wall, Space, Space, Space, Space, BoxL, BoxR, Space, Space,
+ Space, Space, BoxL, BoxR, Space, Space, BoxL, BoxR, Wall, Wall],
+ vec![Wall, Wall, Space, Space, Space, Space, Space, Space, Space, Space,
+ Space, Space, Space, Space, BoxL, BoxR, Space, Space, Wall, Wall],
+ vec![Wall, Wall, Space, Space, BoxL, BoxR, BoxL, BoxR, Space, Space,
+ Space, Space, BoxL, BoxR, Space, Space, BoxL, BoxR, Wall, Wall],
+ vec![Wall, Wall, Space, Space, Space, Space, BoxL, BoxR, Robot, Space,
+ Space, Space, Space, Space, BoxL, BoxR, Space, Space, Wall, Wall],
+ vec![Wall, Wall, BoxL, BoxR, Wall, Wall, Space, Space, Space, Space,
+ BoxL, BoxR, Space, Space, Space, Space, Space, Space, Wall, Wall],
+ vec![Wall, Wall, BoxL, BoxR, Space, Space, Space, Space, BoxL, BoxR,
+ Space, Space, Space, Space, BoxL, BoxR, Space, Space, Wall, Wall],
+ vec![Wall, Wall, Space, Space, BoxL, BoxR, BoxL, BoxR, Space, Space,
+ BoxL, BoxR, Space, Space, BoxL, BoxR, BoxL, BoxR, Wall, Wall],
+ vec![Wall, Wall, Space, Space, Space, Space, Space, Space, Space, Space,
+ BoxL, BoxR, Space, Space, Space, Space, Space, Space, Wall, Wall],
+ vec![Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall,
+ Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall, Wall]
]),
)
}