#!/usr/bin/env python3 import sys import os def dupe(c): if c == "#": return ["#", "#"] if c == "O": return ["[", "]"] if c == "@": return ["@", "."] if c == ".": return [".", "."] else: raise RuntimeException(f"Unknown char {c}") def parse(): G = [] moves = [] rob = None for l in sys.stdin: if l[0] == "#": row = [] for c in l.strip(): row += dupe(c) G.append(row) if l[0] in {">", "<", "^", "v"}: moves += [c for c in l.strip()] for i in range(len(G)): for j in range(len(G[0])): if G[i][j] == "@": rob = (i, j) return G, moves, rob def debug(msg): if os.getenv("DEBUG"): print(msg) def pprint(G): for row in G: debug("".join(row)) velocity = { "^": (-1, 0), ">": (0, 1), "v": (1, 0), "<": (0, -1), } def get(G, pos): if pos[0] < 0 or pos[0] > len(G) or pos[1] < 0 or pos[1] > len(G[0]): return None return G[pos[0]][pos[1]] def step(pos, move): dy, dx = velocity[move] return (pos[0] + dy, pos[1] + dx) def hasopen(G, move, rob): curr = step(rob, move) while get(G, curr): if get(G, curr) == ".": return True if get(G, curr) == "#": return False curr = step(curr, move) return False def move(G, move, rob): dy, dx = velocity[move] if not hasopen(G, move, rob): return rob # we have an open spot to shift into curr = rob cval = get(G, curr) while True: next = step(curr, move) nval = get(G, next) G[next[0]][next[1]] = cval cval = nval curr = next if nval == ".": break G[rob[0]][rob[1]] = "." return step(rob, move) def score(G): s = 0 for i in range(len(G)): for j in range(len(G[0])): if G[i][j] == "O": s += 100 * i + j return s if __name__ == '__main__': G, moves, rob = parse() pprint(G) for m in moves: debug(f"Move {m}:") rob = move(G, m, rob) pprint(G) debug("") print(score(G))