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 10 namespace { __anond3ffbf540202(int x) 11 auto squareLambda = [](int x) -> int { return x*x; }; __anond3ffbf540302(int x) 12 auto cubeLambda = [](int x) -> int { return x*x*x; }; 13 typedef std::vector<int> IntVector; 14 typedef std::list<int> IntList; 15 typedef std::pair<int, int> IntPair; 16 typedef std::vector<IntPair> IntPairs; 17 IntVector xs = {1,2,2,3,2}; 18 19 struct dummy 20 { 21 int i; 22 }; 23 } 24 25 TEST_CASE("pairs_test - zip_with") 26 { 27 using namespace fplus; __anond3ffbf540402(int x, int y)28 const auto multiply = [](int x, int y){ return x * y; }; 29 REQUIRE_EQ(zip_with(multiply, xs, xs), transform(squareLambda, xs)); __anond3ffbf540502(int x, int y)30 const auto add = [](int x, int y){ return x + y; }; 31 REQUIRE_EQ(zip_with(add, IntVector({1,2,3}), IntVector({1,2})), IntVector({2,4})); 32 REQUIRE_EQ(zip_with(add, IntVector({1,2}), IntVector({1,2,3})), IntVector({2,4})); 33 REQUIRE_EQ(zip_with(add, IntVector({1,2}), IntList({1,2,3})), IntVector({2,4})); 34 __anond3ffbf540602(auto x, int y) 35 const auto add_generic = [](auto x, int y) {return x + y;}; 36 REQUIRE_EQ(zip_with(add_generic, IntVector({1,2,3}), IntVector({1,2})), IntVector({2,4})); 37 REQUIRE_EQ(zip_with(std::plus<>{}, IntVector({1,2,3}), IntVector({1,2})), IntVector({2,4})); 38 } 39 40 TEST_CASE("pairs_test - zip_with_3") 41 { 42 using namespace fplus; __anond3ffbf540702(int x, int y, int z)43 const auto multiply = [](int x, int y, int z){ return x * y * z; }; __anond3ffbf540802(auto x, auto y, auto z)44 const auto multiply_generic = [](auto x, auto y, auto z){ return x * y * z; }; 45 const auto cubed = transform(cubeLambda, xs); 46 REQUIRE_EQ(zip_with_3(multiply, xs, xs, xs), cubed); 47 REQUIRE_EQ(zip_with_3(multiply_generic, xs, xs, xs), cubed); 48 } 49 50 TEST_CASE("pairs_test - zip_with_defaults") 51 { 52 using namespace fplus; __anond3ffbf540902(int x, int y)53 const auto add = [](int x, int y){ return x + y; }; __anond3ffbf540a02(auto x, auto y)54 const auto add_generic = [](auto x, auto y){ return x + y; }; 55 REQUIRE_EQ(zip_with_defaults(add, 6, 7, IntVector({1,2,3}), IntVector({1,2})), IntVector({2,4,10})); 56 REQUIRE_EQ(zip_with_defaults(add, 6, 7, IntVector({1,2}), IntVector({1,2,3})), IntVector({2,4,9})); 57 REQUIRE_EQ(zip_with_defaults(add_generic, 6, 7, IntVector({1,2}), IntVector({1,2,3})), IntVector({2,4,9})); 58 } 59 60 TEST_CASE("pairs_test - zip") 61 { 62 using namespace fplus; 63 auto xsZippedWithXs = zip(xs, xs); 64 REQUIRE_EQ(unzip(xsZippedWithXs).first, xs); 65 } 66 67 TEST_CASE("pairs_test - pair functions") 68 { 69 using namespace fplus; 70 IntPair intPair = std::make_pair(2, 3); 71 IntPairs intPairs = {{1,2}, {3,4}}; 72 IntPairs intPairsSwapped = {{2,1}, {4,3}}; 73 REQUIRE_EQ(fst(intPair), 2); 74 REQUIRE_EQ(snd(intPair), 3); 75 REQUIRE_EQ(swap_pair_elems(intPair), std::make_pair(3, 2)); 76 REQUIRE_EQ(swap_pairs_elems(intPairs), intPairsSwapped); 77 REQUIRE_EQ(transform_fst(squareLambda, intPair), std::make_pair(4, 3)); 78 REQUIRE_EQ(transform_snd(squareLambda, intPair), std::make_pair(2, 9)); __anond3ffbf540b02(auto i) 79 REQUIRE_EQ(transform_fst([](auto i) { return i * i; }, intPair), std::make_pair(4, 3)); __anond3ffbf540c02(auto i) 80 REQUIRE_EQ(transform_snd([](auto i) { return i * i; }, intPair), std::make_pair(2, 9)); 81 REQUIRE_EQ(transform_pair(squareLambda, squareLambda, intPair), std::make_pair(4, 9)); 82 83 typedef std::vector<std::pair<std::string, int>> StringIntPairs; 84 StringIntPairs stringIntPairs = {{"a", 1}, {"a", 2}, {"b", 6}, {"a", 4}}; 85 auto stringIntPairsAsMapGrouped = pairs_to_map_grouped(stringIntPairs); 86 auto groupNames = transform(fst<std::string, int>, stringIntPairs); 87 auto groupNameToMedianMap = transform_map_values(median<std::vector<int>>, stringIntPairsAsMapGrouped); 88 auto getMedianValue = bind_1st_and_2nd_of_3(get_from_map_with_def<std::map<std::string, int>>, groupNameToMedianMap, 0); 89 auto groupMendianValues = transform(getMedianValue, groupNames); 90 auto stringIntPairsSndReplacedWithGroupMedian = zip(groupNames, groupMendianValues); 91 REQUIRE_EQ(stringIntPairsSndReplacedWithGroupMedian, StringIntPairs({{"a", 2}, {"a", 2}, {"b", 6}, {"a", 2}})); __anond3ffbf540d02(int x) 92 const std::function<int(int)> double_int = [](int x) -> int { 93 return 2 * x; 94 }; 95 REQUIRE_EQ(transform_pair(double_int, double_int, IntPair({2, 3})), 96 IntPair({4, 6})); 97 // Thanks to invoke, such code works. 98 // (I don't have a use case for it though) 99 dummy dumb; 100 dumb.i = 42; 101 102 auto p = std::make_pair(dumb, dumb); 103 auto result = transform_pair(&dummy::i, &dummy::i, p); 104 REQUIRE_EQ(result, std::make_pair(42, 42)); 105 } 106 107 TEST_CASE("pairs_test - enumerate") 108 { 109 using namespace fplus; 110 REQUIRE_EQ(enumerate(xs), (std::vector<std::pair<std::size_t, int>>({{0,1}, {1,2}, {2,2}, {3,3}, {4,2}}))); 111 } 112 113 TEST_CASE("pairs_test - adjacent_pairs") 114 { 115 using namespace fplus; 116 REQUIRE_EQ(adjacent_pairs(xs), IntPairs({{1,2},{2,3}})); 117 REQUIRE_EQ(adjacent_pairs(IntVector({1,2,2,3})), IntPairs({{1,2},{2,3}})); 118 } 119 120 TEST_CASE("pairs_test - overlapping_pairs") 121 { 122 using namespace fplus; 123 REQUIRE_EQ(overlapping_pairs(xs), IntPairs({{1,2},{2,2},{2,3},{3,2}})); 124 } 125 126 TEST_CASE("pairs_test - overlapping_pairs_cyclic") 127 { 128 using namespace fplus; 129 REQUIRE_EQ(overlapping_pairs_cyclic(xs), IntPairs({{1,2},{2,2},{2,3},{3,2},{2,1}})); 130 } 131 132 TEST_CASE("pairs_test - first_mismatch_idx_on") 133 { 134 using namespace fplus; 135 REQUIRE_EQ(first_mismatch_idx_on(is_even<int>, IntVector({1,2,3}), IntVector({3,5,3})), just<std::size_t>(1)); 136 REQUIRE_EQ(first_mismatch_idx_on(is_even<int>, IntVector({1,2,3}), IntVector({1,5})), just<std::size_t>(1)); 137 REQUIRE_EQ(first_mismatch_idx_on(is_even<int>, IntVector({1,2,3}), IntVector({1,6})), nothing<std::size_t>()); 138 REQUIRE_EQ(first_mismatch_idx_on(is_even<int>, IntVector(), IntVector({1,2})), nothing<std::size_t>()); 139 } 140 141 TEST_CASE("pairs_test - first_mismatch_on") 142 { 143 using namespace fplus; 144 REQUIRE_EQ(first_mismatch_on(is_even<int>, IntVector({1,2,3}), IntVector({3,5,3})), just(IntPair(2,5))); 145 REQUIRE_EQ(first_mismatch_on(is_even<int>, IntVector({1,2,3}), IntVector({1,5})), just(IntPair(2,5))); 146 REQUIRE_EQ(first_mismatch_on(is_even<int>, IntVector({1,2,3}), IntVector({1,6})), nothing<IntPair>()); 147 REQUIRE_EQ(first_mismatch_on(is_even<int>, IntVector(), IntVector({1,2})), nothing<IntPair>()); 148 } 149 150 TEST_CASE("pairs_test - first_mismatch_idx") 151 { 152 using namespace fplus; 153 REQUIRE_EQ(first_mismatch_idx(IntVector({1,2,3}), IntVector({1,4,3})), just<std::size_t>(1)); 154 REQUIRE_EQ(first_mismatch_idx(IntVector({1,2,3}), IntVector({1,4})), just<std::size_t>(1)); 155 REQUIRE_EQ(first_mismatch_idx(IntVector({1,2,3}), IntVector({1,2})), nothing<std::size_t>()); 156 REQUIRE_EQ(first_mismatch_idx(IntVector(), IntVector({1,2})), nothing<std::size_t>()); 157 } 158 159 TEST_CASE("pairs_test - first_mismatch") 160 { 161 using namespace fplus; 162 REQUIRE_EQ(first_mismatch(IntVector({1,2,3}), IntVector({1,4,3})), just(IntPair(2,4))); 163 REQUIRE_EQ(first_mismatch(IntVector({1,2,3}), IntVector({1,4})), just(IntPair(2,4))); 164 REQUIRE_EQ(first_mismatch(IntVector({1,2,3}), IntVector({1,2})), nothing<IntPair>()); 165 REQUIRE_EQ(first_mismatch(IntVector(), IntVector({1,2})), nothing<IntPair>()); 166 } 167 168 TEST_CASE("pairs_test - first_match_idx_on") 169 { 170 using namespace fplus; 171 REQUIRE_EQ(first_match_idx_on(is_even<int>, IntVector({1,2,3}), IntVector({2,4,3})), just<std::size_t>(1)); 172 REQUIRE_EQ(first_match_idx_on(is_even<int>, IntVector(), IntVector({1,2})), nothing<std::size_t>()); 173 } 174 175 TEST_CASE("pairs_test - first_match") 176 { 177 using namespace fplus; 178 REQUIRE_EQ(first_match(IntVector({1,2,3}), IntVector({5,2,3})), just(IntPair(2,2))); 179 REQUIRE_EQ(first_match(IntVector(), IntVector({1,2})), nothing<IntPair>()); 180 } 181 182 TEST_CASE("pairs_test - zip_repeat") 183 { 184 using namespace fplus; 185 typedef std::vector<std::string> Strings; 186 typedef std::pair<std::string, int> Pairs; 187 Strings label{"even", "odd"}; 188 std::vector<Pairs> expected{{"even", 0}, {"odd", 1}, {"even", 2}}; 189 REQUIRE_EQ(zip_repeat(label, IntVector{0,1}), zip(label, IntVector{0, 1})); 190 REQUIRE_EQ(zip_repeat(label, IntVector{0,1,2}), expected); 191 REQUIRE_EQ(zip_repeat(IntVector{0,1,2}, label), transform(fwd::swap_pair_elems(), expected)); 192 }