diff --git a/math/deret_geometri.cpp b/math/deret_geometri.cpp new file mode 100644 index 0000000..2516591 --- /dev/null +++ b/math/deret_geometri.cpp @@ -0,0 +1,201 @@ +/** + * @brief Program untuk mensimulasikan deret geometri. + * + * Program ini menyediakan berbagai overload fungsi untuk menghitung + * suku ke-n, jumlah n suku pertama, serta memvisualisasikan deret + * geometri berdasarkan rasio dan suku awal yang diberikan. + * + * @details + * - Mengimplementasikan konsep *three-pair overload*, yaitu hanya satu fungsi + * utama yang bekerja dengan parameter berbasis iterator, sementara dua overload + * lainnya (untuk parameter `initializer_list` dan tiga nilai langsung `a, r, + * n`) hanya berperan sebagai pembungkus (*wrapper*) yang memanggil fungsi utama + * tersebut. + * - Dengan pendekatan ini, hanya ada satu sumber logika inti, sehingga + * memudahkan pemeliharaan dan menghindari duplikasi kode. + * - Mendukung perhitungan berbasis bilangan bulat (integer-only) + * sehingga tidak perlu mengkhawatirkan kesalahan presisi floating point. + * - Menggunakan indeks berbasis 0 (0-based indexing), artinya suku pertama + * berada pada indeks 0. + * - Dapat digunakan untuk eksperimen atau pembelajaran konsep deret geometri + * dengan parameter yang bervariasi. + * + * @authors Muh Yusuf + * @note Program ini bekerja dengan 0-based indexed. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/** + * @brief Menghitung rasio (r) dari suatu deret geometri. + * + * @details + * Fungsi ini bekerja dengan dua iterator (`first` dan `last`) yang + * merepresentasikan rentang elemen dalam deret geometri. Nilai rasio ditentukan + * dengan membagi elemen kedua dengan elemen pertama dari deret tersebut. + * + */ +template +auto rasio(It first, It last) + -> std::common_type_t, std::size_t> { + using common = std::common_type_t, std::size_t>; + std::vector deret(first, last); + if (deret.size() < 2) { + return *deret.begin(); + } + return deret[1] / deret[0]; +} +template + requires(std::integral>) +auto rasio(It first, It last, std::size_t pos_1, std::size_t pos_2) + -> std::common_type_t, std::size_t> { + std::vector deret(first, last); + if (deret.size() < 2) { + return *deret.begin(); // return suku pertama + } + using common = std::common_type_t, std::size_t>; + auto val_pos1 = deret[pos_1]; + auto val_pos2 = deret[pos_2]; + common rhs = (pos_1 < pos_2) ? val_pos2 / val_pos1 : val_pos1 / val_pos2; + double lhs = pos_1 < pos_2 ? pos_2 - 1 : pos_1 - pos_2; + common result = pow(rhs, 1.0 / lhs); + return result; +} +/** + * @brief Menghitung suku ke-n dari deret geometri. + * + * @details + * Fungsi ini menerima dua iterator (`first`, `last`) yang menunjuk ke deret + * bilangan geometri dan sebuah parameter `n` yang menunjukkan suku ke-n yang + * ingin dihitung. + * + * Cara kerja: + * 1. Menentukan rasio umum deret dengan memanggil fungsi `rasio()`. + * 2. Mengambil nilai suku pertama (`a`). + * 3. Menggunakan rumus dasar deret geometri: + * + * U_n = a + r^(n - 1) + * dimana: + * Un = rumus suku ke-n + * a = suku pertama + * r = rasio + * n = suku yang ingin diketahui + * Nilai dikembalikan dalam tipe data yang merupakan hasil dari + * `std::common_type_t` antara nilai iterator dan `std::size_t`. + */ +template + requires(std::integral>) +auto suku_keN(It first, It last, std::size_t n) + -> std::common_type_t, std::size_t> { + using common = std::common_type_t, std::size_t>; + common _rasio = rasio(first, last); + std::vector deret(first, last); + common res = deret.front() * pow(_rasio, n - 1); + return res; +} +/** + * @brief Menghasilkan representasi string dari rumus umum suku ke-n deret + * geometri. + * + * @details + * Fungsi ini menyusun rumus dalam bentuk teks menggunakan nilai suku pertama + * (`a`) dan rasio (`r`) yang diperoleh dari deret. + * + * Rumus yang dihasilkan berbentuk: + * + * ``` + * Un = a * r^(n - 1) + * ``` + */ +template + requires(std::integral>) +std::string rumus_suku_KeN(It first, It last){ + // using common = std::common_type,std::size_t>; + using type_iter = std::iter_value_t; + type_iter a = *first; + type_iter r = rasio(first, last); + std::ostringstream oss; + oss << "Un = " << a << " + " << r << "^n - 1"; + return oss.str(); +} +template + requires(std::integral) +// jika 2 diketahui 2 suku berurutan +T rasio(T suku_1, T suku_2) { + return suku_2 > suku_1 ? suku_2 / suku_1 : suku_1 / suku_2; +} +// jika tidak ketahui suku berurutan tetapi diberikan deret +template + requires(std::integral) +T rasio(std::initializer_list arr) { + return rasio(arr.begin(), arr.end()); +} +// jika diketahui 2 suku ke n yang tidak beurutan +template + requires(std::integral) +auto rasio(std::initializer_list arr, std::size_t pos_1, std::size_t pos_2) + -> std::common_type_t { + return rasio(arr.begin(), arr.end(), pos_1, pos_2); +} +// jika diketahui deret +template + requires(std::integral>) +auto rasio(arr &&R) { + return rasio(R.begin(), R.end()); +} +template + requires(std::integral>) +auto rasio(arr &&R, std::size_t pos_1, std::size_t pos_2) { + return rasio(R.begin(), R.end(), pos_1, pos_2); +} +template + requires(std::integral) +auto suku_keN(std::initializer_list arr, std::size_t n) { + return suku_keN(arr.begin(), arr.end(), n); +} +template + requires(std::integral>) +auto suku_keN(arr &&R, std::size_t n) { + return suku_keN(R.begin(), R.end(), n); +} +template + requires(std::integral) +std::string rumus_suku_KeN(std::initializer_list arr) { + return rumus_suku_KeN(arr.begin(), arr.end()); +} +template + requires(std::integral>) +std::string rumus_suku_KeN(arr &&R) { + return rumus_suku_KeN(R.begin(), R.end()); +} +int main() { + std::cout << "jika hanya diketahui 2 suku berurutan" << std::endl; + std::cout << "hasil: " << rasio(2, 4) << std::endl; + std::cout << "jika diketahui 2 suku tidak berurutan(base on index)" << std::endl; + std::cout << "hasil: " << rasio({2, 4, 8, 16}, 0, 2) << std::endl; + std::vector a = {3, 6, 12, 24}; + std::cout << "menggunakan ranges" << std::endl; + std::cout << rasio(a) << std::endl; + std::cout << "rumus suku keN" << std::endl; + std::cout << "rumus: " << rumus_suku_KeN(a) << std::endl; + // Menggunakan iterator langsung (begin, end) + std::cout << "[4] Menggunakan iterator langsung\n"; + std::vector deret1 = {2, 6, 18, 54}; + std::cout << "rasio(deret1.begin(), deret1.end()) = " + << rasio(deret1.begin(), deret1.end()) << std::endl; + // Menghitung nilai suku ke-n (iterator) + std::cout << "[8] Nilai suku ke-n (iterator)\n"; + std::vector deret3 = {3, 6, 12, 24}; + std::cout << "suku_keN(deret3.begin(), deret3.end(), 5) = " + << suku_keN(deret3.begin(), deret3.end(), 5) << "\n\n"; + std::cin.get(); + return 0; +} \ No newline at end of file