Try an interactive version of this dialog: Sign up at solve.it.com, click Upload, and pass this URL.
from aocd import get_data
inp = get_data(year=2025, day=9)
len(inp), len(inp.splitlines()), len(inp.splitlines()[0]), inp[:100]
g = np.array([["."]*(max(xs)+1) for _ in range(max(ys)+1)])
for x, y in zip(xs, ys):
g[y][x] = "#"
print("\n".join(["".join(l) for l in g]))
minx, miny, maxx, maxy = min(xs), min(ys), max(xs), max(ys)
points_to_check = L(coords).filter(lambda c: c[0] == minx or c[0] == maxx or c[1] == miny or c[1] == maxy)
points_to_check
# Now we iterate over these
max_a = 0
for p in points_to_check:
for p2 in points_to_check:
if p2 == p: continue
a = abs(1+p[0] - p2[0]) * abs(1+p[1] - p2[1]) # 1+ because inclusive
# print(a, p, p2)
max_a = max(max_a, a)
max_a
Using the code above, make a solve function that takes samp and outputs this final area
def solve(s):
lines = s.splitlines()
coords = [L(l.split(",")).map(int) for l in lines]
xs, ys = map(np.array, zip(*coords))
minx, miny, maxx, maxy = min(xs), min(ys), max(xs), max(ys)
points_to_check = L(coords).filter(lambda c: c[0] == minx or c[0] == maxx or c[1] == miny or c[1] == maxy)
max_a = 0
for p in points_to_check:
for p2 in points_to_check:
if p2 == p: continue
a = abs(1+p[0] - p2[0]) * abs(1+p[1] - p2[1])
max_a = max(max_a, a)
return max_a
solve(samp)
def solve(s):
lines = s.splitlines()
coords = [L(l.split(",")).map(int) for l in lines]
xs, ys = map(np.array, zip(*coords))
minx, miny, maxx, maxy = min(xs), min(ys), max(xs), max(ys)
points_to_check = L(coords).filter(lambda c: c[0] == minx or c[0] == maxx or c[1] == miny or c[1] == maxy)
max_a = 0
for p in points_to_check:
for p2 in points_to_check:
if p2 == p: continue
a = abs(1+p[0] - p2[0]) * abs(1+p[1] - p2[1])
max_a = max(max_a, a)
return max_a
solve(samp)
def solve(s):
lines = s.splitlines()
coords = [L(l.split(",")).map(int) for l in lines]
xs, ys = map(np.array, zip(*coords))
minx, miny, maxx, maxy = min(xs), min(ys), max(xs), max(ys)
points_to_check = L(coords)#.filter(lambda c: c[0] == minx or c[0] == maxx or c[1] == miny or c[1] == maxy)
max_a = 0
for p in points_to_check:
for p2 in points_to_check:
if p2 == p: continue
a = abs(1+p[0] - p2[0]) * abs(1+p[1] - p2[1])
max_a = max(max_a, a)
return max_a
solve(samp)
The Elves just remembered: they can only switch out tiles that are red or green. So, your rectangle can only include red or green tiles.
In your list, every red tile is connected to the red tile before and after it by a straight line of green tiles. The list wraps, so the first red tile is also connected to the last red tile. Tiles that are adjacent in your list will always be on either the same row or the same column.
Using the same example as before, the tiles marked X would be green:
..............
.......#XXX#..
.......X...X..
..#XXXX#...X..
..X........X..
..#XXXXXX#.X..
.........X.X..
.........#X#..
..............
In addition, all of the tiles inside this loop of red and green tiles are also green. So, in this example, these are the green tiles:
..............
.......#XXX#..
.......XXXXX..
..#XXXX#XXXX..
..XXXXXXXXXX..
..#XXXXXX#XX..
.........XXX..
.........#X#..
..............
The remaining tiles are never red nor green.
The rectangle you choose still must have red tiles in opposite corners, but any other tiles it includes must now be red or green. This significantly limits your options.
g = np.array([["."]*(max(xs)+1) for _ in range(max(ys)+1)])
for x, y in zip(xs, ys): g[y][x] = "#"
g
array([['.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.'],
['.', '.', '.', '.', '.', '.', '.', '#', '.', '.', '.', '#'],
['.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.'],
['.', '.', '#', '.', '.', '.', '.', '#', '.', '.', '.', '.'],
['.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.'],
['.', '.', '#', '.', '.', '.', '.', '.', '.', '#', '.', '.'],
['.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.'],
['.', '.', '.', '.', '.', '.', '.', '.', '.', '#', '.', '#']],
dtype='<U1')for i,row in enumerate(g):
rlocs = np.where(row == "#")[0]
if len(rlocs) > 1: g[i, rlocs[0]+1:rlocs[-1]] = "X"
print("\n".join(["".join(l) for l in g]))
for i in range(g.shape[1]):
col = g[:,i]
rlocs = np.where((col == "#")|(col == "X"))[0]
if len(rlocs) > 1: g[rlocs[0]+1:rlocs[-1], i] = "X"
print("\n".join(["".join(l) for l in g]))
def solveb(s):
lines = s.splitlines()
coords = [L(l.split(",")).map(int) for l in lines]
xs, ys = map(np.array, zip(*coords))
g = np.array([["."]*(max(xs)+1) for _ in range(max(ys)+1)])
for x, y in zip(xs, ys): g[y][x] = "#"
for i in range(len(coords)):
p1, p2 = coords[i], coords[(i+1)%len(coords)]
if p1[0] == p2[0]:
miny, maxy = min(p1[1], p2[1]), max(p1[1], p2[1])
g[miny:maxy+1, p1[0]] = "X"
else:
minx, maxx = min(p1[0], p2[0]), max(p1[0], p2[0])
g[p1[1], minx:maxx+1] = "X"
for i in range(g.shape[0]):
rlocs = np.where((g[i] == "#")|(g[i] == "X"))[0]
if len(rlocs) > 1: g[i, rlocs[0]+1:rlocs[-1]] = "X"
max_a = 0
for p in coords:
for p2 in coords:
if p2 == p: continue
minx, maxx = min(p[0], p2[0]), max(p[0], p2[0])
miny, maxy = min(p[1], p2[1]), max(p[1], p2[1])
rect = g[miny:maxy+1, minx:maxx+1]
if np.all((rect == "#")|(rect == "X")): max_a = max(max_a, (maxx-minx+1)*(maxy-miny+1))
return max_a
solveb(samp)
lines = inp.splitlines()
coords = [L(l.split(",")).map(int) for l in lines]
xs, ys = map(np.array, zip(*coords))
min(xs), max(xs), min(ys), max(ys)
xmap = {x:i for i,x in enumerate(list(set(xs)))}
ymap = {y:i for i,y in enumerate(list(set(ys)))}
new_coords = [(xmap[x], ymap[y]) for x,y in coords]
new_coords[:4]
def solveb(s):
lines = s.splitlines()
coords = [L(l.split(",")).map(int) for l in lines]
xs, ys = map(np.array, zip(*coords))
xmap = {x:i for i,x in enumerate(sorted(set(xs)))}
ymap = {y:i for i,y in enumerate(sorted(set(ys)))}
xrev = {i:x for x,i in xmap.items()}
yrev = {i:y for y,i in ymap.items()}
new_coords = [(xmap[x], ymap[y]) for x,y in coords]
g = np.array([["."]*(len(xmap)) for _ in range(len(ymap))])
for x, y in new_coords: g[y][x] = "#"
for i in range(len(new_coords)):
p1, p2 = new_coords[i], new_coords[(i+1)%len(new_coords)]
if p1[0] == p2[0]:
miny, maxy = min(p1[1], p2[1]), max(p1[1], p2[1])
g[miny:maxy+1, p1[0]] = "X"
else:
minx, maxx = min(p1[0], p2[0]), max(p1[0], p2[0])
g[p1[1], minx:maxx+1] = "X"
for i in range(g.shape[0]):
rlocs = np.where((g[i] == "#")|(g[i] == "X"))[0]
if len(rlocs) > 1: g[i, rlocs[0]+1:rlocs[-1]] = "X"
max_a = 0
for p in new_coords:
for p2 in new_coords:
if p2 == p: continue
minx, maxx = min(p[0], p2[0]), max(p[0], p2[0])
miny, maxy = min(p[1], p2[1]), max(p[1], p2[1])
rect = g[miny:maxy+1, minx:maxx+1]
if np.all((rect == "#")|(rect == "X")):
orig_w = xrev[maxx] - xrev[minx] + 1
orig_h = yrev[maxy] - yrev[miny] + 1
max_a = max(max_a, orig_w * orig_h)
return max_a
solveb(samp)