Skip to content

Commit 70e65ee

Browse files
feat: implement deret geometri
# Deskripsi (Description) Menambahkan source code untuk mensimulasikan `deret geometri`. Program ini menyediakan implementasi komprehensif untuk melakukan berbagai operasi terkait deret geometri, termasuk: - Menghitung **rasio (r)** antara dua atau lebih suku dalam deret. - Menentukan **suku ke-n (Un)** dari deret geometri dengan memanfaatkan rasio dan suku awal. - Menampilkan **rumus umum** dari deret dalam bentuk string agar mudah dibaca dan dipahami. Seluruh implementasi dirancang dengan menggunakan **konsep `three pair`**, yaitu memusatkan logika utama pada fungsi yang menerima **input iterator**. Dengan pendekatan ini, versi overload lain seperti yang menerima `std::initializer_list` atau `std::ranges::input_range` cukup melakukan **delegasi** (memanggil) fungsi utama tersebut tanpa perlu duplikasi logika. # Checklist: ##### Umum: - [x] Saya menambah algoritma terbaru. ##### Contributor Requirements (Syarat Kontributor) dan Lain-Lain: - [x] Saya sudah membaca (I have read) [CONTRIBUTING](https://github.com/bellshade/CPP/blob/main/CONTRIBUTING.md) dan sudah menyetujui semua syarat. - [x] Saya telah menambahkan komentar kode yang memberikan penjelasan maksud dari kode yang saya buat. - [x] Saya menggunakan bahasa Indonesia untuk memberikan penjelasan dari kode yang saya buat. # Environment Saya menggunakan (I'm using): - ``OS`` = `Linux` - ``g++`` = `15.2.1` # Link Issues Issues : # This Commit License https://github.com/bellshade/CPP/blob/main/license Co-authored-by: bellshadebot <[email protected]>
1 parent c6b8e19 commit 70e65ee

File tree

1 file changed

+201
-0
lines changed

1 file changed

+201
-0
lines changed

