Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-stl-zip_test.cc
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
48#include <gtest/gtest.h>
49#include <ah-stl-zip.H>
50
51#include <vector>
52#include <list>
53#include <set>
54#include <deque>
55#include <array>
56#include <string>
57#include <numeric>
58
59using namespace Aleph;
60
61//==============================================================================
62// Basic StlZipView Tests
63//==============================================================================
64
65class StlZipViewTest : public ::testing::Test
66{
67protected:
68 std::vector<int> vi = {1, 2, 3, 4, 5};
69 std::vector<std::string> vs = {"a", "b", "c", "d", "e"};
70 std::list<double> ld = {1.1, 2.2, 3.3, 4.4, 5.5};
71};
72
74{
75 int count = 0;
76 for (auto [i, s] : stl_zip(vi, vs))
77 {
78 EXPECT_EQ(i, vi[count]);
79 EXPECT_EQ(s, vs[count]);
80 ++count;
81 }
82 EXPECT_EQ(count, 5);
83}
84
86{
87 int count = 0;
88 for (auto [i, s, d] : stl_zip(vi, vs, ld))
89 {
90 EXPECT_EQ(i, vi[count]);
91 EXPECT_EQ(s, vs[count]);
92 ++count;
93 }
94 EXPECT_EQ(count, 5);
95}
96
98{
99 std::vector<int> short_vec = {10, 20};
100
101 int count = 0;
102 for (auto [i, s] : stl_zip(short_vec, vs))
103 {
104 (void)i;
105 (void)s;
106 ++count;
107 }
108 EXPECT_EQ(count, 2); // Stops at shorter container
109}
110
112{
113 std::vector<int> empty_vec;
114
115 int count = 0;
116 for (auto [i, s] : stl_zip(empty_vec, vs))
117 {
118 (void)i;
119 (void)s;
120 ++count;
121 }
122 EXPECT_EQ(count, 0);
123}
124
126{
127 std::vector<int> single = {42};
128 std::vector<std::string> single_s = {"answer"};
129
130 int count = 0;
131 for (auto [i, s] : stl_zip(single, single_s))
132 {
133 EXPECT_EQ(i, 42);
134 EXPECT_EQ(s, "answer");
135 ++count;
136 }
137 EXPECT_EQ(count, 1);
138}
139
141{
142 auto view = stl_zip(vi, vs);
143 EXPECT_EQ(view.size(), 5);
144}
145
147{
148 std::vector<int> empty_vec;
149 auto view = stl_zip(empty_vec, vs);
151
152 auto view2 = stl_zip(vi, vs);
154}
155
156//==============================================================================
157// Different Container Types
158//==============================================================================
159
161{
162 std::vector<int> v = {1, 2, 3};
163 std::list<int> l = {10, 20, 30};
164
165 std::vector<int> sums;
166 for (auto [a, b] : stl_zip(v, l))
167 sums.push_back(a + b);
168
169 EXPECT_EQ(sums.size(), 3);
170 EXPECT_EQ(sums[0], 11);
171 EXPECT_EQ(sums[1], 22);
172 EXPECT_EQ(sums[2], 33);
173}
174
176{
177 std::vector<int> v = {1, 2, 3};
178 std::set<int> s = {100, 200, 300};
179
180 int count = 0;
181 for (auto [a, b] : stl_zip(v, s))
182 {
183 EXPECT_EQ(a, count + 1);
184 ++count;
185 }
186 EXPECT_EQ(count, 3);
187}
188
190{
191 std::vector<int> v = {1, 2, 3};
192 std::deque<std::string> d = {"x", "y", "z"};
193
194 int count = 0;
195 for (auto [num, str] : stl_zip(v, d))
196 {
197 (void)num;
198 (void)str;
199 ++count;
200 }
201 EXPECT_EQ(count, 3);
202}
203
205{
206 std::array<int, 3> a1 = {1, 2, 3};
207 std::array<int, 3> a2 = {10, 20, 30};
208
209 std::vector<int> products;
210 for (auto [x, y] : stl_zip(a1, a2))
211 products.push_back(x * y);
212
213 EXPECT_EQ(products.size(), 3);
214 EXPECT_EQ(products[0], 10);
215 EXPECT_EQ(products[1], 40);
216 EXPECT_EQ(products[2], 90);
217}
218
220{
221 std::vector<int> v1 = {1, 2};
222 std::vector<int> v2 = {10, 20};
223 std::vector<int> v3 = {100, 200};
224 std::vector<int> v4 = {1000, 2000};
225
226 int count = 0;
227 for (auto [a, b, c, d] : stl_zip(v1, v2, v3, v4))
228 {
229 if (count == 0)
230 {
231 EXPECT_EQ(a, 1);
232 EXPECT_EQ(b, 10);
233 EXPECT_EQ(c, 100);
234 EXPECT_EQ(d, 1000);
235 }
236 ++count;
237 }
238 EXPECT_EQ(count, 2);
239}
240
241//==============================================================================
242// Functional Operations: stl_zip_all
243//==============================================================================
244
246{
247 std::vector<int> xs = {1, 2, 3};
248 std::vector<int> ys = {10, 20, 30};
249
250 bool result = stl_zip_all([](auto t) {
251 return std::get<0>(t) < std::get<1>(t);
252 }, xs, ys);
253
254 EXPECT_TRUE(result);
255}
256
258{
259 std::vector<int> xs = {1, 200, 3};
260 std::vector<int> ys = {10, 20, 30};
261
262 bool result = stl_zip_all([](auto t) {
263 return std::get<0>(t) < std::get<1>(t);
264 }, xs, ys);
265
266 EXPECT_FALSE(result);
267}
268
270{
271 std::vector<int> empty1, empty2;
272
273 bool result = stl_zip_all([](auto) { return false; }, empty1, empty2);
274
275 EXPECT_TRUE(result); // Vacuously true
276}
277
279{
280 std::vector<int> xs = {1, 2, 3};
281 std::vector<int> ys = {10, 20, 30};
282
283 bool result = stl_zip_all_eq([](auto t) {
284 return std::get<0>(t) < std::get<1>(t);
285 }, xs, ys);
286
287 EXPECT_TRUE(result);
288
289 // Different lengths
290 std::vector<int> short_vec = {1, 2};
291 result = stl_zip_all_eq([](auto) { return true; }, short_vec, ys);
292 EXPECT_FALSE(result); // Lengths differ
293}
294
295//==============================================================================
296// Functional Operations: stl_zip_exists / stl_zip_any
297//==============================================================================
298
300{
301 std::vector<int> xs = {1, 2, 3};
302 std::vector<int> ys = {10, 20, 30};
303
304 bool result = stl_zip_exists([](auto t) {
305 return std::get<0>(t) == 2;
306 }, xs, ys);
307
308 EXPECT_TRUE(result);
309}
310
312{
313 std::vector<int> xs = {1, 2, 3};
314 std::vector<int> ys = {10, 20, 30};
315
316 bool result = stl_zip_exists([](auto t) {
317 return std::get<0>(t) == 99;
318 }, xs, ys);
319
320 EXPECT_FALSE(result);
321}
322
324{
325 std::vector<int> empty1, empty2;
326
327 bool result = stl_zip_exists([](auto) { return true; }, empty1, empty2);
328
329 EXPECT_FALSE(result);
330}
331
333{
334 std::vector<int> xs = {1, 2, 3};
335 std::vector<int> ys = {10, 20, 30};
336
337 bool result = stl_zip_any([](auto t) {
338 return std::get<0>(t) > 2;
339 }, xs, ys);
340
341 EXPECT_TRUE(result);
342}
343
345{
346 std::vector<int> xs = {1, 2, 3};
347 std::vector<int> ys = {10, 20, 30};
348
349 bool result = stl_zip_none([](auto t) {
350 return std::get<0>(t) > 100;
351 }, xs, ys);
352
353 EXPECT_TRUE(result);
354}
355
356//==============================================================================
357// Functional Operations: stl_zip_for_each
358//==============================================================================
359
361{
362 std::vector<int> xs = {1, 2, 3};
363 std::vector<int> ys = {10, 20, 30};
364
365 std::vector<int> sums;
366 stl_zip_for_each([&sums](auto t) {
367 sums.push_back(std::get<0>(t) + std::get<1>(t));
368 }, xs, ys);
369
370 EXPECT_EQ(sums.size(), 3);
371 EXPECT_EQ(sums[0], 11);
372 EXPECT_EQ(sums[1], 22);
373 EXPECT_EQ(sums[2], 33);
374}
375
377{
378 std::vector<int> xs = {10, 20, 30};
379 std::vector<std::string> ys = {"a", "b", "c"};
380
381 std::vector<size_t> indices;
382 stl_zip_for_each_indexed([&indices](size_t idx, auto) {
383 indices.push_back(idx);
384 }, xs, ys);
385
386 EXPECT_EQ(indices.size(), 3);
387 EXPECT_EQ(indices[0], 0);
388 EXPECT_EQ(indices[1], 1);
389 EXPECT_EQ(indices[2], 2);
390}
391
392//==============================================================================
393// Functional Operations: stl_zip_foldl / stl_zip_reduce
394//==============================================================================
395
397{
398 std::vector<int> prices = {10, 20, 30};
399 std::vector<int> quantities = {2, 3, 1};
400
401 int total = stl_zip_foldl(0, [](int acc, auto t) {
402 return acc + std::get<0>(t) * std::get<1>(t);
403 }, prices, quantities);
404
405 // 10*2 + 20*3 + 30*1 = 20 + 60 + 30 = 110
406 EXPECT_EQ(total, 110);
407}
408
410{
411 std::vector<int> nums = {1, 2, 3};
412 std::vector<std::string> strs = {"a", "b", "c"};
413
414 std::string result = stl_zip_foldl(std::string(""), [](std::string acc, auto t) {
415 return acc + std::to_string(std::get<0>(t)) + std::get<1>(t);
416 }, nums, strs);
417
418 EXPECT_EQ(result, "1a2b3c");
419}
420
422{
423 std::vector<int> xs = {1, 2, 3};
424 std::vector<int> ys = {10, 20, 30};
425
426 int sum = stl_zip_reduce(0, [](int acc, auto t) {
427 return acc + std::get<0>(t) + std::get<1>(t);
428 }, xs, ys);
429
430 EXPECT_EQ(sum, 66); // 1+10 + 2+20 + 3+30 = 66
431}
432
433//==============================================================================
434// Functional Operations: stl_zip_map
435//==============================================================================
436
438{
439 std::vector<int> xs = {1, 2, 3};
440 std::vector<int> ys = {10, 20, 30};
441
442 auto sums = stl_zip_map([](auto t) {
443 return std::get<0>(t) + std::get<1>(t);
444 }, xs, ys);
445
446 EXPECT_EQ(sums.size(), 3);
447 EXPECT_EQ(sums[0], 11);
448 EXPECT_EQ(sums[1], 22);
449 EXPECT_EQ(sums[2], 33);
450}
451
453{
454 std::vector<int> xs = {1, 2, 3};
455 std::vector<int> ys = {10, 20, 30};
456
457 auto strs = stl_zip_map([](auto t) {
458 return std::to_string(std::get<0>(t)) + "+" + std::to_string(std::get<1>(t));
459 }, xs, ys);
460
461 EXPECT_EQ(strs.size(), 3);
462 EXPECT_EQ(strs[0], "1+10");
463 EXPECT_EQ(strs[1], "2+20");
464 EXPECT_EQ(strs[2], "3+30");
465}
466
467//==============================================================================
468// Functional Operations: stl_zip_filter
469//==============================================================================
470
472{
473 std::vector<int> xs = {1, 2, 3, 4, 5};
474 std::vector<int> ys = {10, 20, 30, 40, 50};
475
476 auto result = stl_zip_filter([](auto t) {
477 return std::get<0>(t) % 2 == 0; // Even xs
478 }, xs, ys);
479
480 EXPECT_EQ(result.size(), 2); // (2,20) and (4,40)
481}
482
484{
485 std::vector<int> xs = {1, 3, 5};
486 std::vector<int> ys = {10, 30, 50};
487
488 auto result = stl_zip_filter([](auto t) {
489 return std::get<0>(t) % 2 == 0; // No even numbers
490 }, xs, ys);
491
492 EXPECT_EQ(result.size(), 0);
493}
494
495//==============================================================================
496// Functional Operations: stl_zip_find_first
497//==============================================================================
498
500{
501 std::vector<int> xs = {1, 2, 3, 4, 5};
502 std::vector<std::string> ys = {"a", "b", "c", "d", "e"};
503
504 auto result = stl_zip_find_first([](auto t) {
505 return std::get<0>(t) == 3;
506 }, xs, ys);
507
508 ASSERT_TRUE(result.has_value());
509 EXPECT_EQ(std::get<0>(*result), 3);
510 EXPECT_EQ(std::get<1>(*result), "c");
511}
512
514{
515 std::vector<int> xs = {1, 2, 3};
516 std::vector<int> ys = {10, 20, 30};
517
518 auto result = stl_zip_find_first([](auto t) {
519 return std::get<0>(t) == 99;
520 }, xs, ys);
521
522 EXPECT_FALSE(result.has_value());
523}
524
525//==============================================================================
526// Functional Operations: stl_zip_count
527//==============================================================================
528
530{
531 std::vector<int> xs = {1, 2, 3, 4, 5};
532 std::vector<int> ys = {10, 20, 30, 40, 50};
533
534 size_t count = stl_zip_count([](auto t) {
535 return std::get<0>(t) % 2 == 0;
536 }, xs, ys);
537
538 EXPECT_EQ(count, 2); // 2 and 4
539}
540
542{
543 std::vector<int> xs = {1, 2, 3, 4, 5};
544 std::vector<int> ys = {10, 20, 30, 40, 50};
545
547
548 std::vector<int> short_vec = {1, 2};
550}
551
553{
554 std::vector<int> xs = {1, 2, 3};
555 std::vector<int> ys = {10, 20, 30};
556
558}
559
561{
562 std::vector<int> xs = {1, 2, 3};
563 std::vector<int> ys = {10, 20};
564
566}
567
568//==============================================================================
569// Functional Operations: stl_zip_nth
570//==============================================================================
571
573{
574 std::vector<int> xs = {1, 2, 3, 4, 5};
575 std::vector<std::string> ys = {"a", "b", "c", "d", "e"};
576
577 auto result = stl_zip_nth(2, xs, ys);
578
579 ASSERT_TRUE(result.has_value());
580 EXPECT_EQ(std::get<0>(*result), 3);
581 EXPECT_EQ(std::get<1>(*result), "c");
582}
583
585{
586 std::vector<int> xs = {1, 2, 3};
587 std::vector<int> ys = {10, 20, 30};
588
589 auto result = stl_zip_nth(10, xs, ys);
590
591 EXPECT_FALSE(result.has_value());
592}
593
594//==============================================================================
595// Functional Operations: stl_zip_take / stl_zip_drop
596//==============================================================================
597
599{
600 std::vector<int> xs = {1, 2, 3, 4, 5};
601 std::vector<int> ys = {10, 20, 30, 40, 50};
602
603 auto result = stl_zip_take(3, xs, ys);
604
605 EXPECT_EQ(result.size(), 3);
606 EXPECT_EQ(std::get<0>(result[0]), 1);
607 EXPECT_EQ(std::get<0>(result[2]), 3);
608}
609
611{
612 std::vector<int> xs = {1, 2};
613 std::vector<int> ys = {10, 20};
614
615 auto result = stl_zip_take(10, xs, ys);
616
617 EXPECT_EQ(result.size(), 2);
618}
619
621{
622 std::vector<int> xs = {1, 2, 3, 4, 5};
623 std::vector<int> ys = {10, 20, 30, 40, 50};
624
625 auto result = stl_zip_drop(2, xs, ys);
626
627 EXPECT_EQ(result.size(), 3);
628 EXPECT_EQ(std::get<0>(result[0]), 3);
629 EXPECT_EQ(std::get<0>(result[2]), 5);
630}
631
633{
634 std::vector<int> xs = {1, 2, 3};
635 std::vector<int> ys = {10, 20, 30};
636
637 auto result = stl_zip_drop(10, xs, ys);
638
639 EXPECT_EQ(result.size(), 0);
640}
641
642//==============================================================================
643// Functional Operations: stl_zip_partition
644//==============================================================================
645
647{
648 std::vector<int> xs = {1, 2, 3, 4, 5};
649 std::vector<std::string> ys = {"a", "b", "c", "d", "e"};
650
651 auto [evens, odds] = stl_zip_partition([](auto t) {
652 return std::get<0>(t) % 2 == 0;
653 }, xs, ys);
654
655 EXPECT_EQ(evens.size(), 2); // (2,"b"), (4,"d")
656 EXPECT_EQ(odds.size(), 3); // (1,"a"), (3,"c"), (5,"e")
657}
658
659//==============================================================================
660// Functional Operations: stl_zip_to_vector
661//==============================================================================
662
664{
665 std::vector<int> xs = {1, 2, 3};
666 std::vector<std::string> ys = {"a", "b", "c"};
667
668 auto result = stl_zip_to_vector(xs, ys);
669
670 EXPECT_EQ(result.size(), 3);
671 EXPECT_EQ(std::get<0>(result[0]), 1);
672 EXPECT_EQ(std::get<1>(result[0]), "a");
673}
674
675//==============================================================================
676// Traverse Operations
677//==============================================================================
678
680{
681 std::vector<int> xs = {1, 2, 3};
682 std::vector<int> ys = {10, 20, 30};
683
684 bool result = stl_zip_traverse([](auto t) {
685 return std::get<0>(t) < std::get<1>(t);
686 }, xs, ys);
687
688 EXPECT_TRUE(result);
689}
690
692{
693 std::vector<int> xs = {1, 200, 3};
694 std::vector<int> ys = {10, 20, 30};
695
696 int count = 0;
697 bool result = stl_zip_traverse([&count](auto t) {
698 ++count;
699 return std::get<0>(t) < std::get<1>(t);
700 }, xs, ys);
701
702 EXPECT_FALSE(result);
703 EXPECT_EQ(count, 2); // Stopped at second element
704}
705
706//==============================================================================
707// Comparison: stl_zip_cmp
708//==============================================================================
709
711{
712 std::vector<int> a = {1, 2, 3};
713 std::vector<int> b = {1, 2, 3};
714 std::vector<int> c = {1, 2, 3};
715
716 bool result = stl_zip_cmp([](auto x, auto y) { return x == y; }, a, b, c);
717
718 EXPECT_TRUE(result);
719}
720
722{
723 std::vector<int> a = {1, 2, 3};
724 std::vector<int> b = {1, 99, 3};
725 std::vector<int> c = {1, 2, 3};
726
727 bool result = stl_zip_cmp([](auto x, auto y) { return x == y; }, a, b, c);
728
729 EXPECT_FALSE(result);
730}
731
732//==============================================================================
733// Edge Cases
734//==============================================================================
735
737{
738 std::vector<int> empty1, empty2;
739
740 auto view = stl_zip(empty1, empty2);
742 EXPECT_EQ(view.size(), 0);
743}
744
746{
747 std::vector<int> empty;
748 std::vector<int> nonempty = {1, 2, 3};
749
750 auto view = stl_zip(empty, nonempty);
752}
753
755{
756 std::vector<int> xs(1000);
757 std::vector<int> ys(1000);
758 std::iota(xs.begin(), xs.end(), 0);
759 std::iota(ys.begin(), ys.end(), 1000);
760
761 int sum = stl_zip_foldl(0, [](int acc, auto t) {
762 return acc + std::get<0>(t) + std::get<1>(t);
763 }, xs, ys);
764
765 // Sum of 0..999 + sum of 1000..1999
766 // = 999*1000/2 + (1999*2000/2 - 999*1000/2)
767 // = 499500 + 1499500 = 1999000
768 EXPECT_EQ(sum, 1999000);
769}
770
771//==============================================================================
772// Enumerate Tests
773//==============================================================================
774
776{
777 std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
778
779 std::vector<size_t> indices;
780 std::vector<std::string> collected_names;
781
782 for (auto [idx, name] : stl_enumerate(names))
783 {
784 indices.push_back(idx);
785 collected_names.push_back(name);
786 }
787
788 EXPECT_EQ(indices.size(), 3);
789 EXPECT_EQ(indices[0], 0);
790 EXPECT_EQ(indices[1], 1);
791 EXPECT_EQ(indices[2], 2);
792 EXPECT_EQ(collected_names[0], "Alice");
793}
794
796{
797 std::vector<int> empty;
798
799 int count = 0;
800 for (auto [idx, val] : stl_enumerate(empty))
801 {
802 (void)idx;
803 (void)val;
804 ++count;
805 }
806
807 EXPECT_EQ(count, 0);
808}
809
810//==============================================================================
811// Take While / Drop While Tests
812//==============================================================================
813
815{
816 std::vector<int> xs = {1, 2, 3, 10, 4, 5};
817 std::vector<int> ys = {10, 20, 30, 100, 40, 50};
818
819 auto result = stl_zip_take_while([](auto t) {
820 return std::get<0>(t) < 10;
821 }, xs, ys);
822
823 EXPECT_EQ(result.size(), 3);
824 EXPECT_EQ(std::get<0>(result[0]), 1);
825 EXPECT_EQ(std::get<0>(result[2]), 3);
826}
827
829{
830 std::vector<int> xs = {10, 20, 30};
831 std::vector<int> ys = {1, 2, 3};
832
833 auto result = stl_zip_take_while([](auto t) {
834 return std::get<0>(t) < 5;
835 }, xs, ys);
836
837 EXPECT_EQ(result.size(), 0);
838}
839
841{
842 std::vector<int> xs = {1, 2, 3, 10, 4, 5};
843 std::vector<int> ys = {10, 20, 30, 100, 40, 50};
844
845 auto result = stl_zip_drop_while([](auto t) {
846 return std::get<0>(t) < 10;
847 }, xs, ys);
848
849 EXPECT_EQ(result.size(), 3);
850 EXPECT_EQ(std::get<0>(result[0]), 10);
851}
852
854{
855 std::vector<int> xs = {1, 2, 3};
856 std::vector<int> ys = {10, 20, 30};
857
858 auto result = stl_zip_drop_while([](auto t) {
859 return std::get<0>(t) < 100;
860 }, xs, ys);
861
862 EXPECT_EQ(result.size(), 0);
863}
864
865//==============================================================================
866// First / Last Tests
867//==============================================================================
868
870{
871 std::vector<int> xs = {1, 2, 3};
872 std::vector<std::string> ys = {"a", "b", "c"};
873
874 auto result = stl_zip_first(xs, ys);
875
876 ASSERT_TRUE(result.has_value());
877 EXPECT_EQ(std::get<0>(*result), 1);
878 EXPECT_EQ(std::get<1>(*result), "a");
879}
880
882{
883 std::vector<int> empty1, empty2;
884
885 auto result = stl_zip_first(empty1, empty2);
886
887 EXPECT_FALSE(result.has_value());
888}
889
891{
892 std::vector<int> xs = {1, 2, 3};
893 std::vector<std::string> ys = {"a", "b", "c"};
894
895 auto result = stl_zip_last(xs, ys);
896
897 ASSERT_TRUE(result.has_value());
898 EXPECT_EQ(std::get<0>(*result), 3);
899 EXPECT_EQ(std::get<1>(*result), "c");
900}
901
903{
904 std::vector<int> xs = {1, 2, 3, 4, 5};
905 std::vector<int> ys = {10, 20, 30, 40, 50};
906
907 auto result = stl_zip_find_last([](auto t) {
908 return std::get<0>(t) % 2 == 0;
909 }, xs, ys);
910
911 ASSERT_TRUE(result.has_value());
912 EXPECT_EQ(std::get<0>(*result), 4); // Last even
913}
914
916{
917 std::vector<int> xs = {1, 2, 3, 4, 5};
918 std::vector<int> ys = {10, 20, 30, 40, 50};
919
920 size_t idx = stl_zip_find_index([](auto t) {
921 return std::get<0>(t) == 3;
922 }, xs, ys);
923
924 EXPECT_EQ(idx, 2);
925}
926
928{
929 std::vector<int> xs = {1, 2, 3};
930 std::vector<int> ys = {10, 20, 30};
931
932 size_t idx = stl_zip_find_index([](auto t) {
933 return std::get<0>(t) == 99;
934 }, xs, ys);
935
936 EXPECT_EQ(idx, 3); // Returns total count when not found
937}
938
939//==============================================================================
940// Unzip Tests
941//==============================================================================
942
944{
945 std::vector<std::pair<int, std::string>> pairs = {{1, "a"}, {2, "b"}, {3, "c"}};
946
947 auto [nums, strs] = stl_unzip(pairs);
948
949 EXPECT_EQ(nums.size(), 3);
950 EXPECT_EQ(strs.size(), 3);
951 EXPECT_EQ(nums[0], 1);
952 EXPECT_EQ(strs[2], "c");
953}
954
956{
957 std::vector<std::tuple<int, double, char>> tuples = {
958 {1, 1.1, 'a'}, {2, 2.2, 'b'}, {3, 3.3, 'c'}
959 };
960
961 auto [ints, doubles, chars] = stl_unzip_tuple(tuples);
962
963 EXPECT_EQ(ints.size(), 3);
964 EXPECT_EQ(doubles.size(), 3);
965 EXPECT_EQ(chars.size(), 3);
966 EXPECT_EQ(ints[1], 2);
967 EXPECT_DOUBLE_EQ(doubles[1], 2.2);
968 EXPECT_EQ(chars[1], 'b');
969}
970
971//==============================================================================
972// Adjacent Tests
973//==============================================================================
974
976{
977 std::vector<int> v = {1, 2, 3, 4, 5};
978
979 auto pairs = stl_adjacent(v);
980
981 EXPECT_EQ(pairs.size(), 4);
982 EXPECT_EQ(pairs[0].first, 1);
983 EXPECT_EQ(pairs[0].second, 2);
984 EXPECT_EQ(pairs[3].first, 4);
985 EXPECT_EQ(pairs[3].second, 5);
986}
987
989{
990 std::vector<int> v = {42};
991
992 auto pairs = stl_adjacent(v);
993
994 EXPECT_EQ(pairs.size(), 0);
995}
996
998{
999 std::vector<int> v;
1000
1001 auto pairs = stl_adjacent(v);
1002
1003 EXPECT_EQ(pairs.size(), 0);
1004}
1005
1007{
1008 std::vector<int> v = {1, 3, 6, 10};
1009
1010 auto diffs = stl_adjacent_map([](int a, int b) { return b - a; }, v);
1011
1012 EXPECT_EQ(diffs.size(), 3);
1013 EXPECT_EQ(diffs[0], 2);
1014 EXPECT_EQ(diffs[1], 3);
1015 EXPECT_EQ(diffs[2], 4);
1016}
1017
1019{
1020 std::vector<int> sorted = {1, 2, 3, 4, 5};
1021 std::vector<int> unsorted = {1, 3, 2, 4, 5};
1022
1023 EXPECT_TRUE(stl_adjacent_all([](int a, int b) { return a < b; }, sorted));
1024 EXPECT_FALSE(stl_adjacent_all([](int a, int b) { return a < b; }, unsorted));
1025}
1026
1028{
1029 std::vector<int> with_dup = {1, 2, 2, 3};
1030 std::vector<int> no_dup = {1, 2, 3, 4};
1031
1032 EXPECT_TRUE(stl_adjacent_exists([](int a, int b) { return a == b; }, with_dup));
1033 EXPECT_FALSE(stl_adjacent_exists([](int a, int b) { return a == b; }, no_dup));
1034}
1035
1036//==============================================================================
1037// ML-style Operations Tests
1038//==============================================================================
1039
1041{
1042 std::vector<int> xs = {10, 20, 30};
1043 std::vector<int> ys = {1, 2, 3};
1044
1045 auto results = stl_zip_mapi([](size_t i, auto t) {
1046 return std::to_string(i) + ":" + std::to_string(std::get<0>(t) + std::get<1>(t));
1047 }, xs, ys);
1048
1049 EXPECT_EQ(results.size(), 3);
1050 EXPECT_EQ(results[0], "0:11");
1051 EXPECT_EQ(results[1], "1:22");
1052 EXPECT_EQ(results[2], "2:33");
1053}
1054
1056{
1057 std::vector<int> xs = {10, 20, 30, 40, 50};
1058 std::vector<std::string> ys = {"a", "b", "c", "d", "e"};
1059
1060 auto evens = stl_zip_filteri([](size_t i, auto) {
1061 return i % 2 == 0;
1062 }, xs, ys);
1063
1064 EXPECT_EQ(evens.size(), 3);
1065 EXPECT_EQ(std::get<0>(evens[0]), 10);
1066 EXPECT_EQ(std::get<0>(evens[1]), 30);
1067 EXPECT_EQ(std::get<0>(evens[2]), 50);
1068}
1069
1071{
1072 std::vector<int> xs = {1, 2, 3, 4};
1073 std::vector<int> ys = {10, 20, 30, 40};
1074
1075 auto sums = stl_zip_scan_left(0, [](int acc, auto t) {
1076 return acc + std::get<0>(t);
1077 }, xs, ys);
1078
1079 EXPECT_EQ(sums.size(), 5);
1080 EXPECT_EQ(sums[0], 0); // init
1081 EXPECT_EQ(sums[1], 1); // 0 + 1
1082 EXPECT_EQ(sums[2], 3); // 1 + 2
1083 EXPECT_EQ(sums[3], 6); // 3 + 3
1084 EXPECT_EQ(sums[4], 10); // 6 + 4
1085}
1086
1088{
1089 std::vector<int> xs = {1, 2, 3};
1090 std::vector<int> ys = {10, 20, 30};
1091
1092 auto products = stl_zip_scan_left(1, [](int acc, auto t) {
1093 return acc * std::get<0>(t) * std::get<1>(t);
1094 }, xs, ys);
1095
1096 EXPECT_EQ(products.size(), 4);
1097 EXPECT_EQ(products[0], 1); // init
1098 EXPECT_EQ(products[1], 10); // 1 * 1 * 10
1099 EXPECT_EQ(products[2], 400); // 10 * 2 * 20
1100 EXPECT_EQ(products[3], 36000); // 400 * 3 * 30
1101}
1102
1104{
1105 std::vector<int> xs = {1, 2, 3, 4, 5};
1106 std::vector<std::string> ys = {"a", "b", "c", "d", "e"};
1107
1108 auto result = stl_zip_find_mapi([](size_t i, auto t) -> std::optional<std::string> {
1109 if (std::get<0>(t) == 3)
1110 return "found at " + std::to_string(i);
1111 return std::nullopt;
1112 }, xs, ys);
1113
1114 ASSERT_TRUE(result.has_value());
1115 EXPECT_EQ(*result, "found at 2");
1116}
1117
1119{
1120 std::vector<int> xs = {1, 2, 3};
1121 std::vector<int> ys = {10, 20, 30};
1122
1123 auto result = stl_zip_find_mapi([](size_t, auto t) -> std::optional<int> {
1124 if (std::get<0>(t) > 100)
1125 return std::get<0>(t);
1126 return std::nullopt;
1127 }, xs, ys);
1128
1129 EXPECT_FALSE(result.has_value());
1130}
1131
1133{
1134 std::vector<int> xs = {1, 2, 3};
1135 std::vector<int> ys = {10, 20, 30};
1136
1138}
1139
1141{
1142 std::vector<int> xs = {1, 2, 3, 4};
1143 std::vector<int> ys = {10, 20, 30};
1144
1146}
1147
1149{
1150 std::vector<int> xs = {1, 2, 3};
1151 std::vector<int> ys = {10, 20, 30};
1152
1153 bool result = stl_zip_equal_by([](auto t) {
1154 return std::get<0>(t) * 10 == std::get<1>(t);
1155 }, xs, ys);
1156
1157 EXPECT_TRUE(result);
1158}
1159
1161{
1162 std::vector<int> xs = {1, 2, 3};
1163 std::vector<std::string> ys = {"a", "b", "c"};
1164
1165 EXPECT_TRUE(stl_zip_mem(std::make_tuple(2, std::string("b")), xs, ys));
1166 EXPECT_FALSE(stl_zip_mem(std::make_tuple(2, std::string("x")), xs, ys));
1167}
1168
1170{
1171 std::vector<std::string> keys = {"one", "two", "three"};
1172 std::vector<int> values = {1, 2, 3};
1173
1174 auto result = stl_zip_assoc(std::string("two"), keys, values);
1175
1176 ASSERT_TRUE(result.has_value());
1177 EXPECT_EQ(std::get<0>(*result), "two");
1178 EXPECT_EQ(std::get<1>(*result), 2);
1179}
1180
1182{
1183 std::vector<std::string> keys = {"one", "two", "three"};
1184 std::vector<int> values = {1, 2, 3};
1185
1186 auto result = stl_zip_assoc(std::string("four"), keys, values);
1187
1188 EXPECT_FALSE(result.has_value());
1189}
1190
1192{
1193 std::vector<int> xs = {3, 1, 4, 1, 5};
1194 std::vector<int> ys = {30, 10, 40, 10, 50};
1195
1196 auto result = stl_zip_min(xs, ys);
1197
1198 ASSERT_TRUE(result.has_value());
1199 EXPECT_EQ(std::get<0>(*result), 1);
1200}
1201
1203{
1204 std::vector<int> xs = {3, 1, 4, 1, 5};
1205 std::vector<int> ys = {30, 10, 40, 10, 50};
1206
1207 auto result = stl_zip_max(xs, ys);
1208
1209 ASSERT_TRUE(result.has_value());
1210 EXPECT_EQ(std::get<0>(*result), 5);
1211}
1212
1214{
1215 std::vector<int> xs = {3, 1, 4, 1, 5};
1216 std::vector<int> ys = {30, 10, 40, 10, 50};
1217
1218 auto result = stl_zip_min_max(xs, ys);
1219
1220 ASSERT_TRUE(result.has_value());
1221 EXPECT_EQ(std::get<0>(result->first), 1); // min
1222 EXPECT_EQ(std::get<0>(result->second), 5); // max
1223}
1224
1226{
1227 std::vector<int> empty;
1228 std::vector<int> ys = {1, 2, 3};
1229
1230 auto result = stl_zip_min_max(empty, ys);
1231
1232 EXPECT_FALSE(result.has_value());
1233}
1234
1235// Main
1236int main(int argc, char **argv)
1237{
1238 ::testing::InitGoogleTest(&argc, argv);
1239 return RUN_ALL_TESTS();
1240}
Lazy zip iterators and functional operations for STL containers.
TEST_F(StlZipViewTest, BasicIteration)
int main()
void empty() noexcept
empty the list
Definition htlist.H:1689
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
std::vector< std::string > vs
std::vector< int > vi
std::list< double > ld
#define TEST(name)
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
auto stl_zip_filteri(Pred &&pred, const Containers &... cs)
Filter with index (filteri in ML).
auto stl_adjacent_map(Op &&op, const Container &c)
Apply function to adjacent pairs of elements.
bool stl_zip_exists(Pred &&pred, const Containers &... cs)
Check if predicate holds for any zipped tuple.
Definition ah-stl-zip.H:529
bool stl_zip_equal_by(Eq &&eq, const Containers &... cs)
Check equality with custom comparator.
bool stl_adjacent_exists(Pred &&pred, const Container &c)
Check if predicate holds for any adjacent pair.
auto stl_zip_find_last(Pred &&pred, const Containers &... cs)
Find last tuple satisfying predicate.
bool stl_zip_traverse(Pred &&pred, const Containers &... cs)
Traverse while predicate returns true.
Definition ah-stl-zip.H:940
bool stl_zip_all_eq(Pred &&pred, const Containers &... cs)
Check if predicate holds for all tuples AND containers have equal length.
Definition ah-stl-zip.H:493
auto stl_zip_min_max(const Containers &... cs)
Get both min and max in a single pass.
auto stl_zip_max(const Containers &... cs)
Get maximum tuple according to comparator.
bool stl_adjacent_all(Pred &&pred, const Container &c)
Check if predicate holds for all adjacent pairs.
auto stl_zip_take_while(Pred &&pred, const Containers &... cs)
Take tuples while predicate returns true.
size_t stl_zip_count(Pred &&pred, const Containers &... cs)
Count tuples satisfying predicate.
Definition ah-stl-zip.H:752
bool stl_zip_equal_length(const Containers &... cs)
Check if all containers have equal length.
Definition ah-stl-zip.H:789
auto stl_zip_drop_while(Pred &&pred, const Containers &... cs)
Skip tuples while predicate returns true, then return the rest.
bool stl_zip_cmp(Cmp &&cmp, const Containers &... cs)
Compare elements across containers using a comparator.
auto stl_zip_find_first(Pred &&pred, const Containers &... cs)
Find first tuple satisfying predicate.
Definition ah-stl-zip.H:731
bool stl_zip_mem(const Tuple &target, const Containers &... cs)
Check if a tuple exists in the zipped sequence (mem in ML).
auto stl_unzip_tuple(const std::vector< std::tuple< Ts... > > &tuples)
Unzip a vector of tuples into a tuple of vectors.
auto stl_zip_first(const Containers &... cs)
Get first tuple from zipped containers.
auto stl_zip_mapi(Op &&op, const Containers &... cs)
Map with index (mapi in ML).
size_t stl_zip_find_index(Pred &&pred, const Containers &... cs)
Find index of first tuple satisfying predicate.
bool stl_zip_none(Pred &&pred, const Containers &... cs)
Check if no tuple satisfies the predicate.
Definition ah-stl-zip.H:558
auto stl_zip_scan_left(T init, Op &&op, const Containers &... cs)
Scan left (scan_left in ML) - fold with intermediate results.
constexpr auto stl_enumerate(const Container &c)
Create an enumerate view over a container.
auto stl_zip_map(Op &&op, const Containers &... cs)
Map operation over zipped tuples, returning a vector.
Definition ah-stl-zip.H:685
bool stl_zip_equal(const Containers &... cs)
Check equality of zipped sequences.
auto stl_zip_find_mapi(Op &&op, const Containers &... cs)
Find and map with index (find_mapi in ML).
auto stl_zip_assoc(const Key &key, const Containers &... cs)
Find value associated with key in zipped pairs (assoc in ML).
auto stl_zip_filter(Pred &&pred, const Containers &... cs)
Filter zipped tuples by predicate.
Definition ah-stl-zip.H:709
auto stl_unzip(const std::vector< std::pair< T, U > > &pairs)
Unzip a vector of pairs into two vectors.
auto stl_zip_drop(const size_t n, const Containers &... cs)
Skip first n tuples, return the rest.
Definition ah-stl-zip.H:853
T stl_zip_foldl(T init, Op &&op, const Containers &... cs)
Left fold over zipped tuples.
Definition ah-stl-zip.H:641
auto stl_zip_min(const Containers &... cs)
Get minimum tuple according to comparator.
T stl_zip_reduce(T init, Op &&op, const Containers &... cs)
Alias for stl_zip_foldl (alternative name)
Definition ah-stl-zip.H:651
auto stl_zip_nth(const size_t n, const Containers &... cs)
Get n-th tuple from zipped containers.
Definition ah-stl-zip.H:808
auto stl_adjacent(const Container &c)
Zip adjacent (consecutive) elements of a container.
auto stl_zip_partition(Pred &&pred, const Containers &... cs)
Partition tuples by predicate.
Definition ah-stl-zip.H:884
constexpr auto stl_zip(const Containers &... cs)
Create a lazy zip view over STL containers.
Definition ah-stl-zip.H:414
auto stl_zip_take(const size_t n, const Containers &... cs)
Take first n tuples from zipped containers.
Definition ah-stl-zip.H:830
auto stl_zip_last(const Containers &... cs)
Get last tuple from zipped containers.
size_t stl_zip_length(const Containers &... cs)
Count total tuples (minimum length of containers).
Definition ah-stl-zip.H:771
void stl_zip_for_each(Op &&op, const Containers &... cs)
Apply operation to each zipped tuple (for side effects).
Definition ah-stl-zip.H:587
auto stl_zip_to_vector(const Containers &... cs)
Materialize zipped tuples into a vector.
Definition ah-stl-zip.H:912
void stl_zip_for_each_indexed(Op &&op, const Containers &... cs)
Apply operation to each tuple with its index.
Definition ah-stl-zip.H:603
bool stl_zip_all(Pred &&pred, const Containers &... cs)
Check if predicate holds for all zipped tuples.
Definition ah-stl-zip.H:472
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
bool stl_zip_any(Pred &&pred, const Containers &... cs)
Alias for stl_zip_exists (Python/JS style name)
Definition ah-stl-zip.H:539
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
DynList< int > l