🍊 | |||||
🦁 |
""" | |||||
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()) |