Muy bien Richard, pero yo preferiría ver código, porque a veces el algoritmo está muy claro pero a la hora de programar aparecen dificultades (aunque no creo que sea el caso del ejercicio de hoy).
Por si queréis pensar la segunda parte pero no tenéis ganas de registraros o de programar la primera, la copio aquí. Básicamente se trata de encontrar componentes conexas de la matriz, donde la componente conexa correspondiente a un punto son todos los puntos a los que se puede llegar por caminos que no contengan ningún 9 (con movimientos solo en horizontal o vertical).
--- Part Two ---
Next, you need to find the largest basins so you know what areas are most important to avoid.
A basin is all locations that eventually flow downward to a single low point. Therefore, every low point has a basin, although some basins are very small. Locations of height 9 do not count as being in any basin, and all other locations will always be part of exactly one basin.
The size of a basin is the number of locations within the basin, including the low point. The example above has four basins.
The top-left basin, size 3:
2199943210
3987894921
9856789892
8767896789
9899965678
The top-right basin, size 9:
2199943210
3987894921
9856789892
8767896789
9899965678
The middle basin, size 14:
2199943210
3987894921
9856789892
8767896789
9899965678
The bottom-right basin, size 9:
2199943210
3987894921
9856789892
8767896789
9899965678
Find the three largest basins and multiply their sizes together. In the above example, this is 9 * 14 * 9 = 1134.
What do you get if you multiply together the sizes of the three largest basins?
Pongo mi código para las dos partes:
Spoiler
Aquí quizás lo único interesante es el truquillo del padding de la matriz con 9 (es decir, añadir filas y columnas de 9's al principio y al final) para evitar tener que imponer condiciones adicionales para los bordes.
with open("input9.txt") as f:
inp = [x[:-1] for x in f.readlines()]
# Part 1
import numpy as np
matrix = np.array([[int(x) for x in y] for y in inp])
def local_minima(matrix):
"""Returns list with locations of all local minima"""
ncol, nrow = len(matrix), len(matrix[0])
matrix = np.pad(matrix, ((1,),(1,)), constant_values=(9,9))
minima=[]
for i in range(1, nrow+1):
for j in range(1, ncol+1):
if matrix[i][j] < min(matrix[i-1][j], matrix[i][j-1], matrix[i+1][j], matrix[i][j+1]):
minima.append((i-1,j-1))
return minima
minima = local_minima(matrix)
print(sum([matrix[i][j]+1 for i,j in minima]))
# Part 2
def basin(minima, matrix):
"""Returns a list with the points of the basin corresponding to the given minima"""
matrix = np.pad(matrix, ((1,),(1,)), constant_values=(9,9))
points = [minima]
iteration = points
end = False
while not end:
new_iter = []
for x in iteration:
list_pos = [(x[0]-1, x[1]), (x[0]+1, x[1]), (x[0], x[1]-1), (x[0], x[1]+1)]
new_iter = new_iter + [(i,j) for (i,j) in list_pos if matrix[i+1][j+1] != 9]
new_iter = [x for x in list(set(new_iter)) if x not in points]
if not new_iter:
end = True
iteration = new_iter
points = points + new_iter
return points
basin_sizes = [len(basin(x, matrix)) for x in minima]
print(np.prod(sorted(basin_sizes)[-3:]))