3. Jednoduché výpočty

Návratová hodnota – return

V předchozích kapitolách funkce přímo něco prováděly – pohybovaly želvou nebo něco vypisovaly. Mnohokrát však nepotřebujeme aby funkce přímo něco provedla, ale jen aby něco vypočítala a vypočtenou hodnotu (případně nějaké jiné informace) vrátila, abychom s ní mohli dále pracovat. K tomuto účelu je v Pythonu klíčové slovo return. Příkaz return vrátí hodnotu, která za ním následuje, a okamžitě ukončí výpočet funkce. Tato vrácená hodnota je následně dostupná v místě volání funkce a lze s ní dále pracovat. Naprostá většina funkcí vestavěných v Pythonu něco vrací, například funkce round vrací zaokrouhlené číslo, funkce abs vrací absolutní hodnotu zadaného čísla, atd…

Důležitá a často zapomenutá vlastnost return je okamžité ukončení provádění funkce – typicky v případech kdy už funkce odvedla svoji práci a něco vrátila, takže není potřeba nic dále počítat.

Využití zastavení výpočtu funkce pomocí return

Cyklus while

V minulé kapitole byl představen cyklus for, který se hodí, když dopředu víme kolikrát cyklus chceme provést, nebo pokud chceme něco provést pro každou položku v seznamu (více v kapitole Řetězce a seznamy). V některých případech však nevíme, kolikrát cyklus chceme provést na začátku cyklení, ale zjistíme to až v jeho průběhu. Pro tyto případy Python má cyklus while, který jen definuje podmínku a dokud tato podmínka platí, tak se tělo cyklu opakovaně provádí.

Výpis mocnin trojky, menší než 10 000

3.1. Pokročilé počítání

Součet čísel od 1 do n

Napište funkci series_sum(n), která vrátí součet čísel od 1 do n.

3.1.1. Faktoriál pomocí for

Napište funkci factorial(n), která vrací faktoriál čísla n a využívá cyklus for. Připomeňme, že n! = 1·2·3· ... ·n a že 0! = 1.

def factorial(n):
    pass

def test_factorial():
    assert factorial(0) == 1
    assert factorial(1) == 1
    assert factorial(10) == 3628800
    assert factorial(50) == 30414093201713378043612608166064768844377641568960512000000000000

3.1.2. Faktoriál pomocí while

Napište funkci factorial(n), která vrací faktoriál čísla n a využívá cyklus while.

def factorial(n):
    pass

def test_factorial():
    assert factorial(0) == 1
    assert factorial(1) == 1
    assert factorial(10) == 3628800
    assert factorial(50) == 30414093201713378043612608166064768844377641568960512000000000000

3.1.3. Ciferný součet

Napište funkci digit_sum(n), která vrátí ciferný součet čísla n.

def digit_sum(n):
    pass

def test_digit_sum():
    assert digit_sum(0) == 0
    assert digit_sum(274) == 13
    assert digit_sum(123456789) == 45

3.1.4. Opakovaný ciferný součet

Napište funkci repeated_digit_sum(n), která vypočítá ciferný součet čísla n. Ze získaného ciferného součtu opět vypočítá ciferný součet a tento postup opakuje dokud nezbude jednociferné číslo, které vrátí. Zkuste své řešení rozložit do dvou funkcí.

def repeated_digit_sum(n):
    pass

def test_repeated_digit_sum():
    assert repeated_digit_sum(123) == 6
    assert repeated_digit_sum(123456789) == 9
    assert repeated_digit_sum(99989788879879) == 7

3.2. Dělitelnost a prvočísla

Připomeňme pár informací. Celé číslo (int) a je dělitelem b pokud existuje celé číslo c tak, že a · c = b – jednoduše řečeno: zbytek po dělení b / a je 0. Zbytek po dělení v Pythonu získáme pomocí operace b % a. Prvočísla jsou pak přirozená čísla n, která mají právě dva dělitele (1 a n) – tedy 1 není prvočíslo.

Snažte se využívat funkce, které jste již dříve implementovali. Ušetříte tak čas a kód bude více srozumitelný. Obecně také lze říci, že pokud máte někde v programu dvakrát ten stejný nebo velmi podobný kód, něco je špatně. Zkuste společný kód abstrahovat do zvláštní funkce a tu pak jen volat s různými parametry.

