Ulohy_reseni

In [1]:
from IPython.display import Image

Úlohy na procvičení základních operací v Pythonu

Základy

Úloha 1 - na zahřátí

  • procvičení: tvorba proměnných, aritmetické operace, podmínky, tisk

Výpočet BMI člověka: $$ \mathrm{bmi} = \frac{w}{h^2}, $$ kde h je výška [m] a w je hmotnost [kg].

  1. vytvořte proměnnou height (nebo h) a weight (nebo w) a vložte do ní nějaké hodnoty imaginárního člověka
  2. do proměnné bmi uložte výsledek
  3. vytiskněte "Výsledné BMI = XXX" s přesností na jedno desetinné místo
In [2]:
h = 1.8
w = 65
bmi = w / h**2
print(f'Výsledné BMI = {bmi:.1f}')
Výsledné BMI = 20.1
  1. vytvořte proměnnou gender, která může nabývat hodnot "m" (muž) nebo "f" (žena)
  2. na základě tabulky vytvořte mechanizmus, který vypíše, zda má daná osoba podváhu, těžký stupeň nebo jinak něco mezi
ženy muži
podváha $<$ 19 $<$ 20
normální stav $<$ 24 $<$ 25
mírná obezita $<$ 29 $<$ 30
střední stupeň $<$ 39 $<$ 40
těžký stupeň $\geq$ 39 $\geq$40
In [3]:
# základní řešení
gender = 'm'
if gender == 'f':
    if bmi < 19:
        print('Tato žena má podváhu')
    elif bmi >= 39:
        print('Tato žena má těžký stupeň obezity')
    else:
        print('Tato žena má něco mezi podváhou a těžkým stupněm obezity')
if gender == 'm':
    if bmi < 20:
        print('Tento muž má podváhu')
    elif bmi >= 40:
        print('Tento muž má těžký stupeň obezity')
    else:
        print('Tento muž má něco mezi podváhou a těžkým stupněm obezity')
Tento muž má něco mezi podváhou a těžkým stupněm obezity
In [4]:
# trochu vylepšené řešení
gender_print = {'f': 'Tato žena', 'm': 'Tento muž'}
# kat1 == podváha, kat5 == těžký stupeň
gender_kat = {'kat1': {'f': 19, 'm': 20},
              'kat5': {'f': 39, 'm': 40}}
if bmi < gender_kat['kat1'][gender]:
    print(f'{gender_print[gender]} má podváhu')
elif bmi >= gender_kat['kat5'][gender]:
    print(f'{gender_print[gender]} má těžký stupeň obezity')
else:
    print(f'{gender_print[gender]} má něco mezi podváhou a těžkým stupněm obezity')
Tento muž má něco mezi podváhou a těžkým stupněm obezity
In [5]:
# odstranění opakujícího se kódu
gender_print = {'f': 'Tato žena', 'm': 'Tento muž'}
# kat1 == podváha, kat5 == těžký stupeň
gender_kat = {'kat1': {'f': 19, 'm': 20},
              'kat5': {'f': 39, 'm': 40}}

message = gender_print[gender] + ' má '
if bmi < gender_kat['kat1'][gender]:
    message += 'podváhu'
elif bmi >= gender_kat['kat5'][gender]:
    message += 'těžký stupeň obezity'
else:
    message += 'něco mezi podváhou a těžkým stupněm obezity'
print(message)
Tento muž má něco mezi podváhou a těžkým stupněm obezity

Bonus celá tabulka

In [6]:
import math

gender_print = {'f': 'Tato žena', 'm': 'Tento muž'}
# kat1 == podváha, kat5 == těžký stupeň
gender_kat = {'kat1': {'f': 19, 'm': 20, 'msg': 'podváhu'},
              'kat2': {'f': 24, 'm': 25, 'msg': 'normální váhu'},
              'kat3': {'f': 29, 'm': 30, 'msg': 'mírnou obezitu'},
              'kat4': {'f': 39, 'm': 40, 'msg': 'střední obezitu'},
              'kat4': {'f': math.inf, 'm': math.inf, 'msg': 'těžkou obezitu'}}

