O Advent of Code słyszałem już od kilku lat. Nigdy nie miałem okazji spróbować, ale pod koniec ubiegłego roku stwierdziłem, że wezmę udział i postanowiłem rozwiązać wszystkie zadania i robić to na bieżąco. Okazało się to niezłym wyzwaniem i nie było łatwo.

Christmas tree

Advent of Code

Advent of Code to coroczne wydarzenie programistyczne (pierwsza edycja wystartowała w 2015 roku) stworzone przez Erica Wastla. Zaczynając od pierwszego grudnia, przez 25 dni, codziennie o godzinie 6:00 czasu Polskiego pojawia się jedno zadanie do rozwiązania.

Każde zadanie składa się z dwóch części. Pierwsza część jest swego rodzaju rozgrzewką. Druga część bazuje na pierwszej i przykładowo zwiększa rozmiar problemu albo modyfikuje niektóre reguły tak, że problem staje się znacząco bardziej skomplikowany.

Wejściem do programu zazwyczaj jest plik, który jest inny dla każdego gracza (a przynajmniej nie jest taki sam dla wszystkich). Czasami samo jego parsowanie potrafi być niezłym wyzwaniem. W niektórych zadaniach zamiast pliku mamy tylko kilka liczb, które są wyświetlone bezpośrednio na stronie - oszczędzamy trochę czasu na parsowaniu, ale samo zadanie niekoniecznie jest łatwiejsze.

Dla zadanego wejścia musimy podać rozwiązanie, najlepiej pisząc odpowiedni program (w końcu to wydarzenie programistyczne). Nie trzeba wysyłać programu, wystarczy jego rezultat, który jest jedną liczbą albo jednym stringiem.

Na stronie wydarzenia można znaleźć więcej informacji. Sam autor miał też wystąpienie na temat wydarzenia na Øredev Conference.

Jak mi poszło?

Udało mi się rozwiązać wszystkie zadania, ale nie udało się skończyć wszystkiego na bieżąco. Ostatnie rozwiązanie wysłałem 2 dni po terminie (post opóźnił się jeszcze bardziej), a rozwiązanie pięciu zadań (z dwudziestu pięciu) przekroczyło 24 godziny. Moje rozwiązania są na githubie.

Niestety, o ile przez pierwsze 5-6 dni zadania były proste, to następne dni potrafiły przynieść duże wyzwania (niektóre były wręcz diabelnie trudne - patrz dzień 20) i w niektórych miejscach nie poradziłbym sobie bez pomocy reddita, gdzie każdego dnia, po rozwiązaniu zadania przez określoną liczbę osób, odblokowywany jest wątek, w którym można wrzucać swoje rozwiązania. A niektóre były naprawdę ciekawe i zaskakujące - używanie AWK, Excela, Asemblera, uruchamianie rozwiązania na Gameboyu, animacje graficzne itd. Są też wątki “Gettin’ Crafty With It”, gdzie najciekawsze rozwiązania są nagradzane - tutaj podsumowanie 2020.

Drugim bardzo pomocnym źródłem był dla mnie kanał Youtube Jonathana Paulsona, który na bieżąco streamował swoje rozwiązania i w tym roku zajął 15 miejsce.

Niektórzy uznają zapewne, że korzystanie z pomocy przy rozwiązywaniu zadań to oszustwo, ale osobiście tak tego nie traktuję. Sporo się w ten sposób nauczyłem/przypomniałem, zarówno jeśli chodzi o algorytmikę i tego typu zadania, jak i o Pythona (o czym za moment). Żadne rozwiązanie to nie było kopiuj-wklej bez zrozumienia, a pomimo korzystania z takiej pomocy, w sytuacjach kiedy nie wiedziałem co robić, i tak nie zająłem żadnego sensownego miejsca ;)

Język

Pierwsze pięć zadań rozwiązałem w Javie. Niestety, pomimo niezłych, jak mi się wydawało, czasów miałem słabe miejsca. Przykładowo, zadanie zostało przeze mnie rozwiązane w 11 minut, a byłem na 2866 miejscu.

Okazało się, że niektórzy wykręcają tam niewiarygodne czasy rozwiązań i rozwiązanie mają szybciej, niż ja zdążę przeczytać polecenie… Trochę się wtedy załamałem. Ale poczytałem i okazało się, że zabawa stała się bardzo konkurencyjna. Ludzie mają zestawy skryptów, biblioteki rozwiązań itd. (dla ciekawych Awesome Advent of Code czy też wpis tegorocznego zwycięzcy).

