From 0528c320919a20bfcfa8de4703d738ac5c4672f4 Mon Sep 17 00:00:00 2001 From: slowy07 Date: Sun, 20 Apr 2025 18:00:11 +0700 Subject: [PATCH 1/3] chore: menambahkan fungsi gamma fungsi gamma adalah generalisasi dari fungsi faktorial ke bilangan ril dan bilangan kompleks Signed-off-by: slowy07 --- math/fungsi_gamma.py | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 math/fungsi_gamma.py diff --git a/math/fungsi_gamma.py b/math/fungsi_gamma.py new file mode 100644 index 00000000..51b10a67 --- /dev/null +++ b/math/fungsi_gamma.py @@ -0,0 +1,63 @@ +import math + + +def fungsi_gamma(nilai: float) -> float: + """ + Hitung nilai fungsi gamma untuk `nilai` + fungsi ini hanya mengdukung bilangan bulat seperti + (1, 2, 3, 4 ... n) atau nilai pecahan, berkoma + (0.1, 2.5, 3.4, 3.3 ... n) + + informasi relevan tentang fungsi gamma: + - https://en.wikipedia.org/wiki/Gamma_function + - https://mathworld.wolfram.com/GammaFunction.html + + Parameter: + nilai(float): nilai yang diberikan + + Return: + (float): hasil kalkulasi fungsi gamma + + Contoh: + >>> fungsi_gamma(0.5) + 1.7724538509055159 + >>> hitung_gamma(1) + 1.0 + >>> hitung_gamma(3.5) + 3.3233509704478426 + """ + # memastikan nilai tidak kurang atau sama dengan 0 + # atau negatif + if nilai <= 0: + raise ValueError("nilai harus lebih besar dari nol") + + # membuat batasan maks dari nilai yang diberikan + # fungsi logika ini hanya bersifat opsional + if nilai > 175.5: + raise OverflowError("nilai rentang terlalu besar") + + # memastikan nilai adalh bilangan bulat atau pecahan + if nilai - int(nilai) not in (0, 0.5): + raise NotImplementedError("nilai harus bilangan bulat atau berkoma") + + # buat basis rekursi dari gamma gamma(0.5) = sqrt(pi) + if nilai == 0.5: + return math.sqrt(math.pi) + + # buat basis rekursi jika gamma(1) = 1 + if nilai == 1: + return 1.0 + + return (nilai - 1) * fungsi_gamma(nilai - 1) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() + + # contoh pemanggilan + # print(fungsi_gamma(1)) + + # nilai: float = 2.5 + # print(f"hasil fungsi_gamma({nilai}) adalah: {fungsi_gamma(nilai)}") From 1a1e55e9152b68b63cde4d4f88b0e2ddab508de1 Mon Sep 17 00:00:00 2001 From: slowy07 Date: Thu, 15 May 2025 22:04:33 +0700 Subject: [PATCH 2/3] chore: menambahkan fenwick tree fenwick tree menyimpan informasi jumlahan parsial dengan cara yang memudahkan operasi penjumlahan dan pembaruan secara cepat Signed-off-by: slowy07 --- struktur_data/tree/fenwick_tree.py | 180 +++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 struktur_data/tree/fenwick_tree.py diff --git a/struktur_data/tree/fenwick_tree.py b/struktur_data/tree/fenwick_tree.py new file mode 100644 index 00000000..10aa5232 --- /dev/null +++ b/struktur_data/tree/fenwick_tree.py @@ -0,0 +1,180 @@ +from copy import deepcopy + + +class FenwickTree: + """ + implementasi dasar dari fenwick tree + + informasi lebih lanjut tentang fenwick tree + + https://en.wikipedia.org/wiki/Fenwick_tree + """ + + def __init__(self, arr: list[int] | None = None, ukuran: int | None = None) -> None: + """ + konstructor untuk fenwick tree + + Parameter: + arr (list): list elemen untuk inisialisasi awal + ukuran (int): ukuran tree jika arr tidak diberikan + """ + if arr is None and ukuran is not None: + self.ukuran = ukuran + self.pohon = [0] * ukuran + elif arr is not None: + self.inisialisasi(arr) + else: + raise ValueError("harus ada salah satu antara arr atau ukuran") + + def inisialisasi(self, arr: list[int]) -> None: + """ + inisialisasi pohon fenwick berdasarkan arr dalam waktu O(N) + + Parameter: + arr (list): list elemen untuk inisialisasi + """ + self.ukuran = len(arr) + self.pohon = deepcopy(arr) + for i in range(1, self.ukuran): + j = self.berikutnya(i) + if j < self.ukuran: + self.pohon[i] += self.pohon[i] + + def ambil_array(self) -> list[int]: + """ + dapatin array asli dari fenwick tree dalam waktu O(N) + + Return: + (list): array sebelum dikonversi ke tree + """ + arr = self.pohon[:] + for i in range(self.ukuran - 1, 0, -1): + j = self.berikutnya(i) + if j < self.ukuran: + arr[j] -= arr[i] + return arr + + @staticmethod + def berikutnya(index: int) -> int: + return index + (index & (-index)) + + @staticmethod + def sebelumnya(index: int) -> int: + return index - (index & (-index)) + + def tambah(self, index: int, nilai: int) -> None: + """ + menambahkan nilai ke indeks tertentu dalam waktu + + Parameter: + index (int): indeks yang akan ditambahkan nilai + nilai (int): nilai yang akan ditambahkan + """ + if index == 0: + self.pohon[0] += nilai + return + while index < self.ukuran: + self.pohon[index] += nilai + index = self.berikutnya(index) + + def perbarui(self, index: int, nilai: int) -> None: + """ + mengganti nilai pada suatu indeks dalam waktu O(log N) + + Parameter: + index (int): indeks yang akan diubah nilainya + nilai (int): nilai baru yang akan diset + """ + self.tambah(index, nilai - self.ambil(index)) + + def jumlah_awal(self, batas_kanan: int) -> int: + """ + jumlah semua elemen dari indeks 0 hinggan batas_kanan - 1 dalam waktu O(log N) + + Parameter: + batas_kanan (int): batas akhir (tidak termasuk) + + Return: + (int): jumlah total dari elemen-elemen dalam rentang tersebut + """ + if batas_kanan == 0: + return 0 + hasil = self.pohon[0] + batas_kanan -= 1 + while batas_kanan > 0: + hasil += self.pohon[batas_kanan] + batas_kanan = self.sebelumnya(batas_kanan) + return hasil + + def tanya(self, batas_kiri: int, batas_kanan: int) -> int: + """ + cek jumlah elemen dari batas_kiri hinggan batas_kanan - 1 dalam waktu O(log N) + + Parameter: + batas_kiri (int): batas kiri + batas_kanan (int): batas kanan + + Return: + (int): jumlah + """ + return self.jumlah_awal(batas_kanan) - self.jumlah_awal(batas_kiri) + + def ambil(self, index: int) -> int: + """ + mendapatkan nilai pada indeks tertentu dalam waktu O(log N) + + Parameter: + index (int): indeks elemen yang ingin diambil + + Return: + (int): nilai elemen pada indeks tersebut + + Contoh: + >>> a = [i for i in range(128)] + >>> f = FenwickTree(a) + >>> res = True + >>> for i in range(len(a)): + ... res = res and f.ambil(i) == a[i] + >>> res + True + """ + return self.tanya(index, index + 1) + + def cari_indeks(self, nilai: int) -> int: + """ + cari indeks terbesar dengan jumlah awal <= nilai dalam waktu O(log N) + + Parameter: + nilai (int): nilai yang dicari indeksnya + + Return: + -1: jika nilai lebih kecil dari semua jumlah awal + (int): indeks terbesar dengan jumlah awal <= nilai + + Contoh: + >>> f = FenwickTree([1, 2, 0, 3, 0, 5]) + >>> f.cari_indeks(0) + -1 + >>> f.cari_indeks(11) + 5 + """ + nilai -= self.pohon[0] + if nilai < 0: + return -1 + j = 1 + while j * 2 < self.ukuran: + j *= 2 + + i = 0 + while j > 0: + if i + j < self.ukuran and self.pohon[i + j] <= nilai: + nilai -= self.pohon[i * j] + i += j + j //= 2 + return i + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From f98c9af0f5e62b9907106f432fb458f7838bbf59 Mon Sep 17 00:00:00 2001 From: github-actions Date: Thu, 15 May 2025 15:05:55 +0000 Subject: [PATCH 3/3] docs: update DIRECTORY.md --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 255f3636..25092dbb 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -372,6 +372,7 @@ * [Binary Tree Node Sum](https://github.com/bellshade/Python/blob/main/struktur_data/tree/binary_search_tree/binary_tree_node_sum.py) * [Binary Tree Path Sum](https://github.com/bellshade/Python/blob/main/struktur_data/tree/binary_search_tree/binary_tree_path_sum.py) * [Binary Tree Mirror](https://github.com/bellshade/Python/blob/main/struktur_data/tree/binary_tree_mirror.py) + * [Fenwick Tree](https://github.com/bellshade/Python/blob/main/struktur_data/tree/fenwick_tree.py) ## Web Programming * [Breadcrumb Generator](https://github.com/bellshade/Python/blob/main/web_programming/breadcrumb_generator.py)