Część 1
W dzisiejszym zadaniu mamy na wejściu zbiór kluczy i zamków, naszym zadaniem jest obliczyć ile w sumie kluczy pasuje do ilu zamków. Input wygląda w ten sposób:
#####
##.##
.#.##
...##
...#.
...#.
.....
.....
#....
#....
#...#
#.#.#
#.###
#####
.....
.....
#.#..
###..
###.#
###.#
#####
Zamki to te macierze które w górnym rzędzie mają same #
, a klucze mają w dolnym
rzędzie same #
, klucz mieści się w zamku jeśli ilość #
w każdej kolumnie, nie
przekracza wysokości kolumny. Właściwie w treści zadania mamy podane całe jego
rozwiązanie, widać że autor nie chciał jak najbardziej ułatwić nam dzisiejsze zadanie.
Rozwiązanie
Parsowanie wejścia
import sys
data = sys.stdin.read().strip().split("\n\n")
WIDTH = 5
HEIGHT = 7
# zbieramy klucze i zamki do oddzielnych list
keys, locks = [], []
for d in data:
arr = d.strip().split("\n")
# counts to krotka z ilością # w każdej kolumnie, np. (1, 0, 3, 4, 1)
counts = tuple(
len(list(filter(lambda a: a == "#", col))) for col in list(zip(*arr))
)
if arr[0][0] == "#": # jeśli w pierwszym rzędzie jest # to to zamek
locks.append(counts)
else:
keys.append(counts)
W powyższym kodzie użyłem ciekawego tricka: list(zip(*arr))
, który w prosty sposób
pozwala na transpozycję dwuwymiarowej listy w pythonie.
Obliczenie rozwiązaina
Iterujemy po produkcie kartezjańskim kluczy i zamków, sumujemy ilość pól #
w każdej
kolumnie i jeśli liczba przekroczy wyosość kolumny (7) to pomijamy tę parę klucz-zamek.
result = 0
for key, lock in itertools.product(keys, locks):
if all(key[i] + lock[i] <= HEIGHT for i in range(len(lock))):
result += 1
print(result)
Podsumowanie
W tym roku udało mi się pierwszy razy zrobić wszystkie zadania z Advent of Code, było to ciekawe doświadczenie, tym bardziej że dokumentowałem wszystko na blogu. Zadania były bardzo ciekawe, poziom trudności osiągnął szczyt w dniu 17 i 21.
Na następny rok na pewno warto ogarnąć sobie parę bibliotek do często powtarzających się problemów:
networkx
pozwala na znajdywanie rozwiązań problemów z grafami (np. shortest-path, clique…)z3
- pozwala na rozwiązywanie różnych równań- stworzenie prostej biblioteki do parsowania wejścia
- prosta biblioteka do pracy na 2d gridach
A może warto spóbować swoich sił w innym języku programowania? Zobaczę na co będę miał
ochotę, pisanie pierwszych kilku części w awk
u było odświeżającym doświaczeniem ale
na dłuższą metę męczącym, być może jakbym wybrał jakiś bardziej rozwinięty język jak
Rust
, Go
albo C++
to byłoby łatwiej.
Dzięki za przeczytanie moich notatek z tegorocznej edycji Advent of Code, mam nadzieję że były pomocne i ciekawe. Do zobaczenia za rok!