Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah_comb_generators_test.cc
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 https://github.com/lrleon/Aleph-w
6
7 This file is part of Aleph-w library
8
9 Copyright (c) 2002-2026 Leandro Rabindranath Leon
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in all
19 copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 SOFTWARE.
28*/
29
42#include <algorithm>
43#include <bit>
44#include <set>
45#include <stdexcept>
46#include <vector>
47
48#include <gtest/gtest.h>
49
50#include <ah-comb-generators.H>
51
52using namespace Aleph;
53
54namespace
55{
56template <typename T>
57std::vector<T> vec_of(const Array<T> &a)
58{
59 return to_stdvector(a);
60}
61} // namespace
62
64{
65 int count = 0;
66 for (const Array<int> &p : lazy_permutations(Array<int>{}))
67 { (void) p; ++count; }
68 EXPECT_EQ(count, 1); // the empty sequence has exactly one permutation
69
70 std::vector<std::vector<int>> seen;
71 for (const Array<int> &p : lazy_permutations(Array<int>{7}))
72 seen.push_back(vec_of(p));
73 EXPECT_EQ(seen, (std::vector<std::vector<int>>{{7}}));
74}
75
77{
78 std::vector<int> ref = {1, 2, 3, 4};
79 size_t eager_count = 0;
80 do
82 while (std::next_permutation(ref.begin(), ref.end()));
83
84 size_t lazy_count = 0;
85 for (const Array<int> &p : lazy_permutations(Array<int>{1, 2, 3, 4}))
86 { (void) p; ++lazy_count; }
87
88 EXPECT_EQ(eager_count, 24u); // 4!
90}
91
93{
94 std::vector<std::vector<int>> eager;
95 std::vector<int> ref = {1, 2, 3};
96 std::sort(ref.begin(), ref.end());
97 do
98 eager.push_back(ref);
99 while (std::next_permutation(ref.begin(), ref.end()));
100
101 std::vector<std::vector<int>> lazy;
102 for (const Array<int> &p : lazy_permutations(Array<int>{3, 1, 2}))
103 lazy.push_back(vec_of(p)); // must copy: the yielded array is reused
104
105 EXPECT_EQ(lazy, eager); // both lexicographically ordered from the sorted start
106}
107
109{
110 std::vector<int> ref = {1, 1, 2};
111 std::sort(ref.begin(), ref.end());
112 size_t eager_count = 0;
113 do
114 ++eager_count;
115 while (std::next_permutation(ref.begin(), ref.end()));
116
117 size_t lazy_count = 0;
118 for (const Array<int> &p : lazy_permutations(Array<int>{2, 1, 1}))
119 { (void) p; ++lazy_count; }
120
121 EXPECT_EQ(eager_count, 3u); // 3!/2! = 3, not 6
123}
124
126{
127 std::set<std::vector<int>> seen;
128 for (const Array<int> &p : lazy_permutations(Array<int>{1, 2, 3, 4}))
129 seen.insert(vec_of(p)); // copy before the buffer advances
130 EXPECT_EQ(seen.size(), 24u);
131}
132
134{
135 int count = 0;
136 for (const Array<int> &p : lazy_permutations(Array<int>{1, 2, 3, 4, 5}))
137 {
138 (void) p;
139 if (++count == 3)
140 break;
141 }
142 EXPECT_EQ(count, 3); // stopped well before all 120 permutations
143}
144
146{
147 std::vector<std::vector<int>> seen;
148 for (const Array<int> &c : lazy_combinations(Array<int>{1, 2, 3}, 0))
149 seen.push_back(vec_of(c));
150 ASSERT_EQ(seen.size(), 1u);
151 EXPECT_TRUE(seen[0].empty());
152}
153
155{
156 std::vector<std::vector<int>> seen;
157 for (const Array<int> &c : lazy_combinations(Array<int>{1, 2, 3}, 3))
158 seen.push_back(vec_of(c));
159 ASSERT_EQ(seen.size(), 1u);
160 EXPECT_EQ(seen[0], (std::vector<int>{1, 2, 3}));
161}
162
164{
166 {
167 for (const Array<int> &c : lazy_combinations(Array<int>{1, 2}, 3))
168 (void) c;
169 },
170 std::domain_error);
171}
172
174{
175 const Array<int> a{1, 2, 3, 4, 5, 6};
176 for (size_t k = 0; k <= a.size(); ++k)
177 {
178 size_t count = 0;
179 for (const Array<int> &c : lazy_combinations(a, k))
180 { (void) c; ++count; }
181 EXPECT_EQ(count, combination_count(a.size(), k)) << "k=" << k;
182 }
183}
184
186{
187 const Array<int> a{10, 20, 30, 40, 50};
188 const size_t n = a.size();
189 const size_t k = 3;
190
191 // Brute-force reference: every n-bit mask with exactly k bits set,
192 // in ascending numeric order, collects the values at the set positions
193 // in index order — the same convention lazy_combinations documents.
194 std::vector<std::vector<int>> expected;
195 for (uint64_t mask = 0; mask < (1u << n); ++mask)
196 {
197 if (static_cast<size_t>(std::popcount(mask)) != k)
198 continue;
199 std::vector<int> combo;
200 for (size_t i = 0; i < n; ++i)
201 if (mask & (1u << i))
202 combo.push_back(a[i]);
203 expected.push_back(combo);
204 }
205 std::sort(expected.begin(), expected.end());
206
207 std::vector<std::vector<int>> got;
208 for (const Array<int> &c : lazy_combinations(a, k))
209 got.push_back(vec_of(c));
210 std::sort(got.begin(), got.end());
211
213}
214
216{
217 const Array<int> a{1, 2, 3, 4, 5};
218 std::set<std::vector<int>> seen;
219 for (const Array<int> &c : lazy_combinations(a, 2))
220 seen.insert(vec_of(c));
221 EXPECT_EQ(seen.size(), combination_count(5, 2));
222}
223
225{
226 const Array<char> a{'a', 'b', 'c'};
227 std::vector<std::vector<char>> seen;
228 for (const Array<char> &c : lazy_combinations(a, 2))
229 seen.push_back(vec_of(c));
230 EXPECT_EQ(seen, (std::vector<std::vector<char>>{{'a', 'b'}, {'a', 'c'}, {'b', 'c'}}));
231}
232
234{
236
237 auto it = gen.begin();
238 ASSERT_NE(it, gen.end());
239 Array<int> first = *it;
240
241 ++it;
242 ASSERT_NE(it, gen.end());
243 Array<int> second = *it;
244
245 EXPECT_EQ(vec_of(first), (std::vector<int>{1, 2}));
246 EXPECT_EQ(vec_of(second), (std::vector<int>{1, 3}));
247}
Lazy (coroutine-based) permutation and combination enumeration.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
Definition tpl_array.H:365
T & insert(const T &data)
insert a copy of data at the beginning of the array.
Definition tpl_array.H:286
Lazy, single-pass sequence of T values produced by a coroutine.
iterator begin() &
Begin iterating: resumes the coroutine to its first co_yield.
Minimal std::expected-style result type for C++20.
#define TEST(name)
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
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
Aleph::Generator< Array< T > > lazy_permutations(Array< T > a, Compare cmp=Compare())
Lazily enumerate all permutations of a, in lexicographic order.
size_t combination_count(size_t n, size_t k)
Compute n choose k with overflow checks.
Definition ah-comb.H:837
Aleph::Generator< Array< T > > lazy_combinations(Array< T > a, size_t k)
Lazily enumerate all k-element combinations of a's elements.
std::vector< typename Container::Item_Type > to_stdvector(const Container &c)
Definition tpl_array.H:630
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
static int * k