# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Lekcja 3: Instrukcje warunkowe

# ## Spis treści

# <a href="#1">1. Przypomnienie: Typ danych `bool`, operatory porównania, operatory logiczne</a>
#
#
# - <a href="#1.1">1.1. Operatory porównania</a>
#
#
# - <a href="#1.2">1.2. Operatory logiczne - logiczne zdania złożone</a>
#
#
# <a href="#2">2. Instrukcje warunkowe</a>
#
#
# - <a href="#2.1">2.1. Instrukcja `if`</a>
#
#
# - <a href="#2.2">2.2. Instrukcja `if` - `else`</a>
#
#
# - <a href="#2.3">2.3. Instrukcja `if` - `elif` - `elif` - ... - `elif` - `else`</a>
#
#
# - <a href="#2.4">2.4. Warunki zagnieżdżone</a>
#
#
# <a href="#3">3. Zadania domowe</a>

# ## <a id="1"></a>1. Przypomnienie: Typ danych `bool`, operatory porównania, operatory logiczne

# W tej lekcji skupimy się na dwóch kwestiach:
#
# - Dowiedzieliśmy się podczas Lekcji 2 o typie danych Boolean (`bool`), opisującym zdania logiczne. Np. wyrażenie `(2 < 5)` jest zdaniem logicznym "2 jest mniejsze niż 5", które jest prawdziwe - mówimy, że jego wartość logiczna to "prawda", w Pythonie oznaczana przez słowo kluczowe `True`. Całe to zdanie jest odrębnym obiektem, "bytem", właśnie typu Boolean. Możemy w szczególności wartość takiego obiektu przypisać do zmiennej, np. `check = (2 < 5)`, i teraz `check` to zmienna typu `bool` o wartości `True`. (Pamiętamy, że moglibyśmy to napisać też bez nawiasów, `check = 2 < 5`, jako że Python najpierw wykonuje obliczenie po prawej stronie operatora przypisania `=`, a dopiero na końcu jego wynik podstawia do zmiennej.) Możemy pokusić się teraz o zdecydowane rozszerzenie funkcjonalności naszych programów - aby nasz program mógł podejmować jakieś, mniej lub bardziej złożone, decyzje, na podstawie warunków logicznych - "jeśli to zdanie logiczne jest prawdziwe, wykonaj następujący fragment kodu". Konstrukcje takie noszą nazwę **instrukcji warunkowych** ("conditional statements") i budowane są za pomocą słów kluczowych `if`, `else`, `elif`.
#
# - Druga kwestia jest bardziej techniczna: Do tej pory nasze programy były dość proste - były po prostu sekwencją wyrażeń zapisanych jedno po drugim, każde w nowej linijce. Interpreter Pythona przechodził przez taki kod linijka po linijce i wykonywał zawarte w nich instrukcje - można powiedzieć w sposób "linearny". Dowiemy się dzisiaj, że wszystkie takie programy były tak naprawdę pojedynczym **blokiem kodu** ("code block"). W kontekście instrukcji warunkowych będziemy mieć natomiast do czynienia z wieloma "rozgałęzionymi" blokami kodu, typu - "jeśli to zdanie jest prawdziwe, wykonaj następujący blok kodu; w przeciwnym razie, wykonaj inny blok kodu". Interpreter sprawdza wówczas prawdziwość danego warunku (zdania logicznego) i wykonuje tylko jeden blok kodu - na odpowiedniej "gałęzi" warunku logicznego. Dowiemy się także o tym, jak w Pythonie oznaczać blok kodu - poprzez **wcięcie** ("indentation") kodu od lewej strony złożone z czterech spacji.

# ### <a id="1.1"></a>1.1. Operatory porównania

# Przypomnijmy sobie teraz szybko to, co dowiedziliśmy się o typie danych `bool`. Podstawową metodą konstrukcji zdań logicznych jest użycie operatorów porównania, które tu sobie znowu wylistujmy:
#
# | Operator | Działanieh |
# | --- | --- |
# | <center>`==`</center> | <center>równe</center> |
# | <center>`!=`</center> | <center>różne</center> |
# | <center>`>`</center> | <center>większe niż</center> |
# | <center>`<`</center> | <center>mniejsze niż</center> |
# | <center>`>=`</center> | <center>większe lub równe niż</center> |
# | <center>`<=`</center> | <center>mniejsze lub równe niż</center> |
#
# Podkreślmy raz jeszcze, iż operatorem równości jest `==`, natomiast `=` jest operatorem przypisania do zmiennej. Zatem `x == 5` jest zdaniem logicznym "wartość zmiennej `x` jest równa 5" (może być ono prawdziwe bądź fałszywe, w zależności od wartości zmiennej `x`); natomiast `x = 5` jest instrukcją przypisania do zmiennej `x` wartości 5.
#
# Operatory te zdefiniowane są dla typów numerycznych (`int`, `float` - gdzie oznaczają znajome porównania arytmetyczne), a także dla typu tekstowego (`str` - gdzie odnoszą się do porządku leksykograficznego). Np.:

5 > 7

'HAniA' == 'Hania'

# Możemy porównywać też całe wyrażenia, np.:

5 * 6 + 1 > 45 / 2

'HAniA'.lower() == 'Hania'.lower()

# ... gdyż Python najpierw wykonuje obliczenia, otrzymując ostateczną wartość każdego wyrażenia, a dopiero na końcu dokonuje porównania.

# Możemy oczywiście też porównywać wartości opisane przez zmienne, np.:

# +
x = 5 * 6
y = 23 - 1

x != y # x ma wartość 30, y ma wartość 22, zatem zdanie "x jest różne od y" jest prawdziwe
# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Szybkie ćwiczenie 1: Zdefiniuj zmienną `name`, do którego przypiszesz jakiś string, np. `'Ania'`. Napisz zdanie logiczne sprawdzające, czy imię w zmiennej `name` zgadza się z imieniem "Ola" (jest to imię pani porucznik MO, współpracującej z kpt. Żbikiem w historii "Kryptonim >>Walizka<<").

# +
# szybkie ćwiczenie 1 - rozwiązanie


# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Szybkie ćwiczenie 2: Zdefiniuj zmienną `num`, do której przypisz jakąś liczbę całkowitą. Napisz zdanie logiczne sprawdzające, czy jest ona parzysta - wypisz tę informację dla użytkownika w postaci "Liczba <...> jest parzysta: <...>".
#
# Wskazówka: Pamiętaj o operatorze reszty z dzielenia `%`. Do samego drukowania wykorzystaj jedną z poznanych metod wypisywania stringów (konkatenację za pomocą operatora `+`, metodę `format`, bądź interpolację stringów).

# +
# szybkie ćwiczenie 2 - rozwiązanie


# -

# ### <a id="1.2"></a>1.2. Operatory logiczne - logiczne zdania złożone

# Nic nie staje na przeszkodzie, aby budować bardziej złożone wyrażenia logiczne - mamy przecież do dyspozycji operatory logiczne!
#
# | Operator | Działanie |
# | ---|--- |
# | <center>`and`</center> | <center>"i"; zwraca `True`, gdy oba wyrażenia są `True`</center> |
# | <center>`or`</center> | <center>"lub"; zwraca `True`, gdy przynajmniej jedno wyrażenie jest `True`</center> |
# | <center>`not`</center> | <center>"nie"; negacja/zaprzeczenie, odwraca `True` na `False` i odwrotnie</center> |

# Napiszmy dla przykładu następujący (dość uproszczony, oczywiście) algorytm wyszukiwania miejsca wypoczynku na wakacje:

# +
# definicje zmiennych

price = 3500
hotel_stars = 4
all_inclusive = True
distance_to_beach = 400
private_beach = False

# czy jesteśmy zainteresowani ofertą?

( price <= 5000 ) and ( hotel_stars >= 4 ) and all_inclusive and ( distance_to_beach < 500 ) and private_beach
# -

# Mamy tutaj pięć zdań logicznych, a więc wyrażeń typu `bool`, połączonych operatorem `and` - całe takie zdanie złożone będzie miało wartość `True` jedynie wtedy, kiedy wszystkie zdania składowe będą mieć wartość `True`.
#
# Zwróćmy uwagę, że pośród pięciu zmiennych, jakie zdefiniowaliśmy powyżej, mamy dwie zmienne typu `bool`, tj. `all_inclusive` i `private_beach`. Zauważmy, jak są one użyte w zdaniu złożonym; nie musimy pisać np. `all_inclusive == True` (co byłoby najzupełniej poprawne) - wystarczy samo `all_inclusive`, jako że ono samo jest typu `bool`.

# Aby poprawić czytelność takich złożonych zdań logicznych, przypomnijmy sobie ważny punkt z Lekcji 2 - wartości logiczne możemy w normalny sposób przypisywać do zmiennych. Wyrażenie logiczne `(price <= 5000)` jest jako całość obiektem typu `bool`, możemy więc przypisać je do zmiennej, `price_check = (price <= 5000)`, i teraz zmienna `price_check` jest typu `bool` o wartości `True` albo `False`, w zależności od tego, jaką wartość ma zmienna `price` w porównaniu do 5000. Moglibyśmy napisać więc np. (pomińmy nawiasy, abyśmy oswoili się z tą notacją!):

# +
price_check = price <= 5000 # do zmiennej o nazwie price_check przypisujemy wartość obiektu typu bool (price <= 5000)
hotel_stars_check = hotel_stars >= 4
distance_to_beach_check = distance_to_beach < 500

is_interesting = price_check and hotel_stars_check and all_inclusive and distance_to_beach_check and private_beach
# -

