44#include <gtest/gtest.h>
100 auto r =
stl_generate(5, [](
size_t i) {
return i * i; });
113 std::vector<int> v = {1, 2, 3, 4, 5};
121 std::vector<std::string> v = {
"a",
"b",
"c"};
122 std::vector<std::string>
results;
124 results.push_back(std::to_string(i) +
":" + s);
133 std::vector<int> v = {1, 2, 3, 4, 5};
144 std::vector<int> v = {1, 2, 3};
145 auto strings =
stl_map([](
int x) {
return std::to_string(x); }, v);
153 std::vector<std::string> v = {
"a",
"b",
"c"};
155 return std::to_string(i) + s;
164 std::vector<int> v = {1, 2, 3, 4, 5, 6};
174 std::vector<int> v = {10, 20, 30, 40, 50};
189 std::vector<int> v = {1, 2, 3, 4, 5};
196 std::vector<int> v = {1, 2, 3, 4};
204 std::vector<int> v = {1, 2, 3};
212 std::vector<int> v = {1, 2, 3};
213 std::string result =
stl_foldr(std::string(
""), [](
int x, std::string
acc) {
214 return std::to_string(x) +
acc;
221 std::vector<int> v = {1, 2, 3, 4};
234 std::vector<int> v = {1, 2, 3};
251 std::vector<int> v = {2, 4, 6, 8};
257 std::vector<int> v = {2, 3, 6, 8};
263 std::vector<int> v = {1, 2, 3, 4, 5};
269 std::vector<int> v = {1, 2, 3, 4, 5};
275 std::vector<int> v = {1, 3, 5, 7};
285 std::vector<int> v = {1, 2, 3, 4, 5};
286 auto result =
stl_find([](
int x) {
return x > 3; }, v);
294 std::vector<int> v = {1, 2, 3};
295 auto result =
stl_find([](
int x) {
return x > 10; }, v);
302 std::vector<int> v = {1, 2, 3, 4, 5};
303 auto result =
stl_find_last([](
int x) {
return x % 2 == 0; }, v);
311 std::vector<std::string> v = {
"a",
"b",
"c",
"d"};
312 auto result =
stl_find_index([](
const std::string& s) {
return s ==
"c"; }, v);
320 std::vector<int> v = {1, 2, 3, 4, 5};
321 auto result =
stl_find_mapi([](
size_t i,
int x) -> std::optional<std::string> {
323 return "found at " + std::to_string(i);
333 std::vector<int> v = {1, 2, 3, 4, 5};
344 std::vector<int> v = {1, 2, 3, 4, 5, 6};
351 std::vector<int> v = {1, 2, 2, 3, 2, 4};
361 std::vector<int> v = {1, 2, 3, 4, 5};
371 std::vector<int> v = {1, 2, 3, 4, 5};
381 std::vector<int> v = {1, 2, 3, 4, 5};
391 std::vector<int> v = {1, 2, 3, 10, 4, 5};
400 std::vector<int> v = {1, 2, 3, 10, 4, 5};
413 std::vector<int> v = {10, 20, 30};
430 std::vector<int> v = {10, 20, 30};
439 std::vector<int> v = {10, 20, 30, 40, 50};
452 std::vector<int> v = {3, 1, 4, 1, 5, 9};
461 std::vector<int> v = {3, 1, 4, 1, 5, 9};
470 std::vector<int> v = {3, 1, 4, 1, 5, 9};
480 std::vector<std::string> v = {
"hello",
"a",
"world"};
481 auto result =
stl_min_by([](
const std::string& s) {
return s.length(); }, v);
489 std::vector<std::string> v = {
"hello",
"a",
"world"};
490 auto result =
stl_max_by([](
const std::string& s) {
return s.length(); }, v);
502 std::vector<int> v = {1, 2, 3, 4, 5};
508 std::vector<int> v = {1, 2, 3, 4};
518 std::vector<int> v = {1, 2, 3, 4, 5, 6};
531 std::vector<int> v1 = {1, 2, 3};
532 std::vector<std::string> v2 = {
"a",
"b",
"c"};
543 std::vector<std::pair<int, std::string>> v = {{1,
"a"}, {2,
"b"}, {3,
"c"}};
555 std::vector<std::string> v = {
"a",
"b",
"c"};
571 std::vector<int> v1 = {1, 2, 3};
572 std::vector<int> v2 = {1, 2, 3};
579 std::vector<int> v1 = {1, 2, 3};
580 std::vector<int> v2 = {1, 2, 4};
587 std::vector<int> v1 = {1, 2, 3};
588 std::vector<int> v2 = {1, 2, 3};
595 std::vector<int> v1 = {1, 2, 3};
596 std::vector<int> v2 = {1, 2, 4};
603 std::vector<int> v1 = {1, 2, 4};
604 std::vector<int> v2 = {1, 2, 3};
615 std::vector<int> v = {1, 2, 3, 4, 5};
624 std::vector<int> v = {3, 1, 4, 1, 5, 9};
633 std::vector<std::string> v = {
"hello",
"a",
"world"};
634 auto result =
stl_sort_by([](
const std::string& a,
const std::string& b) {
635 return a.length() < b.length();
648 std::vector<int> v = {1, 1, 2, 2, 2, 3, 3};
659 std::vector<int> v = {1, 2, 1, 3, 2, 4};
671 std::vector<int> v1 = {1, 2, 3};
672 std::vector<int> v2 = {4, 5, 6};
683 std::vector<std::vector<int>> v = {{1, 2}, {3, 4}, {5}};
694 std::vector<int> v = {1, 2, 3};
696 return std::vector<int>{x, x * 10};
712 std::vector<int> v = {1, 1, 2, 2, 2, 3};
724 std::vector<std::string> v = {
"a",
"bb",
"c",
"dd",
"eee"};
726 auto result =
stl_group_by([](
const std::string& s) {
return s.length(); }, v);
737 std::list<int>
l = {1, 2, 3, 4, 5};
753 std::deque<int> d = {1, 2, 3, 4, 5};
765 std::vector<int> v = {1, 2, 3};
773 std::vector<int> v = {1, 2, 3};
787 std::vector<int> v = {1, 2, 3, 4};
800 std::vector<int> v = {1, 2, 3, 4, 5};
809 std::vector<int> v = {1, 2, 3};
818 std::vector<std::vector<int>>
sets = {{1, 2}, {3, 4}};
827 std::vector<int> v = {1, 2, 3};
840 std::vector<int> v = {1, 2, 3, 4, 5};
851 std::vector<int> v = {1, 2, 3, 4, 5};
862 std::vector<int> v = {1, 2, 3};
865 EXPECT_EQ(result, (std::vector<int>{1, 0, 2, 0, 3}));
870 std::vector<int> v = {1, 2, 3, 4, 5};
873 EXPECT_EQ(first, (std::vector<int>{1, 2}));
879 std::vector<int> v = {1, 2, 3, 10, 4, 5};
882 EXPECT_EQ(first, (std::vector<int>{1, 2, 3}));
888 std::vector<int> v = {1, 2, 3, 4, 5};
891 EXPECT_EQ(result, (std::vector<int>{1, 2, 3, 4}));
896 std::vector<int> v = {1, 2, 3, 4, 5};
899 EXPECT_EQ(result, (std::vector<int>{2, 3, 4, 5}));
904 std::vector<int> v = {1, 2, 2, 3, 3, 3};
918 std::vector<int> v = {1, 2, 3, 4, 5, 6};
919 auto result =
stl_reject([](
int x) {
return x % 2 == 0; }, v);
921 EXPECT_EQ(result, (std::vector<int>{1, 3, 5}));
931 std::vector<int>
large;
933 for (
int i = 0; i < 1000; ++i)
934 large.push_back(i % 100);
950 for (
int i = 0; i < 10000; ++i)
960 std::vector<int>
large;
962 for (
int i = 0; i < 1000; ++i)
963 large.push_back(i % 100);
969 for (
const auto & [val,
count] : result)
975 std::vector<int>
large;
977 for (
int i = 0; i < 1000; ++i)
984 for (
const auto & [key,
group] : result)
994 std::vector<int> empty;
1001 std::vector<int>
single = {42};
1009 std::vector<int>
all_same(100, 42);
1024 std::vector<int> empty;
1031 std::vector<int>
single = {42};
1040 std::vector<int> empty;
1041 auto result =
stl_group_by([](
int x) {
return x; }, empty);
1047 std::vector<int>
single = {42};
1056 std::vector<int> v = {10, 20, 30, 40, 50};
1057 auto result =
stl_group_by([](
int x) {
return x % 10; }, v);
1071 for (
int i = 0; i < 64; ++i)
1080 std::vector<int>
small = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4};
1108 size_t operator()(
const Point & p)
const
1110 return std::hash<int>{}(p.
x) ^ (std::hash<int>{}(p.
y) << 1);
1130 std::vector<Point> points = {{1, 2}, {3, 4}, {1, 2}, {5, 6}, {3, 4}};
1140 std::vector<Point> points;
1141 points.reserve(200);
1142 for (
int i = 0; i < 200; ++i)
1143 points.push_back({i % 50, i % 25});
1153 std::vector<Point> points = {{1, 2}, {3, 4}, {1, 2}, {5, 6}, {1, 2}};
1158 auto it = std::find_if(result.begin(), result.end(),
1159 [](
const auto & p) { return p.first.x == 1 && p.first.y == 2; });
1166 std::vector<Point> points = {
1167 {1, 1}, {-1, 1}, {-1, -1}, {1, -1},
1168 {2, 3}, {-2, 3}, {-2, -3}, {2, -3}
1172 if (p.x >= 0 && p.y >= 0)
return 1;
1173 if (p.x < 0 && p.y >= 0)
return 2;
1174 if (p.x < 0 && p.y < 0)
return 3;
1181 for (
const auto & [
quad,
pts] : result)
1194 static int move_count;
1195 static int copy_count;
1197 MoveTracker(
int v = 0) : value(v) {}
1199 MoveTracker(
const MoveTracker &
other) : value(
other.value)
1210 MoveTracker & operator=(
const MoveTracker &
other)
1212 value =
other.value;
1217 MoveTracker & operator=(MoveTracker &&
other)
noexcept
1219 value =
other.value;
1227 return value ==
other.value;
1237int MoveTracker::move_count = 0;
1238int MoveTracker::copy_count = 0;
1255 std::vector<int> v = {1, 2, 3};
1256 std::string
prefix =
"num_";
1259 return prefix + std::to_string(x);
1269 std::vector<int> v = {1, 2, 3, 4, 5};
1274 auto result =
stl_filter([&call_count, threshold](
int x)
mutable {
1276 return x > threshold;
1285 std::vector<std::string> words = {
"hello",
" ",
"world"};
1287 auto result =
stl_foldl(std::string{}, [](std::string
acc,
const std::string &
w) {
1300 std::list<int>
l = {1, 2, 1, 3, 2, 4};
1307 std::deque<int> d = {1, 2, 1, 3, 2, 4};
1314 std::list<int>
l = {1, 2, 2, 3, 3, 3};
1321 std::list<std::string>
l = {
"a",
"bb",
"ccc",
"dd",
"e"};
1322 auto result =
stl_group_by([](
const std::string & s) {
return s.length(); },
l);
1332 std::vector<int> v = {5, 3, 5, 1, 3, 7, 1, 5};
1347 for (
int i = 199; i >= 0; --i)
1348 v.push_back(i % 100);
1361 std::vector<int> v = {5, 3, 5, 1, 3, 7, 1, 5};
1377 std::vector<int> v = {15, 23, 31, 42, 54};
1378 auto result =
stl_group_by([](
int x) {
return x % 10; }, v);
1393 std::vector<std::string> v = {
"apple",
"banana",
"apple",
"cherry",
"banana"};
1404 std::vector<std::string> v;
1406 for (
int i = 0; i < 200; ++i)
1407 v.push_back(
"str_" + std::to_string(i % 50));
1415 std::vector<std::string> v = {
"a",
"bb",
"ccc",
"dd",
"eee",
"f"};
1416 auto result =
stl_group_by([](
const std::string & s) {
return s.length(); }, v);
1423 std::vector<std::string> v = {
"apple",
"apricot",
"banana",
"blueberry",
"cherry"};
1424 auto result =
stl_group_by([](
const std::string & s) {
return s[0]; }, v);
1436 for (
int i = 0; i < 63; ++i)
1437 v.push_back(i % 30);
1446 for (
int i = 0; i < 64; ++i)
1447 v.push_back(i % 30);
1456 for (
int i = 0; i < 65; ++i)
1457 v.push_back(i % 30);
1469 std::vector<int> v = {1, 2, 1, 3, 2, 4};
1478 std::vector<int> v = {1, 2, 3, 4, 5, 6, 1, 2, 3};
1487 std::vector<int> v = {1, 2, 3, 4, 5, 6};
1490 return std::make_pair(p.first,
stl_foldl(0, std::plus<int>{}, p.second));
1500#include <forward_list>
1504 std::forward_list<int>
fl = {1, 2, 3, 4, 5};
1505 auto result =
stl_map([](
int x) {
return x * 2; },
fl);
1514 std::forward_list<int>
fl = {1, 2, 3, 4, 5, 6};
1515 auto result =
stl_filter([](
int x) {
return x % 2 == 0; },
fl);
1523 std::forward_list<int>
fl = {1, 2, 3, 4, 5};
1531 std::forward_list<int>
fl = {1, 2, 1, 3, 2, 4};
1539 std::forward_list<int>
fl = {1, 2, 2, 3, 3, 3};
1547 std::forward_list<int>
fl = {1, 2, 3, 4, 5, 6};
1555 std::forward_list<int>
fl = {1, 2, 3, 4, 5};
1564 std::forward_list<int>
fl = {1, 2, 3, 4, 5};
1574 std::forward_list<int>
fl = {1, 2, 3, 4, 5};
1602 std::vector<NonHashable> v = {{1, 2}, {3, 4}, {1, 2}, {5, 6}};
1611 std::vector<NonHashable> v;
1613 for (
int i = 0; i < 200; ++i)
1614 v.push_back({i % 50, i % 25});
1624 std::vector<NonHashable> v = {{1, 2}, {3, 4}, {1, 2}, {1, 2}};
1629 auto it = std::find_if(result.begin(), result.end(),
1630 [](
const auto & p) { return p.first.x == 1 && p.first.y == 2; });
1638 std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8};
1642 return NonHashable{x % 2, x % 3};
1656struct StatefulCallable
1661 explicit StatefulCallable(
int t) : threshold(t) {}
1663 bool operator()(
int x)
1666 return x > threshold;
1670struct StatefulMapper
1675 explicit StatefulMapper(
int m) : multiplier(m) {}
1677 int operator()(
int x)
1680 return x * multiplier;
1688 std::vector<int> v = {1, 2, 3, 4, 5};
1691 StatefulCallable
pred(3);
1701 std::vector<int> v = {1, 2, 3};
1703 StatefulMapper
mapper(10);
1714 std::vector<int> v = {1, 2, 3, 4, 5};
1731 std::vector<int> v = {2, 4, 6, 8, 10};
1734 bool result =
stl_all([&call_count](
int x) {
1745 std::vector<int> v = {1, 2, 3, 4, 5};
1748 bool result =
stl_exists([&call_count](
int x) {
1763 std::vector<int> empty;
1770 std::vector<int> empty;
1777 std::vector<int> empty;
1784 std::vector<int> empty;
1791 std::vector<int> empty;
1798 std::vector<int> empty;
1799 auto result =
stl_scan_left(42, [](
int a,
int b) {
return a + b; }, empty);
1807 std::vector<int> empty;
1808 auto result =
stl_scan_right(42, [](
int a,
int b) {
return a + b; }, empty);
1816 std::vector<int> empty;
1823 std::vector<int> empty;
1830 std::vector<int> empty;
1842 std::vector<int>
large(64);
1850 std::vector<int>
small = {1, 2, 3, 4, 5};
1859 ::testing::InitGoogleTest(&
argc,
argv);
Functional programming utilities for C++ Standard Library containers.
size_t size() const noexcept
Count the number of elements of the list.
Rectangular point in the plane.
bool operator==(const Point &point) const
iterator end() noexcept
Return an STL-compatible end iterator.
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
Freq_Node * pred
Predecessor node in level-order traversal.
Main namespace for Aleph-w library functions.
auto stl_first(const Container &c)
Get first element.
std::vector< T > stl_scan_left(T init, Op &&op, const Container &c)
Scan left - fold with all intermediate results.
auto stl_span(Pred &&pred, const Container &c)
Split at predicate boundary (span in Haskell).
auto stl_take_last(size_t n, const Container &c)
Take last n elements.
auto stl_chunks(size_t n, const Container &c)
Split container into chunks of size n (each_slice in Ruby).
int stl_compare(const Container1 &c1, const Container2 &c2)
Compare two containers lexicographically.
auto stl_min_max(const Container &c)
Get both min and max in a single pass.
auto stl_last(const Container &c)
Get last element.
bool operator==(const DynList< T > &l1, const DynList< T > &l2)
Equality operator for DynList.
bool completed() const noexcept
Return true if all underlying iterators are finished.
auto stl_distinct(const Container &c)
Remove all duplicates (keeps first occurrence).
auto stl_max(const Container &c)
Get maximum element.
size_t size(Node *root) noexcept
auto stl_flatten(const Container &c)
Flatten a container of containers.
auto stl_reject(Pred &&pred, const Container &c)
Filter out elements (reject in Ruby, opposite of filter).
auto stl_filter(Pred &&pred, const Container &c)
Filter elements satisfying predicate.
auto stl_arrangements(size_t k, const Container &c)
Generate all k-arrangements (k-permutations) of a container.
auto stl_drop(size_t n, const Container &c)
Drop first n elements, return the rest.
auto stl_enumerate_to_pairs(const Container &c)
Enumerate container (return pairs of index and element).
bool stl_equal(const Container1 &c1, const Container2 &c2)
Check equality of two containers.
auto stl_concat(const Container1 &c1, const Container2 &c2)
Concatenate two containers.
auto stl_combinations(size_t k, const Container &c)
Generate all k-combinations of a container.
auto stl_take_while(Pred &&pred, const Container &c)
Take elements while predicate is true.
auto stl_find_mapi(Op &&op, const Container &c)
Find and map with index (find_mapi in ML).
auto stl_nth(const size_t n, const Container &c)
Get n-th element.
auto stl_map(Op &&op, const Container &c)
Map operation - transform each element.
bool stl_mem(const T &target, const Container &c)
Check if element exists in container (mem in ML).
std::optional< size_t > stl_find_index(Pred &&pred, const Container &c)
Find index of first element satisfying predicate.
T stl_foldl(T init, Op &&op, const Container &c)
Left fold (foldl) - reduce from left to right.
auto stl_min_by(Key &&key, const Container &c)
Get minimum element by key function.
std::vector< T > stl_linspace(T start, T end, size_t n)
Generate n evenly spaced values between start and end.
bool stl_exists(Pred &&pred, const Container &c)
Check if any element satisfies predicate.
auto stl_take(size_t n, const Container &c)
Take first n elements.
auto stl_generate(size_t n, Gen &&gen)
Generate a vector using a generator function.
std::vector< T > stl_range(T start, T end, T step=1)
Generate a range of values [start, end] with given step.
auto stl_init(const Container &c)
Get all elements except the last (init in Haskell).
bool stl_traverse_permutations(Op &&op, const Container &c)
Traverse all permutations of a container.
size_t stl_count_value(const T &target, const Container &c)
Count occurrences of a value.
auto stl_sort(const Container &c)
Return sorted copy of container.
static void prefix(Node *root, DynList< Node * > &acc)
auto stl_permutations(const Container &c)
Generate all permutations of a container.
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
auto stl_tally(const Container &c)
Count occurrences of each element (tally in Ruby, frequencies).
bool stl_all(Pred &&pred, const Container &c)
Check if all elements satisfy predicate.
auto stl_partition(Pred &&pred, const Container &c)
Partition elements by predicate.
auto stl_unique(const Container &c)
Remove consecutive duplicates.
auto stl_mapi(Op &&op, const Container &c)
Map with index (mapi in ML).
size_t stl_count(Pred &&pred, const Container &c)
Count elements satisfying predicate.
void stl_for_each_indexed(Op &&op, const Container &c)
Apply operation to each element with index.
auto stl_sum(const Container &c)
Sum all elements.
auto stl_sliding_window(size_t n, const Container &c)
Sliding window of size n over container (each_cons in Ruby).
auto stl_max_by(Key &&key, const Container &c)
Get maximum element by key function.
auto stl_group_by(Key &&key, const Container &c)
Group elements by key function.
auto stl_min(const Container &c)
Get minimum element.
bool stl_none(Pred &&pred, const Container &c)
Check if no element satisfies predicate.
auto stl_reverse(const Container &c)
Return reversed copy of container.
auto stl_flat_map(Op &&op, const Container &c)
Flat map - map then flatten.
std::vector< T > stl_rep(size_t n, const T &value)
Generate a vector of n repeated values.
T stl_foldr(T init, Op &&op, const Container &c)
Right fold (foldr) - reduce from right to left.
std::vector< T > stl_scan_right(T init, Op &&op, const Container &c)
Scan right - right fold with all intermediate results.
auto stl_unzip_pairs(const Container &c)
Unzip pairs into two vectors.
auto stl_drop_while(Pred &&pred, const Container &c)
Drop elements while predicate is true, return the rest.
auto stl_intersperse(const T &sep, const Container &c)
Insert element between each pair (intersperse in Haskell).
auto stl_cartesian_product(const std::vector< std::vector< T > > &containers)
Generate cartesian product of multiple containers.
auto stl_product(const Container &c)
Product of all elements.
auto stl_tail(const Container &c)
Get all elements except the first (tail in Haskell).
auto stl_filteri(Pred &&pred, const Container &c)
Filter with index (filteri in ML).
auto stl_find(Pred &&pred, const Container &c)
Find first element satisfying predicate.
void stl_for_each(Op &&op, const Container &c)
Apply operation to each element (for_each).
auto stl_split_at(size_t n, const Container &c)
Split at position n, returning (take n, drop n) in one pass.
auto stl_sort_by(Cmp &&cmp, const Container &c)
Return sorted copy using custom comparator.
auto stl_power_set(const Container &c)
Generate power set (all subsets) of a container.
auto stl_group(const Container &c)
Group consecutive equal elements.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
auto stl_zip_to_pairs(const Container1 &c1, const Container2 &c2)
Zip two containers into pairs.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
auto stl_find_last(Pred &&pred, const Container &c)
Find last element satisfying predicate.
size_t operator()(const MoveTracker &m) const
size_t operator()(const Point &p) const