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