# %% Generátory skvěle doplňují některé vestavěné funkce. Fungují obecně s libovolným iterable. Například all:
in_lst = [8, 9, 15, 25, 6]
result_all = all(x > 10 for x in in_lst)
print(f'all: {result_all}')


# %% Funkce pro práci s generátory - any:
result_any = any(x > 10 for x in in_lst)
print(f'any: {result_any}')


# %% Funkce pro práci s generátory - min a max:
result_min = min(x ** 2 for x in in_lst)
result_max = max(x ** 2 for x in in_lst)
print(f'min squared: {result_min}')
print(f'max squared: {result_max}')


# %% Funkce pro práci s generátory - sum:
result_sum = sum(x ** 2 for x in in_lst)
print(f'sum: {result_sum}')


# %% Itertools- funkce pro práci s iterables (tedy i generátory). itertools.cycle:
from itertools import cycle


for i, val in enumerate(cycle(x ** 2 for x in range(0, 10))):
    print(f'[{i}] = {val}')
    if i >= 100:
        break


# %% itertools.repeat():
from itertools import repeat


for i, val in enumerate(repeat(42, 10)):
    print(f'[{i}] = {val}')


# %% itertoos.chain():
from itertools import chain


for val in chain(range(0, 3), range(10, 13), range(100, 103)):
    print(val)

# %% itertools.islice():
from itertools import islice


for val in islice((x ** 2 for x in range(0, 100)), 2, 12, 2):
    print(val)


# %% itertools.starmap():
from itertools import starmap


arg_list = [
    (1, 1, 2),
    (10, 10, 4),
    (5, 5, 12),
]


def expr_fn(a, b, c):
    return (a + b) * c


for val in starmap(expr_fn, arg_list):
    print(val)


#%% itertools.filterfalse():
from itertools import filterfalse


for value in filterfalse(lambda n: n % 2 == 0, range(0, 10)):
    print(value)


#%% itertools.takewhile():
from itertools import takewhile


in_lst = [2, 4, 8, 12, 0, 10, 25, 6]

for i in takewhile(lambda x: x > 0, (x ** 2 for x in in_lst)):
    print(i)


#%% itertools.dropwhile():
from itertools import dropwhile


in_lst = [2, 4, 8, 12, 0, 14, 25, 9]

for i in dropwhile(lambda x: x > 0, (x ** 2 for x in in_lst)):
    print(i)


#%% itertools.ziplongest() - generuje, dokud může:
from itertools import zip_longest


zip_long = zip_longest(range(0, 5), range(0, 10))
print(f'zip_long = {list(zip_long)}')


#%% itertools.ziplongest() - lze specifikovat i hodnotu, kterou prázdná místa vyplnit:
zip_long = zip_longest(range(0, 5), range(0, 10), fillvalue=-1)
print(f'zip_long = {list(zip_long)}')


#%% itertools.product():
from itertools import product


for i in product(range(1, 7), range(1, 7)):
    print(i)


#%% itertools.permutations():
from itertools import permutations


for i in permutations('ABC'):
    print(i)


#%% itertools.combinations():
from itertools import combinations


for i in combinations('ABC', 2):
    print(i)
