Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
zip_example.C
Go to the documentation of this file.
1
138#include <iostream>
139#include <iomanip>
140#include <string>
141#include <vector>
142
143#include <tclap/CmdLine.h>
144
145#include <htlist.H>
146#include <tpl_dynDlist.H>
147#include <ah-zip.H>
148#include <ahFunctional.H>
149
150using namespace std;
151using namespace Aleph;
152
153// =============================================================================
154// Helper functions
155// =============================================================================
156
157void print_section(const string& title)
158{
159 cout << "\n" << string(60, '=') << "\n";
160 cout << " " << title << "\n";
161 cout << string(60, '=') << "\n\n";
162}
163
164void print_subsection(const string& title)
165{
166 cout << "\n--- " << title << " ---\n";
167}
168
169template <typename Container>
170void print_list(const string& label, const Container& c)
171{
172 cout << label << ": [";
173 bool first = true;
174 for (auto it = c.get_it(); it.has_curr(); it.next())
175 {
176 if (not first) cout << ", ";
177 cout << it.get_curr();
178 first = false;
179 }
180 cout << "]" << endl;
181}
182
183// =============================================================================
184// 1. Basic Zip Iteration
185// =============================================================================
186
188{
189 print_section("BASIC ZIP ITERATION");
190
191 DynList<int> numbers = {1, 2, 3, 4, 5};
192 DynList<string> names = {"uno", "dos", "tres", "cuatro", "cinco"};
193 DynList<char> letters = {'a', 'b', 'c', 'd', 'e'};
194
195 print_list("numbers", numbers);
196 print_list("names", names);
197 print_list("letters", letters);
198
199 // ZipIterator with two containers
200 print_subsection("ZipIterator (2 containers)");
201 cout << "Iterating numbers and names together:\n";
202 for (ZipIterator it(numbers, names); it.has_curr(); it.next())
203 {
204 auto [num, name] = it.get_curr();
205 cout << " " << num << " -> " << name << endl;
206 }
207
208 // ZipIterator with three containers
209 print_subsection("ZipIterator (3 containers)");
210 cout << "Iterating numbers, names, and letters:\n";
211 for (ZipIterator it(numbers, names, letters); it.has_curr(); it.next())
212 {
213 auto [num, name, letter] = it.get_curr();
214 cout << " " << num << " (" << name << ") [" << letter << "]" << endl;
215 }
216
217 // Different length containers
218 print_subsection("Handling Different Lengths");
219 DynList<int> short_list = {10, 20};
220 print_list("short_list", short_list);
221
222 cout << "Zipping numbers with short_list (stops at shorter):\n";
223 for (ZipIterator it(numbers, short_list); it.has_curr(); it.next())
224 {
225 auto [a, b] = it.get_curr();
226 cout << " " << a << ", " << b << endl;
227 }
228}
229
230// =============================================================================
231// 2. Enumerated Zip
232// =============================================================================
233
235{
236 print_section("ENUMERATED ZIP");
237
238 DynList<string> fruits = {"manzana", "pera", "uva", "mango"};
239 DynList<double> prices = {1.50, 0.80, 2.30, 1.20};
240
241 print_list("fruits", fruits);
242 cout << "prices: [1.50, 0.80, 2.30, 1.20]" << endl;
243
244 // EnumZipIterator
245 print_subsection("EnumZipIterator");
246 cout << "Iterating with index:\n";
247 for (EnumZipIterator it(fruits, prices); it.has_curr(); it.next())
248 {
249 auto [idx, fruit, price] = it.get_curr();
250 cout << " [" << idx << "] " << fruit << ": $" << fixed << setprecision(2) << price << endl;
251 }
252
253 // t_enum_zip - creates list of tuples with index
254 print_subsection("t_enum_zip()");
256 cout << "Created list of (index, fruit, price) tuples:\n";
257 for (auto it = enumerated.get_it(); it.has_curr(); it.next())
258 {
259 auto [idx, fruit, price] = it.get_curr();
260 cout << " (" << idx << ", " << fruit << ", $" << price << ")" << endl;
261 }
262}
263
264// =============================================================================
265// 3. Tuple List Operations
266// =============================================================================
267
269{
270 print_section("TUPLE LIST OPERATIONS");
271
272 DynList<string> products = {"cafe", "panela", "arroz"};
273 DynList<double> prices = {15.0, 5.0, 8.0};
274 DynList<int> stock = {100, 250, 180};
275
276 print_list("products", products);
277 cout << "prices: [15.0, 5.0, 8.0]" << endl;
278 print_list("stock", stock);
279
280 // t_zip - create list of tuples
281 print_subsection("t_zip()");
283 cout << "Inventory as list of tuples:\n";
284 for (auto it = inventory.get_it(); it.has_curr(); it.next())
285 {
286 auto [prod, price, qty] = it.get_curr();
287 cout << " (" << prod << ", $" << price << ", " << qty << " units)" << endl;
288 }
289
290 // t_unzip - split tuple list back
291 print_subsection("t_unzip()");
293 cout << "Unzipped back to separate lists:\n";
294 print_list(" products", prods_back);
295 cout << " prices: [";
296 bool first = true;
297 for (auto it = prices_back.get_it(); it.has_curr(); it.next())
298 {
299 if (not first) cout << ", ";
300 cout << it.get_curr();
301 first = false;
302 }
303 cout << "]" << endl;
304 print_list(" stock", stock_back);
305}
306
307// =============================================================================
308// 4. Zip Transformation
309// =============================================================================
310
312{
313 print_section("ZIP TRANSFORMATION");
314
315 DynList<int> quantities = {5, 3, 8, 2};
316 DynList<double> unit_prices = {10.0, 25.0, 5.0, 100.0};
317
318 print_list("quantities", quantities);
319 cout << "unit_prices: [10.0, 25.0, 5.0, 100.0]" << endl;
320
321 // zip_map - transform pairs (lambda receives tuple)
322 print_subsection("zip_map()");
323 auto totals = zip_map([](const auto& t) {
324 return get<0>(t) * get<1>(t);
326
327 cout << "Totals (qty * price):\n";
328 for (auto it = totals.get_it(); it.has_curr(); it.next())
329 cout << " $" << fixed << setprecision(2) << it.get_curr() << endl;
330
331 // zip_filter - keep pairs satisfying predicate (lambda receives tuple)
332 print_subsection("zip_filter()");
333 auto expensive = zip_filter([](const auto& t) {
334 return get<0>(t) * get<1>(t) > 30;
336
337 cout << "Orders > $30:\n";
338 for (auto it = expensive.get_it(); it.has_curr(); it.next())
339 {
340 auto [qty, price] = it.get_curr();
341 cout << " " << qty << " x $" << price << " = $" << (qty * price) << endl;
342 }
343
344 // Manual map with ZipIterator
345 print_subsection("Manual transformation with ZipIterator");
346 DynList<string> names = {"laptop", "mouse", "cable", "monitor"};
347 cout << "Product descriptions:\n";
348 for (ZipIterator it(names, quantities, unit_prices); it.has_curr(); it.next())
349 {
350 auto [name, qty, price] = it.get_curr();
351 cout << " " << name << " (" << qty << " @ $" << price << ")" << endl;
352 }
353}
354
355// =============================================================================
356// 5. Zip Utilities
357// =============================================================================
358
360{
361 print_section("ZIP UTILITIES");
362
363 DynList<string> cities = {"Bogota", "Medellin", "Cali", "Barranquilla", "Cartagena"};
364 DynList<int> populations = {7400, 2500, 2200, 1200, 1000}; // in thousands
365
366 print_list("cities", cities);
367 print_list("populations (thousands)", populations);
368
369 // zip_take - take first n
370 print_subsection("zip_take()");
371 auto top3 = zip_take(3, cities, populations);
372 cout << "Top 3 cities:\n";
373 for (auto it = top3.get_it(); it.has_curr(); it.next())
374 {
375 auto [city, pop] = it.get_curr();
376 cout << " " << city << ": " << pop << "k" << endl;
377 }
378
379 // zip_drop - drop first n
380 print_subsection("zip_drop()");
381 auto rest = zip_drop(3, cities, populations);
382 cout << "Remaining cities (after dropping 3):\n";
383 for (auto it = rest.get_it(); it.has_curr(); it.next())
384 {
385 auto [city, pop] = it.get_curr();
386 cout << " " << city << ": " << pop << "k" << endl;
387 }
388
389 // zip_take_while (lambda receives tuple)
390 print_subsection("zip_take_while()");
391 auto big_cities = zip_take_while([](const auto& t) {
392 return get<1>(t) > 1500;
393 }, cities, populations);
394
395 cout << "Cities with population > 1500k (prefix):\n";
396 for (auto it = big_cities.get_it(); it.has_curr(); it.next())
397 {
398 auto [city, pop] = it.get_curr();
399 cout << " " << city << ": " << pop << "k" << endl;
400 }
401
402 // Manual partition using filter
403 print_subsection("Manual partition using filter");
405
406 auto large = all_tuples.filter([](const auto& t) {
407 return get<1>(t) >= 2000;
408 });
409 auto small_cities = all_tuples.filter([](const auto& t) {
410 return get<1>(t) < 2000;
411 });
412
413 cout << "Large cities (>= 2M):\n";
414 for (auto it = large.get_it(); it.has_curr(); it.next())
415 {
416 auto [city, pop] = it.get_curr();
417 cout << " " << city << ": " << pop << "k" << endl;
418 }
419 cout << "Smaller cities (< 2M):\n";
420 for (auto it = small_cities.get_it(); it.has_curr(); it.next())
421 {
422 auto [city, pop] = it.get_curr();
423 cout << " " << city << ": " << pop << "k" << endl;
424 }
425}
426
427// =============================================================================
428// 6. STL Compatibility
429// =============================================================================
430
432{
433 print_section("STL COMPATIBILITY");
434
435 vector<int> vec1 = {1, 2, 3, 4};
436 vector<string> vec2 = {"a", "b", "c", "d"};
437
438 cout << "vec1 (std::vector): [1, 2, 3, 4]" << endl;
439 cout << "vec2 (std::vector): [a, b, c, d]" << endl;
440
441 // std_zip - zip two STL containers (returns std::vector<pair>)
442 print_subsection("std_zip()");
443 auto zipped = std_zip(vec1, vec2);
444 cout << "Zipped STL vectors (returns std::vector):\n";
445 for (const auto& [num, letter] : zipped)
446 {
447 cout << " (" << num << ", " << letter << ")" << endl;
448 }
449
450 // tzip_std - zip multiple STL containers (returns std::vector<tuple>)
451 print_subsection("tzip_std()");
452 vector<double> vec3 = {1.1, 2.2, 3.3, 4.4};
453 cout << "vec3 (std::vector): [1.1, 2.2, 3.3, 4.4]" << endl;
454
455 auto triple_zip = tzip_std(vec1, vec2, vec3);
456 cout << "Triple-zipped (returns std::vector):\n";
457 for (const auto& t : triple_zip)
458 {
459 auto [num, letter, dbl] = t;
460 cout << " (" << num << ", " << letter << ", " << dbl << ")" << endl;
461 }
462}
463
464// =============================================================================
465// 7. Length Checking
466// =============================================================================
467
469{
470 print_section("LENGTH CHECKING");
471
472 DynList<int> list1 = {1, 2, 3};
473 DynList<int> list2 = {10, 20, 30};
474 DynList<int> list3 = {100, 200}; // Different length!
475
476 print_list("list1", list1);
477 print_list("list2", list2);
478 print_list("list3 (shorter!)", list3);
479
480 // equal_length check
481 print_subsection("equal_length()");
482 cout << "list1 and list2 equal length? "
483 << (equal_length(list1, list2) ? "yes" : "no") << endl;
484 cout << "list1 and list3 equal length? "
485 << (equal_length(list1, list3) ? "yes" : "no") << endl;
486
487 // Regular zip stops at shorter
488 print_subsection("Regular zip (stops at shorter)");
489 cout << "Zipping list1 and list3:\n";
490 for (ZipIterator it(list1, list3); it.has_curr(); it.next())
491 {
492 auto [a, b] = it.get_curr();
493 cout << " " << a << " + " << b << " = " << (a + b) << endl;
494 }
495 cout << " (Only 2 pairs produced)\n";
496
497 // Using t_zip_eq throws on mismatch
498 print_subsection("t_zip_eq() - throws on mismatch");
499 cout << "t_zip_eq on equal lists:\n";
500 try
501 {
502 auto result = t_zip_eq(list1, list2);
503 cout << " Created " << result.size() << " tuples successfully\n";
504 }
505 catch (const length_error& e)
506 {
507 cout << " Error: " << e.what() << endl;
508 }
509
510 cout << "\nt_zip_eq on unequal lists:\n";
511 try
512 {
513 auto result = t_zip_eq(list1, list3);
514 cout << " Created " << result.size() << " tuples\n";
515 }
516 catch (const length_error& e)
517 {
518 cout << " Caught exception: " << e.what() << endl;
519 }
520}
521
522// =============================================================================
523// 8. Practical Example: Sales Analysis
524// =============================================================================
525
527{
528 print_section("PRACTICAL EXAMPLE: Coffee Sales Analysis");
529
530 // Colombian coffee regions sales data
531 DynList<string> regions = {"Huila", "NariƱo", "Cauca", "Tolima", "Antioquia"};
532 DynList<int> bags_2023 = {1200, 850, 720, 650, 580};
533 DynList<int> bags_2024 = {1350, 920, 800, 680, 620};
534
535 print_list("regions", regions);
536 print_list("bags_2023", bags_2023);
537 print_list("bags_2024", bags_2024);
538
539 // Calculate growth using ZipIterator
540 print_subsection("Year-over-Year Growth");
541 cout << "Growth by region:\n";
542 for (ZipIterator it(regions, bags_2023, bags_2024); it.has_curr(); it.next())
543 {
544 auto [region, y23, y24] = it.get_curr();
545 double pct = 100.0 * (y24 - y23) / y23;
546 cout << " " << setw(12) << left << region
547 << ": " << y23 << " -> " << y24
548 << " (" << showpos << fixed << setprecision(1) << pct << "%)"
549 << noshowpos << endl;
550 }
551
552 // Find best performers using zip_filter
553 print_subsection("Regions with > 10% growth");
555 auto good_growth = tuples.filter([](const auto& t) {
556 int y23 = get<1>(t);
557 int y24 = get<2>(t);
558 return (y24 - y23) * 100.0 / y23 > 10.0;
559 });
560
561 cout << "High growth regions:\n";
562 for (auto it = good_growth.get_it(); it.has_curr(); it.next())
563 {
564 auto [region, y23, y24] = it.get_curr();
565 double pct = 100.0 * (y24 - y23) / y23;
566 cout << " " << region << ": " << showpos << fixed << setprecision(1)
567 << pct << "%" << noshowpos << endl;
568 }
569
570 // Total production using ZipIterator
571 print_subsection("Total Production");
572 int total_2023 = 0, total_2024 = 0;
573 for (ZipIterator it(bags_2023, bags_2024); it.has_curr(); it.next())
574 {
575 auto [y23, y24] = it.get_curr();
576 total_2023 += y23;
577 total_2024 += y24;
578 }
579
580 cout << "2023 total: " << total_2023 << " bags" << endl;
581 cout << "2024 total: " << total_2024 << " bags" << endl;
582 cout << "Overall growth: " << showpos << fixed << setprecision(1)
583 << 100.0 * (total_2024 - total_2023) / total_2023 << "%" << noshowpos << endl;
584}
585
586// =============================================================================
587// Main
588// =============================================================================
589
590int main(int argc, char* argv[])
591{
592 try
593 {
594 TCLAP::CmdLine cmd(
595 "Comprehensive zip operations example for Aleph-w.\n"
596 "Demonstrates ZipIterator, t_zip, zip_map, and more.",
597 ' ', "1.0"
598 );
599
600 TCLAP::ValueArg<string> sectionArg(
601 "s", "section",
602 "Run only specific section: basic, enum, tuples, transform, "
603 "utilities, stl, length, practical, or 'all'",
604 false, "all", "section", cmd
605 );
606
607 cmd.parse(argc, argv);
608
609 string section = sectionArg.getValue();
610
611 cout << "\n";
612 cout << "============================================================\n";
613 cout << " ALEPH-W ZIP OPERATIONS EXAMPLE\n";
614 cout << "============================================================\n";
615
616 if (section == "all" or section == "basic")
618
619 if (section == "all" or section == "enum")
621
622 if (section == "all" or section == "tuples")
624
625 if (section == "all" or section == "transform")
627
628 if (section == "all" or section == "utilities")
630
631 if (section == "all" or section == "stl")
633
634 if (section == "all" or section == "length")
636
637 if (section == "all" or section == "practical")
639
640 cout << "\n" << string(60, '=') << "\n";
641 cout << "Zip operations demo completed!\n";
642 cout << string(60, '=') << "\n\n";
643
644 return 0;
645 }
646 catch (TCLAP::ArgException& e)
647 {
648 cerr << "Error: " << e.error() << " for argument " << e.argId() << endl;
649 return 1;
650 }
651 catch (exception& e)
652 {
653 cerr << "Error: " << e.what() << endl;
654 return 1;
655 }
656}
Zip iterators and functional operations for multiple containers.
Functional programming utilities for Aleph-w containers.
int main()
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Iterator that traverses multiple containers with enumeration index.
Aleph::DynList< T > filter(Operation &operation) const
Filter the elements of a container according to a matching criteria.
Definition ah-dry.H:1135
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
Iterator that traverses multiple Aleph containers in lockstep.
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
auto std_zip(const C1 &c1, const C2 &c2)
Build a vector of pairs from two STL containers.
Definition ah-zip.H:1498
auto tzip_std(const Cs &... cs)
Build a vector of tuples from 2 or more STL containers (variadic).
Definition ah-zip.H:1526
auto zip_filter(Op op, const Cs &... cs)
Filter zipped tuples by predicate op.
Definition ah-zip.H:895
auto zip_take_while(Pred &&pred, const Cs &... cs)
Take tuples while predicate pred returns true.
Definition ah-zip.H:1705
bool equal_length(const Cs &... cs)
Return true if all containers have the same length.
Definition ah-zip.H:296
auto zip_take(size_t n, const Cs &... cs)
Take at most n tuples from the zipped containers.
Definition ah-zip.H:1661
auto t_zip(const Cs &... cs)
Materialize zipped tuples into a DynList.
Definition ah-zip.H:1112
auto t_unzip(const DynList< std::tuple< Ts... > > &tuples)
Unzip a list of tuples into a tuple of lists.
Definition ah-zip.H:1400
auto t_enum_zip(const Cs &... cs)
Materialize enumerated zipped tuples into a DynList.
Definition ah-zip.H:1346
auto t_zip_eq(const Cs &... cs)
Materialize zipped tuples; throw if containers differ in length.
Definition ah-zip.H:1132
auto zip_drop(size_t n, const Cs &... cs)
Skip n tuples and return the rest.
Definition ah-zip.H:1680
auto zip_map(Op &&op, const Cs &... cs)
Map op over zipped tuples with auto-deduced return type.
Definition ah-zip.H:833
DynList< T > maps(const C &c, Op op)
Classic map operation.
STL namespace.
Dynamic doubly linked list implementation.
void demo_tuple_operations()
void print_subsection(const string &title)
void demo_zip_transformation()
void demo_basic_zip()
void demo_length_checking()
void print_section(const string &title)
void demo_zip_utilities()
void demo_enum_zip()
void print_list(const string &label, const Container &c)
void demo_practical_example()
void demo_stl_compatibility()