├── README.md ├── warsztat_1 ├── Python_101.ipynb ├── Readme.md ├── testy_rozwiazan_1 │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ ├── zadanie4.py │ └── zadanie5.py └── zadania_domowe_1 │ ├── zadanie0.py │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ ├── zadanie4.py │ └── zadanie5.py ├── warsztat_2 ├── README.md ├── p4b-funkcje.pdf ├── testy_rozwiazan_2 │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ ├── zadanie4.py │ ├── zadanie5.py │ └── zadanie6.py ├── zadania_z_zajec │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ ├── zadanie4.py │ ├── zadanie5.py │ ├── zadanie6.py │ ├── zadanie7.py │ └── zadanie8.py └── zadanie_domowe_2 │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ ├── zadanie4.py │ ├── zadanie5.py │ └── zadanie6.py ├── warsztat_3 ├── Programowanie_z_klasa.ipynb ├── README.md ├── praca_domowa_3 │ ├── zadanie_1.py │ └── zadanie_1_rozwiazanie.py └── testy_rozwiazan_3 │ └── zadanie1.py ├── warsztat_4 ├── README.md ├── another_copy_p4b_logo.bmp ├── another_file.txt ├── conferences_data.csv ├── copy_p4b_logo.bmp ├── multiline_file.txt ├── p4b_logo.bmp ├── pliki.ipynb ├── praca_domowa │ ├── odpowiedzi.csv │ ├── pytania.csv │ ├── stolice.csv │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ └── zadanie_4.py ├── rozwiazania │ ├── odpowiedzi.csv │ ├── pytania.csv │ ├── stolice.csv │ ├── zadanie1.py │ ├── zadanie2.py │ ├── zadanie3.py │ └── zadanie4.py └── test.txt ├── warsztat_5 ├── README.md ├── generatory.ipynb ├── praca_domowa │ ├── zadanie_1.py │ ├── zadanie_2.py │ ├── zadanie_3.py │ └── zadanie_4.py ├── rozwiazania │ ├── zadanie_1.py │ ├── zadanie_2.py │ ├── zadanie_3.py │ └── zadanie_4.py └── testy │ ├── zadanie1.py │ └── zadanie3.py ├── warsztat_6 ├── Ssssssnake.ipynb └── przykłady │ ├── 01_initial_pygame_programm.py │ ├── 02_kolko_i_kwadrat.py │ ├── 03_kolko_i_kwadrat_fps.py │ ├── 04_kolko_i_kwadrat_no_voice.py │ ├── 05_segmenty.py │ ├── 06_moving_snake.py │ ├── 07_moving_snake_with_snake_class.py │ ├── 08_controling_snake.py │ ├── 09_better_controling_snake.py │ ├── 10_feed_the_snake.py │ └── 11_growing.py └── warsztat_7 ├── test_zad01_flatten.py ├── test_zad02_a_bank_account.py ├── test_zad02_b_test_bank_account_fixtures.py ├── test_zad03_test_bank_account_with_promo.py ├── testowanie.ipynb ├── zad01_flatten.py ├── zad02_bank_account.py ├── zad03_bank_account_with_promo.py └── zad04_ugly_roman_numbers.py /README.md: -------------------------------------------------------------------------------- 1 | # Python 4 Beginners 2 | ## Ważne linki 3 | Informacje organizacyjne: 4 | [https://www.facebook.com/events/436879610041461/](https://www.facebook.com/events/436879610041461/) 5 | 6 | Materiały z zajęć: 7 | [https://github.com/daftcode/python4beginners](https://github.com/daftcode/python4beginners) 8 | ## Kontakt 9 | [python4beginners@daftcode.pl](python4beginners@daftcode.pl) 10 | ## Przygotowanie środowiska pracy przed zajęciami 11 | ### Instalacja Python 3.6 12 | Żeby nie tracić czasu w trakcie warsztatu, zależałoby nam żebyście przyszli na zajęcia z zainstalowaną odpowiednią wersją Pythona. Poniżej opisana jest krótka instrukcja instalacji dla najpopularniejszych systemów operacyjnych. 13 | 14 | W przypadku problemów z instalacją możesz się z nami kontaktować mailowo ;) 15 | #### Windows 16 | Wejdź na stronę [https://www.python.org/downloads/release/python-363/](https://www.python.org/downloads/release/python-363/) i pobierz odpowiedni instalator z sekcji `Files` - `Windows x86-64 executable installer` dla systemu 64-bitowego lub `Windows x86 executable installer` dla systemy 32-bitowego. 17 | 18 | Uruchom pobrany instalator. Zaznacz opcję `Add Python 3.6 to PATH`, a następnie kliknij `Install Now`. 19 | #### macOS 20 | Wejdź na stronę [https://www.python.org/downloads/release/python-363/](https://www.python.org/downloads/release/python-363/) i pobierz odpowiedni instalator z sekcji `Files` - `Mac OS X 64-bit/32-bit installer`. Uruchom pobrany plik i dokończ instalację. 21 | #### Linux 22 | Istnieje duża szansa, że masz zainstalowanego odpowiedniego pythona na swoim komputerze. W celu sprawdzenia jaka wersja jest zainstalowana, wpisz w terminalu: 23 | ```bazaar 24 | python3 --version 25 | ``` 26 | Jeżelu uzyskasz wynik `Python 3.6.x` - jesteś gotowy na zajęcia. W przypadku, gdy nie zostanie odnaleziona komenda `python3` lub zainstalowana będzie niższa wersja niż `Python 3.6`, należy podążać za kolejnymi krokami, zależnymi od systemu, który posiadasz. 27 | ##### Debian lub Ubuntu 28 | Użyj w terminalu następującej komendy: 29 | ```bazaar 30 | sudo apt-get install python3.6 31 | ``` 32 | Dla wersji Ubuntu starszych niż 16.10 powyższa komenda może nie zadziałać. W takiej sytuacji należy skorzystać z deadsnakes PPA: 33 | ```bazaar 34 | sudo add-apt-repository ppa:deadsnakes/ppa 35 | sudo apt-get update 36 | sudo apt-get install python3.6 37 | ``` 38 | ##### Fedora (22+) 39 | Użyj w terminalu następującej komendy: 40 | ```bazaar 41 | sudo dnf install python3 42 | ``` 43 | Dla starszych wersji Fedory możesz dostać błąd mówiący o tym, że komenda `dnf` nie została znaleziona. W takiej sytuacji należy skorzystać z komendy `yum`. 44 | ##### openSUSE 45 | Użyj w terminalu następującej komendy: 46 | ```bazaar 47 | sudo zypper install python3 48 | ``` 49 | ### Sprawdzenie, czy Python 3.6 jest zainstalowany 50 | Wpisz w terminalu następującą komendę: 51 | ```bazaar 52 | python3.6 --version 53 | ``` 54 | Jeżeli powyższa komenda zwróci wynik `Python 3.6.x` oznacza to, że masz zainstalowaną odpowiednią wersję Pythona. 55 | 56 | Na Windowsie powyższa komenda może nie zadziałać. Wtedy należy użyć w `Wierszu polecenia`: 57 | ```bazaar 58 | python --version 59 | ``` 60 | Powinno ono zwrócić wynik `Python 3.6.x`. 61 | ### Wybór edytora tekstu 62 | Programowanie w Pythonie nie wymaga żadnych specjalistycznych narzędzi - wystarczy korzystać z edytora tekstu. Na zajęciach możesz korzystać z dowolnego edytora. Jeżeli nie wiesz co wybrać, polecamy Sublime Text [https://www.sublimetext.com/](https://www.sublimetext.com/). 63 | -------------------------------------------------------------------------------- /warsztat_1/Readme.md: -------------------------------------------------------------------------------- 1 | # Uruchamianie Pythona z linii poleceń 2 | Na pierwszych zajęciach pojawiło się trochę pytań o to, jak należy uruchamiać programy w pythonie. Z pythonem pracować będziemy z poziomu terminala - poniżej krótka instrukcja. 3 | 4 | ## Włączanie terminala 5 | #### Windows: 6 | ``` 7 | Start → Wszystkie programy → Akcesoria → Wiersz poleceń 8 | ``` 9 | #### macOS 10 | ``` 11 | Aplikacje → Narzędzia → Terminal 12 | ``` 13 | #### Linux 14 | Różnie w zależności od dystrybucji, ale pewnie coś w stylu 15 | ``` 16 | Aplikacje → Akcesoria → Terminal 17 | ``` 18 | 19 | ## Podstawowe komendy 20 | ### Przechodzenie pomiędzy folderami 21 | #### Windows, macOS, Linux 22 | ``` 23 | cd nazwa_folderu 24 | ``` 25 | np. żeby przejść na pulpit 26 | ``` 27 | cd Desktop 28 | ``` 29 | powracanie do katalogu nadrzędnego: 30 | ``` 31 | cd .. 32 | ``` 33 | W trakcie wpisywania nazwy folderu można nacisnąć TAB, wtedy terminal automatyczne uzupełnia resztę nazwy lub po wciśnięciu TABa dwa razy wyświetli propozycje folderów, których nazwy zaczynają się tak jak wpisany przez nas fragment nazwy. 34 | ### Wyświetlanie aktualnego folderu 35 | #### Windows 36 | ``` 37 | cd 38 | ``` 39 | #### macOS, Linux 40 | ``` 41 | pwd 42 | ``` 43 | ### Wylistowanie zawartości folderu 44 | #### Windows 45 | ``` 46 | dir 47 | ``` 48 | #### macOS, Linux 49 | ``` 50 | ls 51 | ``` 52 | ### Tworzenie folderu 53 | #### Windows, macOS, Linux 54 | ``` 55 | mkdir nazwa_folderu 56 | ``` 57 | ## Uruchamianie pythona w terminalu 58 | Na zajęciach interpreter pythona będziemy uruchamiać z terminala. Żeby to zrobić, musimy sprawdzić w jaki sposób powinniśmy odwoływać się u siebie do pythona 3.6. 59 | ### Sprawdzanie komendy do uruchamiania Pythona 60 | Wpisz w terminalu 61 | ``` 62 | python3.6 --version 63 | ``` 64 | Jeżeli pojawi się wynik w postaci `Python 3.6.x`, oznacza to, że to nazwy `python3.6` powinniśmy używać do uruchamiania pythona na swoim komputerze. 65 | #### Windows 66 | Na Windowsie prawdopodobnie zainstalowany Python będzie dostępny w terminalu pod nazwą `python`. 67 | Żeby to sprawdzić, wpisz 68 | ``` 69 | python --version 70 | ``` 71 | Jeżeli pojawi się wynik w postaci `Python 3.6.x`, oznacza to, że to nazwy `python` powinniśmy używać do uruchamiania pythona na swoim komputerze. 72 | 73 | Jeżeli dla obu tych nazw pojawia się błąd, napisz do nas maila, chętnie pomożemy ;) 74 | 75 | ### Uruchamianie skryptu pythonowego 76 | Stwórz plik `test.py` o treści: 77 | ``` 78 | print('Test!') 79 | ``` 80 | i zapisz go. Przejdź za pomocą poleceń terminala do folderu z tym plikiem, a następnie uruchom go za pomocą komendy (w zależności od tego co u Ciebie działa): 81 | ``` 82 | python3.6 test.py 83 | ``` 84 | lub 85 | ``` 86 | python test.py 87 | ``` 88 | Na ekranie powinien pojawić się napis `Test!`, co oznacza, że program działa poprawnie. 89 | 90 | ### Włączanie interpretera 91 | Żeby włączyć interpreter pythona, użyj odpowiedniej dla siebie komendy, tzn. 92 | ``` 93 | python3.6 94 | ``` 95 | lub 96 | ``` 97 | python 98 | ``` 99 | W interpreterze można wpisywać komendy w języku python, które są od razu wykonywane. Pamiętajcie, że w interpreterze nie działają terminalowe komendy takie jak `cd`, `ls` itp. Żeby ich używać lub żeby uruchomić cały plik z programem napisanym w pythonie, należy zamknąć interpreter. Żeby zamknąć interpreter naciśnij `Ctrl+Z` na Windowsie lub `Ctrl+D` na Macu lub na Linuksie. 100 | -------------------------------------------------------------------------------- /warsztat_1/testy_rozwiazan_1/zadanie1.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Stwórz listę liczb od 0 do 999. 5 | # Liczby podzielne przez 3 zastąp słowem 'trzy'. 6 | # Liczby podzielne przez 5 zastąp słowem 'pięć'. 7 | # Liczby podzielne jednocześnie przez 3 i 5 zastąp słowem 'trzypięć'. 8 | # Wynikową listę przypisz zmiennej result. 9 | 10 | 11 | def fifteen_ok(result): 12 | assert result[15] == 'trzypięć' 13 | 14 | 15 | def three_ok(result): 16 | assert result[3] == 'trzy' 17 | 18 | 19 | def four_ok(result): 20 | assert result[4] == 4 21 | 22 | 23 | def five_ok(result): 24 | assert result[5] == 'pięć' 25 | 26 | 27 | def result_ok(result): 28 | expected_list = [] 29 | for i in range(1000): 30 | if i % 3 == 0 and i % 5 == 0: 31 | expected_list.append('trzypięć') 32 | elif i % 3 == 0: 33 | expected_list.append('trzy') 34 | elif i % 5 == 0: 35 | expected_list.append('pięć') 36 | else: 37 | expected_list.append(i) 38 | assert result == expected_list 39 | 40 | 41 | assignment = Assignment( 42 | 'zadanie1', 43 | 'zadanie1.py', 44 | 'result', 45 | (fifteen_ok, three_ok, four_ok, five_ok, result_ok) 46 | ) 47 | -------------------------------------------------------------------------------- /warsztat_1/testy_rozwiazan_1/zadanie2.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | # Napisać kod tworzący listę list kolejnych elementów parzystych < 100 według 4 | # schematu: [[0], [2], ... , [98]]. Wynikową listę przypisz na zmienną result. 5 | 6 | 7 | def type_ok(result): 8 | assert type(result) == list 9 | 10 | 11 | def length_ok(result): 12 | assert len(result) == 50 13 | 14 | 15 | def second_ok(result): 16 | assert result[1] == [2] 17 | 18 | 19 | def beforelast_ok(result): 20 | assert result[-2] == [96] 21 | 22 | 23 | def test5(result): 24 | assert result == [[i] for i in range(100) if i % 2 == 0] 25 | 26 | 27 | assignment = Assignment( 28 | 'zadanie2', 29 | 'zadanie2.py', 30 | 'result', 31 | (type_ok, length_ok, second_ok, beforelast_ok, test5) 32 | ) 33 | -------------------------------------------------------------------------------- /warsztat_1/testy_rozwiazan_1/zadanie3.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | # Stwórz listę 100 list, każda z liczbami od 1 do 100. Potem dla każdej j-tej 4 | # z tych list wewnętrznych na jej końcu dodać sumę jej pierwszych elementów 5 | # do j-tego włącznie. 6 | # Spodziewany efekt: [ [1, 2, 3, ..., 100, 1], [1, 2, 3, ..., 100, 3], 7 | # [1, 2, 3, ..., 100, 6], ..., [1, 2, 3, ..., 100, 5050] ] 8 | # Wynikową listę przypisz na zmienną result 9 | 10 | 11 | def test1(result): 12 | assert type(result) == list 13 | 14 | 15 | def length_ok(result): 16 | assert len(result) == 100 17 | 18 | 19 | def first_ok(result): 20 | expected_result = list(range(1, 101)) + [1] 21 | assert result[0] == expected_result 22 | 23 | 24 | def last_ok(result): 25 | expected_result = list(range(1, 101)) + [5050] 26 | assert result[-1] == expected_result 27 | 28 | 29 | def result_ok(result): 30 | sum_list = [list(range(1,101)) for x in range(100)] 31 | i = 0 32 | while i < 100: 33 | sum_list[i].append(sum(sum_list[i][:i + 1])) 34 | i += 1 35 | assert result == sum_list 36 | 37 | 38 | assignment = Assignment( 39 | 'zadanie3', 40 | 'zadanie3.py', 41 | 'result', 42 | (test1, length_ok, first_ok, last_ok, result_ok) 43 | ) 44 | -------------------------------------------------------------------------------- /warsztat_1/testy_rozwiazan_1/zadanie4.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | # Napisz kod transformujący podany słownik: 4 | # { 5 | # 1: 'Poniedziałek', 6 | # 2: 'Wtorek', 7 | # 3: 'Środa', 8 | # 4: 'Czwartek', 9 | # 5: 'Piątek', 10 | # 6: 'Sobota', 11 | # 7: 'Niedziela' 12 | # } 13 | # do postaci: 14 | # { 15 | # 'Poniedziałek': 1, 16 | # 'Środa': 3, 17 | # 'Piątek': 5, 18 | # 'Niedziela': 7 19 | # } 20 | # (Zamiana klucza z wartością i zostawienie tylko dni nieparzystych). 21 | # Wynik przypisz na zmienną result 22 | 23 | 24 | def length_ok(result): 25 | assert len(result) == 4 26 | 27 | 28 | def types_ok(result): 29 | for k in result.keys(): 30 | assert type(k) == str 31 | 32 | 33 | def has_poniedzialek(result): 34 | assert 'Poniedziałek' in result 35 | 36 | 37 | def result_ok(result): 38 | expected_result = { 39 | 'Poniedziałek': 1, 40 | 'Środa': 3, 41 | 'Piątek': 5, 42 | 'Niedziela': 7 43 | } 44 | assert result == expected_result 45 | 46 | 47 | assignment = Assignment( 48 | 'zadanie4', 49 | 'zadanie4.py', 50 | 'result', 51 | (length_ok, types_ok, has_poniedzialek, result_ok) 52 | ) 53 | -------------------------------------------------------------------------------- /warsztat_1/testy_rozwiazan_1/zadanie5.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | # Powerset - Napisz kod tworzęcy ze zbioru A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 4 | # zbiór zawierający wszystkie podzbiory A (włącznie z pustym i A). 5 | # UWAGA: w python zbiory (set) nie mogą być elementami innych zbiorów, 6 | # proszę użyć frozenset jako zbiorów wewnętrznych. 7 | # Wynik przypisz na zmienną result 8 | 9 | 10 | A = frozenset((0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) 11 | answer = {frozenset()} 12 | for x in A: 13 | tmp = set() 14 | for y in answer: 15 | tmp.add(y | frozenset((x,))) 16 | answer |= tmp 17 | 18 | 19 | def has_full(result): 20 | assert A in result 21 | 22 | 23 | def has_empty(result): 24 | assert frozenset() in result 25 | 26 | 27 | def is_set(result): 28 | assert type(result) == set 29 | 30 | 31 | def length_ok(result): 32 | assert len(result) == len(answer) 33 | 34 | 35 | def result_ok(result): 36 | assert result == answer 37 | 38 | 39 | assignment = Assignment( 40 | 'zadanie5', 41 | 'zadanie5.py', 42 | 'result', 43 | (has_full, has_empty, is_set, length_ok, result_ok) 44 | ) 45 | -------------------------------------------------------------------------------- /warsztat_1/zadania_domowe_1/zadanie0.py: -------------------------------------------------------------------------------- 1 | # 1. Zapoznanie sie z https://docs.python.org/3.6/library/functions.html 2 | # Nie chodzi o znajomość na pamięć co każda funkcja robi, 3 | # ale o wiedzę co w ogóle python umożliwia na dzień dobry. 4 | # Dzięki temu nie będziesz implementować funkcjonalności, które już są. 5 | 6 | # 2. Zapoznanie się z https://docs.python.org/3/tutorial/datastructures.html 7 | # Dzięki temu będziesz wiedzieć co potrafią podstawowe struktury danych. 8 | # Na zajęciach były tylko pobieżnie przedstawione. 9 | -------------------------------------------------------------------------------- /warsztat_1/zadania_domowe_1/zadanie1.py: -------------------------------------------------------------------------------- 1 | # Stwórz listę liczb od 0 do 999. 2 | # Liczby podzielne przez 3 zastąp słowem 'trzy'. 3 | # Liczby podzielne przez 5 zastąp słowem 'pięć'. 4 | # Liczby podzielne jednocześnie przez 3 i 5 zastąp słowem 'trzypięć'. 5 | # Wynikową listę przypisz zmiennej result. 6 | 7 | result = None 8 | 9 | assert result[15] == 'trzypięć' 10 | -------------------------------------------------------------------------------- /warsztat_1/zadania_domowe_1/zadanie2.py: -------------------------------------------------------------------------------- 1 | # Napisać kod tworzący listę list kolejnych elementów parzystych < 100 według 2 | # schematu: [[0], [2], ... , [98]]. Wynikową listę przypisz na zmienną result. 3 | 4 | result = None 5 | 6 | assert result[1] == [2] 7 | -------------------------------------------------------------------------------- /warsztat_1/zadania_domowe_1/zadanie3.py: -------------------------------------------------------------------------------- 1 | # Stwórz listę 100 list, każda z liczbami od 1 do 100. Potem dla każdej j-tej 2 | # z tych list wewnętrznych na jej końcu dodać sumę jej pierwszych elementów 3 | # do j-tego włącznie. 4 | # Spodziewany efekt: [ [1, 2, 3, ..., 100, 1], [1, 2, 3, ..., 100, 3], 5 | # [1, 2, 3, ..., 100, 6], ..., [1, 2, 3, ..., 100, 5050] ] 6 | # Wynikową listę przypisz na zmienną result 7 | 8 | result = None 9 | 10 | assert result[-1][-1] == 5050 11 | -------------------------------------------------------------------------------- /warsztat_1/zadania_domowe_1/zadanie4.py: -------------------------------------------------------------------------------- 1 | # Napisz kod transformujący podany słownik: 2 | # { 3 | # 1: 'Poniedziałek', 4 | # 2: 'Wtorek', 5 | # 3: 'Środa', 6 | # 4: 'Czwartek', 7 | # 5: 'Piątek', 8 | # 6: 'Sobota', 9 | # 7: 'Niedziela' 10 | # } 11 | # do postaci: 12 | # { 13 | # 'Poniedziałek': 1, 14 | # 'Środa': 3, 15 | # 'Piątek': 5, 16 | # 'Niedziela': 7 17 | # } 18 | # (Zamiana klucza z wartością i zostawienie tylko dni nieparzystych). 19 | # Wynik przypisz na zmienną result 20 | 21 | 22 | result = { 23 | 1: 'Poniedziałek', 24 | 2: 'Wtorek', 25 | 3: 'Środa', 26 | 4: 'Czwartek', 27 | 5: 'Piątek', 28 | 6: 'Sobota', 29 | 7: 'Niedziela' 30 | } 31 | 32 | assert 'Poniedziałek' in result 33 | -------------------------------------------------------------------------------- /warsztat_1/zadania_domowe_1/zadanie5.py: -------------------------------------------------------------------------------- 1 | # Powerset - Napisz kod tworzęcy ze zbioru A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9} 2 | # zbiór zawierający wszystkie podzbiory A (włącznie z pustym i A). 3 | # UWAGA: w python zbiory (set) nie mogą być elementami innych zbiorów, 4 | # proszę użyć frozenset jako zbiorów wewnętrznych. 5 | # Wynik przypisz na zmienną result 6 | 7 | result = None 8 | 9 | assert frozenset((0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) in result 10 | -------------------------------------------------------------------------------- /warsztat_2/README.md: -------------------------------------------------------------------------------- 1 | Rozwiązania zadań prosimy przesyłać **tylko** za pomocą formularza: https://goo.gl/forms/eDhPMrGSJTwbjcav2 2 | Do niedzieli 05.11.2017 23:59:59. -------------------------------------------------------------------------------- /warsztat_2/p4b-funkcje.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaftAcademy/python4beginners/f108ae9c8ebcd94214b57c0f4a5479f36ce59a11/warsztat_2/p4b-funkcje.pdf -------------------------------------------------------------------------------- /warsztat_2/testy_rozwiazan_2/zadanie1.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zadanie 1 5 | # Napisz funkcję power, która dla danego n i p zwraca w wyniku n podniesione do potęgi p. 6 | # Domyślna wartość argumentu p to 2. 7 | # Niech n i p będą liczbami całkowitymi >= 0. 8 | 9 | 10 | def power(n, p=2): 11 | return n ** p 12 | 13 | 14 | # testy poprawnosci 15 | 16 | 17 | def power_5_3(func): 18 | """Czy podniesienie 5 do 3 potęgi zwraca 125?""" 19 | assert func(5, 3) == 125 20 | 21 | 22 | def default_arg_2(func): 23 | """Czy drugi argument ma domyślną wartość 2?""" 24 | assert func(5) == 25 25 | 26 | 27 | def p_zero(func): 28 | """Czy podniesienie do potęgi zerowej zwraca poprawny wynik (1)?""" 29 | assert func(5, 0) == 1 30 | 31 | 32 | def n_zero(func): 33 | """Czy podnoszenie zera do potęgi działa poprawnie?""" 34 | assert func(0, 5) == 0 35 | 36 | 37 | assignment = Assignment( 38 | 'zadanie1', 39 | 'zadanie1.py', 40 | 'power', 41 | (power_5_3, default_arg_2, p_zero, n_zero) 42 | ) 43 | -------------------------------------------------------------------------------- /warsztat_2/testy_rozwiazan_2/zadanie2.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zadanie 2 5 | # Napisz funkcję copy_reversed, która przyjmuje dwie listy, list_a i list_b 6 | # i która dodaje do listy list_b całą zawartość list_a, ale w odwróconej kolejności. 7 | # Funkcja copy_reversed niech zwraca None. 8 | 9 | 10 | 11 | def copy_reversed(list_a, list_b): 12 | list_b.extend(reversed(list_a)) 13 | 14 | 15 | # test poprawnosci 16 | 17 | def return_none(func): 18 | """Czy funkcja zwraca pusty wynik (None) wg treści zadania?""" 19 | assert func([1, 2, 3], [4, 5, 6]) is None 20 | 21 | 22 | def list_b_changed(func): 23 | """Czy lista podana jako drugi argument sie zmieniła? (czytanie treści zadania)""" 24 | x = [1, 2, 3] 25 | y = [4, 5, 6] 26 | func(x, y) 27 | assert y == [4, 5, 6, 3, 2, 1] 28 | 29 | 30 | def list_a_not_changed(func): 31 | """Czy lista podana jako pierwszy argument zmieniła sie w trakcie zamiast zostać skopiowana?""" 32 | x = [1, 2, 3] 33 | y = [4, 5, 6] 34 | func(x, y) 35 | assert x == [1, 2, 3] 36 | 37 | 38 | def list_a_empty(func): 39 | """Czy działa dla pustej listy w pierwszym argumencie?""" 40 | x = [] 41 | y = [4, 5, 6] 42 | func(x, y) 43 | assert y == [4, 5, 6] 44 | 45 | 46 | assignment = Assignment( 47 | 'zadanie2', 48 | 'zadanie2.py', 49 | 'copy_reversed', 50 | (return_none, list_b_changed, list_a_not_changed, list_a_empty) 51 | ) 52 | -------------------------------------------------------------------------------- /warsztat_2/testy_rozwiazan_2/zadanie3.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zadanie 3 5 | # Napisz funkcję, add_one, która przyjmuje jako argument listę. 6 | # Do podanej listy powinien zostać dodany nowy element: 1, a następnie lista powinna zostać zwrócona z funkcji. 7 | # Argument w funkcji niech będzie opcjonalny - w przypadku, gdy funkcja nie otrzyma żadnego argumentu, niech zachowuje się tak, jakby otrzymała pustą listę. 8 | 9 | 10 | def add_one(given_list=None): 11 | if given_list is None: 12 | given_list = [] 13 | given_list.append(1) 14 | return given_list 15 | 16 | 17 | # test poprawnosci 18 | 19 | 20 | def basic_test(func): 21 | """Czy działa podstawowa funkcjonalność?""" 22 | test_list = [5, 6, 7] 23 | assert func(test_list) == [5, 6, 7, 1] 24 | 25 | 26 | def default_arg(func): 27 | """Czy domyślny argument został poprawnie obsłużony? (każdorazowo powinna być tworzona nowa lista)""" 28 | assert func() == [1] 29 | assert func() == [1] 30 | 31 | 32 | def is_none_used(func, module): 33 | """Czy został wykorzystany `is None`?""" 34 | class stupid_list(list): 35 | def __eq__(self, other): 36 | # self == None returns True, but self is None doesn't 37 | return True 38 | module.list = stupid_list 39 | test_list = stupid_list([5, 6, 7]) 40 | result = func(test_list) 41 | module.list = list 42 | assert [5, 6, 7, 1] == result 43 | 44 | 45 | def empty_list_as_arg(func): 46 | """Czy podanie pustej listy działa poprawnie (wynik == [1])?""" 47 | test_list = [] 48 | assert func(test_list) == [1] 49 | 50 | 51 | assignment = Assignment( 52 | 'zadanie3', 53 | 'zadanie3.py', 54 | 'add_one', 55 | ( 56 | basic_test, 57 | default_arg, 58 | is_none_used, 59 | empty_list_as_arg, 60 | ) 61 | ) 62 | -------------------------------------------------------------------------------- /warsztat_2/testy_rozwiazan_2/zadanie4.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zadanie 4 5 | # Napisz funkcję factorial, która dla danego n obliczy rekurencyjnie silnię 6 | 7 | def factorial(n): 8 | if n == 0: 9 | return 1 10 | return n * factorial(n - 1) 11 | 12 | 13 | # test poprawnosci 14 | 15 | 16 | def basic_test(func): 17 | """Czy zwraca poprawny wynik dla argumentu 5?""" 18 | return func(5) == 120 19 | 20 | 21 | def test_one(func): 22 | """Czy zwraca poprawny wynik dla argumentu 1?""" 23 | return func(1) == 1 24 | 25 | 26 | def test_zero(func): 27 | """Czy zwraca poprawny wynik dla argumentu 0?""" 28 | return func(0) == 1 29 | 30 | 31 | def counted(f): 32 | def wrapped(*args, **kwargs): 33 | wrapped.calls += 1 34 | return f(*args, **kwargs) 35 | 36 | wrapped.calls = 0 37 | return wrapped 38 | 39 | 40 | def recurrency_used(func, module, attr_name): 41 | """Czy rozwiazanie jest rekurencyjne (wywołuje samo siebie)?""" 42 | wrapped = counted(func) 43 | setattr(module, attr_name, wrapped) 44 | wrapped(5) 45 | setattr(module, attr_name, func) 46 | assert wrapped.calls > 1 47 | 48 | 49 | assignment = Assignment( 50 | 'zadanie4', 51 | 'zadanie4.py', 52 | 'factorial', 53 | ( 54 | basic_test, 55 | test_one, 56 | test_zero, 57 | recurrency_used, 58 | ) 59 | ) 60 | -------------------------------------------------------------------------------- /warsztat_2/testy_rozwiazan_2/zadanie5.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zadanie 5 5 | # Napisz funkcję function_results_sum, która przyjmuje dowolną liczbę funkcji 6 | # jako argumenty pozycyjne. 7 | # Argumenty do poszczególnych funkcji przekazywane są do function_results_sum jako keyword arguments w 8 | # postaci NAZWA_FUNKCJI=ARGUMENTY. 9 | # Funkcja function_results_sum powinna zwrócić sumę wyników otrzymanych 10 | # po odpaleniu każdej z funkcji z odpowiednimi argumentami. 11 | # Jeżeli funkcja jest bezargumentowa, nie oczekuje się podania do niej 12 | # argumentów 13 | # Gdy funkcja przyjmuje jeden argument, jako keyword argument przekazany 14 | # będzie int, np. one_arg_function_name=2 15 | # Gdy funkcja przyjmuje więcej argumentów - oczekiwana jest tupla odpowiedniej 16 | # długości, np. two_args_function_name=(1, 2) 17 | 18 | # przykład 1: 19 | # sygnatury funkcji: 20 | # def no_arg() 21 | # def one_arg(a) 22 | # def multiple_args(a, b, c, e, f) 23 | # 24 | # wywołanie function_results_sum: 25 | # function_results_sum( 26 | # no_arg, one_arg, multiple_args, 27 | # one_arg=23, 28 | # multiple_args=(1, 2, 3, 4, 5) 29 | # ) 30 | 31 | # inne wywołanie function_results_sum: 32 | # function_results_sum( 33 | # no_arg, one_arg, multiple_args, 34 | # one_arg=-1245 35 | # multiple_args=(45, 65, 76, 123456, 111.222) 36 | # ) 37 | # 38 | # W zadaniu skorzystaj z atrybutu __name__ dostępnego na obiekcie funkcji 39 | # 40 | # Zadanie nie wymaga sprawdzania poprawności przekazywanych argumentów, 41 | # obowiązek przekazania odpowiedniej liczby argumentów do wszystkich funkcji spoczywa na tym, kto wywołuje function_results_sum 42 | # 43 | # Do odpowiedniego uruchomienia funkcji przyda się operator * przy wywołaniu funkcji. Poniżej przydatne linki: 44 | # https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists 45 | # https://stackoverflow.com/questions/2921847/what-does-the-star-operator-mean 46 | 47 | def function_results_sum(*functions, **function_args): 48 | result = 0 49 | for function in functions: 50 | arguments = function_args.get(function.__name__, ()) 51 | if isinstance(arguments, int): 52 | result += function(arguments) 53 | else: 54 | result += function(*arguments) 55 | return result 56 | 57 | 58 | # dane do testow 59 | 60 | def no_arg(): 61 | return 10 62 | 63 | 64 | def get_double_n(n): 65 | return 2 * n 66 | 67 | 68 | def get_product_of_three_values(a, b, c): 69 | return a * b * c 70 | 71 | 72 | # testy poprawnosci 73 | 74 | 75 | def test_no_arg(func): 76 | """Czy brak argumentów działa? (brak funkcji w kwargsach)""" 77 | assert func(no_arg) == 10 78 | 79 | 80 | def test_one_arg(func): 81 | """Czy pojedynczy argument działa? (fname=1)""" 82 | assert func(get_double_n, get_double_n=20) == 40 83 | 84 | 85 | def test_multiple_args(func): 86 | """Czy lista argumentów działa? (fname=(1,2,3))""" 87 | assert func(get_product_of_three_values, get_product_of_three_values=(3, 4, 5)) == 60 88 | 89 | 90 | def test_all_types_of_args(func): 91 | """Czy wszystkie typy argumentów przeszły (całkowity brak, pojedyncza wartość I lista wartości)?""" 92 | result = func( 93 | get_product_of_three_values, 94 | no_arg, 95 | get_double_n, 96 | get_double_n=3, 97 | get_product_of_three_values=(1, 2, 6) 98 | ) 99 | assert result == 28 100 | 101 | 102 | assignment = Assignment( 103 | 'zadanie5', 104 | 'zadanie5.py', 105 | 'function_results_sum', 106 | ( 107 | test_no_arg, 108 | test_one_arg, 109 | test_multiple_args, 110 | test_all_types_of_args, 111 | ) 112 | ) 113 | -------------------------------------------------------------------------------- /warsztat_2/testy_rozwiazan_2/zadanie6.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zadanie 6 5 | # Jesteś administratorem Bardzo Wysokiego Budynku Biurowego BWBB. 6 | # Masz listę ile osób znajduje się na kolejnych piętrach BWBB: `lista_osob` (czyli wartość lista_osób[5] to liczba osób na piętrze nr 5) - zawiera ona tylko liczby całkowite 7 | # W budynku znajduje się określona liczba ewakuacyjnych klatek schodowych: `liczba_klatek_schodowych` - jest to liczba całkowita 8 | # Każda z klatek pozwala na jednoczesne poruszanie się kilku osób obok siebie: `liczba_osob_w_rzedzie` (liczba całkowita). 9 | # Odstęp czasowy miedzy każdym ewakuowanym rzędem osób to 1 sekunda. 10 | # `tempo_schodzenia` to liczba sekund potrzebna na przejście jednego piętra. Uznajemy, że wszyscy schodzą w tym samym tempie 11 | # Ewakuacja budynku zaczyna się od najwyższego piętra, piętro po piętrze w dół. 12 | # Po jakim czasie powinna zaczynać się ewakuacja dla poszczególnych pięter żeby nie tworzyły się zatory? 13 | # Zatory nie tworzą się wtedy, gdy osoby z wyższych minęły już piętro, które jest w danym momencie ewakuowane. 14 | # Funkcja ewakuacja powinna zwracać listę z intami po ilu sekundach od rozpoczęcia ewakuacji budynku na każdym piętrze zostanie włączony alarm 15 | # czyli result[6] przechowuje po ilu sekundach został włączony alarm na szóstym piętrze 16 | 17 | # Osoby ewakuowane same rozkładają się po równo na liczbę zejść ewakuacyjnych 18 | # Piętro zaczyna się ewakuować od razu po uruchomieniu na nim alarmu 19 | # Argumenty do funkcji będą przekazane po nazwie, jako keyword 20 | 21 | def ewakuacja(lista_osob, liczba_klatek_schodowych, liczba_osob_w_rzedzie, tempo_schodzenia): 22 | answ = [0] # najwyższe piętro zaczyna ewakuację natychmiast 23 | for liczba_osob in lista_osob[-1:0:-1]: 24 | max_na_zejscie = liczba_osob // liczba_klatek_schodowych 25 | if max_na_zejscie * liczba_klatek_schodowych < liczba_osob: 26 | max_na_zejscie += 1 # nie można ewakuować osoby w kawałkach 27 | 28 | max_rzedow = max_na_zejscie // liczba_osob_w_rzedzie 29 | if max_rzedow * liczba_osob_w_rzedzie < max_na_zejscie: 30 | max_rzedow += 1 # nie pomijamy rzędu w którym ewakuje się jedna osoba 31 | 32 | czas = max_rzedow + tempo_schodzenia 33 | answ.append(answ[-1] + czas) 34 | return list(reversed(answ)) 35 | 36 | 37 | # testy poprawnosci 38 | 39 | def ground_floor_only(func): 40 | """Czy poprawnie działa dla samego parteru?""" 41 | assert [0] == func( 42 | lista_osob=[20], 43 | liczba_klatek_schodowych=2, 44 | liczba_osob_w_rzedzie=10, 45 | tempo_schodzenia=3) 46 | 47 | 48 | def test_from_assignment_description(func): 49 | """Czy zadanie 6 zwraca poprawny wynik?""" 50 | lista_osob = [5, 10, 15] 51 | liczba_klatek_schodowych = 2 52 | liczba_osob_w_rzedzie = 1 53 | tempo_schodzenia = 30 54 | 55 | assert [73, 38, 0] == func( 56 | lista_osob=lista_osob, 57 | liczba_klatek_schodowych=liczba_klatek_schodowych, 58 | liczba_osob_w_rzedzie=liczba_osob_w_rzedzie, 59 | tempo_schodzenia=tempo_schodzenia 60 | ) 61 | 62 | 63 | def five_floors(func): 64 | """Czy dla 5 pięter dobre rozwiązanie.""" 65 | lista_osob = [123, 456, 789, 246, 369] 66 | liczba_klatek_schodowych = 10 67 | liczba_osob_w_rzedzie = 10 68 | tempo_schodzenia = 3 69 | 70 | assert [32, 24, 13, 7, 0] == func( 71 | lista_osob=lista_osob, 72 | liczba_klatek_schodowych=liczba_klatek_schodowych, 73 | liczba_osob_w_rzedzie=liczba_osob_w_rzedzie, 74 | tempo_schodzenia=tempo_schodzenia 75 | ) 76 | 77 | 78 | def same_number_of_people_on_each_floor(func): 79 | """Czy dla jednakowej liczby osób na każdym piętrze dobre rozwiązanie.""" 80 | lista_osob = [100] * 46 81 | liczba_klatek_schodowych = 2 82 | liczba_osob_w_rzedzie = 4 83 | tempo_schodzenia = 15 84 | 85 | assert [1260, 1232, 1204, 1176, 1148, 1120, 1092, 1064, 1036, 1008, 980, 952, 86 | 924, 896, 868, 840, 812, 784, 756, 728, 700, 672, 644, 616, 588, 560, 87 | 532, 504, 476, 448, 420, 392, 364, 336, 308, 280, 252, 224, 196, 168, 88 | 140, 112, 84, 56, 28, 0] == func( 89 | lista_osob=lista_osob, 90 | liczba_klatek_schodowych=liczba_klatek_schodowych, 91 | liczba_osob_w_rzedzie=liczba_osob_w_rzedzie, 92 | tempo_schodzenia=tempo_schodzenia 93 | ) 94 | 95 | 96 | assignment = Assignment( 97 | 'zadanie6', 98 | 'zadanie6.py', 99 | 'ewakuacja', 100 | ( 101 | ground_floor_only, 102 | test_from_assignment_description, 103 | five_floors, 104 | same_number_of_people_on_each_floor 105 | ) 106 | ) 107 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie1.py: -------------------------------------------------------------------------------- 1 | for i in range(3): 2 | print((3 - i - 1) * ' ' + (2 * i + 1) * '*') 3 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie2.py: -------------------------------------------------------------------------------- 1 | def draw_tree(): 2 | for i in range(3): 3 | print((3 - i - 1) * ' ' + (2 * i + 1) * '*') 4 | 5 | draw_tree() 6 | draw_tree() 7 | draw_tree() 8 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie3.py: -------------------------------------------------------------------------------- 1 | def draw_tree(h): 2 | for i in range(h): 3 | print((h - i - 1) * ' ' + (2 * i + 1) * '*') 4 | 5 | draw_tree(3) 6 | draw_tree(4) 7 | draw_tree(5) 8 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie4.py: -------------------------------------------------------------------------------- 1 | def draw_tree(h, s): 2 | for i in range(h): 3 | print((h - i - 1) * ' ' + (2 * i + 1) * str(s)) 4 | 5 | draw_tree(3, 1) 6 | draw_tree(4, s='#') 7 | draw_tree(s='*', h=5) 8 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie5.py: -------------------------------------------------------------------------------- 1 | def draw_tree(h, s='*'): 2 | for i in range(h): 3 | print((h - i - 1) * ' ' + (2 * i + 1) * str(s)) 4 | 5 | draw_tree(3, 1) 6 | draw_tree(h=4, s='#') 7 | draw_tree(5) 8 | draw_tree(h=6) 9 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie6.py: -------------------------------------------------------------------------------- 1 | def draw_tree(h, s='*'): 2 | symbols_count = 0 3 | for i in range(h): 4 | print((h - i - 1) * ' ' + (2 * i + 1) * str(s)) 5 | symbols_count += (2 * i + 1) 6 | return symbols_count 7 | 8 | total_symbols_count = 0 9 | total_symbols_count += draw_tree(3, 1) 10 | total_symbols_count += draw_tree(h=4, s='#') 11 | total_symbols_count += draw_tree(5) 12 | total_symbols_count += draw_tree(h=6) 13 | print(total_symbols_count) 14 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie7.py: -------------------------------------------------------------------------------- 1 | def draw_tree(s, *args): 2 | for h in args: 3 | for i in range(h): 4 | print((h - i - 1) * ' ' + (2 * i + 1) * str(s)) 5 | 6 | draw_tree('*', 3, 4, 5, 6) 7 | -------------------------------------------------------------------------------- /warsztat_2/zadania_z_zajec/zadanie8.py: -------------------------------------------------------------------------------- 1 | def draw_tree(s, **kwargs): 2 | for name, h in kwargs.items(): 3 | print(name) 4 | for i in range(h): 5 | print((h - i - 1) * ' ' + (2 * i + 1) * str(s)) 6 | 7 | draw_tree('*', sosna=5, świerk=6) 8 | -------------------------------------------------------------------------------- /warsztat_2/zadanie_domowe_2/zadanie1.py: -------------------------------------------------------------------------------- 1 | # Zadanie 1 2 | # Napisz funkcję power, która dla danego n i p zwraca w wyniku n podniesione do potęgi p. 3 | # Domyślna wartość argumentu p to 2. 4 | # Niech n i p będą liczbami całkowitymi >= 0. 5 | 6 | assert power(5) == 25 7 | assert power(5, 3) == 125 8 | -------------------------------------------------------------------------------- /warsztat_2/zadanie_domowe_2/zadanie2.py: -------------------------------------------------------------------------------- 1 | # Zadanie 2 2 | # Napisz funkcję copy_reversed, która przyjmuje dwie listy, list_a i list_b 3 | # i która dodaje do listy list_b całą zawartość list_a, ale w odwróconej kolejności. 4 | # Funkcja copy_reversed niech zwraca None. 5 | 6 | x = [1, 2, 3] 7 | y = [4, 5, 6] 8 | 9 | result = copy_reversed(x, y) 10 | 11 | assert y == [4, 5, 6, 3, 2, 1] 12 | assert result is None 13 | -------------------------------------------------------------------------------- /warsztat_2/zadanie_domowe_2/zadanie3.py: -------------------------------------------------------------------------------- 1 | # Zadanie 3 2 | # Napisz funkcję, add_one, która przyjmuje jako argument listę. 3 | # Do podanej listy powinien zostać dodany nowy element: 1, a następnie lista powinna zostać zwrócona z funkcji. 4 | # Argument w funkcji niech będzie opcjonalny - w przypadku, gdy funkcja nie otrzyma żadnego argumentu, niech zachowuje się tak, jakby otrzymała pustą listę. 5 | 6 | test_list = [5, 6, 7] 7 | result1 = add_one(test_list) 8 | assert result1 == [5, 6, 7, 1] 9 | 10 | result2 = add_one() 11 | assert result2 == [1] 12 | 13 | result3 = add_one() 14 | assert result3 == [1] 15 | -------------------------------------------------------------------------------- /warsztat_2/zadanie_domowe_2/zadanie4.py: -------------------------------------------------------------------------------- 1 | # Zadanie 4 2 | # Napisz funkcję factorial, która dla danego n obliczy rekurencyjnie silnię 3 | 4 | assert factorial(5) == 120 5 | -------------------------------------------------------------------------------- /warsztat_2/zadanie_domowe_2/zadanie5.py: -------------------------------------------------------------------------------- 1 | # Zadanie 5 2 | # Napisz funkcję function_results_sum, która przyjmuje dowolną liczbę funkcji 3 | # jako argumenty pozycyjne. 4 | # Argumenty do poszczególnych funkcji przekazywane są do function_results_sum jako keyword arguments w 5 | # postaci NAZWA_FUNKCJI=ARGUMENTY. 6 | # Funkcja function_results_sum powinna zwrócić sumę wyników otrzymanych 7 | # po odpaleniu każdej z funkcji z odpowiednimi argumentami. 8 | # Jeżeli funkcja jest bezargumentowa, nie oczekuje się podania do niej 9 | # argumentów 10 | # Gdy funkcja przyjmuje jeden argument, jako keyword argument przekazany 11 | # będzie int, np. one_arg_function_name=2 12 | # Gdy funkcja przyjmuje więcej argumentów - oczekiwana jest tupla odpowiedniej 13 | # długości, np. two_args_function_name=(1, 2) 14 | 15 | # przykład 1: 16 | # sygnatury funkcji: 17 | # def no_arg() 18 | # def one_arg(a) 19 | # def multiple_args(a, b, c, e, f) 20 | # 21 | # wywołanie function_results_sum: 22 | # function_results_sum( 23 | # no_arg, one_arg, multiple_args, 24 | # one_arg=23, 25 | # multiple_args=(1, 2, 3, 4, 5) 26 | # ) 27 | 28 | # inne wywołanie function_results_sum: 29 | # function_results_sum( 30 | # no_arg, one_arg, multiple_args, 31 | # one_arg=-1245 32 | # multiple_args=(45, 65, 76, 123456, 111.222) 33 | # ) 34 | # 35 | # W zadaniu skorzystaj z atrybutu __name__ dostępnego na obiekcie funkcji 36 | # 37 | # Zadanie nie wymaga sprawdzania poprawności przekazywanych argumentów, 38 | # obowiązek przekazania odpowiedniej liczby argumentów do wszystkich funkcji spoczywa na tym, kto wywołuje function_results_sum 39 | # 40 | # Do odpowiedniego uruchomienia funkcji przyda się operator * przy wywołaniu funkcji. Poniżej przydatne linki: 41 | # https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists 42 | # https://stackoverflow.com/questions/2921847/what-does-the-star-operator-mean 43 | 44 | 45 | def no_arg(): 46 | return 5 47 | 48 | def ident(x): 49 | return x 50 | 51 | def mult(x, y): 52 | return x * y 53 | 54 | assert function_results_sum(no_arg, ident, mult, ident=2, mult=(3, 4)) == 19 55 | -------------------------------------------------------------------------------- /warsztat_2/zadanie_domowe_2/zadanie6.py: -------------------------------------------------------------------------------- 1 | # Zadanie 6 2 | # Jesteś administratorem Bardzo Wysokiego Budynku Biurowego BWBB. 3 | # Masz listę ile osób znajduje się na kolejnych piętrach BWBB: `lista_osob` (czyli wartość lista_osób[5] to liczba osób na piętrze nr 5) - zawiera ona tylko liczby całkowite 4 | # W budynku znajduje się określona liczba ewakuacyjnych klatek schodowych: `liczba_klatek_schodowych` - jest to liczba całkowita 5 | # Każda z klatek pozwala na jednoczesne poruszanie się kilku osób obok siebie: `liczba_osob_w_rzedzie` (liczba całkowita). 6 | # Odstęp czasowy miedzy każdym ewakuowanym rzędem osób to 1 sekunda. 7 | # `tempo_schodzenia` to liczba sekund potrzebna na przejście jednego piętra. Uznajemy, że wszyscy schodzą w tym samym tempie 8 | # Ewakuacja budynku zaczyna się od najwyższego piętra, piętro po piętrze w dół. 9 | # Po jakim czasie powinna zaczynać się ewakuacja dla poszczególnych pięter żeby nie tworzyły się zatory? 10 | # Zatory nie tworzą się wtedy, gdy osoby z wyższych minęły już piętro, które jest w danym momencie ewakuowane. 11 | # Funkcja ewakuacja powinna zwracać listę z intami po ilu sekundach od rozpoczęcia ewakuacji budynku na każdym piętrze zostanie włączony alarm 12 | # czyli result[6] przechowuje po ilu sekundach został włączony alarm na szóstym piętrze 13 | 14 | # Osoby ewakuowane same rozkładają się po równo na liczbę zejść ewakuacyjnych 15 | # Piętro zaczyna się ewakuować od razu po uruchomieniu na nim alarmu 16 | # Argumenty do funkcji będą przekazane po nazwie, jako keyword 17 | 18 | def ewakuacja(lista_osob, liczba_klatek_schodowych, liczba_osob_w_rzedzie, tempo_schodzenia): 19 | raise NotImplementedError 20 | 21 | 22 | 23 | 24 | lista_osob = [5, 10, 15] 25 | liczba_klatek_schodowych = 2 26 | liczba_osob_w_rzedzie = 1 27 | tempo_schodzenia = 30 28 | 29 | assert [73, 38, 0] == ewakuacja( 30 | lista_osob=lista_osob, 31 | liczba_klatek_schodowych=liczba_klatek_schodowych, 32 | liczba_osob_w_rzedzie=liczba_osob_w_rzedzie, 33 | tempo_schodzenia=tempo_schodzenia 34 | ) -------------------------------------------------------------------------------- /warsztat_3/README.md: -------------------------------------------------------------------------------- 1 | W katalogu `praca_domowa_3` jest zadanie domowe `zadanie_1.py`. 2 | Na rozwiązanie czekamy do niedzieli **12.XI.2017 23:59:59**. 3 | Zadanie pierwsze może wymagać lektury: https://docs.python.org/3/reference/datamodel.html 4 | Dokument jest obszerny, nie ma potrzeby uczenia się całego na pamięć tylko przeczytanie interesujących fragmentów. 5 | Swoje rozwiązania wpiszcie do formularza: https://goo.gl/forms/hCe5X7VMGkQLN8sc2 6 | 7 | W ciągu kilku dni pojawią się zadania nr 2 i 3. 8 | Na ich rozwiązanie czekamy do niedzieli **19.XI.2017 23:59:59**. 9 | 10 | Podsumowanie wydajności wbudowanych struktur danych (może się przydać w zadaniach nr 2 i 3): https://wiki.python.org/moin/TimeComplexity -------------------------------------------------------------------------------- /warsztat_3/praca_domowa_3/zadanie_1.py: -------------------------------------------------------------------------------- 1 | # Rozwinięcie przykładu z zajęć 2 | # Na zajęciach pisaliśmy klasę Vector. 3 | 4 | class Vector(): 5 | def __init__(self, *args): 6 | # print(args) 7 | self.coords = list(args) 8 | 9 | def __repr__(self): 10 | template = '{}({})' 11 | name = self.__class__.__name__ 12 | args = ', '.join(repr(x) for x in self.coords) 13 | # print(name, args) 14 | return template.format(name, args) 15 | 16 | def __add__(self, other): 17 | tmp = [] 18 | for i in range(len(self)): 19 | tmp.append(self.coords[i] + other.coords[i]) 20 | return Vector(*tmp) 21 | 22 | def __iadd__(self, other): 23 | for i in range(len(self)): 24 | self.coords[i] += other.coords[i] 25 | return self 26 | 27 | def __len__(self): 28 | return len(self.coords) 29 | 30 | def __eq__(self, other): 31 | for i in range(len(self)): 32 | if not self.coords[i] == other.coords[i]: 33 | return False 34 | return True 35 | 36 | # Zadaniem domowym jest rozszerzenie funkcjonalności i refactor już istniejących. 37 | # Trzeba zmodyfikować kod klasy Vector nie psując obecnych funkcjonalności. 38 | # W pracy domowej proszę zamieścić tylko kod klasy Vector, żadnych assertów/printów . 39 | 40 | # Chcemy mieć możliwość uzyskania wartości konkretnej współrzędnej po indeksie 41 | 42 | v = Vector(1, 2, 3, 4) 43 | assert 1 == v[0] 44 | assert 2 == v[1] 45 | assert 3 == v[2] 46 | assert 4 == v[3] 47 | 48 | assert 4 == v[-1] 49 | 50 | # Chcemy mieć możliwość ustawienia wartości konkretnej współrzędnej 51 | 52 | v1 = Vector(3, 4, 8) 53 | v1[2] = 5 54 | assert 'Vector(3, 4, 5)' == str(v1) 55 | 56 | # Jeżeli powyższe dwa polecenia zostały wykonane "sprytnie" to powinniśmy 57 | # mieć teraz możliwość iterowania po współrzędnych wektora 58 | 59 | v2 = Vector(4, 6, 8, 10, 12) 60 | dumped = [x for x in v2] 61 | assert [4, 6, 8, 10, 12] == dumped 62 | 63 | # Dzięki temu możemy w funkcjach "magicznych" pozbyć się odwołań do implementacji vectora. 64 | # Odwołania do other.coords są już niepotrzebne i większość self.coords też. 65 | # Należy je zastąpić czymś innym - to już wasze zadanie wymyślić i zaprogramować. 66 | # Chcemy zapewnić sobie możliwość "duck typing". 67 | 68 | looks_like_vector = [0, 1, 2, 3] 69 | v3 = Vector(3, 2, 1, 0) 70 | v4 = v3 + looks_like_vector 71 | v5 = looks_like_vector + v3 72 | assert v4 == v5 73 | assert isinstance(v4, Vector) 74 | assert isinstance(v5, Vector) 75 | assert 'Vector(3, 3, 3, 3)' == str(v4) 76 | 77 | v6 = Vector(0, 1, 2, 3) 78 | assert v6 == looks_like_vector 79 | assert looks_like_vector == v6 80 | -------------------------------------------------------------------------------- /warsztat_3/praca_domowa_3/zadanie_1_rozwiazanie.py: -------------------------------------------------------------------------------- 1 | class Vector(): 2 | def __init__(self, *args): 3 | self.coords = list(args) 4 | 5 | def __repr__(self): 6 | template = '{}({})' # chcemy osiągnąć NazwaKlasy(argumenty, oddzielone, przecinkami) 7 | name = self.__class__.__name__ 8 | args = ', '.join(repr(x) for x in self) 9 | return template.format(name, args) 10 | 11 | def __add__(self, other): 12 | tmp = [x + y for x, y in zip(self, other)] 13 | return Vector(*tmp) 14 | 15 | def __iadd__(self, other): 16 | for i, v in enumerate(other): 17 | self[i] += v 18 | return self 19 | 20 | def __radd__(self, other): 21 | return self + other 22 | 23 | def __len__(self): 24 | return len(self.coords) 25 | 26 | def __eq__(self, other): 27 | for x, y in zip(self, other): 28 | if not x == y: 29 | return False 30 | return True 31 | 32 | def __getitem__(self, idx): 33 | return self.coords[idx] 34 | 35 | def __setitem__(self, idx, value): 36 | self.coords[idx] = value 37 | -------------------------------------------------------------------------------- /warsztat_3/testy_rozwiazan_3/zadanie1.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # 5 | # Treść zadania 6 | # 7 | 8 | # # Rozwinięcie przykładu z zajęć 9 | # # Na zajęciach pisaliśmy klasę Vector. 10 | # 11 | # class Vector(): 12 | # def __init__(self, *args): 13 | # # print(args) 14 | # self.coords = list(args) 15 | # 16 | # def __repr__(self): 17 | # template = '{}({})' 18 | # name = self.__class__.__name__ 19 | # args = ', '.join(repr(x) for x in self.coords) 20 | # # print(name, args) 21 | # return template.format(name, args) 22 | # 23 | # def __add__(self, other): 24 | # tmp = [] 25 | # for i in range(len(self)): 26 | # tmp.append(self.coords[i] + other.coords[i]) 27 | # return Vector(*tmp) 28 | # 29 | # def __iadd__(self, other): 30 | # for i in range(len(self)): 31 | # self.coords[i] += other.coords[i] 32 | # return self 33 | # 34 | # def __len__(self): 35 | # return len(self.coords) 36 | # 37 | # def __eq__(self, other): 38 | # for i in range(len(self)): 39 | # if not self.coords[i] == other.coords[i]: 40 | # return False 41 | # return True 42 | # 43 | # # Zadaniem domowym jest rozszerzenie funkcjonalności i refactor już istniejących. 44 | # # Trzeba zmodyfikować kod klasy Vector nie psując obecnych funkcjonalności. 45 | # # W pracy domowej proszę zamieścić tylko kod klasy Vector, żadnych assertów/printów . 46 | # 47 | # # Chcemy mieć możliwość uzyskania wartości konkretnej współrzędnej po indeksie 48 | # 49 | # v = Vector(1, 2, 3, 4) 50 | # assert 1 == v[0] 51 | # assert 2 == v[1] 52 | # assert 3 == v[2] 53 | # assert 4 == v[3] 54 | # 55 | # assert 4 == v[-1] 56 | # 57 | # # Chcemy mieć możliwość ustawienia wartości konkretnej współrzędnej 58 | # 59 | # v1 = Vector(3, 4, 8) 60 | # v1[2] = 5 61 | # assert 'Vector(3, 4, 5)' == str(v1) 62 | # 63 | # # Jeżeli powyższe dwa polecenia zostały wykonane "sprytnie" to powinniśmy 64 | # # mieć teraz możliwość iterowania po współrzędnych wektora 65 | # 66 | # v2 = Vector(4, 6, 8, 10, 12) 67 | # dumped = [x for x in v2] 68 | # assert [4, 6, 8, 10, 12] == dumped 69 | # 70 | # # Dzięki temu możemy w funkcjach "magicznych" pozbyć się odwołań do implementacji vectora. 71 | # # Odwołania do other.coords są już niepotrzebne i większość self.coords też. 72 | # # Należy je zastąpić czymś innym - to już wasze zadanie wymyślić i zaprogramować. 73 | # # Chcemy zapewnić sobie możliwość "duck typing". 74 | # 75 | # looks_like_vector = [0, 1, 2, 3] 76 | # v3 = Vector(3, 2, 1, 0) 77 | # v4 = v3 + looks_like_vector 78 | # v5 = looks_like_vector + v3 79 | # assert v4 == v5 80 | # assert isinstance(v4, Vector) 81 | # assert isinstance(v5, Vector) 82 | # assert 'Vector(3, 3, 3, 3)' == str(v4) 83 | # 84 | # v6 = Vector(0, 1, 2, 3) 85 | # assert v6 == looks_like_vector 86 | # assert looks_like_vector == v6 87 | 88 | # 89 | # Przykładowe rozwiązanie: 90 | # 91 | 92 | class Vector(): 93 | def __init__(self, *args): 94 | # print(args) 95 | self.coords = list(args) 96 | 97 | def __repr__(self): 98 | template = '{}({})' # chcemy osiągnąć NazwaKlasy(argumenty, oddzielone, przecinkami) 99 | name = self.__class__.__name__ 100 | args = ', '.join(repr(x) for x in self) 101 | return template.format(name, args) 102 | 103 | def __add__(self, other): 104 | tmp = [x + y for x, y in zip(self, other)] 105 | # for i in range(len(self)): 106 | # tmp.append(self.coords[i] + other.coords[i])= 107 | return Vector(*tmp) 108 | 109 | def __iadd__(self, other): 110 | for i, v in enumerate(other): 111 | self[i] += v 112 | return self 113 | 114 | def __radd__(self, other): 115 | return self + other 116 | 117 | def __len__(self): 118 | return len(self.coords) 119 | 120 | def __eq__(self, other): 121 | for x, y in zip(self, other): 122 | if not x == y: 123 | return False 124 | return True 125 | 126 | def __getitem__(self, idx): 127 | return self.coords[idx] 128 | 129 | def __setitem__(self, idx, value): 130 | self.coords[idx] = value 131 | 132 | 133 | # 134 | # testy poprawności 135 | # 136 | 137 | def has_getitem(cls): 138 | """Czy zdefiniowano metodę '__getitem__'?""" 139 | assert hasattr(cls, '__getitem__') 140 | 141 | 142 | def getitem_works_properly(cls): 143 | """Czy używając dostępu przez indeks otrzymujemy odpowiednie wartości?""" 144 | v = cls(1, 2, 3, 4) 145 | assert 1 == v[0] 146 | assert 2 == v[1] 147 | assert 3 == v[2] 148 | assert 4 == v[3] 149 | assert 4 == v[-1] 150 | 151 | 152 | def has_setitem(cls): 153 | """Czy zdefiniowano metodę '__set_item__'?""" 154 | assert hasattr(cls, '__setitem__') 155 | 156 | 157 | def setitem_works_properly(cls): 158 | """Czy używając przypisania przez indeks ustawiamy odpowiednie wartości?""" 159 | v1 = cls(3, 4, 8) 160 | v1[2] = 5 161 | assert v1[2] == 5 162 | 163 | 164 | def iterate_over_elements(cls): 165 | """Czy iterowanie po elementach wektora działa poprawnie?""" 166 | v2 = cls(4, 6, 8, 10, 12) 167 | dumped = [x for x in v2] 168 | assert [4, 6, 8, 10, 12] == dumped 169 | 170 | 171 | def check_eq(cls): 172 | """Czy operator __eq__ działa poprawnie?""" 173 | v1, v2 = cls(0, 1, 2, 3), cls(0, 1, 2, 3) 174 | v3, v4 = cls(0, 1, 2, 3), cls(0, 2, 2, 3) 175 | assert v1 == v2 176 | assert not v1 == v2 177 | 178 | 179 | def add_vectors(cls): 180 | """Czy można dodawać do siebie obiekty tej samej klasy?""" 181 | v1, v2 = Vector(0, 1, 2, 3), Vector(4, 5, 6, 7) 182 | ex = Vector(4, 6, 8, 10) 183 | assert ex == v1 + v2 184 | 185 | 186 | def add_like_vectors(cls): 187 | """Czy można dodawać obiekty "podobne" do naszej klasy?""" 188 | looks_like_vector = [0, 1, 2, 3] 189 | v3 = Vector(3, 2, 1, 0) 190 | v4 = v3 + looks_like_vector 191 | v5 = looks_like_vector + v3 192 | assert v4 == v5 193 | assert isinstance(v4, Vector) 194 | assert isinstance(v5, Vector) 195 | assert 'Vector(3, 3, 3, 3)' == str(v4) 196 | 197 | 198 | def comparison_with_list(cls): 199 | """Czy można porównywać z listą?""" 200 | looks_like_vector = [0, 1, 2, 3] 201 | v6 = Vector(0, 1, 2, 3) 202 | assert v6 == looks_like_vector 203 | assert looks_like_vector == v6 204 | 205 | 206 | def check_inheritance_hierarchy(cls): 207 | """Czy klasa dziedziczy tylko i wyłącznie po typie 'object'?""" 208 | assert cls.mro() == [cls, object] 209 | 210 | 211 | def check_len(cls): 212 | """Czy działa obliczanie długości wektora?""" 213 | v = cls(1, 2) 214 | assert 2 == len(v) 215 | v1 = cls(2, 4, 5.6, 7, 8) 216 | assert 5 == len(v1) 217 | 218 | 219 | assignment = Assignment( 220 | 'zadanie1', 221 | 'zadanie1.py', 222 | 'Vector', 223 | (has_getitem, getitem_works_properly, has_setitem, setitem_works_properly, 224 | iterate_over_elements, add_vectors, add_like_vectors, comparison_with_list, 225 | check_inheritance_hierarchy, check_len) 226 | ) 227 | -------------------------------------------------------------------------------- /warsztat_4/README.md: -------------------------------------------------------------------------------- 1 | W katalogu `praca_domowa` są zadania domowe. 2 | Na rozwiązanie czekamy do niedzieli **19.XI.2017 23:59:59**. 3 | Swoje rozwiązania wpisujcie do formularza: https://goo.gl/forms/DuLrUBLySP9nsBwE3 4 | Rozwiązania przysłane w inny sposób nie będą brane pod uwagę. 5 | -------------------------------------------------------------------------------- /warsztat_4/another_copy_p4b_logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaftAcademy/python4beginners/f108ae9c8ebcd94214b57c0f4a5479f36ce59a11/warsztat_4/another_copy_p4b_logo.bmp -------------------------------------------------------------------------------- /warsztat_4/another_file.txt: -------------------------------------------------------------------------------- 1 | Nowa linia 1 2 | -------------------------------------------------------------------------------- /warsztat_4/conferences_data.csv: -------------------------------------------------------------------------------- 1 | konferencja 0;konferencja 1;konferencja 2;konferencja 3;konferencja 4;konferencja 5 2 | lvezfaczqvxhljttnmttwhssawixu@gghtjd.fi;beppuyrbgpydmsjrmcpma@fzmj.af;lucnwkqxgktpasxboavjeg@ejriqbr.ba;cbbzuarcpsl@lfznlyuuf.se;briamvvmgjmdhzazadfj@xuhku.at;txdmjuunhlsbkgtqhchllqaqjmb@wok.ua 3 | ppmitv@vef.ba;hcrcncwgurrjk@amwr.ua;hhwefxkuzjtisixl@wok.es;nnzyuaglfaajzjbslzm@kiv.af;olbefvrcd@pzjerp.es;hkqsyztvipzi@wcnx.uk 4 | ivycltinjlavfkpulnrao@mpqsld.af;vcuelufzqmjbzddzonbsgg@kosevsxxz.fi;ctiyb@eqxvyp.ba;tbkkkuaagokqg@dmkmdfpdyn.ru;dvialwtuubxzwdtxob@oahrg.at;yshscfmldksuargdpaki@oiy.cz 5 | orwfdw@wok.fi;dimpcgydp@cygyi.es;mykotvlbrihmzkocczftkv@ueh.sm;ktwqu@wok.dk;pjlgeazobqlgmysptuunyxoaodz@ptndv.at;mhigscufcbokllrqwymtcifrtcren@ksnrtaffj.by 6 | bpyxlfylxdxwuhccpqvdg@lasaq.se;culgkdrhypverhc@mxbuysxj.ru;ochxmdjth@bymufcfm.br;cdxaghhtlrpcnyrknwlcw@zqtwhscaf.se;couszrnqxzdntvmy@mcaltxvj.pl;cznenbguuzwlmjbgrlacyjhz@cvtdmz.at 7 | xyukr@fszuubaeub.fi;dryqtznfqwpyihxmsjpep@larbtbh.ar;jzjmfgdlpecltyqgwb@ybxxvmllfd.ca;xnaazcwgpopb@yqliqpxxka.ca;hzbifkgvxovvsnrufcxp@zsbauw.es;nwqzlhbpawvcsdme@fau.ru 8 | smyhzjmjtqjwsvvexsvghz@wok.ua;hfaoeziqinfvqdcoscnhkaavwr@zcofsryqqk.pl;qljtqfphebsdb@uqlsoip.ba;fvugsvnawsp@ychm.se;zsfhoyylbcaz@famlu.af;zsxsufurbxhp@uamcdimz.pl 9 | ejk@pjsnaeveqy.dk;dgjz@qbsldgjpv.br;lirvdbpdl@hfzcbiixt.af;ijztjlofqcxheoggzuv@vtx.ba;alyrhvghozkkbvwydrjqke@hfzcbiixt.fi;hekwckwtyqqdvarkqjomywh@wok.ru 10 | cjsfziw@jsadpqi.cz;ymgekpeqoomhaiaieew@wok.ru;ugffqfpykswaywoxwpcgefshhh@nvvnizn.se;bnlgklbhnpcix@akfkeevs.br;ansylejrmsqnxducx@yxysdv.br;vtqqwiwqchegaptk@wok.ua 11 | beppuyrbgpydmsjrmcpma@kkgisp.pl;efxkqu@wok.cl;ykejyunwxwxwftccvvyiebzlvx@wok.at;wqhxvdmqxrzqycdoipgbdsxdtoajh@vef.uk;uybh@uxsopsikbg.ar;hoiionidicankeklpmohlizgtz@wok.sm 12 | qvgqtygopwyarcxdboapavqx@pvzfucptvp.se;tamfpbxgcglfd@wok.cl;jvbhzgfgmofbcppztymesrehjc@xhcifccku.at;jxjyrjhnvwrxvhecbakisjp@ibgaadwcco.fi;xzexfhkphvhum@wok.at;orwfdw@wok.fi 13 | nalbqwmp@ssdgetdbys.uk;idkmkbacsctdmdakeagluuxvqbcgb@stsl.ua;qljtqfphebsdb@utozh.af;briamvvmgjmdhzazadfj@bienxdbd.ba;dgzbjxxgdxyunqyzxghbvrdrbd@qxkbzsjz.cl;hhwefxkuzjtisixl@wok.se 14 | tdocgfvijuzhone@zzyjbobjcx.fi;qljtqfphebsdb@uamcdimz.es;ptwttqxqyljtuxqstphttzkcnpnl@wezgtexd.cz;ytzxizuuhbshcfrv@wok.fi;hfaoeziqinfvqdcoscnhkaavwr@zcofsryqqk.pl;zsxsufurbxhp@qdxcszdt.cl 15 | qekv@udfcjpuhjk.af;lirvdbpdl@etraamocz.ba;vlzayzdetrrpesqyotmb@wix.ca;gqupuadngvuopvdcf@xkllkjja.ua;kdls@ptllgohbo.ba;sjafr@utmffmm.ua 16 | qhwchoatcuuabbpvrquicgcjpnjmew@bmjbmgzaf.fi;kjoaympljshx@wok.es;diqfptyflq@akbzuiq.de;angtztykkjrfmbuietroxqgwrcswgi@evyroerbie.sm;kqbvyigpsjjmqlxpjypmszjnkry@sgjpbxkb.ua;thav@wok.cl 17 | wynltmxpygtizzqmxt@wok.ar;ansylejrmsqnxducx@uqlsoip.dk;ptwttqxqyljtuxqstphttzkcnpnl@sbyubstbmc.fi;xyukr@fszuubaeub.fi;thav@wok.cl;gzrexzdibggs@oytcxdfzow.de 18 | xapdrotdznngrkkqy@cwqye.sm;xyukr@hfzcbiixt.ca;hcrcncwgurrjk@isntphktfl.de;hhwefxkuzjtisixl@wok.es;azogrodldhtmmwpmqvjpfbh@xgvhkyy.de;occjts@lfznlyuuf.br 19 | iifvgnwqicqa@mlz.cl;hhwefxkuzjtisixl@wok.es;gesp@jhgadvzqi.ar;lvezfaczqvxhljttnmttwhssawixu@kkgisp.ua;noriyvhouckw@wok.at;swvuqdgvsrullelhxwzsfjoalzgk@cbya.by 20 | gesp@shsqbxtt.fi;hebejqcxwcihtwmlhmtg@hsw.uk;yeieazwlvkgyafoisnubrqjhviisdr@fehj.pl;dnphc@qcrohwtuqx.af;nnzyuaglfaajzjbslzm@artduww.fi;qqpgoxfljuiz@wok.cl 21 | ruc@kdii.ua;couszrnqxzdntvmy@lgbm.ca;wtcistagvldeeyw@ngaexurotx.se;upmnkugqgfyotlkzatbwufcl@amwr.at;bnbeokroxv@pefowzqorc.ar;hnwvyt@uwu.ca 22 | wotcinplbwjipactepkyk@ead.sm;ctiyb@akbzuiq.ua;nkpbipqmub@wvhtos.ua;iprlgtvizpkwvuauknybo@wok.ba;wkniuffkvzqswdfqhfnxg@wok.ar;bbzjrwbrgrywmlzeohnfgyjq@dyl.at 23 | nnzyuaglfaajzjbslzm@artduww.fi;zdxopiskgeomcdkgzfaxrhfgh@ead.cz;ruc@kdii.ua;mhigscufcbokllrqwymtcifrtcren@evyroerbie.ba;ujwgmdnulhhytdybxdinabb@pkns.es;lqzdoyrfjcvoehvjp@mcaltxvj.dk 24 | kwxakssjltmxdohukslxqtdjokwvsj@grtdovinnr.ba;briamvvmgjmdhzazadfj@xuhku.at;rcsohozimrlilgysgfmhx@uxiaxufay.by;wwgxrxlazhltfizoy@irkdwhaxi.af;ijztjlofqcxheoggzuv@npnpnctdp.de;jabbun@ylgiw.fi 25 | gesp@mmqcyirc.cz;nyimhyutfqsncuqleopjfu@kdii.se;bnbeokroxv@wdn.ua;cdnitatkllvcvycrdkdlzgvkpjan@wok.es;iprlgtvizpkwvuauknybo@wok.es;qhwchoatcuuabbpvrquicgcjpnjmew@bmjbmgzaf.fi 26 | ykfvxlot@cabnhbne.ca;tdocgfvijuzhone@zzyjbobjcx.fi;dpobbznglqrypxnryxcxbfv@kyreyoqml.cl;nyimhyutfqsncuqleopjfu@mlwyokn.es;yjl@jicctch.sm;ffjfovboerdonvdnxu@vfs.ba 27 | xyks@ilef.cz;dtxkeiaut@pjsnaeveqy.cl;oej@wok.de;zr@kdii.cl;ngjsyzgtbbfxqxpiu@decajwyrqm.at;lkwqnqx@oahrg.cz 28 | olbefvrcd@rzjchy.sm;dtlelfiahsqfmodjeoocul@ahn.ua;gggfrbjbvxvlitszcnxdxjwr@wok.pl;briamvvmgjmdhzazadfj@cwu.es;dtxkeiaut@yhaku.pl;lirvdbpdl@etraamocz.ba 29 | atkoamcfilsciwbmfbfkjenlr@qwljailo.ca;yhyccevbpywgeoczhuexiyipdgo@vwd.by;lztdadzsovcuhksmesmif@ftgwj.at;oj@oiy.de;tamfpbxgcglfd@wok.cl;dlweaokxbohveyazucsnhgalyvtvbt@lzyzihao.de 30 | rajvjqgsfwts@aadfaf.ua;hnwvyt@uwu.ca;ufbucsgfyxcunqdtyiiohhrht@glbgbyu.fi;fvugsvnawsp@worv.es;raifwsripgsajdwmwreoalptd@oitm.ru;fghrn@qdjnkv.dk 31 | idkmkbacsctdmdakeagluuxvqbcgb@uxg.es;arivbalqmzzlvrq@zelslz.cz;kjpl@wok.by;tkrstlwxo@kcf.by;lvezfaczqvxhljttnmttwhssawixu@viet.by;ykejyunwxwxwftccvvyiebzlvx@wok.at 32 | jhmwxqbphcfafxwjfcltrohsju@wezgtexd.at;ufmryhwwkdfkzzpteup@zhh.ru;jhmwxqbphcfafxwjfcltrohsju@tzy.ru;txeidmbjmpcmppylvaxrxwgcbchtdt@xdpmsltjn.ua;lztdadzsovcuhksmesmif@vecngtrc.ba;ppasectficmugusmrfqriklpy@uqlsoip.uk 33 | ektznvkmlyrewsgdmsvgfjzofdbkb@ueh.af;mhigscufcbokllrqwymtcifrtcren@ibaf.ru;bqkeermv@wok.af;couszrnqxzdntvmy@pxfyryxl.sm;hfaoeziqinfvqdcoscnhkaavwr@jmrwtbc.ba;dev@kct.by 34 | otgwuladierhprivydiivtmgpfhf@hfzcbiixt.ar;bbzjrwbrgrywmlzeohnfgyjq@dyl.at;neolemgsw@osaslunew.se;nyimhyutfqsncuqleopjfu@sjuzabv.uk;yhyccevbpywgeoczhuexiyipdgo@xhcifccku.se;pxgoxtxebmxnx@nvvnizn.se 35 | ttpsktatnlfhvfvynmqjl@wok.ca;qhwchoatcuuabbpvrquicgcjpnjmew@bmjbmgzaf.fi;eolsmrrxpemkjhyicph@ihljrjp.ua;xevtwccbjkhlkqhr@wok.cz;dxuqnzszwufibcwxlgddvmnknx@tzy.pl;tggspmooeqdwcuvkacigovigguobj@eihjjjgpen.by 36 | ykfvxlot@vgasse.ar;virkwcoonpt@bqqvlphsba.at;obehgoooffldthpqafcxrtziodtv@mwcus.ru;okjqrjixmcwtggriq@pvrkpyo.cz;uskoknhevmcungtctmgaqwlga@qwdh.cz;mlhcgkryeyxpzquxyrgyef@cbeerpjcw.br 37 | cjsfziw@itonmbxdc.at;fbxpuxdkeupqslbydskfiptyzedoue@wok.at;ektznvkmlyrewsgdmsvgfjzofdbkb@vrhxpwzb.fi;ootstiipwujr@dprplrey.se;kwxakssjltmxdohukslxqtdjokwvsj@dvev.fi;xyukr@hfzcbiixt.ca 38 | dpobbznglqrypxnryxcxbfv@egtnadhn.pl;qvgqtygopwyarcxdboapavqx@qwljailo.pl;ufmryhwwkdfkzzpteup@idr.at;eelgbmmhtxf@wok.es;qekv@gegavijh.cz;xevtwccbjkhlkqhr@wok.br 39 | yzcjsqjmjczvtig@wdn.cz;keirmlbtjfxoyfubvrgwvlgv@yspdso.ar;upmnkugqgfyotlkzatbwufcl@amwr.at;jbvhyhyafhlrpyszznre@zblpljuv.br;ijfydsbwpulewzljtwmmxysej@znugaqu.af;igfatfmksol@wok.sm 40 | fkxeoduko@sacgjdk.ar;bntxuszbxorjdlehr@xnqjjxshg.es;gesp@ranac.ca;dlweaokxbohveyazucsnhgalyvtvbt@lzyzihao.de;tduiqhhpdebaffw@tzy.ba;mer@hbqol.cl 41 | bbzjrwbrgrywmlzeohnfgyjq@dyl.at;charslmrfpugsabaahe@wok.ar;qschhcinplkyhzzafdfapmio@fau.es;ctiyb@kosevsxxz.sm;pdpqxlhyfxpukompamqmrcpzsf@fpxyquqyog.by;beppuyrbgpydmsjrmcpma@bxzytaq.fi 42 | xevtwccbjkhlkqhr@wok.cz;ymglgcuyjxzysiklojlmqmkqaq@cabnhbne.fi;jcr@eww.se;hdesnnbomivpkzgwaboxisj@vkwkzswdq.dk;lztdadzsovcuhksmesmif@jkhsetj.es;gyi@wok.ar 43 | dlweaokxbohveyazucsnhgalyvtvbt@isntphktfl.cl;drvqyhxaporbqighcxtggdmw@rycz.ba;nkpbipqmub@yncclzsqh.cl;zsxsufurbxhp@uamcdimz.pl;drvqyhxaporbqighcxtggdmw@zyrpsryhvm.ba;ktwqu@wok.dk 44 | qchdfqbkcrmlgv@kirsu.sm;lluzfcuggqcxrpknfmjrjlvanmn@hfzcbiixt.ca;ppmitv@esnpuhlo.br;qllt@akbzuiq.ba;bqkeermv@wok.af;ctiyb@nmmlg.cz 45 | cdnitatkllvcvycrdkdlzgvkpjan@wok.es;noriyvhouckw@wok.at;tptwdhtohqcffq@yczeuphxfx.cl;lzcufg@fehj.ca;hebejqcxwcihtwmlhmtg@uyute.cl;tjwztnqeuuugoiwey@ejriqbr.ar 46 | ivycltinjlavfkpulnrao@qdieeqdb.fi;rtdyfzhkbfcplhefraytz@bboclqryh.by;zsxsufurbxhp@qdxcszdt.cl;mykotvlbrihmzkocczftkv@jqphkgj.fi;xzexfhkphvhum@wok.se;uybh@kysvwnzxeb.ru 47 | uzycasjamcbrgzxebmd@tbudb.dk;tjwztnqeuuugoiwey@ejriqbr.ar;hoiionidicankeklpmohlizgtz@wok.sm;yvgee@rdpyfq.ba;xrpheyoqlaqoso@isdcudwry.se;ddglswxmlrwedmdqhnagtmixzy@imfdxc.by 48 | zsxsufurbxhp@uamcdimz.pl;eilciqwluiouuwnnjxx@cwqye.de;psfzivhyvquwdzmkcsikphtozps@easogc.fi;lucnwkqxgktpasxboavjeg@ejriqbr.ba;erqmjriirwuplftcvpfe@lojmkfdkpl.de;vtqqwiwqchegaptk@wok.ba 49 | ujwgmdnulhhytdybxdinabb@worv.br;ktwqu@wok.dk;rhvefretdphpbwrdlsscrckf@cwu.pl;dtxkeiaut@akfkeevs.fi;wqhxvdmqxrzqycdoipgbdsxdtoajh@znugaqu.by;aqtlhvnpdr@wok.pl 50 | dtxkeiaut@gnpajskzb.uk;hebejqcxwcihtwmlhmtg@uyute.cl;ansylejrmsqnxducx@uqlsoip.dk;nsywzgizodmpzduvloajeothmh@vgasse.pl;okjqrjixmcwtggriq@avgzvwzgb.uk;isay@waws.cl 51 | ducbtdarqqksmssqvfaksbgx@etj.dk;dxuqnzszwufibcwxlgddvmnknx@wvpzkz.ar;phnle@kyreyoqml.at;jmxefxasguvjkqpxeqqocsewn@yhaku.ru;iifvgnwqicqa@esnpuhlo.cz;wkniuffkvzqswdfqhfnxg@wok.br 52 | ymglgcuyjxzysiklojlmqmkqaq@mpqsld.cl;jzjmfgdlpecltyqgwb@etoupp.ru;zwqlj@wok.de;kjz@tzgaysxc.pl;arivbalqmzzlvrq@cqxdsdeo.ar;abw@qdxcszdt.de 53 | jhmwxqbphcfafxwjfcltrohsju@xbt.dk;nkpbipqmub@kkgisp.ar;rxoopezoyczcknudru@lbnkhne.af;pxqgoobllllwdnvclsuzkycupubz@etoupp.pl;bntxuszbxorjdlehr@pvrkpyo.cz;vgxoqsitsaerdbtrxypfsfmmasqq@ahhm.cl 54 | scknjengrhandmfmgatbdgdtrwjsq@dmkmdfpdyn.de;ckatcqvzni@bvkzlqhdt.uk;ufmryhwwkdfkzzpteup@ovq.by;ochxmdjth@tzgaysxc.pl;uskoknhevmcungtctmgaqwlga@lzds.af;nyimhyutfqsncuqleopjfu@kdii.se 55 | tjwztnqeuuugoiwey@ejriqbr.ar;kyegjmqtrbtzefqlrixy@fboocadbni.cz;hkqsyztvipzi@ftf.ua;bnbeokroxv@lgbm.uk;yhyccevbpywgeoczhuexiyipdgo@zmaaqhtugn.cz;uybh@qfeeuco.br 56 | jwkvlvvb@boxtxvkvb.ua;dtlelfiahsqfmodjeoocul@izghtapi.de;tamfpbxgcglfd@wok.cl;gftvlseys@wok.se;kazbrkatswhzhxdqdes@wix.es;oej@wok.es 57 | gqupuadngvuopvdcf@bxzytaq.ar;ivycltinjlavfkpulnrao@isrymguyxt.pl;mhigscufcbokllrqwymtcifrtcren@racholujgb.ar;fgyhfe@wcrkehnp.af;qljtqfphebsdb@uqlsoip.ba;zwqlj@wok.pl 58 | vjyxcutxnxsebbtjuhov@wok.cz;briysriqlywfs@ljcwsdmb.ba;zepchmlgio@evyroerbie.sm;vbnahxexchwrbsxfedq@dyhxycnh.dk;diqfptyflq@mwaedserli.cl;hzbxtzfldwtqswwcjxfsghdx@kiv.ca 59 | arixqrodhtfmnjywlnage@okdcqqe.ar;ducbtdarqqksmssqvfaksbgx@pan.af;bbzjrwbrgrywmlzeohnfgyjq@dyl.at;ppmitv@jicctch.uk;obmcirwwsidsqygj@uij.ru;fdpqblfjnlmwbiwxeppq@vef.at 60 | tphcpgynuqar@izghtapi.cl;briamvvmgjmdhzazadfj@cwu.es;jcr@eww.pl;cja@wok.sm;erqmjriirwuplftcvpfe@moafr.by;iprlgtvizpkwvuauknybo@wok.ba 61 | acslhtmpfyhxr@sbyubstbmc.ru;hhlkegtik@etraamocz.br;nsywzgizodmpzduvloajeothmh@bft.at;ngjsyzgtbbfxqxpiu@decajwyrqm.at;hebejqcxwcihtwmlhmtg@zzyjbobjcx.cl;kjpl@wok.at 62 | abw@qdxcszdt.de;hfaoeziqinfvqdcoscnhkaavwr@jmrwtbc.ba;gilrazoed@rpxtifwv.at;lvezfaczqvxhljttnmttwhssawixu@xnnnp.sm;cdnitatkllvcvycrdkdlzgvkpjan@wok.cz;cwzjzimvxqrkcppbakngbexpoyvdeo@hjsxjoyzma.de 63 | nyimhyutfqsncuqleopjfu@sjuzabv.uk;mlhcgkryeyxpzquxyrgyef@cbeerpjcw.br;zdxopiskgeomcdkgzfaxrhfgh@ead.cz;dqwjjraihubn@akfkeevs.ca;hwpzbwqmmztnuipwdwjoypa@yvyftik.fi;ugffqfpykswaywoxwpcgefshhh@nvvnizn.se 64 | qschhcinplkyhzzafdfapmio@grtdovinnr.de;vgxoqsitsaerdbtrxypfsfmmasqq@lryzqaboy.de;hebejqcxwcihtwmlhmtg@jnc.at;zsfhoyylbcaz@gnbxvnnopd.by;hobuhkadl@hfzcbiixt.ar;qzadysztazgyrmitqzual@wok.af 65 | rdrtjnbkjbvcwibczn@lojmkfdkpl.by;oajvbccwwfmxcnjjpipbbkrudukiu@zyqzsnsy.ru;abw@qdxcszdt.de;necleossyquibvzncsrxgbbi@wok.cl;mxpgwwdstuwnyyltdlduyslx@shhsendiiy.de;nsct@hjsxjoyzma.br 66 | bpyxlfylxdxwuhccpqvdg@utpq.ca;kmdnihdudrq@ycaaicr.ca;ymglgcuyjxzysiklojlmqmkqaq@racholujgb.se;kmdnihdudrq@tsjy.cl;kjkuidlduykdcy@pwkz.fi;rhvefretdphpbwrdlsscrckf@cwu.pl 67 | zr@kdii.cl;ftfhtprfme@etoupp.at;hcrcncwgurrjk@amwr.ua;cusvqoxeqdwdllxuhkfbp@fpxyquqyog.uk;aqtlhvnpdr@wok.ba;ppasectficmugusmrfqriklpy@dqclbpvzcd.ca 68 | no@cbya.ar;pjlgeazobqlgmysptuunyxoaodz@gophttna.ar;lirvdbpdl@fszuubaeub.cz;jxjyrjhnvwrxvhecbakisjp@viet.de;hhwefxkuzjtisixl@wok.es;zjsmptvilfcicd@kext.br 69 | uzycasjamcbrgzxebmd@znugaqu.uk;tkrstlwxo@xgvhkyy.dk;txeidmbjmpcmppylvaxrxwgcbchtdt@xlb.es;vgxoqsitsaerdbtrxypfsfmmasqq@lryzqaboy.de;ncnojrzmzn@nbt.af;nyimhyutfqsncuqleopjfu@artduww.ba 70 | nmctv@pan.cz;bntxuszbxorjdlehr@irkdwhaxi.ca;dimpcgydp@zwbvzingg.br;ourlqrmkcaaiyqcuutccxsshdsg@zfsgsern.dk;idt@wok.at;rtyjyhderildmp@hsw.sm 71 | hcrcncwgurrjk@isntphktfl.de;rxoopezoyczcknudru@njqx.cl;cwzjzimvxqrkcppbakngbexpoyvdeo@xcyuvy.br;eolsmrrxpemkjhyicph@ihljrjp.ua;ykfvxlot@rycz.ca;mnzzfbgfvvozye@ybxxvmllfd.ba 72 | culgkdrhypverhc@shhsendiiy.by;xyks@mpsecu.ua;swvuqdgvsrullelhxwzsfjoalzgk@agals.uk;ivycltinjlavfkpulnrao@bxjhuub.pl;hhlkegtik@khtovn.sm;otgwuladierhprivydiivtmgpfhf@xllbln.se 73 | rhvefretdphpbwrdlsscrckf@cwu.pl;qymsqocimprrytcortbi@hxvbjqtusl.br;cdnitatkllvcvycrdkdlzgvkpjan@wok.cz;hzbxtzfldwtqswwcjxfsghdx@kiv.ca;ncnojrzmzn@nvp.by;atkoamcfilsciwbmfbfkjenlr@yxh.dk 74 | hzbifkgvxovvsnrufcxp@mmqcyirc.fi;upmnkugqgfyotlkzatbwufcl@amwr.at;gn@pvzfucptvp.ar;eudavbkbrlazsbjlvgwlujowu@viet.at;jcr@fisdm.se;gplvkaxgkzhwijssmcat@mxbuysxj.dk 75 | fnverpb@fszuubaeub.de;vjyxcutxnxsebbtjuhov@wok.cz;smyhzjmjtqjwsvvexsvghz@wok.af;cbbzuarcpsl@opggeamc.de;virkwcoonpt@bqqvlphsba.at;hcrcncwgurrjk@amwr.ua 76 | hkqsyztvipzi@gozqs.uk;fgyhfe@wcrkehnp.af;hbrjqdkfnqyztxgzu@gjl.sm;oajvbccwwfmxcnjjpipbbkrudukiu@zyqzsnsy.ru;uskoknhevmcungtctmgaqwlga@gsilzhfaj.af;swvuqdgvsrullelhxwzsfjoalzgk@ftf.fi 77 | fkmvbwxbfixmsbaprbsrxnalti@easogc.sm;atkoamcfilsciwbmfbfkjenlr@xlb.pl;idkmkbacsctdmdakeagluuxvqbcgb@irkdwhaxi.at;eeseb@pljmbxgi.fi;tphcpgynuqar@izghtapi.cl;smyhzjmjtqjwsvvexsvghz@wok.uk 78 | dgzbjxxgdxyunqyzxghbvrdrbd@sgjpbxkb.es;wenbcploy@fehj.ca;zr@kdii.cl;pxgoxtxebmxnx@dqclbpvzcd.ua;cjsfziw@isrymguyxt.by;dtlelfiahsqfmodjeoocul@ahn.ua 79 | dlweaokxbohveyazucsnhgalyvtvbt@lzyzihao.de;ruc@bqqvlphsba.sm;dqwjjraihubn@wnldx.br;xrpheyoqlaqoso@ssdgetdbys.es;cznenbguuzwlmjbgrlacyjhz@tprimph.dk;ymglgcuyjxzysiklojlmqmkqaq@xlwxbssr.uk 80 | idt@wok.at;hmhnhawhelnblmdckqezjbpsbntcm@nzmkjoae.cl;otgwuladierhprivydiivtmgpfhf@btmlbi.cz;jhmwxqbphcfafxwjfcltrohsju@qvsssahiz.af;mykotvlbrihmzkocczftkv@xwr.ua;etbvoyrwnrjewwoechtjtpxgjxt@irkdwhaxi.se 81 | zsxsufurbxhp@uamcdimz.cz;yeieazwlvkgyafoisnubrqjhviisdr@fehj.pl;nalbqwmp@tmohtbj.br;uskoknhevmcungtctmgaqwlga@worv.by;oej@wok.de;mwhgcfxtyphaso@nzntf.cz 82 | hbrjqdkfnqyztxgzu@wvpzkz.ua;bnbeokroxv@cuowszpk.se;erqmjriirwuplftcvpfe@wnldx.sm;gzrexzdibggs@padodntek.ar;rajvjqgsfwts@nhayyitzk.br;xzexfhkphvhum@wok.se 83 | grtedtcguvgfrqemhuegcsqhhoip@wok.se;ppasectficmugusmrfqriklpy@dqclbpvzcd.ca;yshscfmldksuargdpaki@tsjy.dk;diqfptyflq@wnldx.cl;hwpzbwqmmztnuipwdwjoypa@hhy.fi;ijzelphoiieworoukf@okdcqqe.br 84 | huzfmvqsirdsrcbbjqzrciygihig@wok.ru;yhcpogihwfbk@galongk.br;vlzayzdetrrpesqyotmb@opggeamc.ar;yjyhptvflowlzadedvoyrcddgrc@smjbitk.pl;qllt@gejabo.uk;tggspmooeqdwcuvkacigovigguobj@wvpzkz.uk 85 | nyimhyutfqsncuqleopjfu@mlwyokn.es;ssabdgppy@nzmkjoae.at;kwdjzumynenpokppopoaruu@ojblwm.se;ssoqmbenhcjbrilahiavoetyonxeq@cwqye.at;lkwqnqx@qdieeqdb.pl;culgkdrhypverhc@jxuznxdd.de 86 | hfaoeziqinfvqdcoscnhkaavwr@jmrwtbc.ba;hzbxtzfldwtqswwcjxfsghdx@zyqzsnsy.cl;beppuyrbgpydmsjrmcpma@cuowszpk.fi;gqupuadngvuopvdcf@wngy.cz;lzcufg@fehj.ca;briamvvmgjmdhzazadfj@xuhku.at 87 | lrfosdfcigaksjppimo@vfs.br;aqtlhvnpdr@wok.pl;tcxlmqauboxxztawg@bacjb.es;uvez@wok.se;vxbclnsdrfnropisfbmshnqgqej@isntphktfl.by;yjyhptvflowlzadedvoyrcddgrc@smjbitk.pl 88 | vhhocgdjnqrwvtnczuajm@wok.br;ijztjlofqcxheoggzuv@dyhxycnh.ar;bvjwonautdxqkx@fehj.pl;bqkeermv@wok.af;fdxcf@zfsgsern.at;binrzwexeam@mpqsld.at 89 | rtyjyhderildmp@hsw.sm;eolsmrrxpemkjhyicph@ihljrjp.ua;qjzuleyy@chf.fi;hebejqcxwcihtwmlhmtg@jnc.at;dvialwtuubxzwdtxob@wvhtos.br;arivbalqmzzlvrq@zelslz.cz 90 | kjoaympljshx@wok.es;eeseb@pljmbxgi.fi;zsfhoyylbcaz@qfeeuco.ca;vlzayzdetrrpesqyotmb@tzy.ua;rtyjyhderildmp@hsw.sm;ijzelphoiieworoukf@hfzcbiixt.af 91 | qymsqocimprrytcortbi@dmkmdfpdyn.af;zjsmptvilfcicd@oqvjjpdz.pl;pbbejy@nvp.pl;ytyckyxinhccszppbzdknbw@mpqik.cz;briamvvmgjmdhzazadfj@cwu.es;upmnkugqgfyotlkzatbwufcl@btmlbi.cz 92 | sjafr@yqliqpxxka.se;grtedtcguvgfrqemhuegcsqhhoip@wok.se;yshscfmldksuargdpaki@xbt.by;lluzfcuggqcxrpknfmjrjlvanmn@waws.sm;nwqzlhbpawvcsdme@udfcjpuhjk.se;yzcjsqjmjczvtig@nzmkjoae.pl 93 | azogrodldhtmmwpmqvjpfbh@vgasse.cl;ffjfovboerdonvdnxu@vfs.ba;lirvdbpdl@etraamocz.ba;oj@utpq.es;wynltmxpygtizzqmxt@wok.ar;bnlgklbhnpcix@zhh.ru 94 | mqticxwmnykhlcjme@ocbek.uk;ijztjlofqcxheoggzuv@ssdgetdbys.sm;ttpsktatnlfhvfvynmqjl@wok.ca;pdpqxlhyfxpukompamqmrcpzsf@vzn.at;qllt@vkwkzswdq.es;kjpl@wok.by 95 | jzjmfgdlpecltyqgwb@qvsssahiz.by;obmcirwwsidsqygj@uij.ru;tjwztnqeuuugoiwey@yvtzngsw.by;fghrn@qdjnkv.dk;phnle@lsaotsxrin.dk;ibmohbgrckbhfbk@kyreyoqml.de 96 | gesbsnructafygxxcajtvqujkveu@imhaqt.ru;nnzyuaglfaajzjbslzm@kiv.af;ptwttqxqyljtuxqstphttzkcnpnl@yhaku.by;yjl@akfkeevs.by;hkqsyztvipzi@ivamk.af;fbxdtyltydhgtgrz@wok.ua 97 | jbvhyhyafhlrpyszznre@zfsgsern.se;mnzzfbgfvvozye@opggeamc.af;mnzzfbgfvvozye@bxjhuub.ua;mhigscufcbokllrqwymtcifrtcren@tbudb.es;smyhzjmjtqjwsvvexsvghz@wok.ua;xfmlliaymqbyboielimfu@nzntf.ru 98 | smyhzjmjtqjwsvvexsvghz@wok.uk;hkqsyztvipzi@pwkz.ba;lucnwkqxgktpasxboavjeg@tzgaysxc.ba;oj@qvsssahiz.by;gesp@gjl.af;ihkjflydsrju@ajkd.sm 99 | siyqiowghutxp@wltepkbyc.de;yhcpogihwfbk@gozqs.pl;xyukr@fszuubaeub.fi;exixfgjaeaigqrjmzwbftlntjzwn@padodntek.sm;ijfydsbwpulewzljtwmmxysej@mqgk.ba;wynltmxpygtizzqmxt@wok.ar 100 | zsxsufurbxhp@isntphktfl.se;otgwuladierhprivydiivtmgpfhf@btmlbi.cz;imjpcbbm@opggeamc.es;tmguldpvgf@ranac.ru;hzbxtzfldwtqswwcjxfsghdx@kiv.ca;jzjmfgdlpecltyqgwb@tsjy.br 101 | culgkdrhypverhc@aadfaf.at;nnzyuaglfaajzjbslzm@gvgapdzuou.pl;vgxoqsitsaerdbtrxypfsfmmasqq@lryzqaboy.de;angtztykkjrfmbuietroxqgwrcswgi@ivfov.fi;idgiptckagwx@rycz.ar;tdocgfvijuzhone@zzyjbobjcx.fi 102 | exixfgjaeaigqrjmzwbftlntjzwn@hbqol.es;smyhzjmjtqjwsvvexsvghz@wok.af;ihkjflydsrju@gjlrkykl.sm;hebejqcxwcihtwmlhmtg@uyute.cl;cdxaghhtlrpcnyrknwlcw@ranac.ca;hcrcncwgurrjk@isntphktfl.de 103 | dimpcgydp@znugaqu.br;zdxopiskgeomcdkgzfaxrhfgh@pymprwke.ru;nyimhyutfqsncuqleopjfu@sjuzabv.uk;kyegjmqtrbtzefqlrixy@tzy.ba;mqticxwmnykhlcjme@yhtkyxxdba.de;efxkqu@wok.cl 104 | eogspcmtokikqaugdqyty@nmmlg.fi;ruc@amwr.ca;qzadysztazgyrmitqzual@wok.af;ppasectficmugusmrfqriklpy@dqclbpvzcd.ca;vbnahxexchwrbsxfedq@nmmlg.ru;ruc@kdii.ua 105 | mhigscufcbokllrqwymtcifrtcren@jsswlq.af;otgwuladierhprivydiivtmgpfhf@hfzcbiixt.ar;ujwgmdnulhhytdybxdinabb@yue.ru;tkrstlwxo@wdn.br;laqxscblsyrotqz@xzxsgf.sm;eswj@kext.ba 106 | ytyckyxinhccszppbzdknbw@isrymguyxt.ru;zepchmlgio@zfsgsern.dk;nyimhyutfqsncuqleopjfu@artduww.ba;mamvfazoakjenojhaumnicofgnbm@cwu.fi;qqpgoxfljuiz@wok.cl;gqupuadngvuopvdcf@tsjy.cz 107 | lqzdoyrfjcvoehvjp@ccp.br;fnverpb@skymzxknjd.ar;lvezfaczqvxhljttnmttwhssawixu@hhjsomr.ba;beppuyrbgpydmsjrmcpma@zblpljuv.ba;wwgxrxlazhltfizoy@drudal.cl;jxjyrjhnvwrxvhecbakisjp@bft.uk 108 | pxgoxtxebmxnx@dqclbpvzcd.ua;ncnojrzmzn@seu.af;fuxaiht@fcfxnqhpn.cz;oej@wok.de;ndynoktuabg@izghtapi.uk;fgyhfe@wcrkehnp.af 109 | bntxuszbxorjdlehr@snlpoks.by;xyks@ilef.cz;obehgoooffldthpqafcxrtziodtv@lzds.by;nyimhyutfqsncuqleopjfu@kdii.se;moo@avgzvwzgb.pl;gggfrbjbvxvlitszcnxdxjwr@wok.pl 110 | kqbvyigpsjjmqlxpjypmszjnkry@worv.by;xevtwccbjkhlkqhr@wok.cz;wkniuffkvzqswdfqhfnxg@wok.br;no@zangp.fi;kyegjmqtrbtzefqlrixy@nbeqcylup.sm;zepchmlgio@ranac.ca 111 | kmdnihdudrq@glbgbyu.ca;ugffqfpykswaywoxwpcgefshhh@nvvnizn.se;beppuyrbgpydmsjrmcpma@cwqye.by;etbvoyrwnrjewwoechtjtpxgjxt@oytcxdfzow.af;tptwdhtohqcffq@yczeuphxfx.cl;xyks@ilef.cz 112 | mpfn@nednhdcag.at;qktbohuzjmubjeoaliw@zyrpsryhvm.cz;lrfosdfcigaksjppimo@vfs.br;hdesnnbomivpkzgwaboxisj@kqljjnx.cz;eilciqwluiouuwnnjxx@xnqjjxshg.ca;lirvdbpdl@hfzcbiixt.af 113 | clqd@cuddbnapy.by;jiibpcgcohaf@fkhrkebghm.cz;gyi@wok.ar;eswj@kext.ba;fkxeoduko@njqx.cz;qqpgoxfljuiz@wok.es 114 | kwxakssjltmxdohukslxqtdjokwvsj@pwkz.se;uskoknhevmcungtctmgaqwlga@zblpljuv.by;rbyoaiyvasy@tzy.ba;ckatcqvzni@dstvqioz.fi;vhhocgdjnqrwvtnczuajm@wok.de;lfbqsujiwgihqoxxz@jmrwtbc.fi 115 | pxgoxtxebmxnx@nvvnizn.se;lzcufg@fehj.ca;dxuqnzszwufibcwxlgddvmnknx@dunfmelzn.es;pbbejy@nbt.af;dimpcgydp@kqljjnx.ru;alyrhvghozkkbvwydrjqke@hfzcbiixt.fi 116 | yhcpogihwfbk@gspyxf.cz;tkrstlwxo@qvsssahiz.dk;kjkuidlduykdcy@lzds.ru;hfaoeziqinfvqdcoscnhkaavwr@jmrwtbc.ba;beppuyrbgpydmsjrmcpma@ueh.af;iprlgtvizpkwvuauknybo@wok.es 117 | rbyoaiyvasy@caa.ba;uvkkmkhiaawxsrwsezpxrnqqhv@wok.es;kazbrkatswhzhxdqdes@wvhtos.ca;jbvhyhyafhlrpyszznre@racholujgb.ar;fdxcf@gnpajskzb.fi;oej@wok.de 118 | vcuelufzqmjbzddzonbsgg@vgasse.es;hkqsyztvipzi@rqkdbz.at;cz@apatas.cz;zmc@fkhrkebghm.se;uybh@eduxgpfjk.dk;uskoknhevmcungtctmgaqwlga@dzz.pl 119 | ujwgmdnulhhytdybxdinabb@uynr.cz;xzexfhkphvhum@wok.se;dvialwtuubxzwdtxob@ypqkns.se;lqzdoyrfjcvoehvjp@yvyftik.by;fghrn@qdjnkv.dk;ohzzyyqehhfgznnxvgri@wok.af 120 | kazbrkatswhzhxdqdes@zrkp.de;noadglzqqhwwvd@wvhtos.at;otgwuladierhprivydiivtmgpfhf@hfzcbiixt.ar;hcrcncwgurrjk@isntphktfl.de;lkwqnqx@zmaaqhtugn.sm;cja@wok.sm 121 | fbxpuxdkeupqslbydskfiptyzedoue@wok.at;wtcistagvldeeyw@ngaexurotx.se;lfbqsujiwgihqoxxz@jmrwtbc.fi;ckatcqvzni@dmkmdfpdyn.ua;qljtqfphebsdb@uamcdimz.es;rcsohozimrlilgysgfmhx@uxiaxufay.by 122 | gftvlseys@wok.se;yzcjsqjmjczvtig@wdv.sm;xevtwccbjkhlkqhr@wok.br;gplvkaxgkzhwijssmcat@ctxkmdn.br;diqfptyflq@qwdh.de;nyimhyutfqsncuqleopjfu@mlwyokn.es 123 | dev@kct.by;gsqexqbqmjkfiiejdydbatbtrtzueg@wok.ca;ppasectficmugusmrfqriklpy@uqlsoip.uk;qqpgoxfljuiz@wok.cl;ibmohbgrckbhfbk@wix.dk;kdls@ptllgohbo.ba 124 | qekv@qfeeuco.es;cja@wok.br;ansylejrmsqnxducx@ipfpln.se;hypreabpousoaujurogkvu@bmjbmgzaf.es;eilciqwluiouuwnnjxx@ivamk.ru;arivbalqmzzlvrq@cqxdsdeo.ar 125 | nsct@zyqzsnsy.es;lucnwkqxgktpasxboavjeg@mlwyokn.ba;ghkuqhdyueocvqgvpjzadqo@vecngtrc.se;ektznvkmlyrewsgdmsvgfjzofdbkb@utp.br;rajvjqgsfwts@dwlchfu.ar;xyukr@fszuubaeub.fi 126 | pxgoxtxebmxnx@cbeerpjcw.es;ewhbkrs@wok.sm;xzexfhkphvhum@wok.at;vlzayzdetrrpesqyotmb@sbyubstbmc.at;hhwefxkuzjtisixl@wok.se;qljtqfphebsdb@utozh.af 127 | dxuqnzszwufibcwxlgddvmnknx@xkllkjja.at;mwhgcfxtyphaso@nzntf.cz;ujwgmdnulhhytdybxdinabb@zsbauw.de;vhhocgdjnqrwvtnczuajm@wok.br;lztdadzsovcuhksmesmif@dwlchfu.ua;gmgotzwfpmjyonczezuty@aykkjvki.ca 128 | cznenbguuzwlmjbgrlacyjhz@fisdm.se;ootstiipwujr@xkllkjja.pl;dimpcgydp@zpjoz.de;kwdjzumynenpokppopoaruu@lbnkhne.ba;jhmwxqbphcfafxwjfcltrohsju@oymslltv.ru;exixfgjaeaigqrjmzwbftlntjzwn@utp.br 129 | qekv@qwdh.se;gesbsnructafygxxcajtvqujkveu@aykkjvki.ar;hfaoeziqinfvqdcoscnhkaavwr@jmrwtbc.ba;cgtu@yyqbsd.dk;idgiptckagwx@rqkdbz.de;qekv@rqkdbz.by 130 | ffjfovboerdonvdnxu@vfs.ba;ducbtdarqqksmssqvfaksbgx@snlpoks.fi;eeseb@pljmbxgi.fi;lrfosdfcigaksjppimo@psgljl.by;tbwohrsuxltafjmpnascnfyqibcnc@njax.ca;hwpzbwqmmztnuipwdwjoypa@fisdm.br 131 | cjsfziw@gklf.pl;qvgqtygopwyarcxdboapavqx@mpqsld.cl;kmdnihdudrq@vtp.ba;dtlelfiahsqfmodjeoocul@ahn.ua;lluzfcuggqcxrpknfmjrjlvanmn@hfzcbiixt.ca;hhlkegtik@etraamocz.br 132 | jhmwxqbphcfafxwjfcltrohsju@idr.es;tggspmooeqdwcuvkacigovigguobj@rksnzvene.de;hhlkegtik@khtovn.sm;ddglswxmlrwedmdqhnagtmixzy@hhy.de;fbxdtyltydhgtgrz@wok.ua;vgxoqsitsaerdbtrxypfsfmmasqq@dckrroizm.ar 133 | rcsohozimrlilgysgfmhx@uxiaxufay.by;igqcmfts@sblev.by;kazbrkatswhzhxdqdes@hce.af;pjlgeazobqlgmysptuunyxoaodz@stsl.ua;qchdfqbkcrmlgv@tzy.ru;ymgekpeqoomhaiaieew@wok.ru 134 | eudavbkbrlazsbjlvgwlujowu@kqljjnx.uk;gdixjuapxvlutzz@aurmi.pl;zjsmptvilfcicd@oqvjjpdz.pl;hzbifkgvxovvsnrufcxp@ctxkmdn.at;ftfhtprfme@gncqfzz.cz;svlinvrffi@aqd.se 135 | jvbhzgfgmofbcppztymesrehjc@kkgisp.pl;ptepfaoxithbsmtqie@rui.pl;hebejqcxwcihtwmlhmtg@hsw.uk;kjpl@wok.at;arivbalqmzzlvrq@zelslz.cz;mqticxwmnykhlcjme@jhgadvzqi.pl 136 | diqfptyflq@mqdyseen.fi;eelgbmmhtxf@wok.es;necleossyquibvzncsrxgbbi@wok.cl;pxgoxtxebmxnx@nvvnizn.se;beppuyrbgpydmsjrmcpma@pxfyryxl.ua;nsywzgizodmpzduvloajeothmh@lfznlyuuf.se 137 | ektznvkmlyrewsgdmsvgfjzofdbkb@iic.uk;huzfmvqsirdsrcbbjqzrciygihig@wok.ru;couszrnqxzdntvmy@zrkp.de;charslmrfpugsabaahe@wok.ar;rbyoaiyvasy@ffvk.ru;zdxopiskgeomcdkgzfaxrhfgh@ead.cz 138 | skewgxcpzkkxzsufvrlzekbugtexpz@uqlsoip.pl;fdpqblfjnlmwbiwxeppq@yxh.ba;igfatfmksol@wok.sm;efxkqu@wok.cl;noadglzqqhwwvd@racholujgb.ba;xyks@mpsecu.ua 139 | jzjmfgdlpecltyqgwb@ovq.by;mnzzfbgfvvozye@nbomx.ca;ijzelphoiieworoukf@okdcqqe.br;vlzayzdetrrpesqyotmb@urowh.by;xyks@decajwyrqm.af;fghrn@wce.by 140 | xaysohuvor@tmxehoyki.ar;nyimhyutfqsncuqleopjfu@artduww.ba;jjlruxs@vdvw.se;zsxsufurbxhp@uamcdimz.cz;xapdrotdznngrkkqy@wnldx.sm;hfaoeziqinfvqdcoscnhkaavwr@zcofsryqqk.pl 141 | swvuqdgvsrullelhxwzsfjoalzgk@njqx.ru;cdnitatkllvcvycrdkdlzgvkpjan@wok.cz;jwkvlvvb@rzjchy.af;dryqtznfqwpyihxmsjpep@tcqtiqy.de;binrzwexeam@dprplrey.dk;bvjwonautdxqkx@fehj.pl 142 | gzrexzdibggs@zdsifqbav.by;jjlruxs@vdvw.se;virkwcoonpt@bqqvlphsba.at;svlinvrffi@evyroerbie.fi;binrzwexeam@qwdh.ca;qljtqfphebsdb@uqlsoip.ba 143 | kduxacwcdxrhbtxugxyr@amwr.de;mer@xyu.fi;cgtu@xgvhkyy.cz;hdesnnbomivpkzgwaboxisj@xkllkjja.se;yzcjsqjmjczvtig@jicctch.at;aqtlhvnpdr@wok.ba 144 | hebejqcxwcihtwmlhmtg@jnc.at;smyhzjmjtqjwsvvexsvghz@wok.ua;dev@kct.by;qljtqfphebsdb@uamcdimz.es;gn@pxfyryxl.sm;lucnwkqxgktpasxboavjeg@ejriqbr.ba 145 | kazbrkatswhzhxdqdes@glbgbyu.cz;otgwuladierhprivydiivtmgpfhf@xllbln.se;lzcufg@fehj.ca;bbzjrwbrgrywmlzeohnfgyjq@dyl.at;angtztykkjrfmbuietroxqgwrcswgi@jsswlq.ba;vhhocgdjnqrwvtnczuajm@wok.de 146 | hwpzbwqmmztnuipwdwjoypa@xiywylms.dk;bqkeermv@wok.af;xapdrotdznngrkkqy@xdpmsltjn.uk;lluzfcuggqcxrpknfmjrjlvanmn@hfzcbiixt.ca;isay@waws.cl;fnverpb@fszuubaeub.de 147 | fdpqblfjnlmwbiwxeppq@jqphkgj.sm;pxgoxtxebmxnx@dqclbpvzcd.ua;yhyccevbpywgeoczhuexiyipdgo@zqytlhdq.sm;ibmohbgrckbhfbk@akfkeevs.br;yeieazwlvkgyafoisnubrqjhviisdr@fehj.pl;lirvdbpdl@fszuubaeub.cz 148 | diqfptyflq@lzds.br;qjzuleyy@chf.fi;obehgoooffldthpqafcxrtziodtv@gegavijh.se;iprlgtvizpkwvuauknybo@wok.es;ckatcqvzni@xgvhkyy.cl;yzcjsqjmjczvtig@wvpzkz.cz 149 | yvgee@rdpyfq.ba;xnaazcwgpopb@ztcsrqamey.ru;tdocgfvijuzhone@etraamocz.ar;mnzzfbgfvvozye@znugaqu.cl;gyi@wok.ar;okjqrjixmcwtggriq@yyqbsd.es 150 | ourlqrmkcaaiyqcuutccxsshdsg@gtri.fi;neolemgsw@ptndv.es;kwxakssjltmxdohukslxqtdjokwvsj@dvev.ru;obehgoooffldthpqafcxrtziodtv@gepkycgh.ru;mrfwetm@boxtxvkvb.fi;eeseb@pljmbxgi.fi 151 | ncnojrzmzn@iqor.ar;vjyxcutxnxsebbtjuhov@wok.br;drvqyhxaporbqighcxtggdmw@mwaedserli.af;smyhzjmjtqjwsvvexsvghz@wok.ua;xaysohuvor@pvzfucptvp.sm;lluzfcuggqcxrpknfmjrjlvanmn@ovmnbdeh.de 152 | bnbeokroxv@etoupp.pl;qljtqfphebsdb@uqlsoip.ba;bnlgklbhnpcix@ivfov.ca;bbzjrwbrgrywmlzeohnfgyjq@uwu.ru;ddglswxmlrwedmdqhnagtmixzy@ovsg.pl;mamvfazoakjenojhaumnicofgnbm@cwu.fi 153 | svlinvrffi@imfdxc.ca;svlinvrffi@fpxyquqyog.es;binbdgfwdscazglmcczybhe@wok.ca;cja@wok.br;hcrcncwgurrjk@isntphktfl.de;hebejqcxwcihtwmlhmtg@hsw.uk 154 | ncnojrzmzn@wix.cz;cjsfziw@vtp.se;mpfn@nednhdcag.at;lirvdbpdl@fszuubaeub.cz;yjl@zyrpsryhvm.dk;ssabdgppy@ajkd.ru 155 | yhcpogihwfbk@sgjpbxkb.by;ctiyb@xple.ru;ewhbkrs@wok.sm;nnzyuaglfaajzjbslzm@artduww.fi;pjlgeazobqlgmysptuunyxoaodz@xjns.cz;zr@kdii.cl 156 | upmnkugqgfyotlkzatbwufcl@amwr.at;bnlgklbhnpcix@vibymplxdp.dk;mamvfazoakjenojhaumnicofgnbm@cwu.fi;gypyeovwuadqsgktqfgcvv@tmxehoyki.uk;qvgqtygopwyarcxdboapavqx@dunfmelzn.by;ektznvkmlyrewsgdmsvgfjzofdbkb@xzxsgf.by 157 | hebejqcxwcihtwmlhmtg@hsw.uk;xrpheyoqlaqoso@akfkeevs.cl;aqtlhvnpdr@wok.ba;xyukr@hfzcbiixt.ca;umocutdzrxuk@eduxgpfjk.ca;gsqexqbqmjkfiiejdydbatbtrtzueg@wok.ca 158 | qyzgfrifhbldwevyxjrukgvrgkxtg@wvhtos.uk;fghrn@qdjnkv.dk;diqfptyflq@qnshl.de;vhkeabt@brwvpp.uk;zjsmptvilfcicd@kext.br;hebejqcxwcihtwmlhmtg@jnc.at 159 | rdrtjnbkjbvcwibczn@vrhxpwzb.de;clfoevvmsknaqsfisgazedkz@ilef.ua;ssoqmbenhcjbrilahiavoetyonxeq@ranac.pl;lluzfcuggqcxrpknfmjrjlvanmn@ovmnbdeh.de;jwkvlvvb@cvtdmz.ar;wbffyaqzyxmxajcepmnfknehnv@dprplrey.dk 160 | bqkeermv@wok.af;gggfrbjbvxvlitszcnxdxjwr@wok.pl;hzbifkgvxovvsnrufcxp@vibymplxdp.uk;pjlgeazobqlgmysptuunyxoaodz@nvp.ca;idkmkbacsctdmdakeagluuxvqbcgb@ypqkns.se;hfaoeziqinfvqdcoscnhkaavwr@jmrwtbc.ba 161 | uzycasjamcbrgzxebmd@padodntek.cl;vgxoqsitsaerdbtrxypfsfmmasqq@ahhm.cl;fkxeoduko@imhaqt.cz;dev@kct.by;lirvdbpdl@fszuubaeub.cz;neolemgsw@bxjhuub.pl 162 | keirmlbtjfxoyfubvrgwvlgv@yspdso.ar;yjl@nby.de;nnzyuaglfaajzjbslzm@kiv.af;culgkdrhypverhc@dnzjva.ba;ansylejrmsqnxducx@ipfpln.se;tkrstlwxo@padodntek.br 163 | ufmryhwwkdfkzzpteup@tghdtl.uk;sjafr@famlu.br;gzawz@hydbrg.ba;tggspmooeqdwcuvkacigovigguobj@ksj.ar;ddglswxmlrwedmdqhnagtmixzy@pxfyryxl.es;virkwcoonpt@bqqvlphsba.at 164 | txdmjuunhlsbkgtqhchllqaqjmb@wok.ua;cgtu@cxsustaqd.br;ptepfaoxithbsmtqie@rui.pl;gn@seu.se;qllt@jnckf.by; 165 | ndynoktuabg@izghtapi.uk;ijzelphoiieworoukf@okdcqqe.br;retzhdmcoheiwhadpynrthycgzzomg@wok.ua;tggspmooeqdwcuvkacigovigguobj@nbwoy.de;mnzzfbgfvvozye@pkns.cz; 166 | xzexfhkphvhum@wok.se;xevtwccbjkhlkqhr@wok.br;eilciqwluiouuwnnjxx@yncclzsqh.ru;qmowmllbecoj@xyjurhh.de;nvbtzekumzo@akbzuiq.ba; 167 | qjzuleyy@chf.fi;dpobbznglqrypxnryxcxbfv@zqtwhscaf.sm;oej@wok.es;wbffyaqzyxmxajcepmnfknehnv@egtnadhn.se;laqxscblsyrotqz@qcrohwtuqx.ca; 168 | ijzelphoiieworoukf@okdcqqe.br;cjsfziw@rlnl.br;ufmryhwwkdfkzzpteup@ajkd.at;vtqqwiwqchegaptk@wok.dk;lrfosdfcigaksjppimo@psgljl.by; 169 | lirvdbpdl@fszuubaeub.cz;tdocgfvijuzhone@etraamocz.ar;idt@wok.at;hcrcncwgurrjk@amwr.ua;ansylejrmsqnxducx@uqlsoip.dk; 170 | hfaoeziqinfvqdcoscnhkaavwr@zcofsryqqk.pl;pxgoxtxebmxnx@cbeerpjcw.es;gyi@wok.pl;hoiionidicankeklpmohlizgtz@wok.sm;vxbclnsdrfnropisfbmshnqgqej@crtgq.ru; 171 | noadglzqqhwwvd@mqgk.uk;kkmmpzmygcrhmsykewrsleqzusvsjl@isntphktfl.ua;ejk@shsqbxtt.cz;fkxeoduko@xlwxbssr.se;dqwjjraihubn@eduxgpfjk.cz; 172 | ykejyunwxwxwftccvvyiebzlvx@wok.at;bntxuszbxorjdlehr@wezgtexd.ua;nwqzlhbpawvcsdme@nvp.uk;beppuyrbgpydmsjrmcpma@lasaq.by;gmgotzwfpmjyonczezuty@mlz.uk; 173 | mwhgcfxtyphaso@nzntf.cz;tjwztnqeuuugoiwey@yvtzngsw.by;nvbtzekumzo@ovq.by;hnwvyt@uwu.ca;gmgotzwfpmjyonczezuty@padodntek.ar; 174 | qljtqfphebsdb@uamcdimz.es;uvez@wok.se;gftvlseys@wok.se;rcsohozimrlilgysgfmhx@uxiaxufay.by;nyimhyutfqsncuqleopjfu@artduww.ba; 175 | cgtu@imfdxc.cz;vhhocgdjnqrwvtnczuajm@wok.br;ddglswxmlrwedmdqhnagtmixzy@znugaqu.sm;jwkvlvvb@mxbuysxj.pl;rajvjqgsfwts@padodntek.de; 176 | ochxmdjth@tzgaysxc.pl;vhhocgdjnqrwvtnczuajm@wok.de;zwqlj@wok.pl;pcymrkmqpka@jicctch.ca;zsxsufurbxhp@qdxcszdt.cl; 177 | psfzivhyvquwdzmkcsikphtozps@esnpuhlo.cz;iprlgtvizpkwvuauknybo@wok.pl;rbyoaiyvasy@wdv.at;lkwqnqx@wcnx.cz;gesp@vef.ba; 178 | nnzyuaglfaajzjbslzm@gvgapdzuou.pl;fbxdtyltydhgtgrz@wok.ua;briysriqlywfs@ljcwsdmb.ba;erqmjriirwuplftcvpfe@tsjy.fi;kqbvyigpsjjmqlxpjypmszjnkry@wvpzkz.de; 179 | cdxaghhtlrpcnyrknwlcw@xlb.ca;jbvhyhyafhlrpyszznre@wngy.at;lqzdoyrfjcvoehvjp@shhsendiiy.cz;lucnwkqxgktpasxboavjeg@tzgaysxc.ba;ibmohbgrckbhfbk@itonmbxdc.by; 180 | hekwckwtyqqdvarkqjomywh@wok.ru;alyrhvghozkkbvwydrjqke@hfzcbiixt.fi;nnzyuaglfaajzjbslzm@artduww.fi;jabbun@ylgiw.fi;no@imhaqt.uk; 181 | uskoknhevmcungtctmgaqwlga@hqtjcwn.cl;ihkjflydsrju@mbeeqolmp.by;xyks@mpsecu.ua;ppmitv@gozqs.pl;beppuyrbgpydmsjrmcpma@nsula.at; 182 | acslhtmpfyhxr@xple.cz;necleossyquibvzncsrxgbbi@wok.cl;xapdrotdznngrkkqy@grtdovinnr.ar;zmc@gsilzhfaj.cl;jxjyrjhnvwrxvhecbakisjp@vgasse.at; 183 | jjlruxs@vdvw.se;wwgxrxlazhltfizoy@tcqtiqy.sm;ibmohbgrckbhfbk@ibaf.cz;mrfwetm@tzy.br;oej@wok.es; 184 | kjpl@wok.at;otgwuladierhprivydiivtmgpfhf@byypso.ba;qljtqfphebsdb@uamcdimz.es;tggspmooeqdwcuvkacigovigguobj@avgzvwzgb.ar;cznenbguuzwlmjbgrlacyjhz@hydbrg.at; 185 | lirvdbpdl@hfzcbiixt.af;hzbxtzfldwtqswwcjxfsghdx@kiv.ca;jjthuprjxrnpyqghyge@jsswlq.cz;lbav@wok.cl;hzbxtzfldwtqswwcjxfsghdx@zyqzsnsy.cl; 186 | qschhcinplkyhzzafdfapmio@aadfaf.af;zsxsufurbxhp@uamcdimz.pl;dtxkeiaut@mbeeqolmp.pl;dapvedqa@easogc.at;eogspcmtokikqaugdqyty@sblev.ar; 187 | ijzelphoiieworoukf@hfzcbiixt.af;khmx@prmfgcc.ru;oajvbccwwfmxcnjjpipbbkrudukiu@zyqzsnsy.ru;ochxmdjth@bymufcfm.br;xpawqqcvot@bft.at; 188 | arivbalqmzzlvrq@zelslz.cz;iifvgnwqicqa@ccp.es;vpekviireemimtrrfflrerxqbuun@ocbek.af;kyegjmqtrbtzefqlrixy@opggeamc.ca;gqupuadngvuopvdcf@iic.ar; 189 | raifwsripgsajdwmwreoalptd@zfsgsern.ua;hwpzbwqmmztnuipwdwjoypa@fjuo.de;hfaoeziqinfvqdcoscnhkaavwr@zcofsryqqk.pl;xzexfhkphvhum@wok.se;uzycasjamcbrgzxebmd@zskzeiu.ar; 190 | vjyxcutxnxsebbtjuhov@wok.br;ymglgcuyjxzysiklojlmqmkqaq@pefowzqorc.de;qqpgoxfljuiz@wok.cl;hbrjqdkfnqyztxgzu@wvhtos.es;qschhcinplkyhzzafdfapmio@esnpuhlo.ua; 191 | azogrodldhtmmwpmqvjpfbh@aurmi.br;wotcinplbwjipactepkyk@ead.sm;vxbclnsdrfnropisfbmshnqgqej@crtgq.ru;hebejqcxwcihtwmlhmtg@hsw.uk;bbzjrwbrgrywmlzeohnfgyjq@kuw.dk; 192 | zsxsufurbxhp@qdxcszdt.cl;bntxuszbxorjdlehr@hyotztovpx.uk;vorxwrbeisxv@qogclkozc.ca;kqbvyigpsjjmqlxpjypmszjnkry@dfukk.at;ochxmdjth@bymufcfm.br; 193 | ijfydsbwpulewzljtwmmxysej@gsilzhfaj.es;kjz@tzgaysxc.pl;iaqvrnwbpdhcnkrmllmrs@crtgq.cz;yzcjsqjmjczvtig@eww.uk;kwdjzumynenpokppopoaruu@ssdgetdbys.se; 194 | fkxeoduko@hbqol.at;bnlgklbhnpcix@padodntek.uk;gmgotzwfpmjyonczezuty@shsqbxtt.pl;qktbohuzjmubjeoaliw@rgab.de;mnzzfbgfvvozye@hce.sm; 195 | bnbeokroxv@cxsustaqd.ru;nsct@hjsxjoyzma.br;ghkuqhdyueocvqgvpjzadqo@xgvhkyy.cz;pjlgeazobqlgmysptuunyxoaodz@xxgydh.ca;qjzuleyy@chf.fi; 196 | angtztykkjrfmbuietroxqgwrcswgi@cwqye.dk;ufbucsgfyxcunqdtyiiohhrht@xjns.ar;ktwqu@wok.dk;drvqyhxaporbqighcxtggdmw@ranac.ar;moo@tsjy.pl; 197 | ngjsyzgtbbfxqxpiu@decajwyrqm.at;fghrn@wce.by;jmxefxasguvjkqpxeqqocsewn@ovsg.af;oj@jwpkdhxtsd.af;necleossyquibvzncsrxgbbi@wok.cl; 198 | oadekyp@gjl.se;yowmwuzxfjrqrwwavtwh@cbeerpjcw.sm;gbyen@nhnnr.sm;ftfhtprfme@eqxvyp.cz;ruc@kdii.ua; 199 | ewhbkrs@wok.sm;jhmwxqbphcfafxwjfcltrohsju@hhjsomr.af;tphcpgynuqar@izghtapi.cl;pbbejy@tcqtiqy.cz;vgxoqsitsaerdbtrxypfsfmmasqq@lryzqaboy.de; 200 | kjpl@wok.by;vwq@ymai.cl;vjyxcutxnxsebbtjuhov@wok.cz;siyqiowghutxp@jsswlq.ua;jxjyrjhnvwrxvhecbakisjp@iqor.de; 201 | dtxkeiaut@wdn.af;lirvdbpdl@hfzcbiixt.af;tjwztnqeuuugoiwey@ejriqbr.ar;xrpheyoqlaqoso@prmfgcc.sm;kjkuidlduykdcy@rqkc.ar; 202 | ektznvkmlyrewsgdmsvgfjzofdbkb@aurmi.de;hhwefxkuzjtisixl@wok.se;ctiyb@xhcifccku.pl;mhigscufcbokllrqwymtcifrtcren@iqor.cz;ykfvxlot@arldggh.sm; 203 | uvkkmkhiaawxsrwsezpxrnqqhv@wok.es;diqfptyflq@zhh.de;ektznvkmlyrewsgdmsvgfjzofdbkb@gghtjd.ca;vorxwrbeisxv@glf.dk;idgiptckagwx@zqytlhdq.ca; 204 | gilrazoed@rpxtifwv.at;vorxwrbeisxv@idr.ar;bntxuszbxorjdlehr@ptndv.ba;binbdgfwdscazglmcczybhe@wok.ca;ddglswxmlrwedmdqhnagtmixzy@ajsbrujatf.br; 205 | tmguldpvgf@esnpuhlo.uk;sxbezdjlqp@npnpnctdp.pl;erqmjriirwuplftcvpfe@cxsustaqd.es;ruc@bqqvlphsba.sm;pdpqxlhyfxpukompamqmrcpzsf@jsadpqi.ru; 206 | ptepfaoxithbsmtqie@rui.pl;ohzzyyqehhfgznnxvgri@wok.af;thav@wok.cl;zhcpyuhd@ilef.uk;ootstiipwujr@zrkp.se; 207 | cwzjzimvxqrkcppbakngbexpoyvdeo@xcyuvy.br;;dnphc@ztcsrqamey.ar;qvgqtygopwyarcxdboapavqx@nbt.cz;zepchmlgio@uxg.cz; 208 | qktbohuzjmubjeoaliw@cwqye.uk;;diqfptyflq@gejabo.ca;vxbclnsdrfnropisfbmshnqgqej@isntphktfl.by;dtlelfiahsqfmodjeoocul@izghtapi.de; 209 | qllt@sqguj.se;;nnzyuaglfaajzjbslzm@gvgapdzuou.pl;fbxdtyltydhgtgrz@wok.ua;cja@wok.br; 210 | dtlelfiahsqfmodjeoocul@izghtapi.de;;smyhzjmjtqjwsvvexsvghz@wok.ua;qllt@xikvock.af;oajvbccwwfmxcnjjpipbbkrudukiu@zyqzsnsy.ru; 211 | ddglswxmlrwedmdqhnagtmixzy@drudal.cl;;rhvefretdphpbwrdlsscrckf@kct.pl;ruyucuoamahvsxo@wcnx.es;gesp@wezgtexd.ca; 212 | uzycasjamcbrgzxebmd@ibgaadwcco.fi;;nmctv@ksnrtaffj.br;kqbvyigpsjjmqlxpjypmszjnkry@imhaqt.ua;pjlgeazobqlgmysptuunyxoaodz@sbyubstbmc.de; 213 | khmx@qcrohwtuqx.af;;mlhcgkryeyxpzquxyrgyef@cbeerpjcw.br;gzrexzdibggs@ypqkns.fi;otgwuladierhprivydiivtmgpfhf@xllbln.se; 214 | olbefvrcd@yvyftik.af;;clqd@aqd.ar;isay@waws.cl;xaysohuvor@opggeamc.af; 215 | ochxmdjth@bymufcfm.br;;upmnkugqgfyotlkzatbwufcl@bjys.ua;qhwchoatcuuabbpvrquicgcjpnjmew@bmjbmgzaf.fi;briysriqlywfs@ljcwsdmb.ba; 216 | vtqqwiwqchegaptk@wok.dk;;xrpheyoqlaqoso@ftf.dk;binrzwexeam@sqgwvervf.cl;ctiyb@onydwy.by; 217 | dgjz@hqtjcwn.br;;smyhzjmjtqjwsvvexsvghz@wok.uk;etbvoyrwnrjewwoechtjtpxgjxt@sqczqfqdgw.es;lvezfaczqvxhljttnmttwhssawixu@qogclkozc.ba; 218 | vgxoqsitsaerdbtrxypfsfmmasqq@ahhm.cl;;cdxaghhtlrpcnyrknwlcw@gtri.fi;vlzayzdetrrpesqyotmb@vkwkzswdq.ca;xyukr@hfzcbiixt.ca; 219 | ffjfovboerdonvdnxu@rlflaoy.cz;;lucnwkqxgktpasxboavjeg@mlwyokn.ba;yeieazwlvkgyafoisnubrqjhviisdr@fehj.pl;mxpgwwdstuwnyyltdlduyslx@jwpkdhxtsd.pl; 220 | oej@wok.es;;nmctv@nvp.br;swvuqdgvsrullelhxwzsfjoalzgk@bhhpqk.at;jabbun@rpxtifwv.fi; 221 | ruc@bqqvlphsba.sm;;xrpheyoqlaqoso@wvhtos.ua;rdrtjnbkjbvcwibczn@nbt.br;vbnahxexchwrbsxfedq@pwkz.ar; 222 | obmcirwwsidsqygj@uij.ru;;dlweaokxbohveyazucsnhgalyvtvbt@lzyzihao.de;fgyhfe@xwqmhxlzov.dk;jhmwxqbphcfafxwjfcltrohsju@szmmlccbk.cl; 223 | gyi@wok.ar;;ymglgcuyjxzysiklojlmqmkqaq@bft.by;cusvqoxeqdwdllxuhkfbp@xlwxbssr.ua;uskoknhevmcungtctmgaqwlga@osaslunew.af; 224 | jxjyrjhnvwrxvhecbakisjp@opggeamc.se;;mykotvlbrihmzkocczftkv@rglvdc.af;vhhocgdjnqrwvtnczuajm@wok.de;nwqzlhbpawvcsdme@npnpnctdp.ru; 225 | ptwttqxqyljtuxqstphttzkcnpnl@nbomx.br;;pxgoxtxebmxnx@dqclbpvzcd.ua;tbowddrvbizipdslvocf@caa.by;mrfwetm@seu.de; 226 | ijztjlofqcxheoggzuv@hpydcbk.af;;gesp@qdieeqdb.fi;kkmmpzmygcrhmsykewrsleqzusvsjl@isntphktfl.ua;eeseb@pljmbxgi.fi; 227 | nyimhyutfqsncuqleopjfu@kdii.se;;hzbifkgvxovvsnrufcxp@nbeqcylup.af;ymglgcuyjxzysiklojlmqmkqaq@eww.es;ruc@bqqvlphsba.sm; 228 | vbnahxexchwrbsxfedq@sqczqfqdgw.cz;;mnzzfbgfvvozye@xple.ba;upmnkugqgfyotlkzatbwufcl@bjys.ua;fghrn@wce.by; 229 | tbkkkuaagokqg@sblev.cz;;cjsfziw@wix.ru;tphcpgynuqar@izghtapi.cl;nwqzlhbpawvcsdme@cduhqw.by; 230 | necleossyquibvzncsrxgbbi@wok.cl;;wqhxvdmqxrzqycdoipgbdsxdtoajh@jrgo.fi;xevtwccbjkhlkqhr@wok.br;bntxuszbxorjdlehr@oahrg.ua; 231 | gyi@wok.pl;;beppuyrbgpydmsjrmcpma@itonmbxdc.fi;nsywzgizodmpzduvloajeothmh@fzmj.dk;fkmvbwxbfixmsbaprbsrxnalti@snlpoks.br; 232 | wenbcploy@fehj.ca;;uvez@wok.se;kfdpoouynsfux@uynr.at;occjts@sqczqfqdgw.ru; 233 | yowmwuzxfjrqrwwavtwh@cbeerpjcw.sm;;fvugsvnawsp@pvrkpyo.dk;hypreabpousoaujurogkvu@fds.af;drvqyhxaporbqighcxtggdmw@szrndbssbr.ru; 234 | iprlgtvizpkwvuauknybo@wok.es;;kjpl@wok.at;otgwuladierhprivydiivtmgpfhf@xllbln.se;rhvefretdphpbwrdlsscrckf@cwu.pl; 235 | gzrexzdibggs@itonmbxdc.ua;;eelgbmmhtxf@wok.es;sjafr@kirsu.fi;gesbsnructafygxxcajtvqujkveu@vnizrxbq.uk; 236 | gggfrbjbvxvlitszcnxdxjwr@wok.pl;;cbbzuarcpsl@nzmkjoae.pl;xfmlliaymqbyboielimfu@nzntf.ru;vhhocgdjnqrwvtnczuajm@wok.br; 237 | zbddt@mopujgou.af;;kyegjmqtrbtzefqlrixy@utegbtw.by;iprlgtvizpkwvuauknybo@wok.pl;diqfptyflq@larbtbh.se; 238 | qqpgoxfljuiz@wok.es;;idgiptckagwx@zpjoz.ua;ndynoktuabg@izghtapi.uk;neolemgsw@drudal.dk; 239 | lucnwkqxgktpasxboavjeg@mlwyokn.ba;;xapdrotdznngrkkqy@akbzuiq.ba;sjafr@rycz.fi;noriyvhouckw@wok.by; 240 | vgxoqsitsaerdbtrxypfsfmmasqq@lryzqaboy.de;;obehgoooffldthpqafcxrtziodtv@eduxgpfjk.af;dimpcgydp@cwqye.ca;tjwztnqeuuugoiwey@ejriqbr.ar; 241 | cja@wok.br;;tggspmooeqdwcuvkacigovigguobj@hhy.ba;gbyen@avgzvwzgb.se;dvialwtuubxzwdtxob@fisdm.cz; 242 | qyzgfrifhbldwevyxjrukgvrgkxtg@qdieeqdb.af;;ochxmdjth@tzgaysxc.pl;vlzayzdetrrpesqyotmb@imhaqt.br;umocutdzrxuk@dyhxycnh.ua; 243 | dimpcgydp@qcrohwtuqx.pl;;cja@wok.sm;smyhzjmjtqjwsvvexsvghz@wok.af;ssabdgppy@mmqcyirc.br; 244 | xaysohuvor@njqx.at;;vgxoqsitsaerdbtrxypfsfmmasqq@dckrroizm.ar;azogrodldhtmmwpmqvjpfbh@vgasse.ba;dryqtznfqwpyihxmsjpep@njqx.ua; 245 | lfbqsujiwgihqoxxz@jmrwtbc.fi;;imjpcbbm@gklf.ar;dapvedqa@xbt.fi;mhigscufcbokllrqwymtcifrtcren@mpqsld.es; 246 | ansylejrmsqnxducx@ipfpln.se;;eswj@kext.ba;jwkvlvvb@ychm.fi;dimpcgydp@ffvk.cz; 247 | oadekyp@mgudgiiwld.dk;;gzawz@imhaqt.ru;ugffqfpykswaywoxwpcgefshhh@nvvnizn.se;kjz@ghyq.ca; 248 | xyks@decajwyrqm.af;;skewgxcpzkkxzsufvrlzekbugtexpz@uqlsoip.pl;dimpcgydp@fzmj.cl;kfdpoouynsfux@wngy.sm; 249 | aqtlhvnpdr@wok.ba;;zdxopiskgeomcdkgzfaxrhfgh@pymprwke.ru;pxgoxtxebmxnx@cbeerpjcw.es;cja@wok.sm; 250 | rxoopezoyczcknudru@ilgpn.ru;;uskoknhevmcungtctmgaqwlga@edlvg.se;mzgvnvodbjd@bxjhuub.cl;gmgotzwfpmjyonczezuty@bxzytaq.fi; 251 | qljtqfphebsdb@uqlsoip.ba;;noriyvhouckw@wok.at;arivbalqmzzlvrq@zelslz.cz;eogspcmtokikqaugdqyty@tcqtiqy.uk; 252 | hhlkegtik@etraamocz.br;;vtqqwiwqchegaptk@wok.ba;zmc@usiyv.ua;qzadysztazgyrmitqzual@wok.af; 253 | pdpqxlhyfxpukompamqmrcpzsf@hce.dk;;cbbzuarcpsl@irkdwhaxi.ua;qekv@qxkbzsjz.dk;ptwttqxqyljtuxqstphttzkcnpnl@osaslunew.by; 254 | xzexfhkphvhum@wok.at;;cgtu@uxbcaywh.ua;cjsfziw@qwdh.uk;uzycasjamcbrgzxebmd@mxbuysxj.cz; 255 | hoiionidicankeklpmohlizgtz@wok.sm;;uvkkmkhiaawxsrwsezpxrnqqhv@wok.es;ohzzyyqehhfgznnxvgri@wok.af;atkoamcfilsciwbmfbfkjenlr@qwdh.uk; 256 | fgyhfe@xwqmhxlzov.dk;;kjz@ghyq.ca;wenbcploy@fehj.ca;vwq@ymai.cl; 257 | lluzfcuggqcxrpknfmjrjlvanmn@waws.sm;;xevtwccbjkhlkqhr@wok.cz;zmc@dnzjva.fi;xpawqqcvot@xnqjjxshg.de; 258 | vtqqwiwqchegaptk@wok.ba;;vorxwrbeisxv@ivamk.pl;ymglgcuyjxzysiklojlmqmkqaq@sgjpbxkb.fi;zwqlj@wok.de; 259 | mlhcgkryeyxpzquxyrgyef@cbeerpjcw.br;;fghrn@qdjnkv.dk;qyzgfrifhbldwevyxjrukgvrgkxtg@jsswlq.ba;nyimhyutfqsncuqleopjfu@yczeuphxfx.de; 260 | hkqsyztvipzi@lasaq.cl;;couszrnqxzdntvmy@mbeeqolmp.br;jjthuprjxrnpyqghyge@nmmlg.es;gypyeovwuadqsgktqfgcvv@dprplrey.at; 261 | lbav@wok.cl;;vhhocgdjnqrwvtnczuajm@wok.br;oadekyp@ptndv.ru;lluzfcuggqcxrpknfmjrjlvanmn@ovmnbdeh.de; 262 | kkmmpzmygcrhmsykewrsleqzusvsjl@isntphktfl.ua;;laqxscblsyrotqz@gnpajskzb.es;wqhxvdmqxrzqycdoipgbdsxdtoajh@xzxsgf.cz;zdxopiskgeomcdkgzfaxrhfgh@ead.cz; 263 | xaysohuvor@cxsustaqd.cl;;obmcirwwsidsqygj@uij.ru;hwpzbwqmmztnuipwdwjoypa@stsl.cz;tkrstlwxo@xple.cz; 264 | ;;mrfwetm@zsbauw.dk;lfbqsujiwgihqoxxz@jmrwtbc.fi;lucnwkqxgktpasxboavjeg@tzgaysxc.ba; 265 | ;;qmowmllbecoj@xyjurhh.de;ddglswxmlrwedmdqhnagtmixzy@yncclzsqh.cz;xyks@mpsecu.ua; 266 | ;;iprlgtvizpkwvuauknybo@wok.pl;ruyucuoamahvsxo@wvpzkz.fi;dlweaokxbohveyazucsnhgalyvtvbt@isntphktfl.cl; 267 | ;;ghkuqhdyueocvqgvpjzadqo@gejabo.br;cdnitatkllvcvycrdkdlzgvkpjan@wok.cz;iprlgtvizpkwvuauknybo@wok.pl; 268 | ;;bbzjrwbrgrywmlzeohnfgyjq@uwu.ru;;vtqqwiwqchegaptk@wok.dk; 269 | ;;gzawz@mwaedserli.pl;;ctiyb@gsilzhfaj.sm; 270 | ;;;;bbzjrwbrgrywmlzeohnfgyjq@dyl.at; 271 | ;;;;lirvdbpdl@hfzcbiixt.af; 272 | ;;;;jzjmfgdlpecltyqgwb@qbsldgjpv.af; 273 | ;;;;mhigscufcbokllrqwymtcifrtcren@xlwxbssr.cz; 274 | ;;;;ftfhtprfme@qwljailo.sm; 275 | ;;;;mlhcgkryeyxpzquxyrgyef@cbeerpjcw.br; 276 | ;;;;dryqtznfqwpyihxmsjpep@easogc.pl; 277 | ;;;;dimpcgydp@olboq.af; 278 | ;;;;lluzfcuggqcxrpknfmjrjlvanmn@waws.sm; 279 | ;;;;dqwjjraihubn@qcrohwtuqx.by; 280 | ;;;;zhcpyuhd@ilef.uk; 281 | ;;;;ugffqfpykswaywoxwpcgefshhh@nvvnizn.se; 282 | ;;;;clfoevvmsknaqsfisgazedkz@ilef.ua; 283 | ;;;;ujwgmdnulhhytdybxdinabb@kcf.br; 284 | ;;;;dqwjjraihubn@yhaku.se; 285 | ;;;;hkqsyztvipzi@eww.at; 286 | ;;;;skewgxcpzkkxzsufvrlzekbugtexpz@uqlsoip.pl; 287 | ;;;;ptwttqxqyljtuxqstphttzkcnpnl@uynr.dk; 288 | ;;;;smyhzjmjtqjwsvvexsvghz@wok.af; 289 | ;;;;raifwsripgsajdwmwreoalptd@xnnnp.uk; 290 | ;;;;clqd@hpydcbk.de; 291 | ;;;;gesp@yyqbsd.cl; 292 | ;;;;zepchmlgio@tsjy.se; 293 | ;;;;lfbqsujiwgihqoxxz@jmrwtbc.fi; 294 | -------------------------------------------------------------------------------- /warsztat_4/copy_p4b_logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaftAcademy/python4beginners/f108ae9c8ebcd94214b57c0f4a5479f36ce59a11/warsztat_4/copy_p4b_logo.bmp -------------------------------------------------------------------------------- /warsztat_4/multiline_file.txt: -------------------------------------------------------------------------------- 1 | Nowa linia 1 2 | Nowa linia 2 3 | Nowa linia 3 4 | Nowa linia 4 5 | APPEND Nowa linia 6 | -------------------------------------------------------------------------------- /warsztat_4/p4b_logo.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DaftAcademy/python4beginners/f108ae9c8ebcd94214b57c0f4a5479f36ce59a11/warsztat_4/p4b_logo.bmp -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/odpowiedzi.csv: -------------------------------------------------------------------------------- 1 | Odpowiedź 2 | A 3 | C 4 | D 5 | D 6 | D 7 | B 8 | C 9 | A 10 | -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/pytania.csv: -------------------------------------------------------------------------------- 1 | Państwo;A;B;C;D 2 | Szwecja;Sztokholm;Zagrzeb;Rejkiawik;Watykan 3 | Islandia;Rejkiawik;Ankara;Wilno;Watykan 4 | Malta;Nikozja;Valletta;Belgrad;Mińsk 5 | Norwegia;Tirana;Amsterdam;Ankara;Oslo 6 | Polska;Budapeszt;Lizbona;Bratysława;Warszawa 7 | Belgia;Bruksela;Londyn;Kiszyniów;Lizbona 8 | Dania;Luksemburg;Sofia;Kopenhaga;Sarajewo 9 | San Marino;San Marino;Lizbona;Podgorica;Rzym 10 | -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/stolice.csv: -------------------------------------------------------------------------------- 1 | Państwo;Stolica 2 | Albania;Tirana 3 | Andora;Andora 4 | Austria;Wiedeń 5 | Belgia;Bruksela 6 | Białoruś;Mińsk 7 | Bośnia i Hercegowina;Sarajewo 8 | Bułgaria;Sofia 9 | Chorwacja;Zagrzeb 10 | Cypr;Nikozja 11 | Czarnogóra;Podgorica 12 | Czechy;Praga 13 | Dania;Kopenhaga 14 | Estonia;Tallin 15 | Finlandia;Helsinki 16 | Francja;Paryż 17 | Grecja;Ateny 18 | Gruzja;Tbilisi 19 | Hiszpania;Madryt 20 | Holandia;Amsterdam 21 | Irlandia;Dublin 22 | Islandia;Rejkiawik 23 | Kazachstan;Ałma-Ata 24 | Kosowo;Prisztina 25 | Lichtenstein;Vaduz 26 | Litwa;Wilno 27 | Luksemburg;Luksemburg 28 | Łotwa;Ryga 29 | Macedonia;Skopie 30 | Malta;Valletta 31 | Mołdawia;Kiszyniów 32 | Monako;Monako 33 | Niemcy;Berlin 34 | Norwegia;Oslo 35 | Polska;Warszawa 36 | Portugalia;Lizbona 37 | Rosja;Moskwa 38 | Rumunia;Bukareszt 39 | San Marino;San Marino 40 | Serbia;Belgrad 41 | Słowacja;Bratysława 42 | Słowenia;Lublana 43 | Szwecja;Sztokholm 44 | Turcja;Ankara 45 | Ukraina;Kijów 46 | Watykan;Watykan 47 | Węgry;Budapeszt 48 | Wielka Brytania;Londyn 49 | Włochy;Rzym 50 | -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/zadanie1.py: -------------------------------------------------------------------------------- 1 | # Zaimplementuj klasę Date, która tworzona jest na podstawie trzech wartości - day, month i year. 2 | # Obiekt klasy powinien zawierać atrybuty day, month i year 3 | 4 | # Twoim zadaniem jest sprawdzenie w trakcie tworzenia obiektu, czy podane wartości są poprawne: 5 | # jeśli year nie jest intem - rzucić InvalidYearError 6 | # jeśli month nie jest intem lub nie zawiera się w przedziale od 1 do 12 - rzucić InvalidMonthError 7 | # jeśli day nie jest intem lub nie zawiera się w przedziale o 1 do 28/30/31 (odpowiednio w zależności od miesiąca) - rzucić InvalidDayError 8 | 9 | # Wszystkie opisane powyżej błędy powinny dziedziczyć z bazowego błędu - DateError 10 | 11 | # W zadaniu dla uproszczenia zakładamy, że każdy luty ma 28 dni ;) 12 | 13 | class Date: 14 | def __init__(self, day, month, year): 15 | # Tu wpisz swoje rozwiązanie (i skasuj raise NotImplementedError() :) 16 | raise NotImplementedError() 17 | 18 | 19 | date = Date(30, 5, 2020) 20 | assert date.day == 30 21 | assert date.month == 5 22 | assert date.year == 2020 23 | 24 | try: 25 | date2 = Date(40, 5, 2020) 26 | except InvalidDayError: 27 | print('Błąd wyrzucony tak jak trzeba') 28 | else: 29 | print('Bez błędu, a trzeba było :(') 30 | -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/zadanie2.py: -------------------------------------------------------------------------------- 1 | # Chcemy napisać sprawdzarkę do testu znajomości stolic europejskich. 2 | # Format listy stolic taki jak w pliku stolice.csv 3 | # Format pytań taki jak w pliku pytania.csv 4 | # Format odpowiedzi taki jak w pliku odpowiedzi.csv 5 | 6 | # Napisz funkcję check_homework, która przyjmuje trzy argumenty: 7 | # - capitals_csv to ścieżka do pliku, który zawiera listę stolic europejskich 8 | # - questions_csv to ścieżka pliku csv, który zawiera pytania 9 | # - answers_csv to ścieżka pliku, który zawiera odpowiedzi 10 | # Funkcja zwraca liczbę poprawnych odpowiedzi 11 | 12 | def check_homework(capitals_csv, questions_csv, answers_csv): 13 | # Tu wpisz swoje rozwiązanie (i skasuj raise NotImplementedError() :) 14 | raise NotImplementedError() 15 | 16 | assert check_homework('stolice.csv', 'pytania.csv', 'odpowiedzi.csv') == 5 17 | -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/zadanie3.py: -------------------------------------------------------------------------------- 1 | import csv 2 | 3 | # Chcemy napisać kod, który dla danego pliku z listą stolic wygeneruje number_of_sets zestawów pytań po number_of_questions_per_set pytań 4 | # - Format listy stolic taki jak w stolice.csv 5 | # - Format oczekiwanego pojedynczego zestawu pytań taki jak w pliku pytania.csv - prosimy pamiętać o nagłówkach 6 | # - Każdy zestaw powinien znaleźć się w osobnym pliku - pierwszy w zestaw1.csv, drugi w zestaw2.csv itd (nie ma czegoś takiego jak zestaw 0) 7 | # - pliki zestaw1.csv, zestaw2.csv itd. powinny się stworzyć w folderze z rozwiązaniem zadania (tzn. przy otwieraniu pliku nie podawać żadnej ścieżki, tylko samą nazwę pliku) 8 | # 9 | # Dodatkowe założenia: 10 | # Pytanie o jeden kraj nie może wystąpić więcej niż raz (biorąc pod uwagę wszystkie zestawy) 11 | # W przypadku, gdy ktoś poda nam dane, dla których musielibyśmy wygenerować więcej niż 48 pytań (tyle mamy stolic w pliku stolice.csv) - rzućmy ValueError 12 | # Poprawna odpowiedź powinna znajdować się w losowej kolumnie - tzn. losowo powinna być odpowiedzią A, B, C lub D 13 | # Do losowania należy skorzystać z modułu random https://docs.python.org/3/library/random.html 14 | 15 | 16 | def create_sets_of_question(capitals_csv, number_of_sets, number_of_questions_per_set): 17 | # Tu wpisz swoje rozwiązanie (i skasuj raise NotImplementedError() :) 18 | raise NotImplementedError() 19 | 20 | 21 | create_sets_of_question('stolice.csv', 1, 8) 22 | 23 | 24 | with open('zestaw1.csv') as zestaw1: 25 | reader = csv.reader(zestaw1, delimiter=';') 26 | lines_count = 0 27 | for row in reader: 28 | print(row) 29 | assert len(row) == 5 # 5 kolumn - Państwo + propozycje odpowiedzi A, B, C, D 30 | lines_count += 1 31 | assert lines_count == 9 # 8 pytan + naglowek 32 | 33 | 34 | try: 35 | create_sets_of_question('stolice.csv', 5, 10) 36 | except ValueError: 37 | print('Błąd wyrzucony tak jak trzeba') 38 | else: 39 | print('Bez błędu, a trzeba było :(') 40 | -------------------------------------------------------------------------------- /warsztat_4/praca_domowa/zadanie_4.py: -------------------------------------------------------------------------------- 1 | # Napisać klasę Picture(red, green, blue, width, height). 2 | # Argumenty red, green i blue mogą być dowolnymi obiektami po których można iterować (np. listami, tuplami) 3 | # red, green, blue będą tej samej długości. 4 | # Każdy element red, green, blue będzie miał wartość liczby całkowitej z przedziału 0 - 255 włącznie. 5 | # dodatkowe informacje: https://en.wikipedia.org/wiki/RGB_color_model 6 | # Każdy element obiektów red, green, blue reprezentuje wartość konkretnego koloru dla danego piksela. 7 | # Piksele są podane są w kolejności od lewej do prawej, od górnego do dolnego wiersza. 8 | 9 | # Instancje klasy Picture mają mieć publicznie dostępne metody: 10 | # red() 11 | # green() 12 | # blue() 13 | # size() 14 | # crop(x, y, width, height) 15 | # pixel(x, y) 16 | 17 | # red() 18 | # ma zwrócić tuplę, wartości kanału czerwonego w kolejności wierszami od lewego górnego do prawego dolnego 19 | 20 | # green() 21 | # to samo co red ale dla kanału zielonego w kolejności wierszami od lewego górnego do prawego dolnego 22 | 23 | # blue() 24 | # to samo co red i green ale dla kanału niebieskiego w kolejności wierszami od lewego górnego do prawego dolnego 25 | 26 | # size() 27 | # ma zwrócić tuplę z szerokością i wysokością obrazka (ile pixeli mieści się wzdłuż i wszerz) 28 | 29 | # crop(x, y, width, height) 30 | # ma obciąć obrazek ("w miejscu") do prostokąta podanego w argumentach . 31 | # x, y - lewy górny róg prostokąta (na pewno mieści się w obrazku) 32 | # width, height - szerokość i wysokość prostokąta (mogą wyjść poza obrazek) 33 | # jeśli prostokąt będzie wystawał poza obrazek to istotna jest tylko część wspólna obecnego obrazka i prostokąta. 34 | 35 | # pixel(x, y) 36 | # ma zwrócić tuplę wartości poszczególnych kolorów w pikselu o współrzędnych x, y. 37 | # Kolejność kanałów w wynikowej tupli to RGB. 38 | # np. dla obrazka o size = (10, 21) współrzędne 39 | # 0, 0 → lewy górny róg 40 | # 0, 20 → prawy górny róg 41 | # 9, 0 → lewy dolny róg 42 | # 9, 20 → prawy dolny róg 43 | # na potrzeby tego zadania proszę założyć, że wszystkie współrzędne x, y będą się zawierać w obrazku 44 | 45 | def test_one_red_pixel(): 46 | red = [255] 47 | green = [0] 48 | blue = [0] 49 | width = 1 50 | height = 1 51 | obrazek = Picture(red=red, green=green, blue=blue, width=width, height=height) 52 | assert (1, 1) == obrazek.size() 53 | assert (255, ) == obrazek.red() 54 | assert (0, ) == obrazek.green() 55 | assert (0, ) == obrazek.blue() 56 | assert (255, 0, 0) == obrazek.pixel(0, 0) 57 | 58 | def test_kwadrat_gradient(): 59 | obrazek = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 60 | assert (16, 16) == obrazek.size() 61 | val = 0 62 | for y in range(16): 63 | for x in range(16): 64 | assert (val, val, val) == obrazek.pixel(x, y) 65 | val += 1 66 | 67 | # Same picture 68 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 69 | obrazek_2.crop(0, 0, 16, 16) # powinniśmy dostać ten sam obrazek 70 | assert obrazek.red() == obrazek_2.red() 71 | assert obrazek.green() == obrazek_2.green() 72 | assert obrazek.blue() == obrazek_2.blue() 73 | 74 | # Left upper corner 75 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 76 | obrazek_2.crop(0, 0, 1, 1) 77 | assert (0, ) == obrazek_2.red() 78 | assert (0, ) == obrazek_2.green() 79 | assert (0, ) == obrazek_2.blue() 80 | 81 | # right upper corner 82 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 83 | obrazek_2.crop(15, 0, 1, 1) 84 | assert (15, ) == obrazek_2.red() 85 | assert (15, ) == obrazek_2.green() 86 | assert (15, ) == obrazek_2.blue() 87 | 88 | # right lower corner 89 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 90 | obrazek_2.crop(15, 15, 1, 1) 91 | assert (255, ) == obrazek_2.red() 92 | assert (255, ) == obrazek_2.green() 93 | assert (255, ) == obrazek_2.blue() 94 | 95 | # left lower corner 96 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 97 | obrazek_2.crop(0, 15, 1, 1) 98 | assert (240, ) == obrazek_2.red() 99 | assert (240, ) == obrazek_2.green() 100 | assert (240, ) == obrazek_2.blue() 101 | 102 | # 2x3 near lower corner 103 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 104 | obrazek_2.crop(1, 12, 2, 3) 105 | assert (193, 194, 209, 210, 225, 226) == obrazek_2.red() 106 | assert (193, 194, 209, 210, 225, 226) == obrazek_2.green() 107 | assert (193, 194, 209, 210, 225, 226) == obrazek_2.blue() 108 | 109 | # 10x15 wystający → 3x5 lower right corner 110 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 111 | obrazek_2.crop(13, 11, 10, 15) 112 | assert (189, 190, 191, 205, 206, 207, 221, 222, 223, 237, 238, 239, 253, 254, 255) == obrazek_2.red() 113 | assert (189, 190, 191, 205, 206, 207, 221, 222, 223, 237, 238, 239, 253, 254, 255) == obrazek_2.green() 114 | assert (189, 190, 191, 205, 206, 207, 221, 222, 223, 237, 238, 239, 253, 254, 255) == obrazek_2.blue() 115 | 116 | if __name__ == '__main__': 117 | test_one_red_pixel() 118 | test_kwadrat_gradient() 119 | -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/odpowiedzi.csv: -------------------------------------------------------------------------------- 1 | Odpowiedź 2 | A 3 | C 4 | D 5 | D 6 | D 7 | B 8 | C 9 | A 10 | -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/pytania.csv: -------------------------------------------------------------------------------- 1 | Państwo;A;B;C;D 2 | Szwecja;Sztokholm;Zagrzeb;Rejkiawik;Watykan 3 | Islandia;Rejkiawik;Ankara;Wilno;Watykan 4 | Malta;Nikozja;Valletta;Belgrad;Mińsk 5 | Norwegia;Tirana;Amsterdam;Ankara;Oslo 6 | Polska;Budapeszt;Lizbona;Bratysława;Warszawa 7 | Belgia;Bruksela;Londyn;Kiszyniów;Lizbona 8 | Dania;Luksemburg;Sofia;Kopenhaga;Sarajewo 9 | San Marino;San Marino;Lizbona;Podgorica;Rzym 10 | -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/stolice.csv: -------------------------------------------------------------------------------- 1 | Państwo;Stolica 2 | Albania;Tirana 3 | Andora;Andora 4 | Austria;Wiedeń 5 | Belgia;Bruksela 6 | Białoruś;Mińsk 7 | Bośnia i Hercegowina;Sarajewo 8 | Bułgaria;Sofia 9 | Chorwacja;Zagrzeb 10 | Cypr;Nikozja 11 | Czarnogóra;Podgorica 12 | Czechy;Praga 13 | Dania;Kopenhaga 14 | Estonia;Tallin 15 | Finlandia;Helsinki 16 | Francja;Paryż 17 | Grecja;Ateny 18 | Gruzja;Tbilisi 19 | Hiszpania;Madryt 20 | Holandia;Amsterdam 21 | Irlandia;Dublin 22 | Islandia;Rejkiawik 23 | Kazachstan;Ałma-Ata 24 | Kosowo;Prisztina 25 | Lichtenstein;Vaduz 26 | Litwa;Wilno 27 | Luksemburg;Luksemburg 28 | Łotwa;Ryga 29 | Macedonia;Skopie 30 | Malta;Valletta 31 | Mołdawia;Kiszyniów 32 | Monako;Monako 33 | Niemcy;Berlin 34 | Norwegia;Oslo 35 | Polska;Warszawa 36 | Portugalia;Lizbona 37 | Rosja;Moskwa 38 | Rumunia;Bukareszt 39 | San Marino;San Marino 40 | Serbia;Belgrad 41 | Słowacja;Bratysława 42 | Słowenia;Lublana 43 | Szwecja;Sztokholm 44 | Turcja;Ankara 45 | Ukraina;Kijów 46 | Watykan;Watykan 47 | Węgry;Budapeszt 48 | Wielka Brytania;Londyn 49 | Włochy;Rzym 50 | -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/zadanie1.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Zaimplementuj klasę Date, która tworzona jest na podstawie trzech wartości - day, month i year. 5 | # Obiekt klasy powinien zawierać atrybuty day, month i year 6 | 7 | # Twoim zadaniem jest sprawdzenie w trakcie tworzenia obiektu, czy podane wartości są poprawne: 8 | # jeśli year nie jest intem - rzucić InvalidYearError 9 | # jeśli month nie jest intem lub nie zawiera się w przedziale od 1 do 12 - rzucić InvalidMonthError 10 | # jeśli day nie jest intem lub nie zawiera się w przedziale o 1 do 28/30/31 (odpowiednio w zależności od miesiąca) - rzucić InvalidDayError 11 | 12 | # Wszystkie opisane powyżej błędy powinny dziedziczyć z bazowego błędu - DateError 13 | 14 | # W zadaniu dla uproszczenia zakładamy, że każdy luty ma 28 dni ;) 15 | 16 | class DateError: 17 | pass 18 | 19 | 20 | class InvalidYearError(DateError): 21 | pass 22 | 23 | 24 | class InvalidMonthError(DateError): 25 | pass 26 | 27 | 28 | class InvalidDayError(DateError): 29 | pass 30 | 31 | 32 | class Date: 33 | MONTH_DAYS = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6: 30, 34 | 7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31} 35 | 36 | def __init__(self, day, month, year): 37 | if type(year) is not int: 38 | raise InvalidYearError 39 | if type(month) is not int or not 1 <= month <= 12: 40 | raise InvalidMonthError 41 | if type(day) is not int or not 1 <= day <= self.MONTH_DAYS[month]: 42 | raise InvalidDayError 43 | 44 | self.year = year 45 | self.month = month 46 | self.day = day 47 | 48 | 49 | 50 | def has_date_error(attribute, module, attr_name): 51 | assert 'DateError' in dir(module) 52 | 53 | 54 | def has_invalid_day_error(attribute, module, attr_name): 55 | assert 'InvalidDayError' in dir(module) 56 | 57 | 58 | def invalid_day_error_bases_on_date_error(attribute, module, attr_name): 59 | assert issubclass(module.InvalidDayError, module.DateError) 60 | 61 | 62 | def has_invalid_month_error(attribute, module, attr_name): 63 | assert 'InvalidMonthError' in dir(module) 64 | 65 | 66 | def invalid_month_bases_on_date_error(attribute, module, attr_name): 67 | assert issubclass(module.InvalidMonthError, module.DateError) 68 | 69 | 70 | def has_invalid_year_error(attribute, module, attr_name): 71 | assert 'InvalidYearError' in dir(module) 72 | 73 | 74 | def invalid_year_error_bases_on_date_error(attribute, module, attr_name): 75 | assert issubclass(module.InvalidYearError, module.DateError) 76 | 77 | 78 | def test_basic_usage(attribute, module, attr_name): 79 | date = attribute(30, 5, 2020) 80 | assert date.day == 30 81 | assert date.month == 5 82 | assert date.year == 2020 83 | 84 | 85 | def test_check_day(attribute, module, attr_name): 86 | try: 87 | attribute(40, 5, 2020) 88 | except module.InvalidDayError: 89 | pass 90 | else: 91 | assert False 92 | 93 | 94 | def test_check_month(attribute, module, attr_name): 95 | try: 96 | attribute(21, 13, 2020) 97 | except module.InvalidMonthError: 98 | pass 99 | else: 100 | assert False 101 | 102 | 103 | def test_check_year(attribute, module, attr_name): 104 | try: 105 | attribute(40, 5, 'hello') 106 | except module.InvalidYearError: 107 | pass 108 | else: 109 | assert False 110 | 111 | 112 | assignment = Assignment( 113 | 'zadanie1', 114 | 'zadanie1.py', 115 | 'Date', 116 | (has_date_error, has_invalid_year_error, has_invalid_month_error, has_invalid_day_error, 117 | invalid_year_error_bases_on_date_error, invalid_month_bases_on_date_error, 118 | invalid_day_error_bases_on_date_error, test_basic_usage, test_check_year, test_check_month, 119 | test_check_day) 120 | ) 121 | -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/zadanie2.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import tempfile 4 | from functools import wraps 5 | 6 | from homework_checker.base import Assignment 7 | 8 | # # Chcemy napisać sprawdzarkę do testu znajomości stolic europejskich. 9 | # # Format listy stolic taki jak w pliku stolice.csv 10 | # # Format pytań taki jak w pliku pytania.csv 11 | # # Format odpowiedzi taki jak w pliku odpowiedzi.csv 12 | # 13 | # # Napisz funkcję check_homework, która przyjmuje trzy argumenty: 14 | # # - capitals_csv to ścieżka do pliku, który zawiera listę stolic europejskich 15 | # # - questions_csv to ścieżka pliku csv, który zawiera pytania 16 | # # - answers_csv to ścieżka pliku, który zawiera odpowiedzi 17 | # # Funkcja zwraca liczbę poprawnych odpowiedzi 18 | # 19 | # def check_homework(capitals_csv, questions_csv, answers_csv): 20 | # # Tu wpisz swoje rozwiązanie (i skasuj raise NotImplementedError() :) 21 | # raise NotImplementedError() 22 | # 23 | # assert check_homework('stolice.csv', 'pytania.csv', 'odpowiedzi.csv') == 5 24 | # 25 | import csv 26 | 27 | def check_homework(capitals_file_name, questions_file_name, answers_file_name): 28 | 29 | capitals_data = {} 30 | with open('stolice.csv', 'r') as capitals: 31 | reader = csv.reader(capitals, delimiter=';') 32 | next(reader) 33 | for row in reader: 34 | country, capital = row 35 | capitals_data[country] = capital 36 | 37 | good_answers = [] 38 | with open('pytania.csv', 'r') as questions: 39 | reader = csv.reader(questions, delimiter=';') 40 | next(reader) 41 | for row in reader: 42 | country, a, b, c, d = row 43 | if capitals_data[country] == a: 44 | good_answers.append('A') 45 | elif capitals_data[country] == b: 46 | good_answers.append('B') 47 | elif capitals_data[country] == c: 48 | good_answers.append('C') 49 | elif capitals_data[country] == d: 50 | good_answers.append('D') 51 | 52 | points = 0 53 | with open('odpowiedzi.csv', 'r') as answers_file: 54 | reader = csv.reader(answers_file, delimiter=';') 55 | next(reader) 56 | for idx, row in enumerate(reader): 57 | answer = row[0] 58 | if answer == good_answers[idx]: 59 | points += 1 60 | 61 | return points 62 | 63 | 64 | def run_in_clean_directory(src): 65 | 66 | def decorator(func): 67 | 68 | @wraps(func) 69 | def wrapper(*args, **kwargs): 70 | cwd = os.getcwd() 71 | with tempfile.TemporaryDirectory() as tmpdirname: 72 | src_files = os.listdir(src) 73 | for file_name in src_files: 74 | full_file_name = os.path.join(src, file_name) 75 | if (os.path.isfile(full_file_name)): 76 | shutil.copy(full_file_name, tmpdirname) 77 | try: 78 | os.chdir(tmpdirname) 79 | func(*args, **kwargs) 80 | finally: 81 | os.chdir(cwd) 82 | 83 | return wrapper 84 | 85 | return decorator 86 | 87 | 88 | @run_in_clean_directory('../homework4/2a') 89 | def test_basic(func, module, attr_name): 90 | assert 5 == func('stolice.csv', 'pytania.csv', 'odpowiedzi.csv') 91 | 92 | @run_in_clean_directory('../homework4/2b') 93 | def test_basic_2(func, module, attr_name): 94 | assert 4 == func('stolice.csv', 'pytania.csv', 'odpowiedzi.csv') 95 | 96 | @run_in_clean_directory('../homework4/2c') 97 | def test_everyting_bad(func, module, attr_name): 98 | assert 0 == func('stolice.csv', 'pytania.csv', 'odpowiedzi.csv') 99 | 100 | assignment = Assignment('zadanie2', 'zadanie2.py', 'check_homework', (test_basic, test_basic_2, 101 | test_everyting_bad)) 102 | -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/zadanie3.py: -------------------------------------------------------------------------------- 1 | import csv 2 | import random 3 | 4 | def create_sets_of_question(capitals_csv, number_of_sets, number_of_questions_per_set): 5 | # Read capitals dict 6 | capitals = {} 7 | with open(capitals_csv, encoding='utf-8') as csvfile: 8 | reader = csv.reader(csvfile, delimiter=';') 9 | next(reader) 10 | for row in reader: 11 | capitals[row[0]] = row[1] 12 | 13 | # Check no country will be repeated. 14 | if number_of_sets * number_of_questions_per_set > len(capitals): 15 | raise ValueError 16 | 17 | # Start with all capitals available. 18 | available_countries = list(capitals.keys()) 19 | 20 | # Create `number_of_sets` files. 21 | for questin_set_number in range(1, number_of_sets + 1): 22 | 23 | # Open specific file for writing, eq. `zestaw1.csv` 24 | with open(f'zestaw{questin_set_number}.csv', 'w') as csvfile: 25 | 26 | # Start-up csv writer, by opening it and writing heading line. 27 | writer = csv.writer(csvfile, delimiter=';') 28 | writer.writerow(('Państwo','A','B','C','D')) 29 | 30 | # We need `number_of_questions_per_set` questions. 31 | for _ in range(number_of_questions_per_set): 32 | 33 | # Chose country from the list of available countries. 34 | current_country = random.choice(available_countries) 35 | available_countries.remove(current_country) 36 | 37 | # Take current country capital as a first answer. 38 | answers = [capitals[current_country]] 39 | 40 | # Extend the answers list by chosing 3 other cities. 41 | answers.extend( 42 | random.sample( 43 | # Remember to omit current capital, as it is already in the answers list 44 | [capital for country, capital in capitals.items() 45 | if country != current_country], 46 | 3 47 | ) 48 | ) 49 | 50 | # Shuffle answers. 51 | random.shuffle(answers) 52 | 53 | # Output the data to resulting csv file. 54 | writer.writerow((current_country, *answers)) 55 | 56 | if '__main__' == __name__: 57 | create_sets_of_question('stolice.csv', 1, 48) -------------------------------------------------------------------------------- /warsztat_4/rozwiazania/zadanie4.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | class Picture(): 4 | def __init__(self, red, green, blue, width, height): 5 | self.r = list(red) # tworzymy nową listę, żeby się uniezależnić od przyszłych zmian w rgb poza naszą klasą 6 | self.g = list(green) 7 | self.b = list(blue) 8 | self.w = width 9 | self.h = height 10 | 11 | def red(self): 12 | return tuple(self.r) 13 | 14 | def green(self): 15 | return tuple(self.g) 16 | 17 | def blue(self): 18 | return tuple(self.b) 19 | 20 | def size(self): 21 | return self.w, self.h 22 | 23 | def pixel(self, x, y): 24 | pixel_index = self._get_pixel_index(x, y) 25 | r = self.r[pixel_index] 26 | g = self.g[pixel_index] 27 | b = self.b[pixel_index] 28 | return r, g, b 29 | 30 | def _get_pixel_index(self, x, y): 31 | return x + y * self.w 32 | 33 | def crop(self, x, y, width, height): 34 | new_r = [] 35 | new_b = [] 36 | new_g = [] 37 | width = min(width, self.w - x) 38 | height = min(height, self.h - y) 39 | for i in range(height): 40 | start_idx = self._get_pixel_index(x, y + i) 41 | end_idx = self._get_pixel_index(x + width, y + i) 42 | new_r.extend(self.r[start_idx:end_idx]) 43 | new_g.extend(self.g[start_idx:end_idx]) 44 | new_b.extend(self.b[start_idx:end_idx]) 45 | self.r = new_r 46 | self.g = new_g 47 | self.b = new_b 48 | self.w = width 49 | self.h = height 50 | 51 | 52 | def test_one_red_pixel(): 53 | red = [255] 54 | green = [0] 55 | blue = [0] 56 | width = 1 57 | height = 1 58 | obrazek = Picture(red=red, green=green, blue=blue, width=width, height=height) 59 | assert (1, 1) == obrazek.size() 60 | assert (255,) == obrazek.red() 61 | assert (0,) == obrazek.green() 62 | assert (0,) == obrazek.blue() 63 | assert (255, 0, 0) == obrazek.pixel(0, 0) 64 | 65 | 66 | def test_kwadrat_gradient(): 67 | obrazek = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 68 | assert (16, 16) == obrazek.size() 69 | val = 0 70 | for y in range(16): 71 | for x in range(16): 72 | assert (val, val, val) == obrazek.pixel(x, y) 73 | val += 1 74 | 75 | # Same picture 76 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 77 | obrazek_2.crop(0, 0, 16, 16) # powinniśmy dostac ten sam obrazek 78 | assert obrazek.red() == obrazek_2.red() 79 | assert obrazek.green() == obrazek_2.green() 80 | assert obrazek.blue() == obrazek_2.blue() 81 | 82 | # Left upper corner 83 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 84 | obrazek_2.crop(0, 0, 1, 1) 85 | assert (0,) == obrazek_2.red() 86 | assert (0,) == obrazek_2.green() 87 | assert (0,) == obrazek_2.blue() 88 | 89 | # right upper corner 90 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 91 | obrazek_2.crop(15, 0, 1, 1) 92 | assert (15,) == obrazek_2.red() 93 | assert (15,) == obrazek_2.green() 94 | assert (15,) == obrazek_2.blue() 95 | 96 | # right lower corner 97 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 98 | obrazek_2.crop(15, 15, 1, 1) 99 | assert (255,) == obrazek_2.red() 100 | assert (255,) == obrazek_2.green() 101 | assert (255,) == obrazek_2.blue() 102 | 103 | # left lower corner 104 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 105 | obrazek_2.crop(0, 15, 1, 1) 106 | assert (240,) == obrazek_2.red() 107 | assert (240,) == obrazek_2.green() 108 | assert (240,) == obrazek_2.blue() 109 | 110 | # 2x3 near lower corner 111 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 112 | obrazek_2.crop(1, 12, 2, 3) 113 | assert (193, 194, 209, 210, 225, 226) == obrazek_2.red() 114 | assert (193, 194, 209, 210, 225, 226) == obrazek_2.green() 115 | assert (193, 194, 209, 210, 225, 226) == obrazek_2.blue() 116 | 117 | # 10x15 wystający → 3x5 lower right corner 118 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=16, height=16) 119 | obrazek_2.crop(13, 11, 10, 15) 120 | assert (189, 190, 191, 205, 206, 207, 221, 222, 223, 237, 238, 239, 253, 254, 121 | 255) == obrazek_2.red() 122 | assert (189, 190, 191, 205, 206, 207, 221, 222, 223, 237, 238, 239, 253, 254, 123 | 255) == obrazek_2.green() 124 | assert (189, 190, 191, 205, 206, 207, 221, 222, 223, 237, 238, 239, 253, 254, 125 | 255) == obrazek_2.blue() 126 | 127 | 128 | def test_prostokat_gradient(): 129 | obrazek = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 130 | assert (64, 4) == obrazek.size() 131 | val = 0 132 | for y in range(4): 133 | for x in range(64): 134 | assert (val, val, val) == obrazek.pixel(x, y) 135 | val += 1 136 | 137 | # Same picture 138 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 139 | obrazek_2.crop(0, 0, 64, 4) # powinniśmy dostac ten sam obrazek 140 | assert obrazek.red() == obrazek_2.red() 141 | assert obrazek.green() == obrazek_2.green() 142 | assert obrazek.blue() == obrazek_2.blue() 143 | 144 | # Left upper corner 145 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 146 | obrazek_2.crop(0, 0, 1, 1) 147 | assert (0,) == obrazek_2.red() 148 | assert (0,) == obrazek_2.green() 149 | assert (0,) == obrazek_2.blue() 150 | 151 | # right upper corner 152 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 153 | obrazek_2.crop(63, 0, 1, 1) 154 | assert (63,) == obrazek_2.red() 155 | assert (63,) == obrazek_2.green() 156 | assert (63,) == obrazek_2.blue() 157 | 158 | # right lower corner 159 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 160 | obrazek_2.crop(63, 3, 1, 1) 161 | assert (255,) == obrazek_2.red() 162 | assert (255,) == obrazek_2.green() 163 | assert (255,) == obrazek_2.blue() 164 | 165 | # left lower corner 166 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 167 | obrazek_2.crop(0, 3, 1, 1) 168 | assert (192,) == obrazek_2.red() 169 | assert (192,) == obrazek_2.green() 170 | assert (192,) == obrazek_2.blue() 171 | 172 | # 2x3 near lower corner 173 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 174 | obrazek_2.crop(1, 1, 2, 3) 175 | assert (65, 66, 129, 130, 193, 194) == obrazek_2.red() 176 | assert (65, 66, 129, 130, 193, 194) == obrazek_2.green() 177 | assert (65, 66, 129, 130, 193, 194) == obrazek_2.blue() 178 | 179 | # 15x15 wystający → 5x3 lower right corner 180 | obrazek_2 = Picture(red=range(256), green=range(256), blue=range(256), width=64, height=4) 181 | obrazek_2.crop(59, 1, 15, 15) 182 | assert (123, 124, 125, 126, 127, 187, 188, 189, 190, 191, 251, 252, 253, 254, 183 | 255) == obrazek_2.red() 184 | assert (123, 124, 125, 126, 127, 187, 188, 189, 190, 191, 251, 252, 253, 254, 185 | 255) == obrazek_2.green() 186 | assert (123, 124, 125, 126, 127, 187, 188, 189, 190, 191, 251, 252, 253, 254, 187 | 255) == obrazek_2.blue() 188 | 189 | 190 | assignment = Assignment( 191 | 'zadanie4', 192 | 'zadanie4.py', 193 | 'Vector', 194 | (test_one_red_pixel, test_kwadrat_gradient, test_prostokat_gradient) 195 | ) 196 | -------------------------------------------------------------------------------- /warsztat_4/test.txt: -------------------------------------------------------------------------------- 1 | Linia pierwsza 2 | Linia druga 3 | Linia trzecia 4 | -------------------------------------------------------------------------------- /warsztat_5/README.md: -------------------------------------------------------------------------------- 1 | W katalogu `praca_domowa` są zadania domowe. 2 | Na rozwiązanie czekamy do niedzieli **26.XI.2017 23:59:59**. 3 | Proszę się upewnić, że każde rozwiązanie się uruchamia! 4 | Proszę o wysyłanie tylko kodu Waszego autorstwa (**asserty z polecenia są zbędne**). 5 | Swoje rozwiązania wpisujcie do formularza: https://goo.gl/forms/UdFpdrkjVBIxnk3C3 6 | Rozwiązania przysłane w inny sposób nie będą brane pod uwagę. 7 | 8 | -------------------------------------------------------------------------------- /warsztat_5/praca_domowa/zadanie_1.py: -------------------------------------------------------------------------------- 1 | # Iterator Collatza 2 | # 3 | # Zadanie rozwiąż BEZ UŻYCIA GENERATORÓW. 4 | # Napisz klasę CollatzSeq(start_value) wyliczającą kolejne liczby według wzoru: 5 | # https://pl.wikipedia.org/wiki/Problem_Collatza#Sformu.C5.82owanie_problemu_Collatza 6 | # Powinno być możliwe iterowanie po CollatzSeq (po kolejnych liczbach z sekwencji). 7 | # Wartość 1 powinna być zwrócona tylko raz, potem iteracja powinna zostać przerwana 8 | # 9 | # Argumenty: 10 | # `start_value` - liczba od której zaczniemy wyliczać sekwencję. Podanie liczby innej niż 11 | # liczba naturalna powinno skutkować rzuceniem wyjątku ValueError 12 | 13 | 14 | def test_invalid_start(start): 15 | raised = False 16 | try: 17 | a = CollatzSeq(start) 18 | except ValueError as e: 19 | raised = True 20 | assert raised 21 | 22 | 23 | if __name__ == '__main__': 24 | assert list(CollatzSeq(1)) == [1] 25 | assert list(CollatzSeq(2)) == [2, 1] 26 | assert list(CollatzSeq(3)) == [3, 10, 5, 16, 8, 4, 2, 1] 27 | assert list(CollatzSeq(12)) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1] 28 | assert list(CollatzSeq(19)) == [19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1] 29 | assert list(CollatzSeq(27)) == [27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1] 30 | assert list(CollatzSeq(12346789)) == [12346789, 37040368, 18520184, 9260092, 4630046, 2315023, 6945070, 3472535, 10417606, 5208803, 15626410, 7813205, 23439616, 11719808, 5859904, 2929952, 1464976, 732488, 366244, 183122, 91561, 274684, 137342, 68671, 206014, 103007, 309022, 154511, 463534, 231767, 695302, 347651, 1042954, 521477, 1564432, 782216, 391108, 195554, 97777, 293332, 146666, 73333, 220000, 110000, 55000, 27500, 13750, 6875, 20626, 10313, 30940, 15470, 7735, 23206, 11603, 34810, 17405, 52216, 26108, 13054, 6527, 19582, 9791, 29374, 14687, 44062, 22031, 66094, 33047, 99142, 49571, 148714, 74357, 223072, 111536, 55768, 27884, 13942, 6971, 20914, 10457, 31372, 15686, 7843, 23530, 11765, 35296, 17648, 8824, 4412, 2206, 1103, 3310, 1655, 4966, 2483, 7450, 3725, 11176, 5588, 2794, 1397, 4192, 2096, 1048, 524, 262, 131, 394, 197, 592, 296, 148, 74, 37, 112, 56, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1] 31 | test_invalid_start(0) 32 | test_invalid_start(-12) 33 | test_invalid_start(2.0) 34 | test_invalid_start("111") 35 | -------------------------------------------------------------------------------- /warsztat_5/praca_domowa/zadanie_2.py: -------------------------------------------------------------------------------- 1 | # Napisz funkcję longest_collatz(start, stop) 2 | # Funkcja ma zwracać długość najdłuższej sekwencji Collatza i wartość startową dla wartości od ‘start’ włącznie, do ‘stop’ wyłącznie. 3 | # W tym zadaniu można (lecz nie ma przymusu) użyć generatorów. 4 | # Proszę o wykorzystanie kodu z zadania 1 (przeklejcie kod do tego zadania, żeby uniknąć problemów z importami, to nie zadanie na sprawdzenie importowania) 5 | 6 | 7 | if __name__ == '__main__': 8 | assert longest_collatz(1, 2) == (1, 1) 9 | assert longest_collatz(2, 3) == (2, 2) 10 | assert longest_collatz(3, 4) == (len([3, 10, 5, 16, 8, 4, 2, 1]), 3) 11 | assert longest_collatz(12, 13) == (len([12, 6, 3, 10, 5, 16, 8, 4, 2, 1]), 12) 12 | assert longest_collatz(19, 20) == (len([19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]), 19) 13 | assert longest_collatz(27, 28) == (len([27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]), 27) 14 | assert longest_collatz(12346789, 12346790) == (len([12346789, 37040368, 18520184, 9260092, 4630046, 2315023, 6945070, 3472535, 10417606, 5208803, 15626410, 7813205, 23439616, 11719808, 5859904, 2929952, 1464976, 732488, 366244, 183122, 91561, 274684, 137342, 68671, 206014, 103007, 309022, 154511, 463534, 231767, 695302, 347651, 1042954, 521477, 1564432, 782216, 391108, 195554, 97777, 293332, 146666, 73333, 220000, 110000, 55000, 27500, 13750, 6875, 20626, 10313, 30940, 15470, 7735, 23206, 11603, 34810, 17405, 52216, 26108, 13054, 6527, 19582, 9791, 29374, 14687, 44062, 22031, 66094, 33047, 99142, 49571, 148714, 74357, 223072, 111536, 55768, 27884, 13942, 6971, 20914, 10457, 31372, 15686, 7843, 23530, 11765, 35296, 17648, 8824, 4412, 2206, 1103, 3310, 1655, 4966, 2483, 7450, 3725, 11176, 5588, 2794, 1397, 4192, 2096, 1048, 524, 262, 131, 394, 197, 592, 296, 148, 74, 37, 112, 56, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]), 12346789) 15 | assert longest_collatz(1, 10**6) == (525, 837799) 16 | -------------------------------------------------------------------------------- /warsztat_5/praca_domowa/zadanie_3.py: -------------------------------------------------------------------------------- 1 | # Fibonacci generator 2 | # 3 | # Napis generator ciągu Fibonacciego: fibonnacci(elements_limit). 4 | # Generator ma zwracać kolejne wyrazy ciągu Fibonacciego: https://pl.wikipedia.org/wiki/Ci%C4%85g_Fibonacciego 5 | # 6 | # Args: 7 | # `elements_limit` - określa ilość zwróconych liczb. Jeśli `elements_limit` nie zostanie podane to generator ma być nieograniczony. Załóż, że jeżeli `elements_limit` będzie podane to zawsze będzie to int >= 0. 8 | 9 | 10 | if __name__ == '__main__': 11 | assert list(fibonnacci(10)) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 12 | assert list(fibonnacci(1)) == [0] 13 | assert list(fibonnacci(0)) == [] 14 | assert list(fibonnacci(2)) == [0, 1] 15 | -------------------------------------------------------------------------------- /warsztat_5/praca_domowa/zadanie_4.py: -------------------------------------------------------------------------------- 1 | # Requests: Wszystkie postaci z “Gwiezdnych Wojen” 2 | # 3 | # Na podstawie API: https://swapi.co/ napisz generator listujący wszystkie postaci pochodzące 4 | # z sagi Star Wars `sw_person_generator`. Postaci zwracaj wg kolejności z API. 5 | # Jeśli generator nie będzie mógł się połączyć z API, to powinien się zakończyć - generacja osób nie jest możliwa. 6 | # Proszę użyć modułu requests. 7 | 8 | 9 | if __name__ == '__main__': 10 | assert list(sw_person_generator()) == ['Luke Skywalker', 'C-3PO', 'R2-D2', 'Darth Vader', 'Leia Organa', 'Owen Lars', 'Beru Whitesun lars', 'R5-D4', 'Biggs Darklighter', 'Obi-Wan Kenobi', 'Anakin Skywalker', 'Wilhuff Tarkin', 'Chewbacca', 'Han Solo', 'Greedo', 'Jabba Desilijic Tiure', 'Wedge Antilles', 'Jek Tono Porkins', 'Yoda', 'Palpatine', 'Boba Fett', 'IG-88', 'Bossk', 'Lando Calrissian', 'Lobot', 'Ackbar', 'Mon Mothma', 'Arvel Crynyd', 'Wicket Systri Warrick', 'Nien Nunb', 'Qui-Gon Jinn', 'Nute Gunray', 'Finis Valorum', 'Padmé Amidala', 'Jar Jar Binks', 'Roos Tarpals', 'Rugor Nass', 'Ric Olié', 'Watto', 'Sebulba', 'Quarsh Panaka', 'Shmi Skywalker', 'Darth Maul', 'Bib Fortuna', 'Ayla Secura', 'Ratts Tyerell', 'Dud Bolt', 'Gasgano', 'Ben Quadinaros', 'Mace Windu', 'Ki-Adi-Mundi', 'Kit Fisto', 'Eeth Koth', 'Adi Gallia', 'Saesee Tiin', 'Yarael Poof', 'Plo Koon', 'Mas Amedda', 'Gregar Typho', 'Cordé', 'Cliegg Lars', 'Poggle the Lesser', 'Luminara Unduli', 'Barriss Offee', 'Dormé', 'Dooku', 'Bail Prestor Organa', 'Jango Fett', 'Zam Wesell', 'Dexter Jettster', 'Lama Su', 'Taun We', 'Jocasta Nu', 'R4-P17', 'Wat Tambor', 'San Hill', 'Shaak Ti', 'Grievous', 'Tarfful', 'Raymus Antilles', 'Sly Moore', 'Tion Medon', 'Finn', 'Rey', 'Poe Dameron', 'BB8', 'Captain Phasma'] 11 | -------------------------------------------------------------------------------- /warsztat_5/rozwiazania/zadanie_1.py: -------------------------------------------------------------------------------- 1 | # Iterator Collatza 2 | # 3 | # Zadanie rozwiąż BEZ UŻYCIA GENERATORÓW. 4 | # Napisz klasę CollatzSeq(start_value) wyliczającą kolejne liczby według wzoru: 5 | # https://pl.wikipedia.org/wiki/Problem_Collatza#Sformu.C5.82owanie_problemu_Collatza 6 | # Powinno być możliwe iterowanie po CollatzSeq (po kolejnych liczbach z sekwencji). 7 | # Wartość 1 powinna być zwrócona tylko raz, potem iteracja powinna zostać przerwana 8 | # 9 | # Argumenty: 10 | # `start_value` - liczba od której zaczniemy wyliczać sekwencję. Podanie liczby innej niż 11 | # liczba naturalna powinno skutkować rzuceniem wyjątku ValueError 12 | 13 | 14 | class CollatzSeq: 15 | def __init__(self, start_value): 16 | if not isinstance(start_value, int): 17 | raise ValueError 18 | if start_value < 1: 19 | raise ValueError 20 | self.start_value = start_value 21 | 22 | def __iter__(self): 23 | return CollatzSeqIterator(self) 24 | 25 | 26 | class CollatzSeqIterator: 27 | def __init__(self, seq): 28 | self.val = seq.start_value 29 | self.initial_returned = False 30 | self.seq_finished = False 31 | 32 | 33 | def __iter__(self): 34 | return self 35 | 36 | def __next__(self): 37 | if self.seq_finished: 38 | raise StopIteration 39 | if not self.initial_returned: 40 | self.initial_returned = True 41 | if self.val == 1: 42 | self.seq_finished = True 43 | return self.val 44 | if self.val % 2: # niepodzielne przez 2 45 | self.val = 3 * self.val + 1 46 | else: 47 | self.val //= 2 # // bo chcemy int a nie float. 48 | if self.val == 1: 49 | self.seq_finished = True 50 | return self.val 51 | -------------------------------------------------------------------------------- /warsztat_5/rozwiazania/zadanie_2.py: -------------------------------------------------------------------------------- 1 | # Napisz funkcję longest_collatz(start, stop) 2 | # Funkcja ma zwracać długość najdłuższej sekwencji Collatza i wartość startową dla wartości od ‘start’ włącznie, do ‘stop’ wyłącznie. 3 | # W tym zadaniu można (lecz nie ma przymusu) użyć generatorów. 4 | # Proszę o wykorzystanie kodu z zadania 1 (przeklejcie kod do tego zadania, żeby uniknąć problemów z importami, to nie zadanie na sprawdzenie importowania) 5 | 6 | class CollatzSeq: 7 | def __init__(self, start_value): 8 | if not isinstance(start_value, int): 9 | raise ValueError 10 | if start_value < 1: 11 | raise ValueError 12 | self.start_value = start_value 13 | 14 | def __iter__(self): 15 | return CollatzSeqIterator(self) 16 | 17 | def __len__(self): 18 | return sum(1 for _ in self) 19 | 20 | 21 | class CollatzSeqIterator: 22 | def __init__(self, seq): 23 | self.val = seq.start_value 24 | self.initial_returned = False 25 | self.seq_finished = False 26 | 27 | 28 | def __iter__(self): 29 | return self 30 | 31 | def __next__(self): 32 | if self.seq_finished: 33 | raise StopIteration 34 | if not self.initial_returned: 35 | self.initial_returned = True 36 | if self.val == 1: 37 | self.seq_finished = True 38 | return self.val 39 | if self.val % 2: # niepodzielne przez 2 40 | self.val = 3 * self.val + 1 41 | else: 42 | self.val //= 2 # // bo chcemy int a nie float. 43 | if self.val == 1: 44 | self.seq_finished = True 45 | return self.val 46 | 47 | def longest_collatz(start, stop): 48 | answ_len = 0 49 | answ_i = None 50 | for i in range(start, stop): 51 | total = len(CollatzSeq(i)) 52 | if total > answ_len: 53 | answ_len = total 54 | answ_i = i 55 | return answ_len, answ_i 56 | 57 | if __name__ == '__main__': 58 | assert longest_collatz(1, 2) == (1, 1) 59 | assert longest_collatz(2, 3) == (2, 2) 60 | assert longest_collatz(3, 4) == (len([3, 10, 5, 16, 8, 4, 2, 1]), 3) 61 | assert longest_collatz(12, 13) == (len([12, 6, 3, 10, 5, 16, 8, 4, 2, 1]), 12) 62 | assert longest_collatz(19, 20) == (len([19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]), 19) 63 | assert longest_collatz(27, 28) == (len([27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]), 27) 64 | assert longest_collatz(12346789, 12346790) == (len([12346789, 37040368, 18520184, 9260092, 4630046, 2315023, 6945070, 3472535, 10417606, 5208803, 15626410, 7813205, 23439616, 11719808, 5859904, 2929952, 1464976, 732488, 366244, 183122, 91561, 274684, 137342, 68671, 206014, 103007, 309022, 154511, 463534, 231767, 695302, 347651, 1042954, 521477, 1564432, 782216, 391108, 195554, 97777, 293332, 146666, 73333, 220000, 110000, 55000, 27500, 13750, 6875, 20626, 10313, 30940, 15470, 7735, 23206, 11603, 34810, 17405, 52216, 26108, 13054, 6527, 19582, 9791, 29374, 14687, 44062, 22031, 66094, 33047, 99142, 49571, 148714, 74357, 223072, 111536, 55768, 27884, 13942, 6971, 20914, 10457, 31372, 15686, 7843, 23530, 11765, 35296, 17648, 8824, 4412, 2206, 1103, 3310, 1655, 4966, 2483, 7450, 3725, 11176, 5588, 2794, 1397, 4192, 2096, 1048, 524, 262, 131, 394, 197, 592, 296, 148, 74, 37, 112, 56, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]), 12346789) 65 | assert longest_collatz(1, 10**6) == (525, 837799) 66 | -------------------------------------------------------------------------------- /warsztat_5/rozwiazania/zadanie_3.py: -------------------------------------------------------------------------------- 1 | # Fibonacci generator 2 | # 3 | # Napisz generator ciągu Fibonacciego: fibonnacci(elements_limit). 4 | # Generator ma zwracać kolejne wyrazy ciągu Fibonacciego: https://pl.wikipedia.org/wiki/Ci%C4%85g_Fibonacciego 5 | # 6 | # Args: 7 | # `elements_limit` - określa ilość zwróconych liczb. Jeśli `elements_limit` nie zostanie podane to generator ma być nieograniczony. Załóż, że jeżeli `elements_limit` będzie podane to zawsze będzie to int >= 0. 8 | 9 | 10 | 11 | def fibonnacci(elements_limit=None): 12 | limit_set = False 13 | count = 0 14 | if elements_limit is not None: 15 | limit_set = True 16 | fib = _inf_fib() 17 | while True: 18 | if limit_set: 19 | if count < elements_limit: 20 | count += 1 21 | yield next(fib) 22 | else: 23 | break 24 | else: 25 | yield next(fib) 26 | 27 | 28 | def _inf_fib(): 29 | a, b = 0, 1 30 | yield a 31 | yield b 32 | while True: 33 | c = a + b 34 | yield c 35 | a, b = b, c 36 | -------------------------------------------------------------------------------- /warsztat_5/rozwiazania/zadanie_4.py: -------------------------------------------------------------------------------- 1 | # Requests: Wszystkie postaci z “Gwiezdnych Wojen” 2 | # 3 | # Na podstawie API: https://swapi.co/ napisz generator listujący wszystkie postaci pochodzące 4 | # z sagi Star Wars `sw_person_generator`. Postaci zwracaj wg kolejności z API. 5 | # Jeśli generator nie będzie mógł się połączyć z API, to powinien się zakończyć - generacja osób nie jest możliwa. 6 | # Proszę użyć modułu requests. 7 | 8 | 9 | 10 | BASE_URL = 'https://swapi.co/api/people/{person_id}/' 11 | 12 | import requests 13 | from requests.exceptions import RequestException 14 | 15 | def sw_person_generator(): 16 | person_counter = 1 17 | not_found_in_row = 0 18 | while True: 19 | current_url = BASE_URL.format(person_id=person_counter) # może od razu coś lepszego do składania urli??? (Żeby brało pod uwagę kodowanie) 20 | # print('przed requestem nr {}, url: {}'.format(person_counter, current_url)) 21 | try: 22 | r = requests.get(url=current_url) 23 | except RequestException: 24 | return # cannot connect to api, generation process finished 25 | person_counter += 1 26 | print(r.status_code, current_url)#, r.headers) 27 | if r.ok: 28 | not_found_in_row = 0 29 | person = r.json() 30 | yield person.get('name') 31 | elif r.status_code == 404: 32 | not_found_in_row += 1 33 | if not_found_in_row > 5: 34 | return 35 | else: 36 | continue 37 | else: 38 | return 39 | 40 | if __name__ == '__main__': 41 | assert list(sw_person_generator()) == ['Luke Skywalker', 'C-3PO', 'R2-D2', 'Darth Vader', 'Leia Organa', 'Owen Lars', 'Beru Whitesun lars', 'R5-D4', 'Biggs Darklighter', 'Obi-Wan Kenobi', 'Anakin Skywalker', 'Wilhuff Tarkin', 'Chewbacca', 'Han Solo', 'Greedo', 'Jabba Desilijic Tiure', 'Wedge Antilles', 'Jek Tono Porkins', 'Yoda', 'Palpatine', 'Boba Fett', 'IG-88', 'Bossk', 'Lando Calrissian', 'Lobot', 'Ackbar', 'Mon Mothma', 'Arvel Crynyd', 'Wicket Systri Warrick', 'Nien Nunb', 'Qui-Gon Jinn', 'Nute Gunray', 'Finis Valorum', 'Padmé Amidala', 'Jar Jar Binks', 'Roos Tarpals', 'Rugor Nass', 'Ric Olié', 'Watto', 'Sebulba', 'Quarsh Panaka', 'Shmi Skywalker', 'Darth Maul', 'Bib Fortuna', 'Ayla Secura', 'Ratts Tyerell', 'Dud Bolt', 'Gasgano', 'Ben Quadinaros', 'Mace Windu', 'Ki-Adi-Mundi', 'Kit Fisto', 'Eeth Koth', 'Adi Gallia', 'Saesee Tiin', 'Yarael Poof', 'Plo Koon', 'Mas Amedda', 'Gregar Typho', 'Cordé', 'Cliegg Lars', 'Poggle the Lesser', 'Luminara Unduli', 'Barriss Offee', 'Dormé', 'Dooku', 'Bail Prestor Organa', 'Jango Fett', 'Zam Wesell', 'Dexter Jettster', 'Lama Su', 'Taun We', 'Jocasta Nu', 'R4-P17', 'Wat Tambor', 'San Hill', 'Shaak Ti', 'Grievous', 'Tarfful', 'Raymus Antilles', 'Sly Moore', 'Tion Medon', 'Finn', 'Rey', 'Poe Dameron', 'BB8', 'Captain Phasma'] 42 | 43 | 44 | # 200 https://swapi.co/api/people/1/ 45 | # Luke Skywalker 46 | # 200 https://swapi.co/api/people/2/ 47 | # C-3PO 48 | # 200 https://swapi.co/api/people/3/ 49 | # R2-D2 50 | # 200 https://swapi.co/api/people/4/ 51 | # Darth Vader 52 | # 200 https://swapi.co/api/people/5/ 53 | # Leia Organa 54 | # 200 https://swapi.co/api/people/6/ 55 | # Owen Lars 56 | # 200 https://swapi.co/api/people/7/ 57 | # Beru Whitesun lars 58 | # 200 https://swapi.co/api/people/8/ 59 | # R5-D4 60 | # 200 https://swapi.co/api/people/9/ 61 | # Biggs Darklighter 62 | # 200 https://swapi.co/api/people/10/ 63 | # Obi-Wan Kenobi 64 | # 200 https://swapi.co/api/people/11/ 65 | # Anakin Skywalker 66 | # 200 https://swapi.co/api/people/12/ 67 | # Wilhuff Tarkin 68 | # 200 https://swapi.co/api/people/13/ 69 | # Chewbacca 70 | # 200 https://swapi.co/api/people/14/ 71 | # Han Solo 72 | # 200 https://swapi.co/api/people/15/ 73 | # Greedo 74 | # 200 https://swapi.co/api/people/16/ 75 | # Jabba Desilijic Tiure 76 | # 404 https://swapi.co/api/people/17/ 77 | # 200 https://swapi.co/api/people/18/ 78 | # Wedge Antilles 79 | # 200 https://swapi.co/api/people/19/ 80 | # Jek Tono Porkins 81 | # 200 https://swapi.co/api/people/20/ 82 | # Yoda 83 | # 200 https://swapi.co/api/people/21/ 84 | # Palpatine 85 | # 200 https://swapi.co/api/people/22/ 86 | # Boba Fett 87 | # 200 https://swapi.co/api/people/23/ 88 | # IG-88 89 | # 200 https://swapi.co/api/people/24/ 90 | # Bossk 91 | # 200 https://swapi.co/api/people/25/ 92 | # Lando Calrissian 93 | # 200 https://swapi.co/api/people/26/ 94 | # Lobot 95 | # 200 https://swapi.co/api/people/27/ 96 | # Ackbar 97 | # 200 https://swapi.co/api/people/28/ 98 | # Mon Mothma 99 | # 200 https://swapi.co/api/people/29/ 100 | # Arvel Crynyd 101 | # 200 https://swapi.co/api/people/30/ 102 | # Wicket Systri Warrick 103 | # 200 https://swapi.co/api/people/31/ 104 | # Nien Nunb 105 | # 200 https://swapi.co/api/people/32/ 106 | # Qui-Gon Jinn 107 | # 200 https://swapi.co/api/people/33/ 108 | # Nute Gunray 109 | # 200 https://swapi.co/api/people/34/ 110 | # Finis Valorum 111 | # 200 https://swapi.co/api/people/35/ 112 | # Padmé Amidala 113 | # 200 https://swapi.co/api/people/36/ 114 | # Jar Jar Binks 115 | # 200 https://swapi.co/api/people/37/ 116 | # Roos Tarpals 117 | # 200 https://swapi.co/api/people/38/ 118 | # Rugor Nass 119 | # 200 https://swapi.co/api/people/39/ 120 | # Ric Olié 121 | # 200 https://swapi.co/api/people/40/ 122 | # Watto 123 | # 200 https://swapi.co/api/people/41/ 124 | # Sebulba 125 | # 200 https://swapi.co/api/people/42/ 126 | # Quarsh Panaka 127 | # 200 https://swapi.co/api/people/43/ 128 | # Shmi Skywalker 129 | # 200 https://swapi.co/api/people/44/ 130 | # Darth Maul 131 | # 200 https://swapi.co/api/people/45/ 132 | # Bib Fortuna 133 | # 200 https://swapi.co/api/people/46/ 134 | # Ayla Secura 135 | # 200 https://swapi.co/api/people/47/ 136 | # Ratts Tyerell 137 | # 200 https://swapi.co/api/people/48/ 138 | # Dud Bolt 139 | # 200 https://swapi.co/api/people/49/ 140 | # Gasgano 141 | # 200 https://swapi.co/api/people/50/ 142 | # Ben Quadinaros 143 | # 200 https://swapi.co/api/people/51/ 144 | # Mace Windu 145 | # 200 https://swapi.co/api/people/52/ 146 | # Ki-Adi-Mundi 147 | # 200 https://swapi.co/api/people/53/ 148 | # Kit Fisto 149 | # 200 https://swapi.co/api/people/54/ 150 | # Eeth Koth 151 | # 200 https://swapi.co/api/people/55/ 152 | # Adi Gallia 153 | # 200 https://swapi.co/api/people/56/ 154 | # Saesee Tiin 155 | # 200 https://swapi.co/api/people/57/ 156 | # Yarael Poof 157 | # 200 https://swapi.co/api/people/58/ 158 | # Plo Koon 159 | # 200 https://swapi.co/api/people/59/ 160 | # Mas Amedda 161 | # 200 https://swapi.co/api/people/60/ 162 | # Gregar Typho 163 | # 200 https://swapi.co/api/people/61/ 164 | # Cordé 165 | # 200 https://swapi.co/api/people/62/ 166 | # Cliegg Lars 167 | # 200 https://swapi.co/api/people/63/ 168 | # Poggle the Lesser 169 | # 200 https://swapi.co/api/people/64/ 170 | # Luminara Unduli 171 | # 200 https://swapi.co/api/people/65/ 172 | # Barriss Offee 173 | # 200 https://swapi.co/api/people/66/ 174 | # Dormé 175 | # 200 https://swapi.co/api/people/67/ 176 | # Dooku 177 | # 200 https://swapi.co/api/people/68/ 178 | # Bail Prestor Organa 179 | # 200 https://swapi.co/api/people/69/ 180 | # Jango Fett 181 | # 200 https://swapi.co/api/people/70/ 182 | # Zam Wesell 183 | # 200 https://swapi.co/api/people/71/ 184 | # Dexter Jettster 185 | # 200 https://swapi.co/api/people/72/ 186 | # Lama Su 187 | # 200 https://swapi.co/api/people/73/ 188 | # Taun We 189 | # 200 https://swapi.co/api/people/74/ 190 | # Jocasta Nu 191 | # 200 https://swapi.co/api/people/75/ 192 | # R4-P17 193 | # 200 https://swapi.co/api/people/76/ 194 | # Wat Tambor 195 | # 200 https://swapi.co/api/people/77/ 196 | # San Hill 197 | # 200 https://swapi.co/api/people/78/ 198 | # Shaak Ti 199 | # 200 https://swapi.co/api/people/79/ 200 | # Grievous 201 | # 200 https://swapi.co/api/people/80/ 202 | # Tarfful 203 | # 200 https://swapi.co/api/people/81/ 204 | # Raymus Antilles 205 | # 200 https://swapi.co/api/people/82/ 206 | # Sly Moore 207 | # 200 https://swapi.co/api/people/83/ 208 | # Tion Medon 209 | # 200 https://swapi.co/api/people/84/ 210 | # Finn 211 | # 200 https://swapi.co/api/people/85/ 212 | # Rey 213 | # 200 https://swapi.co/api/people/86/ 214 | # Poe Dameron 215 | # 200 https://swapi.co/api/people/87/ 216 | # BB8 217 | # 200 https://swapi.co/api/people/88/ 218 | # Captain Phasma 219 | # 404 https://swapi.co/api/people/89/ 220 | # 404 https://swapi.co/api/people/90/ 221 | # 404 https://swapi.co/api/people/91/ 222 | # 404 https://swapi.co/api/people/92/ 223 | # 404 https://swapi.co/api/people/93/ 224 | # 404 https://swapi.co/api/people/94/ 225 | -------------------------------------------------------------------------------- /warsztat_5/testy/zadanie1.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | # Iterator Collatza 3 | # 4 | # Zadanie rozwiąż BEZ UŻYCIA GENERATORÓW. 5 | # Napisz klasę CollatzSeq(start_value) wyliczającą kolejne liczby według wzoru: 6 | # https://pl.wikipedia.org/wiki/Problem_Collatza#Sformu.C5.82owanie_problemu_Collatza 7 | # Powinno być możliwe iterowanie po CollatzSeq (po kolejnych liczbach z sekwencji). 8 | # Wartość 1 powinna być zwrócona tylko raz, potem iteracja powinna zostać przerwana 9 | # 10 | # Argumenty: 11 | # `start_value` - liczba od której zaczniemy wyliczać sekwencję. Podanie liczby innej niż 12 | # liczba naturalna powinno skutkować rzuceniem wyjątku ValueError 13 | 14 | 15 | def test_collatz_seq_1(func): 16 | assert list(func(1)) == [1] 17 | 18 | 19 | def test_collatz_seq_2(func): 20 | assert list(func(2)) == [2, 1] 21 | 22 | 23 | def test_collatz_seq_3(func): 24 | assert list(func(3)) == [3, 10, 5, 16, 8, 4, 2, 1] 25 | 26 | 27 | def test_collatz_seq_12(func): 28 | assert list(func(12)) == [12, 6, 3, 10, 5, 16, 8, 4, 2, 1] 29 | 30 | 31 | def test_collatz_seq_19(func): 32 | assert list(func(19)) == [19, 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8,4, 2, 1] 33 | 34 | 35 | def test_collatz_seq_27(func): 36 | assert list(func(27)) == [27, 82, 41, 124, 62, 31, 94, 47, 142, 71, 214, 107, 322, 161, 484, 242, 121, 364, 182, 91, 274, 137, 412, 206, 103, 310, 155, 466, 233, 700, 350, 175, 526, 263, 790, 395, 1186, 593, 1780, 890, 445, 1336, 668, 334, 167, 502, 251, 754, 377, 1132, 566, 283, 850, 425, 1276, 638, 319, 958, 479, 1438, 719, 2158, 1079, 3238, 1619, 4858, 2429, 7288, 3644, 1822, 911, 2734, 1367, 4102, 2051, 6154, 3077, 9232, 4616, 2308, 1154, 577, 1732, 866, 433, 1300, 650, 325, 976, 488, 244, 122, 61, 184, 92, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1] 37 | 38 | 39 | def test_collatz_seq_12346789(func): 40 | assert list(func(12346789)) == [12346789, 37040368, 18520184, 9260092, 4630046, 2315023, 6945070, 3472535, 10417606, 5208803, 15626410, 7813205, 23439616, 11719808, 5859904, 2929952, 1464976, 732488, 366244, 183122, 91561, 274684, 137342, 68671, 206014, 103007, 309022, 154511, 463534, 231767, 695302, 347651, 1042954, 521477, 1564432, 782216, 391108, 195554, 97777, 293332, 146666, 73333, 220000, 110000, 55000, 27500, 13750, 6875, 20626, 10313, 30940, 15470, 7735, 23206, 11603, 34810, 17405, 52216, 26108, 13054, 6527, 19582, 9791, 29374, 14687, 44062, 22031, 66094, 33047, 99142, 49571, 148714, 74357, 223072, 111536, 55768, 27884, 13942, 6971, 20914, 10457, 31372, 15686, 7843, 23530, 11765, 35296, 17648, 8824, 4412, 2206, 1103, 3310, 1655, 4966, 2483, 7450, 3725, 11176, 5588, 2794, 1397, 4192, 2096, 1048, 524, 262, 131, 394, 197, 592, 296, 148, 74, 37, 112, 56, 28, 14, 7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1] 41 | 42 | 43 | def test_invalid_start(func, start): 44 | raised = False 45 | try: 46 | a = func(start) 47 | except ValueError as e: 48 | raised = True 49 | assert raised 50 | 51 | 52 | def test_collatz_seq_invalid_start_0(func): 53 | test_invalid_start(func, 0) 54 | 55 | 56 | def test_collatz_seq_invalid_start_negative(func): 57 | test_invalid_start(func, -12) 58 | 59 | 60 | def test_collatz_seq_invalid_start_float(func): 61 | test_invalid_start(func, 2.0) 62 | 63 | 64 | def test_collatz_seq_invalid_start_string(func): 65 | test_invalid_start(func, "111") 66 | 67 | def test_collatz_seq_has_no_next_method(func): 68 | assert not hasattr(func, '__next__') 69 | 70 | 71 | assignment = Assignment( 72 | 'zadanie1', 73 | 'zadanie1.py', 74 | 'CollatzSeq', 75 | (test_collatz_seq_1, test_collatz_seq_2, test_collatz_seq_3, test_collatz_seq_12, 76 | test_collatz_seq_19, test_collatz_seq_27, test_collatz_seq_12346789, 77 | test_collatz_seq_invalid_start_0, test_collatz_seq_invalid_start_negative, 78 | test_collatz_seq_invalid_start_float, test_collatz_seq_invalid_start_string, 79 | test_collatz_seq_has_no_next_method) 80 | ) 81 | -------------------------------------------------------------------------------- /warsztat_5/testy/zadanie3.py: -------------------------------------------------------------------------------- 1 | from homework_checker.base import Assignment 2 | 3 | 4 | # Fibonacci generator 5 | # 6 | # Napis generator ciągu Fibonacciego: fibonnacci(elements_limit). 7 | # Generator ma zwracać kolejne wyrazy ciągu Fibonacciego: https://pl.wikipedia.org/wiki/Ci%C4%85g_Fibonacciego 8 | # 9 | # Args: 10 | # `elements_limit` - określa ilość zwróconych liczb. Jeśli `elements_limit` nie zostanie podane to generator ma być nieograniczony. Załóż, że jeżeli `elements_limit` będzie podane to zawsze będzie to int >= 0. 11 | 12 | 13 | def test_10(func): 14 | assert list(func(10)) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 15 | 16 | 17 | def test_1(func): 18 | assert list(func(1)) == [0] 19 | 20 | 21 | def test_0(func): 22 | assert list(func(0)) == [] 23 | 24 | 25 | def test_2(func): 26 | assert list(func(2)) == [0, 1] 27 | 28 | 29 | def test_infitnite(func): 30 | ten = [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 31 | no_limits = func() 32 | for x, y in zip(no_limits, ten): 33 | assert x == y 34 | 35 | 36 | assignment = Assignment('zadanie3', 'zadanie3.py', 'fibonnacci', 37 | (test_0, test_1, test_2, test_10, test_infitnite)) 38 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/01_initial_pygame_programm.py: -------------------------------------------------------------------------------- 1 | # zgapione z książki: http://inventwithpython.com/pygame 2 | import pygame, sys 3 | from pygame.locals import * 4 | 5 | pygame.init() 6 | DISPLAYSURF = pygame.display.set_mode((400, 300)) 7 | pygame.display.set_caption('Hello World!') 8 | while True: # main game loop 9 | for event in pygame.event.get(): 10 | if event.type == QUIT: 11 | pygame.quit() 12 | sys.exit() 13 | pygame.display.update() -------------------------------------------------------------------------------- /warsztat_6/przykłady/02_kolko_i_kwadrat.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | 5 | # RGB 6 | WHITE = (255, 255, 255) 7 | RED = (255, 0, 0) 8 | 9 | pygame.init() 10 | DISPLAYSURF = pygame.display.set_mode((400, 300)) 11 | pygame.display.set_caption('Circle and the square!') 12 | 13 | # x, y (lewy górny róg), szerokość, wysokość 14 | pygame.draw.rect(DISPLAYSURF, WHITE, (100, 100, 50, 50)) 15 | # (x, y), promień, grubość 16 | pygame.draw.circle(DISPLAYSURF, RED, (200, 150), 50) 17 | while True: 18 | for event in pygame.event.get(): 19 | if event.type == QUIT: 20 | pygame.quit() 21 | sys.exit() 22 | pygame.display.update() 23 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/03_kolko_i_kwadrat_fps.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | 5 | # RGB 6 | WHITE = (255, 255, 255) 7 | RED = (255, 0, 0) 8 | 9 | pygame.init() 10 | FPS = 60 # Frames Per Second 11 | fpsClock = pygame.time.Clock() 12 | DISPLAYSURF = pygame.display.set_mode((400, 300)) 13 | pygame.display.set_caption('Circle and the square!') 14 | 15 | # x, y (lewy górny róg), szerokość, wysokość 16 | pygame.draw.rect(DISPLAYSURF, WHITE, (100, 100, 50, 50)) 17 | # (x, y), promień, grubość 18 | pygame.draw.circle(DISPLAYSURF, RED, (200, 150), 50) 19 | while True: 20 | for event in pygame.event.get(): 21 | if event.type == QUIT: 22 | pygame.quit() 23 | sys.exit() 24 | pygame.display.update() 25 | fpsClock.tick(FPS) 26 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/04_kolko_i_kwadrat_no_voice.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | 5 | # RGB 6 | WHITE = (255, 255, 255) 7 | RED = (255, 0, 0) 8 | 9 | pygame.init() 10 | # workaround for: https://github.com/pygame/pygame/issues/331 11 | pygame.mixer.quit() 12 | FPS = 60 # Frames Per Second 13 | fpsClock = pygame.time.Clock() 14 | DISPLAYSURF = pygame.display.set_mode((400, 300)) 15 | pygame.display.set_caption('Circle and the square!') 16 | 17 | # x, y (lewy górny róg), szerokość, wysokość 18 | pygame.draw.rect(DISPLAYSURF, WHITE, (100, 100, 50, 50)) 19 | # (x, y), promień, grubość 20 | pygame.draw.circle(DISPLAYSURF, RED, (200, 150), 50) 21 | while True: 22 | for event in pygame.event.get(): 23 | if event.type == QUIT: 24 | pygame.quit() 25 | sys.exit() 26 | pygame.display.update() 27 | fpsClock.tick(FPS) 28 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/05_segmenty.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 5 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 6 | 7 | GAME_CELLS_X = 20 8 | GAME_CELLS_Y = 15 9 | 10 | 11 | def draw_segment(surface, x, y): 12 | """ 13 | :param surface: surface to draw on 14 | :param x: x coord in game cells 15 | :param y: y coord in game cells 16 | :return: 17 | """ 18 | WHITE = (255, 255, 255) 19 | position = ( 20 | x * GAME_CELL_SIZE_PX, 21 | y * GAME_CELL_SIZE_PX, 22 | GAME_CELL_SIZE_PX, 23 | GAME_CELL_SIZE_PX 24 | ) 25 | pygame.draw.rect(surface, WHITE, position) 26 | 27 | 28 | def draw_food(surface, x, y): 29 | """ 30 | :param surface: surface to draw on 31 | :param x: x coord in game cells 32 | :param y: y coord in game cells 33 | :return: 34 | """ 35 | RED = (255, 0, 0) 36 | position = ( 37 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 38 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 39 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 40 | 41 | 42 | def run_game(): 43 | pygame.init() 44 | # workaround for: https://github.com/pygame/pygame/issues/331 45 | pygame.mixer.quit() 46 | FPS = 60 # Frames Per Second 47 | fpsClock = pygame.time.Clock() 48 | DISPLAYSURF = pygame.display.set_mode( 49 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 50 | ) 51 | pygame.display.set_caption('Segment and food') 52 | for x in range(GAME_CELLS_X): 53 | for y in range(GAME_CELLS_Y): 54 | if (x + y) % 2 == 0: 55 | draw_segment(surface=DISPLAYSURF, x=x, y=y) 56 | else: 57 | draw_food(surface=DISPLAYSURF, x=x, y=y) 58 | while True: 59 | for event in pygame.event.get(): 60 | if event.type == QUIT: 61 | pygame.quit() 62 | sys.exit() 63 | pygame.display.update() 64 | fpsClock.tick(FPS) 65 | 66 | 67 | if __name__ == '__main__': 68 | run_game() 69 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/06_moving_snake.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 5 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 6 | 7 | GAME_CELLS_X = 20 8 | GAME_CELLS_Y = 15 9 | 10 | # list is a bad idea ... 11 | # much better: 12 | # https://docs.python.org/3.5/library/collections.html#collections.deque 13 | # Ale nie jestem w stanie zgadnąć czy w przypadku krótkiego węża różnica 14 | # będzie zauważalna 15 | snake_segments = [(0, 5), (1, 5), (2, 5)] 16 | 17 | 18 | def draw_segment(surface, x, y): 19 | """ 20 | :param surface: surface to draw on 21 | :param x: x coord in game cells 22 | :param y: y coord in game cells 23 | :return: 24 | """ 25 | WHITE = (255, 255, 255) 26 | position = ( 27 | x * GAME_CELL_SIZE_PX, 28 | y * GAME_CELL_SIZE_PX, 29 | GAME_CELL_SIZE_PX, 30 | GAME_CELL_SIZE_PX 31 | ) 32 | pygame.draw.rect(surface, WHITE, position) 33 | 34 | 35 | def draw_food(surface, x, y): 36 | """ 37 | :param surface: surface to draw on 38 | :param x: x coord in game cells 39 | :param y: y coord in game cells 40 | :return: 41 | """ 42 | RED = (255, 0, 0) 43 | position = ( 44 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 45 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 46 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 47 | 48 | 49 | def move_snake_right(snake_segments): 50 | # usunięcie ostatniego segmentu 51 | snake_segments.pop(0) 52 | # dodanie elementu na początek 53 | first_segment = snake_segments[-1] 54 | snake_segments.append((first_segment[0] + 1, first_segment[1])) 55 | 56 | 57 | def draw_snake(surface, snake_segments): 58 | for segment in snake_segments: 59 | draw_segment(surface, *segment) 60 | 61 | 62 | def draw_background(surface): 63 | BLACK = (0, 0, 0) 64 | position = ( 65 | 0, 0, 66 | GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX 67 | ) 68 | pygame.draw.rect(surface, BLACK, position) 69 | 70 | 71 | def run_game(): 72 | pygame.init() 73 | # workaround for: https://github.com/pygame/pygame/issues/331 74 | pygame.mixer.quit() 75 | FPS = 10 # Frames Per Second 76 | fpsClock = pygame.time.Clock() 77 | DISPLAYSURF = pygame.display.set_mode( 78 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 79 | ) 80 | pygame.display.set_caption('Moving segments') 81 | frame_number = 0 82 | while True: 83 | for event in pygame.event.get(): 84 | print('event: {}'.format(event)) 85 | if event.type == QUIT: 86 | pygame.quit() 87 | sys.exit() 88 | draw_background(DISPLAYSURF) 89 | draw_snake(DISPLAYSURF, snake_segments) 90 | move_snake_right(snake_segments) 91 | pygame.display.update() 92 | fpsClock.tick(FPS) 93 | 94 | 95 | if __name__ == '__main__': 96 | run_game() 97 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/07_moving_snake_with_snake_class.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 5 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 6 | 7 | GAME_CELLS_X = 20 8 | GAME_CELLS_Y = 15 9 | 10 | 11 | def draw_segment(surface, x, y): 12 | """ 13 | :param surface: surface to draw on 14 | :param x: x coord in game cells 15 | :param y: y coord in game cells 16 | :return: 17 | """ 18 | WHITE = (255, 255, 255) 19 | position = ( 20 | x * GAME_CELL_SIZE_PX, 21 | y * GAME_CELL_SIZE_PX, 22 | GAME_CELL_SIZE_PX, 23 | GAME_CELL_SIZE_PX 24 | ) 25 | pygame.draw.rect(surface, WHITE, position) 26 | 27 | 28 | def draw_food(surface, x, y): 29 | """ 30 | :param surface: surface to draw on 31 | :param x: x coord in game cells 32 | :param y: y coord in game cells 33 | :return: 34 | """ 35 | RED = (255, 0, 0) 36 | position = ( 37 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 38 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 39 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 40 | 41 | 42 | class Snake: 43 | # A tu jest babol, ciekawe, czy ktoś ogarnie jaki 44 | vectors = { 45 | 'UP': (0, 1), 46 | 'DOWN': (0, -1), 47 | 'LEFT': (-1, 0), 48 | 'RIGHT': (1, 0), 49 | 50 | } 51 | 52 | def __init__(self): 53 | self.segments = [(0, 5), (1, 5), (2, 5)] 54 | self.direction = 'RIGHT' 55 | 56 | def move(self): 57 | vector = self.vectors.get(self.direction, (0, 0)) 58 | # wypadałoby zalogować, że brakuje jakiegos klucza... 59 | self.segments.pop(0) 60 | first_segment = self.segments[-1] 61 | self.segments.append( 62 | # TODO: a może da się sprytniej? Coś z zip? 63 | (first_segment[0] + vector[0], first_segment[1] + vector[1]) 64 | ) 65 | 66 | def draw(self, surface): 67 | for segment in self.segments: 68 | draw_segment(surface, *segment) 69 | 70 | 71 | def draw_background(surface): 72 | BLACK = (0, 0, 0) 73 | position = ( 74 | 0, 0, 75 | GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX 76 | ) 77 | pygame.draw.rect(surface, BLACK, position) 78 | 79 | 80 | def run_game(): 81 | pygame.init() 82 | # workaround for: https://github.com/pygame/pygame/issues/331 83 | pygame.mixer.quit() 84 | FPS = 10 # Frames Per Second 85 | fpsClock = pygame.time.Clock() 86 | DISPLAYSURF = pygame.display.set_mode( 87 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 88 | ) 89 | pygame.display.set_caption('Moving segments with snake class') 90 | snake = Snake() 91 | while True: 92 | for event in pygame.event.get(): 93 | print('event: {}'.format(event)) 94 | if event.type == QUIT: 95 | pygame.quit() 96 | sys.exit() 97 | draw_background(DISPLAYSURF) 98 | snake.draw(DISPLAYSURF) 99 | snake.move() 100 | pygame.display.update() 101 | fpsClock.tick(FPS) 102 | 103 | 104 | if __name__ == '__main__': 105 | run_game() 106 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/08_controling_snake.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 5 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 6 | 7 | GAME_CELLS_X = 20 8 | GAME_CELLS_Y = 15 9 | 10 | 11 | def draw_segment(surface, x, y): 12 | """ 13 | :param surface: surface to draw on 14 | :param x: x coord in game cells 15 | :param y: y coord in game cells 16 | :return: 17 | """ 18 | WHITE = (255, 255, 255) 19 | position = ( 20 | x * GAME_CELL_SIZE_PX, 21 | y * GAME_CELL_SIZE_PX, 22 | GAME_CELL_SIZE_PX, 23 | GAME_CELL_SIZE_PX 24 | ) 25 | pygame.draw.rect(surface, WHITE, position) 26 | 27 | 28 | def draw_food(surface, x, y): 29 | """ 30 | :param surface: surface to draw on 31 | :param x: x coord in game cells 32 | :param y: y coord in game cells 33 | :return: 34 | """ 35 | RED = (255, 0, 0) 36 | position = ( 37 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 38 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 39 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 40 | 41 | 42 | class Snake: 43 | vectors = { 44 | 'UP': (0, -1), 45 | 'DOWN': (0, 1), 46 | 'LEFT': (-1, 0), 47 | 'RIGHT': (1, 0), 48 | } 49 | 50 | def __init__(self): 51 | self.segments = [(0, 5), (1, 5), (2, 5), (3, 5), (4, 5), (5, 5)] 52 | self.direction = 'RIGHT' 53 | 54 | def move(self): 55 | vector = self.vectors.get(self.direction, (0, 0)) 56 | # wypadałoby zalogować, że brakuje jakiegos klucza... 57 | self.segments.pop(0) 58 | first_segment = self.segments[-1] 59 | self.segments.append( 60 | # TODO: a może da się sprytniej? Coś z zip? 61 | (first_segment[0] + vector[0], first_segment[1] + vector[1]) 62 | ) 63 | 64 | def draw(self, surface): 65 | for segment in self.segments: 66 | draw_segment(surface, *segment) 67 | 68 | def process_event(self, event): 69 | # A tu jest problem - wąż może zawrócić w miejscu! 70 | if event.type == KEYDOWN: 71 | if event.key == K_LEFT: 72 | self.direction = 'LEFT' 73 | elif event.key == K_RIGHT: 74 | self.direction = 'RIGHT' 75 | elif event.key == K_UP: 76 | self.direction = 'UP' 77 | elif event.key == K_DOWN: 78 | self.direction = 'DOWN' 79 | 80 | 81 | def draw_background(surface): 82 | BLACK = (0, 0, 0) 83 | position = ( 84 | 0, 0, 85 | GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX 86 | ) 87 | pygame.draw.rect(surface, BLACK, position) 88 | 89 | 90 | def run_game(): 91 | pygame.init() 92 | # workaround for: https://github.com/pygame/pygame/issues/331 93 | pygame.mixer.quit() 94 | FPS = 10 # Frames Per Second 95 | fpsClock = pygame.time.Clock() 96 | DISPLAYSURF = pygame.display.set_mode( 97 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 98 | ) 99 | pygame.display.set_caption('Moving segments with snake class') 100 | snake = Snake() 101 | while True: 102 | for event in pygame.event.get(): 103 | print('event: {}'.format(event)) 104 | if event.type == QUIT: 105 | pygame.quit() 106 | sys.exit() 107 | snake.process_event(event) 108 | draw_background(DISPLAYSURF) 109 | snake.draw(DISPLAYSURF) 110 | snake.move() 111 | pygame.display.update() 112 | fpsClock.tick(FPS) 113 | 114 | 115 | if __name__ == '__main__': 116 | run_game() 117 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/09_better_controling_snake.py: -------------------------------------------------------------------------------- 1 | import pygame, sys 2 | from pygame.locals import * 3 | 4 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 5 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 6 | 7 | GAME_CELLS_X = 20 8 | GAME_CELLS_Y = 15 9 | 10 | 11 | def draw_segment(surface, x, y): 12 | """ 13 | :param surface: surface to draw on 14 | :param x: x coord in game cells 15 | :param y: y coord in game cells 16 | :return: 17 | """ 18 | WHITE = (255, 255, 255) 19 | position = ( 20 | x * GAME_CELL_SIZE_PX, 21 | y * GAME_CELL_SIZE_PX, 22 | GAME_CELL_SIZE_PX, 23 | GAME_CELL_SIZE_PX 24 | ) 25 | pygame.draw.rect(surface, WHITE, position) 26 | 27 | 28 | def draw_food(surface, x, y): 29 | """ 30 | :param surface: surface to draw on 31 | :param x: x coord in game cells 32 | :param y: y coord in game cells 33 | :return: 34 | """ 35 | RED = (255, 0, 0) 36 | position = ( 37 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 38 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 39 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 40 | 41 | 42 | class Snake: 43 | vectors = { 44 | 'UP': (0, -1), 45 | 'DOWN': (0, 1), 46 | 'LEFT': (-1, 0), 47 | 'RIGHT': (1, 0), 48 | } 49 | 50 | def __init__(self): 51 | self.segments = [[0, 5], [1, 5], [2, 5], [3, 5], [4, 5], [5, 5]] 52 | self.direction = 'RIGHT' 53 | 54 | def _normalize_segments(self): 55 | for segment in self.segments: 56 | if segment[0] >= GAME_CELLS_X: 57 | segment[0] -= GAME_CELLS_X 58 | if segment[0] < 0: 59 | segment[0] += GAME_CELLS_X 60 | if segment[1] >= GAME_CELLS_Y: 61 | segment[1] -= GAME_CELLS_Y 62 | if segment[1] < 0: 63 | segment[1] += GAME_CELLS_Y 64 | 65 | def move(self): 66 | vector = self.vectors.get(self.direction, (0, 0)) 67 | # wypadałoby zalogować, że brakuje jakiegos klucza... 68 | self.segments.pop(0) 69 | first_segment = self.segments[-1] 70 | self.segments.append( 71 | # TODO: a może da się sprytniej? Coś z zip? 72 | [first_segment[0] + vector[0], first_segment[1] + vector[1]] 73 | ) 74 | self._normalize_segments() 75 | 76 | def draw(self, surface): 77 | for segment in self.segments: 78 | draw_segment(surface, *segment) 79 | 80 | def process_event(self, event): 81 | # te stałe stringi wypadałoby do jakiś constów przenieść 82 | if event.type == KEYDOWN: 83 | if event.key == K_LEFT: 84 | if not self.direction == 'RIGHT': 85 | self.direction = 'LEFT' 86 | elif event.key == K_RIGHT: 87 | if not self.direction == 'LEFT': 88 | self.direction = 'RIGHT' 89 | elif event.key == K_UP: 90 | if not self.direction == 'DOWN': 91 | self.direction = 'UP' 92 | elif event.key == K_DOWN: 93 | if not self.direction == 'UP': 94 | self.direction = 'DOWN' 95 | 96 | 97 | def draw_background(surface): 98 | BLACK = (0, 0, 0) 99 | position = ( 100 | 0, 0, 101 | GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX 102 | ) 103 | pygame.draw.rect(surface, BLACK, position) 104 | 105 | 106 | def run_game(): 107 | pygame.init() 108 | # workaround for: https://github.com/pygame/pygame/issues/331 109 | pygame.mixer.quit() 110 | FPS = 10 # Frames Per Second 111 | fpsClock = pygame.time.Clock() 112 | DISPLAYSURF = pygame.display.set_mode( 113 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 114 | ) 115 | pygame.display.set_caption('Moving segments with snake class') 116 | snake = Snake() 117 | while True: 118 | for event in pygame.event.get(): 119 | print('event: {}'.format(event)) 120 | if event.type == QUIT: 121 | pygame.quit() 122 | sys.exit() 123 | snake.process_event(event) 124 | draw_background(DISPLAYSURF) 125 | snake.draw(DISPLAYSURF) 126 | snake.move() 127 | pygame.display.update() 128 | fpsClock.tick(FPS) 129 | 130 | 131 | if __name__ == '__main__': 132 | run_game() 133 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/10_feed_the_snake.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | import pygame, sys 4 | from pygame.locals import * 5 | 6 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 7 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 8 | 9 | GAME_CELLS_X = 20 10 | GAME_CELLS_Y = 15 11 | 12 | random.seed(a=1) 13 | 14 | 15 | def draw_segment(surface, x, y): 16 | """ 17 | :param surface: surface to draw on 18 | :param x: x coord in game cells 19 | :param y: y coord in game cells 20 | :return: 21 | """ 22 | WHITE = (255, 255, 255) 23 | position = ( 24 | x * GAME_CELL_SIZE_PX, 25 | y * GAME_CELL_SIZE_PX, 26 | GAME_CELL_SIZE_PX, 27 | GAME_CELL_SIZE_PX 28 | ) 29 | pygame.draw.rect(surface, WHITE, position) 30 | 31 | 32 | def draw_food(surface, x, y): 33 | """ 34 | :param surface: surface to draw on 35 | :param x: x coord in game cells 36 | :param y: y coord in game cells 37 | :return: 38 | """ 39 | RED = (255, 0, 0) 40 | position = ( 41 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 42 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 43 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 44 | 45 | 46 | class Snake: 47 | vectors = { 48 | 'UP': (0, -1), 49 | 'DOWN': (0, 1), 50 | 'LEFT': (-1, 0), 51 | 'RIGHT': (1, 0), 52 | } 53 | 54 | def __init__(self, food): 55 | self.segments = [[0, 5], [1, 5], [2, 5], [3, 5], [4, 5], [5, 5]] 56 | self.direction = 'RIGHT' 57 | self.food = food 58 | 59 | def _normalize_segments(self): 60 | for segment in self.segments: 61 | if segment[0] >= GAME_CELLS_X: 62 | segment[0] -= GAME_CELLS_X 63 | if segment[0] < 0: 64 | segment[0] += GAME_CELLS_X 65 | if segment[1] >= GAME_CELLS_Y: 66 | segment[1] -= GAME_CELLS_Y 67 | if segment[1] < 0: 68 | segment[1] += GAME_CELLS_Y 69 | 70 | def move(self): 71 | vector = self.vectors.get(self.direction, (0, 0)) 72 | # wypadałoby zalogować, że brakuje jakiegos klucza... 73 | self.segments.pop(0) 74 | first_segment = self.segments[-1] 75 | self.segments.append( 76 | # TODO: a może da się sprytniej? Coś z zip? 77 | [first_segment[0] + vector[0], first_segment[1] + vector[1]] 78 | ) 79 | self._normalize_segments() 80 | self.try_to_eat() 81 | 82 | def draw(self, surface): 83 | for segment in self.segments: 84 | draw_segment(surface, *segment) 85 | 86 | def process_event(self, event): 87 | # te stałe stringi wypadałoby do jakiś constów przenieść 88 | if event.type == KEYDOWN: 89 | if event.key == K_LEFT: 90 | if not self.direction == 'RIGHT': 91 | self.direction = 'LEFT' 92 | elif event.key == K_RIGHT: 93 | if not self.direction == 'LEFT': 94 | self.direction = 'RIGHT' 95 | elif event.key == K_UP: 96 | if not self.direction == 'DOWN': 97 | self.direction = 'UP' 98 | elif event.key == K_DOWN: 99 | if not self.direction == 'UP': 100 | self.direction = 'DOWN' 101 | 102 | def try_to_eat(self): 103 | if ( 104 | self.segments[-1][0] == self.food.x 105 | and self.segments[-1][1] == self.food.y 106 | ): 107 | self.food.eaten() 108 | 109 | 110 | class FoodProvider: 111 | def __init__(self): 112 | self._get_new_coords() 113 | 114 | def _get_new_coords(self): 115 | self.x = random.randrange(GAME_CELLS_X) 116 | self.y = random.randrange(GAME_CELLS_Y) 117 | 118 | def draw(self, surface): 119 | draw_food(surface, self.x, self.y) 120 | 121 | def eaten(self): 122 | self._get_new_coords() 123 | 124 | 125 | def draw_background(surface): 126 | BLACK = (0, 0, 0) 127 | position = ( 128 | 0, 0, 129 | GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX 130 | ) 131 | pygame.draw.rect(surface, BLACK, position) 132 | 133 | 134 | def run_game(): 135 | pygame.init() 136 | # workaround for: https://github.com/pygame/pygame/issues/331 137 | pygame.mixer.quit() 138 | FPS = 10 # Frames Per Second 139 | fpsClock = pygame.time.Clock() 140 | DISPLAYSURF = pygame.display.set_mode( 141 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 142 | ) 143 | pygame.display.set_caption('Moving segments with snake class') 144 | food = FoodProvider() 145 | snake = Snake(food=food) 146 | while True: 147 | for event in pygame.event.get(): 148 | print('event: {}'.format(event)) 149 | if event.type == QUIT: 150 | pygame.quit() 151 | sys.exit() 152 | snake.process_event(event) 153 | draw_background(DISPLAYSURF) 154 | snake.draw(DISPLAYSURF) 155 | food.draw(DISPLAYSURF) 156 | snake.move() 157 | pygame.display.update() 158 | fpsClock.tick(FPS) 159 | 160 | 161 | if __name__ == '__main__': 162 | run_game() 163 | -------------------------------------------------------------------------------- /warsztat_6/przykłady/11_growing.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | import pygame, sys 4 | from pygame.locals import * 5 | 6 | GAME_CELL_SIZE_PX = 50 # HAVE TO BE EVEN NUMBER 7 | assert (int(GAME_CELL_SIZE_PX/2)*2) == GAME_CELL_SIZE_PX 8 | 9 | GAME_CELLS_X = 20 10 | GAME_CELLS_Y = 15 11 | 12 | random.seed(a=1) 13 | 14 | 15 | def draw_segment(surface, x, y): 16 | """ 17 | :param surface: surface to draw on 18 | :param x: x coord in game cells 19 | :param y: y coord in game cells 20 | :return: 21 | """ 22 | WHITE = (255, 255, 255) 23 | position = ( 24 | x * GAME_CELL_SIZE_PX, 25 | y * GAME_CELL_SIZE_PX, 26 | GAME_CELL_SIZE_PX, 27 | GAME_CELL_SIZE_PX 28 | ) 29 | pygame.draw.rect(surface, WHITE, position) 30 | 31 | 32 | def draw_food(surface, x, y): 33 | """ 34 | :param surface: surface to draw on 35 | :param x: x coord in game cells 36 | :param y: y coord in game cells 37 | :return: 38 | """ 39 | RED = (255, 0, 0) 40 | position = ( 41 | x * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2, 42 | y * GAME_CELL_SIZE_PX + GAME_CELL_SIZE_PX//2) 43 | pygame.draw.circle(surface, RED, position, GAME_CELL_SIZE_PX//2) 44 | 45 | 46 | class Snake: 47 | vectors = { 48 | 'UP': (0, -1), 49 | 'DOWN': (0, 1), 50 | 'LEFT': (-1, 0), 51 | 'RIGHT': (1, 0), 52 | } 53 | 54 | def __init__(self, food): 55 | self.segments = [[0, 5], [1, 5], [2, 5], [3, 5], [4, 5], [5, 5]] 56 | self.direction = 'RIGHT' 57 | self.food = food 58 | 59 | def _normalize_segments(self): 60 | for segment in self.segments: 61 | if segment[0] >= GAME_CELLS_X: 62 | segment[0] -= GAME_CELLS_X 63 | if segment[0] < 0: 64 | segment[0] += GAME_CELLS_X 65 | if segment[1] >= GAME_CELLS_Y: 66 | segment[1] -= GAME_CELLS_Y 67 | if segment[1] < 0: 68 | segment[1] += GAME_CELLS_Y 69 | 70 | def move(self): 71 | vector = self.vectors.get(self.direction, (0, 0)) 72 | # wypadałoby zalogować, że brakuje jakiegos klucza... 73 | first_segment = self.segments[-1] 74 | self.segments.append( 75 | # TODO: a może da się sprytniej? Coś z zip? 76 | [first_segment[0] + vector[0], first_segment[1] + vector[1]] 77 | ) 78 | self._normalize_segments() 79 | if not self.try_to_eat(): 80 | self.segments.pop(0) 81 | 82 | def draw(self, surface): 83 | for segment in self.segments: 84 | draw_segment(surface, *segment) 85 | 86 | def process_event(self, event): 87 | # te stałe stringi wypadałoby do jakiś constów przenieść 88 | if event.type == KEYDOWN: 89 | if event.key == K_LEFT: 90 | if not self.direction == 'RIGHT': 91 | self.direction = 'LEFT' 92 | elif event.key == K_RIGHT: 93 | if not self.direction == 'LEFT': 94 | self.direction = 'RIGHT' 95 | elif event.key == K_UP: 96 | if not self.direction == 'DOWN': 97 | self.direction = 'UP' 98 | elif event.key == K_DOWN: 99 | if not self.direction == 'UP': 100 | self.direction = 'DOWN' 101 | 102 | def try_to_eat(self): 103 | if ( 104 | self.segments[-1][0] == self.food.x 105 | and self.segments[-1][1] == self.food.y 106 | ): 107 | self.food.eaten() 108 | return True 109 | return False 110 | 111 | 112 | class FoodProvider: 113 | def __init__(self): 114 | # A tu jest subtelny bug - możemy postawić jedzenie na wężu!!!!! 115 | self._get_new_coords() 116 | 117 | def _get_new_coords(self): 118 | self.x = random.randrange(GAME_CELLS_X) 119 | self.y = random.randrange(GAME_CELLS_Y) 120 | 121 | def draw(self, surface): 122 | draw_food(surface, self.x, self.y) 123 | 124 | def eaten(self): 125 | self._get_new_coords() 126 | 127 | 128 | def draw_background(surface): 129 | BLACK = (0, 0, 0) 130 | position = ( 131 | 0, 0, 132 | GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX 133 | ) 134 | pygame.draw.rect(surface, BLACK, position) 135 | 136 | 137 | def run_game(): 138 | pygame.init() 139 | # workaround for: https://github.com/pygame/pygame/issues/331 140 | pygame.mixer.quit() 141 | FPS = 10 # Frames Per Second 142 | fpsClock = pygame.time.Clock() 143 | DISPLAYSURF = pygame.display.set_mode( 144 | (GAME_CELLS_X * GAME_CELL_SIZE_PX, GAME_CELLS_Y * GAME_CELL_SIZE_PX) 145 | ) 146 | pygame.display.set_caption('Moving segments with snake class') 147 | food = FoodProvider() 148 | snake = Snake(food=food) 149 | while True: 150 | for event in pygame.event.get(): 151 | print('event: {}'.format(event)) 152 | if event.type == QUIT: 153 | pygame.quit() 154 | sys.exit() 155 | snake.process_event(event) 156 | draw_background(DISPLAYSURF) 157 | snake.draw(DISPLAYSURF) 158 | food.draw(DISPLAYSURF) 159 | snake.move() 160 | pygame.display.update() 161 | fpsClock.tick(FPS) 162 | 163 | 164 | if __name__ == '__main__': 165 | run_game() 166 | -------------------------------------------------------------------------------- /warsztat_7/test_zad01_flatten.py: -------------------------------------------------------------------------------- 1 | from zad01_flatten import flatten 2 | 3 | 4 | def test_flatten_not_nested_list(): 5 | test_list = [1, 2, 3] 6 | 7 | result = flatten(test_list) 8 | 9 | assert result == [1, 2, 3] 10 | 11 | 12 | def test_flatten_nested_list(): 13 | test_list = [1, [2, 3], 4] 14 | 15 | result = flatten(test_list) 16 | 17 | assert result == [1, 2, 3, 4] 18 | 19 | 20 | def test_flatten_empty_list(): 21 | test_list = [] 22 | 23 | result = flatten(test_list) 24 | 25 | assert result == [] 26 | 27 | 28 | def test_flatten_different_nestings(): 29 | test_list = [[1, 2, [3, 4, 5], [6], 7, 8], 9] 30 | 31 | result = flatten(test_list) 32 | 33 | assert result == [1, 2, 3, 4, 5, 6, 7, 8, 9] 34 | -------------------------------------------------------------------------------- /warsztat_7/test_zad02_a_bank_account.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from zad02_bank_account import ( 4 | BankAccount, 5 | NotEnoughMoney, 6 | ) 7 | 8 | 9 | def test_bank_account_starting_amount_is_0(): 10 | bank_account = BankAccount() 11 | 12 | assert bank_account.get_balance() == 0 13 | 14 | 15 | def test_deposit_200(): 16 | bank_account = BankAccount() 17 | 18 | bank_account.deposit(200) 19 | 20 | assert bank_account.get_balance() == 200 21 | 22 | 23 | def test_deposit_300(): 24 | bank_account = BankAccount() 25 | 26 | bank_account.deposit(300) 27 | 28 | assert bank_account.get_balance() == 300 29 | 30 | def test_deposit_more_than_once(): 31 | bank_account = BankAccount() 32 | bank_account.deposit(100) 33 | 34 | bank_account.deposit(200) 35 | 36 | assert bank_account.get_balance() == 300 37 | 38 | 39 | def test_withdraw_some_money(): 40 | bank_account = BankAccount() 41 | bank_account.deposit(200) 42 | 43 | bank_account.withdraw(100) 44 | 45 | assert bank_account.get_balance() == 100 46 | 47 | 48 | def test_withdraw_some_money_2(): 49 | bank_account = BankAccount() 50 | bank_account.deposit(200) 51 | 52 | bank_account.withdraw(50) 53 | 54 | assert bank_account.get_balance() == 150 55 | 56 | 57 | def test_withdraw_when_balance_is_zero(): 58 | bank_account = BankAccount() 59 | 60 | with pytest.raises(NotEnoughMoney): 61 | bank_account.withdraw(50) 62 | 63 | 64 | def test_withdraw_when_not_not_enough_money_on_account(): 65 | bank_account = BankAccount() 66 | bank_account.deposit(200) 67 | 68 | with pytest.raises(NotEnoughMoney): 69 | bank_account.withdraw(201) 70 | 71 | 72 | def test_withdraw_all_money(): 73 | bank_account = BankAccount() 74 | bank_account.deposit(200) 75 | 76 | bank_account.withdraw(200) 77 | 78 | assert bank_account.get_balance() == 0 79 | 80 | 81 | -------------------------------------------------------------------------------- /warsztat_7/test_zad02_b_test_bank_account_fixtures.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from zad02_bank_account import ( 4 | BankAccount, 5 | NotEnoughMoney, 6 | ) 7 | 8 | 9 | @pytest.fixture 10 | def bank_account(): 11 | """ 12 | Zwraca zainicjowany obiekt konta bankowego. 13 | """ 14 | return BankAccount() 15 | 16 | 17 | def test_bank_account_starting_amount_is_0(bank_account): 18 | assert bank_account.get_balance() == 0 19 | 20 | 21 | def test_deposit_200(bank_account): 22 | bank_account.deposit(200) 23 | 24 | assert bank_account.get_balance() == 200 25 | 26 | 27 | def test_deposit_300(bank_account): 28 | bank_account.deposit(300) 29 | 30 | assert bank_account.get_balance() == 300 31 | 32 | def test_deposit_more_than_once(bank_account): 33 | bank_account.deposit(100) 34 | 35 | bank_account.deposit(200) 36 | 37 | assert bank_account.get_balance() == 300 38 | 39 | 40 | def test_withdraw_some_money(bank_account): 41 | bank_account.deposit(200) 42 | 43 | bank_account.withdraw(100) 44 | 45 | assert bank_account.get_balance() == 100 46 | 47 | 48 | def test_withdraw_some_money_2(bank_account): 49 | bank_account.deposit(200) 50 | 51 | bank_account.withdraw(50) 52 | 53 | assert bank_account.get_balance() == 150 54 | 55 | 56 | def test_withdraw_when_balance_is_zero(bank_account): 57 | with pytest.raises(NotEnoughMoney): 58 | bank_account.withdraw(50) 59 | 60 | 61 | def test_withdraw_when_not_not_enough_money_on_account(bank_account): 62 | bank_account.deposit(200) 63 | 64 | with pytest.raises(NotEnoughMoney): 65 | bank_account.withdraw(201) 66 | 67 | 68 | def test_withdraw_all_money(bank_account): 69 | bank_account.deposit(200) 70 | 71 | bank_account.withdraw(200) 72 | 73 | assert bank_account.get_balance() == 0 74 | 75 | 76 | -------------------------------------------------------------------------------- /warsztat_7/test_zad03_test_bank_account_with_promo.py: -------------------------------------------------------------------------------- 1 | import random 2 | from unittest.mock import patch 3 | 4 | import pytest 5 | 6 | from zad03_bank_account_with_promo import ( 7 | BankAccount, 8 | NotEnoughMoney, 9 | ) 10 | 11 | 12 | @pytest.fixture 13 | def bank_account(): 14 | """ 15 | Zwraca zainicjowany obiekt konta bankowego. 16 | """ 17 | return BankAccount() 18 | 19 | 20 | def test_bank_account_starting_amount_is_0(bank_account): 21 | assert bank_account.get_balance() == 0 22 | 23 | 24 | def test_deposit_200(bank_account): 25 | bank_account.deposit(200) 26 | 27 | assert bank_account.get_balance() == 200 28 | 29 | 30 | def test_deposit_300(bank_account): 31 | bank_account.deposit(300) 32 | 33 | assert bank_account.get_balance() == 300 34 | 35 | def test_deposit_more_than_once(bank_account): 36 | bank_account.deposit(100) 37 | 38 | bank_account.deposit(200) 39 | 40 | assert bank_account.get_balance() == 300 41 | 42 | 43 | def test_withdraw_some_money(bank_account): 44 | bank_account.deposit(200) 45 | 46 | bank_account.withdraw(100) 47 | 48 | assert bank_account.get_balance() == 100 49 | 50 | 51 | def test_withdraw_some_money_2(bank_account): 52 | bank_account.deposit(200) 53 | 54 | bank_account.withdraw(50) 55 | 56 | assert bank_account.get_balance() == 150 57 | 58 | 59 | def test_withdraw_when_balance_is_zero(bank_account): 60 | with pytest.raises(NotEnoughMoney): 61 | bank_account.withdraw(50) 62 | 63 | 64 | def test_withdraw_when_not_not_enough_money_on_account(bank_account): 65 | bank_account.deposit(200) 66 | 67 | with pytest.raises(NotEnoughMoney): 68 | bank_account.withdraw(201) 69 | 70 | 71 | def test_withdraw_all_money(bank_account): 72 | bank_account.deposit(200) 73 | 74 | bank_account.withdraw(200) 75 | 76 | assert bank_account.get_balance() == 0 77 | 78 | 79 | def test_deposit_with_promo(bank_account): 80 | with patch('random.random') as mock_random: 81 | mock_random.return_value = 0.05 82 | bank_account.deposit(100, with_promo=True) 83 | 84 | assert bank_account.get_balance() == 101 85 | 86 | 87 | def test_deposit_with_promo_2(bank_account): 88 | with patch('random.random') as mock_random: 89 | mock_random.return_value = 0.05 90 | bank_account.deposit(200, with_promo=True) 91 | 92 | assert bank_account.get_balance() == 201 93 | 94 | def test_deposit_with_promo_3(bank_account): 95 | with patch('random.random') as mock_random: 96 | mock_random.return_value = 0.0999 97 | bank_account.deposit(300, with_promo=True) 98 | 99 | assert bank_account.get_balance() == 301 100 | 101 | 102 | def test_deposit_with_promo_no_luck(bank_account): 103 | with patch('random.random') as mock_random: 104 | mock_random.return_value = 0.2 105 | bank_account.deposit(100, with_promo=True) 106 | 107 | assert bank_account.get_balance() == 100 108 | 109 | 110 | def test_deposit_with_promo_no_luck_2(bank_account): 111 | with patch('random.random') as mock_random: 112 | mock_random.return_value = 0.1 113 | bank_account.deposit(100, with_promo=True) 114 | 115 | assert bank_account.get_balance() == 100 116 | -------------------------------------------------------------------------------- /warsztat_7/testowanie.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "slideshow": { 7 | "slide_type": "slide" 8 | } 9 | }, 10 | "source": [ 11 | "# Testowanie\n", 12 | "## Jakub Szponder\n", 13 | "### 07.12.2017, Python 4 Beginners" 14 | ] 15 | }, 16 | { 17 | "cell_type": "markdown", 18 | "metadata": { 19 | "slideshow": { 20 | "slide_type": "subslide" 21 | } 22 | }, 23 | "source": [ 24 | "# Testowanie kodu jest ważne" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "metadata": { 30 | "slideshow": { 31 | "slide_type": "slide" 32 | } 33 | }, 34 | "source": [ 35 | "# Co to jest testowanie?\n", 36 | "- uruchamianie kodu naszego programu w celu sprawdzenia, czy robi to, co powinien\n", 37 | "\n" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": { 43 | "slideshow": { 44 | "slide_type": "fragment" 45 | } 46 | }, 47 | "source": [ 48 | "### Program testing can be used to show the presence of bugs, but never to show their absence!\n", 49 | "Edsker D. Dijkstra (1970)" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": { 55 | "slideshow": { 56 | "slide_type": "subslide" 57 | } 58 | }, 59 | "source": [ 60 | "# Testy automatyczne \n", 61 | "- dodatkowe fragmenty kodu, które uruchamiają nasz główny kod, a następnie porównują wyniki z oczekiwaniami\n", 62 | "- szybko się je odpala\n", 63 | "- są powtarzalne\n", 64 | "- wszyscy z zespołu są w stanie powtórzyć test\n", 65 | "- tylko tym rodzajem testów będziemy się dzisiaj zajmować" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": { 71 | "slideshow": { 72 | "slide_type": "subslide" 73 | } 74 | }, 75 | "source": [ 76 | "# Debugowanie\n", 77 | "- proces szukania błędu w kodzie, a następnie naprawiania go" 78 | ] 79 | }, 80 | { 81 | "cell_type": "markdown", 82 | "metadata": { 83 | "slideshow": { 84 | "slide_type": "slide" 85 | } 86 | }, 87 | "source": [ 88 | "# Dlaczego testujemy\n", 89 | "- testowanie pozwala upewnić się, że w wybranych przez nas warunkach wszystko działa tak jak chcemy\n", 90 | "- zmniejsza strach przed zmianami\n", 91 | "- łatwiejsze niż debugowanie!" 92 | ] 93 | }, 94 | { 95 | "cell_type": "markdown", 96 | "metadata": { 97 | "slideshow": { 98 | "slide_type": "slide" 99 | } 100 | }, 101 | "source": [ 102 | "1. Tworzymy nowy virtualenv\n", 103 | "2. Aktywujemy go\n", 104 | "3. Instalujemy z pip __pytest__" 105 | ] 106 | }, 107 | { 108 | "cell_type": "markdown", 109 | "metadata": { 110 | "slideshow": { 111 | "slide_type": "subslide" 112 | } 113 | }, 114 | "source": [ 115 | "Tworzymy nowy virtualenv:\n", 116 | "```\n", 117 | "mkdir testing_venv\n", 118 | "python3.6 -m venv testing_venv\n", 119 | "```" 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": { 125 | "slideshow": { 126 | "slide_type": "subslide" 127 | } 128 | }, 129 | "source": [ 130 | "Aktywowanie na Linux/Mac:\n", 131 | "```\n", 132 | "source testing_vent/bin/activate\n", 133 | "```\n", 134 | "Aktywowanie na Windows:\n", 135 | "```\n", 136 | "testing_venv\\Scripts\\activate\n", 137 | "```" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": { 143 | "slideshow": { 144 | "slide_type": "subslide" 145 | } 146 | }, 147 | "source": [ 148 | "Instalacja pytest\n", 149 | "```\n", 150 | "pip install pytest\n", 151 | "```" 152 | ] 153 | }, 154 | { 155 | "cell_type": "markdown", 156 | "metadata": { 157 | "slideshow": { 158 | "slide_type": "slide" 159 | } 160 | }, 161 | "source": [ 162 | "Framework do testowania:\n", 163 | "- ułatwia pisanie i organizację testów\n", 164 | "- daje narzędzie do odpalania i wyszukiwania testów\n", 165 | "- wyświetla wyniki w ładnej formie\n", 166 | "\n", 167 | "Przykład:\n", 168 | "- __pytest__ - zewnętrzna paczka, pozwala pisać ładniejsze testy\n", 169 | "\n", 170 | "http://pythontesting.net/framework/pytest/pytest-introduction/" 171 | ] 172 | }, 173 | { 174 | "cell_type": "markdown", 175 | "metadata": { 176 | "slideshow": { 177 | "slide_type": "subslide" 178 | } 179 | }, 180 | "source": [ 181 | "# pytest\n", 182 | "- rozbudowany framework do testowania\n", 183 | "- aktywnie rozwijany zarówno dla pythona 3 jak i pythona 2\n", 184 | "- najlepszy aktualnie wybór" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": { 190 | "slideshow": { 191 | "slide_type": "slide" 192 | } 193 | }, 194 | "source": [ 195 | "# Zadanie\n", 196 | "Napisać funkcję __flatten__, która dostaję listę zagnieżdżonych list i zwraca je jako listę na jednym poziomie.\n", 197 | "\n", 198 | "np. flatten([1, 2, 3, [4, 5]]) == [1, 2, 3, 4, 5]" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 7, 204 | "metadata": { 205 | "slideshow": { 206 | "slide_type": "subslide" 207 | } 208 | }, 209 | "outputs": [], 210 | "source": [ 211 | "def flatten(element):\n", 212 | " return list(flatten_gen(element))\n", 213 | "\n", 214 | "\n", 215 | "def flatten_gen(element):\n", 216 | " for e in element:\n", 217 | " if isinstance(e, list):\n", 218 | " for e_elem in flatten_gen(e):\n", 219 | " yield e_elem\n", 220 | " else:\n", 221 | " yield e\n" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": null, 227 | "metadata": { 228 | "slideshow": { 229 | "slide_type": "subslide" 230 | } 231 | }, 232 | "outputs": [], 233 | "source": [ 234 | "def test_flatten_not_nested_list():\n", 235 | " test_list = [1, 2, 3]\n", 236 | "\n", 237 | " result = flatten(test_list)\n", 238 | "\n", 239 | " assert result == [1, 2, 3]\n", 240 | "\n", 241 | "\n", 242 | "def test_flatten_nested_list():\n", 243 | " test_list = [1, [2, 3], 4]\n", 244 | "\n", 245 | " result = flatten(test_list)\n", 246 | "\n", 247 | " assert result == [1, 2, 3, 4]\n", 248 | "\n", 249 | "\n", 250 | "def test_flatten_empty_list():\n", 251 | " test_list = []\n", 252 | "\n", 253 | " result = flatten(test_list)\n", 254 | "\n", 255 | " assert result == []\n", 256 | "\n", 257 | "\n", 258 | "def test_flatten_different_nestings():\n", 259 | " test_list = [[1, 2, [3, 4, 5], [6], 7, 8], 9]\n", 260 | "\n", 261 | " result = flatten(test_list)\n", 262 | "\n", 263 | " assert result == [1, 2, 3, 4, 5, 6, 7, 8, 9]" 264 | ] 265 | }, 266 | { 267 | "cell_type": "markdown", 268 | "metadata": { 269 | "slideshow": { 270 | "slide_type": "slide" 271 | } 272 | }, 273 | "source": [ 274 | "# Test Driven Development (TDD)\n", 275 | "1. napisać nieprzechodzący test\n", 276 | "2. zmienić kod w najłatwiejszy możliwy sposób żeby test przeszedł\n", 277 | "3. zrobić refactor" 278 | ] 279 | }, 280 | { 281 | "cell_type": "markdown", 282 | "metadata": { 283 | "slideshow": { 284 | "slide_type": "subslide" 285 | } 286 | }, 287 | "source": [ 288 | "# Refaktoryzacja\n", 289 | "- zmiana struktury programu bez zmiany jego funkcjonalności\n", 290 | "- ma na celu poprawę jakości kodu" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": { 296 | "slideshow": { 297 | "slide_type": "slide" 298 | } 299 | }, 300 | "source": [ 301 | "# Zadanie\n", 302 | "\n", 303 | "Napisać klasę BankAccount (konto bankowe). Ma udostępniać trzy metody: \n", 304 | "- get_current_balance - zwracającą aktualny stan konta\n", 305 | "- deposit - dodającą pieniądze do konta\n", 306 | "- withdraw - zabierającą pieniądze z konta\n", 307 | "\n", 308 | "Zastosować TDD!" 309 | ] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": { 314 | "slideshow": { 315 | "slide_type": "slide" 316 | } 317 | }, 318 | "source": [ 319 | "# Dobre testy\n", 320 | "- szybkie\n", 321 | "- zautomatyzonwane\n", 322 | "- przewidywalne\n", 323 | "- dające dobrą informację zwrotną\n", 324 | "- skupiające się na jednym aspekcie na raz\n", 325 | "- dobrze izolowane" 326 | ] 327 | }, 328 | { 329 | "cell_type": "markdown", 330 | "metadata": { 331 | "slideshow": { 332 | "slide_type": "subslide" 333 | } 334 | }, 335 | "source": [ 336 | "# Izolacja testów\n", 337 | "- testy nie powinny mieć wpływu na siebie nawzajem\n", 338 | "- błąd w jednym teście ne przerywa wykonania testów\n", 339 | "- każdy test powinien przejść zarówno odpalany pojedynczo jak i w grupie" 340 | ] 341 | }, 342 | { 343 | "cell_type": "markdown", 344 | "metadata": { 345 | "slideshow": { 346 | "slide_type": "slide" 347 | } 348 | }, 349 | "source": [ 350 | "# Fixtures\n", 351 | "pytestowy sposób na skrócenie kodu testów i ograniczenie zduplikowanego kodu" 352 | ] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "execution_count": 11, 357 | "metadata": { 358 | "slideshow": { 359 | "slide_type": "fragment" 360 | } 361 | }, 362 | "outputs": [], 363 | "source": [ 364 | "import pytest\n", 365 | "\n", 366 | "@pytest.fixture\n", 367 | "def my_list():\n", 368 | " return [1, 2, 3, 4, 5]\n", 369 | "\n", 370 | "def test_append(my_list):\n", 371 | " my_list.append(6)\n", 372 | " \n", 373 | " assert my_list == [1, 2, 3, 4, 5, 6]\n" 374 | ] 375 | }, 376 | { 377 | "cell_type": "markdown", 378 | "metadata": { 379 | "slideshow": { 380 | "slide_type": "slide" 381 | } 382 | }, 383 | "source": [ 384 | "# Zadanie\n", 385 | "Rozszerzyć klasę BankAccount o obsługę promocji.\n", 386 | "\n", 387 | "Promocja polega na tym, że w przypadku wpłacania pieniędzy do banku, wpłacający ma 10% szans na otrzymanie dodatkowej złotówki." 388 | ] 389 | }, 390 | { 391 | "cell_type": "markdown", 392 | "metadata": { 393 | "slideshow": { 394 | "slide_type": "subslide" 395 | } 396 | }, 397 | "source": [ 398 | "# Mock\n", 399 | "- zachowuje się jak dowolny obiekt\n", 400 | "- zapisuje co się z nim dzieje (jakie akcje sę na nim wykonywane itp)\n", 401 | "- można na tym potem wywoływać asserty\n", 402 | "- łatwiej popsuć testy, bo polegamy na dokładnej implementacji danego kawałka\n", 403 | "\n", 404 | "\n", 405 | "https://docs.python.org/3/library/unittest.mock.html" 406 | ] 407 | }, 408 | { 409 | "cell_type": "code", 410 | "execution_count": 8, 411 | "metadata": { 412 | "slideshow": { 413 | "slide_type": "subslide" 414 | } 415 | }, 416 | "outputs": [ 417 | { 418 | "name": "stdout", 419 | "output_type": "stream", 420 | "text": [ 421 | "Przed mockowaniem\n", 422 | "0.8234714723494972\n", 423 | "0.8263488923710834\n", 424 | "0.0890493109094096\n", 425 | "Zamockowany random\n", 426 | "0.05\n", 427 | "0.05\n", 428 | "0.05\n", 429 | "Po mockowaniu\n", 430 | "0.1416876662261768\n", 431 | "0.8828365501612419\n", 432 | "0.37485739451984523\n" 433 | ] 434 | } 435 | ], 436 | "source": [ 437 | "import random\n", 438 | "from unittest.mock import patch\n", 439 | "\n", 440 | "print('Przed mockowaniem')\n", 441 | "for i in range(3):\n", 442 | " print(random.random())\n", 443 | "\n", 444 | "with patch('random.random') as mock_random:\n", 445 | " print('Zamockowany random')\n", 446 | " mock_random.return_value = 0.05\n", 447 | " for i in range(3):\n", 448 | " print(random.random())\n", 449 | " \n", 450 | "print('Po mockowaniu')\n", 451 | "for i in range(3):\n", 452 | " print(random.random())\n" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": { 458 | "slideshow": { 459 | "slide_type": "slide" 460 | } 461 | }, 462 | "source": [ 463 | "# Debugowanie - jak sobie z tym radzić\n", 464 | "- najprostszy sposób - wstawianie printów do kodu\n", 465 | "- lepszy sposób - użycie interaktywnego debuggera" 466 | ] 467 | }, 468 | { 469 | "cell_type": "markdown", 470 | "metadata": { 471 | "slideshow": { 472 | "slide_type": "fragment" 473 | } 474 | }, 475 | "source": [ 476 | "Debugger jest dostępny w bibliotece standardowej:\n", 477 | "\n", 478 | "https://docs.python.org/3.6/library/pdb.html\n", 479 | "\n", 480 | "https://github.com/nblock/pdb-cheatsheet" 481 | ] 482 | }, 483 | { 484 | "cell_type": "code", 485 | "execution_count": 9, 486 | "metadata": { 487 | "slideshow": { 488 | "slide_type": "subslide" 489 | } 490 | }, 491 | "outputs": [], 492 | "source": [ 493 | "def test_function():\n", 494 | " ...\n", 495 | " import pdb;pdb.set_trace()" 496 | ] 497 | }, 498 | { 499 | "cell_type": "markdown", 500 | "metadata": { 501 | "slideshow": { 502 | "slide_type": "subslide" 503 | } 504 | }, 505 | "source": [ 506 | "# Zadanie\n", 507 | "\n", 508 | "Zlokalizować błędy w pliku ugly_roman_numbers.py. Wiemy, że:\n", 509 | "- źle działa dla liczby 4\n", 510 | "- źle działa dla liczby 1479" 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": { 516 | "slideshow": { 517 | "slide_type": "slide" 518 | } 519 | }, 520 | "source": [ 521 | "# Materiały do samodzielnej nauki po zakończeniu kursu\n", 522 | "\n", 523 | "- https://www.packtpub.com/packt/offers/free-learning - codziennie inny darmowy ebook, często pythonowe\n", 524 | "- https://www.codingame.com/start - różnorodne zadania programistyczne\n", 525 | "- https://www.hackerrank.com/ - j/w\n", 526 | "- https://codility.com/programmers/lessons/1-iterations/ - podstawy algorytmiki\n", 527 | "- http://shop.oreilly.com/product/0636920032519.do - dobra książka o pythonie\n", 528 | "- https://www.udacity.com/course/design-of-computer-programs--cs212 - kurs projektowania programów\n", 529 | "- https://www.learnpython.org/ - podstawy pythona, interaktywne zadania\n", 530 | "- https://www.reddit.com/r/learnprogramming/wiki/index - subreddit dla uczących się programować\n", 531 | "- https://www.analyticsvidhya.com/learning-paths-data-science-business-analytics-business-intelligence-big-data/learning-path-data-science-python/ - plan nauki data science\n", 532 | "- https://www.fullstackpython.com - baza wiedzy o aplikacjach webowych\n", 533 | "- https://www.udacity.com/course/programming-foundations-with-python--ud036 - kurs podstawowy\n", 534 | "- https://www.udacity.com/course/introduction-to-python--ud1110 - kurs podstawowy/powtórzenie z zajęć\n", 535 | "- https://www.udacity.com/learn/python - sporo linków z dodatkowymi źródłami\n", 536 | "- https://automatetheboringstuff.com/ - sporo praktycznych zastosowań pythona\n", 537 | "- https://docs.djangoproject.com/en/2.0/intro/tutorial01/ - tutorial django, stworzenie pierwszej aplikacji webowej\n", 538 | "- https://www.apress.com/la/book/9781430227571 - zaawansowana książka o pythonie" 539 | ] 540 | }, 541 | { 542 | "cell_type": "markdown", 543 | "metadata": { 544 | "slideshow": { 545 | "slide_type": "subslide" 546 | } 547 | }, 548 | "source": [ 549 | "# Najlepiej wymyślić sobie jakiś projekt do zaprogramowania ;)" 550 | ] 551 | } 552 | ], 553 | "metadata": { 554 | "celltoolbar": "Slideshow", 555 | "kernelspec": { 556 | "display_name": "Python 3", 557 | "language": "python", 558 | "name": "python3" 559 | }, 560 | "language_info": { 561 | "codemirror_mode": { 562 | "name": "ipython", 563 | "version": 3 564 | }, 565 | "file_extension": ".py", 566 | "mimetype": "text/x-python", 567 | "name": "python", 568 | "nbconvert_exporter": "python", 569 | "pygments_lexer": "ipython3", 570 | "version": "3.6.3" 571 | } 572 | }, 573 | "nbformat": 4, 574 | "nbformat_minor": 2 575 | } 576 | -------------------------------------------------------------------------------- /warsztat_7/zad01_flatten.py: -------------------------------------------------------------------------------- 1 | def flatten(element): 2 | return list(flatten_gen(element)) 3 | 4 | 5 | def flatten_gen(element): 6 | for e in element: 7 | if isinstance(e, list): 8 | for e_elem in flatten_gen(e): 9 | yield e_elem 10 | else: 11 | yield e 12 | -------------------------------------------------------------------------------- /warsztat_7/zad02_bank_account.py: -------------------------------------------------------------------------------- 1 | class BankAccount: 2 | def __init__(self): 3 | self.balance = 0 4 | 5 | def get_balance(self): 6 | return self.balance 7 | 8 | def deposit(self, amount): 9 | self.balance += amount 10 | 11 | def withdraw(self, amount): 12 | if self.balance < amount: 13 | raise NotEnoughMoney() 14 | self.balance -= amount 15 | 16 | 17 | class NotEnoughMoney(Exception): 18 | pass 19 | -------------------------------------------------------------------------------- /warsztat_7/zad03_bank_account_with_promo.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | class BankAccount: 4 | def __init__(self): 5 | self.balance = 0 6 | 7 | def get_balance(self): 8 | return self.balance 9 | 10 | def deposit(self, amount, with_promo=False): 11 | self.balance += amount 12 | if with_promo and random.random() < 0.1: 13 | self.balance += 1 14 | 15 | def withdraw(self, amount): 16 | if self.balance < amount: 17 | raise NotEnoughMoney() 18 | self.balance -= amount 19 | 20 | 21 | class NotEnoughMoney(Exception): 22 | pass 23 | -------------------------------------------------------------------------------- /warsztat_7/zad04_ugly_roman_numbers.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | # UWAGA! Ten kod jest specjalnie napisany brzydko :) 4 | 5 | 6 | def get_roman_number(arabic): 7 | number_m = get_m(arabic) 8 | arabic -= 1000 * len(number_m) 9 | number_d = get_d(arabic) 10 | arabic -= 500 * len(number_d) 11 | number_c = get_c(arabic) 12 | arabic -= 100 * len(number_c) 13 | number_l = get_l(arabic) 14 | arabic -= 50 * len(number_l) 15 | number_x = get_x(arabic) 16 | arabic -= 10 * len(number_x) 17 | number_v = get_v(arabic) 18 | arabic -= 5 * len(number_v) 19 | number_i = get_i(arabic) 20 | number_m, number_d, number_c, number_l, number_x, number_v, number_i = ( 21 | do_magic(number_m, number_d, number_c, number_l, number_x, number_v, number_i)) 22 | return number_m + number_d + number_c + number_l + number_x + number_v + number_i 23 | 24 | 25 | def get_m(arabic): 26 | number_m = arabic // 1000 27 | return 'M' * number_m 28 | 29 | 30 | def get_d(arabic): 31 | number_d = arabic // 500 32 | return 'D' * number_d 33 | 34 | 35 | def get_c(arabic): 36 | number_c = arabic // 100 37 | return 'C' * number_c 38 | 39 | 40 | def get_l(arabic): 41 | number_l = arabic // 50 42 | return 'L' * number_l 43 | 44 | 45 | def get_x(arabic): 46 | number_x = arabic // 10 47 | return 'X' * number_x 48 | 49 | 50 | def get_v(arabic): 51 | number_v = arabic // 5 52 | return 'V' * number_v 53 | 54 | 55 | def get_i(arabic): 56 | number_i = arabic 57 | return 'I' * number_i 58 | 59 | def do_magic(number_m, number_d, number_c, number_l, 60 | number_x, number_v, number_i): 61 | if len(number_c) == 4 and len(number_d) == 1: 62 | number_d = '' 63 | number_c = 'CM' 64 | elif len(number_c) == 4 and len(number_d) == 0: 65 | number_d = '' 66 | number_c = 'CD' 67 | if len(number_x) == 4 and len(number_l) == 1: 68 | number_l = '' 69 | number_x = 'XC' 70 | elif len(number_x) == 4 and len(number_l) == 0: 71 | number_l = '' 72 | number_x = 'XL' 73 | if len(number_i) == 4 and len(number_v) == 1: 74 | number_i = '' 75 | number_v = 'IX', 76 | elif len(number_i) == 4 and len(number_v) == 0: 77 | number_ii = 'IV' 78 | return (number_m, number_d, number_c, number_l, 79 | number_x, number_v, number_i) 80 | 81 | 82 | num = input() 83 | roman = get_roman_number(int(num)) 84 | print(roman) 85 | --------------------------------------------------------------------------------