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 
11 namespace {
12 
__anon107dddc40202(int x)13     auto is_even_int = [](int x){ return x % 2 == 0; };
14     typedef std::vector<int> IntVector;
15     typedef std::vector<bool> BoolVector;
16     IntVector xs = {1,2,2,3,2};
17 }
18 
19 TEST_CASE("container_properties_test - any")
20 {
21     using namespace fplus;
22     REQUIRE_EQ(any(BoolVector()), false);
23     REQUIRE_EQ(any(BoolVector({true})), true);
24     REQUIRE_EQ(any(BoolVector({false})), false);
25     REQUIRE_EQ(any(BoolVector({false, false})), false);
26     REQUIRE_EQ(any(BoolVector({true, false})), true);
27 
28     REQUIRE_EQ(any_by(is_even_int, IntVector()), false);
29     REQUIRE_EQ(any_by(is_even_int, IntVector({2})), true);
30     REQUIRE_EQ(any_by(is_even_int, IntVector({1})), false);
31     REQUIRE_EQ(any_by(is_even_int, IntVector({1, 1})), false);
32     REQUIRE_EQ(any_by(is_even_int, IntVector({2, 1})), true);
33 }
34 
35 
36 TEST_CASE("container_properties_test - none")
37 {
38     using namespace fplus;
39     REQUIRE_EQ(none(BoolVector()), true);
40     REQUIRE_EQ(none(BoolVector({true})), false);
41     REQUIRE_EQ(none(BoolVector({false})), true);
42     REQUIRE_EQ(none(BoolVector({false, false})), true);
43     REQUIRE_EQ(none(BoolVector({true, false})), false);
44 
45     REQUIRE_EQ(none_by(is_even_int, IntVector()), true);
46     REQUIRE_EQ(none_by(is_even_int, IntVector({2})), false);
47     REQUIRE_EQ(none_by(is_even_int, IntVector({1})), true);
48     REQUIRE_EQ(none_by(is_even_int, IntVector({1, 1})), true);
49     REQUIRE_EQ(none_by(is_even_int, IntVector({2, 1})), false);
50 }
51 
52 TEST_CASE("container_properties_test - minmax")
53 {
54     using namespace fplus;
__anon107dddc40302(int i) 55     auto negateInt = [](int i) -> int { return -i; };
56 
57     REQUIRE_EQ(minimum(xs), 1);
58     REQUIRE_EQ(maximum(xs), 3);
59 
60     REQUIRE_EQ(minimum_by(std::greater<int>(), xs), 3);
61     REQUIRE_EQ(maximum_by(std::greater<int>(), xs), 1);
62 
63     REQUIRE_EQ(minimum_on(negateInt, xs), 3);
64     REQUIRE_EQ(maximum_on(negateInt, xs), 1);
65 
66     REQUIRE_EQ(minimum_idx(xs), 0);
67     REQUIRE_EQ(maximum_idx(xs), 3);
68 
69     REQUIRE_EQ(minimum_idx_by(std::greater<int>(), xs), 3);
70     REQUIRE_EQ(maximum_idx_by(std::greater<int>(), xs), 0);
71 
72     REQUIRE_EQ(minimum_idx_on(negateInt, xs), 3);
73     REQUIRE_EQ(maximum_idx_on(negateInt, xs), 0);
74 }
75 
76 TEST_CASE("container_properties_test - minmax_maybe")
77 {
78     using namespace fplus;
__anon107dddc40402(int i) 79     auto negateInt = [](int i) -> int { return -i; };
80 
81     REQUIRE_EQ(minimum_maybe(xs), maybe<int>(1));
82     REQUIRE_EQ(maximum_maybe(xs), maybe<int>(3));
83 
84     REQUIRE_EQ(minimum_by_maybe(std::greater<int>(), xs), maybe<int>(3));
85     REQUIRE_EQ(maximum_by_maybe(std::greater<int>(), xs), maybe<int>(1));
86 
87     REQUIRE_EQ(minimum_on_maybe(negateInt, xs), maybe<int>(3));
88     REQUIRE_EQ(maximum_on_maybe(negateInt, xs), maybe<int>(1));
89 
90     REQUIRE_EQ(minimum_idx_maybe(xs), maybe<std::size_t>(0));
91     REQUIRE_EQ(maximum_idx_maybe(xs), maybe<std::size_t>(3));
92 
93     REQUIRE_EQ(minimum_idx_by_maybe(std::greater<int>(), xs), maybe<std::size_t>(3));
94     REQUIRE_EQ(maximum_idx_by_maybe(std::greater<int>(), xs), maybe<std::size_t>(0));
95 
96 
97 }
98 
99 TEST_CASE("container_properties_test - mean")
100 {
101     using namespace fplus;
102     std::vector<unsigned char> uchars = {200, 202};
103     typedef std::vector<double> DoubleVector;
104     REQUIRE_EQ(sum(xs), 10);
105     REQUIRE_EQ(product(xs), 24);
106     REQUIRE_EQ(mean<int>(xs), 2);
107     REQUIRE_EQ(mean_using_doubles<unsigned char>(uchars), 201);
108     REQUIRE_EQ(median(IntVector({ 3 })), 3);
109     REQUIRE_EQ(median(IntVector({ 3, 5 })), 4);
110     REQUIRE(is_in_interval(3.49f, 3.51f, median<IntVector, float>(IntVector({ 3, 4 }))));
111     REQUIRE(is_in_interval(3.49, 3.51, mean<double>(DoubleVector({ 3, 4 }))));
112     REQUIRE_EQ(median(IntVector({ 3, 9, 5 })), 5);
113     REQUIRE_EQ(median(xs), 2);
114     REQUIRE_EQ(sum(convert_container_and_elems<std::vector<int>>(std::string("hello"))), 532);
115     REQUIRE(is_in_interval(5.99, 6.01, mean_stddev<double>(DoubleVector({ 4, 8 })).first));
116     REQUIRE(is_in_interval(1.99, 2.01, mean_stddev<double>(DoubleVector({ 4, 8 })).second));
117     REQUIRE(is_in_interval(3.749f, 3.751f, mean_stddev<float>(IntVector({ 1, 3, 7, 4 })).first));
118     REQUIRE(is_in_interval(2.16f, 2.17f, mean_stddev<float>(IntVector({ 1, 3, 7, 4 })).second));
119 }
120 
121 TEST_CASE("container_properties_test - all_unique_less")
122 {
123     using namespace fplus;
124     REQUIRE_FALSE(all_unique_less(IntVector({1,2,3,2})));
125     REQUIRE(all_unique_less(IntVector({4,2,1,3})));
126 }
127 
128 TEST_CASE("container_properties_test - infix")
129 {
130     using namespace fplus;
131     REQUIRE_EQ(is_infix_of(IntVector({}), IntVector({})), true);
132     REQUIRE_EQ(is_infix_of(IntVector({}), IntVector({1,2})), true);
133     REQUIRE_EQ(is_infix_of(IntVector({2,3}), xs), true);
134     REQUIRE_EQ(is_infix_of(IntVector({2,3}), xs), true);
135     REQUIRE_EQ(is_infix_of(IntVector({2,1}), xs), false);
136     REQUIRE_EQ(is_prefix_of(IntVector({ 1,2 }), xs), true);
137     REQUIRE_EQ(is_prefix_of(IntVector({ 2,2 }), xs), false);
138     REQUIRE_EQ(is_suffix_of(IntVector({ 3,2 }), xs), true);
139     REQUIRE_EQ(is_suffix_of(IntVector({ 2,2 }), xs), false);
140 }
141 
142 TEST_CASE("container_properties_test - subsequence")
143 {
144     using namespace fplus;
145     REQUIRE_EQ(is_subsequence_of(IntVector(), IntVector()), true);
146     REQUIRE_EQ(is_subsequence_of(IntVector(), xs), true);
147     REQUIRE_EQ(is_subsequence_of(IntVector({ 1,3 }), xs), true);
148     REQUIRE_EQ(is_subsequence_of(IntVector({ 3,1 }), xs), false);
149 }
150 
151 TEST_CASE("container_properties_test - count")
152 {
153     using namespace fplus;
154     REQUIRE_EQ(count(2, xs), 3);
155 }
156 
157 TEST_CASE("container_properties_test - is_unique_in")
158 {
159     using namespace fplus;
160     REQUIRE_FALSE(is_unique_in(2, xs));
161     REQUIRE(is_unique_in(3, xs));
162 }
163 
164 TEST_CASE("container_properties_test - is_permutation_of")
165 {
166     using namespace fplus;
167     REQUIRE(is_permutation_of(IntVector({2,3,1}), IntVector({1,2,3})));
168     REQUIRE_FALSE(is_permutation_of(IntVector({2,3,2}), IntVector({1,2,3})));
169     REQUIRE_FALSE(is_permutation_of(IntVector({2,3}), IntVector({1,2,3})));
170     REQUIRE_FALSE(is_permutation_of(IntVector({2,3,1}), IntVector({1,23})));
171 }
172 
173 TEST_CASE("container_properties_test - fill_pigeonholes")
174 {
175     const std::vector<unsigned int> ys = { 0, 1, 3, 1 };
176     REQUIRE_EQ(fplus::fill_pigeonholes_to(5, ys), std::vector<std::size_t>({1,2,0,1,0}));
177     REQUIRE_EQ(fplus::fill_pigeonholes_to(3, ys), std::vector<std::size_t>({1,2,0}));
178     REQUIRE_EQ(fplus::fill_pigeonholes(ys), std::vector<std::size_t>({1,2,0,1}));
179 
180     REQUIRE_EQ(fplus::fill_pigeonholes_bool_to(3, ys), std::vector<unsigned char>({1,1,0}));
181     REQUIRE_EQ(fplus::fill_pigeonholes_bool_to(5, ys), std::vector<unsigned char>({1,1,0,1,0}));
182     REQUIRE_EQ(fplus::fill_pigeonholes_bool(ys), std::vector<unsigned char>({1,1,0,1}));
183 }
184 
185 TEST_CASE("container_properties_test - present_in_all")
186 {
187     using namespace fplus;
188     const std::vector<std::vector<int>> xss = { {4,1,2}, {5,2,1}, {2,4,1} };
189     REQUIRE_EQ(present_in_all(xss), IntVector({1,2}));
190 }