message = gender_print[gender] + ' má '

# Python <3.7 does not preserve insertion order => need sorted
#for kat in sorted(gender_kat):
# Python 3.7+ preserve insertion order
for kat in gender_kat:
    kat_dict = gender_kat[kat]
    if bmi < kat_dict[gender]:
        message += kat_dict['msg']
        break

print(message)
Tento muž má normální váhu

Úloha 2

  • procvičení: cykly, listy/tuply, slovník
  • použijte pouze cykly (žádné vestavěné funkce)
  1. vytvořte funkci get_count(source, fval), která vrátí počet výskytů fval
  2. vytvořte funkci get_index, která v listu nalezne zadanou hodnotu a vrátí jeho polohu/index
  3. v get_index vytvořte přepínač, který vrátí výsledek po prvním výskytu a skončí
  4. vytvořte funkci get_counts, která vrátí četnost všech hodnot (pro ukládání výsledků využijte slovník)
  5. ze získaných výsledků vytiskněte jednoduchý histogram
txt
    1 ***
    2 **
    3 *
    4 *****
In [7]:
# zadáno
data = (1, 2, 3, 4, 7, 3, 2, 2, 3, 5, 2)
In [8]:
def get_count(source, fval):
    count = 0
    for val in source:
        if val == fval:
            count += 1
    return count

def get_index(source, fval, first=True):
    indices = []
    for vali, val in enumerate(source):
        if val == fval:
            indices.append(vali)
            if first:
                break
    return indices

def get_counts(source):
    counts = {}
    for val in source:
        if counts.get(val):
            counts[val] += 1
        else:
            counts[val] = 1
    return counts
In [9]:
get_count(data, 2)
Out[9]:
4
In [10]:
get_index(data, 2, first=False)
Out[10]:
[1, 6, 7, 10]
In [11]:
counts = get_counts(data)
counts
Out[11]:
{1: 1, 2: 4, 3: 3, 4: 1, 7: 1, 5: 1}
In [12]:
for key, val in sorted(counts.items(), key=lambda x: x[0]):
    print(f'{key} {"*"*val}')
1 *
2 ****
3 ***
4 *
5 *
7 *

Úloha 3

  • procvičení: listy, cykly, funkce

  • máme list length_list naměřených délek

  1. určete velikost souboru dat
  2. vytvořte funci mean, která vrátí střední hodnotu listu $$ \mu = \frac{1}{n} \sum\limits_{i=0}^n x_i $$
  3. pomocí funkce vypočítejte střední hodnotu
  4. vytvořte funkci std, která vrátí směrodatnou odchylku a obsahuje volitelný parametr delta, který je defaultně 0 $$ \sigma = \sqrt{\frac{1}{n - \delta} \sum\limits_{i=0}^n \left( x_i - \mu \right)^2} $$
  5. pomocí funkce std vypočítejte nestranný (nevychýlený) odhad
  6. vytvořte funkce get_max a get_min, která vrátí maximální a minimální hodnotu (pomocí cyklu)
  7. vytvořte funkci, která výsledné hodnoty vytiskne
  8. ze souborů length_txt a time_txt načtěte data do length_list a časů time_list a do proměnné speed_list napočítejte rychlosti $v = \frac{s}{t}$
    • využijte print, type a len pro zjištění toho co a v jaké podobě získáváte
  9. výsledky uložte do souboru results.txt vpodobě tří sloupečků a oddělovač použijte tabulátor
length time speed
1.0    2.2  2.2
with open('nazev_souboru.txt', 'X') as f: 
    #'X' == 'w' zápis (pokud soubor existuje, smaže se jeho obsah)
    #'X' == 'r' čtení, 'X' == 'a' append (pokud soubor existuje, přidá se obsah na jeho konec)
    promenna = f.read() # načtení celého souboru jako jeden textový řetězec
    promenna = f.readlines() # načtení celého souboru - výstupem je list obsahující jednotlivé řádky
    promenna = f.write('retezec') # zapíše řetězec do souboru
    promenna = f.writelines(['radek 1\n', 'radek 2\n', 'radek 3\n'])
