Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-comb.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31#ifndef COMB_H
32#define COMB_H
33
62#include <algorithm>
63#include <bit>
64#include <cstdint>
65#include <limits>
66#include <numeric>
67
68#include <ah-errors.H>
69
70#include <htlist.H>
71#include <tpl_dynDlist.H>
72#include <tpl_dynArray.H>
73#include <tpl_array.H>
74#include <tpl_dynSetTree.H>
75#include <ahFunction.H>
76#include <ahSort.H>
77
78namespace Aleph {
80namespace comb_detail {
94template <typename T>
96{
97 if (l.is_empty())
98 return {};
99
101
102 size_t ncol = 0;
103 {
104 const HTList &lrow = l.get_first();
106 for (HTList::Iterator it(lrow); it.has_curr(); it.next_ne(), ++ncol)
107 row.append(static_cast<Snodenc<T> *>(it.get_curr()));
108 mat.append(std::move(row));
109 }
110
111 size_t nrow = 1;
112 for (auto row_it = l.get_it(1); row_it.has_curr(); row_it.next_ne(), ++nrow)
113 {
114 const HTList &lrow = row_it.get_curr();
117 size_t col = 0;
118 for (HTList::Iterator it(lrow); it.has_curr(); it.next_ne(), ++col)
119 row.append(static_cast<Snodenc<T> *>(it.get_curr()));
120
121 assert(col == ncol);
122
123 mat.append(std::move(row));
124 }
125
127 for (size_t j = 0; j < ncol; ++j)
128 {
130 for (size_t i = 0; i < nrow; ++i)
131 row.append(mat(i)(j)->get_data());
132
133 ret.append(std::move(row));
134 }
135
136 return ret;
137}
138
139template <class ArrayLike>
140inline void reverse_range(ArrayLike &a, size_t left, size_t right) noexcept
141{
142 while (left < right)
143 {
144 std::swap(a(left), a(right));
145 ++left;
146 --right;
147 }
148}
149
150template <class IndexArray>
151inline void validate_combination_indices(const IndexArray &idx, const size_t n)
152{
153 const size_t k = idx.size();
154 ah_domain_error_if(k > n) << "next_combination_indices: k=" << k << " cannot exceed n=" << n;
155
156 for (size_t i = 0; i < k; ++i)
157 {
158 ah_out_of_range_error_if(idx(i) >= n)
159 << "next_combination_indices: index " << idx(i) << " at position " << i
160 << " is outside [0, " << n << ")";
161
162 if (i > 0)
163 ah_domain_error_if(idx(i - 1) >= idx(i))
164 << "next_combination_indices: indices must be strictly increasing";
165 }
166}
167
168template <class ArrayLike, class Compare>
169[[nodiscard]] inline bool next_permutation_impl(ArrayLike &a, Compare cmp, const bool reset_on_last)
170{
171 const size_t n = a.size();
172 if (n < 2)
173 return false;
174
175 size_t pivot = n;
176 for (size_t i = n - 1; i > 0; --i)
177 if (cmp(a(i - 1), a(i)))
178 {
179 pivot = i - 1;
180 break;
181 }
182
183 if (pivot == n)
184 {
185 if (reset_on_last)
186 reverse_range(a, 0, n - 1);
187 return false;
188 }
189
190 size_t succ = n - 1;
191 while (not cmp(a(pivot), a(succ)))
192 --succ;
193
194 std::swap(a(pivot), a(succ));
195 reverse_range(a, pivot + 1, n - 1);
196 return true;
197}
198
199template <class IndexArray>
200[[nodiscard]] inline bool next_combination_indices_impl(IndexArray &idx, const size_t n,
201 const bool reset_on_last)
202{
204
205 const size_t k = idx.size();
206 if (k == 0)
207 return false;
208
209 for (size_t pos = k; pos > 0; --pos)
210 {
211 const size_t i = pos - 1;
212 const size_t max_here = n - (k - i);
213 if (idx(i) < max_here)
214 {
215 ++idx(i);
216 for (size_t j = i + 1; j < k; ++j)
217 idx(j) = idx(j - 1) + 1;
218 return true;
219 }
220 }
221
222 if (reset_on_last)
223 for (size_t i = 0; i < k; ++i)
224 idx(i) = i;
225
226 return false;
227}
228} // namespace comb_detail
229
231
246template <typename T>
248{
249 if (l.is_empty())
250 return {};
251
252 Array<Array<T>> mat;
253
254 for (auto it = l.get_it(); it.has_curr(); it.next_ne())
255 mat.append(it.get_curr());
256
257 const size_t nrow = mat.size();
258 const size_t ncol = mat[0].size();
259
260 for (size_t i = 1; i < nrow; ++i)
261 assert(mat[i].size() == ncol);
262
264
265 for (size_t j = 0; j < ncol; ++j)
266 {
268 for (size_t i = 0; i < nrow; ++i)
269 row.append(mat(i)(j));
270
271 ret.append(std::move(row));
272 }
273
274 return ret;
275}
276
290template <template <typename> class C, typename T>
291inline void in_place_transpose(C<C<T>> &l)
292
293{
294 C<C<T>> mat;
295
296 const size_t nrow = l.size();
297 if (nrow == 0)
298 return;
299
300 const size_t ncol = l.get_first().size();
301
302 for (size_t i = 0; i < nrow; ++i)
303 assert(l(i).size() == ncol);
304
305 for (size_t j = 0; j < ncol; ++j)
306 {
307 C<T> row;
308 for (size_t i = 0; i < nrow; ++i)
309 row.append(std::move(l(i)(j)));
310 mat.append(std::move(row));
311 }
312 l.swap(mat);
313}
314
328template <typename T>
330{
331 if (l.is_empty())
332 return;
333
335
336 size_t ncol = 0;
337
338 {
341 for (; not lrow.is_empty(); ++ncol)
342 row.append(lrow.remove_head());
343 mat.append(std::move(row));
344 }
345
346 size_t nrow = 1;
347 for (; not l.is_empty(); ++nrow)
348 {
352 size_t col = 0;
353 while (not lrow.is_empty())
354 {
355 row.append(lrow.remove_head());
356 ++col;
357 }
358
359 assert(col == ncol);
360
361 mat.append(std::move(row));
362 }
363
364 assert(l.is_empty());
365
366 for (size_t j = 0; j < ncol; ++j)
367 {
369 for (size_t i = 0; i < nrow; ++i)
370 {
371 Slinknc *node_ptr = mat(i)(j);
372 row.HTList::append(static_cast<Snodenc<T> *>(node_ptr));
373 }
374 l.append(std::move(row));
375 }
376}
377
379
392template <typename T, class Op>
393static inline bool traverse_perm_impl(DynList<T> &sample,
394 DynList<typename DynList<T>::Iterator> &its, Op &op)
395{
396 if (its.is_empty())
397 return op(sample.template maps<T>([](const T &i)
398 {
399 return i;
400 }));
401
402 auto itor = its.remove_first();
403 for (auto it = itor; it.has_curr(); it.next_ne())
404 {
405 auto item = it.get_curr();
406 sample.insert(item);
407 if (not traverse_perm_impl(sample, its, op))
408 {
409 sample.remove_first();
410 its.insert(itor);
411 return false;
412 }
413 sample.remove_first();
414 }
415 its.insert(itor);
416
417 return true;
418}
419
421
439template <typename T, class Op>
440inline bool traverse_perm(const DynList<DynList<T>> &l, Op &op)
441
442{
443 using IT = typename DynList<T>::Iterator;
445
446 { // This block allows getting a constant copy of l and then reverse
447 // it. At the end of block lcpy memory is freed
448 const DynList<IT> lcpy = l.template maps<IT>([](const auto &l)
449 {
450 return l.get_it();
451 });
452 its = lcpy.rev();
453 }
454
456 return traverse_perm_impl(ll, its, op);
457}
458
463template <typename T, class Op>
464inline bool traverse_perm(const DynList<DynList<T>> &l, Op &&op)
465{
466 return traverse_perm(l, op);
467}
468
480template <typename T, class Op>
481inline void for_each_perm(const DynList<DynList<T>> &l, Op &op)
482{
483 traverse_perm(l, [&op](const auto &row)
484 {
485 op(row);
486 return true;
487 });
488}
489
494template <typename T, class Op>
495inline void for_each_perm(const DynList<DynList<T>> &l, Op &&op)
496{
497 return for_each_perm(l, op);
498}
499
510template <typename T>
511[[nodiscard]]
513{
515 for_each_perm(l, [&ret](const DynList<T> &perm)
516 {
517 ret.append(perm);
518 });
519 return ret;
520}
521
534template <typename T>
535[[nodiscard]]
537{
539
541 {
543 combs.insert(std::move(comb));
544 });
545
546 return combs.template maps<DynList<T>>([](const DynList<T> &comb)
547 {
548 return comb;
549 });
550}
551
567template <typename T, typename Tc, class Op = Dft_Fold_Op<Tc, T>>
568[[nodiscard]]
569T fold_perm(const T &init, const DynList<DynList<Tc>> &l, Op &op)
570{
571 T acu = init;
572 traverse_perm(l, [&op, &acu](const auto &l)
573 {
574 acu = op(acu, l);
575 return true;
576 });
577 return acu;
578}
579
584template <typename T, typename Tc, class Op = Dft_Fold_Op<Tc, T>>
585[[nodiscard]]
586T fold_perm(const T &init, const DynList<DynList<Tc>> &l, Op &&op)
587{
588 return fold_perm(init, l, op);
589}
590
602template <typename T>
603[[nodiscard]]
605{
606 size_t count = 1;
607 for (auto it = l.get_it(); it.has_curr(); it.next_ne())
608 {
609 const size_t sz = it.get_curr().size();
610 if (sz == 0)
611 return 0; // Any empty list results in no permutations
612 count *= sz;
613 }
614 return count;
615}
616
629template <typename T, class Pred>
630[[nodiscard]]
632{
633 bool found = false;
634 traverse_perm(l, [&pred, &found](const DynList<T> &perm)
635 {
636 if (pred(perm))
637 {
638 found = true;
639 return false; // stop
640 }
641 return true;
642 });
643 return found;
644}
645
650template <typename T, class Pred>
651[[nodiscard]]
653{
654 return exists_perm(l, pred);
655}
656
669template <typename T, class Pred>
670[[nodiscard]]
672{
673 return traverse_perm(l, pred);
674}
675
680template <typename T, class Pred>
681[[nodiscard]]
683{
684 return all_perm(l, pred);
685}
686
699template <typename T, class Pred>
700[[nodiscard]]
702{
703 return not exists_perm(l, pred);
704}
705
710template <typename T, class Pred>
711[[nodiscard]]
713{
714 return none_perm(l, pred);
715}
716
727template <typename T, class Pred>
728[[nodiscard]]
730{
732 for_each_perm(l, [&ret, &pred](const DynList<T> &perm)
733 {
734 if (pred(perm))
735 ret.append(perm);
736 });
737 return ret;
738}
739
744template <typename T, class Pred>
745[[nodiscard]]
750
762template <typename R, typename T, class Op>
763[[nodiscard]]
765{
767 for_each_perm(l, [&ret, &op](const DynList<T> &perm)
768 {
769 ret.append(op(perm));
770 });
771 return ret;
772}
773
778template <typename R, typename T, class Op>
779[[nodiscard]]
781{
782 return map_perm<R>(l, op);
783}
784
812template <typename T, class Compare = Aleph::less<T>>
813[[nodiscard]] inline bool next_permutation(Array<T> &a, Compare cmp = Compare(),
814 const bool reset_on_last = true)
815{
816 return comb_detail::next_permutation_impl(a, cmp, reset_on_last);
817}
818
820template <typename T, class Compare = Aleph::less<T>>
821[[nodiscard]] inline bool next_permutation(DynArray<T> &a, Compare cmp = Compare(),
822 const bool reset_on_last = true)
823{
824 return comb_detail::next_permutation_impl(a, cmp, reset_on_last);
825}
826
837[[nodiscard]] inline size_t combination_count(size_t n, size_t k)
838{
839 if (k > n)
840 return 0;
841
842 k = std::min(k, n - k);
843 if (k == 0)
844 return 1;
845
846 size_t result = 1;
847 for (size_t i = 1; i <= k; ++i)
848 {
849 size_t num = n - k + i;
850 size_t den = i;
851
852 size_t g = std::gcd(num, den);
853 num /= g;
854 den /= g;
855
856 g = std::gcd(result, den);
857 result /= g;
858 den /= g;
859
860 g = std::gcd(num, den);
861 num /= g;
862 den /= g;
863
865 << "combination_count: internal reduction failure for C(" << n << ", " << k << ")";
866
867 ah_runtime_error_if(result > std::numeric_limits<size_t>::max() / num)
868 << "combination_count: overflow for C(" << n << ", " << k << ")";
869 result *= num;
870 }
871
872 return result;
873}
874
891[[nodiscard]] inline bool next_combination_indices(Array<size_t> &idx, const size_t n,
892 const bool reset_on_last = true)
893{
894 return comb_detail::next_combination_indices_impl(idx, n, reset_on_last);
895}
896
898[[nodiscard]] inline bool next_combination_indices(DynArray<size_t> &idx, const size_t n,
899 const bool reset_on_last = true)
900{
901 return comb_detail::next_combination_indices_impl(idx, n, reset_on_last);
902}
903
906{
907 ah_out_of_range_error_if(k > 64) << "first_combination_mask: k=" << k << " cannot exceed 64";
908
909 if (k == 0)
910 return 0;
911 if (k == 64)
912 return std::numeric_limits<uint64_t>::max();
913 return (static_cast<uint64_t>(1) << k) - 1;
914}
915
932[[nodiscard]] inline bool next_combination_mask(uint64_t &mask, const size_t n,
933 const bool reset_on_last = true)
934{
935 ah_out_of_range_error_if(n > 64) << "next_combination_mask: n=" << n << " cannot exceed 64";
936
937 if (n == 0)
938 {
939 ah_domain_error_if(mask != 0) << "next_combination_mask: for n=0, mask must be 0";
940 return false;
941 }
942
943 const uint64_t domain_mask =
944 n == 64 ? std::numeric_limits<uint64_t>::max() : ((uint64_t(1) << n) - 1);
945
947 << "next_combination_mask: mask has bits outside the low n bits";
948
949 const size_t k = std::popcount(mask);
950 if (k == 0)
951 {
952 if (reset_on_last)
953 mask = 0;
954 return false;
955 }
956
957 const uint64_t c = mask & (~mask + 1); // isolate least significant set bit
958 const uint64_t r = mask + c;
959
960 if (r == 0)
961 {
962 if (reset_on_last)
964 return false;
965 }
966
967 const uint64_t next = (((r ^ mask) >> 2) / c) | r;
968 if (next & ~domain_mask)
969 {
970 if (reset_on_last)
972 return false;
973 }
974
975 mask = next;
976 return true;
977}
978
980template <class ValuesArray, class Op>
981[[nodiscard]] static inline bool for_each_combination_impl(const ValuesArray &values,
982 const size_t k, Op &&op)
983{
984 const size_t n = values.size();
985 ah_domain_error_if(k > n) << "for_each_combination: k=" << k << " cannot exceed n=" << n;
986
987 if (k == 0)
989
991 for (size_t i = 0; i < k; ++i)
992 idx(i) = i;
993
994 while (true)
995 {
997 for (size_t i = 0; i < k; ++i)
998 comb(i) = values(idx(i));
999
1000 if (not op(comb))
1001 return false;
1002
1003 if (not next_combination_indices(idx, n, false))
1004 break;
1005 }
1006
1007 return true;
1008}
1010
1025template <typename T, class Op>
1026[[nodiscard]] inline bool for_each_combination(const Array<T> &values, const size_t k, Op &&op)
1027{
1028 return for_each_combination_impl(values, k, std::forward<Op>(op));
1029}
1030
1032template <typename T, class Op>
1033[[nodiscard]] inline bool for_each_combination(const DynArray<T> &values, const size_t k, Op &&op)
1034{
1035 return for_each_combination_impl(values, k, std::forward<Op>(op));
1036}
1037
1047template <typename T>
1048[[nodiscard]] inline Array<Array<T>> build_combinations(const Array<T> &values, const size_t k)
1049{
1051 (void) for_each_combination(values, k, [&ret](const Array<T> &comb)
1052 {
1053 ret.append(comb);
1054 return true;
1055 });
1056 return ret;
1057}
1058
1060template <typename T>
1061[[nodiscard]] inline Array<Array<T>> build_combinations(const DynArray<T> &values, const size_t k)
1062{
1064 (void) for_each_combination(values, k, [&ret](const Array<T> &comb)
1065 {
1066 ret.append(comb);
1067 return true;
1068 });
1069 return ret;
1070}
1071
1083template <std::unsigned_integral T>
1084[[nodiscard]] constexpr T bin_to_gray(const T n) noexcept
1085{
1086 return n ^ (n >> 1);
1087}
1088
1100template <std::unsigned_integral T>
1101[[nodiscard]] constexpr T gray_to_bin(T g) noexcept
1102{
1103 for (size_t shift = 1; shift < sizeof(T) * 8; shift <<= 1)
1104 g ^= (g >> shift);
1105 return g;
1106}
1107
1121{
1122 ah_domain_error_if(n > 31) << "build_gray_code: n=" << n << " exceeds 31-bit limit for Array";
1123
1124 const size_t count = size_t(1) << n;
1126 ret.reserve(count);
1127 for (size_t i = 0; i < count; ++i)
1128 ret.append(bin_to_gray(static_cast<uint32_t>(i)));
1129
1130 return ret;
1131}
1132} // namespace Aleph
1133
1134#endif // COMB_H
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
Definition ah-errors.H:271
Standard functor implementations and comparison objects.
High-level sorting functions for Aleph containers.
size_t row
Definition ca-c-api.h:115
size_t size_t col
Definition ca-c-api.h:116
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:196
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:365
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:250
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:320
T & append()
Allocate a new entry to the end of array.
Iterator on the items of list.
Definition htlist.H:1420
Doubly-linked list (defined in tpl_dynList.H).
Definition htlist.H:1155
T & insert(const T &item)
Definition htlist.H:1220
T & append(const T &item)
Definition htlist.H:1271
T & get_first() const
Return the first item of the list.
Definition htlist.H:1375
DynList & rev() noexcept
Definition htlist.H:1475
DynList & swap(DynList &l) noexcept
Definition htlist.H:1176
Dynamic set backed by balanced binary search trees with automatic memory management.
bool has_curr() const noexcept
Definition htlist.H:930
Single linked list of nodes.
Definition htlist.H:403
constexpr bool is_empty() const noexcept
Definition htlist.H:419
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1065
Link of a single linked list non-circular and without header node.
Definition htlist.H:95
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
Definition ah-dry.H:228
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4129
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Singly linked list implementations with head-tail access.
Freq_Node * pred
Predecessor node in level-order traversal.
void reverse_range(T *a, size_t lo, size_t hi) noexcept(std::is_nothrow_swappable_v< T >)
Reverse elements in [lo, hi).
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool none_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if no permutation satisfies a predicate.
Definition ah-comb.H:701
DynList< DynList< T > > build_combs(const DynList< DynList< T > > &l)
Build the set of unique combinations from a list of lists.
Definition ah-comb.H:536
bool for_each_combination(const Array< T > &values, const size_t k, Op &&op)
*‍/
Definition ah-comb.H:1026
Array< Array< T > > build_combinations(const Array< T > &values, const size_t k)
Materialize all k-combinations of Array<T>.
Definition ah-comb.H:1048
DynList< R > map_perm(const DynList< DynList< T > > &l, Op &op)
Transform each permutation via a mapping operation.
Definition ah-comb.H:764
size_t size(Node *root) noexcept
bool next_combination_indices(Array< size_t > &idx, const size_t n, const bool reset_on_last=true)
Advance an index-combination [i0 < i1 < ... < i(k-1)] to the next one.
Definition ah-comb.H:891
T fold_perm(const T &init, const DynList< DynList< Tc > > &l, Op &op)
Left-fold over all permutations.
Definition ah-comb.H:569
size_t perm_count(const DynList< DynList< T > > &l)
Count the total number of permutations from a list of lists.
Definition ah-comb.H:604
bool traverse_perm(const DynList< DynList< T > > &l, Op &op)
*‍/
Definition ah-comb.H:440
constexpr T gray_to_bin(T g) noexcept
Convert a Gray code number to its binary representation.
Definition ah-comb.H:1101
bool next_combination_mask(uint64_t &mask, const size_t n, const bool reset_on_last=true)
Advance a fixed-popcount bitmask to the next combination (Gosper hack).
Definition ah-comb.H:932
DynList< DynList< T > > filter_perm(const DynList< DynList< T > > &l, Pred &pred)
Filter permutations that satisfy a predicate.
Definition ah-comb.H:729
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
DynArray< T > sort(const DynArray< T > &a, Cmp &&cmp=Cmp())
Returns a sorted copy of a DynArray.
Definition ahSort.H:234
Array< uint32_t > build_gray_code(const size_t n)
Generate the sequence of n-bit Gray codes.
Definition ah-comb.H:1120
bool next_permutation(Array< T > &a, Compare cmp=Compare(), const bool reset_on_last=true)
Compute the next lexicographic permutation of an Array.
Definition ah-comb.H:813
void for_each_perm(const DynList< DynList< T > > &l, Op &op)
Apply a procedure to every permutation produced by traverse_perm.
Definition ah-comb.H:481
DynList< DynList< T > > transpose(const DynList< DynList< T > > &l)
*‍/
Definition ah-comb.H:247
uint64_t first_combination_mask(const size_t k)
Build the first k-of-64 combination mask (k low bits set).
Definition ah-comb.H:905
size_t combination_count(size_t n, size_t k)
Compute n choose k with overflow checks.
Definition ah-comb.H:837
DynList< DynList< T > > build_perms(const DynList< DynList< T > > &l)
Materialize all permutations from a list of lists.
Definition ah-comb.H:512
void in_place_transpose(C< C< T > > &l)
In-place transpose of a rectangular matrix stored as a nested container.
Definition ah-comb.H:291
bool exists_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if any permutation satisfies a predicate.
Definition ah-comb.H:631
constexpr T bin_to_gray(const T n) noexcept
Convert a binary number to its Gray code representation.
Definition ah-comb.H:1084
bool all_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if all permutations satisfy a predicate.
Definition ah-comb.H:671
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:171
static std::atomic< bool > init
Definition hash-fct.C:54
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
AVL binary search tree with nodes without a virtual destructor.
Definition tpl_avl.H:743
static int * k
gsl_rng * r
Dynamic array container with automatic resizing.
Lazy and scalable dynamic array implementation.
Dynamic doubly linked list implementation.
Dynamic set implementations based on balanced binary search trees.
DynList< int > l