Jason. Cała informatyka w jednym miejscu!

Wrzesień i październik poświęciłem kolejnej książeczce informatycznej którą mam ochotę Wam zrecenzować bez otrzymania za to ani złotówki. "Algorytmy. Ilustrowany przewodnik" kupiłem jako jedną z pierwszych książek, zanim na dobre wciągnąłem się w wir czytania i wreszcie po latach, zmotywowałem się i przeczytałem ją od deski do deski. Wbijajcie do środka!

"ALGORYTMY. ILUSTROWANY PRZEWODNIK". CO O TYM SĄDZĘ?

Autorem książki jest niejaki Pan Aditya Bhargava. Jak dla mnie, pozycja rewelacyjna i warta uwagi każdego z przyszłych programistów o większym lub mniejszym doświadczeniu, bez względu na profeskę. To jest taki "level one" drogi do dziedziny algorytmiki. Jest dużo abstrakcji, porównań, ukochanych przeze mnie obrazków, ale z ostrożnym podsuwaniem coraz to nowych terminów, żeby nie odstraszyć czytelnika starającego się zrozumieć temat. Widać, że włożono pracę w staranne dobieranie kolejności nowych tematów. Nie dość, że stopień trudności jest precyzyjny, to jeszcze postarano się pokazać algorytmikę z kilku kategorii i punktów widzenia (sortowanie, struktury danych, terminologia itp.). Dużą pomocą naukową okażą się gotowe kody źródłowe napisane w Pythonie, które można sobie przepisać i zobaczyć jak one działają w praktyce! Niewątpliwie pomogły także i mnie, a w ramach ćwiczenia przeniosłem sobie program na inne języki i eksperymentowałem. Zawsze będę za połączeniem uczenia się z zabawą.

Ale, ale! W trakcie czytania lektury natrafiłem na dużą liczbę literówek, a część z nich znacząco utrudniła zrozumienie przebiegu algorytmu!!! Jak zapewne moi czytelnicy się spodziewają, przedstawię formułkę celem rozwiania wątpliwości i zasuwamy.

Recenzując książkę autorstwa Pana Aditya Bhargavy (przepraszam, jeśli odmiana jest nieprawidłowa) i prezentując swoje zdanie na jej temat, nie leżało w mojej intencji żadne złośliwe wytykanie błędów ani ośmieszenie. Jedynym moim celem publikacji recenzji było przedstawienie swojej subiektywnej opinii oraz sprostowanie pewnych przytoczonych treści, aby ewentualne ponowne wydanie książki było pozbawione wskazanych błędów, jeśli faktycznie takimi są (bo sam mogę się mylić!).

Start!

GRZESZKI KSIĄŻKI

Lecimy jak poprzednio, najpierw konkrety, potem pierdoły.

JEDNA DRUGA, A NIE JEDNA CAŁA!

Patrzały kierują się na stronę nr 9, tam gdzie algorytmy zaczynają się od wyszukiwania binarnego. To mi pokazało raz kolejny jak nawet niewielka dezinformacja może wydłużyć czas zrozumienia tematu. Konkretnie chodzi mi o instrukcję kalkulowania środka przedziału (skorzystajcie z zewnętrznych źródeł, jeśli nie kapujecie działania wyszukiwania binarnego):

mid = (low + high)

Suma jest, dzielenia nie ma! Skoro to ma być środek, to musi to być połowa sumy zmiennych odpowiadających za lewy i prawy koniec przedziału:

mid = (low + high) / 2

Skromnie dodam, że jest napisane poprawnie stronę wcześniej...

PYTHON NIE BYŁBY ZACHWYCONY...

Myślicie sobie, "coooo?". Tak, niestety. Nikt nie lubi błędów w kodach źródłowych. A już zwłaszcza w tutorialach. Jest ich od groma i uruchomienie kodów w takim stanie rozgniewało by mocno Pythona (choć podkreślam, że nie wszystkie dotyczą kategorii błędów składniowych). Oto one:

  1. brak wcięć dla instrukcji w kodzie źródłowym pod słowem kluczowym "def" (strona 41 i 43)
  2. brak nawiasów okrągłych dla wywołania funkcji "print" (strona 65)
  3. w jednym fragmencie jest "phone_book["jasia"]", a w kolejnym jest już klucz "jenny" (strona 80)
  4. złe wcięcie od początku definicji funkcji do instrukcji "print" (strona 82)
  5. dwukrotnie większe wcięcie instrukcji "return" w definicji funkcji "person_is_seller" (strona 108)
  6. dwukrotnie większe wcięcia wszystkich instrukcji (strona 110)
  7. odwrócenie wypisywanych na terminal wartości (to węzeł "a" ma wagę 6, a nie "b", strona 132)
  8. jeden raz jest napisane "costs["fin"]", a w całej reszcie obowiązuje klucz "meta" (strona 133)
  9. tekst "To się nazywa przecięciem zbiorów" powinien wskazywać na linijkę kodu wyżej (strona 149)
  10. brak wcięcia dla ostatnich dwóch instrukcji, które POWINNY być, gdyż mają one związek ze zmiennymi lokalnymi pętli "while" (strona 151)
  11. zmiana nazwy drugiej zmiennej pętli "for" ze "states_for_station" na "states" (strona 151)
  12. wzór w funkcji nie uwzględnia przypadku, gdy pojawia się zgodność liter w pierwszej komórce; wówczas doszłoby do wyjścia poza tablicę! (strona 182)

P.S.
Mogliście się przyzwyczaić, że listy numerowane umieszczam zawsze na końcu. Odstąpiłem od tego, gdyż uznałem tę listę błędów za punkt większej wagi, a zależy mi na tym, żebyście później się pilnowali podczas analizy tychże kodów i nie dziwili, że algorytmy się sypią.

GALIMATIAS NA PEŁNYCH OBROTACH

To dało mi najbardziej do wiwatu. Konkretnie to strona #138. Rozgryzałem po kolei zasadę działania algorytmu Dijkstry, aż trafiłem na tę stronę, która wymaga po mojemu większej lub mniejszej obróbki. Konkretnie to zdanie:

"Stary koszt dotarcia do węzła A wynosi 6"

a na rysunku poniżej gołym okiem widać, że trasa wyznacza drogę do mety, więc gdzie do węzła A??? Tekst nie odzwierciedla aktualnego stanu grafu zaprezentowanego na rysunku poniżej. Według mnie, ten napis powinien brzmieć tak:

"Koszt dotarcia do mety wynosi 7"

Ponadto, chyba jest podany błędny wynik kosztu dotarcia do węzła A. Na poprzedniej stronie jest 5, potem tymczasowo jest ustawione na 6, a po rysunkach grafów znowu nagle staje się piątką. Nie ma jak rozróżnić zapisów "na boku" jak w brudnopisie od tych, które są aktualnym stanem rzeczy na grafie.

Najbardziej rozproszyły mnie te niespójności. Strzałki zwrócone w stronę rysunków sugerują, że tekst prezentuje aktualną sytuację, a sam tekst temu przeczy i bredzi co innego. Po mojemu, powinno się jeszcze raz przyjrzeć tej całej stronie i trochę pozmieniać, żeby to miało ręce i nogi. Jeśli nie teksty, to rysunki. Żeby to sobie ułożyć w głowie, musiałem przebieg całego algorytmu od początku do końca narysować na wielkiej kartce A4. Nie żartuję!

NIESPÓJNOŚĆ CYFROWA

Interesuje nas strona #194, ale też i poprzednia bo ma związek z tym, o czym chcę w tym miejscu napisać. Jedna przekręcona cyfra spowodowała otrzymanie złego wyniku dystansu dzielącego dwa punkty w przestrzeni 5D (dlaczego w 5D, dowiecie się czytając treść). Rozpatrywane są dwa zestawy pięciu liczb oznaczających poziom zainteresowania poszczególnymi kategoriami oglądanych filmów przez dwie osoby, Patrycję i Justynę. Kłopot w tym, że druga para liczb użyta we wzorze nie pokrywa się z liczbami pobranymi z jednego z zestawów (u Justyny)!

Akcja            4            3

a we wzorze występuje takie odejmowanie:

(4 - 4)2

Rozumiecie już, mam nadzieję. W całej reszcie jest OK. Obstawiam, że błędnie wprowadzono liczbę na stronie #193, bo odjęcie od siebie czwórek powoduje, że wynik powstały ze wzoru jest "elegancki" (bez ułamków).

Podpunkt drugi to podanie błędnej odpowiedzi na zadane pytanie o odległość dwóch innych punktów, żeby czytelnik sobie poćwiczył. Mowa o odległości równej 24, tak? Yyyyy...

sqrt((3-2)2 + (4-5)2 + (4-1)2 + (1-3)2 + (4-1)2) = sqrt(1 + 1 + 9 + 4 + 3) = √18 = 3√2

Chyba nie bardzo. Algorytmy tak już działają, że jeden błąd w postępowaniu krok po kroku i otrzymujemy całkiem inny wynik!

PRZYDAŁYBY SIĘ NAWIASY

Ten punkt także ma dużo wspólnego z arytmetyką. Strona #233 pokazuje pewne wyliczenia w opisie rozwiązania zadania opatrzonego numerem 10.2. Proste pytanie: ile jest równe poniższe wyrażenie?

3 + 4 + 5/3 = ?

Książka "twierdzi", że to wynosi 4. Wynosiłoby, gdyby nie jeden brakujący szczegół:

(3 + 4 + 5)/3 = 4

Nawiasy! Nie ma nawiasów! A niestety z racji tego, że w matematyce każdy szczegół ma znaczenie, tak i teraz ja zwracam na to uwagę. Przynajmniej ja na pierwszy rzut oka stwierdziłem, że to nie jest dzielenie sumy składników przez 3, tylko zwykła suma składników, a ostatni z nich jest ułamkiem.

Wers niżej jest kolejne wyrażenie. To samo pytanie: ile to się równa?

3 + 4 + 5 + 5 + 5/5 = ?

I znowu źle! Nie 4,4! Bo żeby wynik wynosił 4,4, to musiałoby być napisane tak:

(3 + 4 + 5 + 5 + 5)/5 = 4,4

A w podanej postaci bez nawiasów wynik wynosi 18.

NAWET SPIS TREŚCI MOŻE ZASKOCZYĆ

Czy ktoś z Was zaczyna czytać od spisu treści? Ja tak i dzięki temu spostrzegłem wyjątkowy napis "Powtórzenie wiadomości" oznaczający stronę #160, a w całej reszcie widnieje "Powtórzenie". Jak przejdziecie do tej sto sześćdziesiątej strony, to tam też jest napisane "Powtórzenie wiadomości", więc to nie do końca taki "chochlik". To już bardziej mały "easter egg" niż błąd, aczkolwiek miło było o tym napisać.

KUSI, ŻEBY ZAJRZEĆ

Nie żeby mi to sprawiało jakieś cierpienie, aczkolwiek ciężko mi wykonywać jakieś ćwiczenie, które na tej samej stronie parę linijek niżej ma napisane rozwiązanie. Choć nie da się zaprzeczyć, że w książce "Algorytmy. Ilustrowany przewodnik" znajdują się odpowiedzi na samym końcu książki, to jednak na stronach #14, #124, #157 i #194 widać wyjątek odstający od reguły. Weźcie spróbujcie nie patrzeć na rozwiązanie :D!

"FACT"? "FACTORIAL"? A CO TO ZA RÓŻNICA?

To co prawda, powinno wlecieć pomiędzy inne punkty listy numerowanej, jednakże ciężko mi to było wpleść, bo to w zasadzie ani nie literówka, ani błąd składniowy, a ponadto nie byłem w stanie skrócić myśli do jednego zdania. Strona #45 kochani moi, i patrzymy na akapit poniżej nagłówka "Stos wywołań z rekurencją". Każdy bystry człowiek zauważy, że nazwa funkcji "factorial" została powtórzona aż trzy razy. Fajnie!

def fact(x):
    if x == 1:
        return
    else:
        return x * fact(x-1)

*pisownia oryginalna

