Vaya, lo puse en cajitas de código dentro del spoiler, pero por lo que decís parece que no se ve bien. Yo sí lo veo bien. Lo pongo aquí en texto plano de nuevo a ver si se ve mejor.
Día 8:
Spoiler
with open("input8.txt") as f:
inp = [x[:-1] for x in f.readlines()]
data = [(x.split('|')[0].split(), x.split('|')[1].split()) for x in inp]
# Part 1
fourdigits = [x[1] for x in data]
print(sum([len(x) in [2,3,4,7] for x in [x for y in fourdigits for x in y]]))
# Part 2
# Segments: a: upper, b: upper left, c: upper right, d: central, e: lower left, f: lower right, g: lower
num_to_char = {0:'abcefg',
1:'cf',
2:'acdeg',
3:'acdfg',
4:'bcdf',
5:'abdfg',
6:'abdefg',
7:'acf',
8:'abcdefg',
9:'abcdfg'}
char_to_num = {y:x for x,y in num_to_char.items()}
def find_letters(inp):
"""Given a list of the digit segment (randomized) returns
a dict with the correspondence with the original segments (dict[random]=original)"""
# Convert every element of the list to a set
inp = [set(x) for x in inp]
corr = dict()
# Step 1: Find the letter which is in 7 (length = 3) but not in 1 (length = 2)
a = list([x for x in inp if len(x)==3][0] - [x for x in inp if len(x)==2][0])[0]
corr['a'] = a
# Step 2: Find b (appears 6 times), e (appears 4 times) and f (appears 9 times)
for char in 'abcdefg':
x = sum([char in x for x in inp])
if x==6:
corr['b'] = char
elif x==4:
corr['e'] = char
elif x==9:
corr['f'] = char
# Step 3: Find c as the only char appearing in 1 (unique set of len 2) which is not f
corr['c'] = list([x for x in inp if len(x)==2][0] - {corr['f']})[0]
# Step 4: Find g as the only char appearing in 0 which is not abcef
corr['g'] = list([x for x in inp if len(x)==6 and set([corr[ x ] for x in 'abcef']).issubset(x)][0]\
- {corr[ x ] for x in 'abcef'})[0]
# Step 5: Find d as the remaining letter
corr['d'] = [x for x in 'abcdefg' if x not in corr.values()][0]
return {y:x for x,y in corr.items()}
def word_to_num(inp, corr):
"""Given a list of 4 words returns the corresponding number.
Corr: dictionary giving the correspondences with original segments"""
digits = []
for x in inp:
x = char_to_num[''.join(sorted(list({corr[y] for y in x})))]
digits.append(x)
return sum([10**(3-i)*digits for i in range(4)])
def solve(inp):
"""Returns the sum of all 4-digit numbers"""
nums = []
for x,y in inp:
corr = find_letters(x)
nums.append(word_to_num(y,corr))
return sum(nums)
print(solve(data))
Día 9:
Spoiler
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[j] < min(matrix[i-1][j], matrix[j-1], matrix[i+1][j], matrix[j+1]):
minima.append((i-1,j-1))
return minima
minima = local_minima(matrix)
print(sum([matrix[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:]))