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