To dlaczego potem używa się w kodzie nazwy "fact"??? Mało tego, stronę dalej korzysta się z tego skrótu w następnym akapicie! Po co ta komplikacja?

TO TABLICA CZY LISTA?
"Jeśli chodzi o listy, to przypadkiem podstawowym najczęściej jest tablica pusta lub zawierająca jeden element."

Taki cytat możecie ujrzeć na stronie #72 dotyczący podziału przypadku podstawowego i rekurencyjnego w stosunku do techniki znanej jako "dziel i rządź". Miałem konsternację: "to tablica czy lista, bo to ma znaczenie?". To nie żadne kąśliwości, tylko to w końcu książka prezentująca algorytmy, a co za tym idzie między innymi struktury danych i nie wolno stawiać znaku równości między listą a tablicą. W Pythonie może i można stosować takie kombinacje, aczkolwiek w zdecydowanej większości języków wysokiego poziomu, już konieczna jest konwersja.

Domyślam się, że to mógł być skrót myślowy oraz mam świadomość, że zawsze w programie można dokonać konwersji z tablicy na listę i na odwrót, także traktować to z przymrużeniem oka.

REPLAY

Bardziej leksykalny śmieszek niż uwaga, który możecie dostrzec na stronach #80 i #81. Fraza "wyobraź sobie" pojawia się aż pięć razy! Kto nie wierzy, niech policzy...A na stronie #91 jest już inna fraza, "w takiej sytuacji"...która występuje dwukrotnie w jednym akapicie i które dzieli je tylko jedno zdanie!

Powtarzam. Żadne czepianie się słów ani wytykanie, tylko fajnie to brzmi jak szybko przeczytacie treść na podanych stronach.

LITERÓWKI I INNE DROBNOSTKI

Kruczki są jak w każdej lekturze, więc podsyłam wszystkie znalezione przeze mnie literówki "Algorytmy. Ilustrowany przewodnik". Gotowi? S'il vous plaît:

LITERÓWKI
  1. "[...] o czasie wykonywania logarytmu [...]", zamiast "[...] o czasie wykonywania algorytmu [...]" (strona 7)
  2. "Czasy wykonywania algorytmów sortujących", zamiast "Czasy wykonywania algorytmów wyszukujących" (rysunek dotyczy algorytmów wyszukujących, strona 10)
  3. "Aha, 32 ms!", zamiast "Aha, 30 ms!" (w poprzednim zdaniu jest napisane "30 ms", strona 11)
  4. "Nazwa notacja dużego O [...]" ("notacja dużego O" powinna być ujęta w cudzysłów, strona 13)
  5. "O ", zamiast "O" (spacja objęta w cudzysłów zaraz po literze, strona 13)
  6. "[...] w książce telefonicznej." (kropka przed zdaniem w nawiasie, strona 17)
  7. "[...] o nazwiskach na A." (kropka przed zdaniem w nawiasie, strona 17 i 221)
  8. "[...] pamięć w komputerze, który można porównać [...]", zamiast "[...] pamięć w komputerze, którą można porównać [...]" (TĘ pamięć, strona 23)
  9. "Ciąg znaków fe0ffeeb [...]" (adres "fe0ffeeb" powinien być ujęty w cudzysłów, strona 23)
  10. "[...] jednym z najprostszym rozwiązań [...]", zamiast "[...] jednym z najprostszych rozwiązań [...]" (strona 25)
  11. "Czy do implementacji takiej kolejki użyłbyś tablicy, czy listy powiązanej." (kropka przed zdaniem w nawiasie, a sam znak powinien być znakiem zapytania, strona 31 i 223)
  12. "[...] na Facebooku postanawia założyć konto [...]", zamiast "[...] na Facebooku postanawiasz założyć konto [...]" albo "[...] na Facebooku ktoś postanawia założyć konto [...]" (strona 32)
  13. "Jak się masz Magda?", zamiast "Jak się masz, Magda?" (w kodzie źródłowym funkcji "greet2" na poprzedniej stronie, występuje ten sam łańcuch z przecinkiem, strona 44)
  14. "Spójrz np. na wybieranie przez sortowanie, [...]", zamiast "Spójrz np. na sortowanie przez wybieranie, [...]" (strona 66)
  15. "26 % 10 = 2", zamiast "26 % 10 = 6" (błędny wynik wyznaczania reszty z dzielenia, strona 93)
  16. "[...] z najmniejszą liczbę zmian?", zamiast "[...] z najmniejszą liczbą zmian?" (strona 97)
  17. "[...] rozwiązujący problem najkrótszej drogi [...]", zamiast "[...] rozwiązujący problem wyboru najkrótszej drogi [...]" (strona 98)
  18. wypunktowana lista typów pytań (nadmiarowe znaki zapytania przed zdaniami w nawiasie, strona 102)
  19. "A czy zatem jest szybsza droga do parku." (kropka zamiast znaku zapytania, strona 124)
  20. "[...] zobaczmy, jak nasz algorytm find_lowest_cost_node sprawdzi się w działaniu.", zamiast "[...] zobaczmy, jak nasz algorytm Dijkstry sprawdzi się w działaniu." (błędna nazwa funkcji, gdyż tłumaczenie dotyczy algorytmu Dijkstry, strona 134)
  21. "[...] na każdym z poniższym grafów.", zamiast "[...] na każdym z poniższych grafów." (strona 139)
  22. "[...] więc staran się [...]", zamiast "[...] więc staramy się [...]" (strona 146)
  23. "Innymi słowy, w zbiorze nie może być duplikatów." (zdanie niepotrzebnie opatrzone kursywą, strona 148)
  24. "Zatem w przykładzie stacja kone [...]" ("kone" powinno być ujęte w cudzysłów, strona 148)
  25. "[...] po dwie dla każdego miast, [...]", zamiast "[...] po dwie dla każdego z miast, [...]" (strona 155)
  26. "[...] jeśli włożymy do plecaka stereo zamiast gitary [...]", zamiast "[...] jeśli włożymy do plecaka stereo zamiast gitarę [...]" (strona 167)
  27. "Aktualnie maksymalna wartość tego plecaka wynosi 2000 zł", zamiast "Aktualnie maksymalna wartość tego plecaka wynosi 3000 zł" (przedmiot "Stereo" kosztuje na przykładzie 3000 zł, strona 168)
  28. "[...] pominąłem część nieistotnych spraw związanych z wstawianiem [...]", zamiast "[...] pominąłem część nieistotnych spraw związanych ze wstawianiem [...]" (strona 170)
  29. "[...] mamy listę miejsce do zwiedzenia.", zamiast "[...] mamy listę miejsc do zwiedzenia." (strona 176)
  30. "[...] musisz ich jakość przenieść na graf.", zamiast "[...] musisz ich jakoś przenieść na graf." (strona 192)
  31. ">>An Interactive Giude [...]", zamiast ">>An Interactive Guide [...]" (strona 207 - przypis)
  32. "Najpierw próbuję szyfru a =1, [...]", zamiast "Najpierw próbuję szyfru a = 1, [...]" (brak spacji po znaku równości, strona 217)
  33. "W przeciwnym przypadku szukanego elementu nie ma strukturze.", zamiast "[...] nie ma w strukturze." (strona 226)
BŁĘDY W RYSUNKACH