math/deret_geometri.cpp

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
/**
2+
* @brief Program untuk mensimulasikan deret geometri.
3+
*
4+
* Program ini menyediakan berbagai overload fungsi untuk menghitung
5+
* suku ke-n, jumlah n suku pertama, serta memvisualisasikan deret
6+
* geometri berdasarkan rasio dan suku awal yang diberikan.
7+
*
8+
* @details
9+
* - Mengimplementasikan konsep *three-pair overload*, yaitu hanya satu fungsi
10+
* utama yang bekerja dengan parameter berbasis iterator, sementara dua overload
11+
* lainnya (untuk parameter `initializer_list` dan tiga nilai langsung `a, r,
12+
* n`) hanya berperan sebagai pembungkus (*wrapper*) yang memanggil fungsi utama
13+
* tersebut.
14+
* - Dengan pendekatan ini, hanya ada satu sumber logika inti, sehingga
15+
* memudahkan pemeliharaan dan menghindari duplikasi kode.
16+
* - Mendukung perhitungan berbasis bilangan bulat (integer-only)
17+
* sehingga tidak perlu mengkhawatirkan kesalahan presisi floating point.
18+
* - Menggunakan indeks berbasis 0 (0-based indexing), artinya suku pertama
19+
* berada pada indeks 0.
20+
* - Dapat digunakan untuk eksperimen atau pembelajaran konsep deret geometri
21+
* dengan parameter yang bervariasi.
22+
*
23+
* @authors Muh Yusuf
24+
* @note Program ini bekerja dengan 0-based indexed.
25+
*/
26+
#include <cmath>
27+
#include <concepts>
28+
#include <cstddef>
29+
#include <initializer_list>
30+
#include <iostream>
31+
#include <iterator>
32+
#include <ranges>
33+
#include <sstream>
34+
#include <string>
35+
#include <type_traits>
36+
#include <vector>
37+
/**
38+
* @brief Menghitung rasio (r) dari suatu deret geometri.
39+
*
40+
* @details
41+
* Fungsi ini bekerja dengan dua iterator (`first` dan `last`) yang
42+
* merepresentasikan rentang elemen dalam deret geometri. Nilai rasio ditentukan
43+
* dengan membagi elemen kedua dengan elemen pertama dari deret tersebut.
44+
*
45+
*/
46+
template <std::input_iterator It>
47+
auto rasio(It first, It last)
48+
-> std::common_type_t<std::iter_value_t<It>, std::size_t> {
49+
using common = std::common_type_t<std::iter_value_t<It>, std::size_t>;
50+
std::vector<common> deret(first, last);
51+
if (deret.size() < 2) {
52+
return *deret.begin();
53+
}
54+
return deret[1] / deret[0];
55+
}
56+
template <std::input_iterator It>
57+
requires(std::integral<std::iter_value_t<It>>)
58+
auto rasio(It first, It last, std::size_t pos_1, std::size_t pos_2)
59+
-> std::common_type_t<std::iter_value_t<It>, std::size_t> {
60+
std::vector<int> deret(first, last);
61+
if (deret.size() < 2) {
62+
return *deret.begin(); // return suku pertama
63+
}
64+
using common = std::common_type_t<std::iter_value_t<It>, std::size_t>;
65+
auto val_pos1 = deret[pos_1];
66+
auto val_pos2 = deret[pos_2];
67+
common rhs = (pos_1 < pos_2) ? val_pos2 / val_pos1 : val_pos1 / val_pos2;
68+
double lhs = pos_1 < pos_2 ? pos_2 - 1 : pos_1 - pos_2;
69+
common result = pow(rhs, 1.0 / lhs);
70+
return result;
71+
}
72+
/**
73+
* @brief Menghitung suku ke-n dari deret geometri.
74+
*
75+
* @details
76+
* Fungsi ini menerima dua iterator (`first`, `last`) yang menunjuk ke deret
77+
* bilangan geometri dan sebuah parameter `n` yang menunjukkan suku ke-n yang
78+
* ingin dihitung.
79+
*
80+
* Cara kerja:
81+
* 1. Menentukan rasio umum deret dengan memanggil fungsi `rasio()`.
82+
* 2. Mengambil nilai suku pertama (`a`).
83+
* 3. Menggunakan rumus dasar deret geometri:
84+
*
85+
* U_n = a + r^(n - 1)
86+
* dimana:
87+
* Un = rumus suku ke-n
88+
* a = suku pertama
89+
* r = rasio
90+
* n = suku yang ingin diketahui
91+
* Nilai dikembalikan dalam tipe data yang merupakan hasil dari
92+
* `std::common_type_t` antara nilai iterator dan `std::size_t`.
93+
*/
94+
template <std::input_iterator It>
95+
requires(std::integral<std::iter_value_t<It>>)
96+
auto suku_keN(It first, It last, std::size_t n)
97+
-> std::common_type_t<std::iter_value_t<It>, std::size_t> {
98+
using common = std::common_type_t<std::iter_value_t<It>, std::size_t>;
99+
common _rasio = rasio(first, last);
100+
std::vector<common> deret(first, last);
101+
common res = deret.front() * pow(_rasio, n - 1);
102+
return res;
103+
}
104+
/**
105+
* @brief Menghasilkan representasi string dari rumus umum suku ke-n deret
106+
* geometri.
107+
*
108+
* @details
109+
* Fungsi ini menyusun rumus dalam bentuk teks menggunakan nilai suku pertama
110+
* (`a`) dan rasio (`r`) yang diperoleh dari deret.
111+
*
112+
* Rumus yang dihasilkan berbentuk:
113+
*
114+
* ```
115+
* Un = a * r^(n - 1)
116+
* ```
117+
*/
118+
template <std::input_iterator It>
119+
requires(std::integral<std::iter_value_t<It>>)
120+
std::string rumus_suku_KeN(It first, It last){
121+
// using common = std::common_type<std::iter_value_t<It>,std::size_t>;
122+
using type_iter = std::iter_value_t<It>;
123+
type_iter a = *first;
124+
type_iter r = rasio(first, last);
125+
std::ostringstream oss;
126+
oss << "Un = " << a << " + " << r << "^n - 1";
127+
return oss.str();
128+
}
129+
template <typename T>
130+
requires(std::integral<T>)
131+
// jika 2 diketahui 2 suku berurutan
132+
T rasio(T suku_1, T suku_2) {
133+
return suku_2 > suku_1 ? suku_2 / suku_1 : suku_1 / suku_2;
134+
}
135+
// jika tidak ketahui suku berurutan tetapi diberikan deret
136+
template <typename T>
137+
requires(std::integral<T>)
138+
T rasio(std::initializer_list<T> arr) {
139+
return rasio(arr.begin(), arr.end());
140+
}
141+
// jika diketahui 2 suku ke n yang tidak beurutan
142+
template <typename T>
143+
requires(std::integral<T>)
144+
auto rasio(std::initializer_list<T> arr, std::size_t pos_1, std::size_t pos_2)
145+
-> std::common_type_t<T, std::size_t> {
146+
return rasio(arr.begin(), arr.end(), pos_1, pos_2);
147+
}
148+
// jika diketahui deret
149+
template <std::ranges::input_range arr>
150+
requires(std::integral<std::ranges::range_value_t<arr>>)
151+
auto rasio(arr &&R) {
152+
return rasio(R.begin(), R.end());
153+
}
154+
template <std::ranges::input_range arr>
155+
requires(std::integral<std::ranges::range_value_t<arr>>)
156+
auto rasio(arr &&R, std::size_t pos_1, std::size_t pos_2) {
157+
return rasio(R.begin(), R.end(), pos_1, pos_2);
158+
}
159+
template <typename T>
160+
requires(std::integral<T>)
161+
auto suku_keN(std::initializer_list<T> arr, std::size_t n) {
162+
return suku_keN(arr.begin(), arr.end(), n);
163+
}
164+
template <std::ranges::input_range arr>
165+
requires(std::integral<std::ranges::range_value_t<arr>>)
166+
auto suku_keN(arr &&R, std::size_t n) {
167+
return suku_keN(R.begin(), R.end(), n);
168+
}
169+
template <typename T>
170+
requires(std::integral<T>)
171+
std::string rumus_suku_KeN(std::initializer_list<T> arr) {
172+
return rumus_suku_KeN(arr.begin(), arr.end());
173+
}
174+
template <std::ranges::input_range arr>
175+
requires(std::integral<std::ranges::range_value_t<arr>>)
176+
std::string rumus_suku_KeN(arr &&R) {
177+
return rumus_suku_KeN(R.begin(), R.end());
178+
}
179+
int main() {
180+
std::cout << "jika hanya diketahui 2 suku berurutan" << std::endl;
181+
std::cout << "hasil: " << rasio(2, 4) << std::endl;
182+
std::cout << "jika diketahui 2 suku tidak berurutan(base on index)" << std::endl;
183+
std::cout << "hasil: " << rasio({2, 4, 8, 16}, 0, 2) << std::endl;
184+
std::vector<int> a = {3, 6, 12, 24};
185+
std::cout << "menggunakan ranges" << std::endl;
186+
std::cout << rasio(a) << std::endl;
187+
std::cout << "rumus suku keN" << std::endl;
188+
std::cout << "rumus: " << rumus_suku_KeN(a) << std::endl;
189+
// Menggunakan iterator langsung (begin, end)
190+
std::cout << "[4] Menggunakan iterator langsung\n";
191+
std::vector<int> deret1 = {2, 6, 18, 54};
192+
std::cout << "rasio(deret1.begin(), deret1.end()) = "
193+
<< rasio(deret1.begin(), deret1.end()) << std::endl;
194+
// Menghitung nilai suku ke-n (iterator)
195+
std::cout << "[8] Nilai suku ke-n (iterator)\n";
196+
std::vector<int> deret3 = {3, 6, 12, 24};
197+
std::cout << "suku_keN(deret3.begin(), deret3.end(), 5) = "
198+
<< suku_keN(deret3.begin(), deret3.end(), 5) << "\n\n";
199+
std::cin.get();
200+
return 0;
201+
}

0 commit comments

Comments
 (0)