In [13]:
# zadáno
import math # odmocnina math.sqrt nebo mocnina ** ; math.inf nekonečno
length_list = [1.5, 1.6, 1.3, 1.24, 1.65, 1.35, 1.47] # [m]
length_txt = 'length.txt'
time_txt = 'time.txt'
In [14]:
def mean(data):
    res = 0
    for val in data:
        res += val
    return res / len(data)

def std(data, delta=0):
    res = 0
    mu = mean(data)
    for val in data:
        res += (val - mu)**2
    return (res / (len(data) - 1))**0.5

def get_max(data):
    max_val = -math.inf
    for val in data:
        if max_val < val:
            max_val = val
    return max_val

def get_min(data):
    min_val = math.inf
    for val in data:
        if min_val > val:
            min_val = val
    return min_val

def print_results(count, mu, std_, min_, max_):
    print('Počet hodnot        =', count)
    print('Střední hodnota     =', mu)
    print('Směrodatná odchylka =', std_)
    print('Minimální hodnota   =', min_)
    print('Maximální hodnota   =', max_)
In [15]:
count = len(length_list)
mu = mean(length_list)
std_ = std(length_list, delta=1)
min_ = get_min(length_list)
max_ = get_max(length_list)

print_results(count, mu, std_, min_, max_)
Počet hodnot        = 7
Střední hodnota     = 1.4442857142857144
Směrodatná odchylka = 0.15371587890836597
Minimální hodnota   = 1.24
Maximální hodnota   = 1.65
In [16]:
with open('length.txt', 'r') as f:
    length_list = f.readlines()
    
with open('time.txt', 'r') as f:
    time_list = f.read()

print(len(length_list), length_list[0], type(length_list[0]))
print(len(time_list), time_list[0], type(time_list[0]))
100 1.22
 
500 2 
In [17]:
length_list = [float(i) for i in length_list]
time_list = [float(i) for i in time_list.strip().split('\t')]
print(len(length_list), length_list[0], type(length_list[0]))
print(len(time_list), time_list[0], type(time_list[0]))
100 1.22 
100 2.93 
In [18]:
speed_list = [s / t for s, t in zip(length_list, time_list)]
print('Rychlosti (první 3):', speed_list[:3])

count = len(speed_list)
mu = mean(speed_list)
std_ = std(speed_list, delta=1)
min_ = get_min(speed_list)
max_ = get_max(speed_list)

print_results(count, mu, std_, min_, max_)
Rychlosti (první 3): [0.41638225255972694, 0.7322834645669292, 0.4325259515570934]
Počet hodnot        = 100
Střední hodnota     = 0.7798529924501648
Směrodatná odchylka = 0.31308022101792593
Minimální hodnota   = 0.3768115942028986
Maximální hodnota   = 1.7254901960784315
In [19]:
with open('results.txt', 'w') as f:
    f.write('length\ttime\tspeed\n')
    for l, t, s in zip(length_list, time_list, speed_list):
        f.write(f'{l:.2f}\t{t:.2f}\t{s:.6f}\n')

Úloha 4

  • procvičení: cykly, listy
  • vynásobte matici vektorem (kontroly vynechejte)
In [20]:
# zadáno
mat = [[1, -5],
       [3, 6]]
vec = [-3, 4]
In [21]:
def mat_v_multiply(mat, v):
    nrows = len(mat)
    ncols = len(mat[0])
    v_res = []
    for row in mat:
        tmp = 0
        for vali, val in enumerate(row):
            tmp += val * v[vali]
        v_res.append(tmp)
    return v_res
mat_v_multiply(mat, vec)
Out[21]:
[-23, 15]
In [22]:
def mat_v_multiply(mat, v):
    nrows = len(mat)
    ncols = len(mat[0])
    v_res = []
    for row in mat:
        tmp = 0
        for row_val, v_val in zip(row, v):
            tmp += row_val * v_val
        v_res.append(tmp)
    return v_res
mat_v_multiply(mat, vec)
Out[22]:
[-23, 15]
In [23]:
import numpy as np
np.array(mat) @ np.array(vec)
Out[23]:
array([-23,  15])

