Jak się moi wierni Czytelnicy (a można ich policzyć na palcach pijanego pracownika tartaku) zdążyli zorientować, od czasu do czasu publikuję na łamach swego bloga pchełki. Dotychczas pchełki dzieliły się na dwie kategorie: VBA oraz SQL.
Od niedawna próbuję wgryźć się w Pythona. Jakkolwiek dwuznacznie by to nie brzmiało, zapewniam, że nie chodzi o żadne zwierzę, tylko o skryptowy język programowania.
Tym samym dziś otwieram nowy rozdział: Pchełki Python. Nie wiem jeszcze czy coś z tego będzie, ale próbować trzeba.
Python ma kilka bardzo sympatycznych cech, które odróżniają go od rzeszy innych języków. Na przykład bloki kodu - w innych językach trzeba je brać w nawias, a w Pythonie wystarczy zrobić wcięcie. Trochę to jest nieintuicyjne na początku, ale jak się człowiek przyzwyczai, okazuje się całkiem praktyczne.
Sporo rzeczy jest ściągniętych z C / C++. A ponieważ swego czasu sporo programowałem i w jednym i w drugim, będzie mi się prościej nauczyć.
Przynajmniej w teorii...
Zanim przejdę do mojej pierwszej pchełki w Pythonie, jeszcze jedna uwaga: istnieje wiele różnych środowisk programistycznych do pisania kodu w Pythonie. Ja zdecydowałem się na PyCharm. Raczej losowo, ale póki co nie narzekam. Bardzo sprawnie działające środowisko.
A teraz pchełka:
n, step = (17, 0) while n!=1: if n % 2 == 0: n /= 2 else: n = n * 3 + 1 step += 1 print( "step = %d, n = %d" % (step, n), end = "; " if step % 5 != 0 else "\n")
Powyższe sześć linii kodu generuje kolejne elementy ciągu Collatza, począwszy od zadanej wartości początkowej aż do jedynki. O tym, czym jest ciąg Collatza, a także hipoteza Collatza, pisałem jakiś czas temu (tutaj można poczytać).
Teraz omówimy sobie szczegółowo powyższy kod:
n, step = (17, 0)
W pierwszej linii definiujemy dwie zmienne: n (bieżący element ciągu) oraz step (numer kolejny bieżącego elementu). Zaczynamy od n = 17, chociaż można zacząć od dowolnej innej liczby całkowitej dodatniej. Zmienną step ustawiamy na zero.
Jak widać, nie ma potrzeby deklarowania typów zmiennych - Python sam przypisze typy na podstawie początkowych wartości. Rzuca się również w oczy to, że po lewej stronie znaku równości znajdują się dwie zmienne, a po prawej - w nawiasach okrągłych - dwie wartości. Tak, właśnie tak: można jedną operacją podstawienia przypisać wartości wielu zmiennym na raz! Bardzo wygodne.
while n != 1:
Otwieramy pętlę typu while, która będzie się wykonywać tak długo, dopóki n będzie różne od jedynki (jak wiadomo zgodnie z hipotezą Collatza niezależnie od tego, od jakiego elementu zaczniemy, zawsze skończymy na jedynce). Linia otwierająca pętlę musi obowiązkowo kończyć się dwukropkiem.
if n % 2 == 0: n /= 2
Tutaj mamy blok warunkowy czyli instrukcję if. Warunkiem jest n%2 czyli sprawdzamy parzystość bieżącego elementu ciągu. Jeżeli jest on parzysty, zmniejszamy go o połowę (przy okazji: operatory +=, -=, /= oraz *= działają identycznie jak w C++)
else: n = n * 3 + 1
Jeżeli n jest nieparzyste, zgodnie z algorytmem mnożymy przez trzy i dodajemy jedynkę.
print( "step = %d, n = %d" % (step, n), end = "; " if step % 5 != 0 else "\n")
Tu wypisujemy informacje o aktualnie wykonywanej iteracji: numer kroku oraz bieżącą wartość elementu ciągu. Funkcja print działa bardzo podobnie jak w C / C++, a więc można w tekście umieszczać elementy zaczynające się od symbolu %, które potem zostaną podmienione na konkretne wartości. Wartości przekazuje się za cudzysłowem, po symbolu % (tutaj są dwie: step oraz n; wartość zmiennej step zostanie wstawiona w miejsce pierwszego %d, a wartość n w miejsce drugiego %d). Funkcja print może przyjmować opcjonalny parametr o nazwie 'end' - to jest tekst, który zostanie umieszczony na końcu wypisywanego tekstu. Domyślnie jest to znak końca linii ("\n"), tu jednak robimy mały trik. Otóż za parametr 'end' podstawiamy wynik działania operatora ternarnego. Jeżeli ktoś jeszcze pamięta z C++, operator w tym języku ma składnię: warunek?wartosc1:wartosc2, i zwróci wartosc1 jeżeli warunek jest prawdziwy, lub wartość2, jeżeli warunek jet fałszywy. Składnia operatora ternarnego w Pythonie nie jest tak elegancka jak w C++, niemniej jednak operator taki istnieje. Działa on tak: wartosc1 if warunek else wartosc2. W tym przypadku warunkiem jest step%5!=0, co oznacza, że w każdym kroku, którego numer nie dzieli się bez reszty przez pięć, kończymy średnikiem (ze spacją), a w krokach będących całkowitymi wielokrotnościami piątki wpisujemy na końcu znak końca linii ("\n"). W ten sposób grupujemy wyniki w liniach po pięć kroków, dzięki czemu na ekranie zmieści się więcej informacji.
step += 1
Zwiększamy numer kroku o jeden. Przy okazji, w Pythonie nie ma operatora ++ znanego z C++
I tu koniec pętli (i pchełki też)- jeszcze raz zwracam uwagę na fakt, że nie musimy zamykać żadnych nawiasów, treść pętli jest zdefiniowana wyłącznie wcięciami w kodzie.
Efekt działania powyższego kodu jest taki:
step = 1, n = 52; step = 2, n = 26; step = 3, n = 13; step = 4, n = 40; step = 5, n = 20
step = 6, n = 10; step = 7, n = 5; step = 8, n = 16; step = 9, n = 8; step = 10, n = 4
step = 11, n = 2; step = 12, n = 1;
Sprawdźmy jak zadziała kod dla innej wartości począkowej: 31764
step = 1, n = 15882; step = 2, n = 7941; step = 3, n = 23824; step = 4, n = 11912; step = 5, n = 5956
step = 6, n = 2978; step = 7, n = 1489; step = 8, n = 4468; step = 9, n = 2234; step = 10, n = 1117
step = 11, n = 3352; step = 12, n = 1676; step = 13, n = 838; step = 14, n = 419; step = 15, n = 1258
step = 16, n = 629; step = 17, n = 1888; step = 18, n = 944; step = 19, n = 472; step = 20, n = 236
step = 21, n = 118; step = 22, n = 59; step = 23, n = 178; step = 24, n = 89; step = 25, n = 268
step = 26, n = 134; step = 27, n = 67; step = 28, n = 202; step = 29, n = 101; step = 30, n = 304
step = 31, n = 152; step = 32, n = 76; step = 33, n = 38; step = 34, n = 19; step = 35, n = 58
step = 36, n = 29; step = 37, n = 88; step = 38, n = 44; step = 39, n = 22; step = 40, n = 11
step = 41, n = 34; step = 42, n = 17; step = 43, n = 52; step = 44, n = 26; step = 45, n = 13
step = 46, n = 40; step = 47, n = 20; step = 48, n = 10; step = 49, n = 5; step = 50, n = 16
step = 51, n = 8; step = 52, n = 4; step = 53, n = 2; step = 54, n = 1;
A dla 8841?
step = 1, n = 26524; step = 2, n = 13262; step = 3, n = 6631; step = 4, n = 19894; step = 5, n = 9947
step = 6, n = 29842; step = 7, n = 14921; step = 8, n = 44764; step = 9, n = 22382; step = 10, n = 11191
step = 11, n = 33574; step = 12, n = 16787; step = 13, n = 50362; step = 14, n = 25181; step = 15, n = 75544
step = 16, n = 37772; step = 17, n = 18886; step = 18, n = 9443; step = 19, n = 28330; step = 20, n = 14165
step = 21, n = 42496; step = 22, n = 21248; step = 23, n = 10624; step = 24, n = 5312; step = 25, n = 2656
step = 26, n = 1328; step = 27, n = 664; step = 28, n = 332; step = 29, n = 166; step = 30, n = 83
step = 31, n = 250; step = 32, n = 125; step = 33, n = 376; step = 34, n = 188; step = 35, n = 94
step = 36, n = 47; step = 37, n = 142; step = 38, n = 71; step = 39, n = 214; step = 40, n = 107
step = 41, n = 322; step = 42, n = 161; step = 43, n = 484; step = 44, n = 242; step = 45, n = 121
step = 46, n = 364; step = 47, n = 182; step = 48, n = 91; step = 49, n = 274; step = 50, n = 137
step = 51, n = 412; step = 52, n = 206; step = 53, n = 103; step = 54, n = 310; step = 55, n = 155
step = 56, n = 466; step = 57, n = 233; step = 58, n = 700; step = 59, n = 350; step = 60, n = 175
step = 61, n = 526; step = 62, n = 263; step = 63, n = 790; step = 64, n = 395; step = 65, n = 1186
step = 66, n = 593; step = 67, n = 1780; step = 68, n = 890; step = 69, n = 445; step = 70, n = 1336
step = 71, n = 668; step = 72, n = 334; step = 73, n = 167; step = 74, n = 502; step = 75, n = 251
step = 76, n = 754; step = 77, n = 377; step = 78, n = 1132; step = 79, n = 566; step = 80, n = 283
step = 81, n = 850; step = 82, n = 425; step = 83, n = 1276; step = 84, n = 638; step = 85, n = 319
step = 86, n = 958; step = 87, n = 479; step = 88, n = 1438; step = 89, n = 719; step = 90, n = 2158
step = 91, n = 1079; step = 92, n = 3238; step = 93, n = 1619; step = 94, n = 4858; step = 95, n = 2429
step = 96, n = 7288; step = 97, n = 3644; step = 98, n = 1822; step = 99, n = 911; step = 100, n = 2734
step = 101, n = 1367; step = 102, n = 4102; step = 103, n = 2051; step = 104, n = 6154; step = 105, n = 3077
step = 106, n = 9232; step = 107, n = 4616; step = 108, n = 2308; step = 109, n = 1154; step = 110, n = 577
step = 111, n = 1732; step = 112, n = 866; step = 113, n = 433; step = 114, n = 1300; step = 115, n = 650
step = 116, n = 325; step = 117, n = 976; step = 118, n = 488; step = 119, n = 244; step = 120, n = 122
step = 121, n = 61; step = 122, n = 184; step = 123, n = 92; step = 124, n = 46; step = 125, n = 23
step = 126, n = 70; step = 127, n = 35; step = 128, n = 106; step = 129, n = 53; step = 130, n = 160
step = 131, n = 80; step = 132, n = 40; step = 133, n = 20; step = 134, n = 10; step = 135, n = 5
step = 136, n = 16; step = 137, n = 8; step = 138, n = 4; step = 139, n = 2; step = 140, n = 1
I tak dalej.
Tymczasem czas na zejście ze zmywaka, nadchodzi bowiem coroczny czas staropogańskiego obżarstwa w sąsiedztwie zamordowanego, obwieszonego plastikiem drzewka. Drzewko jest dodatkowo podpięte do świecącego pastucha elektrycznego.
Alleluja!
Jeżeli chcesz do komentarza wstawić kod, użyj składni:
[code]
tutaj wstaw swój kod
[/code]
Jeżeli zrobisz literówkę lub zmienisz zdanie, możesz edytować komentarz po jego zatwierdzeniu.