Day 15: Warehouse Woes
Megathread guidelines
- 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
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/6637268
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Nim
Very fiddly solution with lots of debugging required.
Code
type Vec2 = tuple[x,y: int] Box = array[2, Vec2] Dir = enum U = "^" R = ">" D = "v" L = "<" proc convertPart2(grid: seq[string]): seq[string] = for y in 0..grid.high: result.add "" for x in 0..grid[0].high: result[^1] &= ( if grid[y][x] == 'O': "[]" elif grid[y][x] == '#': "##" else: "..") proc shiftLeft(grid: var seq[string], col: int, range: HSlice[int,int]) = for i in range.a ..< range.b: grid[col][i] = grid[col][i+1] grid[col][range.b] = '.' proc shiftRight(grid: var seq[string], col: int, range: HSlice[int,int]) = for i in countDown(range.b, range.a+1): grid[col][i] = grid[col][i-1] grid[col][range.a] = '.' proc box(pos: Vec2, grid: seq[string]): array[2, Vec2] = if grid[pos.y][pos.x] == '[': [pos, (pos.x+1, pos.y)] else: [(pos.x-1, pos.y), pos] proc step(grid: var seq[string], bot: var Vec2, dir: Dir) = var (x, y) = bot case dir of U: while (dec y; grid[y][x] != '#' and grid[y][x] != '.'): discard if grid[y][x] == '#': return if grid[bot.y-1][bot.x] == 'O': swap(grid[bot.y-1][bot.x], grid[y][x]) dec bot.y of R: while (inc x; grid[y][x] != '#' and grid[y][x] != '.'): discard if grid[y][x] == '#': return if grid[bot.y][bot.x+1] == 'O': swap(grid[bot.y][bot.x+1], grid[y][x]) inc bot.x of L: while (dec x; grid[y][x] != '#' and grid[y][x] != '.'): discard if grid[y][x] == '#': return if grid[bot.y][bot.x-1] == 'O': swap(grid[bot.y][bot.x-1], grid[y][x]) dec bot.x of D: while (inc y; grid[y][x] != '#' and grid[y][x] != '.'): discard if grid[y][x] == '#': return if grid[bot.y+1][bot.x] == 'O': swap(grid[bot.y+1][bot.x], grid[y][x]) inc bot.y proc canMoveVert(box: Box, grid: seq[string], boxes: var HashSet[Box], dy: int): bool = boxes.incl box var left, right = false let (lbox, rbox) = (box[0], box[1]) let lbigBox = box((lbox.x, lbox.y+dy), grid) let rbigBox = box((rbox.x, lbox.y+dy), grid) if grid[lbox.y+dy][lbox.x] == '#' or grid[rbox.y+dy][rbox.x] == '#': return false elif grid[lbox.y+dy][lbox.x] == '.': left = true else: left = canMoveVert(box((lbox.x,lbox.y+dy), grid), grid, boxes, dy) if grid[rbox.y+dy][rbox.x] == '.': right = true elif lbigBox == rbigBox: right = left else: right = canMoveVert(box((rbox.x, rbox.y+dy), grid), grid, boxes, dy) left and right proc moveBoxes(grid: var seq[string], boxes: var HashSet[Box], d: Vec2) = for box in boxes: grid[box[0].y][box[0].x] = '.' grid[box[1].y][box[1].x] = '.' for box in boxes: grid[box[0].y+d.y][box[0].x+d.x] = '[' grid[box[1].y+d.y][box[1].x+d.x] = ']' boxes.clear() proc step2(grid: var seq[string], bot: var Vec2, dir: Dir) = case dir of U: if grid[bot.y-1][bot.x] == '#': return if grid[bot.y-1][bot.x] == '.': dec bot.y else: var boxes: HashSet[Box] if canMoveVert(box((x:bot.x, y:bot.y-1), grid), grid, boxes, -1): grid.moveBoxes(boxes, (0, -1)) dec bot.y of R: var (x, y) = bot while (inc x; grid[y][x] != '#' and grid[y][x] != '.'): discard if grid[y][x] == '#': return if grid[bot.y][bot.x+1] == '[': grid.shiftRight(bot.y, bot.x+1..x) inc bot.x of L: var (x, y) = bot while (dec x; grid[y][x] != '#' and grid[y][x] != '.'): discard if grid[y][x] == '#': return if grid[bot.y][bot.x-1] == ']': grid.shiftLeft(bot.y, x..bot.x-1) dec bot.x of D: if grid[bot.y+1][bot.x] == '#': return if grid[bot.y+1][bot.x] == '.': inc bot.y else: var boxes: HashSet[Box] if canMoveVert(box((x:bot.x, y:bot.y+1), grid), grid, boxes, 1): grid.moveBoxes(boxes, (0, 1)) inc bot.y proc solve(input: string): AOCSolution[int, int] = let chunks = input.split("\n\n") var grid = chunks[0].splitLines() let movements = chunks[1].splitLines().join().join() var robot: Vec2 for y in 0..grid.high: for x in 0..grid[0].high: if grid[y][x] == '@': grid[y][x] = '.' robot = (x,y) block p1: var grid = grid var robot = robot for m in movements: let dir = parseEnum[Dir]($m) step(grid, robot, dir) for y in 0..grid.high: for x in 0..grid[0].high: if grid[y][x] == 'O': result.part1 += 100 * y + x block p2: var grid = grid.convertPart2() var robot = (robot.x*2, robot.y) for m in movements: let dir = parseEnum[Dir]($m) step2(grid, robot, dir) #grid.inspect(robot) for y in 0..grid.high: for x in 0..grid[0].high: if grid[y][x] == '[': result.part2 += 100 * y + x
Codeberg Repo