Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
comb_example.C
Go to the documentation of this file.
1
67#include <iostream>
68#include <iomanip>
69#include <string>
70
71#include <tclap/CmdLine.h>
72
73#include <htlist.H>
74#include <ah-comb.H>
75
76using namespace std;
77using namespace Aleph;
78
79// =============================================================================
80// Helper functions
81// =============================================================================
82
83void print_section(const string& title)
84{
85 cout << "\n" << string(60, '=') << "\n";
86 cout << " " << title << "\n";
87 cout << string(60, '=') << "\n\n";
88}
89
90void print_subsection(const string& title)
91{
92 cout << "\n--- " << title << " ---\n";
93}
94
95template <typename T>
96void print_list(const string& label, const DynList<T>& l)
97{
98 cout << label << ": [";
99 bool first = true;
100 for (auto it = l.get_it(); it.has_curr(); it.next())
101 {
102 if (not first) cout << ", ";
103 cout << it.get_curr();
104 first = false;
105 }
106 cout << "]" << endl;
107}
108
109template <typename T>
110void print_matrix(const string& label, const DynList<DynList<T>>& mat)
111{
112 cout << label << ":" << endl;
113 size_t row = 0;
114 for (auto it = mat.get_it(); it.has_curr(); it.next(), row++)
115 {
116 cout << " [" << row << "]: [";
117 bool first = true;
118 for (auto jt = it.get_curr().get_it(); jt.has_curr(); jt.next())
119 {
120 if (not first) cout << ", ";
121 cout << jt.get_curr();
122 first = false;
123 }
124 cout << "]" << endl;
125 }
126}
127
128// =============================================================================
129// 1. Matrix Transpose
130// =============================================================================
131
133{
134 print_section("MATRIX TRANSPOSE");
135
136 // Create a 3x4 matrix
138 matrix.append(DynList<int>({1, 2, 3, 4}));
139 matrix.append(DynList<int>({5, 6, 7, 8}));
140 matrix.append(DynList<int>({9, 10, 11, 12}));
141
142 print_matrix("Original matrix (3x4)", matrix);
143
144 // Transpose
145 print_subsection("transpose()");
147 print_matrix("Transposed (4x3)", transposed);
148
149 // In-place transpose
150 print_subsection("in_place_transpose()");
152 names.append(DynList<string>({"Ana", "Juan"}));
153 names.append(DynList<string>({"Maria", "Pedro"}));
154 names.append(DynList<string>({"Luisa", "Carlos"}));
155
156 print_matrix("Before", names);
158 print_matrix("After in-place transpose", names);
159}
160
161// =============================================================================
162// 2. Permutations (Cartesian Product)
163// =============================================================================
164
166{
167 print_section("PERMUTATIONS (Cartesian Product)");
168
169 cout << "Given lists of choices, enumerate all combinations.\n";
170 cout << "This is the CARTESIAN PRODUCT, not mathematical permutations.\n\n";
171
172 // Simple example: colors and sizes
174 choices.append(DynList<string>({"rojo", "azul", "verde"}));
175 choices.append(DynList<string>({"S", "M", "L"}));
176
177 cout << "Choices:" << endl;
178 cout << " Colors: [rojo, azul, verde]" << endl;
179 cout << " Sizes: [S, M, L]" << endl;
180
181 // for_each_perm
182 print_subsection("for_each_perm()");
183 cout << "All color-size combinations:\n";
184 size_t count = 0;
186 cout << " " << ++count << ": ";
187 bool first = true;
188 for (auto it = perm.get_it(); it.has_curr(); it.next())
189 {
190 if (not first) cout << "-";
191 cout << it.get_curr();
192 first = false;
193 }
194 cout << endl;
195 });
196
197 // perm_count
198 print_subsection("perm_count()");
199 cout << "Total permutations: " << perm_count(choices) << endl;
200 cout << " (3 colors × 3 sizes = 9)" << endl;
201
202 // Three-way product
203 print_subsection("Three-way Cartesian product");
205 digits.append(DynList<int>({0, 1}));
206 digits.append(DynList<int>({0, 1}));
207 digits.append(DynList<int>({0, 1}));
208
209 cout << "Binary digits: [0,1] × [0,1] × [0,1]\n";
210 cout << "All 3-bit binary numbers:\n";
212 cout << " ";
213 for (auto it = perm.get_it(); it.has_curr(); it.next())
214 cout << it.get_curr();
215 cout << endl;
216 });
217 cout << "Total: " << perm_count(digits) << " (2³ = 8)" << endl;
218}
219
220// =============================================================================
221// 3. Permutation Predicates
222// =============================================================================
223
225{
226 print_section("PERMUTATION PREDICATES");
227
228 // Dice combinations
230 dice.append(DynList<int>({1, 2, 3, 4, 5, 6}));
231 dice.append(DynList<int>({1, 2, 3, 4, 5, 6}));
232
233 cout << "Two dice: [1-6] × [1-6] = 36 outcomes\n";
234
235 // exists_perm - at least one satisfies
236 print_subsection("exists_perm()");
237
238 bool has_double_six = exists_perm(dice, [](const DynList<int>& roll) {
239 int sum = 0;
240 for (auto it = roll.get_it(); it.has_curr(); it.next())
241 sum += it.get_curr();
242 return sum == 12; // Double six
243 });
244 cout << "Exists roll with sum = 12? " << (has_double_six ? "yes" : "no") << endl;
245
246 bool has_sum_15 = exists_perm(dice, [](const DynList<int>& roll) {
247 int sum = 0;
248 for (auto it = roll.get_it(); it.has_curr(); it.next())
249 sum += it.get_curr();
250 return sum == 15; // Impossible
251 });
252 cout << "Exists roll with sum = 15? " << (has_sum_15 ? "yes" : "no") << endl;
253
254 // all_perm - all satisfy
255 print_subsection("all_perm()");
256
257 bool all_positive = all_perm(dice, [](const DynList<int>& roll) {
258 for (auto it = roll.get_it(); it.has_curr(); it.next())
259 if (it.get_curr() <= 0) return false;
260 return true;
261 });
262 cout << "All rolls have positive values? " << (all_positive ? "yes" : "no") << endl;
263
264 bool all_sum_gt_10 = all_perm(dice, [](const DynList<int>& roll) {
265 int sum = 0;
266 for (auto it = roll.get_it(); it.has_curr(); it.next())
267 sum += it.get_curr();
268 return sum > 10;
269 });
270 cout << "All rolls have sum > 10? " << (all_sum_gt_10 ? "yes" : "no") << endl;
271
272 // none_perm
273 print_subsection("none_perm()");
274
275 bool none_zero = none_perm(dice, [](const DynList<int>& roll) {
276 for (auto it = roll.get_it(); it.has_curr(); it.next())
277 if (it.get_curr() == 0) return true;
278 return false;
279 });
280 cout << "No roll contains a zero? " << (none_zero ? "yes" : "no") << endl;
281}
282
283// =============================================================================
284// 4. Traverse with Early Exit
285// =============================================================================
286
288{
289 print_section("TRAVERSE WITH EARLY EXIT");
290
292 numbers.append(DynList<int>({1, 2, 3}));
293 numbers.append(DynList<int>({10, 20, 30}));
294
295 cout << "Lists: [1,2,3] × [10,20,30]\n\n";
296
297 // traverse_perm stops on false
298 print_subsection("traverse_perm() - stop when sum > 25");
299
300 bool found = not traverse_perm(numbers, [](const DynList<int>& perm) {
301 int sum = 0;
302 for (auto it = perm.get_it(); it.has_curr(); it.next())
303 sum += it.get_curr();
304
305 cout << " Checking: ";
306 bool first = true;
307 for (auto it = perm.get_it(); it.has_curr(); it.next())
308 {
309 if (not first) cout << "+";
310 cout << it.get_curr();
311 first = false;
312 }
313 cout << " = " << sum;
314
315 if (sum > 25)
316 {
317 cout << " > 25, STOP!" << endl;
318 return false; // Stop traversal
319 }
320 cout << endl;
321 return true; // Continue
322 });
323
324 cout << "\nFound sum > 25? " << (found ? "yes" : "no") << endl;
325}
326
327// =============================================================================
328// 5. Fold over Permutations
329// =============================================================================
330
332{
333 print_section("FOLD OVER PERMUTATIONS");
334
335 DynList<DynList<int>> values;
336 values.append(DynList<int>({1, 2}));
337 values.append(DynList<int>({3, 4}));
338
339 cout << "Values: [1,2] × [3,4]\n";
340 cout << "Permutations: (1,3), (1,4), (2,3), (2,4)\n\n";
341
342 // fold_perm - accumulate over all permutations
343 print_subsection("fold_perm() - sum of products");
344
345 int total = fold_perm(0, values, [](int acc, const DynList<int>& perm) {
346 int product = 1;
347 for (auto it = perm.get_it(); it.has_curr(); it.next())
348 product *= it.get_curr();
349 cout << " Product: " << product << ", Running total: " << (acc + product) << endl;
350 return acc + product;
351 });
352
353 cout << "\nTotal (1×3 + 1×4 + 2×3 + 2×4) = " << total << endl;
354 cout << "Expected: 3 + 4 + 6 + 8 = 21" << endl;
355}
356
357// =============================================================================
358// 6. Build Permutations List
359// =============================================================================
360
362{
363 print_section("BUILD PERMUTATIONS LIST");
364
366 menu.append(DynList<string>({"cafe", "te"}));
367 menu.append(DynList<string>({"arepa", "empanada"}));
368 menu.append(DynList<string>({"postre"}));
369
370 cout << "Menu choices:" << endl;
371 cout << " Bebida: [cafe, te]" << endl;
372 cout << " Comida: [arepa, empanada]" << endl;
373 cout << " Extra: [postre]" << endl;
374
375 // build_perms
376 print_subsection("build_perms()");
378
379 cout << "All possible orders (" << all_combos.size() << " total):\n";
380 size_t n = 0;
381 for (auto it = all_combos.get_it(); it.has_curr(); it.next())
382 {
383 cout << " " << ++n << ": ";
384 auto& combo = it.get_curr();
385 bool first = true;
386 for (auto jt = combo.get_it(); jt.has_curr(); jt.next())
387 {
388 if (not first) cout << " + ";
389 cout << jt.get_curr();
390 first = false;
391 }
392 cout << endl;
393 }
394}
395
396// =============================================================================
397// 7. Practical Example: Configuration Generator
398// =============================================================================
399
401{
402 print_section("PRACTICAL: Configuration Generator");
403
404 cout << "Generate all test configurations for a system.\n\n";
405
407 config_options.append(DynList<string>({"debug", "release"}));
408 config_options.append(DynList<string>({"x86", "x64", "arm"}));
409 config_options.append(DynList<string>({"linux", "windows"}));
410
411 cout << "Options:" << endl;
412 cout << " Build: [debug, release]" << endl;
413 cout << " Arch: [x86, x64, arm]" << endl;
414 cout << " Platform: [linux, windows]" << endl;
415
416 print_subsection("All configurations");
417 cout << "Total: " << perm_count(config_options) << " configurations\n\n";
418
419 size_t n = 0;
420 for_each_perm(config_options, [&n](const DynList<string>& config) {
421 cout << " " << setw(2) << ++n << ". ";
422 bool first = true;
423 for (auto it = config.get_it(); it.has_curr(); it.next())
424 {
425 if (not first) cout << "-";
426 cout << it.get_curr();
427 first = false;
428 }
429 cout << endl;
430 });
431
432 // Count specific configurations
433 print_subsection("Count Linux configurations");
434 size_t linux_count = 0;
436 for (auto it = config.get_it(); it.has_curr(); it.next())
437 if (it.get_curr() == "linux")
438 {
439 linux_count++;
440 break;
441 }
442 });
443 cout << "Linux configurations: " << linux_count << endl;
444}
445
446// =============================================================================
447// Main
448// =============================================================================
449
450int main(int argc, char* argv[])
451{
452 try
453 {
454 TCLAP::CmdLine cmd(
455 "Combinatorics example for Aleph-w.\n"
456 "Demonstrates transpose, permutations, and combinations.",
457 ' ', "1.0"
458 );
459
460 TCLAP::ValueArg<string> sectionArg(
461 "s", "section",
462 "Run only specific section: transpose, perm, predicates, "
463 "traverse, fold, build, practical, or 'all'",
464 false, "all", "section", cmd
465 );
466
467 cmd.parse(argc, argv);
468
469 string section = sectionArg.getValue();
470
471 cout << "\n";
472 cout << "============================================================\n";
473 cout << " ALEPH-W COMBINATORICS EXAMPLE\n";
474 cout << "============================================================\n";
475
476 if (section == "all" or section == "transpose")
478
479 if (section == "all" or section == "perm")
481
482 if (section == "all" or section == "predicates")
484
485 if (section == "all" or section == "traverse")
487
488 if (section == "all" or section == "fold")
489 demo_fold();
490
491 if (section == "all" or section == "build")
492 demo_build();
493
494 if (section == "all" or section == "practical")
496
497 cout << "\n" << string(60, '=') << "\n";
498 cout << "Combinatorics demo completed!\n";
499 cout << string(60, '=') << "\n\n";
500
501 return 0;
502 }
503 catch (TCLAP::ArgException& e)
504 {
505 cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
506 return 1;
507 }
508 catch (exception& e)
509 {
510 cerr << "Error: " << e.what() << endl;
511 return 1;
512 }
513}
514
Combinatorics utilities: permutations, combinations and matrix transposition.
int main()
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
void demo_fold()
void print_subsection(const string &title)
void demo_build()
void print_matrix(const string &label, const DynList< DynList< T > > &mat)
void print_section(const string &title)
void demo_perm_predicates()
void demo_practical()
void demo_traverse()
void demo_permutations()
void print_list(const string &label, const DynList< T > &l)
void demo_transpose()
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool none_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if no permutation satisfies a predicate.
Definition ah-comb.H:611
T fold_perm(const T &init, const DynList< DynList< Tc > > &l, Op &op)
Left-fold over all permutations.
Definition ah-comb.H:479
size_t perm_count(const DynList< DynList< T > > &l)
Count the total number of permutations from a list of lists.
Definition ah-comb.H:514
bool traverse_perm(const DynList< DynList< T > > &l, Op &op)
Traverse all the possible permutations that can be done of a list of lists and on each permutation pe...
Definition ah-comb.H:355
void for_each_perm(const DynList< DynList< T > > &l, Op &op)
Apply a procedure to every permutation produced by traverse_perm.
Definition ah-comb.H:395
DynList< DynList< T > > transpose(const DynList< DynList< T > > &l)
Transpose a matrix represented as a list of lists.
Definition ah-comb.H:140
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
DynList< DynList< T > > build_perms(const DynList< DynList< T > > &l)
Materialize all permutations from a list of lists.
Definition ah-comb.H:427
void in_place_transpose(C< C< T > > &l)
In-place transpose of a rectangular matrix stored as a nested container.
Definition ah-comb.H:191
bool exists_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if any permutation satisfies a predicate.
Definition ah-comb.H:541
bool all_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if all permutations satisfy a predicate.
Definition ah-comb.H:581
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
DynList< int > l