You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.2 KiB
112 lines
3.2 KiB
#!/usr/bin/env python3
|
|
|
|
import sys, os, time
|
|
from copy import deepcopy
|
|
|
|
|
|
def show(m):
|
|
for line in m:
|
|
sys.stdout.write("\r"+''.join(line)+'\n')
|
|
sys.stdout.flush()
|
|
time.sleep(0.2)
|
|
|
|
|
|
def gps(x, y):
|
|
return 100*y + x
|
|
|
|
|
|
def move_stone(m, x, y, move):
|
|
dir = {'^': (0,-1), '>': (1,0), 'v': (0,1), '<': (-1,0)}
|
|
nx, ny = x+dir[move][0], y+dir[move][1]
|
|
if m[ny][nx] == '#': return
|
|
if m[ny][nx] == 'O': move_stone(m, nx, ny, move)
|
|
if m[ny][nx] == '.':
|
|
m[ny][nx] = 'O'
|
|
m[y][x] = '.'
|
|
return
|
|
|
|
|
|
def move_box_h(m, x, y, move):
|
|
dir = {'^': (0,-1), '>': (1,0), 'v': (0,1), '<': (-1,0)}
|
|
nx, ny = x+dir[move][0], y
|
|
sym = m[y][x]
|
|
if m[ny][nx] == '#': return
|
|
if m[ny][nx] in ['[', ']']: move_box_h(m, nx, ny, move)
|
|
if m[ny][nx] == '.':
|
|
m[ny][nx] = sym
|
|
m[y][x] = '.'
|
|
return
|
|
|
|
|
|
def move_box_v(m, x, y, move):
|
|
dir = {'^': (0,-1), '>': (1,0), 'v': (0,1), '<': (-1,0)}
|
|
if m[y][x] == '[': x1, x2 = x, x+1
|
|
else: x1, x2 = x-1, x
|
|
nx1, nx2, ny = x1+dir[move][0], x2+dir[move][0], y+dir[move][1]
|
|
if m[ny][nx1] == '#' or m[ny][nx2] == '#': return m
|
|
if m[ny][nx1] == ']' and m[ny][nx2] == '[':
|
|
mp = deepcopy(m)
|
|
mp = move_box_v(mp, nx1, ny, move)
|
|
mp = move_box_v(mp, nx2, ny, move)
|
|
if mp[ny][nx1] == '.' and mp[ny][nx2] == '.': m = deepcopy(mp)
|
|
elif m[ny][nx1] in ['[', ']']: m = move_box_v(m, nx1, ny, move)
|
|
elif m[ny][nx2] in ['[', ']']: m = move_box_v(m, nx2, ny, move)
|
|
if m[ny][nx1] == '.' and m[ny][nx2] == '.':
|
|
m[ny][nx1] = '['
|
|
m[ny][nx2] = ']'
|
|
m[y][x1] = '.'
|
|
m[y][x2] = '.'
|
|
return m
|
|
return m
|
|
|
|
|
|
def move(m, x, y, move):
|
|
dir = {'^': (0,-1), '>': (1,0), 'v': (0,1), '<': (-1,0)}
|
|
nx, ny = x+dir[move][0], y+dir[move][1]
|
|
if m[ny][nx] == '#': return m, x, y
|
|
if m[ny][nx] == 'O': move_stone(m, nx, ny, move)
|
|
if m[ny][nx] in ['[',']'] and move in ['v', '^']:
|
|
m = move_box_v(m, nx, ny, move)
|
|
elif m[ny][nx] in ['[',']'] and move in ['<', '>']:
|
|
move_box_h(m, nx, ny, move)
|
|
if m[ny][nx] == '.':
|
|
m[ny][nx] = '@'
|
|
m[y][x] = '.'
|
|
return m, nx, ny
|
|
else: return m, x, y
|
|
|
|
|
|
if __name__ == '__main__':
|
|
mp, moves = open(sys.argv[1]).read().split('\n\n')
|
|
mp = [list(y.strip('\n')) for y in mp.split('\n')]
|
|
moves = list(''.join([m.strip('\n') for m in moves]))
|
|
wm = []
|
|
for y, l in enumerate(mp):
|
|
line = []
|
|
for x, r in enumerate(l):
|
|
if r == '#': line += ['#', '#']
|
|
elif r == '.': line += ['.', '.']
|
|
elif r == 'O': line += ['[', ']']
|
|
elif r == '@':
|
|
wrx, wry = len(line), y
|
|
line += ['@', '.']
|
|
rx, ry = x, y
|
|
wm.append(line)
|
|
for mov in moves:
|
|
mp, rx, ry = move(mp, rx, ry, mov)
|
|
wm, wrx, wry = move(wm, wrx, wry, mov)
|
|
|
|
# challenge 1
|
|
res1 = 0
|
|
for y, m in enumerate(mp):
|
|
for x, t in enumerate(m):
|
|
if t == 'O': res1 += gps(x, y)
|
|
print(f"challenge 1:\n{res1}\n")
|
|
|
|
# challenge 2
|
|
res2 = 0
|
|
for y, m in enumerate(wm):
|
|
for x, t in enumerate(m):
|
|
if t == '[': res2 += gps(x, y)
|
|
print(f"challenge 2:\n{res2}")
|
|
|
|
|