# ... wszystkie te nowe zmienne są typu `bool` i mają następujące wartości:

print( type( price_check ) )
print( price_check )

print( type( hotel_stars_check ) )
print( hotel_stars_check )

print( type( distance_to_beach_check ) )
print( distance_to_beach_check )

print( type( is_interesting ) )
print( is_interesting )

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Dłuższe ćwiczenie 3: Zmodyfikuj powyższą zmienną `is_interesting`, aby odpowiadała na wszystkie następujące warunki: (1) cena jest poniżej 5000, ale powyżej 2000; (2) liczba gwiazdek jest co najmniej 3 oraz oferta jest all inclusive, lub też liczba gwiazdek jest co najmniej 4; (3) odległość do plaży jest co najwyżej 200 i plaża jest prywatna, lub też odległość do plaży jest co najwyżej 50. Każdy z cząstkowych warunków zapisz jako osobną zmienną typu `bool`.

# +
# dłuższe ćwiczenie 3 - rozwiązanie


# -

# ## <a id="2"></a>2. Instrukcje warunkowe

# Poznaliśmy już dobrze typ `bool` w Pythonie - jak tworzyć zdania logiczne za pomocą operatorów porównania; jak przypisywać je do zmiennych; jak wykonywać na tych zmiennych operacje logiczne. Przejdźmy teraz do głównej części lekcji - jak wykorzystywać zdania logiczne do pisania **instrukcji warunkowych**, a więc instrukcji typu "jeśli to zdanie logiczne jest prawdziwe, wykonaj następujący fragment kodu (a jeśli jest fałszywe, to wykonaj inny fragment kodu)". Nasz program będzie zatem zachowywał się inaczej w zależności od zadanego warunku logicznego.
#
# Są trzy wersje instrukcji warunkowych:
#
# - `if`
#
# - `if` - `else`
#
# - `if` - `elif` - `elif` - ... - `elif` - `else`

# ### <a id="2.1"></a>2.1. Instrukcja `if`

# Najprostsza składnia warunkowa ma następującą konstrukcję:
# ```
# ...
# statement
# statement
#
# if condition:
#     statement
#     statement
#     ...
#     statement
#
# statement
# statement
# ...
# ```
#
# Wygląda ona tak:
# - zaczyna się słówkiem kluczowym `if`;
# - po nim następuje _dowolne wyrażenie logiczne_, tutaj nazwane `condition`; jest to dowolny obiekt typu `bool` (jak np. powyższa zmienna `is_interesting`), w szczególności mógłby on być powstały z kombinacji wielu innych warunków logicznych itd.;
# - linijka kończy się dwukropkiem `:` - nie zapomnijcie go!
# - następnie rozpoczyna się **blok kodu**, charakteryzujący się wcięciem na cztery spacje - ten blok kodu wykona się tylko i wyłącznie wtedy, jeśli zdanie logiczne `condition` będzie prawdziwe; jeśli będzie fałszywe, cały ten blok kodu zostanie przez interpreter pominięty - nic się nie wydarzy.
#
# Aby podkreślić wcięcie bloku kodu dodaliśmy kilka linijek przed i po instrukcji `if`. Zwróćmy też uwagę, iż blok kodu pod `if`-em może składać się z dowolnej liczby linijek.

# Uwagi praktyczne nt. bloków kodu:
#
# - W innych językach programowania - np. C, C++, C#, Java, JavaScript, TypeScript - używa się nawiasów do oznaczenia bloków kodu, a wszystkie tzw. białe znaki (spacje, tabulatory) są ignorowane; w Pythonie jest inaczej - poczwórna spacja oznacza fragment bloku kodu. Jest to notacja bardzo czytelna - blok kodu jest łatwo widoczny - tym niemniej należy uważać na to, co jest wcięte, a co nie: wiele błędów pojawia się z powodu niewłaściwego wcięcia!
#
# - Edytor kodu jakim jest Jupyter Lab - a także większość innych nowoczesnych edytorów kodu, jak np. najpopularniejsze IDE Pythona, czyli PyCharm - automatycznie dokonują wcięcia na cztery spacje po przejściu `Enter`-em do nowej linijki z linijki typu `if condition:`. Edytor rozumie, iż po `if condition:` zaczyna się blok kodu i sam umieszcza kursor na wcięciu.
#
# - We wszystkich nowoczesnych edytorach, klawisz tabulatora `Tab` ma przypisane właśnie dokładnie cztery spacje - a więc nigdy nie trzeba ich ręcznie wpisywać, wystarczy nacisnąć `Tab`! Zauważmy jednak - to może nieco akademicki przykład - że gdybyśmy mieli zachciankę napisać kod np. w Notatniku Windowsa (absolutnie możemy to zrobić! kod to przecież czysty tekst), to klawisz `Tab` w Notatniku ma zwykle inną liczbę spacji niż cztery - i wówczas interpreter Pythona, dostając taki kod, by zaprotestował!

# Prosty przykład:

# +
x = 78

if x % 2 == 0: # jeśli liczba x jest podzielna przez 2...
    print( f'{x} is an even number!' ) # ... to wypisz takie zdanie
# -

# Warunkiem logicznym jest tutaj `x % 2 == 0` - jeśli to zdanie logiczne jest prawdą, Python przechodzi do wykonywania wciętego bloku kodu poniżej. Dla większej czytelności moglibyśmy wziąć je w nawias:
# ```
# if (x % 2 == 0):
#     ...
# ```
# ... ale jak już zauważyliśmy, takich nawiasów często się nie pisze.

# Blok kodu może zawierać dowolną liczbę linijek:

# +
x = 78

if x % 2 == 0: # jeśli liczba x jest podzielna przez 2...
    print( f'{x} is an even number!' )
    x_by_2 = x / 2
    print( f'{x} divided by 2 is {x_by_2}' )
# -

# Spróbujcie wykonać powyższe komórki podając zarówno parzystą, jak i nieparzystą liczbę - w tym drugim przypadku nic się nie stanie: blok kodu nie wykona się, jako że warunek nie jest spełniony.

# Oczywiście cały kod znajdujący się poza blokiem `if` zostanie wykonany bez względu na to, czy warunek jest spełniony - jego nasz `if` nie dotyczy:

# +
x = 78

if x % 2 == 0: # jeśli liczba x jest podzielna przez 2, wykonaj następujący blok kodu
    print( f'{x} is an even number!' )
    x_by_2 = x / 2
    print( f'{x} divided by 2 is {x_by_2}' )

# tu już jesteśmy poza blokiem if (skończyło się wcięcie) i poniższy kod jest wykonywany niezależnie od powyższego if-a

x_by_3 = x / 3
print( f'{x} divided by 3 is {x_by_3}' )
# -

# Takie bloki `if` mogą oczywiście występować jeden po drugim, np.:

# +
x = 78

# pierwszy warunek if

if x % 2 == 0: # jeśli liczba x jest podzielna przez 2, wykonaj następujący blok kodu
    print( f'{x} is an even number!' )
    x_by_2 = x / 2
    print( f'{x} divided by 2 is {x_by_2}' )

# drugi warunek if (zupełnie niezależny od poprzedniego)

if x % 3 == 0: # jeśli liczba x jest podzielna przez 3, wykonaj następujący blok kodu
    print( f'{x} is divisible by 3!' )
    x_by_3 = x / 3
    print( f'{x} divided by 3 is {x_by_3}' )
# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Szybkie ćwiczenie 4: Zdefiniuj zmienne `age` i `sex`, przypisz do nich wiek użytkownika (liczbę całkowitą dodatnią) i płeć (w formie stringu: albo `'M'`, albo `'F'`). Wydrukuj wiadomość, ile lat pozostało użytkownikowi do przejścia na emeryturę (wiek emerytalny to 60 lat dla kobiet i 65 lat dla mężczyzn), np. w formie `'You have <...> years till retirement.'`.

# +
# szybkie ćwiczenie 4 - rozwiązanie


# -

# ### <a id="2.2"></a>2.2. Instrukcja `if` - `else`

# Konstrukcję warunkową `if` możemy rozszerzyć w następujący sposób: "jeśli dany warunek jest prawdziwy, wykonaj poniższy blok kodu - a w przeciwnym razie (czyli jeśli ten warunek jest fałszywy), wykonaj inny blok kodu". Ogólna składnia to:
# ```
# if condition:
#     statement
#     statement
#     ...
#     statement
# else:
#     statement
#     statement
#     ...
#     statement
# ```
# Pierwsza część jest zatem identyczna, jak wcześniej. Mamy za to dodatkową część, rozpoczynającą się słowem kluczowym `else` i dwukropkiem `:`, po których zaczyna się nowy blok kodu - i jest on wykonywany wtedy, kiedy zdanie `condition` jest fałszywe. Zwróćmy uwagę na wcięcia obu bloków!

# Zobaczmy to na przykładzie - zmodyfikujmy nasz program tak, by wypisywał informację, czy podana liczba jest parzysta czy też nieparzysta:

# +
x = 15

if x % 2 == 0: # jeśli liczba x jest podzielna przez 2...
    print( f'{x} is an even number!' ) # ... to wypisz takie zdanie
else: # ... a w przeciwnym razie (czyli, gdy x jest nieparzysta)
    print( f'{x} is an odd number!' ) # ... to wypisz inne zdanie
# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Szybkie ćwiczenie 5: Zdefinuj zmienną `num`, przypisz do niej liczbę całkowitą. Napisz program, który sprawdza, czy liczba ta jest jednocześnie podzielna przez 2, 3 i 5. Jeśli tak, wydrukuj zdanie typu `'<...> is divisible by 2, 3, and 5'`; w przeciwnym razie, wydrukuj inne (przeczące) zdanie.
#
# Wskazówka: Jakiego operatora logicznego należy tu użyć? Możesz zapisać łączny warunek bezpośrednio po `if`-ie, lub też - dla większej czytelności - zdefiniować warunki cząstkowe jako osobne zmienne logiczne i potem połączyć je w `if`-ie.

# +
# szybkie ćwiczenie 5 - rozwiązanie


# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Szybkie ćwiczenie 6: Zdefiniuj zmienną `letter` i przypisz do niej string będący jedną literą (ograniczmy się w tym ćwiczeniu do małych liter i do języka angielskiego). Napisz program, który wydrukuje informację, czy jest to samogłoska, czy spółgłoska, tj. `'<...> is a vowel|consonant'`.
#
# Wskazówka: Napisz najpierw zdanie złożone `is_vowel`, sprawdzające, czy dana litera jest równa `'a'`, lub też `'e'`, lub `'i'`, `'o'`, `'u'` (jaki operator logiczny należy tu użyć?). Następnie napisz odpowiednią instrukcję `if` - `else`.
#
# Uwaga: `'y'` jest w języku angielskim czasem samogłoską, czasem spółgłoską; tutaj traktujemy ją jako spółgłoskę. Niżej nauczymy się sprawdzać bardziej skomplikowane sytuacje - nie tylko "jeśli ten warunek jest prawdziwy, zrób to, a jeśli nie, zrób tamto", ale wiele warunków naraz. Wtedy będziemy mogli wziąć `'y'` pod uwagę i wypisać `'y is sometimes a vowel and sometimes a consonant'`.

# +
# szybkie ćwiczenie 6 - rozwiązanie


# -

# ### <a id="2.3"></a>2.3. Instrukcja `if` - `elif` - `elif` - ... - `elif` - `else`

# Jest to najpełniejsza składnia warunkowa w Pythonie - daje nam ona możliwość sprawdzenia dowolnej liczby warunków logicznych i wykonania odpowiedniego bloku kodu:
#
# - konstrukcja zaczyna się, jak zawsze, od `if`, sprawdzającego warunek logiczny `condition_1`; jeśli jest on prawdziwy, wykonywany jest następujący blok kodu, zaś pozostała część instrukcji warunkowej jest pomijana;
#
# - jeśli `condition_1` jest zdaniem fałszywym, interpreter przechodzi do sprawdzenia kolejnego warunku, `condition_2`, znajdującego się po słowie kluczowym `elif` (skrót od "else-if", znaczącego "jeśli poprzedni warunek jest fałszywy i jeśli obecny warunek jest prawdziwy") - i wykonuje znajdujący się pod spodem blok kodu jeśli `condition_2` jest zdaniem prawdziwym;
#
# - w ten sam sposób możemy sprawdzać dowolną liczbę warunków, każde po słowie `elif`; ważne jest zapamiętanie, że _wykonany zostanie tylko jeden blok kodu z całej serii_, tj. ten, dla którego pierwszego warunek będzie prawdziwy; reszta instrukcji warunkowej jest pomijana (nawet gdyby któryś inny warunek poniżej też był prawdziwy);
#
# - jeśli żaden z warunków - najpierw po `if`, a potem po kolejnych `elif`-ach - nie jest prawdziwy, zostaje wykonany kod znajdujący się na samym końcu, po słowie `else`; uwaga: ten blok `else` jest opcjonalny, nie musi go być, a wówczas jeśli żaden z warunków nie jest prawdziwy, to cała instrukcja warunkowa nie będzie miała po prostu żadnego efektu.
#
# ```
# if condition_1:
#     statement
#     statement
#     ...
#     statement
# elif condition_2:
#     statement
#     statement
#     ...
#     statement
# elif condition_3:
#     statement
#     statement
#     ...
#     statement
# ...
# elif condition_n:
#     statement
#     statement
#     ...
#     statement
# else:
#     statement
#     statement
#     ...
#     statement
# ```
#
# Jak zawsze, każdy blok kodu jest wcięty; zawsze też po każdym warunku (i po `else`) jest dwukropek `:`.

# Prosty przykład:

# +
x = -12

if x == 0:
    print( f'{x} is zero!' )
elif x > 0:
    print( f'{x} is positive!' )
else:
    print( f'{x} is negative!' )
# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Dłuższe ćwiczenie 7: Zdefiniuj zmienną `month` będącą nazwą miesiąca (powiedzmy po angielsku, `'January'` itd.) i wypisz liczbę dni, jakie ten miesiąc ma; dla lutego napisz `'February has 28 or 29 days'`.

# +
# dłuższe ćwiczenie 7 - rozwiązanie


# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Dłuższe ćwiczenie 8: Napisz program dobierający rozmiar ramy rowerów trekkingowych wg poniższej tabelki:
#
# | <center>Wzrost rowerzysty do</center> | <center>Rozmiar ramy roweru trekkingowego</center> |
# | --- | --- |
# | <center>152 cm</center>|<center>16” (41 cm)</center> |
# | <center>157 cm</center>|<center>17” (43 cm)</center> |
# | <center>162 cm</center>|<center>18” (46 cm)</center> |
# | <center>167 cm</center>|<center>18” (46 cm)</center> |
# | <center>172 cm</center>|<center>19” (48 cm)</center> |
# | <center>175 cm</center>|<center>19” (48 cm)</center> |
# | <center>177 cm</center>|<center>20” (51 cm)</center> |
# | <center>182 cm</center>|<center>20” (51 cm)</center> |
# | <center>187 cm</center>|<center>21” (53 cm)</center> |
# | <center>192 cm</center>|<center>22” (56 cm)</center> |
# | <center>197 cm</center>|<center>23” (58 cm)</center> |
#
# Zauważ, że niektóre rozmiary ramy powtarzają się. Możesz uzupełnić ten program o wypisanie wiadomości w stylu `'We have no bike frames large enough!'`, jeśli wzrost będzie wykraczał poza zakres w tabelce. Przyjmij od użytkownika jego wzrost - poprzez zdefiniowanie zmiennej `user_height` - a następnie zwróć rozmiar ramy (najlepiej z ładną wiadomością); wybierz, czy w calach, czy w centymetrach.

# +
# dłuższe ćwiczenie 8 - rozwiązanie


# -

# Powyższe ćwiczenie jest może nieco monotonne - ale postaraj się jednak wypisać pełną instrukcję warunkową: mamy nadzieję, że dzięki temu nigdy nie zapomnisz, iż po warunku musi być dwukropek, a blok warunkowy ma być wcięty!

# ### <a id="2.4"></a>2.4. Warunki zagnieżdżone

# Poznaliśmy już zatem wszystkie trzy rodzaje instrukcji warunkowych w Pythonie. Konstrukcje te można jednak jeszcze bardziej skomplikować! - poprzez **zagnieżdżanie** ("nesting") instrukcji warunkowych w innych instrukcjach warunkowych. Jest to prostsze niż brzmi - oznacza jedynie, iż każdy blok w danej instrukcji warunkowej może sam w sobie zawierać instrukcję warunkową. Czemu by i nie? Blok kodu może zawierać przecież dowolny kod - w tym i inne instrukcje warunkowe.
#
# Zagnieżdżone bloki warunkowe muszą oczywiście też być wcięte - o kolejne cztery spacje!

# Jako przykład wróćmy do naszego programu sprawdzającego, czy liczba całkowita jest parzysta. Utrudnijmy go jednak nieco: przyjmijmy, że zmienna `x` (typu `int`) pochodzi ze stringu `x_raw`, który użytkownik wpisał, np. `'17'`. (Służy do tego funkcja `input` - sprawdź w Internecie jej działanie!) Ten string `x_raw` następnie próbujemy przekonwertować na liczbę całkowitą instrukcją `x = int(x_raw)`, a dopiero potem sprawdzić jej parzystość.
#
# Teraz, gdybyśmy jako `x_raw` podali mu string niedający się zamienić na liczbę całkowitą, np. `'8.8'` lub `'abc'`, interpreter zareaguje błędem:

# +
x_raw = '8.8'
x = int( x_raw )

if x % 2 == 0:
    print( f'{x} is an even number!' )
else:
    print( f'{x} is an odd number!' )
# -

# Sytuację tego typu możemy wziąć pod uwagę dodając "zewnętrzną" instrukcję warunkową, która najpierw sprawdzi, czy wpisany tekst `x_raw` da się przekonwertować na liczbę całkowitą. Aby napisać ten warunek, przypomnijmy sobie z Lekcji 2 metodę stringów `isdigit`, która zwraca obiekt typu `bool` odpowiadający na pytanie, czy dany string jest łańcuchem tylko i wyłącznie cyfr:

'1537652'.isdigit()

'8.8'.isdigit() # tu oprócz cyfr mamy kropkę

'-10'.isdigit() # tu oprócz cyfr mamy myślnik

' 5'.isdigit() # tu oprócz cyfr mamy spację

'abc'.isdigit()

# Możemy więc rozważyć warunek logiczny `x_raw.isdigit()`; będzie on prawdziwy tylko wtedy, kiedy string `x_raw` będzie składał się tylko z cyfr, a wówczas operacja `x = int(x_raw)` bezproblemowo przekonwertuje go na odpowiednią liczbę całkowitą.
#
# Bądźmy jeszcze bardziej dokładni i postarajmy się wziąć pod uwagę sytuację, kiedy użytkownik przypadkowo wpisał spacje przed lub po danej liczbie. Weźmy pod uwagę też liczby ujemne. Aby to zrobić, ze stringu `x_raw` usuńmy najpierw wszystkie ewentualne spacje po lewej i prawej, a także ewentualny myślnik (znak minus) po stronie lewej. Przypomnijmy sobie z Lekcji 2 służące do tego metody stringów `strip` i `lstrip` (jest też `rstrip`).