Následující funkce shoping_list pouze vypíše nákupní seznam ve speciálním formátu. Přestože výsledek je netriviální, samotná funkce zůstává jednoduchá díky volání funkce frame, která se stará o formátování.

3.2.1. Dělitelé

Napište funkci divisors(n), která vypíše všechny dělitele čísla n.

def divisors(n):
    pass

divisors(1)     # 1
divisors(5)     # 1 5
divisors(42)    # 1 2 3 6 7 14 21 42
divisors(127)   # 1 127
divisors(1024)  # 1 2 4 8 16 32 64 128 256 512 1024

3.2.2. Počet dělitelů

Napište funkci divisors_count(n), která vrátí počet dělitelů čísla n.

def divisors_count(n):
    pass

def test_divisors_count():
    assert divisors_count(1) == 1
    assert divisors_count(5) == 2
    assert divisors_count(42) == 8
    assert divisors_count(127) == 2
    assert divisors_count(1024) == 11

3.2.3. Je prvočíslo

Napište funkci is_prime(n), která vrátí True pokud je číslo n prvočíslo, jinak False.

def is_prime(n):
    pass

def test_is_prime():
    assert is_prime(1) == False
    assert is_prime(2) == True
    assert is_prime(3) == True
    assert is_prime(42) == False
    assert is_prime(127) == True

3.2.4. Prvočísla menší než n

Napište funkci primes_less_than(limit), která vypíše všechna prvočísla menší než limit.

def primes_less_than(limit):
    pass

primes_less_than(5)      # 2 3
primes_less_than(15)     # 2 3 5 7 11 13
primes_less_than(100)
# 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

3.2.5. k-té prvočíslo

Napište funkci kth_prime(k), která vrátí k-té prvočíslo.

def kth_prime(k):
    pass

def test_kth_prime():
    assert kth_prime(1) == 2
    assert kth_prime(2) == 3
    assert kth_prime(10) == 29
    assert kth_prime(100) == 541

3.2.6. Prvních k prvočísel

Napište funkci primes(count), která vypíše prvních count prvočísel.

def primes(count):
    pass

primes(2)      # 2 3
primes(5)      # 2 3 5 7 11
primes(10)     # 2 3 5 7 11 13 17 19 23 29

3.2.7. Prvních k prvočíselných dvojčat

Napište funkci twin_primes(count), která vypíše prvních count prvočíselných dvojčat.

def twin_primes(count):
    pass

twin_primes(2)      # 3-5, 5-7,
twin_primes(5)      # 3-5, 5-7, 11-13, 17-19, 29-31,
twin_primes(10)
# 3-5, 5-7, 11-13, 17-19, 29-31, 41-43, 59-61, 71-73, 101-103, 107-109,

3.2.8. Rozklad na prvočísla

Napište funkci factorization(n), která vypíše rozklad čísla n na prvočísla (jen jako součin).

def factorization(n):
    pass

factorization(2)        # 2
factorization(7)        # 7
factorization(25)       # 5 5
factorization(42)       # 2 3 7
factorization(360)      # 2 2 2 3 3 5
factorization(1024)     # 2 2 2 2 2 2 2 2 2 2

3.2.9. Rozklad na prvočísla s mocninami

Napište funkci power_factorization(n), která vypíše rozklad čísla n na prvočísla v mocninném tvaru.

def power_factorization(n):
    pass

power_factorization(2)      # 2^1
power_factorization(7)      # 7^1
power_factorization(25)     # 5^2
power_factorization(42)     # 2^1 3^1 7^1
power_factorization(360)    # 2^3 3^2 5^1
power_factorization(1024)   # 2^10

3.2.10. Největší společný dělitel - naivně

Napište funkci gcd(a, b), která vrátí největší společný dělitel čísel a a b. Funkce může pracovat naivně, tj. zkoušet všechny možnosti a podobně.

def gcd(a, b):
    pass

