import math
import csv
def max_n_log(time_seconds):
# f(n) = log2(n)
# czyli log2(n) <= microseconds -> n <= 2^microseconds
microseconds = time_seconds * 1_000_000
log10_n = microseconds * math.log10(2) # zeby nie wybuchlo, zapis jako 10^x
return f"≈ 10^{log10_n:,.0f}".replace(",", " ")
def max_n_linear(time_seconds):
# f(n) = n, easy, n <= microseconds
microseconds = time_seconds * 1_000_000
return f"{int(microseconds):,}".replace(",", " ")
def max_n_nlogn(time_seconds):
# f(n) = n * log2(n)
# tego nie rozwiazesz recznie, trzeba przyblizenie
microseconds = time_seconds * 1_000_000
left, right = 1, 10**18 # na pewno wystarczy lol
while left < right:
mid = (left + right) // 2
f = mid * math.log2(mid)
if f <= microseconds:
left = mid + 1
else:
right = mid - 1
return f"{left:,}".replace(",", " ")
def max_n_quadratic(time_seconds):
# f(n) = n^2 -> n <= sqrt(microseconds)
microseconds = time_seconds * 1_000_000
n = int(math.sqrt(microseconds))
return f"{n:,}".replace(",", " ")
def max_n_cubic(time_seconds):
# f(n) = n^3 -> n <= microseconds^(1/3)
microseconds = time_seconds * 1_000_000
n = int(round(microseconds ** (1/3)))
return f"{n:,}".replace(",", " ")
def max_n_exponential(time_seconds):
# f(n) = 2^n -> 2^n <= microseconds -> n <= log2(microseconds)
microseconds = time_seconds * 1_000_000
n = int(math.log2(microseconds))
return f"{n:,}".replace(",", " ")
def max_n_factorial(time_seconds):
# f(n) = n! -> n! <= microseconds -> trzeba jechac petla bo inaczej nie policzysz
microseconds = time_seconds * 1_000_000
n = 1
fact = 1
while fact <= microseconds:
n += 1
fact *= n
return f"{n-1:,}".replace(",", " ")
# dobra tu ustawiamy czasy
czasy = [
("1 sekunda", 1),
("1 minuta", 60),
("1 godzina", 3600),
("1 dzień", 86400),
("1 miesiąc", 30 * 86400),
("1 rok", 365 * 86400)
]
# export to csv using primewriter
with open("czasy_transposed.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
# kolumny: nagłówek z etykietami czasu
header = ["label"] + [label for label, _ in czasy]
writer.writerow(header)
# helper do pisania wiersza
def write_row(name, func):
row = [name] + [func(seconds) for _, seconds in czasy]
writer.writerow(row)
# teraz każdy wiersz odpowiada jednej funkcji złożoności
writer.writerow(["seconds"] + [seconds for _, seconds in czasy])
write_row("lg(n)", max_n_log)
write_row("n", max_n_linear)
write_row("n·lg(n)", max_n_nlogn)
write_row("n²", max_n_quadratic)
write_row("n³", max_n_cubic)
write_row("2ⁿ", max_n_exponential)
write_row("n!", max_n_factorial)
# i lecimy z tabela
for label, seconds in czasy:
print("================================")
print(f"{label.upper()}") # no ładnie niech wygląda
print("================================")
print(f"lg(n): n ≤ {max_n_log(seconds)}")
print(f"n: n ≤ {max_n_linear(seconds)}")
print(f"n·lg(n): n ≤ {max_n_nlogn(seconds)}")
print(f"n²: n ≤ {max_n_quadratic(seconds)}")
print(f"n³: n ≤ {max_n_cubic(seconds)}")
print(f"2ⁿ: n ≤ {max_n_exponential(seconds)}")
print(f"n!: n ≤ {max_n_factorial(seconds)}")
print() # pusta linia zeby nie bolało w oczy
# porownaj na wykresie zlozonosci dla osi n / czas
import matplotlib.pyplot as plt
import numpy as np
# dobra, tu robimy dane testowe, bo tych ogromnych liczb i tak nie narysujesz sensownie
# weźmy np. n od 1 do 100 (dla 2^n i n!) i do 1e6 (dla n, n^2, n log n)
n_linear = np.linspace(1, 1e6, 500) # 500 punktow, wystarczy
n_small = np.arange(1, 30) # do wykładniczych
# przeliczamy "czas" w mikrosekundach (nie ma znaczenia jednostka, chodzi o kształt)
y_log = np.log2(n_linear)
y_n = n_linear
y_nlogn = n_linear * np.log2(n_linear)
y_n2 = n_linear**2
y_n3 = n_linear**3
y_2n = 2**n_small
y_fact = [math.factorial(i) for i in n_small]
plt.figure(figsize=(10,6))
# rysujemy wykresy — używamy skali log bo inaczej wszystko zniknie xd
plt.plot(n_linear, y_log, label='lg(n)')
plt.plot(n_linear, y_n, label='n')
plt.plot(n_linear, y_nlogn, label='n·lg(n)')
plt.plot(n_linear, y_n2, label='n²')
plt.plot(n_linear, y_n3, label='n³')
plt.plot(n_small, y_2n, label='2ⁿ')
plt.plot(n_small, y_fact, label='n!')
plt.yscale("log")
plt.xscale("log")
plt.title("Porównanie złożoności czasowych algorytmów")
plt.xlabel("Rozmiar problemu n (skala log)")
plt.ylabel("Czas wykonania f(n) (skala log)")
plt.legend()
plt.grid(True, which="both", linestyle="--", alpha=0.4)
# troche marginesu bo n! szybko idzie w kosmos
plt.tight_layout()
plt.show()