Nie zależało mi aż tak bardzo na wyniku, ale jednak złapałem trochę bakcyla i zacząłem zwracać uwagę na zajmowane miejsce. Nawet napisałem sobie drobny skrypcik do pobierania danych wejściowych i obejrzałem coś na temat competitive programming. Wtedy też postanowiłem przejść z rozwiązaniami na Pythona. Zauważyłem, że sporo ludzi na wysokich miejscach z niego korzysta, nawet jeśli w innych zawodach programistycznych używają C++. Powodem tutaj, jak to określił któryś z zawodników, jest dość elastyczne parsowanie plików, co stanowi sporą część każdego problemu, i rozbudowana biblioteka standardowa. Dla mnie dodatkowym plusem była możliwość przypomnienia sobie tego języka i nauczenia się czegoś - dość dawno go nie używałem i znam go w wersji raczej podstawowej.

I faktycznie, sporo się nauczyłem, oglądając kod innych trafiłem na rzeczy typu fileinput czy też defaultdict. Niestety, jak było do przewidzenia, podstawowa znajomość języka trochę mnie spowalniała - w niektórych momentach było sporo używania Googla, żeby sprawdzić, jak coś zrobić. To nic złego, ale komuś zaczyna zależeć na czasie, to jednak trzeba lepiej poznać język i biblioteki.

Czas

No właśnie, jeśli chodzi o czas. Początkowo zakładałem, że zadania będą mi zajmowały około 15-30 minut, które planowałem wykroić ze swojej porannej godziny dla siebie na naukę/projekty. To się dobrze składało, bo zadania były publikowane o 6:00, a czas dla siebie zarezerwowałem sobie przed pracą, między godziną 6:00 a 7:00. Miałem więc szansę na lepsze miejsca. Niestety, o ile na początku to działało, to szybko okazało się, że nawet cała godzina nie zawsze mi wystarcza i zadanie musiałem kończyć później (w niektórych przypadkach nie udało mi się skończyć nawet tego samego dnia). To sprawiło, że zaniedbałem naukę innych rzeczy, przede wszystkim naukę AWS i przygotowania do certyfikacji. To ta część mnie najbardziej mnie bolała w całym tym projekcie.

Rozwiązywane problemy

Pytanie, czemu zajmowało mi to aż tyle czasu. Jednym z powodów była właśnie słabsza znajomość Pythona, co mnie spowalniało. W kilku miejscach było to złe zrozumienie problemu. Ale chyba najczęściej były to typy problemów do rozwiązania - rekurencja, programowanie dynamiczne, backtracking, game of life na nieskończonej siatce 3D itp. Niestety, nie mam do czynienia z takimi rzeczami na co dzień i sporo tego, czego nauczyłem się na studiach, wyleciało mi z głowy. W 2021 roku planuję poświęcić trochę czasu na tego typu problemy (tutaj ciekawy może być kanał Youtube Back to SWE), żeby poćwiczyć głowę czymś innym niż kod biznesowy.

Jeśli chodzi o competitive programming, to o ile spodobało mi się, do pewnego stopnia rozwiązywanie takich problemów, to niespecjalnie pociągające jest dla mnie programowanie na czas. Zwłaszcza kiedy spojrzy się w kod pisany pod takie zawody - wszystko w jednej funkcji, zmienne jednoliterkowe itd. Niewiele ma to wspólnego z clean code. Nie ma co się dziwić, bo przeznaczenie tego kodu jest inne - on nie będzie utrzymywany i raczej nikt go później nie będzie czytał, ale to chyba jednak nie do końca dla mnie. Chociaż, jak już wspominałem, mimowolnie łapię trochę tę nutkę współzawodnictwa.

Podsumowanie

Advent of Code to świetne wydarzenie i każdemu polecam spróbować. Można postawić sobie różne cele - niekoniecznie trzeba rozwiązywać zadania na czas i patrzeć na miejsca, które się zajmuje. Zamiast tego, można to wydarzenie wykorzystać na przykład do nauki języka czy też poćwiczenia TDD.

Czy sam będę brał udział za rok? Na ten moment nie jestem przekonany. Największym problemem będzie czas, którego niestety nie mam w nadmiarze. Możliwe, że będę robił tylko wybrane zadania. A może, jeśli poćwiczę w tym roku rozwiązywanie takich problemów, to rozwiązywanie będzie mi szło dużo szybciej? Zobaczymy.