Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-functional.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
33
38# include <gtest/gtest.h>
39
40# include <ah-zip.H>
41# include <ahFunctional.H>
42# include <ah-string-utils.H>
43# include <tpl_dynSetTree.H>
44# include <tpl_odhash.H>
45# include <tpl_dynArray.H>
46
47using namespace std;
48using namespace Aleph;
49
51{
52 EXPECT_EQ(range(0, 10), build_dynlist<int>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
53 EXPECT_EQ(range(0, 10, 2), build_dynlist<int>(0, 2, 4, 6, 8, 10));
54 EXPECT_EQ(nrange(2, 5, 3), build_dynlist<int>(2, 3, 5));
55 EXPECT_EQ(contiguous_range(1, 5), build_dynlist<int>(1, 2, 3, 4, 5));
56 EXPECT_EQ(range(5), build_dynlist<int>(0, 1, 2, 3, 4));
57}
58
60{
61 EXPECT_EQ(rep(5, 0), build_dynlist<int>(0, 0, 0, 0, 0));
62 EXPECT_EQ(rep(3), build_dynlist<int>(0, 0, 0));
63}
64
66{
67 auto sq = [] (int x) { return x * x; };
68 auto r = set_range<int, DynList>(0, 4, 1, sq);
69 EXPECT_EQ(r, build_dynlist<int>(0, 1, 4, 9, 16));
70
71 auto r2 = set_range<int, DynList>(0, 6, 2, sq);
72 EXPECT_EQ(r2, build_dynlist<int>(0, 4, 16, 36));
73}
74
76{
77 size_t count = 0;
78 each(5, [&count] () { ++count; });
79 EXPECT_EQ(count, 5);
80
81 count = 0;
82 each(2, 5, [&count] () { ++count; });
83 EXPECT_EQ(count, 4);
84}
85
86struct TreeContainer : testing::Test
87{
88 static constexpr size_t N = 10;
91 {
92 tbl = range<size_t>(0, N - 1);
93 }
94};
95
97{
98 auto l = pointers_list(tbl);
99
100 size_t i = 0;
101 for (auto it = l.get_it(); it.has_curr(); it.next_ne(), ++i)
102 EXPECT_EQ(*it.get_curr_ne(), i);
103
104 EXPECT_TRUE(zip_all([] (auto t) { return *get<0>(t) == get<1>(t); }, l, tbl));
105}
106
112
114{
115 size_t i = 0;
116 for_each(tbl, [&i] (auto & k)
117 {
118 EXPECT_EQ(i++, k);
119 });
120
121 enum_for_each(tbl, ([] (auto & k, auto & i)
122 {
123 EXPECT_EQ(i, k);
124 }));
125
126 i = 0;
127 EXPECT_TRUE(all(tbl, [&i] (auto & k) { return k == i++; }));
128
129 EXPECT_TRUE(exists(tbl, [] (auto & i) { return i == 3; }));
130 EXPECT_FALSE(exists(tbl, [] (auto & i) { return i == N; }));
131
132 auto lfilt = filter(tbl, [] (auto & i) { return i <= 3; });
134
135 auto lp = maps<string>(tbl, [] (const auto & i) { return to_string(i); });
137 ("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"));
138
139 auto lf = foldl<size_t>(tbl, 0, [] (auto & a, auto & i) { return a + i; });
140 EXPECT_EQ(lf, N*(N - 1)/2);
141}
142
144{
145 auto l = gen_seq_list_tuples(tbl, 7);
147 ( build_dynlist<size_t>(0, 1, 2, 3, 4, 5, 6),
148 build_dynlist<size_t>(1, 2, 3, 4, 5, 6, 7),
149 build_dynlist<size_t>(2, 3, 4, 5, 6, 7, 8),
150 build_dynlist<size_t>(3, 4, 5, 6, 7, 8, 9) ));
151}
152
154{
155 auto l = enumerate(tbl);
156 EXPECT_TRUE(l.all([] (auto & p) { return p.first == p.second; }));
157}
158
160{
161 auto idx = indexes(tbl);
162 size_t i = 0;
163 for (auto it = idx.get_it(); it.has_curr(); it.next_ne(), ++i)
164 {
165 auto & p = it.get_curr();
166 EXPECT_EQ(p.first, i);
167 EXPECT_EQ(p.second, i);
168 }
169
170 auto tidx = tindexes(tbl);
171 i = 0;
172 for (auto it = tidx.get_it(); it.has_curr(); it.next_ne(), ++i)
173 {
174 auto & t = it.get_curr();
175 EXPECT_EQ(get<0>(t), i);
176 EXPECT_EQ(get<1>(t), i);
177 }
178}
179
181{
183 auto rev = reverse(l);
184 EXPECT_EQ(rev, build_dynlist<size_t>(9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
185}
186
188{
189 auto p = partition(tbl, [] (const size_t & i) { return i < 5; });
190 EXPECT_EQ(p.first, build_dynlist<size_t>(0, 1, 2, 3, 4));
191 EXPECT_EQ(p.second, build_dynlist<size_t>(5, 6, 7, 8, 9));
192}
193
195{
196 DynList<size_t> l1 = range<size_t>(0, N - 1);
197 DynList<size_t> l2 = range<size_t>(0, N - 1);
198 EXPECT_FALSE(diff(l1, l2));
199
200 l2.get_last() = 100;
201 EXPECT_TRUE(diff(l1, l2));
202}
203
205{
207 EXPECT_TRUE(containers_eq(tbl, l, std::equal_to<size_t>()));
208}
209
211{
212 constexpr size_t N = 20;
213 DynList<size_t> l1 = range(N);
214 DynList<size_t> l2 = range(N + 1);
217
218 EXPECT_TRUE(eq(l1, s1));
219 EXPECT_TRUE(lesser(l1, l2));
220 EXPECT_TRUE(lesser(l1, s2));
221 EXPECT_FALSE(lesser(l1, s1));
222 EXPECT_FALSE(lesser(s1, l1));
223
224 auto d = are_eq(l1, s1);
226 EXPECT_EQ(get<1>(d), N);
227
228 // Now we modify the last item of l1
229 l1.get_last() = N - 2;
230 EXPECT_FALSE(eq(l1, s1));
231 EXPECT_TRUE(lesser(l1, s1));
232
233 d = are_eq(l1, s1);
235 EXPECT_EQ(get<1>(d), N - 1);
236 EXPECT_EQ(get<2>(d), N - 2);
237 EXPECT_EQ(get<3>(d), N - 1);
238}
239
241{
242 {
243 auto z = zip(tbl, range(N));
244 EXPECT_TRUE(z.all([] (auto & p) { return p.first == p.second; }));
245
246 auto p = unzip(z);
247 EXPECT_TRUE(zip_all([] (auto p) { return get<0>(p) == get<1>(p); },
248 p.first, p.second));
249 }
250 {
251 auto z = tzip(tbl, range(N));
252 EXPECT_TRUE(z.all([] (auto & p) { return get<0>(p) == get<1>(p); }));
253
254 auto p = tunzip(z);
255 EXPECT_TRUE(zip_all([] (auto p) { return get<0>(p) == get<1>(p); },
256 get<0>(p), get<1>(p)));
257 }
258 {
259 auto z = zipEq(tbl, range(N));
260 EXPECT_TRUE(z.all([] (auto & p) { return p.first == p.second; }));
261
262 EXPECT_THROW(zipEq(tbl, range(N + 1)), length_error);
263
264 auto p = unzip(z);
265 EXPECT_TRUE(zip_all([] (auto p) { return get<0>(p) == get<1>(p); },
266 p.first, p.second));
267 }
268 {
269 auto z = tzipEq(tbl, range(N));
270 EXPECT_TRUE(z.all([] (auto & p) { return get<0>(p) == get<1>(p); }));
271
272 EXPECT_THROW(tzipEq(tbl, range(N + 1)), length_error);
273
274 auto p = tunzip(z);
275 EXPECT_TRUE(zip_all([] (auto p) { return get<0>(p) == get<1>(p); },
276 get<0>(p), get<1>(p)));
277 }
278}
279
281{
282 DynList<int> l = build_dynlist<int>(1, 1, 2, 2, 2, 4, 4, 0, 0, 1);
283 auto result = sequential_groups(l);
284 EXPECT_EQ(result.second, 5);
285 auto & groups = result.first;
286
287 auto it = groups.get_it();
288 EXPECT_EQ(it.get_curr(), build_dynlist<int>(1, 1)); it.next();
289 EXPECT_EQ(it.get_curr(), build_dynlist<int>(2, 2, 2)); it.next();
290 EXPECT_EQ(it.get_curr(), build_dynlist<int>(4, 4)); it.next();
291 EXPECT_EQ(it.get_curr(), build_dynlist<int>(0, 0)); it.next();
292 EXPECT_EQ(it.get_curr(), build_dynlist<int>(1));
293
294 // Empty container
295 DynList<int> empty;
296 auto empty_result = sequential_groups(empty);
297 EXPECT_EQ(empty_result.second, 0);
299}
300
302{
303 DynList<int> l = build_dynlist<int>(1, 1, 2, 2, 2, 4, 4, 0, 0, 1);
304 auto result = unique_sequential(l);
305 EXPECT_EQ(result.second, 5);
306 EXPECT_EQ(result.first, build_dynlist<int>(1, 2, 4, 0, 1));
307
308 // Empty container
309 DynList<int> empty;
310 auto empty_result = unique_sequential(empty);
311 EXPECT_EQ(empty_result.second, 0);
313}
314
316{
317 DynList<int> l1 = range(5);
318 DynList<int> l2 = range(5);
319
320 auto pit = get_pair_it(l1, l2);
321 size_t i = 0;
322 while (pit.has_curr())
323 {
324 auto p = pit.get_curr();
325 EXPECT_EQ(p.first, i);
326 EXPECT_EQ(p.second, i);
327 pit.next();
328 ++i;
329 }
330 EXPECT_EQ(i, 5);
331 EXPECT_TRUE(pit.was_traversed());
332
333 // Test with position
334 auto pit2 = get_pair_it(l1, l2, 2);
335 auto p = pit2.get_curr();
336 EXPECT_EQ(p.first, 2);
337 EXPECT_EQ(p.second, 2);
338}
339
341{
342 DynList<int> c;
343 size_t n = append_in_container(c, 1, 2, 3);
344 EXPECT_EQ(n, 3);
345 EXPECT_EQ(c, build_dynlist<int>(1, 2, 3));
346
348 n = insert_in_container(s, 5, 3, 1, 4, 2);
349 EXPECT_EQ(n, 5);
350 EXPECT_EQ(s.size(), 5);
351
352 n = remove_from_container(s, 1, 2, 3);
353 EXPECT_EQ(n, 3);
354 EXPECT_EQ(s.size(), 2);
355}
356
363
365{
367 ll.append(build_dynlist<int>(1, 2, 3));
369 ll.append(build_dynlist<int>(6, 7, 8, 9));
370
371 auto flat = flatten(ll);
372 EXPECT_EQ(flat, build_dynlist<int>(1, 2, 3, 4, 5, 6, 7, 8, 9));
373}
374
383
385{
386 EXPECT_TRUE(is_equal(5, 3, 5, 7));
387 EXPECT_TRUE(is_equal(5, 5));
388 EXPECT_FALSE(is_equal(5, 1, 2, 3, 4));
390
391 // Mixed types
392 EXPECT_TRUE(is_equal(5, 5.0));
393 EXPECT_TRUE(is_equal(5, 3, 5.0, 7));
394}
395
397{
398 int val = 42;
399 Some<int> s(val);
401 EXPECT_EQ(s.get_item(), 42);
402 s.get_item() = 43;
403 EXPECT_EQ(val, 43);
404
405 None<int> n;
407 EXPECT_THROW(n.get_item(), std::logic_error);
408
409 const None<int> cn;
410 EXPECT_THROW(cn.get_item(), std::logic_error);
411
412 const Some<int> cs(val);
413 EXPECT_EQ(cs.get_item(), 43);
414}
415
417{
418 // Floating point nrange
419 auto r = nrange<double, DynList>(0.0, 1.0, 11);
420 EXPECT_EQ(r.size(), 11u);
421 EXPECT_DOUBLE_EQ(r.get_first(), 0.0);
422 EXPECT_DOUBLE_EQ(r.get_last(), 1.0);
423 EXPECT_DOUBLE_EQ(r.nth(5), 0.5);
424
425 // n=1 case
426 auto r1 = nrange<int, DynList>(10, 20, 1);
427 ASSERT_EQ(r1.size(), 1u);
428 EXPECT_EQ(r1.get_first(), 10);
429
430 // n=0 case
431 EXPECT_THROW(nrange(0, 10, 0), std::domain_error);
432}
433
448
450{
451 size_t count = 0;
452 each(0, [&count] () { ++count; });
453 EXPECT_EQ(count, 0);
454
455 count = 0;
456 each(1, [&count] () { ++count; });
457 EXPECT_EQ(count, 1);
458}
459
460// Tests for new functions
461
463{
464 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
465 EXPECT_TRUE(none(l, [] (int x) { return x > 10; }));
466 EXPECT_FALSE(none(l, [] (int x) { return x == 3; }));
467
468 DynList<int> empty;
469 EXPECT_TRUE(none(empty, [] (int) { return true; }));
470}
471
473{
474 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
475
476 auto * p = find_ptr(l, [] (int x) { return x == 3; });
477 ASSERT_NE(p, nullptr);
478 EXPECT_EQ(*p, 3);
479
480 // Modify through pointer
481 *p = 30;
482 EXPECT_EQ(l.nth(2), 30);
483
484 auto * not_found = find_ptr(l, [] (int x) { return x == 100; });
485 EXPECT_EQ(not_found, nullptr);
486
487 // const version
488 const DynList<int> cl = build_dynlist<int>(10, 20, 30);
489 const int * cp = find_ptr(cl, [] (int x) { return x == 20; });
490 ASSERT_NE(cp, nullptr);
491 EXPECT_EQ(*cp, 20);
492}
493
495{
496 DynList<int> l = build_dynlist<int>(1, 2, 3, 4);
497
498 // foldr with subtraction: 1 - (2 - (3 - (4 - 0))) = 1 - (2 - (3 - 4)) = 1 - (2 - (-1)) = 1 - 3 = -2
499 auto result = foldr<int>(l, 0, [] (int a, int b) { return a - b; });
500 EXPECT_EQ(result, -2);
501
502 // Compare with foldl: ((((0 - 1) - 2) - 3) - 4) = -10
503 auto result_l = foldl<int>(l, 0, [] (int a, int b) { return a - b; });
504 EXPECT_EQ(result_l, -10);
505}
506
508{
509 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
510 EXPECT_EQ(sum(l), 15);
511 EXPECT_EQ(sum(l, 10), 25);
512
513 EXPECT_EQ(product(l), 120);
514 EXPECT_EQ(product(l, 2), 240);
515
516 DynList<int> empty;
517 EXPECT_EQ(sum(empty), 0);
518 EXPECT_EQ(product(empty), 1);
519
520 DynList<double> ld = build_dynlist<double>(1.5, 2.5, 3.0);
521 EXPECT_DOUBLE_EQ(sum(ld), 7.0);
522}
523
525{
526 DynList<int> l1 = build_dynlist<int>(1, 2, 3);
527 DynList<int> l2 = build_dynlist<int>(4, 5, 6);
528
529 auto c = concat(l1, l2);
530 EXPECT_EQ(c, build_dynlist<int>(1, 2, 3, 4, 5, 6));
531
532 DynList<int> empty;
533 EXPECT_EQ(concat(empty, l1), l1);
534 EXPECT_EQ(concat(l1, empty), l1);
535}
536
538{
539 DynList<int> l = build_dynlist<int>(1, 2, 3, 10, 5, 6);
540
541 auto result = take_while(l, [] (int x) { return x < 5; });
542 EXPECT_EQ(result, build_dynlist<int>(1, 2, 3));
543
544 // All elements satisfy
545 auto all = take_while(l, [] (int) { return true; });
546 EXPECT_EQ(all, l);
547
548 // No elements satisfy
549 auto none_result = take_while(l, [] (int x) { return x > 100; });
551}
552
554{
555 DynList<int> l = build_dynlist<int>(1, 2, 3, 10, 5, 6);
556
557 auto result = drop_while(l, [] (int x) { return x < 5; });
558 EXPECT_EQ(result, build_dynlist<int>(10, 5, 6));
559
560 // All elements satisfy - drop all
561 auto all_dropped = drop_while(l, [] (int) { return true; });
563
564 // No elements satisfy - keep all
565 auto none_dropped = drop_while(l, [] (int x) { return x > 100; });
567}
568
570{
572
573 // Duplicate each element
574 auto result = flat_map(l, [] (int x) {
575 return build_dynlist<int>(x, x);
576 });
577 EXPECT_EQ(result, build_dynlist<int>(1, 1, 2, 2, 3, 3));
578
579 // Create range for each
580 auto ranges = flat_map(l, [] (int x) {
581 return range(x);
582 });
583 EXPECT_EQ(ranges, build_dynlist<int>(0, 0, 1, 0, 1, 2));
584}
585
587{
588 DynList<int> l = build_dynlist<int>(1, 2, 3, 4);
589
590 auto sums = scanl<int>(l, 0, [] (int a, int b) { return a + b; });
591 EXPECT_EQ(sums, build_dynlist<int>(0, 1, 3, 6, 10));
592
593 auto sums2 = scanl_sum(l, 0);
594 EXPECT_EQ(sums2, build_dynlist<int>(0, 1, 3, 6, 10));
595
596 DynList<int> empty;
597 auto empty_scan = scanl<int>(empty, 100, [] (int a, int b) { return a + b; });
599}
600
602{
603 DynList<int> l = build_dynlist<int>(5, 2, 8, 1, 9, 3);
604
605 auto * min_p = min_ptr(l);
606 ASSERT_NE(min_p, nullptr);
607 EXPECT_EQ(*min_p, 1);
608
609 auto * max_p = max_ptr(l);
610 ASSERT_NE(max_p, nullptr);
611 EXPECT_EQ(*max_p, 9);
612
613 auto [minp, maxp] = minmax_ptr(l);
614 ASSERT_NE(minp, nullptr);
615 ASSERT_NE(maxp, nullptr);
616 EXPECT_EQ(*minp, 1);
617 EXPECT_EQ(*maxp, 9);
618
619 // Empty container
620 DynList<int> empty;
621 EXPECT_EQ(min_ptr(empty), nullptr);
622 EXPECT_EQ(max_ptr(empty), nullptr);
623 auto [emp_min, emp_max] = minmax_ptr(empty);
624 EXPECT_EQ(emp_min, nullptr);
625 EXPECT_EQ(emp_max, nullptr);
626
627 // Single element
629 auto [s_min, s_max] = minmax_ptr(single);
630 EXPECT_EQ(*s_min, 42);
631 EXPECT_EQ(*s_max, 42);
632
633 // Custom comparator
634 DynList<int> abs_list = build_dynlist<int>(-10, 5, -20, 3);
635 auto * max_abs = max_ptr(abs_list,
636 [] (const int a, const int b) { return std::abs(a) < std::abs(b); });
637 EXPECT_EQ(*max_abs, -20);
638}
639
641{
642 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
643
644 EXPECT_EQ(count_if(l, [] (int x) { return x % 2 == 0; }), 5);
645 EXPECT_EQ(count_if(l, [] (int x) { return x > 5; }), 5);
646 EXPECT_EQ(count_if(l, [] (int x) { return x > 100; }), 0);
647
648 DynList<int> empty;
649 EXPECT_EQ(count_if(empty, [] (int) { return true; }), 0);
650}
651
653{
654 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
655
661
662 DynList<int> empty;
663 EXPECT_FALSE(contains(empty, 1));
664}
665
667{
668 DynList<string> l = build_dynlist<string>("a", "b", "c");
669
670 auto result = enumerate_tuple(l);
671 EXPECT_EQ(result.size(), 3);
672
673 auto it = result.get_it();
674 EXPECT_EQ(get<0>(it.get_curr()), 0);
675 EXPECT_EQ(get<1>(it.get_curr()), "a");
676 it.next();
677 EXPECT_EQ(get<0>(it.get_curr()), 1);
678 EXPECT_EQ(get<1>(it.get_curr()), "b");
679 it.next();
680 EXPECT_EQ(get<0>(it.get_curr()), 2);
681 EXPECT_EQ(get<1>(it.get_curr()), "c");
682}
683
684// =============================================================================
685// COMPREHENSIVE TESTS FOR ahFunctional.H
686// =============================================================================
687
688// --- zip_longest tests ---
689
691{
692 DynList<int> l1 = build_dynlist<int>(1, 2, 3, 4, 5);
693 DynList<int> l2 = build_dynlist<int>(10, 20, 30);
694
695 auto result = zip_longest(l1, l2, -1, -1);
696 EXPECT_EQ(result.size(), 5);
697
698 auto it = result.get_it();
699 EXPECT_EQ(it.get_curr(), make_pair(1, 10)); it.next();
700 EXPECT_EQ(it.get_curr(), make_pair(2, 20)); it.next();
701 EXPECT_EQ(it.get_curr(), make_pair(3, 30)); it.next();
702 EXPECT_EQ(it.get_curr(), make_pair(4, -1)); it.next();
703 EXPECT_EQ(it.get_curr(), make_pair(5, -1));
704}
705
707{
709 DynList<int> l2 = build_dynlist<int>(10, 20, 30, 40);
710
711 auto result = zip_longest(l1, l2, 0, 0);
712 EXPECT_EQ(result.size(), 4);
713
714 auto it = result.get_it();
715 EXPECT_EQ(it.get_curr(), make_pair(1, 10)); it.next();
716 EXPECT_EQ(it.get_curr(), make_pair(2, 20)); it.next();
717 EXPECT_EQ(it.get_curr(), make_pair(0, 30)); it.next();
718 EXPECT_EQ(it.get_curr(), make_pair(0, 40));
719}
720
722{
723 DynList<int> l1 = build_dynlist<int>(1, 2, 3);
724 DynList<int> l2 = build_dynlist<int>(4, 5, 6);
725
726 auto result = zip_longest(l1, l2, -1, -1);
727 EXPECT_EQ(result.size(), 3);
728
729 EXPECT_TRUE(result.all([] (auto & p) {
730 return p.first + 3 == p.second;
731 }));
732}
733
735{
738
739 auto r1 = zip_longest(empty1, empty2, 0, 0);
741
742 auto r2 = zip_longest(l, empty2, 0, -1);
743 EXPECT_EQ(r2.size(), 3);
744 EXPECT_TRUE(r2.all([] (auto & p) { return p.second == -1; }));
745
746 auto r3 = zip_longest(empty1, l, -1, 0);
747 EXPECT_EQ(r3.size(), 3);
748 EXPECT_TRUE(r3.all([] (auto & p) { return p.first == -1; }));
749}
750
751// --- tzip_longest tests ---
752
754{
755 DynList<int> l1 = build_dynlist<int>(1, 2, 3);
757
758 auto result = tzip_longest(l1, l2, 0, string("X"));
759 EXPECT_EQ(result.size(), 3);
760
761 auto it = result.get_it();
762 EXPECT_EQ(get<0>(it.get_curr()), 1);
763 EXPECT_EQ(get<1>(it.get_curr()), "a");
764 it.next();
765 EXPECT_EQ(get<0>(it.get_curr()), 2);
766 EXPECT_EQ(get<1>(it.get_curr()), "b");
767 it.next();
768 EXPECT_EQ(get<0>(it.get_curr()), 3);
769 EXPECT_EQ(get<1>(it.get_curr()), "X");
770}
771
772// --- zip_longest_opt tests ---
773
775{
776 DynList<int> l1 = build_dynlist<int>(1, 2, 3, 4);
777 DynList<int> l2 = build_dynlist<int>(10, 20);
778
779 auto result = zip_longest_opt(l1, l2);
780 EXPECT_EQ(result.size(), 4);
781
782 auto it = result.get_it();
783 auto p1 = it.get_curr();
784 EXPECT_TRUE(p1.first.has_value());
785 EXPECT_TRUE(p1.second.has_value());
786 EXPECT_EQ(p1.first.value(), 1);
787 EXPECT_EQ(p1.second.value(), 10);
788
789 it.next(); it.next(); it.next();
790 auto p4 = it.get_curr();
791 EXPECT_TRUE(p4.first.has_value());
792 EXPECT_FALSE(p4.second.has_value());
793 EXPECT_EQ(p4.first.value(), 4);
794}
795
796// --- group_by tests ---
797
799{
800 DynList<int> l = build_dynlist<int>(1, 1, 2, 2, 2, 3, 1, 1);
801
802 // group_by takes a key function that extracts the grouping key
803 auto result = group_by(l, [] (int x) { return x; });
804 EXPECT_EQ(result.size(), 4);
805
806 auto it = result.get_it();
807 // Each element is pair<key, DynList<T>>
808 EXPECT_EQ(it.get_curr().first, 1);
809 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(1, 1));
810 it.next();
811 EXPECT_EQ(it.get_curr().first, 2);
812 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(2, 2, 2));
813 it.next();
814 EXPECT_EQ(it.get_curr().first, 3);
815 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(3));
816 it.next();
817 EXPECT_EQ(it.get_curr().first, 1);
818 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(1, 1));
819}
820
822{
823 DynList<int> l = build_dynlist<int>(1, 3, 5, 2, 4, 6, 7, 9);
824
825 // Group by parity (consecutive groups with same parity)
826 auto result = group_by(l, [] (int x) { return x % 2; });
827 EXPECT_EQ(result.size(), 3);
828
829 auto it = result.get_it();
830 EXPECT_EQ(it.get_curr().first, 1); // odd
831 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(1, 3, 5));
832 it.next();
833 EXPECT_EQ(it.get_curr().first, 0); // even
834 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(2, 4, 6));
835 it.next();
836 EXPECT_EQ(it.get_curr().first, 1); // odd again
837 EXPECT_EQ(it.get_curr().second, build_dynlist<int>(7, 9));
838}
839
841{
842 DynList<int> empty;
843 auto result = group_by(empty, [] (int x) { return x; });
844 EXPECT_TRUE(result.is_empty());
845}
846
848{
850 auto result = group_by(single, [] (int x) { return x; });
851 EXPECT_EQ(result.size(), 1);
852 EXPECT_EQ(result.get_first().first, 42);
853 EXPECT_EQ(result.get_first().second, build_dynlist<int>(42));
854}
855
856// --- group_by_reduce tests ---
857
859{
860 DynList<int> l = build_dynlist<int>(1, 1, 2, 2, 2, 3);
861
862 auto result = group_by_reduce(l,
863 [] (int x) { return x; }, // key function
864 [] (const DynList<int> & g) { return sum(g); } // reducer (takes group)
865 );
866
867 // Result should be list of (key, reduced_value) pairs
868 EXPECT_EQ(result.size(), 3);
869
870 auto it = result.get_it();
871 // First group: key=1, sum=1+1=2
872 EXPECT_EQ(it.get_curr().first, 1);
873 EXPECT_EQ(it.get_curr().second, 2);
874 it.next();
875 // Second group: key=2, sum=2+2+2=6
876 EXPECT_EQ(it.get_curr().first, 2);
877 EXPECT_EQ(it.get_curr().second, 6);
878 it.next();
879 // Third group: key=3, sum=3
880 EXPECT_EQ(it.get_curr().first, 3);
881 EXPECT_EQ(it.get_curr().second, 3);
882}
883
884// --- maps and maps_if tests ---
885
887{
888 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
889
890 auto result = maps<int>(l, [] (int x) { return x * x; });
891 EXPECT_EQ(result, build_dynlist<int>(1, 4, 9, 16, 25));
892}
893
895{
897
898 auto result = maps<string>(l, [] (int x) { return to_string(x); });
899 EXPECT_EQ(result, build_dynlist<string>("1", "2", "3"));
900}
901
903{
904 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5, 6);
905
906 // Filter then map: square only even numbers
907 auto filtered = filter(l, [] (int x) { return x % 2 == 0; });
908 auto result = maps<int>(filtered, [] (int x) { return x * x; });
909
910 EXPECT_EQ(result, build_dynlist<int>(4, 16, 36));
911}
912
914{
915 DynList<int> l = build_dynlist<int>(1, 3, 5, 7);
916
917 auto filtered = filter(l, [] (int x) { return x % 2 == 0; });
918 auto result = maps<int>(filtered, [] (int x) { return x * 2; });
919
920 EXPECT_TRUE(result.is_empty());
921}
922
923// --- split tests using DynList split method ---
924
926{
927 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5, 6);
928
929 // Use take and drop to simulate split at position 3
930 auto left = l.take(3);
931 auto right = l.drop(3);
932
933 EXPECT_EQ(left, build_dynlist<int>(1, 2, 3));
934 EXPECT_EQ(right, build_dynlist<int>(4, 5, 6));
935}
936
937// --- take and drop comprehensive tests ---
938
940{
941 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
942
943 EXPECT_EQ(l.take(3), build_dynlist<int>(1, 2, 3));
945 EXPECT_EQ(l.take(10), l);
946}
947
949{
950 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
951
952 EXPECT_EQ(l.drop(2), build_dynlist<int>(3, 4, 5));
953 EXPECT_EQ(l.drop(0), l);
955}
956
958{
959 DynList<int> l = build_dynlist<int>(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
960
961 // Take elements from position 3 to 7
962 auto result = l.take(3, 7);
963 EXPECT_EQ(result, build_dynlist<int>(3, 4, 5, 6, 7));
964}
965
966// --- to_dynlist tests ---
967
969{
970 DynSetTree<int> tree;
971 for (int i = 0; i < 5; ++i)
972 tree.insert(i);
973
974 auto list = to_dynlist(tree);
975 EXPECT_EQ(list.size(), 5);
976 EXPECT_EQ(list, build_dynlist<int>(0, 1, 2, 3, 4));
977}
978
980{
981 DynArray<int> arr;
982 for (int i = 0; i < 5; ++i)
983 arr.append(i * 2);
984
985 auto list = to_dynlist(arr);
986 EXPECT_EQ(list.size(), 5);
987 EXPECT_EQ(list, build_dynlist<int>(0, 2, 4, 6, 8));
988}
989
990// --- traverse with filter test ---
991
993{
994 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
995
996 size_t count = 0;
997 l.traverse([&count] (int x) {
998 if (x % 2 == 0) ++count;
999 return true;
1000 });
1001
1002 EXPECT_EQ(count, 5);
1003}
1004
1005// --- Edge cases and stress tests ---
1006
1008{
1009 constexpr size_t N = 10000;
1011
1012 // Test foldl on large container
1013 auto sum = foldl<size_t>(l, 0, [] (size_t a, size_t b) { return a + b; });
1014 EXPECT_EQ(sum, N * (N - 1) / 2);
1015
1016 // Test filter on large container
1017 auto evens = filter(l, [] (size_t x) { return x % 2 == 0; });
1018 EXPECT_EQ(evens.size(), N / 2);
1019
1020 // Test maps on large container
1021 auto doubled = maps<size_t>(l, [] (size_t x) { return x * 2; });
1022 EXPECT_EQ(doubled.size(), N);
1024 EXPECT_EQ(doubled.get_last(), (N - 1) * 2);
1025}
1026
1028{
1029 DynList<int> l = range(100);
1030
1031 // Chain: filter even -> map square -> take first 5 -> sum
1032 auto result = filter(l, [] (int x) { return x % 2 == 0; }); // 50 evens
1033 auto squared = maps<int>(result, [] (int x) { return x * x; });
1034 auto first5 = squared.take(5); // 0, 4, 16, 36, 64
1035 auto total = sum(first5);
1036
1037 EXPECT_EQ(total, 0 + 4 + 16 + 36 + 64);
1038}
1039
1041{
1042 DynList<int> empty;
1043
1044 // All these should handle empty containers gracefully
1045 EXPECT_TRUE(filter(empty, [] (int) { return true; }).is_empty());
1046 EXPECT_TRUE(maps<int>(empty, [] (int x) { return x; }).is_empty());
1047 EXPECT_EQ(foldl<int>(empty, 42, [] (int a, int b) { return a + b; }), 42);
1048 EXPECT_TRUE(all(empty, [] (int) { return false; })); // vacuously true
1049 EXPECT_FALSE(exists(empty, [] (int) { return true; }));
1050 EXPECT_TRUE(none(empty, [] (int) { return true; }));
1051 EXPECT_EQ(sum(empty), 0);
1052 EXPECT_EQ(product(empty), 1);
1053 EXPECT_TRUE(reverse(empty).is_empty());
1054}
1055
1057{
1059
1060 EXPECT_EQ(filter(single, [] (int x) { return x > 0; }).size(), 1);
1061 EXPECT_EQ(maps<int>(single, [] (int x) { return x * 2; }).get_first(), 84);
1062 EXPECT_EQ(sum(single), 42);
1063 EXPECT_EQ(product(single), 42);
1064 EXPECT_EQ(reverse(single).get_first(), 42);
1065 EXPECT_EQ(*min_ptr(single), 42);
1066 EXPECT_EQ(*max_ptr(single), 42);
1067}
1068
1069// --- Complex type tests ---
1070
1071struct Person
1072{
1073 string name;
1074 int age;
1075
1076 bool operator==(const Person & other) const
1077 {
1078 return name == other.name && age == other.age;
1079 }
1080};
1081
1083{
1085 people.append({"Alice", 30});
1086 people.append({"Bob", 25});
1087 people.append({"Charlie", 35});
1088 people.append({"Diana", 28});
1089
1090 // Filter by age
1091 auto over28 = filter(people, [] (const Person & p) { return p.age > 28; });
1092 EXPECT_EQ(over28.size(), 2);
1093
1094 // Map to names
1095 auto names = maps<string>(people, [] (const Person & p) { return p.name; });
1096 EXPECT_EQ(names, build_dynlist<string>("Alice", "Bob", "Charlie", "Diana"));
1097
1098 // Find oldest
1099 auto * oldest = max_ptr(people, [] (const Person & a, const Person & b) {
1100 return a.age < b.age;
1101 });
1102 ASSERT_NE(oldest, nullptr);
1103 EXPECT_EQ(oldest->name, "Charlie");
1104
1105 // Sum of ages
1106 auto total_age = foldl<int>(people, 0, [] (int acc, const Person & p) {
1107 return acc + p.age;
1108 });
1109 EXPECT_EQ(total_age, 30 + 25 + 35 + 28);
1110}
1111
1112// --- Lazy evaluation / composition tests ---
1113
1115{
1117
1118 // map twice
1119 auto result = maps<int>(maps<int>(l, [] (int x) { return x + 1; }),
1120 [] (int x) { return x * x; });
1121 EXPECT_EQ(result, build_dynlist<int>(4, 9, 16)); // (1+1)^2, (2+1)^2, (3+1)^2
1122}
1123
1125{
1126 DynList<int> l = range(10);
1127
1128 auto result = maps<string>(
1129 filter(l, [] (int x) { return x % 3 == 0; }),
1130 [] (int x) { return "val" + to_string(x); }
1131 );
1132
1133 EXPECT_EQ(result, build_dynlist<string>("val0", "val3", "val6", "val9"));
1134}
1135
1136// --- Quantifier tests ---
1137
1139{
1140 DynList<int> l = build_dynlist<int>(2, 4, 6, 8, 10);
1141
1142 EXPECT_TRUE(all(l, [] (int x) { return x % 2 == 0; })); // all even
1143 EXPECT_TRUE(all(l, [] (int x) { return x > 0; })); // all positive
1144 EXPECT_FALSE(all(l, [] (int x) { return x > 5; })); // not all > 5
1145
1146 // Empty container - vacuously true
1147 DynList<int> empty;
1148 EXPECT_TRUE(all(empty, [] (int) { return false; }));
1149}
1150
1152{
1153 DynList<int> l = build_dynlist<int>(1, 3, 5, 6, 7);
1154
1155 EXPECT_TRUE(exists(l, [] (int x) { return x % 2 == 0; })); // 6 is even
1156 EXPECT_TRUE(exists(l, [] (int x) { return x == 7; })); // 7 exists
1157 EXPECT_FALSE(exists(l, [] (int x) { return x > 100; })); // none > 100
1158
1159 // Empty container - false
1160 DynList<int> empty;
1161 EXPECT_FALSE(exists(empty, [] (int) { return true; }));
1162}
1163
1165{
1166 DynList<int> l = build_dynlist<int>(1, 3, 5, 7, 9);
1167
1168 EXPECT_TRUE(none(l, [] (int x) { return x % 2 == 0; })); // no even
1169 EXPECT_TRUE(none(l, [] (int x) { return x > 100; })); // none > 100
1170 EXPECT_FALSE(none(l, [] (int x) { return x == 5; })); // 5 exists
1171
1172 // Empty container - vacuously true
1173 DynList<int> empty;
1174 EXPECT_TRUE(none(empty, [] (int) { return true; }));
1175}
1176
1177// =============================================================================
1178// Additional comprehensive tests
1179// =============================================================================
1180
1181// --- scanl comprehensive tests ---
1182
1184{
1185 DynList<int> l = build_dynlist<int>(1, 2, 3, 4, 5);
1186
1187 // Basic scanl_sum starting from 0
1188 auto sums = scanl_sum(l, 0);
1189 EXPECT_EQ(sums, build_dynlist<int>(0, 1, 3, 6, 10, 15));
1190
1191 // scanl_sum with non-zero init
1192 auto sums2 = scanl_sum(l, 100);
1193 EXPECT_EQ(sums2, build_dynlist<int>(100, 101, 103, 106, 110, 115));
1194
1195 // Empty container
1196 DynList<int> empty;
1197 auto empty_scan = scanl_sum(empty, 42);
1200}
1201
1203{
1205
1206 // Product scan
1207 auto products = scanl<int>(l, 1, [] (int acc, int x) { return acc * x; });
1208 EXPECT_EQ(products, build_dynlist<int>(1, 2, 6, 24));
1209
1210 // Max scan
1211 auto maxes = scanl<int>(l, 0, [] (int acc, int x) { return std::max(acc, x); });
1212 EXPECT_EQ(maxes, build_dynlist<int>(0, 2, 3, 4));
1213}
1214
1215// --- flat_map comprehensive tests ---
1216
1218{
1220
1221 // Expand each number to a range
1222 auto result = flat_map(l, [] (int x) {
1223 return range(x); // 0..x-1
1224 });
1225 // 1 -> {0}, 2 -> {0,1}, 3 -> {0,1,2}
1226 EXPECT_EQ(result, build_dynlist<int>(0, 0, 1, 0, 1, 2));
1227}
1228
1230{
1232
1233 // Replicate each element by its value
1234 auto result = flat_map(l, [] (int x) -> DynList<int> {
1236 for (int i = 0; i < x; ++i)
1237 res.append(x);
1238 return res;
1239 });
1240 EXPECT_EQ(result, build_dynlist<int>(1, 2, 2, 3, 3, 3));
1241}
1242
1244{
1246
1247 // Some inner results are empty
1248 auto result = flat_map(l, [] (int x) {
1249 if (x % 2 == 0)
1250 return DynList<int>();
1251 return build_dynlist<int>(x);
1252 });
1253 EXPECT_EQ(result, build_dynlist<int>(1, 3));
1254}
1255
1256// --- concat comprehensive tests ---
1257
1259{
1261 DynList<int> b = build_dynlist<int>(3, 4, 5);
1262 DynList<int> empty;
1263
1264 EXPECT_EQ(concat(a, b), build_dynlist<int>(1, 2, 3, 4, 5));
1265 EXPECT_EQ(concat(empty, b), build_dynlist<int>(3, 4, 5));
1266 EXPECT_EQ(concat(a, empty), build_dynlist<int>(1, 2));
1267 EXPECT_EQ(concat(empty, empty), DynList<int>());
1268}
1269
1270// --- take_while / drop_while comprehensive tests ---
1271
1273{
1274 DynList<int> l = build_dynlist<int>(2, 4, 6, 7, 8, 10);
1275
1276 // Take while even
1277 auto evens = take_while(l, [] (int x) { return x % 2 == 0; });
1279
1280 // Take while < 5
1281 auto small = take_while(l, [] (int x) { return x < 5; });
1283
1284 // Take nothing (first element fails)
1285 auto none_taken = take_while(l, [] (int x) { return x > 100; });
1287
1288 // Take all
1289 auto all_taken = take_while(l, [] (int) { return true; });
1291}
1292
1294{
1295 DynList<int> l = build_dynlist<int>(2, 4, 6, 7, 8, 10);
1296
1297 // Drop while even
1298 auto after_evens = drop_while(l, [] (int x) { return x % 2 == 0; });
1300
1301 // Drop while < 5
1302 auto after_small = drop_while(l, [] (int x) { return x < 5; });
1304
1305 // Drop nothing (first element fails)
1306 auto none_dropped = drop_while(l, [] (int x) { return x > 100; });
1308
1309 // Drop all
1310 auto all_dropped = drop_while(l, [] (int) { return true; });
1312}
1313
1314// --- reverse comprehensive tests ---
1315
1317{
1321
1322 DynList<int> empty;
1323 EXPECT_TRUE(reverse(empty).is_empty());
1324
1325 // Reverse twice = original
1326 DynList<int> l = range(10);
1328}
1329
1330// --- min/max pointer comprehensive tests ---
1331
1333{
1335 names.append("Bob");
1336 names.append("Alice");
1337 names.append("Charlie");
1338
1339 // By length
1340 auto * shortest = min_ptr(names, [] (const string & a, const string & b) {
1341 return a.length() < b.length();
1342 });
1343 ASSERT_NE(shortest, nullptr);
1344 EXPECT_EQ(*shortest, "Bob");
1345
1346 auto * longest = max_ptr(names, [] (const string & a, const string & b) {
1347 return a.length() < b.length();
1348 });
1349 ASSERT_NE(longest, nullptr);
1350 EXPECT_EQ(*longest, "Charlie");
1351}
1352
1354{
1355 DynList<int> l = build_dynlist<int>(3, 1, 4, 1, 5, 9, 2, 6);
1356
1357 auto [min_p, max_p] = minmax_ptr(l);
1358 ASSERT_NE(min_p, nullptr);
1359 ASSERT_NE(max_p, nullptr);
1360 EXPECT_EQ(*min_p, 1);
1361 EXPECT_EQ(*max_p, 9);
1362}
1363
1364// --- foldl/foldr comprehensive tests ---
1365
1367{
1368 DynList<string> words;
1369 words.append("a");
1370 words.append("b");
1371 words.append("c");
1372
1373 // foldl is left-associative: ((init op a) op b) op c
1374 auto result = foldl<string>(words, "START", [] (const string & acc, const string & x) {
1375 return "(" + acc + "+" + x + ")";
1376 });
1377 EXPECT_EQ(result, "(((START+a)+b)+c)");
1378}
1379
1381{
1382 DynList<string> words;
1383 words.append("a");
1384 words.append("b");
1385 words.append("c");
1386
1387 // foldr is right-associative: a op (b op (c op init))
1388 auto result = foldr<string>(words, "END", [] (const string & x, const string & acc) {
1389 return "(" + x + "+" + acc + ")";
1390 });
1391 EXPECT_EQ(result, "(a+(b+(c+END)))");
1392}
1393
1394// --- zip comprehensive tests ---
1395
1397{
1398 DynList<int> a = build_dynlist<int>(1, 2, 3, 4, 5);
1399 DynList<char> b;
1400 b.append('a');
1401 b.append('b');
1402
1403 // Regular zip stops at shorter
1404 auto zipped = zip(a, b);
1405 EXPECT_EQ(zipped.size(), 2);
1406}
1407
1409{
1410 DynList<int> a = build_dynlist<int>(1, 2, 3);
1411 DynList<int> b = build_dynlist<int>(2, 4, 6);
1412
1413 // Check if b[i] == 2*a[i] for all i
1414 bool all_double = zip_all([] (auto t) { return get<1>(t) == 2 * get<0>(t); }, a, b);
1416
1417 DynList<int> c = build_dynlist<int>(2, 4, 5); // 5 != 2*3
1418 bool not_all = zip_all([] (auto t) { return get<1>(t) == 2 * get<0>(t); }, a, c);
1420}
1421
1422// --- group_by comprehensive tests ---
1423
1425{
1426 DynList<int> l = build_dynlist<int>(1, 3, 5, 2, 4, 6, 7, 9);
1427
1428 // Group by parity (odd=1, even=0)
1429 auto groups = group_by(l, [] (int x) { return x % 2; });
1430
1431 EXPECT_EQ(groups.size(), 3); // odd, even, odd groups
1432
1433 auto it = groups.get_it();
1434 EXPECT_EQ(it.get_curr().first, 1); // odd
1435 EXPECT_EQ(it.get_curr().second.size(), 3); // 1, 3, 5
1436 it.next();
1437 EXPECT_EQ(it.get_curr().first, 0); // even
1438 EXPECT_EQ(it.get_curr().second.size(), 3); // 2, 4, 6
1439 it.next();
1440 EXPECT_EQ(it.get_curr().first, 1); // odd
1441 EXPECT_EQ(it.get_curr().second.size(), 2); // 7, 9
1442}
1443
1444// --- Performance / stress tests ---
1445
1447{
1448 constexpr size_t N = 10000;
1449 auto large = range<int>(0, static_cast<int>(N) - 1);
1450
1451 // Chain: filter -> map -> sum (first 100 evens)
1452 auto evens = filter(large, [] (int x) { return x % 2 == 0; });
1453 auto squared = maps<int>(evens, [] (int x) { return x * x; });
1454
1455 // Take first 100 elements manually
1457 size_t count = 0;
1458 for (auto it = squared.get_it(); it.has_curr() && count < 100; it.next_ne(), ++count)
1459 first100.append(it.get_curr());
1460
1461 // Sum of squares of first 100 even numbers: 0^2 + 2^2 + 4^2 + ... + 198^2
1462 long long expected = 0;
1463 for (int i = 0; i < 100; ++i)
1464 expected += (2LL * i) * (2LL * i);
1465
1466 auto total = foldl<long long>(first100, 0LL, [] (long long acc, int x) {
1467 return acc + x;
1468 });
1470}
1471
1473{
1474 // Deeply nested maps
1475 auto l = range(5);
1476 auto result = maps<int>(
1477 maps<int>(
1478 maps<int>(l, [] (int x) { return x + 1; }),
1479 [] (int x) { return x * 2; }),
1480 [] (int x) { return x - 1; });
1481
1482 // ((x + 1) * 2) - 1 for x in 0..4
1483 EXPECT_EQ(result, build_dynlist<int>(1, 3, 5, 7, 9));
1484}
1485
TEST_F(TreeContainer, pointers)
String manipulation utilities.
Zip iterators and functional operations for multiple containers.
Functional programming utilities for Aleph-w containers.
T & append()
Allocate a new entry to the end of array.
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
T & get_last() const
Return the last item of the list.
Definition htlist.H:1663
T & get_first() const
Return the first item of the list.
Definition htlist.H:1675
Dynamic set backed by balanced binary search trees with automatic memory management.
const size_t & size() const
Returns the cardinality of the set.
Key * insert(const Key &key)
Inserts a key into the dynamic set.
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Aleph::DynList< T > take(const size_t n) const
Return a list with the first n elements seen in the container during its traversal.
Definition ah-dry.H:1418
bool all(Operation &operation) const
Check if all the elements of container satisfy a condition.
Definition ah-dry.H:816
size_t length() const noexcept
Count the number of elements of a container.
Definition ah-dry.H:1385
Aleph::DynList< T > drop(const size_t n) const
Drop the first n elements seen in the container during its traversal.
Definition ah-dry.H:1467
Type & nth(const size_t n)
Return the n-th item of container.
Definition ah-dry.H:267
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:190
#define TEST(name)
#define N
Definition fib.C:294
MapOLhash< int, Foo > tbl
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::pair< DynList< T >, size_t > unique_sequential(const Container< T > &c, Equal &eq)
Extract unique consecutive items.
std::tuple< bool, size_t, typename C1::Item_Type, typename C2::Item_Type > are_eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Detailed equality check returning mismatch position and values.
bool zip_all(Op &&op, const Cs &... cs)
Return true if op returns true for all tuples and containers have equal length.
Definition ah-zip.H:429
DynList< T > flatten(const C2< C1< T > > &c)
Flatten a nested container of one level.
DynList< typename Container::Item_Type > to_dynlist(const Container &c)
Definition htlist.H:1988
Container< T > nrange(const T start, const T end, const size_t n)
Generate exactly n values evenly spaced between [start, end].
auto group_by_reduce(const Container< T > &c, KeyFunc key_func, Reducer reducer) -> DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, std::invoke_result_t< Reducer, const DynList< T > & > > >
Group consecutive elements and apply a reducer to each group.
std::pair< const typename Container::Item_Type *, const typename Container::Item_Type * > minmax_ptr(const Container &container, Cmp cmp=Cmp())
Find both min and max elements in a single pass.
const Container::Item_Type * min_ptr(const Container &container, Cmp cmp=Cmp())
Find the minimum element in a container.
DynList< std::pair< std::optional< typename Container1::Item_Type >, std::optional< typename Container2::Item_Type > > > zip_longest_opt(const Container1 &a, const Container2 &b)
Zip two containers using optionals for missing values.
auto unzip(const Container &l)
Separate a list of pairs into two lists.
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
void reverse(Itor beg, Itor end)
Reverse elements in a range.
Definition ahAlgo.H:1094
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
DynList< typename Container::Item_Type > drop_while(const Container &c, Pred pred)
Skip elements while predicate is true (drop_while).
auto set_range(const T start, const T end, const T step, Op &op) -> Container< std::decay_t< decltype(op(start))> >
Generate a range [start, end] and apply an operation to each value.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zipEq(const Container1 &a, const Container2 &b)
Zip two containers; throw if lengths differ.
size_t size(Node *root) noexcept
std::pair< TgtContainer< typename SrcContainer::Item_Type >, TgtContainer< typename SrcContainer::Item_Type > > partition(const SrcContainer &c, std::function< bool(const typename SrcContainer::Item_Type &)> operation)
Partition a container into two based on a predicate.
bool containers_eq(const C1 &c1, const C2 &c2, Eq e)
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
bool is_inside(const T &val, const DynList< T > &values)
Check if a value is present in a list.
DynList< typename Container::Item_Type > take_while(const Container &c, Pred pred)
Return elements while predicate is true (take_while).
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip(const Container1 &a, const Container2 &b)
Zip two containers into a list of pairs.
Pair_Iterator< typename C1::Iterator, typename C2::Iterator > get_pair_it(const C1 &c1, const C2 &c2)
Create a Pair_Iterator for two containers.
auto enumerate(const Container &c)
Return pairs of (element, index).
size_t append_in_container(C &c, Args ... args)
Append multiple items into a container.
bool is_equal(const T &val)
Variadic check for equality against multiple values.
bool exists(Container &container, Operation &operation)
Return true if at least one element satisfies a predicate.
auto gen_seq_list_tuples(const Container &c, size_t n)
Generate all sequential tuples (sliding windows) of size n.
bool contains(const std::string_view &str, const std::string_view &substr)
Check if substr appears inside str.
DynList< T > build_dynlist(Args ... args)
Build a DynList with the given items.
auto flat_map(const Container &container, Op op) -> DynList< typename std::decay_t< decltype(op(std::declval< typename Container::Item_Type >()))>::Item_Type >
Apply operation and flatten results (flatMap/concatMap).
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzip(const Container1 &a, const Container2 &b)
Zip two containers into a list of tuples.
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
DynList< typename Container::Item_Type * > pointers_list(Container &c)
Create a list of pointers to items in a container.
DynList< std::pair< size_t, typename Container::Key_Type > > indexes(const Container &c)
Return pairs of (index, key).
DynList< typename Container::Item_Type > sublist(const Container &c, size_t pos, size_t stride)
Extract a sublist using a stride.
bool lesser(const C1 &c1, const C2 &c2, Cmp cmp=Cmp())
Lexicographical comparison between two containers.
TgtC assign_container(const SrcC &srcc)
Convert one container type to another.
DynList< std::tuple< size_t, typename Container::Item_Type > > enumerate_tuple(const Container &container)
Zip containers with an index (enumerate with zip).
const Container::Item_Type * max_ptr(const Container &container, Cmp cmp=Cmp())
Find the maximum element in a container.
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzipEq(const Container1 &a, const Container2 &b)
Zip two containers into tuples; throw if lengths differ.
Operation for_each(Itor beg, const Itor &end, Operation op)
Apply an operation to each element in a range.
Definition ahAlgo.H:76
std::pair< DynList< DynList< T > >, size_t > sequential_groups(const Container< T > &c, Equal &eq)
Group consecutive equal elements together.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
Definition ah-date.H:140
size_t insert_in_container(C &c, Args ... args)
Insert multiple items into a container.
DynList< std::tuple< size_t, typename Container::Key_Type > > tindexes(const Container &c)
Return tuples of (index, key).
Itor::difference_type count_if(Itor beg, const Itor &end, Operation op)
Count elements satisfying a predicate.
Definition ahAlgo.H:100
DynList< T > scanl_sum(const Container &container, const T &init)
Compute running sums (scanl with addition).
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzip_longest(const Container1 &a, const Container2 &b, const typename Container1::Item_Type &fill_a=typename Container1::Item_Type(), const typename Container2::Item_Type &fill_b=typename Container2::Item_Type())
Zip two containers into tuples, padding the shorter one.
std::string concat(const Args &... args)
Concatenate multiple streamable arguments into a single std::string.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip_longest(const Container1 &a, const Container2 &b, const typename Container1::Item_Type &fill_a=typename Container1::Item_Type(), const typename Container2::Item_Type &fill_b=typename Container2::Item_Type())
Zip two containers, padding the shorter one with a fill value.
Container::Item_Type * find_ptr(Container &container, Pred &pred)
Find the first element satisfying pred.
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
void enum_for_each(const Container &container, Operation &operation)
Apply an operation to each element and its index.
DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, DynList< T > > > group_by(const Container< T > &c, KeyFunc key_func)
Group consecutive elements by a key function.
Container< T > contiguous_range(T start, const size_t n)
Generate n contiguous values starting from start.
bool none(const Container &container, Operation &operation)
Return true if no element satisfies operation.
void each(size_t start, size_t end, Op &op)
Execute an operation repeatedly over a range of indices.
size_t remove_from_container(C &c, Args ... args)
Remove multiple items from a container.
std::tuple< Container< T1 >, Container< T2 > > tunzip(const Container< std::tuple< T1, T2 > > &l)
Separate a list of tuples into two containers.
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
DynList< T > rep(size_t n, const T &item)
Create a sequence of repeated items.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
STL namespace.
#define LL
Definition ran_array.c:24
Represents a missing value.
virtual T & get_item() override
virtual bool is_found() const noexcept override
Represents a found value (stored by reference).
virtual bool is_found() const noexcept override
virtual T & get_item() override
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95
bool operator==(const Person &other) const
static constexpr size_t N
DynSetTree< size_t > tbl
Lazy and scalable dynamic array implementation.
Dynamic set implementations based on balanced binary search trees.
Open addressing hash table with double hashing.
DynList< int > l