Druga porcja przeznaczona do znalezionych błędów w rysunkach, które w książce "Algorytmy. Ilustrowany przewodnik" nie skończyły się na paru wystąpieniach:

  1. "1. najczęściej odtwarzane są utwory Radiohead" (nazwa zespołu pozbawiona cudzysłowów, strona 33)
  2. "1. na drugim miejscu znajduje się kishore kumar" (nazwa zespołu napisana małymi literami i bez cudzysłowów, strona 33)
  3. "1. The Strokes" (według tłumaczeń działania algorytmu, powinno być "1. Radiohead", strona 34)
  4. brak strzałki w schemacie blokowym od "Jeśli znajdziesz pudełko, dodaj je do stosu" do "Wróć do stosu" (strona 39)
  5. źle przepisany warunek "if i <= 1", bo w kodzie powyżej jest "if i <= 0" (strona 41)
  6. brak strzałki w schemacie blokowym od "if i <= 1 - koniec pracy" do "W przeciwnym razie wywołaj countdown z i - 1", za to występuje od bloku "print i" (strona 41)
  7. nieuwzględnienie liczby 5 w prawej podtablicy w przedostatnim wywołaniu (strona 69)
  8. nieuwzględnienie liczby 5 w prawej podtablicy, tam gdzie napis "Nadal O(n) elementów"! (strona 71)
  9. niespójny trzeci napis, w którym brakuje na początku tekstu "Trzeba sprawdzić", a na końcu wpisano nadmiarowo "= 2 sek" (strona 74)
  10. błędny zapis złożoności czasowej w tabelce na przykładzie Magdy (O(i) zamiast O(1), strona 75)
  11. błędna nazwa algorytmu operującego na grafie ważonym (w książce rozpatrywany jest algorytm Dijkstry, a napisano o algorytmie Bellmana-Forda, strona 120)
  12. brak uwzględnienia w grafie przypadku otrzymania pięciu złotych, o którym mowa w akapicie (strona 123)
  13. brak wagi liczbowej od węzła B do węzła A (strona 135)
  14. pobieranie kosztu niewłaściwego węzła ("cost = costs[node]", zamiast "cost = costs[n]", wynika to ze strony 135, strona 137)
  15. algorytm dokładny ma napisaną złożoność czasową O(n!), a wcześniej była mowa o O(2n) (strona 152)
  16. na rysunku laptop jest wart 3000 zł, a w dalszych przykładach jest wart już tylko 2000 zł (strona 162)

CZY KSIĄŻKA JEST WARTA ZAKUPU?

Jak najbardziej! "Algorytmy. Ilustrowany przewodnik" jest wręcz znakomitym wejściem w świat algorytmiczny, który nie oczekuje od czytelnika żadnej dotychczasowej wiedzy z algorytmiki (jedynie programowania na poziomie podstawowym). Wiele zagadnień jest tłumaczonych na chłopski rozum i jeśli przymknie się oko na te błędy w kodach źródłowych, to naprawdę nie rozczarujecie się na lekturze. Po przeczytaniu jej ZE ZROZUMIENIEM, poczujecie się znacznie mądrzejsi.

Jeśli naprawdę chcecie, aby ta wiedza została w głowie, to poradzę Wam to samo co ja zrobiłem: przeanalizujcie sobie działanie każdego algorytmu, narysujcie przebieg iteracji na kartce i potem najważniejsze, napiszcie sami kod w innym języku niż Python (wspomagając się podanym kodem, oczywiście)! Zobaczycie, raz-dwa będzie łatwiej to zrozumieć i wtedy próba zapamiętywania setek instrukcji odejdzie do lamusa!

"Algorytmy. Ilustrowany przewodnik"

Lektura "Algorytmy. Ilustrowany przewodnik" oprowadza czytelnika po świecie algorytmiki wyjaśniając każde zagadnienie powoli ze szczegółami. Jest znakomitym wyborem dla osób, które nie mają pojęcia o algorytmice i nie mają ochoty zaczynać od skomplikowanej terminologii "oblepionej" wzorami matematycznymi.


Może się wydawać, że algorytmy nie są ważnym tematem skoro nie znajduje się jej w wymaganiach w większości ofert pracy. Moim skromnym zdaniem, naprawdę warto mieć jakieś pojęcie o tej porcji wiedzy, która co prawda nie stoi na drodze do nauki samego programowania czy nawet znalezienia zatrudnienia (chociaż ja miałem jedno pytanie na rozmowie sprawdzające wiedzę z algorytmów), natomiast stanowi taki zestaw sprawdzonych patentów na dany problem, który może tylko przyspieszyć Waszą pracę nad aplikacją. Wiedza na pewno zaplusuje u rekruterów. Książka "Algorytmy. Ilustrowany przewodnik" jest według mnie takim pierwszym poziomem wtajemniczenia, którą każdy adept informatyki powinien przynajmniej oblecieć. Może wydawnictwo kiedyś rozważy ponowne wydanie książki i weźmie pod uwagę tę skromną recenzję?

PODOBNE ARTYKUŁY