Quest 15: Definitely Not a Maze
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL
Link to participate: https://everybody.codes/
You must log in or # to comment.
Rust
use std::collections::{BTreeSet, HashMap}; use array2d::Array2D; use priority_queue::PriorityQueue; type Point = (i64, i64); pub fn solve_part_1(input: &str) -> String { let mut vertical_walls = Vec::<(Point, Point)>::new(); let mut horizontal_walls = Vec::<(Point, Point)>::new(); let dirs = [(0, -1), (1, 0), (0, 1), (-1, 0)]; let mut dir = 0; let (mut x, mut y) = (0, 0); let mut interesting_points_x = BTreeSet::new(); let mut interesting_points_y = BTreeSet::new(); for instr in input.split(",") { let dist = if let Some(dist) = instr.strip_prefix("L") { dir = (dir + 3) % 4; dist } else if let Some(dist) = instr.strip_prefix("R") { dir = (dir + 1) % 4; dist } else { panic!("unparseable instruction {instr}"); }; let dist = dist.parse::<i64>().unwrap() - 1; let (endx, endy) = (x + dirs[dir].0 * dist, y + dirs[dir].1 * dist); let insert_to_walls = match dirs[dir] { (_, 0) => &mut horizontal_walls, (0, _) => &mut vertical_walls, _ => panic!("unexpected direction"), }; let wall = ((x.min(endx), y.min(endy)), (x.max(endx), y.max(endy))); interesting_points_x.insert(wall.0.0 - 1); interesting_points_x.insert(wall.1.0 + 1); interesting_points_y.insert(wall.0.1 - 1); interesting_points_y.insert(wall.1.1 + 1); insert_to_walls.push(wall); x = endx + dirs[dir].0; y = endy + dirs[dir].1; } let (endx, endy) = (x, y); interesting_points_x.insert(endx); interesting_points_y.insert(endy); interesting_points_x.insert(0); interesting_points_y.insert(0); let x_lower_bound = *interesting_points_x.iter().min().unwrap() - 1; let x_upper_bound = *interesting_points_x.iter().max().unwrap() + 1; let y_lower_bound = *interesting_points_y.iter().min().unwrap() - 1; let y_upper_bound = *interesting_points_y.iter().max().unwrap() + 1; interesting_points_x.insert(x_lower_bound); interesting_points_x.insert(x_upper_bound); interesting_points_y.insert(y_lower_bound); interesting_points_y.insert(y_upper_bound); let mut interesting_points = Array2D::filled_with( (0, 0), interesting_points_x.len(), interesting_points_y.len(), ); let mut interesting_points_reverse = HashMap::new(); for (i, x) in interesting_points_x.iter().enumerate() { for (j, y) in interesting_points_y.iter().enumerate() { interesting_points[(i, j)] = (*x, *y); interesting_points_reverse.insert((*x, *y), (i, j)); } } let mut gscore = HashMap::<Point, i64>::new(); let mut queue = PriorityQueue::new(); queue.push((0, 0), 0); gscore.insert((0, 0), 0); while let Some(((x, y), _)) = queue.pop() { if (x, y) == (endx, endy) { return gscore[&(x, y)].to_string(); } let current_gscore = gscore[&(x, y)]; let (i, j) = interesting_points_reverse.get(&(x, y)).unwrap(); for (ni, nj) in [ (i + 1, *j), (i.wrapping_sub(1), *j), (*i, j + 1), (*i, j.wrapping_sub(1)), ] { if ni >= interesting_points.num_rows() || nj >= interesting_points.num_columns() { continue; } let (nx, ny) = interesting_points[(ni, nj)]; let mut intersects_with_a_wall = false; if nj == *j { let (leftx, rightx) = if nx > x { (x + 1, nx) } else { (nx, x - 1) }; intersects_with_a_wall |= horizontal_walls.iter().any(|(from, to)| { assert_eq!(from.1, to.1); from.1 == ny && (leftx <= from.0 && from.0 <= rightx || leftx <= to.0 && to.0 <= rightx) }); intersects_with_a_wall |= vertical_walls.iter().any(|(from, to)| { assert_eq!(from.0, to.0); (leftx <= from.0 && from.0 <= rightx) && (from.1 <= ny && ny <= to.1) }); } else { let (lefty, righty) = if ny > y { (y + 1, ny) } else { (ny, y - 1) }; intersects_with_a_wall |= vertical_walls.iter().any(|(from, to)| { assert_eq!(from.0, to.0); from.0 == nx && (lefty <= from.1 && from.1 <= righty || lefty <= to.1 && to.1 <= righty) }); intersects_with_a_wall |= horizontal_walls.iter().any(|(from, to)| { assert_eq!(from.1, to.1); (lefty <= from.1 && from.1 <= righty) && (from.0 <= nx && nx <= to.0) }); } if intersects_with_a_wall { continue; } let new_dist = current_gscore .wrapping_add_unsigned(nx.abs_diff(x)) .wrapping_add_unsigned(ny.abs_diff(y)); if new_dist < *gscore.get(&(nx, ny)).unwrap_or(&i64::MAX) { gscore.insert((nx, ny), new_dist); queue.push( (nx, ny), (-new_dist) .wrapping_sub_unsigned(nx.abs_diff(endx)) .wrapping_sub_unsigned(ny.abs_diff(ny)), ); } } } panic!("exit not found"); } pub fn solve_part_2(input: &str) -> String { solve_part_1(input) } pub fn solve_part_3(input: &str) -> String { solve_part_1(input) }

