189 lines
6.0 KiB
Python
189 lines
6.0 KiB
Python
from pprint import pprint as pp
|
|
import shared
|
|
import matrix
|
|
|
|
|
|
|
|
def part1(mx):
|
|
SIZE=len(mx)
|
|
MAX_IDX = SIZE -1
|
|
data = matrix.matrix_of_size(SIZE, SIZE)
|
|
data = matrix.set_matrix_dict(data)
|
|
|
|
for row in range(SIZE):
|
|
for col in range(SIZE):
|
|
data[row][col] = { "l": True, "r": True, "u": True, "d": True }
|
|
|
|
for row, _row in enumerate(mx):
|
|
# Skip outer edges
|
|
if row == 0 or row == MAX_IDX:
|
|
continue
|
|
for col, _val in enumerate(mx[row]):
|
|
# Skip outer edges
|
|
if col == 0 or col == MAX_IDX:
|
|
continue
|
|
|
|
# TODO: slice
|
|
# Get a list of indexes in the current direction to check
|
|
trees_u_indexes = list(range(0, row))
|
|
trees_l_indexes = list(range(0, col))
|
|
trees_d_indexes = list(range(MAX_IDX, row, -1))
|
|
trees_r_indexes = list(range(col+1, SIZE))
|
|
|
|
# Get the trees in the line
|
|
trees_u = [mx[y][col] for y in trees_u_indexes]
|
|
trees_l = [mx[row][x] for x in trees_l_indexes]
|
|
trees_d = [mx[y][col] for y in trees_d_indexes]
|
|
trees_r = [mx[row][x] for x in trees_r_indexes]
|
|
|
|
# find tallest tree in line
|
|
highest_u = max(trees_u)
|
|
highest_l = max(trees_l)
|
|
highest_d = max(trees_d)
|
|
highest_r = max(trees_r)
|
|
|
|
# if there's anything as tall, or taller than this tree in that line
|
|
# then it's not visible
|
|
if highest_u >= _val:
|
|
data[row][col]["u"] = False
|
|
|
|
if highest_l >= _val:
|
|
data[row][col]["l"] = False
|
|
|
|
if highest_d >= _val:
|
|
data[row][col]["d"] = False
|
|
|
|
if highest_r >= _val:
|
|
data[row][col]["r"] = False
|
|
|
|
# count visible
|
|
count = 0
|
|
for row in range(SIZE):
|
|
for col in range(SIZE):
|
|
u = data[row][col]["u"]
|
|
l = data[row][col]["l"]
|
|
d = data[row][col]["d"]
|
|
r = data[row][col]["r"]
|
|
if any((r,l,u,d)):
|
|
count += 1
|
|
print(count)
|
|
|
|
|
|
def part2(mx):
|
|
SIZE=len(mx)
|
|
MAX_IDX = SIZE -1
|
|
data = matrix.matrix_of_size(SIZE, SIZE)
|
|
data = matrix.set_matrix_dict(data)
|
|
|
|
high_score = 0
|
|
|
|
for row in range(SIZE):
|
|
for col in range(SIZE):
|
|
data[row][col] = { "value": mx[row][col]}
|
|
|
|
for row, _row in enumerate(mx):
|
|
for col, _val in enumerate(mx[row]):
|
|
# Get a list of indexes in the current direction to check
|
|
# TODO: slice
|
|
trees_u_indexes = list(range(0, row))
|
|
trees_l_indexes = list(range(0,col))
|
|
trees_d_indexes = list(range(MAX_IDX, row, -1))
|
|
trees_r_indexes = list(range(col+1, SIZE))
|
|
|
|
# Grab the trees potentially in sight
|
|
trees_u = [mx[y][col] for y in trees_u_indexes]
|
|
trees_l = [mx[row][x] for x in trees_l_indexes]
|
|
trees_d = [mx[y][col] for y in trees_d_indexes]
|
|
trees_r = [mx[row][x] for x in trees_r_indexes]
|
|
|
|
# Reverse everything but r, as everything is "away" from the tree
|
|
data[row][col]["u"] = list(reversed(trees_u))
|
|
data[row][col]["l"] = list(reversed(trees_l))
|
|
data[row][col]["d"] = list(reversed(trees_d))
|
|
data[row][col]["r"] = trees_r
|
|
|
|
# Calculate score
|
|
score = 1 # identity yoooo
|
|
cell = data[row][col]
|
|
val = cell['value']
|
|
# Get the score of visible trees in each direction
|
|
for direction in ("u","l","d","r"):
|
|
in_line = cell[direction]
|
|
if not in_line:
|
|
# we're on an edge
|
|
score = 0
|
|
break
|
|
|
|
line_score = 0
|
|
for idx, tree in enumerate(in_line):
|
|
# for every tree, check if its as tall or taller,
|
|
# stop countig after that
|
|
line_score += 1
|
|
if tree >= val:
|
|
break
|
|
score = score * line_score
|
|
if score > high_score:
|
|
high_score = score
|
|
print(high_score)
|
|
|
|
def part2_with_fixes(mx):
|
|
SIZE=len(mx)
|
|
MAX_IDX = SIZE -1
|
|
data = matrix.matrix_of_size(SIZE, SIZE)
|
|
data = matrix.set_matrix_dict(data)
|
|
|
|
high_score = 0
|
|
|
|
for row in range(SIZE):
|
|
for col in range(SIZE):
|
|
data[row][col] = { "value": mx[row][col]}
|
|
|
|
for row, _row in enumerate(mx):
|
|
for col, _val in enumerate(mx[row]):
|
|
lineofsight = matrix.line_of_sight(mx, row, col)
|
|
|
|
data[row][col]["u"] = lineofsight["U"]
|
|
data[row][col]["l"] = lineofsight["L"]
|
|
data[row][col]["d"] = lineofsight["D"]
|
|
data[row][col]["r"] = lineofsight["R"]
|
|
|
|
# Calculate score
|
|
score = 1 # identity yoooo
|
|
val = data[row][col]['value']
|
|
# Get the score of visible trees in each direction
|
|
for direction in ("u","l","d","r"):
|
|
in_line = data[row][col][direction]
|
|
if not in_line:
|
|
# we're on an edge
|
|
score = 0
|
|
break
|
|
|
|
line_score = 0
|
|
for idx, tree in enumerate(in_line):
|
|
# for every tree, check if its as tall or taller,
|
|
# stop countig after that
|
|
line_score += 1
|
|
if tree >= val:
|
|
break
|
|
score = score * line_score
|
|
if score > high_score:
|
|
high_score = score
|
|
print(high_score)
|
|
|
|
def main():
|
|
mx = matrix.load_matrix_file(shared.get_fname(8))
|
|
with shared.elapsed_timer() as elapsed:
|
|
part1(mx)
|
|
print(elapsed())
|
|
with shared.elapsed_timer() as elapsed:
|
|
part2(mx)
|
|
print(elapsed())
|
|
with shared.elapsed_timer() as elapsed:
|
|
part2_with_fixes(mx)
|
|
print(elapsed())
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|