|
| 1 | +from aocd import submit |
| 2 | +from aoc import * |
| 3 | +from collections import defaultdict |
| 4 | +from itertools import combinations |
| 5 | +from pprint import pprint |
| 6 | +from math import sqrt |
| 7 | + |
| 8 | + |
| 9 | +FILE = "20_test.txt" |
| 10 | +FILE = "20.txt" |
| 11 | + |
| 12 | + |
| 13 | +table = { |
| 14 | + 0: {0:0, 1:1, 2:2, 3:3, 'V':4, 'H':6}, |
| 15 | + 1: {0:1, 1:2, 2:3, 3:0, 'V':7, 'H':5}, |
| 16 | + 2: {0:2, 1:3, 2:0, 3:1, 'V':6, 'H':4}, |
| 17 | + 3: {0:3, 1:0, 2:1, 3:2, 'V':5, 'H':7}, |
| 18 | + 4: {0:4, 1:5, 2:6, 3:7, 'V':0, 'H':2}, |
| 19 | + 5: {0:5, 1:6, 2:7, 3:4, 'V':3, 'H':1}, |
| 20 | + 6: {0:6, 1:7, 2:4, 3:5, 'V':2, 'H':0}, |
| 21 | + 7: {0:7, 1:4, 2:5, 3:6, 'V':1, 'H':3}, |
| 22 | +} |
| 23 | + |
| 24 | + |
| 25 | +def get(tile, side, reverse=False): |
| 26 | + if side == "T": |
| 27 | + return list(reversed(tile[0])) if reverse else tile[0] |
| 28 | + elif side == "R": |
| 29 | + col = [x[-1] for x in tile] |
| 30 | + return list(reversed(col)) if reverse else col |
| 31 | + elif side == "B": |
| 32 | + return list(reversed(tile[-1])) if reverse else tile[-1] |
| 33 | + elif side == "L": |
| 34 | + col = [x[0] for x in tile] |
| 35 | + return list(reversed(col)) if reverse else col |
| 36 | + |
| 37 | + |
| 38 | +def get_transform(side: str, side2: str, reverse: bool): |
| 39 | + numa = {"T": 0, "R": 1, "B": 2, "L": 3} |
| 40 | + numb = {"T": 2, "R": 1, "B": 0, "L": 3} |
| 41 | + rot = (numa[side] + numb[side2]) % 4 |
| 42 | + flip = 0 |
| 43 | + if not reverse: |
| 44 | + if (side2 == "B" and side in ["B", "L"]) or (side2 == "T" and side in ["T", "R"]): |
| 45 | + flip = "V" |
| 46 | + elif (side2 == "L" and side in ["B", "L"]) or ( |
| 47 | + side2 == "R" and side in ["T", "R"] |
| 48 | + ): |
| 49 | + flip = "H" |
| 50 | + else: |
| 51 | + if (side2 == "T" and side in ["B", "L"]) or (side2 == "B" and side in ["T", "R"]): |
| 52 | + flip = "V" |
| 53 | + elif (side2 == "R" and side in ["B", "L"]) or ( |
| 54 | + side2 == "L" and side in ["T", "R"] |
| 55 | + ): |
| 56 | + flip = "H" |
| 57 | + return flip, rot |
| 58 | + |
| 59 | + |
| 60 | +def reverse_transform(transform: tuple): |
| 61 | + # This is weid |
| 62 | + return transform[0], transform[1] |
| 63 | + return transform[0], (4 - transform[1]) % 4 |
| 64 | + |
| 65 | + |
| 66 | +def find_neig(tiles): |
| 67 | + neig = defaultdict(dict) # id -> side -> (ID, transf) |
| 68 | + for a, b in combinations(tiles, 2): |
| 69 | + ma = tiles[a] |
| 70 | + mb = tiles[b] |
| 71 | + options = ("T", "R", "B", "L") |
| 72 | + for oa in options: |
| 73 | + for ob in options: |
| 74 | + for r in (False, True): |
| 75 | + if get(ma, oa) == get(mb, ob, r): |
| 76 | + if (a,b) in [(3673,3389), (3389,3673)]: |
| 77 | + breakpoint() |
| 78 | + transform = get_transform(oa, ob, r) |
| 79 | + neig[a][oa] = (b, transform) |
| 80 | + transform = get_transform(ob, oa, r) |
| 81 | + neig[b][ob] = (a, transform) |
| 82 | + return neig |
| 83 | + |
| 84 | + |
| 85 | +def apply_tran(transform, side): |
| 86 | + a = ["B", "L", "T", "R"] |
| 87 | + try: |
| 88 | + index = a.index(side) |
| 89 | + except ValueError: |
| 90 | + breakpoint() |
| 91 | + rotated_index = (index - transform[1]) % 4 |
| 92 | + b, l, t, r = "B", "L", "T", "R" |
| 93 | + if transform[0] == "V": |
| 94 | + l, r = "R", "L" |
| 95 | + elif transform[0] == "H": |
| 96 | + t, b = "B", "T" |
| 97 | + return {0: b, 1: l, 2: t, 3: r}[rotated_index] |
| 98 | + |
| 99 | +def sum_tran(tran1, tran2): |
| 100 | + flip = 0 |
| 101 | + rot = tran1[1] + tran2[1] |
| 102 | + if tran1[0] == 0 and tran2[0] != 0: |
| 103 | + flip = tran2[0] |
| 104 | + elif tran1[0] != 0 and tran2[0] == 0: |
| 105 | + flip = tran1[0] |
| 106 | + elif tran1[0] == 'V': |
| 107 | + if tran2[0] == 'V': |
| 108 | + flip = 0 |
| 109 | + elif tran2[0] == 'H': |
| 110 | + flip = 0 |
| 111 | + rot += 2 |
| 112 | + elif tran1[0] == 'H': |
| 113 | + if tran2[0] == 'V': |
| 114 | + flip = 0 |
| 115 | + rot += 2 |
| 116 | + elif tran2[0] == 'H': |
| 117 | + flip = 0 |
| 118 | + return flip, rot % 4 |
| 119 | + |
| 120 | + |
| 121 | +def apply_tran_glob(global_, transform, side): |
| 122 | + ret = apply_tran(global_, apply_tran(transform, side)) |
| 123 | + # print(ret) |
| 124 | + return ret |
| 125 | + |
| 126 | + |
| 127 | +def create_map(neig): |
| 128 | + siz = int(sqrt(len(neig))) |
| 129 | + siz_ind = siz - 1 |
| 130 | + m = [[(None, (0, 0))] * siz for i in range(siz)] |
| 131 | + # pprint(m) |
| 132 | + |
| 133 | + # corners = [n for n, v in neig.items() if len(v) == 2] |
| 134 | + # edges = [n for n, v in neig.items() if len(v) == 3] |
| 135 | + # inside = [n for n, v in neig.items() if len(v) == 4] |
| 136 | + |
| 137 | + row = 0 |
| 138 | + col = 0 |
| 139 | + edge = [0, siz_ind] |
| 140 | + |
| 141 | + # This was found by hand in the neig dictionary |
| 142 | + # You just need to find the upper left corner |
| 143 | + # The set the transformation of everything |
| 144 | + # global_transform = (0, 2) |
| 145 | + m[row][col] = (3677, (0, 2)) |
| 146 | + while True: |
| 147 | + col += 1 |
| 148 | + if col == siz: |
| 149 | + col = 0 |
| 150 | + row += 1 |
| 151 | + if row == siz: |
| 152 | + break |
| 153 | + if col != 0: |
| 154 | + try: |
| 155 | + left_on_map = m[row][col - 1] |
| 156 | + neighbour_info = neig[left_on_map[0]] |
| 157 | + side = apply_tran(left_on_map[1], "R") |
| 158 | + nex = neighbour_info[side] # There would be R, but we need to transform it |
| 159 | + except KeyError as err: |
| 160 | + print(err) |
| 161 | + breakpoint() |
| 162 | + m[row][col] = nex[0], sum_tran(m[row][col - 1][1], nex[1]) |
| 163 | + else: |
| 164 | + nex = neig[ |
| 165 | + m[row - 1][col][0] |
| 166 | + ][ # There would be B, but we need to transform it |
| 167 | + apply_tran(m[row - 1][col][1], "B") |
| 168 | + ] |
| 169 | + # if row==1 and col==0: |
| 170 | + # breakpoint() |
| 171 | + m[row][col] = nex[0], sum_tran(m[row - 1][col][1], nex[1]) |
| 172 | + return m |
| 173 | + |
| 174 | + |
| 175 | +def main(): |
| 176 | + inp = file(FILE) |
| 177 | + inp = inp.split("\n\n") |
| 178 | + tiles = {} |
| 179 | + for i in inp: |
| 180 | + i = i.split("\n") |
| 181 | + number = int(i[0][5:-1]) |
| 182 | + tiles[number] = list(map(lambda x: list(x.rstrip()), i[1:])) |
| 183 | + neig = find_neig(tiles) |
| 184 | + pprint(neig) |
| 185 | + return |
| 186 | + m = create_map(neig) |
| 187 | + pprint(m) |
| 188 | + # print(len(neig)) |
| 189 | + # print(sum(1 for k, v in neig.items() if len(v) == 3)) |
| 190 | + out = 0 |
| 191 | + print(out) |
| 192 | + return |
| 193 | + input() |
| 194 | + print("submitting") |
| 195 | + submit(out) |
| 196 | + |
| 197 | + |
| 198 | +main() |
0 commit comments