Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-zip.H
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#ifndef AH_ZIP_H
33#define AH_ZIP_H 1
34
35#include <type_traits>
36#include <tuple>
37#include <vector>
38
39#include <htlist.H>
40#include <ahFunctional.H>
41#include <tpl_dynSkipList.H>
42
66namespace Aleph {
67
99template <class HeadC, class... TailC>
100class ZipIterator : public ZipIterator<TailC...>
102{
103 typename HeadC::Iterator it;
104
105 using T = std::decay_t<typename HeadC::Item_Type>;
106
107public:
110 = decltype(std::tuple_cat(std::declval<std::tuple<T>>(),
111 std::declval<typename ZipIterator<TailC...>::Tuple_Type>()));
112
114 using Item_Type = T;
115
123 ZipIterator(const HeadC &head, const TailC &...tail) : ZipIterator<TailC...>(tail...), it(head) {}
124
127 {
128 return it.has_curr() and ZipIterator<TailC...>::has_curr();
129 }
130
137 {
138 return not it.has_curr() and ZipIterator<TailC...>::completed();
139 }
140
145 auto get_curr() const
146 {
147 std::tuple<T> curr(it.get_curr());
148 return std::tuple_cat(curr, ZipIterator<TailC...>::get_curr());
149 }
150
156 {
157 std::tuple<T> curr(it.get_curr_ne());
158 return std::tuple_cat(curr, ZipIterator<TailC...>::get_curr_ne());
159 }
160
163 {
165 l.append(it.get_curr());
167 return l;
168 }
169
171 void next()
172 {
173 it.next();
175 }
176
182 {
183 it.next_ne();
185 }
186};
187
188template <class C>
189class ZipIterator<C> : public C::Iterator
190{
191public:
192 using T = std::decay_t<typename C::Item_Type>;
193
195 using Tuple_Type = std::tuple<T>;
196
198 using Item_Type = T;
199
206 ZipIterator(const C &c) : C::Iterator(c) {}
207
212 std::tuple<T> get_curr() const
213 {
214 return std::tuple<T>(C::Iterator::get_curr());
215 }
216
221 std::tuple<T> get_curr_ne() const noexcept
222 {
223 return std::tuple<T>(C::Iterator::get_curr_ne());
224 }
225
227 {
229 l.append(C::Iterator::get_curr());
230 return l;
231 }
232
235 {
236 return not this->has_curr();
237 }
238};
239
246template <class... Cs>
247[[nodiscard]] inline ZipIterator<Cs...> get_zip_it(const Cs &...cs)
248{
249 return ZipIterator<Cs...>(cs...);
250}
251
259template <class... Cs>
260[[nodiscard]] inline ZipIterator<Cs...> get_zip_it_pos(size_t pos, const Cs &...cs)
261{
262 ZipIterator<Cs...> ret(cs...);
263 for (size_t i = 0; i < pos; ++i)
264 ret.next();
265 return ret;
266}
267
269template <class... Cs>
270[[nodiscard]] inline ZipIterator<Cs...> zip_it(const Cs &...cs)
271{
272 return get_zip_it(cs...);
273}
274
276template <class... Cs>
277[[nodiscard]] inline ZipIterator<Cs...> zip_it_pos(size_t pos, const Cs &...cs)
278{
279 return get_zip_it_pos(pos, cs...);
280}
281
288template <class... Cs>
289[[nodiscard]] inline bool equal_length(const Cs &...cs)
290{
291 auto it = get_zip_it(cs...);
292 for (/* already initialized */; it.has_curr(); it.next_ne())
293 /* empty */;
294
295 return it.completed();
296}
297
325template <class Op, class... Cs>
326[[nodiscard]] inline bool zip_traverse(Op &&op, const Cs &...cs)
327{
328 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
329 if (not std::forward<Op>(op)(it.get_curr()))
330 return false;
331 return true;
332}
333
342template <class Op, class... Cs>
343[[nodiscard]] inline bool zip_traverse_eq(Op &&op, const Cs &...cs)
344{
345 auto it = zip_it(cs...);
346 for (; it.has_curr(); it.next_ne())
347 if (not std::forward<Op>(op)(it.get_curr()))
348 return false;
349 return it.completed();
350}
351
381template <class Op, class... Cs>
382inline void zip_for_each(Op &&op, const Cs &...cs)
383{
384 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
385 std::forward<Op>(op)(it.get_curr());
386}
387
395template <class Op, class... Cs>
396inline void zip_for_each_eq(Op &&op, const Cs &...cs)
397{
398 auto it = get_zip_it(cs...);
399 for (; it.has_curr(); it.next_ne())
400 std::forward<Op>(op)(it.get_curr());
401
402 ah_length_error_if(not it.completed()) << "zip_for_each_eq() containers sizes mismatch";
403}
404
415template <class Op, class... Cs>
416[[nodiscard]] inline bool zip_all(Op &&op, const Cs &...cs)
417{
418 auto it = zip_it(cs...);
419 for (; it.has_curr(); it.next_ne())
420 if (not std::forward<Op>(op)(it.get_curr()))
421 return false;
422
423 return it.completed();
424}
425
436template <class Op, class... Cs>
437[[nodiscard]] inline bool zip_all_short(Op &&op, const Cs &...cs)
438{
439 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
440 if (not std::forward<Op>(op)(it.get_curr()))
441 return false;
442
443 return true;
444}
445
450template <class Op, class... Cs>
451[[nodiscard]] inline bool zip_forall(Op &&op, const Cs &...cs)
452{
453 return zip_all(std::forward<Op>(op), cs...);
454}
455
460template <class Op, class... Cs>
461[[nodiscard]] inline bool zip_forall_short(Op &&op, const Cs &...cs)
462{
463 return zip_all_short(std::forward<Op>(op), cs...);
464}
465
475template <class Op, class... Cs>
476[[nodiscard]] inline bool zip_exists(Op &&op, const Cs &...cs)
477{
478 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
479 if (std::forward<Op>(op)(it.get_curr()))
480 return true;
481
482 return false;
483}
484
489template <class Op, class... Cs>
490[[nodiscard]] inline bool zip_any(Op &&op, const Cs &...cs)
491{
492 return zip_exists(std::forward<Op>(op), cs...);
493}
494
504template <class Op, class... Cs>
505[[nodiscard]] inline bool zip_none(Op &&op, const Cs &...cs)
506{
507 return not zip_exists(std::forward<Op>(op), cs...);
508}
509
517template <class Op, class... Cs>
518[[nodiscard]] inline size_t zip_count(Op &&op, const Cs &...cs)
519{
520 size_t count = 0;
521 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
522 if (std::forward<Op>(op)(it.get_curr()))
523 ++count;
524 return count;
525}
526
533template <class... Cs>
534[[nodiscard]] inline size_t zip_length(const Cs &...cs)
535{
536 size_t count = 0;
537 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
538 ++count;
539 return count;
540}
541
550template <class Op, class... Cs>
551[[nodiscard]]
552auto zip_find_first(Op &&op, const Cs &...cs)
553{
554 using ZipType = typename ZipIterator<Cs...>::Tuple_Type;
555
556 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
557 if (auto t = it.get_curr(); std::forward<Op>(op)(t))
558 return std::make_pair(t, true);
559
560 return std::make_pair(ZipType{}, false);
561}
562
571template <class Op, class... Cs>
572[[nodiscard]]
573auto zip_find_last(Op &&op, const Cs &...cs)
574{
575 using ZipType = typename ZipIterator<Cs...>::Tuple_Type;
576
577 ZipType result{};
578 bool found = false;
579
580 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
581 if (auto t = it.get_curr(); std::forward<Op>(op)(t))
582 {
583 result = t;
584 found = true;
585 }
586
587 return std::make_pair(result, found);
588}
589
598template <class... Cs>
599[[nodiscard]]
600auto zip_nth(size_t n, const Cs &...cs)
601{
602 using ZipType = typename ZipIterator<Cs...>::Tuple_Type;
603
604 size_t i = 0;
605 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne(), ++i)
606 if (i == n)
607 return std::make_pair(it.get_curr(), true);
608
609 return std::make_pair(ZipType{}, false);
610}
611
619template <class... Cs>
620[[nodiscard]]
621auto zip_first(const Cs &...cs)
622{
623 return zip_nth(0, cs...);
624}
625
656template <typename T, class Op, class... Cs>
657[[nodiscard]]
658DynList<T> zip_maps(Op op, const Cs &...cs)
659{
661 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
662 ret.append(op(it.get_curr()));
663 return ret;
664}
665
675template <typename T, class Prop, class Op, class... Cs>
676[[nodiscard]]
678{
680 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
681 if (auto t = it.get_curr(); prop(t))
682 ret.append(op(t));
683
684 return ret;
685}
686
715template <typename T, class Op, class... Cs>
716[[nodiscard]]
717T zip_foldl(const T &init, Op op, const Cs &...cs)
718{
719 T acu = init;
720 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
721 acu = op(acu, it.get_curr());
722 return acu;
723}
724
735template <typename T, class Op, class... Cs>
736[[nodiscard]]
737T zip_foldl_eq(const T &init, Op op, const Cs &...cs)
738{
739 T acu = init;
740 auto it = zip_it(cs...);
741 for (; it.has_curr(); it.next_ne())
742 acu = op(acu, it.get_curr());
743
744 ah_length_error_if(not it.completed()) << "zip_foldl_eq() containers sizes mismatch";
745
746 return acu;
747}
748
758template <typename T, class Op, class... Cs>
759[[nodiscard]]
760DynList<T> zip_maps_eq(Op op, const Cs &...cs)
761{
763 auto it = zip_it(cs...);
764 for (; it.has_curr(); it.next_ne())
765 ret.append(op(it.get_curr()));
766
767 ah_length_error_if(not it.completed()) << "zip_maps_eq() containers sizes mismatch";
768
769 return ret;
770}
771
782template <typename T, class Prop, class Op, class... Cs>
783[[nodiscard]]
785{
787 auto it = zip_it(cs...);
788 for (; it.has_curr(); it.next_ne())
789 if (auto t = it.get_curr(); prop(t))
790 ret.append(op(t));
791
792 ah_length_error_if(not it.completed()) << "zip_maps_if_eq() containers sizes mismatch";
793
794 return ret;
795}
796
807template <class Op, class... Cs>
808[[nodiscard]]
809auto zip_map(Op &&op, const Cs &...cs)
810{
811 using ZipType = typename ZipIterator<Cs...>::Tuple_Type;
812 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
813
815 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
816 ret.append(std::forward<Op>(op)(it.get_curr()));
817 return ret;
818}
819
828template <class Op, class... Cs>
829[[nodiscard]]
830auto zip_map_eq(Op &&op, const Cs &...cs)
831{
832 using ZipType = typename ZipIterator<Cs...>::Tuple_Type;
833 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
834
836 auto it = zip_it(cs...);
837 for (; it.has_curr(); it.next_ne())
838 ret.append(std::forward<Op>(op)(it.get_curr()));
839
840 ah_length_error_if(not it.completed()) << "zip_map_eq() containers sizes mismatch";
841
842 return ret;
843}
844
868template <class Op, class... Cs>
869[[nodiscard]]
870auto zip_filter(Op op, const Cs &...cs)
871{
872 using ZipType = decltype(zip_it(cs...).get_curr());
873
875 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
876 if (auto t = it.get_curr(); op(t))
877 ret.append(t);
878
879 return ret;
880}
881
909template <class Op, class... Cs>
910[[nodiscard]]
911auto zip_filter_eq(Op op, const Cs &...cs)
912{
913 using ZipType = decltype(zip_it(cs...).get_curr());
914
916 auto it = zip_it(cs...);
917 for (; it.has_curr(); it.next_ne())
918 if (auto t = it.get_curr(); op(t))
919 ret.append(t);
920
921 ah_length_error_if(not it.completed()) << "zip_filter_eq() containers sizes mismatch";
922
923 return ret;
924}
925
929namespace zip_detail {
935template <class Cmp, class Tuple, size_t... Is>
936bool compare_adjacent(Cmp &cmp, const Tuple &t, std::index_sequence<Is...>)
937{
938 // Compare t[0] with t[1], t[1] with t[2], etc.
939 return (... and cmp(std::get<Is>(t), std::get<Is + 1>(t)));
940}
941} // namespace zip_detail
942
963template <class Cmp, class... Cs>
964[[nodiscard]]
965bool zip_cmp(Cmp cmp, const Cs &...cs)
966{
967 constexpr size_t N = sizeof...(Cs);
968 static_assert(N >= 2, "zip_cmp requires at least 2 containers");
969
970 for (auto it = get_zip_it(cs...); it.has_curr(); it.next_ne())
971 if (auto t = it.get_curr();
972 not zip_detail::compare_adjacent(cmp, t, std::make_index_sequence<N - 1>{}))
973 return false;
974
975 return true;
976}
977
986template <class Op, class... Cs>
987[[nodiscard]]
988size_t zip_find_index(Op op, const Cs &...cs)
989{
990 size_t i = 0;
991 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne(), ++i)
992 if (auto t = it.get_curr(); op(t))
993 break;
994
995 return i;
996}
997
1033template <class Op, class... Cs>
1034[[nodiscard]]
1035auto zip_partition(Op op, const Cs &...cs)
1036{
1037 using ZipType = decltype(zip_it(cs...).get_curr());
1038
1040 size_t n1 = 0, n2 = 0;
1041 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
1042 if (auto t = it.get_curr(); op(t))
1043 {
1044 ret1.append(t);
1045 ++n1;
1046 }
1047 else
1048 {
1049 ret2.append(t);
1050 ++n2;
1051 }
1052
1053 return std::make_tuple(ret1, n1, ret2, n2);
1054}
1055
1084template <class... Cs>
1085[[nodiscard]] inline auto t_zip(const Cs &...cs)
1086{
1087 auto it = zip_it(cs...);
1088 using T = decltype(it.get_curr());
1090 for (; it.has_curr(); it.next_ne())
1091 ret.append(it.get_curr());
1092
1093 return ret;
1094}
1095
1103template <class... Cs>
1104[[nodiscard]] inline auto t_zip_eq(const Cs &...cs)
1105{
1106 auto it = zip_it(cs...);
1107 using T = decltype(it.get_curr());
1109 for (; it.has_curr(); it.next_ne())
1110 ret.append(it.get_curr());
1111
1112 ah_length_error_if(not it.completed()) << "Container sizes mismatch";
1113
1114 return ret;
1115}
1116
1144template <class HeadC, class... TailC>
1145class EnumZipIterator : public EnumZipIterator<TailC...>
1147{
1148 typename HeadC::Iterator it;
1149
1150 using T = std::decay_t<typename HeadC::Item_Type>;
1151
1152public:
1157 EnumZipIterator(const HeadC &head, const TailC &...tail)
1158 : EnumZipIterator<TailC...>(tail...), it(head)
1159 {}
1160
1162 [[nodiscard]] bool has_curr() const noexcept
1163 {
1164 return it.has_curr() and EnumZipIterator<TailC...>::has_curr();
1165 }
1166
1169 {
1170 return not it.has_curr() and EnumZipIterator<TailC...>::completed();
1171 }
1172
1177 auto get_curr() const
1178 {
1179 std::tuple<T> curr(it.get_curr());
1180 return std::tuple_cat(curr, EnumZipIterator<TailC...>::get_curr());
1181 }
1182
1184 void next()
1185 {
1186 it.next();
1188 }
1189
1191 {
1192 std::tuple<T> curr(it.get_curr_ne());
1193 return std::tuple_cat(curr, EnumZipIterator<TailC...>::get_curr_ne());
1194 }
1195
1200 void next_ne() noexcept
1201 {
1202 it.next_ne();
1204 }
1205};
1206
1207template <class C>
1208class EnumZipIterator<C> : public C::Iterator
1209{
1210 size_t i = 0;
1211
1212public:
1214 void next()
1215 {
1216 C::Iterator::next();
1217 ++i;
1218 }
1219
1225 {
1226 C::Iterator::next_ne();
1227 ++i;
1228 }
1229
1230 using T = std::decay_t<typename C::Item_Type>;
1231
1236 EnumZipIterator(const C &c) : C::Iterator(c) {}
1237
1239 std::tuple<T, size_t> get_curr() const
1240 {
1241 return std::tuple<T, size_t>(C::Iterator::get_curr(), i);
1242 }
1243
1248 std::tuple<T, size_t> get_curr_ne() const noexcept
1249 {
1250 return std::tuple<T, size_t>(C::Iterator::get_curr_ne(), i);
1251 }
1252
1255 {
1256 return not this->has_curr();
1257 }
1258};
1259
1266template <class... Cs>
1268{
1269 return EnumZipIterator<Cs...>(cs...);
1270}
1271
1280template <class C, class... Cs>
1282 const C &c,
1283 const Cs &...cs)
1284{
1285 EnumZipIterator<C, Cs...> ret(c, cs...);
1286 for (size_t i = 0; i < pos; ++i)
1287 ret.next();
1288
1289 return ret;
1290}
1291
1293template <class... Cs>
1294[[nodiscard]] inline EnumZipIterator<Cs...> enum_zip_it(const Cs &...cs)
1295{
1296 return EnumZipIterator<Cs...>(cs...);
1297}
1298
1300template <class... Cs>
1301[[nodiscard]] inline EnumZipIterator<Cs...> enum_zip_it_pos(size_t pos, const Cs &...cs)
1302{
1303 return get_enum_zip_it_pos(pos, cs...);
1304}
1305
1314template <class... Cs>
1315[[nodiscard]] inline auto t_enum_zip(const Cs &...cs)
1316{
1317 auto it = get_enum_zip_it(cs...);
1318 using T = decltype(it.get_curr());
1320 for (; it.has_curr(); it.next_ne())
1321 ret.append(it.get_curr());
1322
1323 return ret;
1324}
1325
1333template <class... Cs>
1334[[nodiscard]] inline auto t_enum_zip_eq(const Cs &...cs)
1335{
1336 auto it = get_enum_zip_it(cs...);
1337 using T = decltype(it.get_curr());
1339 for (; it.has_curr(); it.next_ne())
1340 ret.append(it.get_curr());
1341
1342 ah_length_error_if(not it.completed()) << "Container sizes mismatch";
1343
1344 return ret;
1345}
1346
1347template <typename... Ts, size_t... is>
1348static inline auto t_unzip_impl(const DynList<std::tuple<Ts...>> &l, std::index_sequence<is...>)
1349{
1350 std::tuple<DynList<Ts>...> ret;
1351 for (auto it = l.get_it(); it.has_curr(); it.next_ne())
1352 std::initializer_list<int>{(std::get<is>(ret).append(std::get<is>(it.get_curr())), 0)...};
1353
1354 return ret;
1355}
1356
1363template <class... Ts>
1364[[nodiscard]] inline auto t_unzip(const DynList<std::tuple<Ts...>> &tuples)
1365{
1366 return t_unzip_impl(tuples, std::index_sequence_for<Ts...>{});
1367}
1368
1386template <class C, typename... Lists>
1387[[nodiscard]]
1388auto zip_lists(const C &c, const Lists &...lists)
1389{
1390 using T = typename C::Item_Type;
1392 for (auto it = get_zip_it(c, lists...); it.has_curr(); it.next_ne())
1393 ret.append(it.get_curr_list());
1394 return ret;
1395}
1396
1405template <class C, typename... Lists>
1406[[nodiscard]]
1407auto zip_lists_eq(const C &c, const Lists &...lists)
1408{
1409 using T = typename C::Item_Type;
1411 auto it = get_zip_it(c, lists...);
1412 for (; it.has_curr(); it.next_ne())
1413 ret.append(it.get_curr_list());
1414
1415 ah_length_error_if(not it.completed()) << "zip_list_eq: container sizes mismatch";
1416
1417 return ret;
1418}
1419
1423namespace std_zip_detail {
1428template <typename... Its>
1429bool all_valid(const Its &...its)
1430{
1431 return (... and (its.first != its.second));
1432}
1433
1437template <typename... Its>
1439{
1440 (++its.first, ...);
1441}
1442
1447template <typename... Its>
1448auto deref_all(const Its &...its)
1449{
1450 return std::make_tuple(*its.first...);
1451}
1452} // namespace std_zip_detail
1453
1458template <typename C1, typename C2>
1459[[nodiscard]]
1460auto std_zip(const C1 &c1, const C2 &c2)
1461{
1462 using T = typename C1::value_type;
1463 using U = typename C2::value_type;
1464 std::vector<std::pair<T, U>> result;
1465 auto it1 = c1.begin();
1466 auto it2 = c2.begin();
1467 for (; it1 != c1.end() and it2 != c2.end(); ++it1, ++it2)
1468 result.emplace_back(*it1, *it2);
1469 return result;
1470}
1471
1486template <typename... Cs>
1487[[nodiscard]]
1488auto tzip_std(const Cs &...cs)
1489{
1490 static_assert(sizeof...(Cs) >= 2, "tzip_std requires at least 2 containers");
1491
1492 using TupleType = std::tuple<typename Cs::value_type...>;
1493 std::vector<TupleType> ret;
1494
1495 // Create iterator pairs (begin, end) for each container
1496 auto iters = std::make_tuple(std::make_pair(cs.begin(), cs.end())...);
1497
1498 // Helper to check all iterators and build tuples
1499 auto check_and_push = [&ret](auto &...its)
1500 {
1501 while (std_zip_detail::all_valid(its...))
1502 {
1503 ret.push_back(std_zip_detail::deref_all(its...));
1505 }
1506 };
1507
1508 std::apply(check_and_push, iters);
1509 return ret;
1510}
1511
1521template <typename... Cs>
1522[[nodiscard]]
1523auto std_zip_n(const Cs &...cs)
1524{
1525 return tzip_std(cs...);
1526}
1527
1538template <class Op, class... Cs>
1539[[nodiscard]]
1540auto zip_transform(Op &&op, const Cs &...cs)
1541{
1542 using ZipType = decltype(zip_it(cs...).get_curr());
1543 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
1544
1545 std::vector<ResultType> ret;
1546 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
1547 ret.push_back(std::forward<Op>(op)(it.get_curr()));
1548 return ret;
1549}
1550
1560template <class Op, class... Cs>
1561[[nodiscard]]
1562auto zip_transform_eq(Op &&op, const Cs &...cs)
1563{
1564 using ZipType = decltype(zip_it(cs...).get_curr());
1565 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<ZipType>()))>;
1566
1567 std::vector<ResultType> ret;
1568 auto it = zip_it(cs...);
1569 for (; it.has_curr(); it.next_ne())
1570 ret.push_back(std::forward<Op>(op)(it.get_curr()));
1571
1572 ah_length_error_if(not it.completed()) << "zip_transform_eq() containers sizes mismatch";
1573 return ret;
1574}
1575
1584template <class Op, class... Cs>
1585inline void zip_for_each_indexed(Op &&op, const Cs &...cs)
1586{
1587 size_t idx = 0;
1588 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne(), ++idx)
1589 std::forward<Op>(op)(idx, it.get_curr());
1590}
1591
1599template <class Op, class... Cs>
1600inline void zip_for_each_indexed_eq(Op &&op, const Cs &...cs)
1601{
1602 size_t idx = 0;
1603 auto it = zip_it(cs...);
1604 for (; it.has_curr(); it.next_ne(), ++idx)
1605 std::forward<Op>(op)(idx, it.get_curr());
1606
1607 ah_length_error_if(not it.completed()) << "zip_for_each_indexed_eq() containers sizes mismatch";
1608}
1609
1617template <class... Cs>
1618[[nodiscard]]
1619auto zip_take(size_t n, const Cs &...cs)
1620{
1621 using ZipType = decltype(zip_it(cs...).get_curr());
1623 size_t count = 0;
1624 for (auto it = zip_it(cs...); it.has_curr() and count < n; it.next_ne(), ++count)
1625 ret.append(it.get_curr());
1626 return ret;
1627}
1628
1636template <class... Cs>
1637[[nodiscard]]
1638auto zip_drop(const size_t n, const Cs &...cs)
1639{
1640 using ZipType = decltype(zip_it(cs...).get_curr());
1642 auto it = zip_it(cs...);
1643
1644 // Skip first n elements
1645 for (size_t i = 0; i < n and it.has_curr(); ++i)
1646 it.next_ne();
1647
1648 // Collect the rest
1649 for (; it.has_curr(); it.next_ne())
1650 ret.append(it.get_curr());
1651 return ret;
1652}
1653
1661template <class Pred, class... Cs>
1662[[nodiscard]]
1663auto zip_take_while(Pred &&pred, const Cs &...cs)
1664{
1665 using ZipType = decltype(zip_it(cs...).get_curr());
1667 for (auto it = zip_it(cs...); it.has_curr(); it.next_ne())
1668 {
1669 auto t = it.get_curr();
1670 if (not std::forward<Pred>(pred)(t))
1671 break;
1672 ret.append(t);
1673 }
1674 return ret;
1675}
1676
1684template <class Pred, class... Cs>
1685[[nodiscard]]
1686auto zip_drop_while(Pred &&pred, const Cs &...cs)
1687{
1688 using ZipType = decltype(zip_it(cs...).get_curr());
1690 auto it = zip_it(cs...);
1691
1692 // Skip while pred is true
1693 for (; it.has_curr() and std::forward<Pred>(pred)(it.get_curr()); it.next_ne())
1694 /* skip */;
1695
1696 // Collect the rest
1697 for (; it.has_curr(); it.next_ne())
1698 ret.append(it.get_curr());
1699 return ret;
1700}
1701
1702// ============================================================================
1703// Index sequence helpers
1704// ============================================================================
1705
1709namespace zip_index_detail {
1714template <class Op, class Tuple, size_t... Is>
1715void for_each_in_tuple_impl(Op &&op, Tuple &&t, std::index_sequence<Is...>)
1716{
1717 (std::forward<Op>(op)(std::get<Is>(std::forward<Tuple>(t))), ...);
1718}
1719
1725template <class Op, class Tuple, size_t... Is>
1726auto transform_tuple_impl(Op &&op, Tuple &&t, std::index_sequence<Is...>)
1727{
1728 return std::make_tuple(std::forward<Op>(op)(std::get<Is>(std::forward<Tuple>(t)))...);
1729}
1730
1736template <class Pred, class Tuple, size_t... Is>
1737bool all_of_tuple_impl(Pred &&pred, const Tuple &t, std::index_sequence<Is...>)
1738{
1739 return (... and std::forward<Pred>(pred)(std::get<Is>(t)));
1740}
1741
1747template <class Pred, class Tuple, size_t... Is>
1748bool any_of_tuple_impl(Pred &&pred, const Tuple &t, std::index_sequence<Is...>)
1749{
1750 return (... or std::forward<Pred>(pred)(std::get<Is>(t)));
1751}
1752} // namespace zip_index_detail
1753
1783template <class Op, class Tuple>
1784void for_each_in_tuple(Op &&op, Tuple &&t)
1785{
1786 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1787 zip_index_detail::for_each_in_tuple_impl(std::forward<Op>(op),
1788 std::forward<Tuple>(t),
1789 std::make_index_sequence<N>{});
1790}
1791
1822template <class Op, class Tuple>
1823[[nodiscard]]
1824auto transform_tuple(Op &&op, Tuple &&t)
1825{
1826 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1827 return zip_index_detail::transform_tuple_impl(std::forward<Op>(op),
1828 std::forward<Tuple>(t),
1829 std::make_index_sequence<N>{});
1830}
1831
1853template <class Pred, class Tuple>
1854[[nodiscard]]
1855bool all_of_tuple(Pred &&pred, const Tuple &t)
1856{
1857 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1858 return zip_index_detail::all_of_tuple_impl(std::forward<Pred>(pred),
1859 t,
1860 std::make_index_sequence<N>{});
1861}
1862
1883template <class Pred, class Tuple>
1884[[nodiscard]]
1885bool any_of_tuple(Pred &&pred, const Tuple &t)
1886{
1887 constexpr auto N = std::tuple_size_v<std::decay_t<Tuple>>;
1888 return zip_index_detail::any_of_tuple_impl(std::forward<Pred>(pred),
1889 t,
1890 std::make_index_sequence<N>{});
1891}
1892
1913template <class Pred, class Tuple>
1914[[nodiscard]]
1915bool none_of_tuple(Pred &&pred, const Tuple &t)
1916{
1917 return not any_of_tuple(std::forward<Pred>(pred), t);
1918}
1919
1920} // end namespace Aleph
1921
1922#endif // AH_ZIP_H
#define ah_length_error_if(C)
Throws std::length_error if condition holds.
Definition ah-errors.H:698
Functional programming utilities for Aleph-w containers.
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
bool completed() const noexcept
Return true if the underlying iterator has reached the end.
Definition ah-zip.H:1254
std::tuple< T, size_t > get_curr_ne() const noexcept
Return the current tuple (value, index) (no-throw variant).
Definition ah-zip.H:1248
std::tuple< T, size_t > get_curr() const
Return the current tuple (value, index) (bounds-checked).
Definition ah-zip.H:1239
EnumZipIterator(const C &c)
Construct an enumerating iterator over a single container.
Definition ah-zip.H:1236
void next()
Advance the iterator and increment the associated index (bounds-checked).
Definition ah-zip.H:1214
void next_ne() noexcept
Advance the iterator and increment the associated index (no-throw variant).
Definition ah-zip.H:1224
std::decay_t< typename C::Item_Type > T
Definition ah-zip.H:1230
std::tuple< T > get_curr_ne() const noexcept
Return the current tuple (no-throw variant).
Definition ah-zip.H:221
std::tuple< T > Tuple_Type
The tuple type returned by get_curr() and get_curr_ne()
Definition ah-zip.H:195
std::decay_t< typename C::Item_Type > T
Definition ah-zip.H:192
bool completed() const noexcept
Return true if the underlying iterator has reached the end.
Definition ah-zip.H:234
DynList< T > get_curr_list() const
Definition ah-zip.H:226
std::tuple< T > get_curr() const
Return the current tuple (bounds-checked).
Definition ah-zip.H:212
ZipIterator(const C &c)
Construct a zip iterator over a single container.
Definition ah-zip.H:206
T Item_Type
Type of elements from the container.
Definition ah-zip.H:198
Iterator that traverses multiple containers with enumeration index.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:222
Iterator that traverses multiple Aleph containers in lockstep.
#define N
Definition fib.C:294
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
Singly linked list implementations with head-tail access.
Freq_Node * pred
Predecessor node in level-order traversal.
bool all_valid(const Its &...its)
Check if all iterators are valid (not at end).
Definition ah-zip.H:1429
void advance_all(Its &...its)
Advance all iterators.
Definition ah-zip.H:1438
auto deref_all(const Its &...its)
Dereference all iterators and make a tuple.
Definition ah-zip.H:1448
bool compare_adjacent(Cmp &cmp, const Tuple &t, std::index_sequence< Is... >)
Compare all adjacent pairs in a tuple using the given comparator.
Definition ah-zip.H:936
bool any_of_tuple_impl(Pred &&pred, const Tuple &t, std::index_sequence< Is... >)
Check if any element satisfies a predicate.
Definition ah-zip.H:1748
auto transform_tuple_impl(Op &&op, Tuple &&t, std::index_sequence< Is... >)
Transform each element in a tuple.
Definition ah-zip.H:1726
void for_each_in_tuple_impl(Op &&op, Tuple &&t, std::index_sequence< Is... >)
Apply a function to each element in a tuple.
Definition ah-zip.H:1715
bool all_of_tuple_impl(Pred &&pred, const Tuple &t, std::index_sequence< Is... >)
Check if all elements satisfy a predicate.
Definition ah-zip.H:1737
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
ZipIterator< Cs... > zip_it(const Cs &...cs)
Alias for get_zip_it.
Definition ah-zip.H:270
void zip_for_each_eq(Op &&op, const Cs &...cs)
Apply op to every zipped tuple; throw if containers differ in length.
Definition ah-zip.H:396
EnumZipIterator< Cs... > get_enum_zip_it(const Cs &...cs)
Create an EnumZipIterator over the given containers.
Definition ah-zip.H:1267
bool zip_traverse_eq(Op &&op, const Cs &...cs)
Traverse zipped containers while op returns true; verify equal lengths.
Definition ah-zip.H:343
void zip_for_each_indexed_eq(Op &&op, const Cs &...cs)
Apply op to each zipped tuple with index; throw if lengths differ.
Definition ah-zip.H:1600
auto zip_drop_while(Pred &&pred, const Cs &...cs)
Skip tuples while predicate pred returns true, then return the rest.
Definition ah-zip.H:1686
auto t_enum_zip_eq(const Cs &...cs)
Materialize enumerated zipped tuples; throw if containers differ in length.
Definition ah-zip.H:1334
DynList< T > zip_maps_if_eq(Prop prop, Op op, const Cs &...cs)
Map op over zipped tuples that satisfy prop; throw if lengths differ.
Definition ah-zip.H:784
void zip_for_each(Op &&op, const Cs &...cs)
Apply op to every zipped tuple.
Definition ah-zip.H:382
T Item_Type
Type of elements from the first container.
Definition ah-zip.H:114
bool completed() const noexcept
Return true if all underlying iterators are finished.
Definition ah-zip.H:136
EnumZipIterator< Cs... > enum_zip_it_pos(size_t pos, const Cs &...cs)
Alias for get_enum_zip_it_pos.
Definition ah-zip.H:1301
ZipIterator< Cs... > zip_it_pos(size_t pos, const Cs &...cs)
Alias for get_zip_it_pos.
Definition ah-zip.H:277
bool zip_forall_short(Op &&op, const Cs &...cs)
Alias for zip_all_short.
Definition ah-zip.H:461
auto std_zip(const C1 &c1, const C2 &c2)
Build a vector of pairs from two STL containers.
Definition ah-zip.H:1460
bool all_of_tuple(Pred &&pred, const Tuple &t)
Return true if all tuple elements satisfy pred.
Definition ah-zip.H:1855
auto transform_tuple(Op &&op, Tuple &&t)
Transform each element of a tuple, returning a new tuple.
Definition ah-zip.H:1824
auto zip_transform_eq(Op &&op, const Cs &...cs)
Transform zipped tuples; throw if containers differ in length.
Definition ah-zip.H:1562
static auto t_unzip_impl(const DynList< std::tuple< Ts... > > &l, std::index_sequence< is... >)
Definition ah-zip.H:1348
ZipIterator< Cs... > get_zip_it_pos(size_t pos, const Cs &...cs)
Create a ZipIterator positioned at index pos.
Definition ah-zip.H:260
bool equal_length(const Cs &...cs)
Return true if all containers have the same length.
Definition ah-zip.H:289
T zip_foldl(const T &init, Op op, const Cs &...cs)
Left fold (reduce) over zipped tuples.
Definition ah-zip.H:717
bool zip_all_short(Op &&op, const Cs &...cs)
Return true if op returns true for all tuples (without length check).
Definition ah-zip.H:437
void for_each_in_tuple(Op &&op, Tuple &&t)
Apply op to each element of a tuple.
Definition ah-zip.H:1784
auto std_zip_n(const Cs &...cs)
Build a vector of tuples from 2 or more STL containers (variadic).
Definition ah-zip.H:1523
ZipIterator< Cs... > get_zip_it(const Cs &...cs)
Create a ZipIterator over the given containers.
Definition ah-zip.H:247
void next_ne() noexcept
Advance all underlying iterators (no-throw variant).
Definition ah-zip.H:181
size_t zip_length(const Cs &...cs)
Count all tuples (minimum length of containers).
Definition ah-zip.H:534
auto zip_filter(Op op, const Cs &...cs)
Filter zipped tuples by predicate op.
Definition ah-zip.H:870
T zip_foldl_eq(const T &init, Op op, const Cs &...cs)
Left fold over zipped tuples; throw if containers differ in length.
Definition ah-zip.H:737
auto t_zip(const Cs &...cs)
Materialize zipped tuples into a DynList.
Definition ah-zip.H:1085
decltype(std::tuple_cat(std::declval< std::tuple< T > >(), std::declval< typename ZipIterator< TailC... >::Tuple_Type >())) Tuple_Type
The tuple type returned by get_curr() and get_curr_ne()
Definition ah-zip.H:111
bool zip_any(Op &&op, const Cs &...cs)
Alias for zip_exists.
Definition ah-zip.H:490
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
auto zip_lists(const C &c, const Lists &...lists)
Take several container of same type and some length and builds a list of lists.
Definition ah-zip.H:1388
bool zip_forall(Op &&op, const Cs &...cs)
Alias for zip_all.
Definition ah-zip.H:451
bool any_of_tuple(Pred &&pred, const Tuple &t)
Return true if any tuple element satisfies pred.
Definition ah-zip.H:1885
size_t zip_count(Op &&op, const Cs &...cs)
Count tuples that satisfy predicate op.
Definition ah-zip.H:518
bool zip_traverse(Op &&op, const Cs &...cs)
Traverse zipped containers while op returns true.
Definition ah-zip.H:326
auto get_curr() const
Return the current tuple (bounds-checked).
Definition ah-zip.H:145
auto zip_find_first(Op &&op, const Cs &...cs)
Return the first tuple that satisfies predicate op.
Definition ah-zip.H:552
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:416
auto t_zip_eq(const Cs &...cs)
Materialize zipped tuples; throw if containers differ in length.
Definition ah-zip.H:1104
bool none_of_tuple(Pred &&pred, const Tuple &t)
Return true if no tuple element satisfies pred.
Definition ah-zip.H:1915
bool zip_none(Op &&op, const Cs &...cs)
Return true if op returns false for all tuples.
Definition ah-zip.H:505
bool has_curr() const noexcept
Return true if all underlying iterators are positioned on a valid item.
Definition ah-zip.H:126
auto tzip_std(const Cs &...cs)
Build a vector of tuples from 2 or more STL containers (variadic).
Definition ah-zip.H:1488
auto t_enum_zip(const Cs &...cs)
Materialize enumerated zipped tuples into a DynList.
Definition ah-zip.H:1315
auto zip_first(const Cs &...cs)
Return the first tuple from zipped containers.
Definition ah-zip.H:621
EnumZipIterator< Cs... > enum_zip_it(const Cs &...cs)
Alias for get_enum_zip_it.
Definition ah-zip.H:1294
auto zip_find_last(Op &&op, const Cs &...cs)
Return the last tuple that satisfies predicate op.
Definition ah-zip.H:573
auto t_unzip(const DynList< std::tuple< Ts... > > &tuples)
Unzip a list of tuples into a tuple of lists.
Definition ah-zip.H:1364
auto zip_map(Op &&op, const Cs &...cs)
Map op over zipped tuples with auto-deduced return type.
Definition ah-zip.H:809
auto zip_partition(Op op, const Cs &...cs)
Partition zipped tuples by predicate op.
Definition ah-zip.H:1035
size_t zip_find_index(Op op, const Cs &...cs)
Find the first index where op returns true.
Definition ah-zip.H:988
auto zip_take_while(Pred &&pred, const Cs &...cs)
Take tuples while predicate pred returns true.
Definition ah-zip.H:1663
void zip_for_each_indexed(Op &&op, const Cs &...cs)
Apply op to each zipped tuple along with its index.
Definition ah-zip.H:1585
bool zip_exists(Op &&op, const Cs &...cs)
Return true if op returns true for at least one tuple.
Definition ah-zip.H:476
EnumZipIterator< C, Cs... > get_enum_zip_it_pos(size_t pos, const C &c, const Cs &...cs)
Create an EnumZipIterator positioned at index pos.
Definition ah-zip.H:1281
auto zip_drop(const size_t n, const Cs &...cs)
Skip n tuples and return the rest.
Definition ah-zip.H:1638
DynList< T > get_curr_list() const
Returns current elements as a DynList (requires homogeneous Item_Type)
Definition ah-zip.H:162
DynList< T > zip_maps_eq(Op op, const Cs &...cs)
Map op over zipped tuples; throw if containers differ in length.
Definition ah-zip.H:760
DynList< T > zip_maps(Op op, const Cs &...cs)
Map op over zipped tuples, returning a list of results.
Definition ah-zip.H:658
auto get_curr_ne() const noexcept
Return the current tuple (no-throw variant).
Definition ah-zip.H:155
auto zip_filter_eq(Op op, const Cs &...cs)
Filter zipped tuples by predicate op; throw if containers differ in length.
Definition ah-zip.H:911
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:171
auto zip_nth(size_t n, const Cs &...cs)
Return the n-th tuple from zipped containers.
Definition ah-zip.H:600
auto zip_lists_eq(const C &c, const Lists &...lists)
Like zip_lists but throws if containers differ in length.
Definition ah-zip.H:1407
bool zip_cmp(Cmp cmp, const Cs &...cs)
Return true if cmp(t) is true for each built tuple t.
Definition ah-zip.H:965
auto zip_map_eq(Op &&op, const Cs &...cs)
Map op over zipped tuples with auto-deduced return type; throw if lengths differ.
Definition ah-zip.H:830
auto zip_transform(Op &&op, const Cs &...cs)
Transform zipped tuples using op and return results in a vector.
Definition ah-zip.H:1540
DynList< T > zip_maps_if(Prop prop, Op op, const Cs &...cs)
Map op over zipped tuples that satisfy prop.
Definition ah-zip.H:677
static std::atomic< bool > init
Definition hash-fct.C:53
auto zip_take(size_t n, const Cs &...cs)
Take at most n tuples from the zipped containers.
Definition ah-zip.H:1619
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
Dynamic ordered set implemented with a Skip List.
DynList< int > l