12 / 31
Dec 2018

Przede wszystkim podziękowania dla organizatorów FRAKTALa, bo widać, że wkładacie w to dużo serca i cennego czasu. Szkoda, że tak niewielu nauczycieli / wykładowców poleca SPOJa i organizowane tutaj konkursy swoim uczniom. Można pomyśleć jak bardziej rozreklamować FRAKTAL, żeby było jeszcze więcej uczestników.

Z rozkładu punktów w rankingu widać, że poziom trudności był dobrze dobrany. Myślę, że każdy – bez względu na to, ile zadań rozwiązał – miał okazję, żeby podszkolić swoje umiejętności w programowaniu.

Co do konkretnych zadań:

Najbardziej „ku pokrzepieniu serc”: „Jąkała” – bardzo proste, niematematyczne, jasno opisane zadanko dla każdego.

Największa satysfakcja z rozwiązania: „Pętla” – okazało się nie takie trywialne, jak na pierwszy rzut oka wyglądało.

Najbardziej wciągająca fabuła: oczywiście „Gangi liczbowe” – wreszcie jakaś mroczna historia, a nie cukierkowa opowiastka o Jasiu i Małgosi, Bajtku czy szlachetnym królu Bajtomirze :grin: No i udało mi się je zrobić po gangstersku: brzydko i brutalnie, ale z dobrym skutkiem :rofl:.

Najbardziej upierdliwe: „25” – przy nim przypomniał mi się koszmar z rozwiązywania Pieczątki dzieci8 – zadania z kategorii łatwe, kiedy to miałem ochotę porąbać klawiaturę.

Najbardziej ciekawi mnie optymalne rozwiązanie: „Liczby szczęśliwe” – moje sito nie mieściło się w czasie, ale jeszcze nad tym zadaniem posiedzę, bo widzę, że najlepsi rozwiązali je w 0.00s.

Zadanie, jakiego mi brakowało – coś na tworzenie i sortowanie własnych struktur w stylu Ranking Gildii4 lub Skoki narciarskie4 - zadania nietrudne, ale wymagające kodu dłuższego niż kilkanaście linijek.

Pozdrawiam i do zobaczenia w kolejnej edycji.

Podobało się zdecydowanie :slight_smile: Na pętle nie wpadłam jak to rozwiązać… pewnie bardzo prosto jak się domyślam. A z gangami … też muszę przemyśleć, bo moje za wolne rozwiązanie :slight_smile: Udało sie rozwiązać połowę zadań i jestem z siebię zadowolona :smiley: Żałuję że nie udało sie załapać na nagrodę za zadanie testowe :smiley: 25- wrr… podejście było ale kompletnie nie udane poplątalam sie :slight_smile: Dziękuję autorom za pracę i czekam na kolejny konkurs :slight_smile:
A i wszystkim wesołych świąt :slight_smile:

Wszystko co dobre, zawsze jakoś tak dziwnie się kończy i zawsze dużo za szybko :wink: Święta też będą dobre ale …

W zasadzie nie mam nic więcej do dodania, zastanawiam się tylko kiedy Marecin zgubi buty do biegania. Gdyby biegał w kapciach, to biega tak szybko, że już dawno by je pogubił, a tak … no napewno rok trzeba będzie przeczekać :wink:

Oczywiście wielkie gratulacje i podziękowania 3XM :wink: no i oczywiście zdrowych dla wszystkich …

Oczywiście 2xM, A i T :wink:

Wyszła mi mini powieść, ale akurat Haft to takie zadanie, które trudno krótko opisać :wink: Jeżeli coś jest niejasne piszcie.

Optymalna strategia odwzorowania haftu jest prosta, z każdej komórki staramy się wykonać operację wyszywania o jak największym r. Wartość r dla każdego pola wyznaczamy analizując haft Małgosi. Sprawdzamy ile gwiazdek odchodzi od danej komórki w każdym z czterech kierunków (góra, dół, lewo, prawo) i wybieramy najmniejszą z tych wartości. Jak już znamy wartość r dla każdej komórki to wyszywamy nasz haft i po zakończeniu sprawdzamy czy pokrywa się z haftem Małgosi.

Dojście do takiego rozwiązania na pewno nie jest trudne, większym problemem jest odpowiednia implementacja.

