import sys from pprint import pprint from copy import deepcopy def shift(map, dx, dy): swapped = True while swapped: swapped = False for y in range(max(0, -dy), len(map) - max(0, dy)): for x in range(max(0, -dx), len(map) - max(0, dx)): if map[y + dy][x + dx] == "." and map[y][x] == "O": map[y + dy][x + dx] = "O" map[y][x] = "." swapped = True def weigh(map): return sum((len(map) - y) * row.count("O") for (y, row) in enumerate(map)) CYCLES = 1_000_000_000 def main(): with open(sys.argv[1]) as f: map = [list(l) for l in f.read().strip().splitlines()] part1 = 0 shift(map, 0, -1) part1 = weigh(map) seen = {} history = [] for i in range(CYCLES): shift(map, 0, -1) if i == 0: pprint(map) shift(map, -1, 0) if i == 0: pprint(map) shift(map, 0, 1) if i == 0: pprint(map) shift(map, 1, 0) if i == 0: pprint(map) s = str(map) if s in seen: break seen[s] = i history.append(weigh(map)) j = seen[s] offset = (CYCLES - j) % (i + 1 - j) + j part2 = history[offset] print(part1, part2) main() # 98887 too low # 98898 too high # 103761 too high