'   5     '.strip()

'-10'.lstrip( '-' )

# Nasz warunek przyjmie więc postać: `x_raw.strip().lstrip('-').isdigit()` - najpierw usuń z `x_raw` spacje po obu stronach, potem usuń myślnik po lewej, na końcu sprawdź, czy otrzymany string składa się tylko i wyłącznie z cyfr:

'      -7892   '.strip().lstrip( '-' ).isdigit()

# Poćwiczyliśmy przy okazji kilka metod stringów! Zauważmy, że metody możemy składać jedna po drugiej, każda oczywiście po kolejnej kropce. Nierzadko warunki logiczne w instrukcjach warunkowych powstają właśnie z tego typu zastosowania metod.

# Wróćmy do tematu zagnieżdżonych instrukcji warunkowych. Najbardziej "zewnętrzną" instrukcją będzie sprawdzenie powyższego warunku i tylko jeśli będzie on prawdziwy, to przejdziemy do "wewnętrznej" instrukcji warunkowej sprawdzającej parzystość:

# +
x_raw = '8.8'

if x_raw.strip().lstrip( '-' ).isdigit():
    
    x = int( x_raw )
    
    if x % 2 == 0:
        print( f'{x} is an even number!' )
    else:
        print( f'{x} is an odd number!' )

else:
    
    print( f'{x_raw} is not an integer! Please enter a valid integer number.' )
# -

# Zwróćmy uwagę na podwójne wcięcie w wewnętrznych blokach warunkowych! Zwróćmy też uwagę, iż puste linijki - dodane tu dla większej czytelności - w niczym nie wadzą: Python poznaje blok kodu po wcięciu.

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Dłuższe ćwiczenie 9: Zmodyfikuj program z ćwiczenia 8, tak by najpierw pytał o typ roweru - trekkingowy albo MTB - a następnie dla rowerów MTB dobierał ramę wg poniższej tabeli:
#
# | <center>Wzrost rowerzysty do</center> | <center>Rozmiar ramy roweru MTB</center> |
# | --- | --- |
# | <center>152 cm</center>|<center>14” (36 cm)</center> |
# | <center>157 cm</center>|<center>15” (38 cm)</center> |
# | <center>162 cm</center>|<center>16” (41 cm)</center> |
# | <center>167 cm</center>|<center>16” (41 cm)</center> |
# | <center>172 cm</center>|<center>17” (43 cm)</center> |
# | <center>175 cm</center>|<center>17" (43 cm)</center> |
# | <center>177 cm</center>|<center>18" (46 cm)</center> |
# | <center>182 cm</center>|<center>18" (46 cm)</center> |
# | <center>187 cm</center>|<center>19" (48 cm)</center> |
# | <center>192 cm</center>|<center>20" (51 cm)</center> |
# | <center>197 cm</center>|<center>21" (53 cm)</center> |
#
# (Dla rowerów trekkingowych użyj tabeli z ćwiczenia 8.)

# +
# dłuższe ćwiczenie 9 - rozwiązanie


# -

# ## <a id="3"></a>3. Zadania domowe

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'><img style = 'float: right; margin-left: 10px; margin-bottom: 10px' src = 'Images/dice.png' width="250px"> Dłuższe ćwiczenie 10: Ścianka kostki do gry.
# ```
# -----
# |  *|
# | * |
# |*  |
# -----
# ```
#
# Napisz program, który przyjmie liczbę całkowitą od 1 do 6 (nazwijmy ją powiedzmy `num`) i wydrukuje reprezentację ścianki kostki do gry o tym numerze (jak wyżej pokazano dla liczby 3) - ścianki górne zaznaczone pięcioma myślnikami `'-'`, a także ścianki boczne zaznaczone znakiem "pipe" `'|'`; pośrodku tych ścianek mamy wydrukowane trzy linijki, po trzy znaki w każdej, z czego znak może być albo spacją `' '`, albo gwiazdką `'*'`.
#
# Wskazówka: Można by napisać instrukcję warunkową z sześcioma warunkami, np. `num == 1` itd., gdzie dla każdej wartości `num` drukowalibyśmy odpowiednią reprezentację ścianki. Ale postarajmy się być bardziej zmyślni i wykorzystać istniejącą tu symetrię! W tym celu, zdefiniuj trzy zmienne, `first_row`, `second_row`, `third_row`, które będą przybierały formę trójznakowych stringów, np. dla liczby 3 byłyby one równe odpowiednio `'  *'`, `' * '`, `'*  '`. Napisz teraz dwie oddzielne instrukcje warunkowe, każda z nich mająca tylko trzy (nie sześć!) warunki, a więc `if` - `elif` - `elif`. Pierwsza instrukcja niech przypisuje zmienne `first_row` oraz `third_row`, natomiast druga instrukcja zmienną `second_row`. Zastanów się, dlaczego tak warto zrobić (podpowiedź: pierwszy i trzeci rząd są bardzo do siebie podobne).
#
# Uwaga: Jest to przykład tzw. "ASCII art".

