from lib import * import os EXAMPLE = """........... .....###.#. .###.##..#. ..#.#...#.. ....#.#.... .##..S####. .##..#...#. .......##.. .##.#.####. .##..##.##. ........... """ def solve(input: Input): g = input.grid2() s = g.find('S')[0] g[s] = 'O' steps = 64 seen = set() for i in range(steps): os = tuple(g.find('O')) if os in seen: seen.add(os) print(f"SEEN {i}") break for o in os: g[o] = '.' for o in os: for nb in g.neighbors_ort(o): if not g[nb] == "#": g[nb] = 'O' return len(g.find('O')) def plot(xs, poss): os.system("clear") rcoords = [x[0] for x in xs] ccoords = [x[1] for x in xs] rmin = min(rcoords) rmax = max(rcoords) cmin = min(ccoords) cmax = max(ccoords) for r in range(rmin, rmax + 1): s = "" for c in range(cmin, cmax + 1): if (r, c) in xs: s += "#" elif (r, c) in poss: s += "O" else: s += " " print(s) def move(xs, roff, coff): rcoords = [x[0] for x in xs] ccoords = [x[1] for x in xs] rd = max(rcoords) - min(rcoords) + 3 cd = max(ccoords) - min(ccoords) + 3 newxs = [(x[0] + roff * rd, x[1] + coff * cd) for x in xs] return set(newxs) def iter(poss, stones): nposs = set() for r, c in poss: for ro, co in [(-1, 0), (0, 1), (1, 0), (0, -1)]: nr, nc = r + ro, c + co if not (nr, nc) in stones: nposs.add((nr, nc)) return nposs def get_bounds(size, ro, co): rmin = size * ro rmax = size + size * ro cmin = size * co cmax = size + size * co return rmin, rmax, cmin, cmax def count(poss, size, ro, co): rmin, rmax, cmin, cmax = get_bounds(size, ro, co) res = 0 for (r, c) in poss: if (rmin <= r < rmax) and (cmin <= c < cmax): res += 1 return res def solve2(ip: Input): base_stones = set() poss = set() size = len(ip.lines()) assert size == len(ip.lines()[0]) for r, row in enumerate(ip.lines()): for c, col in enumerate(row): if col == "#": base_stones.add((r, c)) if col == "S": poss.add((r, c)) stones = base_stones.copy() off = 19 // 2 for ro in range(-off, off + 1): for co in range(-off, off + 1): stones |= move(base_stones, ro, co) hists = {} for ro in range(-off, off + 1): for co in range(-off, off + 1): hists[(ro, co)] = [] #for step in range(590): # if step % 1 == 0: # sanity = 0 # os.system("clear") # for ro in range(-off, off + 1): # s = "" # for co in range(-off, off + 1): # v = count(poss, size, ro, co) # sanity += v # if v > 0: # hists[(ro, co)].append(v) # s += f"{v:6}" # else: # s += 6 * " " # print(s) # # input(f"{step=} {step//size=} {len(poss)} ({sanity}) cont...") # print(f"{step=} {step//size=} {len(poss)} ({sanity}) cont...") # poss = iter(poss, stones) # 66, 197, 328 459 # cycle starts # 196, 327, 458, 589 # targets def calc(len, xs): if len % 2 == 0: return len // 2 * sum(xs) else: return len // 2 * sum(xs) + xs[0] target = 196 target = 327 target = 458 target = 589 target = 26501365 # for target in [196, 327, 458, 589]: print() print(target) cycle = 131 c = target // cycle d = (target // cycle) * 2 + 1 - 2 print(f"{c=} {d=}") res = 0 res += 5698 + 5703 + 5709 + 5704 # corners res += c * 964 + c * 984 + c * 968 + c * 978 # outer res += (c - 1) * 6637 + (c - 1) * 6624 + (c - 1) * 6643 + (c - 1) * 6619 # inner for i in range(d, 0, -2): res += calc(i, [7623, 7558]) for i in range(d - 2, 0, -2): res += calc(i, [7623, 7558]) print(res) return res # def get_till(xs, ts): # ts = ts[:] # r = [] # for x in xs: # r.append(x) # if x in ts: # ts.remove(x) # if ts == []: # break # return r osz_values = hists[(0, 4)][-2:] # se = get_till(hists[0, 5], osz_values) # sn = get_till(hists[-5, 0], osz_values) # ss = get_till(hists[5, 0], osz_values) # sw = get_till(hists[0, -5], osz_values) # print(se) # print(sn) # print(sw) # print(ss) # sne = get_till(hists[-5, 5], osz_values) # sse = get_till(hists[5, 5], osz_values) # ssw = get_till(hists[5, -5], osz_values) # snw = get_till(hists[-5, -5], osz_values) # print(sne) # print(sse) # print(ssw) # print(snw) # for i in range(3, 10): # print(hists[(0, i)][:5]) # print(hists[(0, -i)][:5]) def main(): DAY_INPUT = "i21.txt" # print("Example 1:", solve(Input(EXAMPLE))) # print("Solution 1:", solve(Input(DAY_INPUT))) # print("Example 2:", solve2(Input(EXAMPLE))) print("Solution 2:", solve2(Input(DAY_INPUT))) if __name__ == "__main__": main()