|
1 |
| -import re |
2 |
| -from collections import defaultdict, Counter, deque |
3 |
| -from itertools import permutations, combinations, product, combinations_with_replacement |
4 |
| -from queue import PriorityQueue |
| 1 | +from collections import deque |
5 | 2 |
|
6 | 3 | lines = open(0).read().splitlines()
|
7 | 4 | Y, X = len(lines), len(lines[0])
|
8 |
| -S = Y |
9 |
| -assert Y == X |
10 | 5 | dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
|
11 |
| -dirs_diag = [(1, 1), (1, -1), (-1, 1), (-1, -1)] |
12 | 6 |
|
13 | 7 | q = deque()
|
14 |
| - |
15 | 8 | dists = {}
|
| 9 | + |
16 | 10 | for y, line in enumerate(lines):
|
17 | 11 | if 'S' in line:
|
18 | 12 | q.append((y, line.index('S')))
|
19 |
| - dists[(y, line.index('S'))] = 0 |
20 | 13 |
|
21 |
| -s = 0 |
22 |
| -# for i in range(64): |
23 |
| -# nextq = deque() |
24 |
| -visited = set() |
25 |
| -nextq = deque() |
26 | 14 | while q:
|
27 | 15 | y, x = q.popleft()
|
28 | 16 | for dy, dx in dirs:
|
29 | 17 | ya, xa = y + dy, x + dx
|
30 |
| - in_inner = 0 <= ya < Y and 0 <= xa < X |
31 |
| - in_outer = -Y*2 <= ya < Y*3 and -X*2 <= xa < X*3 |
32 |
| - if in_outer and lines[ya%Y][xa%X] != '#': # and (ya, xa) not in visited: |
33 |
| - # ok = True |
34 |
| - # if (ya, xa) in dists: |
35 |
| - # di, do = dists[(ya, xa)] |
36 |
| - # ok = dist_outer+(not in_inner) < do |
37 |
| - # if ok: |
38 |
| - if (ya, xa) not in visited: |
39 |
| - # dists[(ya, xa)] = (dist_inner + in_inner, dist_outer + (not in_inner)) |
40 |
| - dists[(ya, xa)] = dists[(y, x)]+1 |
41 |
| - if in_inner: |
42 |
| - q.append((ya, xa)) |
43 |
| - else: |
44 |
| - nextq.append((ya, xa)) |
45 |
| - visited.add((ya, xa)) |
46 |
| - if not q: |
47 |
| - q = nextq |
48 |
| - |
49 |
| - # q = nextq |
50 |
| - |
51 |
| -# print(dists) |
52 |
| -# print(len(dists)) |
53 |
| - |
54 |
| -for y in range(-Y*2, Y*3): |
55 |
| - if y % Y == 0: |
56 |
| - print('-' * (15*S)) |
57 |
| - # for x in range(-X*2, X*3): |
58 |
| - for x in range(0, X): |
59 |
| - v = '#' |
60 |
| - if (y, x) in dists: |
61 |
| - dist = dists[(y, x)] |
62 |
| - # yadd = 0 if (y == y%Y) else (Y if (y > y%Y) else -Y) |
63 |
| - # xadd = 0 if (x == x%X) else (X if (x > x%X) else -X) |
64 |
| - # veryouter_dist = dists[(y+yadd, x+xadd)] |
65 |
| - # repeat = veryouter_dist - dist |
66 |
| - # repeat = do |
67 |
| - # v = str('Y' if dist % 2== 1 else ' ') |
68 |
| - v = str(dist) |
69 |
| - v = v.replace("(", "").replace(",", "").replace(")", "").replace(" ", "-") |
70 |
| - print(end=f"{v:3}" + ('| ' if x in (-X-1, -1, X-1, 2*X-1) else '')) |
71 |
| - print() |
72 |
| - |
73 |
| - |
74 |
| -# for direction in dirs: |
75 |
| -# for y in range(-Y, Y*2): |
76 |
| -# for x in range(-X, X*2): |
77 |
| -# if (y, x) in dists: |
78 |
| -# in_inner = 0 <= y < Y and 0 <= x < X |
79 |
| -# dist = dists[(y, x)] |
80 |
| -# # inner_di, _ = dists[(y%Y, x%X)] |
81 |
| -# if in_inner: |
82 |
| -# if dist % 2 == mod and dist <= target: |
83 |
| -# s += 1 |
84 |
| -# else: |
85 |
| -# new = max(-1, (target - dist)) |
86 |
| -# if new >= 0: |
87 |
| -# print(y, x, new, target, dist) |
88 |
| -# if new % 2 == mod: |
89 |
| -# if not (0 <= y < Y or 0 <= x < X): |
90 |
| -# div = S*2 |
91 |
| -# s += new // (S*2) + 1 |
92 |
| -# else: |
93 |
| -# div = S |
94 |
| -# s += new // S + 1 |
95 |
| -# if not (0 <= y < Y or 0 <= x < X): |
96 |
| -# for side in [-1, 1]: |
97 |
| -# for i, rem in enumerate(range(target - S * 1, -S*2, -S*2)): |
98 |
| -# new = max(-1, (rem - dist)) |
99 |
| -# if new >= 0: |
100 |
| -# if new % 2 == mod: |
101 |
| -# # print(f"add {new=} {S=} {dist=} {new // S=}") |
102 |
| -# s += (new) // S // 2 + 1 |
103 |
| -# if new % 2 == (not mod): |
104 |
| -# # print(f"add {new=} {S=} {dist=} {new // S=}") |
105 |
| -# s += (new) // S // 2 |
106 |
| - |
107 |
| -# In exactly 6 steps, he can still reach 16 garden plots. |
108 |
| -# In exactly 10 steps, he can reach any of 50 garden plots. |
109 |
| -# In exactly 50 steps, he can reach 1594 garden plots. |
110 |
| -# In exactly 100 steps, he can reach 6536 garden plots. |
111 |
| -# In exactly 500 steps, he can reach 167004 garden plots. |
112 |
| -# In exactly 1000 steps, he can reach 668697 garden plots. |
113 |
| -# In exactly 5000 steps, he can reach 16733044 garden plots. |
114 |
| - |
115 |
| -target = 26501365 |
116 |
| -# target = 100 |
117 |
| -mod = target % 2 |
118 |
| - |
119 |
| -curr_sum = 0 |
120 |
| -next_sum = 0 |
121 |
| -for y in range(0, Y): |
122 |
| - for x in range(0, X): |
123 |
| - if (y, x) in dists: |
124 |
| - curr_sum += dists[(y, x)] % 2 == mod |
125 |
| - next_sum += dists[(y, x)] % 2 == (not mod) |
126 |
| - |
127 |
| -print(curr_sum, next_sum) |
128 |
| -# s = next_sum * sum(range(1, target // S, 2)) * 4 + curr_sum * ((sum(range(0, target // S, 2))) * 4 + 1) |
129 |
| -# s = curr_sum * sum(range(1, target // S, 2)) * 4 + next_sum * ((sum(range(0, target // S, 2))) * 4 + 1) |
130 |
| - |
131 |
| -s += next_sum * 4 |
132 |
| -s += curr_sum * 4 |
133 |
| -s += next_sum * 8 |
134 |
| - |
135 |
| -# Visited is a HashMap<Coord, usize> which maps tiles in the input-square to their distance from the starting tile |
136 |
| -# So read this as "even_corners is the number of tiles which have a distance that is even and greater than 65" |
137 |
| -let even_corners = visited.values().filter(|v| **v % 2 == 0 && **v > 65).count(); |
138 |
| -let odd_corners = visited.values().filter(|v| **v % 2 == 1 && **v > 65).count(); |
139 |
| - |
140 |
| -let even_full = visited.values().filter(|v| **v % 2 == 0).count(); |
141 |
| -let odd_full = visited.values().filter(|v| **v % 2 == 1).count(); |
142 |
| - |
143 |
| -// This is 202300 but im writing it out here to show the process |
144 |
| -let n = ((26501365 - (env.dim.0 / 2)) / env.dim.0) as usize; |
145 |
| -assert_eq!(n, 202300); |
146 |
| - |
147 |
| -let p2 = ((n+1)*(n*1)) * odd_full + (n*n) * even_full - (n+1) * odd_corners + n * even_corners; |
148 |
| - |
149 |
| - |
150 |
| -for x1, x2, y1, y2 in [(0, X, -Y*2, -Y), (0, X, Y*2, Y*3), (-X*2, -X, 0, Y), (X*2, X*3, 0, Y)]: |
151 |
| - for y in range(y1, y2): |
152 |
| - for x in range(x1, x2): |
153 |
| - if (y, x) in dists: |
154 |
| - d = dists[(y, x)] |
155 |
| - for times in range(target // S+10): |
156 |
| - num = d + S * times |
157 |
| - if num <= target: |
158 |
| - s += num % 2 == mod |
159 |
| - |
160 |
| -for xlims, ylims in [((-X*2, -X), (-Y*2, -Y)), ((X*2, X*3), (-Y*2, -Y)), ((X*2, X*3), (Y*2, Y*3)), ((-X*2, -X), (Y*2, Y*3))]: |
161 |
| - for y in range(*ylims): |
162 |
| - for x in range(*xlims): |
163 |
| - if (y, x) in dists: |
164 |
| - d = dists[(y, x)] |
165 |
| - for times in range(target // S+10): |
166 |
| - num = d + S * times |
167 |
| - if num <= target: |
168 |
| - s += (num % 2 == mod) * (times+3) |
169 |
| - |
170 |
| - # num = (dists[(y, x)] - S * 2) + (target // S) * S |
171 |
| - # if num <= target: |
172 |
| - # s += (num % 2 == (not mod)) * (target // S - 2) |
173 |
| - |
174 |
| - # num = (dists[(y, x)] - S * 3) + (target // S) * S |
175 |
| - # if num <= target: |
176 |
| - # s += (num % 2 == mod) * (target // S - 3) |
177 |
| - |
178 |
| - # num = (dists[(y, x)]) + (target // S) * S |
179 |
| - # if num <= target: |
180 |
| - # s += (num % 2 == (not mod)) * (target // S) |
181 |
| - print() |
182 |
| - |
183 |
| -print(s+curr_sum) |
184 |
| -exit() |
185 |
| - |
186 |
| -for y in range(0, Y): |
187 |
| - for x in range(0, X): |
188 |
| - if (y, x) in dists: |
189 |
| - dist = dists[(y, x)] |
190 |
| - if dist % 2 == mod and dist <= target: |
191 |
| - s += 1 |
192 |
| - for dy, dx in dirs + dirs_diag: |
193 |
| - dist = dists[(y+Y*2*dy, x+X*2*dx)] - S |
194 |
| - new = max(-1, (target - dist)) |
195 |
| - if new >= 0: |
196 |
| - # print(y, x, new, target, dist) |
197 |
| - if new % 2 == mod: |
198 |
| - div = S if dy == 0 or dx == 0 else S * 2 |
199 |
| - s += new // div + 1 |
200 |
| - for dy, dx in dirs: |
201 |
| - dist = dists[(y+Y*2*dy, x+X*2*dx)] - S |
202 |
| - # print(dist) |
203 |
| - for side in [-1, 1]: |
204 |
| - for i, rem in enumerate(range(target, -S*2, -S*2)): |
205 |
| - new = max(-1, (rem - dist)) |
206 |
| - if new >= 0: |
207 |
| - if new % 2 == mod: |
208 |
| - s += (new) // S + 1 |
| 18 | + if 0 <= ya < Y and 0 <= xa < X and lines[ya][xa] != '#' and (ya, xa) not in dists: |
| 19 | + dists[(ya, xa)] = dists.get((y, x), 0)+1 |
| 20 | + q.append((ya, xa)) |
209 | 21 |
|
210 |
| -# |
211 |
| -# #---# |
212 |
| -# |###| |
213 |
| -# |###| |
214 |
| -# |###| |
215 |
| -# #---# |
| 22 | +n = 26501365 // X |
216 | 23 |
|
217 |
| -print(s) |
| 24 | +even_full = sum(d % 2 == 0 for d in dists.values()) |
| 25 | +odd_full = sum(d % 2 == 1 for d in dists.values()) |
| 26 | +even_edges = sum(d % 2 == 0 and d > 65 for d in dists.values()) |
| 27 | +odd_edges = sum(d % 2 == 1 and d > 65 for d in dists.values()) |
218 | 28 |
|
| 29 | +print(even_full - even_edges) |
219 | 30 |
|
220 |
| -# Too low: |
221 |
| -# 618261433216623 |
222 |
| -# 618249208752749 wrong |
223 |
| -# 618261433216623 same |
| 31 | +p2 = (n+1)**2 * odd_full + n**2 * even_full - (n+1) * odd_edges + n * even_edges |
| 32 | +print(p2) |
0 commit comments