From 1ceb67a7fd688f5fb40c8f6096393c94e5e679d5 Mon Sep 17 00:00:00 2001 From: felixm Date: Sat, 27 Jan 2024 00:21:07 -0500 Subject: [PATCH] Finish day 21 part 2 not super hands free but I take it. --- d21.py | 192 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 175 insertions(+), 17 deletions(-) diff --git a/d21.py b/d21.py index df7691f..4e8e311 100644 --- a/d21.py +++ b/d21.py @@ -1,7 +1,7 @@ from lib import * +import os -EXAMPLE = """ -........... +EXAMPLE = """........... .....###.#. .###.##..#. ..#.#...#.. @@ -14,13 +14,11 @@ EXAMPLE = """ ........... """ -def solve(i: Input, second=False): - res = 0 - g = i.grid2() +def solve(input: Input): + g = input.grid2() s = g.find('S')[0] g[s] = 'O' - # steps = 64 - steps = 26501365 + steps = 64 seen = set() for i in range(steps): os = tuple(g.find('O')) @@ -38,18 +36,178 @@ def solve(i: Input, second=False): 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))) - return - - print("Example 2:", solve(Input(EXAMPLE), True)) - return - - print("Solution 2:", solve(Input(DAY_INPUT), True)) - return + # 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()