def parse(file): map = [] for line in file: line = line.strip() if not line: break map.append(line) moves = "" for line in file: moves += line.strip().replace("<","<").replace(">",">") return map, moves def solve(file): map, moves = parse(file) map = [list(x) for x in map] for y,line in enumerate(map): if '@' in line: x = line.index('@') cur = x,y print(moves) for m in moves: next, ok = move(map, cur, m) cur = next print(cur) t = 0 for y,line in enumerate(map): for x,c in enumerate(line): if c == 'O': t += y*100 + x print("".join(line)) print(t) def solve2(file): map, moves = parse(file) map2 = [] for line in map: l2 = [] for c in line: if c == '#': c = '##' elif c == 'O': c = '[]' elif c == '.': c = '..' elif c == '@': c = '@.' l2.extend(c) map2.append(l2) map = map2 for y,line in enumerate(map): if '@' in line: x = line.index('@') cur = x,y #print(show(map), cur) #print(moves) for m in moves: #print(m) assert map[cur[1]][cur[0]] == '@' next, ok = move(map, cur, m) cur = next #print(cur) t = 0 for y,line in enumerate(map): for x,c in enumerate(line): if c == '[': t += y*100 + x print("".join(line)) print(t) def move(map, cur, m): if m == 'v': d = (0,1) if m == '<': d = (-1,0) if m == '>': d = (1,0) if m == '^': d = (0,-1) n = (cur[0]+d[0], cur[1]+d[1]) c = map[n[1]][n[0]] if c == 'O': _, ok = move(map, n, m) if not ok: return cur, False elif c in "[]": if m in '<>': _, ok = move(map, n, m) if not ok: return cur, False else: blocks = set() ok = canpush(map, n, d, blocks) if not ok: return cur, False #print(blocks) #print("before push\n", show(map)) for x,y in sorted(blocks, key=lambda a:( a[1]*-d[1],a[0])): map[y+d[1]][x+d[0]] = map[y][x] map[y][x] = '.' #print("after push\n", show(map)) elif c == '#': return cur, False map[n[1]][n[0]] = map[cur[1]][cur[0]] map[cur[1]][cur[0]] = '.' return n, True def show(map): return '\n'.join(''.join(x) for x in map) def canpush(map, cur, d, blocks): if cur in blocks: return True c = map[cur[1]][cur[0]] if c == '.': return True if c not in '[]': return False blocks.add(cur) nx, ny = (cur[0]+d[0], cur[1]+d[1]) if c == '[': blocks.add((cur[0]+1, cur[1])) nx2 = nx+1 else: blocks.add((cur[0]-1, cur[1])) nx2 = nx-1 return canpush(map, (nx,ny), d, blocks) and canpush(map, (nx2,ny), d, blocks) solve(open("sample1.in")) solve(open("sample2.in")) solve2(open('sample1.in')) solve(open("input")) solve2(open('input'))