1 // Copyright 2015, Tobias Hermann and the FunctionalPlus contributors.
2 // https://github.com/Dobiasd/FunctionalPlus
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt or copy at
5 //  http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <doctest/doctest.h>
8 #include <fplus/fplus.hpp>
9 #include <vector>
10 #include <deque>
11 
12 namespace {
__anone8399bc00202(int x) 13     auto squareLambda = [](int x) -> int { return x*x; };
__anone8399bc00302(int x)14     auto is_even_int = [](int x){ return x % 2 == 0; };
__anone8399bc00402(std::size_t x)15     auto is_even_size_t = [](std::size_t x){ return x % 2 == 0; };
__anone8399bc00502(int x)16     auto is_odd_int = [](int x){ return x % 2 != 0; };
17     typedef std::pair<int, int> IntPair;
18     typedef std::vector<IntPair> IntPairs;
19     typedef std::vector<int> IntVector;
20     typedef std::vector<IntVector> IntVectors;
21     typedef std::vector<bool> BoolVector;
22     typedef std::vector<std::size_t> IdxVector;
23     typedef std::array<int, 5> IntArray5;
24     typedef std::deque<int> IntDeque;
25     IntVector xs = {1,2,2,3,2};
26     IntArray5 xs_arr = {{1,2,2,3,2}};
27     IntDeque  xs_deque = {1,2,2,3,2};
28     IntVector xs_reverse = {2,3,2,2,1};
29     IntVector xsSorted = {1,2,2,2,3};
30     IntVector xs2Times = {1,2,2,3,2,1,2,2,3,2};
31     typedef std::list<int> IntList;
32     typedef std::vector<IntList> IntLists;
33     IntLists intLists = { { 1 },{ 2, 2 },{ 3 },{ 2 } };
34     IntList intList = { 1,2,2,3,2 };
35     IntList intListSorted = { 1,2,2,2,3 };
__anone8399bc00602(int x) 36     auto int_mod_10 = [](int x) -> int { return x % 10; };
37     auto is2 = fplus::is_equal_to(2);
38     auto is3 = fplus::is_equal_to(3);
39     auto is4 = fplus::is_equal_to(4);
__anone8399bc00702(int a, int b) 40     auto abs_diff_less_or_equal_3 = [](int a, int b) { return fplus::abs(b - a) <= 3; };
41     typedef std::vector<std::string> string_vec;
42     IntVector vec0123({0,1,2,3});
43     IntList list0123({0,1,2,3});
44     std::string ABC_("ABC");
45     std::string XY("XY");
46     std::string ABCD("ABCD");
47 
48     struct ExplicitFromIntStruct
49     {
ExplicitFromIntStruct__anone8399bc00111::ExplicitFromIntStruct50         explicit ExplicitFromIntStruct(int x) : x_(x) {}
51         int x_;
52     };
operator ==(const ExplicitFromIntStruct & lhs,const ExplicitFromIntStruct & rhs)53     bool operator == (const ExplicitFromIntStruct &lhs, const ExplicitFromIntStruct & rhs) { return lhs.x_ == rhs.x_; }
54 }
55 
56 TEST_CASE("container_common_test - group")
57 {
58     using namespace fplus;
59     typedef std::vector<std::pair<int, std::vector<int>>> LabeledGroups;
60     REQUIRE_EQ(group(intList), intLists);
61     REQUIRE_EQ(group(xs), IntVectors({IntVector({1}),IntVector({2,2}),IntVector({3}),IntVector({2})}));
__anone8399bc00802(auto x) 62     REQUIRE_EQ(group_on([](auto x) { return x % 10; }, IntVector({12,22,34})), IntVectors({IntVector({12,22}),IntVector({34})}));
63     REQUIRE_EQ(group_on_labeled(int_mod_10, IntVector({12,22,34})), LabeledGroups({{2, IntVector({12,22})}, {4, IntVector({34})}}));
64     REQUIRE_EQ(group_on_labeled(int_mod_10, IntVector({12,22,34})), LabeledGroups({{2, IntVector({12,22})}, {4, IntVector({34})}}));
65     REQUIRE_EQ(group_globally(xs), IntVectors({IntVector({1}),IntVector({2,2,2}),IntVector({3})}));
66     REQUIRE_EQ(group_globally_on(int_mod_10, IntVector({12,34,22})), IntVectors({IntVector({12,22}),IntVector({34})}));
67     REQUIRE_EQ(group_globally_on_labeled(int_mod_10, IntVector({12,34,22})), LabeledGroups({{2, IntVector({12,22})}, {4, IntVector({34})}}));
68     REQUIRE_EQ(group_by(abs_diff_less_or_equal_3, IntVector({2,3,6,4,22,21,8,5})), IntVectors({{2,3,6,4},{22,21},{8,5}}));
69 }
70 
71 TEST_CASE("container_common_test - separate")
72 {
73     using namespace fplus;
74     IntVector values = {1, 2, 2, 3, 3, 4, 4, 4};
75     REQUIRE_EQ(separate(values), IntVectors({IntVector({1, 2, 3, 4}),IntVector({2, 3, 4}),IntVector({4})}));
76     REQUIRE_EQ(separate_on(int_mod_10, IntVector({12,22,34})), IntVectors({IntVector({12,34}),IntVector({22})}));
77 }
78 
79 TEST_CASE("container_common_test - singleton_seq")
80 {
81     using namespace fplus;
82     REQUIRE_EQ(singleton_seq(3), IntVector({3}));
83 }
84 
85 TEST_CASE("container_common_test - filter")
86 {
87     using namespace fplus;
88     REQUIRE_EQ(keep_if(is_even_int, xs), IntVector({2,2,2}));
89     REQUIRE_EQ(drop_if(is_even_int, xs), IntVector({1,3}));
90     REQUIRE_EQ(keep_if(is_even_int, intList), IntList({ 2,2,2 }));
91     REQUIRE_EQ(drop_if(is_even_int, intList), IntList({ 1,3 }));
92     REQUIRE_EQ(without(2, intList), IntList({ 1,3 }));
93     REQUIRE_EQ(without_any(IntVector({2,3}), intList), IntList({ 1 }));
94     auto sumis_even = [&](std::size_t x, int y)
__anone8399bc00902(std::size_t x, int y) 95     {
96         return is_even_int(static_cast<int>(x) + y);
97     };
98     REQUIRE_EQ(keep_by_idx(is_even_size_t, xs), IntVector({ 1,2,2 }));
99     REQUIRE_EQ(keep_if_with_idx(sumis_even, xs), IntVector({ 2,3,2 }));
100     REQUIRE_EQ(drop_if_with_idx(sumis_even, xs), IntVector({ 1,2 }));
101 }
102 
103 TEST_CASE("container_common_test - trim")
104 {
105     using namespace fplus;
106     REQUIRE_EQ(trim_left(1, intList), IntList({2,2,3,2}));
107     REQUIRE_EQ(trim_right(2, intList), IntList({1,2,2,3}));
108     REQUIRE_EQ(trim(0, IntVector({0,2,4,5,6,7,8,0,0})), IntVector({2,4,5,6,7,8}));
109     REQUIRE_EQ(trim_token_left(IntVector({1,2}), xs), IntVector({2,3,2}));
110     REQUIRE_EQ(trim_token_left(IntVector({0,1,2}), IntVector({0,1,2,0,1,2,7,5,9})), IntVector({7,5,9}));
111     REQUIRE_EQ(trim_token_right(IntVector({3,2}), xs), IntVector({1,2,2}));
112     REQUIRE_EQ(trim_token(IntVector({0,1}), IntVector({0,1,7,8,9,0,1})), IntVector({7,8,9}));
113 }
114 
115 TEST_CASE("container_common_test - cluster")
116 {
117     using namespace fplus;
118     REQUIRE_EQ(cluster_by(abs_diff_less_or_equal_3, IntVector({2,3,6,4,12,11,20,23,8,4})), IntVectors({{2,3,6,4,12,11,8,4},{20,23}}));
119 }
120 
121 TEST_CASE("container_common_test - run_length_encode")
122 {
123     using namespace fplus;
124     typedef std::pair<std::size_t, int> rle_pair_int;
125     typedef std::vector<rle_pair_int> rle_list_int;
126     IntVector rle_input = {1,2,2,2,2,3,3,2};
127     rle_list_int rle_result = {
128             std::make_pair(1, 1),
129             std::make_pair(4, 2),
130             std::make_pair(2, 3),
131             std::make_pair(1, 2)};
132     REQUIRE_EQ(run_length_encode(rle_input), rle_result);
133     REQUIRE_EQ(run_length_decode(rle_result), rle_input);
134 }
135 
136 TEST_CASE("container_common_test - keep_idxs")
137 {
138     using namespace fplus;
139     REQUIRE_EQ(keep_idxs(IdxVector({1, 3}), xs), IntVector({2,3}));
140     REQUIRE_EQ(keep_idxs(IdxVector({3, 1}), xs), IntVector({2,3}));
141     REQUIRE_EQ(keep_idxs(IdxVector({1, 1, 3}), xs), IntVector({2,3}));
142     REQUIRE_EQ(keep_idxs(IdxVector({1, 3, 7}), xs), IntVector({2,3}));
143     REQUIRE_EQ(drop_idxs(IdxVector({1, 3}), xs), IntVector({1,2,2}));
144 }
145 
146 TEST_CASE("container_common_test - is_equal")
147 {
148     using namespace fplus;
149     REQUIRE_EQ(is_equal_by_and_by(is_even_int, is_even_int)(2, 4), true);
150     REQUIRE_EQ(is_equal_by_and_by(is_even_int, is_even_int)(1, 2), false);
151     REQUIRE_EQ(is_equal_by_and_by(is_odd_int, is_even_int)(1, 2), true);
152     REQUIRE_EQ(is_equal_to(2)(2), true);
153     REQUIRE_EQ(is_equal_to(1)(2), false);
154 }
155 
156 TEST_CASE("container_common_test - is_empty")
157 {
158     using namespace fplus;
159     REQUIRE_EQ(is_empty(xs), false);
160     REQUIRE_EQ(is_empty(IntVector()), true);
161     REQUIRE_EQ(is_not_empty(xs), true);
162     REQUIRE_EQ(is_not_empty(IntVector()), false);
163 }
164 
165 TEST_CASE("container_common_test - convert")
166 {
167     using namespace fplus;
168     REQUIRE_EQ(convert_container<IntList>(xs), intList);
169     typedef std::vector<float> FloatVector;
170     REQUIRE_EQ(convert_elems<float>(xs), FloatVector({1.0f,2.0f,2.0f,3.0f,2.0f}));
171 
172     typedef std::vector<ExplicitFromIntStruct> ExplicitFromIntStructs;
173     ExplicitFromIntStructs explicitFromIntStructs = {
174         ExplicitFromIntStruct(1),
175         ExplicitFromIntStruct(2),
176         ExplicitFromIntStruct(2),
177         ExplicitFromIntStruct(3),
178         ExplicitFromIntStruct(2)
179     };
180 
181     REQUIRE_EQ(convert_elems<ExplicitFromIntStruct>(xs), explicitFromIntStructs);
182 }
183 
184 TEST_CASE("container_common_test - append_elem")
185 {
186     using namespace fplus;
187     IntVector values = {1,2};
188     REQUIRE_EQ(append_elem(3, values), IntVector({1,2,3}));
189     REQUIRE_EQ(append_elem(3, IntVector({1,2})), IntVector({1,2,3}));
190 }
191 
192 TEST_CASE("container_common_test - prepend_elem")
193 {
194     using namespace fplus;
195     IntVector values = {2,3};
196     REQUIRE_EQ(prepend_elem(1, values), IntVector({1,2,3}));
197     REQUIRE_EQ(prepend_elem(1, IntVector({2,3})), IntVector({1,2,3}));
198 }
199 
200 TEST_CASE("container_common_test - append")
201 {
202     using namespace fplus;
203     std::vector<int> xs_empty;
204     REQUIRE_EQ(append(xs, xs), xs2Times);
205     REQUIRE_EQ(append(xs, xs_arr), xs2Times);
206     REQUIRE_EQ(append(xs, xs_empty), xs);
207 }
208 
209 TEST_CASE("container_common_test - append_convert")
210 {
211     using namespace fplus;
212     REQUIRE_EQ(append_convert<decltype(xs2Times)>(xs_arr, xs_arr), xs2Times);
213     REQUIRE_EQ(append_convert<decltype(xs2Times)>(xs_arr, xs_deque), xs2Times);
214 }
215 
216 TEST_CASE("container_common_test - interweave")
217 {
218     using namespace fplus;
219     REQUIRE_EQ(interweave(IntVector({1,3}), IntVector({2,4})), IntVector({1,2,3,4}));
220     REQUIRE_EQ(interweave(IntVector({1,3,5,7}), IntVector({2,4})), IntVector({1,2,3,4,5,7}));
221     REQUIRE_EQ(unweave(IntVector({0,1,2,3})), std::make_pair(IntVector({0,2}), IntVector({1,3})));
222     REQUIRE_EQ(unweave(IntVector({0,1,2,3,4})), std::make_pair(IntVector({0,2,4}), IntVector({1,3})));
223 }
224 
225 TEST_CASE("container_common_test - concat")
226 {
227     using namespace fplus;
228     std::vector<std::vector<int>> emptyIntVecs;
229     std::vector<int> emptyIntVec;
230     REQUIRE_EQ(concat(emptyIntVecs), emptyIntVec);
231     REQUIRE_EQ(concat(intLists), intList);
232     REQUIRE_EQ(concat(IntVectors(2, xs)), xs2Times);
233 }
234 
235 TEST_CASE("container_common_test - repeat")
236 {
237     using namespace fplus;
238     REQUIRE_EQ(repeat(2, xs), xs2Times);
239 }
240 
241 TEST_CASE("container_common_test - replicate")
242 {
243     using namespace fplus;
244     REQUIRE_EQ(replicate(2, xs), IntVectors({xs, xs}));
245 }
246 
247 TEST_CASE("container_common_test - infixes")
248 {
249     using namespace fplus;
250     REQUIRE_EQ(infixes(3, xs), IntVectors({
251         IntVector({1, 2, 2}),
252         IntVector({2, 2, 3}),
253         IntVector({2, 3, 2})}));
254 }
255 
256 TEST_CASE("container_common_test - carthesian_product")
257 {
258     using namespace fplus;
259     typedef std::pair<std::string::value_type, std::string::value_type> char_pair;
260     typedef std::vector<char_pair> char_pair_vec;
__anone8399bc00a02(std::string::value_type x, std::string::value_type y) 261     auto twoCharsToString = [](std::string::value_type x, std::string::value_type y) { std::string result; result += x; result += y; return result; };
__anone8399bc00b02(std::string::value_type, std::string::value_type) 262     auto alwaysTrueCharAndChar = [](std::string::value_type, std::string::value_type) { return true; };
263     REQUIRE_EQ(carthesian_product_with(twoCharsToString, ABC_, XY), string_vec({"AX", "AY", "BX", "BY", "CX", "CY"}));
264     REQUIRE_EQ(carthesian_product_where(alwaysTrueCharAndChar, ABC_, XY), char_pair_vec({{'A','X'}, {'A','Y'}, {'B','X'}, {'B','Y'}, {'C','X'}, {'C','Y'}}));
__anone8399bc00c02(std::string::value_type x, std::string::value_type y) 265     auto charAndCharSumIsEven = [&](std::string::value_type x, std::string::value_type y) { return is_even_int(x + y); };
266     REQUIRE_EQ(carthesian_product_with_where(twoCharsToString, charAndCharSumIsEven, ABC_, XY), string_vec({"AY", "BX", "CY"}));
267     REQUIRE_EQ(carthesian_product_where(charAndCharSumIsEven, ABC_, XY), char_pair_vec({{'A','Y'}, {'B','X'}, {'C','Y'}}));
268     REQUIRE_EQ(carthesian_product(ABC_, XY), char_pair_vec({{'A','X'}, {'A','Y'}, {'B','X'}, {'B','Y'}, {'C','X'}, {'C','Y'}}));
269     REQUIRE_EQ(carthesian_product_n(2, ABCD), string_vec({"AA", "AB", "AC", "AD", "BA", "BB", "BC", "BD", "CA", "CB", "CC", "CD", "DA", "DB", "DC", "DD"}));
270     REQUIRE_EQ(carthesian_product_n(2, vec0123), IntVectors({{0,0}, {0,1}, {0,2}, {0,3}, {1,0}, {1,1}, {1,2}, {1,3}, {2,0}, {2,1}, {2,2}, {2,3}, {3,0}, {3,1}, {3,2}, {3,3}}));
271     REQUIRE_EQ(carthesian_product_n(0, vec0123), IntVectors({IntVector()}));
272 }
273 
274 TEST_CASE("container_common_test - combination")
275 {
276     using namespace fplus;
277     typedef std::vector<std::list<int>> intListVec;
278     REQUIRE_EQ(combinations(2, ABCD), string_vec({"AB", "AC", "AD", "BC", "BD", "CD"}));
279     REQUIRE_EQ(combinations(1, ABCD), string_vec({"A", "B", "C", "D"}));
280     REQUIRE_EQ(combinations(3, ABCD), string_vec({"ABC", "ABD", "ACD", "BCD"}));
281     REQUIRE_EQ(combinations(2, vec0123), IntVectors({{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}}));
282     REQUIRE_EQ(combinations(2, list0123), intListVec({{0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3}}));
283     REQUIRE_EQ(combinations(0, IntVector()), IntVectors({IntVector()}));
284     REQUIRE_EQ(combinations(0, vec0123), IntVectors({IntVector()}));
285     REQUIRE_EQ(combinations(0, ABCD), string_vec({""}));
286     REQUIRE_EQ(combinations_with_replacement(2, ABCD), string_vec({"AA", "AB", "AC", "AD", "BB", "BC", "BD", "CC", "CD", "DD"}));
287     REQUIRE_EQ(combinations_with_replacement(0, vec0123), IntVectors({IntVector()}));
288 }
289 
290 TEST_CASE("container_common_test - permutations")
291 {
292     using namespace fplus;
293     REQUIRE_EQ(permutations(2, ABCD), string_vec({"AB", "AC", "AD", "BA", "BC", "BD", "CA", "CB", "CD", "DA", "DB", "DC"}));
294     REQUIRE_EQ(permutations(0, vec0123), IntVectors({IntVector()}));
295 }
296 
297 TEST_CASE("container_common_test - power_set")
298 {
299     using namespace fplus;
300     REQUIRE_EQ(power_set(std::string("xyz")), string_vec({"", "x", "y", "z", "xy", "xz", "yz", "xyz"}));
301 }
302 
303 TEST_CASE("container_common_test - rotations")
304 {
305     using namespace fplus;
306     REQUIRE_EQ(rotations_left(std::string("abcd")), string_vec({"abcd", "bcda", "cdab", "dabc"}));
307     REQUIRE_EQ(rotations_right(std::string("abcd")), string_vec({"abcd", "dabc", "cdab", "bcda"}));
308 }
309 
310 TEST_CASE("container_common_test - fill")
311 {
312     using namespace fplus;
313     REQUIRE_EQ(fill_left(0, 6, IntVector({1,2,3,4})), IntVector({0,0,1,2,3,4}));
314     REQUIRE_EQ(fill_right(0, 6, IntList({1,2,3,4})), IntList({1,2,3,4,0,0}));
315     REQUIRE_EQ(fill_left(' ', 6, std::string("12")), std::string("    12"));
316 }
317 
318 TEST_CASE("container_common_test - intersperse")
319 {
320     using namespace fplus;
321     REQUIRE_EQ(intersperse(0, xs), IntVector({1,0,2,0,2,0,3,0,2}));
322 }
323 
324 TEST_CASE("container_common_test - fold")
325 {
326     using namespace fplus;
327     REQUIRE_EQ(fold_left(std::plus<>(), 100, xs), 110);
328     REQUIRE_EQ(fold_left_1(std::plus<>(), xs), 10);
329     REQUIRE_EQ(fold_right(std::plus<>(), 100, xs), 110);
330     REQUIRE_EQ(fold_right_1(std::plus<>(), xs), 10);
__anone8399bc00d02(const std::string& str, int x) 331     auto appendXToStrForFoldL = [](const std::string& str, int x) { return str + std::to_string(x); };
__anone8399bc00e02(int x, const std::string& str) 332     auto appendXToStrForFoldR = [](int x, const std::string& str) { return str + std::to_string(x); };
333     std::string emptyString;
334     REQUIRE_EQ(fold_left(appendXToStrForFoldL, emptyString, xs), "12232");
335     REQUIRE_EQ(fold_right(appendXToStrForFoldR, emptyString, xs), "23221");
336 }
337 
338 TEST_CASE("container_common_test - reduce")
339 {
340     using namespace fplus;
341     REQUIRE_EQ(reduce(std::plus<int>(), 100, xs), 110);
342     REQUIRE_EQ(reduce_1(std::plus<int>(), xs), 10);
343 }
344 
345 TEST_CASE("container_common_test - scan")
346 {
347     using namespace fplus;
348     REQUIRE_EQ(scan_left(std::plus<>(), 20, xs), IntVector({ 20,21,23,25,28,30 }));
349     REQUIRE_EQ(scan_right(std::plus<>(), 20, xs), IntVector({ 30,29,27,25,22,20 }));
350     REQUIRE_EQ(scan_left_1(std::plus<>(), xs), IntVector({ 1,3,5,8,10 }));
351     REQUIRE_EQ(scan_right_1(std::plus<>(), xs), IntVector({ 10,9,7,5,2 }));
352 }
353 
354 TEST_CASE("container_common_test - join")
355 {
356     using namespace fplus;
357     REQUIRE_EQ(join(std::string(", "), std::vector<std::string>({"a", "b", "sea"})), std::string("a, b, sea"));
358     REQUIRE_EQ(join(IntList({0}), intLists), IntList({1,0,2,2,0,3,0,2}));
359 }
360 
361 TEST_CASE("container_common_test - join_elem")
362 {
363     using namespace fplus;
364     REQUIRE_EQ(join_elem(',', std::vector<std::string>({"a", "b", "sea"})), std::string("a,b,sea"));
365     REQUIRE_EQ(join_elem(0, intLists), IntList({1,0,2,2,0,3,0,2}));
366 }
367 
368 TEST_CASE("container_common_test - all")
369 {
370     using namespace fplus;
371     REQUIRE_EQ(all(BoolVector()), true);
372     REQUIRE_EQ(all(BoolVector({true})), true);
373     REQUIRE_EQ(all(BoolVector({false})), false);
374     REQUIRE_EQ(all(BoolVector({true, true})), true);
375     REQUIRE_EQ(all(BoolVector({true, false})), false);
376 
377     REQUIRE_EQ(all_by(is_even_int, IntVector()), true);
378     REQUIRE_EQ(all_by(is_even_int, IntVector({2})), true);
379     REQUIRE_EQ(all_by(is_even_int, IntVector({1})), false);
380     REQUIRE_EQ(all_by(is_even_int, IntVector({2, 2})), true);
381     REQUIRE_EQ(all_by(is_even_int, IntVector({2, 1})), false);
382 }
383 
384 TEST_CASE("container_common_test - size")
385 {
386     using namespace fplus;
387     REQUIRE_EQ(fplus::size_of_cont(xs), 5);
388     REQUIRE_EQ(fplus::size_of_cont(IntVector()), 0);
389     REQUIRE_EQ(is_not_empty(xs), true);
390 }
391 
392 TEST_CASE("container_common_test - sort")
393 {
394     using namespace fplus;
395     REQUIRE_EQ(sort(reverse(xs)), xsSorted);
396     REQUIRE_EQ(sort(reverse(intList)), intListSorted);
397     REQUIRE_EQ(sort_by(std::greater<int>(), xs), reverse(xsSorted));
398 
399     REQUIRE_EQ(sort_on(int_mod_10, IntVector({26,3,14})), IntVector({3,14,26}));
400     REQUIRE_EQ(sort_on(size_of_cont<IntVector>, IntVectors({{1,2,3},{4,5}})), IntVectors({{4,5},{1,2,3}}));
401 }
402 
403 TEST_CASE("container_common_test - stable_sort")
404 {
405     using namespace fplus;
406     REQUIRE_EQ(stable_sort(reverse(xs)), xsSorted);
407     REQUIRE_EQ(stable_sort(reverse(intList)), intListSorted);
408     REQUIRE_EQ(stable_sort_by(std::greater<int>(), xs), reverse(xsSorted));
409 
410     REQUIRE_EQ(stable_sort_on(int_mod_10, IntVector({26,3,14})), IntVector({3,14,26}));
411     REQUIRE_EQ(stable_sort_on(size_of_cont<IntVector>, IntVectors({{1,2,3},{4,5}})), IntVectors({{4,5},{1,2,3}}));
412 }
413 
414 TEST_CASE("container_common_test - partial_sort")
415 {
416     using namespace fplus;
417     REQUIRE_EQ(partial_sort(2, xs_reverse), IntVector({1,2}));
418     REQUIRE_EQ(partial_sort(2, reverse(xs)), IntVector({1,2}));
419 }
420 
421 TEST_CASE("container_common_test - reverse")
422 {
423     using namespace fplus;
424     REQUIRE_EQ(reverse(IntVector({1,2,2,3,2})), xs_reverse);
425     REQUIRE_EQ(reverse(xs), xs_reverse);
426 }
427 
428 TEST_CASE("container_common_test - nth_element")
429 {
430     using namespace fplus;
431     REQUIRE_EQ(nth_element(0, xs), 1);
432     REQUIRE_EQ(nth_element(1, xs), 2);
433     REQUIRE_EQ(nth_element(2, xs), 2);
434     REQUIRE_EQ(nth_element(3, xs), 2);
435     REQUIRE_EQ(nth_element(4, xs), 3);
436 
437     REQUIRE_EQ(nth_element(1, xs_arr), 2);
438 }
439 
440 TEST_CASE("container_common_test - unique")
441 {
442     using namespace fplus;
443     REQUIRE_EQ(unique(xs), IntVector({1,2,3,2}));
444     auto IsEqualByis_even = [&](int a, int b)
__anone8399bc00f02(int a, int b) 445             { return is_even_int(a) == is_even_int(b); };
446     REQUIRE_EQ(unique_by(IsEqualByis_even, xs), IntVector({1,2,3,2}));
447 
448     REQUIRE_EQ(unique_on(int_mod_10, IntVector({2,22,3})), IntVector({2, 3}));
449 }
450 
451 TEST_CASE("container_common_test - all_the_same")
452 {
453     using namespace fplus;
454     REQUIRE_EQ(all_the_same(IntVector()), true);
455     REQUIRE_EQ(all_the_same(IntVector({1})), true);
456     REQUIRE_EQ(all_the_same(IntVector({1,1,1})), true);
457     REQUIRE_EQ(all_the_same(IntVector({1,2,1})), false);
458 
459     REQUIRE_EQ(all_the_same_on(int_mod_10, IntVector({3,13,33})), true);
460     REQUIRE_EQ(all_the_same_on(int_mod_10, IntVector({3,14,33})), false);
461 
462     struct foo {};
__anone8399bc01002(const foo&) 463     const auto foo_to_int = [](const foo&) -> int { return 3; };
464     REQUIRE(fplus::all_the_same_on(foo_to_int, std::vector<foo>({})));
465 }
466 
467 TEST_CASE("container_common_test - all_unique")
468 {
469     using namespace fplus;
470     REQUIRE_EQ(all_unique(IntVector()), true);
471     REQUIRE_EQ(all_unique(IntVector({1})), true);
472     REQUIRE_EQ(all_unique(IntVector({1,2,1})), false);
473     REQUIRE_EQ(all_unique(IntVector({1,2,3})), true);
474 
475     REQUIRE_EQ(all_unique_less(IntVector()), true);
476     REQUIRE_EQ(all_unique_less(IntVector({1})), true);
477     REQUIRE_EQ(all_unique_less(IntVector({1,2,1})), false);
478     REQUIRE_EQ(all_unique_less(IntVector({1,2,3})), true);
479 
480     REQUIRE_EQ(all_unique_on(int_mod_10, IntVector({3,14,35})), true);
481     REQUIRE_EQ(all_unique_on(int_mod_10, IntVector({3,14,33})), false);
482 }
483 
484 TEST_CASE("container_common_test - is_sorted")
485 {
486     using namespace fplus;
487     REQUIRE_EQ(is_sorted(IntVector()), true);
488     REQUIRE_EQ(is_sorted(IntVector({1})), true);
489     REQUIRE_EQ(is_sorted(IntVector({1,2,3})), true);
490     REQUIRE_EQ(is_sorted(IntVector({1,2,2})), true);
491     REQUIRE_EQ(is_sorted(IntVector({1,2,1})), false);
492     REQUIRE_EQ(is_sorted_on(int_mod_10, IntVector({51,32,43})), true);
493     REQUIRE_EQ(is_sorted_on(int_mod_10, IntVector({15,23})), false);
494     REQUIRE_EQ(is_strictly_sorted(IntVector({1,2,3})), true);
495     REQUIRE_EQ(is_strictly_sorted(IntVector({1,2,2})), false);
496     REQUIRE_EQ(is_strictly_sorted(IntVector({1,2,1})), false);
497     REQUIRE_EQ(is_strictly_sorted_on(int_mod_10, IntVector({51,32,43})), true);
498     REQUIRE_EQ(is_strictly_sorted_on(int_mod_10, IntVector({51,32,43,63})), false);
499     REQUIRE_EQ(is_strictly_sorted_on(int_mod_10, IntVector({15,23})), false);
500 }
501 
502 TEST_CASE("container_common_test - find")
503 {
504     using namespace fplus;
505 
506     REQUIRE_EQ(find_first_by(is3, xs), just(3));
507     REQUIRE_EQ(find_first_by(is4, xs), nothing<int>());
508     REQUIRE_EQ(find_first_idx_by(is2, xs), just<std::size_t>(1));
509     REQUIRE_EQ(find_first_idx_by(is4, xs), nothing<std::size_t>());
510     REQUIRE_EQ(find_first_idx(2, xs), just<std::size_t>(1));
511     REQUIRE_EQ(find_first_idx(4, xs), nothing<std::size_t>());
512 
513     REQUIRE_EQ(find_last_by(is3, xs), just(3));
514     REQUIRE_EQ(find_last_by(is4, xs), nothing<int>());
515     REQUIRE_EQ(find_last_idx_by(is2, xs), just<std::size_t>(4));
516     REQUIRE_EQ(find_last_idx_by(is4, xs), nothing<std::size_t>());
517     REQUIRE_EQ(find_last_idx(2, xs), just<std::size_t>(4));
518     REQUIRE_EQ(find_last_idx(4, xs), nothing<std::size_t>());
519 }
520 
521 TEST_CASE("container_common_test - is_elem_of")
522 {
523     using namespace fplus;
524     REQUIRE_EQ(is_elem_of(2, xs), true);
525     REQUIRE_EQ(is_elem_of(4, xs), false);
526 }
527 
528 TEST_CASE("container_common_test - elem_at_idx")
529 {
530     using namespace fplus;
531     REQUIRE_EQ(elem_at_idx(2, xs), 2);
532 
533 }
534 
535 TEST_CASE("container_common_test - elem_at_idx_maybe")
536 {
537     using namespace fplus;
538     REQUIRE_EQ(elem_at_idx_maybe(2, xs), maybe<int>(2));
539     REQUIRE_EQ(elem_at_idx_maybe(9, xs), nothing<int>());
540 }
541 
542 TEST_CASE("container_common_test - find_token")
543 {
544     using namespace fplus;
545     REQUIRE_EQ(find_all_instances_of_token(std::string("Plus"),
546         std::string("C Plus Plus is a nice language,") +
547         std::string(" and FunctionalPlus makes it even nicer.")),
548         std::vector<std::size_t>({ 2, 7, 46 }));
549     REQUIRE_EQ(find_all_instances_of_token(std::string("xx"), std::string("bxxxxc")), std::vector<std::size_t>({ 1, 2, 3 }));
550     REQUIRE_EQ(find_all_instances_of_token(std::string("xy"), std::string("xyaaa")), std::vector<std::size_t>({ 0 }));
551     REQUIRE_EQ(find_all_instances_of_token(std::string("xy"), std::string("aaaxy")), std::vector<std::size_t>({ 3 }));
552     REQUIRE_EQ(find_all_instances_of_token(std::string("xx"), std::string("xxxxx")), std::vector<std::size_t>({ 0, 1, 2, 3 }));
553     REQUIRE_EQ(find_all_instances_of_token_non_overlapping(std::string("xx"), std::string("xxxx")), std::vector<std::size_t>({ 0, 2 }));
554     REQUIRE_EQ(find_all_instances_of_token(IntVector({}), IntVector({})), IdxVector({0}));
555     REQUIRE_EQ(find_all_instances_of_token(IntVector({}), IntVector({1})), IdxVector({0,1}));
556     REQUIRE_EQ(find_all_instances_of_token_non_overlapping(IntVector({}), IntVector({})), IdxVector({0}));
557     REQUIRE_EQ(find_all_instances_of_token_non_overlapping(IntVector({}), IntVector({1})), IdxVector({0,1}));
558     REQUIRE_EQ(find_first_instance_of_token(IntVector({}), IntVector({})), just<std::size_t>(0));
559     REQUIRE_EQ(find_first_instance_of_token(IntVector({}), IntVector({1,2})), just<std::size_t>(0));
560     REQUIRE_EQ(find_first_instance_of_token(std::string("haha"), std::string("oh, hahaha!")), just<std::size_t>(4));
561 }
562 
563 TEST_CASE("container_common_test - insert_at_idx")
564 {
565     using namespace fplus;
566     REQUIRE_EQ(insert_at_idx(2, 0, IntVector({1,2,3,4})), IntVector({1,2,0,3,4}));
567 }
568 
569 
570 TEST_CASE("container_common_test - segment")
571 {
572     using namespace fplus;
573     IntList v789 = { 7,8,9 };
574     REQUIRE_EQ(set_segment(1, v789, IntList({ 1,2,2,3,2 })), IntList({ 1,7,8,9,2 }));
575     REQUIRE_EQ(set_segment(1, v789, intList), IntList({ 1,7,8,9,2 }));
576     REQUIRE_EQ(get_segment(2, 5, IntList({ 0,1,2,3,4,5,6,7,8 })), IntList({ 2,3,4 }));
577     REQUIRE_EQ(get_segment(2, 15, IntList({ 0,1,2,3,4,5,6,7,8 })), IntList({ 2,3,4,5,6,7,8 }));
578     REQUIRE_EQ(get_segment(5, 2, IntList({ 0,1,2,3,4,5,6,7,8 })), IntList({}));
579     REQUIRE_EQ(get_segment(12, 15, IntList({ 0,1,2,3,4,5,6,7,8 })), IntList({}));
580     REQUIRE_EQ(get_segment(15, 12, IntList({ 0,1,2,3,4,5,6,7,8 })), IntList({}));
581     REQUIRE_EQ(replace_elems(2, 5, xs), IntVector({1,5,5,3,5}));
582     REQUIRE_EQ(replace_tokens(std::string("123"), std::string("_"), std::string("--123----123123")), std::string("--_----__"));
583     REQUIRE_EQ(take(2, xs), IntVector({ 1,2 }));
584     REQUIRE_EQ(take_last(2, xs), IntVector({ 3,2 }));
585     REQUIRE_EQ(take_exact(2, xs), IntVector({ 1,2 }));
586     REQUIRE_EQ(drop(2, xs), IntVector({ 2,3,2 }));
587     REQUIRE_EQ(drop_last(2, xs), IntVector({ 1,2,2 }));
588     REQUIRE_EQ(drop_exact(2, xs), IntVector({ 2,3,2 }));
589     REQUIRE_EQ(take(999, xs), xs);
590     REQUIRE_EQ(drop(999, xs), IntVector());
591     REQUIRE_EQ(take_while(is_odd_int, xs), IntVector({ 1 }));
592     REQUIRE_EQ(take_while(always(true), xs), xs);
593     REQUIRE_EQ(take_last_while(always(true), IntVector()), IntVector());
594     REQUIRE_EQ(take_last_while(always(false), IntVector()), IntVector());
595     REQUIRE_EQ(take_last_while(always(true), xs), xs);
596     REQUIRE_EQ(take_last_while(always(false), xs), IntVector());
597     REQUIRE_EQ(take_last_while(is_even_int, xs), IntVector({ 2 }));
598     REQUIRE_EQ(take_last_while(is_even_int, intList), IntList({ 2 }));
599     REQUIRE_EQ(drop_while(always(false), xs), xs);
600     REQUIRE_EQ(drop_while(is_odd_int, xs), IntVector({ 2,2,3,2 }));
601     REQUIRE_EQ(drop_last_while(always(false), IntVector()), IntVector());
602     REQUIRE_EQ(drop_last_while(always(true), IntVector()), IntVector());
603     REQUIRE_EQ(drop_last_while(always(false), xs), xs);
604     REQUIRE_EQ(drop_last_while(always(true), xs), IntVector());
605     REQUIRE_EQ(drop_last_while(is_even_int, xs), IntVector({ 1,2,2,3 }));
606     REQUIRE_EQ(drop_last_while(is_even_int, intList), IntList({ 1,2,2,3 }));
607     REQUIRE_EQ(span(is_odd_int, xs), std::make_pair(IntVector({ 1 }), IntVector({ 2,2,3,2 })));
608     REQUIRE_EQ(set_segment(2, IntVector({8,9}), xs), IntVector({1,2,8,9,2}));
609     REQUIRE_EQ(set_segment(2, IntVector({8,9}), IntVector({1,2,2,3,2})), IntVector({1,2,8,9,2}));
610     REQUIRE_EQ(remove_segment(1, 3, xs), IntVector({1,3,2}));
611     REQUIRE_EQ(remove_segment(1, 3, IntVector({1,2,2,3,2})), IntVector({1,3,2}));
612     REQUIRE_EQ(take_cyclic(5, IntVector({0,1,2,3})), IntVector({0,1,2,3,0}));
613     REQUIRE_EQ(take_cyclic(7, IntVector({0,1,2,3})), IntVector({0,1,2,3,0,1,2}));
614     REQUIRE_EQ(take_cyclic(7, IntVector({0,1})), IntVector({0,1,0,1,0,1,0}));
615     REQUIRE_EQ(take_cyclic(2, IntVector({0,1,2,3})), IntVector({0,1}));
616     REQUIRE_EQ(take_cyclic(3, IntVector({0})), IntVector({0,0,0}));
617     REQUIRE_EQ(take_while(is_even<int>, IntVector({ 4, 3 })), IntVector({4}));
618     REQUIRE_EQ(drop_while(is_even<int>, IntVector({ 4, 8 })), IntVector());
619 }
620 
621 TEST_CASE("container_common_test - keep_if")
622 {
623     using namespace fplus;
624     REQUIRE_EQ(keep_if(is2, xs), IntVector({ 2,2,2 }));
625     REQUIRE_EQ(keep_if(is3, xs), IntVector({ 3 }));
626     REQUIRE_EQ(keep_if(is4, xs), IntVector());
627 }
628 
629 TEST_CASE("container_common_test - find_all_idxs_of")
630 {
631     using namespace fplus;
632     REQUIRE_EQ(find_all_idxs_of('h', std::string("oh, ha!")), std::vector<std::size_t>({ 1, 4 }));
633     REQUIRE_EQ(find_all_idxs_of(2, xs), IdxVector({ 1,2,4 }));
634 }
635 
636 TEST_CASE("container_common_test - generate")
637 {
638     using namespace fplus;
639     int countUpCounter = 0;
__anone8399bc01102() 640     auto countUp = [countUpCounter]() mutable { return countUpCounter++; };
641     REQUIRE_EQ(generate<IntVector>(countUp, 3), IntVector({ 0,1,2 }));
642     auto square_size_t_return_int = [&](std::size_t x) -> int
__anone8399bc01202(std::size_t x) 643     {
644         return squareLambda(static_cast<int>(x));
645     };
646     REQUIRE_EQ(generate_by_idx<IntVector>(square_size_t_return_int, 3), IntVector({ 0,1,4 }));
647 }
648 
649 TEST_CASE("container_common_test - nub")
650 {
651     using namespace fplus;
652     REQUIRE_EQ(nub(xs), IntVector({ 1,2,3 }));
653     auto bothEven = is_equal_by(is_even_int);
654     REQUIRE_EQ(nub_by(bothEven, xs), IntVector({ 1,2 }));
655     REQUIRE_EQ(nub_on(int_mod_10, IntVector({12,32,15})), IntVector({12,15}));
656 }
657 
658 TEST_CASE("container_common_test - coucount_occurrences_bynt_occurrences_on")
659 {
660     using namespace fplus;
661     typedef std::map<int, std::size_t> IntSizeTMap;
662     IntSizeTMap OccurrencesResult = {{1, 1}, {2, 3}, {3, 1}};
663     std::vector<double> double_values = {1.1, 2.3, 2.7, 3.6, 2.4};
664     const auto f = floor<double>;
665     REQUIRE_EQ(count_occurrences_by(f, double_values), OccurrencesResult);
666 }
667 
668 TEST_CASE("container_common_test - count_occurrences")
669 {
670     using namespace fplus;
671     typedef std::map<int, std::size_t> IntSizeTMap;
672     IntSizeTMap OccurrencesResult = {{1, 1}, {2, 3}, {3, 1}};
673     REQUIRE_EQ(count_occurrences(xs), OccurrencesResult);
674 }
675 
676 TEST_CASE("container_common_test - insert_at")
677 {
678     using namespace fplus;
679     REQUIRE_EQ(insert_at(2, IntVector({8,9}), xs), IntVector({1,2,8,9,2,3,2}));
680 }
681 
682 TEST_CASE("container_common_test - head")
683 {
684     using namespace fplus;
685     REQUIRE_EQ(head(xs), 1);
686 }
687 
688 TEST_CASE("container_common_test - last")
689 {
690     using namespace fplus;
691     REQUIRE_EQ(last(xs), 2);
692 }
693 
694 TEST_CASE("container_common_test - tail")
695 {
696     using namespace fplus;
697     REQUIRE_EQ(init(xs), IntVector({1,2,2,3}));
698     REQUIRE_EQ(init(IntVector({1,2,2,3,2})), IntVector({1,2,2,3}));
699     REQUIRE_EQ(tail(xs), IntVector({2,2,3,2}));
700     REQUIRE_EQ(tail(IntVector({1,2,2,3,2})), IntVector({2,2,3,2}));
701     REQUIRE_EQ(inits(xs), IntVectors({{},{1},{1,2},{1,2,2},{1,2,2,3},{1,2,2,3,2}}));
702     REQUIRE_EQ(tails(xs), IntVectors({{1,2,2,3,2},{2,2,3,2},{2,3,2},{3,2},{2},{}}));
703 }
704 
705 TEST_CASE("container_common_test - iterate")
706 {
707     using namespace fplus;
__anone8399bc01302(int x) 708     auto times_two = [](int x) { return 2*x; };
709     REQUIRE_EQ(iterate(times_two, 0, 3), IntVector({}));
710     REQUIRE_EQ(iterate(times_two, 1, 3), IntVector({3}));
711     REQUIRE_EQ(iterate(times_two, 2, 3), IntVector({3,6}));
712     REQUIRE_EQ(iterate(times_two, 5, 3), IntVector({3,6,12,24,48}));
713 }
714 
715 TEST_CASE("container_common_test - divvy")
716 {
717     using namespace fplus;
718     REQUIRE_EQ(divvy(5, 2, IntVector({0,1,2,3,4,5,6,7,8,9})), IntVectors({{0,1,2,3,4},{2,3,4,5,6},{4,5,6,7,8}}));
719 }
720 
721 TEST_CASE("container_common_test - aperture")
722 {
723     using namespace fplus;
724     REQUIRE_EQ(aperture(5, IntVector({0,1,2,3,4,5,6})), IntVectors({{0,1,2,3,4},{1,2,3,4,5},{2,3,4,5,6}}));
725     REQUIRE_EQ(divvy(5, 1, IntVector({0,1,2,3,4,5,6})), IntVectors({{0,1,2,3,4},{1,2,3,4,5},{2,3,4,5,6}}));
726 }
727 
728 TEST_CASE("container_common_test - stride")
729 {
730     using namespace fplus;
731     REQUIRE_EQ(stride(3, IntVector({0,1,2,3,4,5,6,7})), IntVector({0,3,6}));
732     REQUIRE_EQ(divvy(1, 3, IntVector({0,1,2,3,4,5,6,7})), IntVectors({{0},{3},{6}}));
733 }
734 
735 TEST_CASE("composition_test - instead_of_if_empty")
736 {
737     using namespace fplus;
738 
739     std::vector<int> xs_empty;
740     std::vector<int> xs_full = {1,2,3};
741     std::vector<int> xs_alt = {0};
742     REQUIRE_EQ(instead_of_if_empty(xs_alt, xs_empty), xs_alt);
743     REQUIRE_EQ(instead_of_if_empty(xs_alt, xs_full), xs_full);
744 }
745