Bonus - násobení matic

In [24]:
# zadáno
mat1 = [[1, -5],
        [3, 6]]
mat2 = [[-2, 1],
        [7, 3]]
In [25]:
def mat_mat_multiply(m1, m2):
    nrows = len(m1)
    ncols = len(m1[0])
    m_res = []
    for rowi, row in enumerate(m1):
        m_res.append([])
        for coli in range(ncols):
            tmp = 0
            for i in range(ncols):
                tmp += row[i] * m2[i][coli]
            m_res[rowi].append(tmp)
    return m_res

mat_mat_multiply(mat1, mat2)
Out[25]:
[[-37, -14], [36, 21]]
In [26]:
np.array(mat1) @ np.array(mat2)
Out[26]:
array([[-37, -14],
       [ 36,  21]])

Vygenerujte Pascalův trojúhelník

https://cs.wikipedia.org/wiki/Pascal%C5%AFv_troj%C3%BAheln%C3%ADk

Vytvořte generátor Pascalova trojúhelníku, který vygeneruje zadaný počet řádků.

                  1                  
               1     1               
            1     2     1            
         1     3     3     1         
      1     4     6     4     1      
In [27]:
# zadáno
pascal_triang = [[1], 
                 [1, 1]]
for line in pascal_triang:
    print(line)
[1]
[1, 1]
In [28]:
number_of_lines = 10
for i in range(number_of_lines - len(pascal_triang)):
    prev_line = pascal_triang[-1]
    new_line = [1]
    for i in range(len(prev_line) - 1):
        new_line.append(prev_line[i] + prev_line[i+1])
    new_line.append(1)
    pascal_triang.append(new_line)

for line in pascal_triang:
    print(line)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
In [29]:
def fancy_print_pascal_triang(pascal_triang):
    last_line_width = len('{}'.format(" ".join(['{:5}'.format(v) for v in pascal_triang[-1]])))
    for line in pascal_triang:    
        print('{:^{}}'.format(" ".join(['{:5}'.format(v) for v in line]), last_line_width))


fancy_print_pascal_triang(pascal_triang)
                               1                           
                            1     1                        
                         1     2     1                     
                      1     3     3     1                  
                   1     4     6     4     1               
                1     5    10    10     5     1            
             1     6    15    20    15     6     1         
          1     7    21    35    35    21     7     1      
       1     8    28    56    70    56    28     8     1   
    1     9    36    84   126   126    84    36     9     1
In [30]:
def f_for(n):
    res = []
    res.append(0)
    if n == 0:
        return res
    res.append(1)
    if n == 1:
        return res
    for i in range(n - len(res) + 1):
        res.append(res[i] + res[i+1])
    return res
print(f_for(20))
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
In [31]:
def f_rec(n):
    if n > 1:
        return f_rec(n - 1) + f_rec(n - 2)
    elif n == 0:
        return 0
    elif n == 1:
        return 1
print([f_rec(i) for i in range(21)])
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
In [32]:
fib_mem = {}
def f_mem(n):
    if n > 1:
        res = fib_mem[n - 1] + fib_mem[n - 2]
    elif n == 0:
        res = 0
    elif n == 1:
        res = 1
    fib_mem[n] = res
    return res
print([f_mem(i) for i in range(21)])
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765]
In [33]:
%timeit f_for(100)
14.5 µs ± 2.16 µs per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [34]:
%timeit [f_rec(i) for i in range(15)]
353 µs ± 58.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [35]:
%timeit [f_mem(i) for i in range(100)]
25.9 µs ± 5.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [36]:
# melka uhlopricka pascalova trojúhelníku
row_it = 0
fib_pasc_list = []
for ri, row in enumerate(pascal_triang):
    row_it = ri
    ci = 0
    tmp = 0
    for rowi in reversed(range(row_it + 1)):
        if ci <= rowi:
            tmp += pascal_triang[rowi][ci]
        ci += 1
    fib_pasc_list.append(tmp)
fib_pasc_list
Out[36]:
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
In [ ]: