aoc

Advent of Code Solutions
git clone git://git.alexkarle.com.com/aoc
Log | Files | Refs | README | LICENSE

2.py (2224B) [raw]


      1 #!/usr/bin/env python3
      2 import sys
      3 import os
      4 
      5 def dupe(c):
      6     if c == "#":
      7         return ["#", "#"]
      8     if c == "O":
      9         return ["[", "]"]
     10     if c == "@":
     11         return ["@", "."]
     12     if c == ".":
     13         return [".", "."]
     14     else:
     15         raise RuntimeException(f"Unknown char {c}")
     16 
     17 def parse():
     18     G = []
     19     moves = []
     20     rob = None
     21     for l in sys.stdin:
     22         if l[0] == "#":
     23             row = []
     24             for c in l.strip():
     25                 row += dupe(c)
     26             G.append(row)
     27         if l[0] in {">", "<", "^", "v"}:
     28             moves += [c for c in l.strip()]
     29     for i in range(len(G)):
     30         for j in range(len(G[0])):
     31             if G[i][j] == "@":
     32                 rob = (i, j)
     33     return G, moves, rob
     34 
     35 def debug(msg):
     36     if os.getenv("DEBUG"):
     37         print(msg)
     38 
     39 def pprint(G):
     40     for row in G:
     41          debug("".join(row))
     42 
     43 velocity = {
     44     "^": (-1, 0),
     45     ">": (0, 1),
     46     "v": (1, 0),
     47     "<": (0, -1),
     48 }
     49 
     50 def get(G, pos):
     51     if pos[0] < 0 or pos[0] > len(G) or pos[1] < 0 or pos[1] > len(G[0]):
     52         return None
     53     return G[pos[0]][pos[1]]
     54 
     55 def step(pos, move):
     56     dy, dx = velocity[move]
     57     return (pos[0] + dy, pos[1] + dx)
     58 
     59 def hasopen(G, move, rob):
     60     curr = step(rob, move)
     61     while get(G, curr):
     62         if get(G, curr) == ".":
     63             return True
     64         if get(G, curr) == "#":
     65             return False
     66         curr = step(curr, move)
     67     return False
     68 
     69 def move(G, move, rob):
     70     dy, dx = velocity[move]
     71     if not hasopen(G, move, rob):
     72         return rob
     73 
     74     # we have an open spot to shift into
     75     curr = rob
     76     cval = get(G, curr)
     77     while True:
     78         next = step(curr, move)
     79         nval = get(G, next)
     80         G[next[0]][next[1]] = cval
     81         cval = nval
     82         curr = next
     83         if nval == ".":
     84             break
     85     G[rob[0]][rob[1]] = "."
     86     return step(rob, move)
     87 
     88 def score(G):
     89     s = 0
     90     for i in range(len(G)):
     91         for j in range(len(G[0])):
     92             if G[i][j] == "O":
     93                 s += 100 * i + j
     94     return s
     95 
     96 if __name__ == '__main__':
     97     G, moves, rob = parse()
     98     pprint(G)
     99     for m in moves:
    100         debug(f"Move {m}:")
    101         rob = move(G, m, rob)
    102         pprint(G)
    103         debug("")
    104     print(score(G))