| 🍊 | |||||
| 🦁 |
| """ | |||||
| 5000 steps, he can reach 16733044 garden plots. | |||||
| 26501365? | |||||
| """ | |||||
| text = open(0).read() | text = open(0).read() | ||||
| graph = { | graph = { | ||||
| complex(x, y): val | complex(x, y): val | ||||
| for y, row in enumerate(text.splitlines()) | for y, row in enumerate(text.splitlines()) | ||||
| for x, val in enumerate(row) | for x, val in enumerate(row) | ||||
| } | } | ||||
| width = max(int(p.real) for p in graph) + 1 | width = max(int(p.real) for p in graph) + 1 | ||||
| height = max(int(p.imag) for p in graph) + 1 | height = max(int(p.imag) for p in graph) + 1 | ||||
| block = lambda p: complex(p.real // width, p.imag // height) | |||||
| wrap = lambda p: complex(p.real % width, p.imag % height) | wrap = lambda p: complex(p.real % width, p.imag % height) | ||||
| start, = (k for k, v in graph.items() if v == 'S') | start, = (k for k, v in graph.items() if v == 'S') | ||||
| state = {(False, start)} | |||||
| seen = state.copy() | |||||
| for step in range(100): | |||||
| seen = [set(), set()] | |||||
| state = {start} | |||||
| bops = set() | |||||
| for step in range(130): | |||||
| twinkle = seen[step % 2] | |||||
| twinkle |= state | |||||
| if step == 64: | |||||
| print(len(twinkle)) # ans1 | |||||
| state = { | state = { | ||||
| (not age, p + s) | |||||
| for age, p in state | |||||
| p + s | |||||
| for p in state | |||||
| for s in [1, -1, 1j, -1j] | for s in [1, -1, 1j, -1j] | ||||
| if graph[wrap(p + s)] in {'.', 'S'} | if graph[wrap(p + s)] in {'.', 'S'} | ||||
| if (not age, p + s) not in seen | |||||
| if p + s not in twinkle | |||||
| } | } | ||||
| seen |= state | |||||
| if step == 64: | |||||
| ans1 = sum(not age for age, pos in seen if pos in graph) | |||||
| print(ans1) | |||||
| def move(old, seen, parents, special_rules): | |||||
| steps = [1, -1, 1j, -1j] | |||||
| for step in special_rules.get(graph[old], steps): | |||||
| new = old + step | |||||
| parents.setdefault(new, set()).add(old) | |||||
| if new in graph and new not in seen: | |||||
| yield new | |||||
| def bfs(start, special_rules): | |||||
| parents = {} | |||||
| state = {start} | |||||
| seen = state.copy() | |||||
| while state: | |||||
| state = {new for old in state for new in move(old, seen, parents, special_rules)} | |||||
| seen |= state | |||||
| return parents | |||||
| def segmentize(dense): | |||||
| sparse = {} | |||||
| for i, js in dense.items(): | |||||
| for j in js: | |||||
| n = 1 | |||||
| k = i | |||||
| while len(dense[j] - {k}) == 1: | |||||
| n += 1 | |||||
| k, [j] = j, dense[j] - {k} | |||||
| sparse.setdefault(i, set()).add((j, n)) | |||||
| return sparse | |||||
| def recurse(pos, parents, path=set(), n=0): | |||||
| if pos == start: | |||||
| yield n | |||||
| else: | |||||
| for parent, cost in parents[pos]: | |||||
| if parent not in path: | |||||
| yield from recurse(parent, parents, path | {pos}, n + cost) | |||||
| def solve(special_rules={}): | |||||
| dense = bfs(start, special_rules) | |||||
| sparse = segmentize(dense) | |||||
| return len(list(recurse(end, sparse))) | |||||
| text = open(0).read() | |||||
| graph = { | |||||
| complex(x, y): val | |||||
| for y, row in enumerate(text.splitlines()) | |||||
| for x, val in enumerate(row) | |||||
| if val != '#' | |||||
| } | |||||
| start = min(graph, key=lambda p: (p.imag, p.real)) | |||||
| end = max(graph, key=lambda p: (p.imag, p.real)) | |||||
| print(solve({'<': [-1], '^': [-1j], 'v': [1j], '>': [1]})) | |||||
| print(solve()) |