# +
# dłuższe ćwiczenie 10 - rozwiązanie


# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'><img style = 'float: right; margin-left: 10px; margin-bottom: 10px' src = 'Images/chess_board.png'  width="250px"> Dłuższe ćwiczenie 11: Kolor pola na szachownicy.
#
# Napisz program, który przyjmie liczbę całkowitą od 1 do 8 (nazwijmy ją `row`) oraz małą literę od `'a'` do `'h'` (nazwijmy ją `col`) i zwróci kolor (nazwijmy go `color`) odpowiedniego pola na szachownicy, tj. `'white'` albo `'black'`.
#
# Wskazówka: Zauważ, że kolor pola szachownicy zależy jednoznacznie od dwóch faktów: czy numer rzędu `row` jest parzysty, czy nie; oraz czy numer kolumny jest parzysty, czy nie - przy czym kolumny są numerowane literami, więc "parzystość" w tym przypadku oznacza, że `col` jest jedną z liter `'b'`, `'d'`, `'f'`, `'h'`. Zdefiniuj zmienne typu `bool`, nazwijmy je `row_even` i `col_even`, które będą miały wartość `True`, gdy rząd/kolumna będą parzyste w tym sensie. Napisz teraz zagnieżdżoną instrukcję warunkową przy użyciu tych dwóch zdań logicznych.

# +
# dłuższe ćwiczenie 11 - rozwiązanie


# -

# Wersja nieco bardziej zaawansowana, ale i elegancka: Powyżej zdefiniowana zmienna `col_even` była stworzona dość "manualnie", poprzez wylistowanie "parzystych" liter alfabetu (za pomocą odpowiedniego operatora logicznego). To byłby problem gdybyśmy np. mieli planszę szachową nie 8 x 8, ale np. 20 x 20. Spróbuj przepisać definicję zmiennej `col_even` w bardziej elegancki sposób - niech będzie ona liczbą odpowiadającą literze, tj. 1 zamiast `'a'`, 2 zamiast `'b'` itd.
#
# Wskazówka: Rozważ string pomocniczy `chess_alphabet = 'abcdefgh'`. Przypomnij sobie z Lekcji 2 metodę stringów `find`, pozwalającą znaleźć pozycję danego znaku w stringu (i pamiętaj, że pozycja taka liczona jest od zera!).

# +
# dłuższe ćwiczenie 11 - rozwiązanie alternatywne


# -

# <img style = 'float: left; margin-right: 10px; margin-bottom: 10px' src = 'Images/question.png'> Dłuższe ćwiczenie 12: Chatbot na siłowni.
#
# (a) Wstęp na siłownię mają osoby w wieku powyżej 14 lat. Napisz program, który przeprowadzi selekcję klientów, pytając ich o wiek (zdefiniuj zmienną `age`, przypisz jej jakąś wartość typu `int`) i wypisując odpowiednią wiadomość na ekranie.
#
# (b) Siłownia wprowadziła promocję - wejściówki dla pań kosztują 10 zł, a dla panów 15 zł. Zmodyfikuj poprzedni program poprzez rozszerzenie go o weryfikację płci (zdefiniuj zmienną `sex`, przypisz jej string `'M'` albo `'F'`) i wypisanie odpowiedniej wiadomości, czy klient może wejść, a jeśli tak, to ile ma zapłacić.
#
# (c) Siłownia wprowadziła zniżkę dla studentów - po okazaniu ważnej legitymacji studenckiej wejściówka kosztuje 5zł, bez względu na płeć. Zmodyfikuj odpowiednio poprzedni program (zdefiniuj zmienną `student`, przypisz jej jakąś wartość typu `bool`).
#
# (d) Siłownia udostępniła saunę dla klientów - jeżeli oprócz siłowni klient chce również skorzystać z sauny, całkowity koszt wstępu to 20 zł, bez względu na płeć i bez względu na ewentualną legitymację studencką. Zmodyfikuj odpowiednio poprzedni program (zdefiniuj zmienną `sauna`, przypisz jej jakąś wartość typu `bool`).

# +
# dłuższe ćwiczenie 12a - rozwiązanie



# +
# dłuższe ćwiczenie 12b - rozwiązanie



# +
# dłuższe ćwiczenie 12c - rozwiązanie



# +
# dłuższe ćwiczenie 12d - rozwiązanie


# -



StarcoderdataJupyterScriptsDedupFiltered