heh
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 475 |
1 files changed, 50 insertions, 425 deletions
diff --git a/src/main.rs b/src/main.rs index 6f8d982..778a54d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,438 +33,63 @@ )] extern crate test; pub mod util; -use atools::CollectArray; +use std::cmp::Reverse; pub use util::prelude::*; -const SIZE: usize = 50; -// enum Bloc { -// Wall, -// Block, -// Space, -// } - -// impl Bloc { -// fn push((x, y): (usize, usize), dir: Dir, grid: &mut [[Bloc; SIZE]], commit: bool) -> bool { -// match dir { -// Dir::N => match grid[y - 1][x] {}, -// Dir::E => todo!(), -// Dir::S => todo!(), -// Dir::W => todo!(), -// } -// } -// } -// impl std::fmt::Debug for Bloc { -// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -// match self { -// Wall => write!(f, "##"), -// Block => write!(f, "[]"), -// Space => write!(f, ".."), -// } -// } -// } -// use Bloc::*; -pub unsafe fn p2(i: &str) -> impl Display { - let i = i.as_bytes(); - let bot = memchr::memchr(b'@', i).ψ(); - let (mut x, mut y) = ((bot % (SIZE + 1)) * 2, bot / (SIZE + 1)); - let grid = i[..(SIZE + 1) * SIZE] - .array_chunks::<{ SIZE + 1 }>() - .flat_map(|x| { - x.iter().take(SIZE).copied().flat_map(|x| match x { - b'#' => [x; 2], - b'O' => *b"[]", - b'@' | b'.' => *b"..", - _ => shucks!(), - }) - }) - .collect::<Vec<_>>() - .leak() - .as_chunks_unchecked_mut::<{ SIZE * 2 }>(); - // for y in 0..SIZE { - // for x in 0..SIZE * 2 { - // if (px, py) == (x, y) { - // print!("@"); - // } else { - // print!("{}", grid[y][x] as char); - // } - // } - // println!(); - // } - // println!("{grid/:?}"); - // let grid = i[..(SIZE + 1) * SIZE] - // .to_vec() - // .leak() - // .as_chunks_unchecked_mut::<{ SIZE + 1 }>(); - // grid[y][x * 2] = b'.'; - let i = &i[((SIZE + 1) * SIZE) + 1..]; - #[no_mangle] - fn push((x, y): (usize, usize), dir: Dir, grid: &mut [[u8; SIZE * 2]], commit: bool) -> bool { - match dir { - Dir::N => { - macro_rules! set { - () => {{ - grid[y - 1][x] = b'['; - grid[y - 1][x + 1] = b']'; - grid[y][x] = b'.'; - grid[y][x + 1] = b'.'; - }}; - } - match [grid[y - 1][x], grid[y - 1][x + 1]] { - [_, b'#'] | [b'#', _] => {} - [b'.', b'.'] => { - if commit { - set!() - } - return true; - } - [b']', b'['] => { - let val = push((x - 1, y - 1), dir, grid, false) - && push((x + 1, y - 1), dir, grid, false); - if commit && val { - push((x - 1, y - 1), dir, grid, commit); - push((x + 1, y - 1), dir, grid, commit); - set!(); - } - return val; - } - [b']', b'.'] => { - let val = push((x - 1, y - 1), dir, grid, commit); - if commit && val { - set!() - } - return val; - } - [b'.', b'['] => { - let val = push((x + 1, y - 1), dir, grid, commit); - if commit && val { - set!() - } - return val; - } - // "simple" case - [b'[', b']'] => { - let val = push((x, y - 1), dir, grid, commit); - if val && commit { - set!() - } - return val; - } - x => shucks!("{x:?}"), - } - } - Dir::S => { - macro_rules! set { - () => {{ - grid[y + 1][x] = b'['; - grid[y + 1][x + 1] = b']'; - grid[y][x] = b'.'; - grid[y][x + 1] = b'.'; - }}; - } - match [grid[y + 1][x], grid[y + 1][x + 1]] { - [_, b'#'] | [b'#', _] => {} - [b'.', b'.'] => { - if commit { - set!() - } - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - [b']', b'['] => { - let val = push((x - 1, y + 1), dir, grid, false) - && push((x + 1, y + 1), dir, grid, false); - if commit && val { - push((x - 1, y + 1), dir, grid, commit); - push((x + 1, y + 1), dir, grid, commit); - set!() - } - return val; - } - [b']', b'.'] => { - let val = push((x - 1, y + 1), dir, grid, commit); - if commit && val { - set!() - } - return val; - } - [b'.', b'['] => { - let val = push((x + 1, y + 1), dir, grid, commit); - if commit && val { - set!() - } - return val; - } - [b'[', b']'] => { - let val = push((x, y + 1), dir, grid, commit); - if val && commit { - set!() - } - return val; - } - x => shucks!("{x:?}"), - } - } - Dir::E => { - macro_rules! set { - () => {{ - grid[y][x + 2] = b']'; - grid[y][x + 1] = b'['; - grid[y][x] = b'.'; - }}; - } - match grid[y][x + 2] { - b'.' => { - set!(); - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - b'[' => { - if push((x + 2, y), dir, grid, true) { - set!(); - return true; - } - } - b'#' => {} - x => shucks!("{}", x as char), - } - } - - Dir::W => { - macro_rules! set { - () => {{ - grid[y][x - 1] = b'['; - grid[y][x] = b']'; - grid[y][x + 1] = b'.'; - }}; - } - match grid[y][x - 1] { - b'.' => { - set!(); - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - b']' => { - if push((x - 2, y), dir, grid, commit) { - set!(); - return true; - } - } - b'#' => {} - x => shucks!("{}", x as char), - } - } - } - false - } - for input in i { - // println!("{}", *input as char); - match input { - b'<' => match grid[y][x - 1] { - b'.' => x = x - 1, - b'#' => (), - b']' => { - if push((x - 2, y), Dir::W, grid, true) { - x = x - 1; - } - } - x => shucks!("{}", x as char), - }, - b'>' => match grid[y][x + 1] { - b'.' => x = x + 1, - b'#' => (), - b'[' => { - if push((x + 1, y), Dir::E, grid, true) { - x = x + 1; - } - } - x => shucks!("{}", x as char), - }, - - b'^' => match grid[y - 1][x] { - b'.' => y = y - 1, - b'#' => (), - b']' => { - if push((x - 1, y - 1), Dir::N, grid, true) { - y = y - 1; - } - } - b'[' => { - if push((x, y - 1), Dir::N, grid, true) { - y = y - 1; - } - } - x => shucks!("{}", x as char), - }, - b'v' => match grid[y + 1][x] { - b'.' => y = y + 1, - b'#' => (), - b'[' => { - if push((x, y + 1), Dir::S, grid, true) { - y = y + 1; - } - } - b']' => { - if push((x - 1, y + 1), Dir::S, grid, true) { - y = y + 1; - } - } - x => shucks!("{}", x as char), - }, - _ => {} - } - } - // grid[y][x] = b'@'; - // for row in &*grid { - // println!("{}", row.p()); - // } - // grid[y][x] = b'.'; - (0..SIZE) - .flat_map(|y| (0..SIZE * 2).map(move |x| (x, y))) - .filter(|&(x, y)| grid[y][x] == b'[') - .map(|(x, y)| 100 * y + x) - .sum::<usize>() -} +const SIZE: usize = 141; #[no_mangle] pub unsafe fn run(i: &str) -> impl Display { let i = i.as_bytes(); - let bot = memchr::memchr(b'@', i).ψ(); - let (mut x, mut y) = (bot % (SIZE + 1), bot / (SIZE + 1)); - let grid = i[..(SIZE + 1) * SIZE] - .to_vec() - .leak() - .as_chunks_unchecked_mut::<{ SIZE + 1 }>(); + let j = memchr::memchr(b'S', i).ψ(); + let (x, y) = (j % (SIZE + 1), j / (SIZE + 1)); + let grid = i.to_vec().leak().as_chunks_unchecked_mut::<{ SIZE + 1 }>(); grid[y][x] = b'.'; - let i = &i[((SIZE + 1) * SIZE) + 1..]; - fn push((x, y): (usize, usize), dir: Dir, grid: &mut [[u8; SIZE + 1]]) -> bool { - match dir { - Dir::N => match grid[y - 1][x] { - b'.' => { - grid[y - 1][x] = b'O'; - grid[y][x] = b'.'; - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - b'O' => { - if push((x, y - 1), dir, grid) { - grid[y - 1][x] = b'O'; - grid[y][x] = b'.'; - return true; - } - } - b'#' => {} - x => shucks!("{}", x as char), - }, - Dir::E => match grid[y][x + 1] { - b'.' => { - grid[y][x + 1] = b'O'; - grid[y][x] = b'.'; - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - b'O' => { - if push((x + 1, y), dir, grid) { - grid[y][x + 1] = b'O'; - grid[y][x] = b'.'; - return true; - } - } - b'#' => {} - x => shucks!("{}", x as char), - }, - Dir::S => match grid[y + 1][x] { - b'.' => { - grid[y + 1][x] = b'O'; - grid[y][x] = b'.'; - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - b'O' => { - if push((x, y + 1), dir, grid) { - grid[y + 1][x] = b'O'; - grid[y][x] = b'.'; - return true; - } - } - b'#' => {} - x => shucks!("{}", x as char), - }, - Dir::W => match grid[y][x - 1] { - b'.' => { - grid[y][x - 1] = b'O'; - grid[y][x] = b'.'; - return true; - // swap(&mut grid[y - 1][x], &mut grid[y][x]), - } - b'O' => { - if push((x - 1, y), dir, grid) { - grid[y][x - 1] = b'O'; - grid[y][x] = b'.'; - return true; - } - } - b'#' => {} - x => shucks!("{}", x as char), - }, - } - false - } - for input in i { - match input { - b'<' => match grid[y][x - 1] { - b'.' => x = x - 1, - b'#' => (), - b'O' => { - if push((x - 1, y), Dir::W, grid) { - x = x - 1; - } - } - x => shucks!("{}", x as char), - }, - b'>' => match grid[y][x + 1] { - b'.' => x = x + 1, - b'#' => (), - b'O' => { - if push((x + 1, y), Dir::E, grid) { - x = x + 1; - } - } - x => shucks!("{}", x as char), - }, - - b'^' => match grid[y - 1][x] { - b'.' => y = y - 1, - b'#' => (), - b'O' => { - if push((x, y - 1), Dir::N, grid) { - y = y - 1; - } - } - x => shucks!("{}", x as char), - }, - b'v' => match grid[y + 1][x] { - b'.' => y = y + 1, - b'#' => (), - b'O' => { - if push((x, y + 1), Dir::S, grid) { - y = y + 1; - } - } - x => shucks!("{}", x as char), - }, - _ => {} - } - } - let mut sum = 0; - for (row, y) in grid.into_iter().ι::<u32>() { - for (col, x) in row.into_iter().ι::<u32>() { - if *col == b'O' { - sum += 100 * y + x - } - } - } + // let mut q = std::collections::BinaryHeap::with_capacity(1 << 10); + // let mut s = HashSet::with_capacity_and_hasher(1 << 16, rustc_hash::FxBuildHasher::default()); + // q.push(Reverse((0u64, ((x, y), Dir::E)))); + // while let Some(Reverse((c, n @ ((x, y), dir)))) = q.pop() { + // if grid[y][x] == b'E' { + // return c; + // } + // if !s.insert(n) { + // continue; + // } + // for (n, d) in [ + // ((dir + n.0, dir), 1), + // ((n.0, dir.turn_90()), 1000), + // ((n.0, dir.turn_90ccw()), 1000), + // ] + // .into_iter() + // .filter(|(((x, y), ..), _)| grid[*y][*x] != b'#') + // { + // if s.contains(&n) { + // continue; + // } + // q.push(Reverse((c + d, n))); + // } + // } - sum + let (path, _) = pathfinding::directed::astar::astar_bag( + &((x, y), Dir::E), + |&(p, dir)| { + let dir: Dir = dir; + [ + ((dir + p, dir), 1), + ((p, dir.turn_90()), 1000u64), + ((p, dir.turn_90ccw()), 1000u64), + ] + .into_iter() + .filter(|(((x, y), ..), _)| grid[*y][*x] != b'#') + }, + |_| 0, + |((x, y), ..)| grid[*y][*x] == b'E', + ) + .unwrap(); + path.into_iter() + .flat_map(|x| x.into_iter().map(|((x, y), _)| (x, y))) + .collect::<HashSet<_>>() + .len() } fn main() { @@ -476,7 +101,7 @@ fn main() { // }w // std::fs::write("src/inp.txt", s); #[allow(unused_unsafe)] - println!("{}", unsafe { p2(i) }); + println!("{}", unsafe { run(i) }); } #[bench] |