import numpy as np


# Vytvoří matici s dimenzi (r,s) vyplněnou číslem c.
def matice_c(r, s, c):
    return np.ones((r, s)) * c


# Vytvoří matici s dimenzi (r,s), která má na okrajích 1 jinde 0
def matice_s_okrajem(r, s):
    m = np.ones((r, s))
    m[1:-1, 1:-1] = 0
    return m


# Vytvoří matici s dimenzi (r,s), kde odpovidaji elementy i-tého řádku číslu i
def matice_s_ocislovanymi_radky(r, s):
    return np.arange(r)[:, np.newaxis] * np.ones(s)


def determinant_10_matic(s):
    ms = []
    for _ in range(10):
        m = np.random.uniform(1, -1, (s, s))
        ms.append({'matice': m,
                   'determinant': np.linalg.det(m)})
    return ms


# Uvažujme "průměrovací Fibonacciho čísla" definovaná rekurentním vztahem xi = (xi-1 + xi-2) / 2.
# Víme-li, že x8=426 a x9=427, kolik je x0 a x1?
# Vyřešte soustavu lineárních rovnic pomocí np.linalg.solve.
def vyres_fib_prumery():
    n = 10

    a = -np.eye(n) / 2 - np.eye(n, k=1) / 2 + np.eye(n, k=2)
    a[-2:, -2:] = np.eye(2)
    b = np.zeros(n)
    b[-2] = 426
    b[-1] = 427
    x = np.linalg.solve(a, b)
    return x[:2]


# Matice s dimenzi r a r, má true na pozici, kde je index řádku dělitelný indexem sloupce
def matice_delitelnosti(r):
    return np.arange(1, r)[:, np.newaxis] % np.arange(1, r) == 0


r, s = (5, 4)
c = 5
i = 2

print(f"Pro vstupy r={r}, s={s} a c={c} matice_c vrací:")
print(matice_c(r, s, c))

print(f"Pro vstupy r={r}, s={s} matice_s_okrajem vrací:")
print(matice_s_okrajem(r, s))

print(f"Pro vstupy r={r}, s={s} matice_s_ocislovanymi_radky vrací:")
print(matice_s_ocislovanymi_radky(r, s))

print(f"Deset matic a jejich determinant:")
print(determinant_10_matic(3))

print("")
print("========= BONUS ==========")
print(f"Pro x_8=426 a x_9=427 najdi x_0, x_1 \"průměrovací Fibonacciho čísla\":")
print(vyres_fib_prumery())

print(f"Matice dělitelnosti s dimenzi ({r - 1}, {r - 1})")
print(matice_delitelnosti(r))