def test_gcd():
    assert gcd(5, 7) == 1
    assert gcd(8, 8) == 8
    assert gcd(10, 5) == 5
    assert gcd(5, 10) == 5
    assert gcd(42, 36) == 6
    assert gcd(0, 7) == 7

3.2.11. Nejmenší společný násobek

Napište funkci lcm(a, b), která vrátí nejmenší společný násobek čísel a a b.

def lcm(a, b):
    pass

def test_lcm():
    assert lcm(6, 9) == 18
    assert lcm(6, 7) == 42
    assert lcm(3, 9) == 9
    assert lcm(9, 3) == 9
    assert lcm(360, 42) == 2520

3.2.12. Euklidův algoritmus

Implementujte Euklidův algoritmus.

def euclid(a, b):
    pass

def test_euclid():
    assert euclid(5, 7) == 1
    assert euclid(8, 8) == 8
    assert euclid(10, 5) == 5
    assert euclid(5, 10) == 5
    assert euclid(42, 36) == 6

3.3. Aproximace

3.3.1. Eulerovo číslo

Napište funkci e() pro přibližný výpočet Eulerova čísla pomocí nekonečného součtu s přesností na miliontiny.

def e():
    pass

print(e())      # 2.718282

3.3.2. Pi

Napište funkci pi() pro přibližný výpočet čísla pi pomocí Leibnizovy řady s přesností na tisíciny.

def pi():
    pass

print(pi())      # 3.141

3.3.3. Aproximace sinu

Napište funkci sinus(x) pro výpočet sinu úhlu x (v radiánech) pomocí Taylorovy řady (sekce Příklady Taylorova rozvoje: sin x) s přesností na tisíciny.

from math import pi

def sinus(x):
    pass

print(sinus(1.2))      # 0.932
print(sinus(0))        # 0.0
print(sinus(pi/4))     # 0.707
print(sinus(pi/2))     # 1.0

3.3.4. Aproximace cosinu

Napište funkci cosinus(x) pro výpočet cosinu úhlu x (v radiánech) pomocí Taylorovy řady (sekce Příklady Taylorova rozvoje: cosin x) s přesností na tisíciny.

from math import pi

def cosinus(x):
    pass

print(cosinus(1.2))      # 0.362
print(cosinus(0))        # 1.0
print(cosinus(pi/4))     # 0.707
print(cosinus(pi/2))     # 0.0

3.4. Převody mezi číselnými soustavami

Motivační vtip:

Q: Why do programmers always mix up Halloween and Christmas?

A: Because Oct 31 == Dec 25!

3.4.1. Převod z desítkové soustavy do dvojkové

Napište funkci convert_10_to_2(n), která vrátí zadané číslo n ve dvojkové soustavě jako řetězec.

def convert_10_to_2(x):
    pass

def test_convert_10_to_2():
    assert convert_10_to_2(2) == "10"
    assert convert_10_to_2(8) == "1000"
    assert convert_10_to_2(10) == "1010"
    assert convert_10_to_2(31) == "11111"
    assert convert_10_to_2(42) == "101010"

3.4.2. Převod z dvojkové soustavy do desítkové

Napište funkci convert_2_to_10(n), která vrátí zadaný řetězec n reprezentující binární číslo v desítkové soustavě jako int.

def convert_2_to_10(n):
    for b in n[::-1]:
        b   # jednotlive bity od zadu

def test_convert_2_to_10():
    assert convert_2_to_10("10") == 2
    assert convert_2_to_10("1000") == 8
    assert convert_2_to_10("1010") == 10
    assert convert_2_to_10("11111") == 31
    assert convert_2_to_10("101010") == 42

3.4.3. Převod z desítkové soustavy do jiné

Napište funkci convert_10_to_x(n, symbols), která vrátí zadané číslo n v jiné soustavě – soustava, do které převádíme, bude zadána řetězcem znaků symbols, které používá.

def convert_10_to_x(n, symbols):
    pass

def test_convert_10_to_x():
    assert convert_10_to_x(42, "01") == "101010"
    assert convert_10_to_x(42, "0123") == "222"
    assert convert_10_to_x(42, "0123456789") == "42"
    assert convert_10_to_x(42, "0123456789ABCDEF") == "2A"
Next Section - 4. Náhodná čísla