Rozwiązanie naiwne to oczywiście zakodowanie powyższej strategii, czyli 3 zagnieżdżone pętle. Dwie zewnętrzne wybierają komórkę, dla której wyznaczamy r. Trzecia najbardziej wewnętrzna pętla wyznacza r, oddalając się coraz bardziej od komórki i sprawdzając czy w każdym z czterech kierunków dalej występują gwiazdki. Jak już wyznaczymy r dla komórki to haftujemy. Złożoność algorytmu to O(n^3).

Uwaga! Zakładam, że wszystkie tablice, które tworzę są wyzerowane przed ich użyciem.

Można to jednak rozwiązać szybciej. Stwórzmy sobie 4 tablice U, D, L, R o rozmiarze odpowiadającym rozmiarowi tkaniny. Każda z tych tablic przechowuje informacje ile gwiazdek odchodzi od danej komórki w jednym z 4 kierunków. Kluczowe jest to żeby zauważyć, że te tablice możemy wyznaczyć w czasie O(n^2), a nie O(n^3).

Pokaże to na przykładzie tablicy L, która przechowuje informacje ile gwiazdek odchodzi od każdej komórki w lewą stronę. Przechodzimy haft Małgosi (tablicę M) wiersz po wierszu. Załóżmy, że jesteśmy w wierszu y. Jeżeli haft Małgosi w pierwszej kolumnie wiersza y ma gwiazdkę (M[y][0] == *) to w komórce L[y][0] zapisujemy wartość 1, w przeciwnym wypadku wartość 0. Teraz przechodzimy wiersz y od drugiej kolumny aż do samego końca. Załóżmy, że jesteśmy w kolumnie x. Jeżeli haft Małgosi w kolumnie x wiersza y ma kropkę (M[y][x] == .) to do komórki L[y][x] zapisujemy wartość 0. Jeżeli jednak haft Małgosi w kolumnie x wiersza y ma gwiazdkę (M[y][x] == *) to zapisujemy do kolumny L[y][x] wartość 1 + liczba gwiazdek, które stoją w wierszu y przed kolumną x. Skąd mamy wziąć tę liczbę? Otóż policzyliśmy ją jeden obrót pętli wcześniej i zapisaliśmy w polu L[y][x - 1]! Podsumowując pseudokod wyznaczający tablicę L prezentuje się tak:

for y = 0 to m - 1 do
  if M[y][0] == * then
    L[y][0] = 1
  else
    L[y][0] = 0
  for x = 1 to n - 1 do
    if M[y][x] == * then
      L[y][x] = L[y][x - 1] + 1
    else
      L[y][x] = 0

Analogicznie wyznaczamy tablice U, D i R. Po ich wyznaczeniu wartość r dla każdej komórki możemy policzyć w czasie stałym r = min(U[y][x] - 1, D[y][x] - 1, L[y][x] - 1, R[y][x] - 1). Jeżeli wartość r wyszła < 1 to oznacza, że z tej komórki nie możemy nic wyszyć.

Wiemy już jak wyznaczyć wszystkie operacje w złożoności O(n^2). Teraz musimy je wykonać żeby sprawdzić czy uzyskaliśmy taki sam haft jak Małgosia. Jak wynika z opisu rozwiązania naiwnego operacja haftowania też będzie miała złożoność O(n^3). Tutaj też dążymy do tego żeby uzyskać złożoność O(n^2). W tym celu wykorzystamy pewien trick.

Wyobraźcie sobie takie zadanie. Macie prostą na której trzeba narysować bardzo dużą liczbę odcinków, które mogą się nakładać na siebie. Żeby nie odbiegać za bardzo od naszego zadania, niech to będzie wiersz tabeli, w którym macie zapisywać odcinki gwiazdek. Rozwiązanie naiwne to oczywiście zapisywanie tych gwiazdek dla każdego wczytanego odcinka. Sprytniejsze rozwiązanie wygląda tak. Dla każdego wczytanego odcinka zwiększamy wartość w komórce, w której się on zaczyna o 1, zaś w pierwszej komórce za końcem odcinka zmniejszamy wartość o 1. Po wczytaniu wszystkich odcinków liczymy sumy prefiksowe dla tego wiersza. Jak łatwo zauważyć po policzeniu sum prefiksowych każda komórka będzie trzymała liczbę odcinków, które ją pokrywają.

Przykład:
Mamy nanieść 2 odcinki 1-3 i 2-4 w tablicy 6-elementowej.
0 1 2 3 4 5 <- Indeksy tablicy
0 0 0 0 0 0 <- Wartości początkowe
0 1 0 0 -1 0 <- Po dodaniu odcinka 1-3
0 1 1 0 -1 -1 <- Po dodaniu odcinka 2-4
0 1 2 2 1 0 <- Po policzeniu sum prefiksowych

Teraz wystarczy, że przejdziemy liniowo tę tablicę i wypiszemy gwiazdkę tam gdzie wartość w komórce jest dodatnia.

Jak to wykorzystać do haftowania? Bardzo prosto, każda operacja to tak naprawdę narysowanie dwóch odcinków, jednego poziomego i jednego pionowego. Utwórzmy zatem kolejne 2 tablice H i V, o rozmiarze o 1 większym w poziomie i pionie od rozmiaru tkaniny. W tablicy H będziemy oznaczać poziome odcinki gwiazdek do narysowania, zaś w tablicy V pionowe. Załóżmy, że mam do wykonania operację x y r czyli z komórki x, y powinienem narysować pionowy odcinek od pola x, y - r do pola x, y + r oraz poziomy odcinek z pola x - r, y do pola x + r, y. Korzystając z tego co napisałem powyżej wykonam poniższe operacje:

H[y][x - r] += 1
H[y][x + r + 1] -= 1
V[y - r][x] += 1
V[y + r + 1][x] -= 1

Po przejściu wszystkich operacji liczę sumy prefiksowe dla każdego wiersza w tablicy H i dla każdej kolumny w tablicy V i na ich podstawie zapisuję gwiazdki. Całość ma złożoność O(n^2).

W ten sposób można uzyskać rozwiązanie o złożoności O(n^2) zamiast O(n^3). Moje rozwiązanie wzorcowe wykonuje się w 0,2s dla najbardziej złośliwego testu. Zastanawiałem się czy nie zmniejszyć limitu czasu do 0,5s, ale uznałem, że jeżeli komuś uda się wcisnąć O(n^3) w 1s to też będzie świadczyło o bardzo dobrych umiejętnościach programistycznych :slight_smile:

No cóż taka już jest naturalna kolei rzeczy. My cieszymy się razem z Tobą z osiągnięć Twoich dzieci, bo to oznacza, że będziemy mieli godnych zastępców :slight_smile:

Jeżeli chodzi o zadanie “Kwadratowy świat II” to szczerze mówiąc spodziewaliśmy się większej liczby AC. W zadaniu mamy n punktów i musimy stwierdzić ile różnych kwadratów równoległych do osi układu współrzędnych możemy ułożyć. Mamy również zagwarantowane, że punkty się nie powtarzają.

Rozwiązanie naiwne to oczywiście 4 zagnieżdżone pętle, z których każda wybiera 1 wierzchołek kwadratu. Mając wybrane 4 wierzchołki sprawdzamy czy tworzą kwadrat równoległy do osi układu współrzędnych. Takie rozwiązanie ma złożoność O(n^4), biorąc pod uwagę, że maksymalna wartość n wynosi 10^6 to nie ma możliwości żeby zmieściło się ono w czasie bo w 4s musielibyśmy wykonać 10^24 operacji.

Rozwiązanie naiwne moglibyśmy przyspieszyć stosując wyszukiwanie binarne. Jeżeli mamy wybrane 2 wierzchołki, które tworzą bok kwadratu to współrzędne pozostałych 2 możemy sobie łatwo wyznaczyć, a następnie za pomocą wyszukiwania binarnego sprawdzić czy takie punkty występują w naszym zbiorze. Pojedyncze wyszukiwanie binarne na zbiorze 10^6 elementów wynosi maksymalnie 20 operacji, co oznacza, że jest to bardzo duże przyspieszenie w porównaniu z wyszukiwaniem liniowym. Złożoność takiego podejścia wynosi O(2 * n^2 * log(n)) czyli dla maksymalnych danych byłoby to 4 * 10^13 operacji. To dalej jest za dużo.

W tym momencie możemy zauważyć, że nawet gdyby udało nam się zejść do złożoności O(n^2) to prawdopodobnie i tak dostaniemy TLE, gdyż będzie to 10^12 operacji. Wiemy jednocześnie, że nie rozwiążemy tego zadania bez wyznaczenia co najmniej 1 boku kwadratu. Co zatem należy zrobić?

Kluczowa obserwacja jest taka, że powierzchnia, na której występują punkty jest mała. W pionie lub poziomie nie będziemy mieli nigdy więcej niż 2001 punktów. Wiemy również, że nasz kwadrat będzie miał wszystkie boki równoległe do jednej z osi. W związku z powyższym łatwo można wywnioskować, że nie opłaca się tworzyć boku z punktów, które nie mają takiej samej wartości współrzędnej x albo y. Skorzystajmy z tych faktów. Posortujmy punkty rosnąco po współrzędnej x, a jeżeli punkty mają taką samą współrzędną x to rosnąco po współrzędnej y. Mając posortowane punkty wyznaczamy bok naszego kwadratu stosując dwie zagnieżdżone pętle tak jak to robiliśmy w poprzednich podejściach. Różnica w tym rozwiązaniu polega na tym, że wewnętrzną pętlę przerywamy w momencie, gdy trafimy na punkt o innej współrzędnej x niż współrzędna x punktu wybranego przez pętlę zewnętrzną. Pseudokod poniżej:

for i = 0 to n - 1 do
  for j = i + 1 to n - 1 do
    if P[j].x != P[i].x then
      break
    // Tutaj sprawdzamy czy istnieją pozostałe 2 punkty, które utworzą kwadrat

Takie podejście gwarantuje nam, że w najgorszym wypadku wykonamy 2001^2 * (n / 2001) operacji. Dla ułatwienia obliczeń załóżmy, że mamy po 2000 punktów w 500 kolumnach. Da to nam 2000^2 * (10^6 / 2000) = 2 * 10^9 operacji. Biorąc pod uwagę limit 4s i szybkość Cube’a (serwer sprawdzający SPOJa) jest to akceptowalna wartość. Pozostaje kwestia szybkiego sprawdzenia czy istnieją pozostałe 2 punkty, które mają utworzyć kwadrat z naszym bokiem. Znowu korzystając z tego, że powierzchnia jest mała możemy to zrobić w czasie stałym. W tym celu tworzymy sobie tablicę o rozmiarach 2001 na 2001 elementów i zapisujemy wartość true w komórkach, w których są punkty. Oczywiście współrzędne punktów musimy zamienić na nieujemne dodając 1000 do każdej z nich.

Takie rozwiązanie gwarantowało AC.

Dzięki za wyjaśnienie
Wydawało mi się, ze właśnie tak to próbowałem rozwiązać. Muszę jeszcze raz zajrzeć do mojego kodu

Z tego co widzę w Twoim ostatnim zgłoszeniu to nie porządkujesz punktów wg. współrzędnych tylko dla każdego punktu starasz się odpowiednio przechodzić tablicę z punktami. Obawiam się, że przy takim podejściu problemem wydajnościowym może być to, że za dużo “skaczesz” po pamięci, ale nie mam 100% pewności bo to była taka 2 minutowa analiza Twojego rozwiązania :slight_smile: Jak jesteś zainteresowany to wklejam link do mojego rozwiązania: https://ideone.com/1OC2Vh23

No to widzę mocno przekombinowałem. Moje pierwsze zgłoszenie było najbliżej prawdy. Kolejne to już była zbędna akrobatyka programistyczna :wink:

Edit. Dla potomnych: korzystanie z unordered_map wprowadza spory narzut w porównaniu ze zwykłą tablicą. Nie spodziewałem się, ze to robi az taką różnicą.

Kolejny “FRAKATAL” i miało być tak pięknie - znaczy się ja zajmuję pierwsze miejsce - no ale niestety wyszło gorzej niż zwykle czyli tylko 8 zadań zaliczonych .

Rozpocząłem też kilka kolejnych które które wydawały się “łatwe” a niestety się od nich odbiłem

  • pierwsze zadanie to “25” w którym nie ogarniałem treści, a po pierwszym wysłaniu rozwiązania zorientowałem się że rozpatruje tylko przypadek z końcówka 25 na końcu liczby ( a pomijam 00, 50, 75 ). Postanowiłem czekać ( w tym czasie rozwiązywać inne zadania ) na jakąś dyskusję pod zadaniem . Ta rozpoczęła się dość późno i dopiero w tedy zorientowałem się o co dokładnie chodzi autorowi - zadanie zostawiłem sobie na “później” czyli nie zrobiłem .
  • Zadanie “Haft” - całkiem dobre zadanie bo w pierwszej chwili myślałem że przejdzie rozwiązanie typu “brutal” . Niestety to że wydaje się łatwe nie znaczy że jest - i po otrzymaniu przekroczenia czasu trzeba było się dokładniej przyjrzeć problemowi . Udało mi się wpaść na pomysł jak przyspieszyć algorytm w momencie testowania czy po każdej stronie od centrum w danej odległości jest nadal haft . Taka optymalizacja jednak nadal nie mieściła się w limicie czasu . I tu nastąpił kryzys optymalizacyjny - bo mój algorytm na końcu testował czy każde pole z haftem zostało wydziergane - a więc nadal w skrajnym przypadku ustawiał od 1 do N wyhaftowanie danego pola . Nie potrafiłem tego mozolnego ustawiania obejść .
  • Zadanie “Czworościan” - uuuuu … pierwsze co zrobiłem to sprawdziłem Wikipedie - i odbiłem się od tego co przeczytałem . Próbowałem w ciągu tych 32 jeszcze kilka razy zrozumieć co tam powypisywali ale ogólnie “wyznacznik macierzy” mnie przeraził i nie wiedziałem jak się do tego zabrać . Po konkursie postanowiłem zrobić to zadanie , obejrzałem 2 filmy na yt i zadanko rozwiązane – nowa wiedza w głowie .
  • Zadanie “Sok jabłkowy” - dokładnie sam nie wiem co nie poszło w tym zadaniu . U mnie dla maks testów ( 1000 jedynek w danych wejściowych ) robiło się 2 sek ( na starym lapku ) . “Brutal” z optymalizacją na sumy prefiksowe jednak nie przeszedł .
  • Zadanie “Kwadratowy śwwiat II” - domyśliłem się że sprawdzanie wszystkich kombinacji nie przejdzie więc wrzucałem liczby po x i y do tablicy o danym numerze N ( coś jak sortowanie kubełkowe dla każdej osi ) - no i tu dalej zwarcie w mózgu bo nie mogłem wymyślić jak dalej zoptymalizować .

Najgorsze jest to że na kilka godzin przed końcem konkursu już się poddałem ( miałem całą serie podejść do zadań które nie wiedziałem jak zoptymalizować ) .

Podsumowując - czekam na kolejną edycję - może pójdzie mi lepiej niż jak zwykle .

“Kwadratowy świat”, “Jąkała”, “Zlot kolekcjonerów monet” - proste, przyjemne zadanka w sam raz na rozgrzewkę przed pozostałymi :slight_smile:

“Pętla” - po pierwszym przeczytaniu (po łebkach) zadanie wydawało się proste (dwuwymiarowa tablica booli, sprawdzanie czy dany punkt był już odwiedzany), niestety czwarty test rozwiał moje nadzieje na kolejne zaliczone łatwe zadanie…

“25” - zadanie, które mnie rozwaliło. Siedziałem nad nim kilka godzin, wymyślając różne testy, w końcu doszedłem do wersji kodu, która dla każdego mojego testu daje dobry wynik, jednak nadal sędzia nie przyjmował :frowning: Jakby ktoś miał czas, to prosiłbym o jakąś wskazówkę co przeoczyłem (z góry przepraszam za syfiasty kod, tak to jest jak się najpierw pisze, potem myśli… <tu był link do kodu, ale się zmył :slight_smile:> ).

Warto też wspomnieć o zadaniu “czworościan” - próbowałem sobie różne rzeczy wyobrażać, szukałem w internecie jakichś wskazówek, nic z tego. Aż w końcu podstawiłem dane do pierwszego znalezionego wzoru na objętość czworościanu i dawał dobry wynik :slight_smile:

Ogółem zadania bardzo ciekawe, udało mi się rozwiązać 9 na 20, co nie jest moim zdaniem bardzo złym wynikiem. Niestety ta nieszczęsna 25 mnie zniechęciła, w innym wypadku pewnie bym spróbował rozwiązać jeszcze kilka. Wielki szacun dla organizatorów, z niecierpliwością czekam na następną edycję Fraktala, w której mam nadzieję, że pobiję swój dotychczasowy wynik.

Wesołego Nowego Roku! :slight_smile:

Masz błąd na tym samym teście, na którym wywalała się większość rozwiązań. Jego uproszczona wersja wygląda tak:
50117
Odpowiedzią jest 5, Twój program zwraca 6. Co ciekawe dla 5017 odpowiedź masz prawidłową. Rzeczywisty test w zadaniu prezentuje się następująco:
5013611499391318666414491496888118839396836143811634996198389384634133991634493896963181689646319187
Odpowiedzią jest 100, Twój program zwraca 196.

Serdeczne dzięki za podpowiedź, zadanie to spędzało mi sen z powiek :slight_smile:

A ja proszę o podpowiedź do pętli, męczy mnie a nijak nie mogę wpaść jak to ugryźć :slight_smile:

Uwaga! Poniższe rozwiązanie jest niepoprawne ponieważ Mariusz zmodyfikował zadanie po moich testach. Dzisiaj wrzucę poprawione omówienie. Przepraszam za wprowadzenie w błąd.

W tym zadaniu naszym celem jest stwierdzenie czy istnieje spójny niepusty podciąg trasy Jasia, który utworzy pętlę.

Pierwsze spostrzeżenie jest takie, że trasa jaką pokonał Jasiu jest krótka i zawiera co najwyżej 100 znaków, a zatem spokojnie możemy zbadać wszystkie możliwe podciągi.

Przejdźmy zatem do weryfikacji czy dany podciąg jest poprawną pętlą (łamaną). Sprawdźmy definicję łamanej.

Łamaną nazywamy figurę geometryczną, która jest sumą skończonej liczby odcinków takich, że każde dwa kolejne mają wspólny koniec oraz:

  • każde dwa kolejne odcinki i tylko dwa kolejne odcinki mają wspólny koniec,
  • żadne dwa następujące po sobie odcinki nie są zawarte w jednej prostej.

Zgodnie z treścią zadania nasz bohater może na trasie wykonywać skręty o 90 lub 180 stopni. Jednak jak widzimy w definicji łamanej nawroty (skręty o 180 stopni) spowodują, że dana figura nie będzie już łamaną ponieważ 2 następujące po sobie odcinki będą zawarte w jednej prostej. I to jest główny haczyk w tym zadaniu. W związku z powyższym pierwszym etapem jest sprawdzenie czy w wybranym podciągu trasy występują nawroty czyli: NS, SN, WE lub EW. Jeżeli występują to dany podciąg nie będzie poprawną pętlą.

Jeżeli nawroty nie występują to pozostało nam sprawdzić czy po przejściu całego podciągu wróciliśmy do punktu, z którym się zaczynał. Można to zrobić np. zliczając liczbę wystąpień liter N, S, E, W. Jeżeli N = S i E = W tzn. że wróciliśmy do punktu wyjścia, a co za tym idzie znaleźliśmy poprawną pętlę.

Wybranie podciągu do sprawdzenia ma złożoność O(n^2), sprawdzenie tego podciągu O(n), a zatem całość ma złożoność O(n^3) co przy maksymalnej wartości n = 100 jest w zupełności wystarczające.

jak dla mnie to rozwiązanie zadania pętla ma zbyt dużą złożoność, używając tablicy dwuwymiarowej mam rozwiązanie o złożoności O(n)

Oczywiście, że można. Możemy założyć sobie, że startujemy z punktu 100,100 i generować kolejne współrzędne. Wchodząc na dany punkt sprawdzamy czy byliśmy na nim wcześniej (co możemy odczytać właśnie z tablicy 2 wymiarowej) i jednocześnie sprawdzamy czy to nie jest nawrót itd.

Jednak specjalnie opisałem wolniejsze rozwiązanie, żeby uczyć ludzi, że nie ma sensu wytaczać armaty na muchy jeżeli zadanie tego nie wymaga. Ostatecznie drugim kryterium po liczbie rozwiązanych zadań jest czas ich rozwiązania.

Julia, testowałem Twoje ostatnie zgłoszenie i np. dla takiego testu:

1
NSEESSWWNNS

Twój program zwraca NIE, a powinien TAK, bo mamy pętlę EESSWWNN począwszy od 3 znaku.

Dopiero się przebiłem przez łatwe zadania. Bardzo fajnie napisane, gratulacje. Mimo już X edycji było czuć w nich dużo świeżości.

Jak dla mnie termin kolidował z wyjazdem do domu rodzinnego i lepieniem świątecznych pierogów, ale cieszę się, że frekwencja dopisała.