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
60# include <algorithm>
61# include <bit>
62# include <cstdint>
63# include <limits>
64# include <numeric>
65
66# include <htlist.H>
67# include <tpl_dynDlist.H>
68# include <tpl_dynArray.H>
69# include <tpl_array.H>
70# include <tpl_dynSetTree.H>
71# include <ahFunction.H>
72# include <ahSort.H>
73
74namespace Aleph
75{
77 namespace comb_detail
78 {
92 template <typename T>
93 [[nodiscard]] inline
95 {
96 if (l.is_empty())
97 return {};
98
100
101 size_t ncol = 0; {
102 const HTList & lrow = l.get_first();
103 Array<Snodenc<T> *> row;
104 for (HTList::Iterator it(lrow); it.has_curr(); it.next_ne(), ++ncol)
105 row.append(static_cast<Snodenc<T> *>(it.get_curr()));
106 mat.append(std::move(row));
107 }
108
109 size_t nrow = 1;
110 for (auto row_it = l.get_it(1); row_it.has_curr(); row_it.next_ne(), ++nrow)
111 {
112 const HTList & lrow = row_it.get_curr();
113 Array<Snodenc<T> *> row;
114 row.reserve(ncol);
115 size_t col = 0;
116 for (HTList::Iterator it(lrow); it.has_curr(); it.next_ne(), ++col)
117 row.append(static_cast<Snodenc<T> *>(it.get_curr()));
118
119 assert(col == ncol);
120
121 mat.append(std::move(row));
122 }
123
125 for (size_t j = 0; j < ncol; ++j)
126 {
127 DynList<T> row;
128 for (size_t i = 0; i < nrow; ++i)
129 row.append(mat(i)(j)->get_data());
130
131 ret.append(std::move(row));
132 }
133
134 return ret;
135 }
136
137 template <class ArrayLike>
138 inline void reverse_range(ArrayLike & a,
139 size_t left, size_t right) noexcept
140 {
141 while (left < right)
142 {
143 std::swap(a(left), a(right));
144 ++left;
145 --right;
146 }
147 }
148
149 template <class IndexArray>
150 inline void validate_combination_indices(const IndexArray & idx,
151 const size_t n)
152 {
153 const size_t k = idx.size();
155 << "next_combination_indices: k=" << k << " cannot exceed n=" << n;
156
157 for (size_t i = 0; i < k; ++i)
158 {
159 ah_out_of_range_error_if(idx(i) >= n)
160 << "next_combination_indices: index " << idx(i)
161 << " at position " << i << " is outside [0, " << n << ")";
162
163 if (i > 0)
164 ah_domain_error_if(idx(i - 1) >= idx(i))
165 << "next_combination_indices: indices must be strictly increasing";
166 }
167 }
168
169 template <class ArrayLike, class Compare>
170 [[nodiscard]] inline bool next_permutation_impl(ArrayLike & a,
171 Compare cmp,
172 const bool reset_on_last)
173 {
174 const size_t n = a.size();
175 if (n < 2)
176 return false;
177
178 size_t pivot = n;
179 for (size_t i = n - 1; i > 0; --i)
180 if (cmp(a(i - 1), a(i)))
181 {
182 pivot = i - 1;
183 break;
184 }
185
186 if (pivot == n)
187 {
188 if (reset_on_last)
189 reverse_range(a, 0, n - 1);
190 return false;
191 }
192
193 size_t succ = n - 1;
194 while (not cmp(a(pivot), a(succ)))
195 --succ;
196
197 std::swap(a(pivot), a(succ));
198 reverse_range(a, pivot + 1, n - 1);
199 return true;
200 }
201
202 template <class IndexArray>
204 const size_t n,
205 const bool reset_on_last)
206 {
208
209 const size_t k = idx.size();
210 if (k == 0)
211 return false;
212
213 for (size_t pos = k; pos > 0; --pos)
214 {
215 const size_t i = pos - 1;
216 const size_t max_here = n - (k - i);
217 if (idx(i) < max_here)
218 {
219 ++idx(i);
220 for (size_t j = i + 1; j < k; ++j)
221 idx(j) = idx(j - 1) + 1;
222 return true;
223 }
224 }
225
226 if (reset_on_last)
227 for (size_t i = 0; i < k; ++i)
228 idx(i) = i;
229
230 return false;
231 }
232 } // namespace comb_detail
234
248 template <typename T>
249 [[nodiscard]] inline
251 {
252 if (l.is_empty())
253 return {};
254
255 Array<Array<T>> mat;
256
257 for (auto it = l.get_it(); it.has_curr(); it.next_ne())
258 mat.append(it.get_curr());
259
260 const size_t nrow = mat.size();
261 const size_t ncol = mat[0].size();
262
263 for (size_t i = 1; i < nrow; ++i)
264 assert(mat[i].size() == ncol);
265
267
268 for (size_t j = 0; j < ncol; ++j)
269 {
270 DynList<T> row;
271 for (size_t i = 0; i < nrow; ++i)
272 row.append(mat(i)(j));
273
274 ret.append(std::move(row));
275 }
276
277 return ret;
278 }
279
280
299 template <template <typename> class C, typename T>
300 inline
302 {
303 C<C<T>> mat;
304
305 const size_t nrow = l.size();
306 if (nrow == 0)
307 return;
308
309 const size_t ncol = l.get_first().size();
310
311 for (size_t i = 0; i < nrow; ++i)
312 assert(l(i).size() == ncol);
313
314 for (size_t j = 0; j < ncol; ++j)
315 {
316 C<T> row;
317 for (size_t i = 0; i < nrow; ++i)
318 row.append(std::move(l(i)(j)));
319 mat.append(std::move(row));
320 }
321 l.swap(mat);
322 }
323
337 template <typename T>
338 inline
340 {
341 if (l.is_empty())
342 return;
343
345
346 size_t ncol = 0; {
349 for (; not lrow.is_empty(); ++ncol)
350 row.append(lrow.remove_head());
351 mat.append(std::move(row));
352 }
353
354 size_t nrow = 1;
355 for (; not l.is_empty(); ++nrow)
356 {
359 row.reserve(ncol);
360 size_t col = 0;
361 while (not lrow.is_empty())
362 {
363 row.append(lrow.remove_head());
364 ++col;
365 }
366
367 assert(col == ncol);
368
369 mat.append(std::move(row));
370 }
371
372 assert(l.is_empty());
373
374 for (size_t j = 0; j < ncol; ++j)
375 {
376 DynList<T> row;
377 for (size_t i = 0; i < nrow; ++i)
378 {
379 Slinknc *node_ptr = mat(i)(j);
380 row.HTList::append(static_cast<Snodenc<T> *>(node_ptr));
381 }
382 l.append(std::move(row));
383 }
384 }
385
387
400 template <typename T, class Op>
401 static inline
402 bool traverse_perm_impl(DynList<T> & sample,
403 DynList<typename DynList<T>::Iterator> & its, Op & op)
404 {
405 if (its.is_empty())
406 return op(sample.template maps<T>([](const T & i) { return i; }));
407
408 auto itor = its.remove_first();
409 for (auto it = itor; it.has_curr(); it.next_ne())
410 {
411 auto item = it.get_curr();
412 sample.insert(item);
413 if (not traverse_perm_impl(sample, its, op))
414 {
415 sample.remove_first();
416 its.insert(itor);
417 return false;
418 }
419 sample.remove_first();
420 }
421 its.insert(itor);
422
423 return true;
424 }
425
427
463 template <typename T, class Op>
464 inline
465 bool traverse_perm(const DynList<DynList<T>> & l, Op & op)
466 {
467 using IT = typename DynList<T>::Iterator;
469
470 { // This block allows getting a constant copy of l and then reverse
471 // it. At the end of block lcpy memory is freed
472 const DynList<IT> lcpy =
473 l.template maps<IT>([](const auto & l) { return l.get_it(); });
474 its = lcpy.rev();
475 }
476
478 return traverse_perm_impl(ll, its, op);
479 }
480
485 template <typename T, class Op>
486 inline
487 bool traverse_perm(const DynList<DynList<T>> & l, Op && op)
488 {
489 return traverse_perm(l, op);
490 }
491
503 template <typename T, class Op>
504 inline
505 void for_each_perm(const DynList<DynList<T>> & l, Op & op)
506 {
507 traverse_perm(l, [&op](const auto & row)
508 {
509 op(row);
510 return true;
511 });
512 }
513
518 template <typename T, class Op>
519 inline
520 void for_each_perm(const DynList<DynList<T>> & l, Op && op)
521 {
522 return for_each_perm(l, op);
523 }
524
535 template <typename T>
536 [[nodiscard]]
538 {
540 for_each_perm(l, [&ret](const DynList<T> & perm) { ret.append(perm); });
541 return ret;
542 }
543
556 template <typename T>
557 [[nodiscard]]
559 {
561
562 for_each_perm(l, [&combs](const DynList<T> & perm)
563 {
565 combs.insert(std::move(comb));
566 });
567
568 return combs.
569 template maps<DynList<T>>([](const DynList<T> & comb) { return comb; });
570 }
571
587 template <typename T, typename Tc, class Op = Dft_Fold_Op<Tc, T>>
588 [[nodiscard]]
589 T fold_perm(const T & init, const DynList<DynList<Tc>> & l, Op & op)
590 {
591 T acu = init;
592 traverse_perm(l, [&op, &acu](const auto & l)
593 {
594 acu = op(acu, l);
595 return true;
596 });
597 return acu;
598 }
599
604 template <typename T, typename Tc, class Op = Dft_Fold_Op<Tc, T>>
605 [[nodiscard]]
606 T fold_perm(const T & init, const DynList<DynList<Tc>> & l, Op && op)
607 {
608 return fold_perm(init, l, op);
609 }
610
622 template <typename T>
623 [[nodiscard]]
625 {
626 size_t count = 1;
627 for (auto it = l.get_it(); it.has_curr(); it.next_ne())
628 {
629 const size_t sz = it.get_curr().size();
630 if (sz == 0)
631 return 0; // Any empty list results in no permutations
632 count *= sz;
633 }
634 return count;
635 }
636
649 template <typename T, class Pred>
650 [[nodiscard]]
652 {
653 bool found = false;
654 traverse_perm(l, [&pred, &found](const DynList<T> & perm)
655 {
656 if (pred(perm))
657 {
658 found = true;
659 return false; // stop
660 }
661 return true;
662 });
663 return found;
664 }
665
670 template <typename T, class Pred>
671 [[nodiscard]]
673 {
674 return exists_perm(l, pred);
675 }
676
689 template <typename T, class Pred>
690 [[nodiscard]]
692 {
693 return traverse_perm(l, pred);
694 }
695
700 template <typename T, class Pred>
701 [[nodiscard]]
703 {
704 return all_perm(l, pred);
705 }
706
719 template <typename T, class Pred>
720 [[nodiscard]]
722 {
723 return not exists_perm(l, pred);
724 }
725
730 template <typename T, class Pred>
731 [[nodiscard]]
733 {
734 return none_perm(l, pred);
735 }
736
747 template <typename T, class Pred>
748 [[nodiscard]]
750 {
752 for_each_perm(l, [&ret, &pred](const DynList<T> & perm)
753 {
754 if (pred(perm))
755 ret.append(perm);
756 });
757 return ret;
758 }
759
764 template <typename T, class Pred>
765 [[nodiscard]]
767 {
768 return filter_perm(l, pred);
769 }
770
782 template <typename R, typename T, class Op>
783 [[nodiscard]]
785 {
787 for_each_perm(l, [&ret, &op](const DynList<T> & perm)
788 {
789 ret.append(op(perm));
790 });
791 return ret;
792 }
793
798 template <typename R, typename T, class Op>
799 [[nodiscard]]
801 {
802 return map_perm<R>(l, op);
803 }
804
832 template <typename T, class Compare = Aleph::less<T>>
833 [[nodiscard]] inline bool
835 Compare cmp = Compare(),
836 const bool reset_on_last = true)
837 {
838 return comb_detail::next_permutation_impl(a, cmp, reset_on_last);
839 }
840
842 template <typename T, class Compare = Aleph::less<T>>
843 [[nodiscard]] inline bool
845 Compare cmp = Compare(),
846 const bool reset_on_last = true)
847 {
848 return comb_detail::next_permutation_impl(a, cmp, reset_on_last);
849 }
850
861 [[nodiscard]] inline size_t combination_count(size_t n, size_t k)
862 {
863 if (k > n)
864 return 0;
865
866 k = std::min(k, n - k);
867 if (k == 0)
868 return 1;
869
870 size_t result = 1;
871 for (size_t i = 1; i <= k; ++i)
872 {
873 size_t num = n - k + i;
874 size_t den = i;
875
876 size_t g = std::gcd(num, den);
877 num /= g;
878 den /= g;
879
880 g = std::gcd(result, den);
881 result /= g;
882 den /= g;
883
884 g = std::gcd(num, den);
885 num /= g;
886 den /= g;
887
889 << "combination_count: internal reduction failure for C("
890 << n << ", " << k << ")";
891
892 ah_runtime_error_if(result > std::numeric_limits<size_t>::max() / num)
893 << "combination_count: overflow for C(" << n << ", " << k << ")";
894 result *= num;
895 }
896
897 return result;
898 }
899
916 [[nodiscard]] inline bool
918 const size_t n,
919 const bool reset_on_last = true)
920 {
921 return comb_detail::next_combination_indices_impl(idx, n, reset_on_last);
922 }
923
925 [[nodiscard]] inline bool
927 const size_t n,
928 const bool reset_on_last = true)
929 {
930 return comb_detail::next_combination_indices_impl(idx, n, reset_on_last);
931 }
932
935 {
937 << "first_combination_mask: k=" << k << " cannot exceed 64";
938
939 if (k == 0)
940 return 0;
941 if (k == 64)
942 return std::numeric_limits<uint64_t>::max();
943 return (uint64_t(1) << k) - 1;
944 }
945
962 [[nodiscard]] inline bool
964 const size_t n,
965 const bool reset_on_last = true)
966 {
968 << "next_combination_mask: n=" << n << " cannot exceed 64";
969
970 if (n == 0)
971 {
972 ah_domain_error_if(mask != 0)
973 << "next_combination_mask: for n=0, mask must be 0";
974 return false;
975 }
976
977 const uint64_t domain_mask =
978 n == 64 ? std::numeric_limits<uint64_t>::max() : ((uint64_t(1) << n) - 1);
979
981 << "next_combination_mask: mask has bits outside the low n bits";
982
983 const size_t k = std::popcount(mask);
984 if (k == 0)
985 {
986 if (reset_on_last)
987 mask = 0;
988 return false;
989 }
990
991 const uint64_t c = mask & (~mask + 1); // isolate least significant set bit
992 const uint64_t r = mask + c;
993
994 if (r == 0)
995 {
996 if (reset_on_last)
998 return false;
999 }
1000
1001 const uint64_t next = (((r ^ mask) >> 2) / c) | r;
1002 if (next & ~domain_mask)
1003 {
1004 if (reset_on_last)
1005 mask = first_combination_mask(k);
1006 return false;
1007 }
1008
1009 mask = next;
1010 return true;
1011 }
1012
1014 template <class ValuesArray, class Op>
1015 [[nodiscard]] static inline bool
1017 const size_t k,
1018 Op && op)
1019 {
1020 const size_t n = values.size();
1022 << "for_each_combination: k=" << k << " cannot exceed n=" << n;
1023
1024 if (k == 0)
1026
1028 for (size_t i = 0; i < k; ++i)
1029 idx(i) = i;
1030
1031 while (true)
1032 {
1034 for (size_t i = 0; i < k; ++i)
1035 comb(i) = values(idx(i));
1036
1037 if (not op(comb))
1038 return false;
1039
1040 if (not next_combination_indices(idx, n, false))
1041 break;
1042 }
1043
1044 return true;
1045 }
1047
1062 template <typename T, class Op>
1063 [[nodiscard]] inline bool
1064 for_each_combination(const Array<T> & values, const size_t k, Op && op)
1065 {
1066 return for_each_combination_impl(values, k, std::forward<Op>(op));
1067 }
1068
1070 template <typename T, class Op>
1071 [[nodiscard]] inline bool
1072 for_each_combination(const DynArray<T> & values, const size_t k, Op && op)
1073 {
1074 return for_each_combination_impl(values, k, std::forward<Op>(op));
1075 }
1076
1086 template <typename T>
1087 [[nodiscard]] inline Array<Array<T>>
1088 build_combinations(const Array<T> & values, const size_t k)
1089 {
1091 (void) for_each_combination(values, k, [&ret](const Array<T> & comb)
1092 {
1093 ret.append(comb);
1094 return true;
1095 });
1096 return ret;
1097 }
1098
1100 template <typename T>
1101 [[nodiscard]] inline Array<Array<T>>
1102 build_combinations(const DynArray<T> & values, const size_t k)
1103 {
1105 (void) for_each_combination(values, k, [&ret](const Array<T> & comb)
1106 {
1107 ret.append(comb);
1108 return true;
1109 });
1110 return ret;
1111 }
1112
1113
1125 template <std::unsigned_integral T>
1126 [[nodiscard]] constexpr T bin_to_gray(const T n) noexcept
1127 {
1128 return n ^ (n >> 1);
1129 }
1130
1131
1143 template <std::unsigned_integral T>
1144 [[nodiscard]] constexpr T gray_to_bin(T g) noexcept
1145 {
1146 for (size_t shift = 1; shift < sizeof(T) * 8; shift <<= 1)
1147 g ^= (g >> shift);
1148 return g;
1149 }
1150
1151
1164 [[nodiscard]] inline Array<uint32_t> build_gray_code(const size_t n)
1165 {
1166 ah_domain_error_if(n > 31)
1167 << "build_gray_code: n=" << n << " exceeds 31-bit limit for Array";
1168
1169 const size_t count = size_t(1) << n;
1171 ret.reserve(count);
1172 for (size_t i = 0; i < count; ++i)
1173 ret.append(bin_to_gray(static_cast<uint32_t>(i)));
1174
1175 return ret;
1176 }
1177}
1178
1179# endif // COMB_H
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_runtime_error_if(C)
Throws std::runtime_error if condition holds.
Definition ah-errors.H:266
Standard functor implementations and comparison objects.
High-level sorting functions for Aleph containers.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:351
T & append(const T &data)
Append a copy of data
Definition tpl_array.H:245
void reserve(size_t cap)
Reserves cap cells into the array.
Definition tpl_array.H:315
T & append()
Allocate a new entry to the end of array.
Iterator on the items of list.
Definition htlist.H:1420
Dynamic singly linked list with functional programming support.
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:222
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.
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:721
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:558
bool for_each_combination(const Array< T > &values, const size_t k, Op &&op)
Enumerate all k-combinations of an Array<T> in lexicographic index order.
Definition ah-comb.H:1064
Array< Array< T > > build_combinations(const Array< T > &values, const size_t k)
Materialize all k-combinations of Array<T>.
Definition ah-comb.H:1088
DynList< R > map_perm(const DynList< DynList< T > > &l, Op &op)
Transform each permutation via a mapping operation.
Definition ah-comb.H:784
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:917
T fold_perm(const T &init, const DynList< DynList< Tc > > &l, Op &op)
Left-fold over all permutations.
Definition ah-comb.H:589
size_t perm_count(const DynList< DynList< T > > &l)
Count the total number of permutations from a list of lists.
Definition ah-comb.H:624
bool traverse_perm(const DynList< DynList< T > > &l, Op &op)
Traverse all the possible permutations that can be done of a list of lists and on each permutation pe...
Definition ah-comb.H:465
constexpr T gray_to_bin(T g) noexcept
Convert a Gray code number to its binary representation.
Definition ah-comb.H:1144
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:963
DynList< DynList< T > > filter_perm(const DynList< DynList< T > > &l, Pred &pred)
Filter permutations that satisfy a predicate.
Definition ah-comb.H:749
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
DynArray< T > sort(const DynArray< T > &a, Cmp &&cmp=Cmp())
Returns a sorted copy of a DynArray.
Definition ahSort.H:227
Array< uint32_t > build_gray_code(const size_t n)
Generate the sequence of n-bit Gray codes.
Definition ah-comb.H:1164
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:834
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:505
DynList< DynList< T > > transpose(const DynList< DynList< T > > &l)
Transpose a matrix represented as a list of lists.
Definition ah-comb.H:250
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:934
size_t combination_count(size_t n, size_t k)
Compute n choose k with overflow checks.
Definition ah-comb.H:861
DynList< DynList< T > > build_perms(const DynList< DynList< T > > &l)
Materialize all permutations from a list of lists.
Definition ah-comb.H:537
void in_place_transpose(C< C< T > > &l)
In-place transpose of a rectangular matrix stored as a nested container.
Definition ah-comb.H:301
bool exists_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if any permutation satisfies a predicate.
Definition ah-comb.H:651
constexpr T bin_to_gray(const T n) noexcept
Convert a binary number to its Gray code representation.
Definition ah-comb.H:1126
bool all_perm(const DynList< DynList< T > > &l, Pred &pred)
Check if all permutations satisfy a predicate.
Definition ah-comb.H:691
void next()
Advance all underlying iterators (bounds-checked).
Definition ah-zip.H:171
static std::atomic< bool > init
Definition hash-fct.C:53
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 virtual destructor.
Definition tpl_avl.H:737
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