32#ifndef AH_FUNCTIONAL_H
33#define AH_FUNCTIONAL_H
107 virtual const T &
get_item()
const override {
return item; }
108 virtual bool is_found() const noexcept
override {
return true; }
112 template <
typename tgtT,
typename srcT>
115 tgtT operator () (
const srcT & item)
const noexcept {
return static_cast<tgtT
>(item); }
119 template <
typename TR,
typename TD>
122 TR operator () (
const TR & ,
const TD & )
123 const noexcept {
return TR(); }
127 template <
typename T>
class DynList;
138 template <
typename T =
int,
template <
typename>
class Container = DynList>
142 for (
T i = start; i <= end; i +=
step)
157 template <
typename T =
int,
template <
typename>
class Container = DynList>
169 const auto step =
static_cast<double>(end - start) / (n - 1);
170 for (
size_t i = 0; i < n; ++i)
187 template <
typename T =
int,
template <
typename>
class Container = DynList,
190 ->
Container<std::decay_t<
decltype(op(start))>>
193 for (
T i = start; i <= end; i +=
step)
199 template <
typename T =
int,
template <
typename>
class Container = DynList,
203 ->
Container<std::decay_t<
decltype(op(start))>>
227 template <
typename T =
int,
template <
typename>
class Container = DynList>
231 for (
size_t i = 0; i < n; ++i)
244 template <
typename T =
int,
template <
typename>
class Container = DynList>
248 for (
T i = 0; i < n; ++i)
262 template <
typename T =
int> [[
nodiscard]]
inline
266 for (
size_t i = 0; i < n; ++i)
272 template <
typename T =
int> [[
nodiscard]]
inline
304 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
317 using T =
const typename Container::Item_Type *;
319 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
343 void each(
size_t start,
size_t end,
Op & op)
345 for (
size_t i = start; i <= end; ++i)
351 void each(
size_t start,
size_t end,
Op && op)
353 each(start, end, op);
385 for (
auto it = c.get_it(pos); it.has_curr();
389 catch (
const std::overflow_error &) { }
424 template <
class Container,
class Operation>
inline
427 container.traverse([&
operation] (
const auto & item)
436 template <
class Container,
class Operation>
inline
439 container.traverse([&
operation] (
const auto & item)
448 template <
class Container,
class Operation>
inline
456 template <
class Container,
class Operation>
inline const Container &
489 template <
class Container,
class Operation>
inline
493 for (
auto it = container.get_it(); it.has_curr(); it.next_ne(), ++i)
498 template <
class Container,
class Operation>
inline
527 template <
class Container,
class Operation>
inline
534 template <
class Container,
class Operation>
inline
541 template <
class Container,
class Operation>
inline
548 template <
class Container,
class Operation>
inline
578 template <
class Container,
class Operation>
inline
582 container.traverse([&
operation] (
const auto & item)
589 template <
class Container,
class Operation>
inline
593 container.traverse([&
operation] (
const auto & item)
600 template <
class Container,
class Operation>
inline
607 template <
class Container,
class Operation>
inline
614 template <
typename T>
617 bool operator () (
const T &)
const noexcept {
return true; }
692 template <
typename T,
class C,
class Op>
696 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
707 template <
typename T,
class Container,
class Operation> [[
nodiscard]]
inline
711 if constexpr (std::ranges::range<Container>)
717 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
748 template <
class Container1,
class Container2> [[
nodiscard]]
inline
749 DynList<std::pair<
typename Container1::Item_Type,
750 typename Container2::Item_Type>>
753 typedef typename Container1::Item_Type
T1;
754 typedef typename Container2::Item_Type
T2;
757 typename Container1::Iterator it1(a);
758 typename Container2::Iterator it2(b);
759 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
760 ret_val.
append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
791 template <
class Container1,
class Container2> [[
nodiscard]]
inline
792 DynList<std::tuple<
typename Container1::Item_Type,
793 typename Container2::Item_Type>>
796 typedef typename Container1::Item_Type
T1;
797 typedef typename Container2::Item_Type
T2;
798 using Tuple = std::tuple<T1, T2>;
801 typename Container1::Iterator it1(a);
802 typename Container2::Iterator it2(b);
803 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
835 template <
class Container1,
class Container2> [[
nodiscard]]
inline
836 DynList<std::pair<
typename Container1::Item_Type,
837 typename Container2::Item_Type>>
841 typedef typename Container1::Item_Type
T1;
842 typedef typename Container2::Item_Type
T2;
846 auto it2 = b.get_it();
847 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
848 ret_val.
append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
850 if (it1.has_curr()
or it2.has_curr())
872 template <
class Container1,
class Container2> [[
nodiscard]]
inline
873 DynList<std::tuple<
typename Container1::Item_Type,
874 typename Container2::Item_Type>>
877 typedef typename Container1::Item_Type
T1;
878 typedef typename Container2::Item_Type
T2;
879 using Tuple = std::tuple<T1, T2>;
882 typename Container1::Iterator it1(a);
883 typename Container2::Iterator it2(b);
884 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
887 if (it1.has_curr()
or it2.has_curr())
921 using Item =
typename Container::Item_Type;
922 using Pair = std::pair<Item, size_t>;
925 c.for_each([&i, &
ret] (
const Item & item) {
ret.
append(Pair(item, i++)); });
958 template <
class C1,
class C2,
959 class Eq = std::equal_to<typename C1::Item_Type>> [[
nodiscard]]
inline
964 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
965 if (
not (e(it1.get_curr(), it2.get_curr())))
968 return not (it1.has_curr()
or it2.has_curr());
972 template <
typename T> [[
nodiscard]]
inline
979 template <
class C1,
class C2,
class Eq> [[
nodiscard]]
inline
1011 template <
class C1,
class C2,
1012 class Eq = std::equal_to<typename C1::Item_Type>> [[
nodiscard]]
inline
1013 std::tuple<bool, size_t, typename C1::Item_Type, typename C2::Item_Type>
1016 using T =
typename C1::Item_Type;
1020 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne(), n++)
1022 auto &
i1 = it1.get_curr();
1023 auto &
i2 = it2.get_curr();
1025 return std::make_tuple(
false, n,
i1,
i2);
1028 return std::make_tuple(
not (it1.has_curr()
or it2.has_curr()), n,
T(),
T());
1057 template <
class C1,
class C2,
1058 class Cmp = std::less<typename C1::Item_Type>> [[
nodiscard]]
inline
1063 for (; it1.has_curr()
and it2.has_curr(); it1.next_ne(), it2.next_ne())
1065 auto &
curr1 = it1.get_curr();
1066 auto &
curr2 = it2.get_curr();
1073 if (
not it1.has_curr()
and not it2.has_curr())
1076 return it2.has_curr();
1095 template <
class C1,
class C2,
1096 class Eq = std::equal_to<typename C1::Item_Type>> [[
nodiscard]]
inline
1126 template <
class Container> [[
nodiscard]]
inline
1129 using T1 = std::decay_t<
decltype(
l.
get_first().first)>;
1130 using T2 = std::decay_t<
decltype(
l.
get_first().second)>;
1133 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1135 auto & curr = it.get_curr();
1140 return std::make_pair(std::move(l1), std::move(l2));
1169 template <
template <
typename>
class Container,
typename T1,
typename T2>
1175 for (
auto it =
l.
get_it(); it.has_curr(); it.next_ne())
1177 auto & curr = it.get_curr();
1178 l1.append(std::get<0>(curr));
1179 l2.append(std::get<1>(curr));
1182 return std::make_tuple(std::move(l1), std::move(l2));
1194 [[
nodiscard]]
inline std::pair<TgtContainer<typename SrcContainer::Item_Type>,
1197 std::function<
bool(
const typename SrcContainer::Item_Type &)>
operation)
1199 typedef typename SrcContainer::Item_Type
Type;
1214 template <
class Container> [[
nodiscard]]
inline
1218 using T =
typename Container::Key_Type;
1219 using Pair = std::pair<size_t, T>;
1222 return c.Container:: template
maps<Pair>([&i] (
const T & d)
1223 {
return Pair(i++, d); });
1228 template <
class Container> [[
nodiscard]]
inline
1232 using T =
typename Container::Key_Type;
1233 using Tuple = std::tuple<size_t, typename Container::Key_Type>;
1237 return Tuple(i++, d);
1262 template <
typename T,
template <
typename>
class Container>
1294 template <
class Container> [[
nodiscard]]
1297 using T =
typename Container::Item_Type;
1298 typename Container::Iterator it(c);
1300 for (
size_t i = 0; i < n; ++i, it.next())
1305 for (; it.has_curr(); it.next_ne())
1340 template <
typename T,
template <
typename>
class Container,
class Equal>
1341 [[
nodiscard]] std::pair<DynList<DynList<T>>,
size_t>
1344 using P = std::pair<DynList<DynList<T>>,
size_t>;
1352 auto it = c.get_it();
1358 for (it.next(); it.has_curr(); it.next_ne())
1360 auto & curr = it.get_curr();
1375 template <
typename T,
template <
typename>
class Container,
1376 class Equal = std::equal_to<T>>
1377 [[
nodiscard]] std::pair<DynList<DynList<T>>,
size_t>
1410 template <
typename T,
template <
typename>
class Container,
class Equal>
1411 [[
nodiscard]] std::pair<DynList<T>,
size_t>
1414 using P = std::pair<DynList<T>,
size_t>;
1420 auto it = c.get_it();
1426 for (it.next(); it.has_curr(); it.next_ne())
1428 auto & curr = it.get_curr();
1441 template <
typename T,
template <
typename>
class Container,
1442 class Equal = std::equal_to<T>>
1443 [[
nodiscard]] std::pair<DynList<T>,
size_t>
1473 template <
class Itor1,
class Itor2 = Itor1>
1488 template <
class C1,
class C2>
1495 bool has_curr() const noexcept {
return it1.has_curr() and it2.has_curr(); }
1509 return std::make_pair(it1.get_curr(), it2.get_curr());
1518 return std::make_pair(it1.get_curr_ne(), it2.get_curr_ne());
1545 return not (it1.has_curr() or it2.has_curr());
1563 template <
class C1,
class C2>
1567 using I1 =
typename C1::Iterator;
1568 using I2 =
typename C2::Iterator;
1575 template <
class C1,
class C2>
1579 using I1 =
typename C1::Iterator;
1580 using I2 =
typename C2::Iterator;
1583 for (
size_t i = 0; i < pos; ++i)
1594 template <
class C,
typename T,
typename ...
Args>
inline
1606 template <
class C,
typename ...
Args>
inline
1617 template <
class C,
typename T,
typename ...
Args>
inline
1629 template <
class C,
typename ...
Args>
inline
1638 template <
class C,
typename ...
Args>
1647 template <
class SrcC,
class TgtC>
1651 for (
auto it =
srcc.
get_it(); it.has_curr(); it.next_ne())
1658 template <
typename T,
typename ...
Args>
1667 template <
class C,
typename T,
typename ...
Args>
inline
1679 template <
class C,
typename ...
Args>
inline
1725 template <
typename T,
1726 template <
typename>
class C1,
1727 template <
typename>
class C2>
1734 for (
auto it =
curr_c.
get_it(); it.has_curr(); it.next_ne())
1751 template <
typename T,
1752 template <
typename>
class C1,
1753 template <
typename>
class C2,
1754 template <
typename>
class C3>
1758 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1774 template <
typename T,
1775 template <
typename>
class C1,
1776 template <
typename>
class C2,
1777 template <
typename>
class C3,
1778 template <
typename>
class C4>
1782 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1798 template <
typename T,
1799 template <
typename>
class C1,
1800 template <
typename>
class C2,
1801 template <
typename>
class C3,
1802 template <
typename>
class C4,
1803 template <
typename>
class C5>
1807 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
1831 template <
typename T> [[
nodiscard]]
inline
1834 for (
const auto & v : values)
1857 template <
typename T> [[
nodiscard]]
inline
1870 template <
typename T,
typename U,
typename ...
Args> [[
nodiscard]]
inline
1882 template <
class Container,
class Operation> [[
nodiscard]]
inline
1889 template <
class Container,
class Operation> [[
nodiscard]]
inline
1922 template <
class Container,
class Pred> [[
nodiscard]]
inline
1923 typename Container::Item_Type *
1926 typename Container::Item_Type * result =
nullptr;
1927 container.traverse([&result, &
pred] (
auto & item)
1940 template <
class Container,
class Pred> [[
nodiscard]]
inline
1941 const typename Container::Item_Type *
1944 const typename Container::Item_Type * result =
nullptr;
1945 container.traverse([&result, &
pred] (
const auto & item)
1958 template <
class Container,
class Pred> [[
nodiscard]]
inline
1959 typename Container::Item_Type *
1966 template <
class Container,
class Pred> [[
nodiscard]]
inline
1967 const typename Container::Item_Type *
1995 template <
class Container,
class Pred> [[
nodiscard]]
inline
1996 std::optional<typename Container::Item_Type>
1999 std::optional<typename Container::Item_Type> result;
2000 container.traverse([&result, &
pred] (
const auto & item)
2013 template <
class Container,
class Pred> [[
nodiscard]]
inline
2014 std::optional<typename Container::Item_Type>
2029 template <
typename T,
class Container,
class Operation> [[
nodiscard]]
inline
2033 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2049 template <
class Container,
typename T =
typename Container::Item_Type>
2053 if constexpr (std::ranges::range<Container>)
2059 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2060 result = result + it.get_curr();
2072 template <
class Container,
typename T =
typename Container::Item_Type>
2076 if constexpr (std::ranges::range<Container>)
2082 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2083 result = result * it.get_curr();
2095 template <
class C1,
class C2> [[
nodiscard]]
inline
2100 for (
auto it =
c1.
get_it(); it.has_curr(); it.next_ne())
2101 result.
append(it.get_curr());
2102 for (
auto it =
c2.
get_it(); it.has_curr(); it.next_ne())
2103 result.
append(it.get_curr());
2114 template <
class Container,
class Pred> [[
nodiscard]]
inline
2119 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2121 const auto & item = it.get_curr();
2136 template <
class Container,
class Pred> [[
nodiscard]]
inline
2142 for (
auto it = c.get_it(); it.has_curr(); it.next_ne())
2144 const auto & item = it.get_curr();
2162 template <
class Container,
class Op> [[
nodiscard]]
inline
2168 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2170 auto sub = op(it.get_curr());
2171 for (
auto sit = sub.get_it();
sit.has_curr();
sit.next_ne())
2186 template <
typename T,
class Container> [[
nodiscard]]
inline
2192 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2194 acc =
acc + it.get_curr();
2210 template <
typename T,
class Container,
class Op> [[
nodiscard]]
inline
2216 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2218 acc = op(
acc, it.get_curr());
2232 class Cmp = std::less<typename Container::Item_Type>>
2233 [[
nodiscard]]
inline const typename Container::Item_Type *
2236 auto it = container.get_it();
2237 if (
not it.has_curr())
2240 const typename Container::Item_Type *
min_elem = &it.get_curr();
2241 for (it.next_ne(); it.has_curr(); it.next_ne())
2243 const auto & curr = it.get_curr();
2258 class Cmp = std::less<typename Container::Item_Type>>
2259 [[
nodiscard]]
inline const typename Container::Item_Type *
2262 auto it = container.get_it();
2263 if (
not it.has_curr())
2266 const typename Container::Item_Type *
max_elem = &it.get_curr();
2267 for (it.next_ne(); it.has_curr(); it.next_ne())
2269 const auto & curr = it.get_curr();
2284 class Cmp = std::less<typename Container::Item_Type>>
2285 [[
nodiscard]]
inline std::pair<
const typename Container::Item_Type *,
2286 const typename Container::Item_Type *>
2289 using T =
typename Container::Item_Type;
2290 auto it = container.get_it();
2291 if (
not it.has_curr())
2292 return {
nullptr,
nullptr};
2296 for (it.next_ne(); it.has_curr(); it.next_ne())
2298 const auto & curr = it.get_curr();
2314 template <
class Container,
class Pred> [[
nodiscard]]
inline
2318 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2319 if (
pred(it.get_curr()))
2331 template <
class Container> [[
nodiscard]]
inline
2333 const typename Container::Item_Type & value)
2335 for (
auto it = container.get_it(); it.has_curr(); it.next_ne())
2336 if (it.get_curr() == value)
2349 template <
class Container> [[
nodiscard]]
inline
2353 using T =
typename Container::Item_Type;
2354 using Tuple = std::tuple<size_t, T>;
2357 for (
auto it = container.get_it(); it.has_curr(); it.next_ne(), ++i)
2397 template <
class Container1,
class Container2> [[
nodiscard]]
inline
2398 DynList<std::pair<
typename Container1::Item_Type,
2399 typename Container2::Item_Type>>
2401 const typename Container1::Item_Type &
fill_a =
typename Container1::Item_Type(),
2402 const typename Container2::Item_Type &
fill_b =
typename Container2::Item_Type())
2404 using T1 =
typename Container1::Item_Type;
2405 using T2 =
typename Container2::Item_Type;
2409 auto it2 = b.get_it();
2412 while (it1.has_curr()
and it2.has_curr())
2414 ret_val.
append(std::pair<T1, T2>(it1.get_curr(), it2.get_curr()));
2420 while (it1.has_curr())
2427 while (it2.has_curr())
2468 template <
class Container1,
class Container2> [[
nodiscard]]
inline
2469 DynList<std::tuple<
typename Container1::Item_Type,
2470 typename Container2::Item_Type>>
2472 const typename Container1::Item_Type &
fill_a =
typename Container1::Item_Type(),
2473 const typename Container2::Item_Type &
fill_b =
typename Container2::Item_Type())
2475 using T1 =
typename Container1::Item_Type;
2476 using T2 =
typename Container2::Item_Type;
2477 using Tuple = std::tuple<T1, T2>;
2481 auto it2 = b.get_it();
2483 while (it1.has_curr()
and it2.has_curr())
2490 while (it1.has_curr())
2496 while (it2.has_curr())
2541 template <
class Container1,
class Container2> [[
nodiscard]]
inline
2543 std::optional<typename Container2::Item_Type>>>
2546 using T1 =
typename Container1::Item_Type;
2547 using T2 =
typename Container2::Item_Type;
2548 using Opt1 = std::optional<T1>;
2549 using Opt2 = std::optional<T2>;
2553 auto it2 = b.get_it();
2555 while (it1.has_curr()
and it2.has_curr())
2562 while (it1.has_curr())
2568 while (it2.has_curr())
2631 using Key = std::invoke_result_t<KeyFunc, const T&>;
2639 auto it = c.get_it();
2644 for (it.next_ne(); it.has_curr(); it.next_ne())
2646 const auto & item = it.get_curr();
2693 template <
typename T,
template <
typename>
class Container,
2699 using Key = std::invoke_result_t<KeyFunc, const T&>;
2707 auto it = c.get_it();
2712 for (it.next_ne(); it.has_curr(); it.next_ne())
2714 const auto & item = it.get_curr();
2767 template <
typename T,
template <
typename>
class Container,
2772 std::invoke_result_t<Reducer, const DynList<T>&>>>
2774 using Key = std::invoke_result_t<KeyFunc, const T&>;
2775 using ReducedType = std::invoke_result_t<Reducer, const DynList<T>&>;
2781 for (
auto it =
groups.
get_it(); it.has_curr(); it.next_ne())
2783 auto & [key,
group] = it.get_curr();
Exception handling system with formatted messages for Aleph-w.
#define ah_length_error()
Throws std::length_error unconditionally.
#define ah_invalid_argument()
Throws std::invalid_argument unconditionally.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
C++20 Ranges support and adaptors for Aleph-w containers.
Dynamic singly linked list with functional programming support.
T & insert(const T &item)
Insert a new item by copy.
T & append(const T &item)
Append a new item by copy.
T & get_first() const
Return the first item of the list.
T remove()
Remove the first item of the list.
Iterator that zips two other iterators.
auto get_curr_ne() const noexcept
Get current pair (no bounds check).
bool has_curr1() const noexcept
Check if first iterator has current element.
Pair_Iterator(const C1 &c1, const C2 &c2)
Construct from two containers.
Pair_Iterator(Itor1 i1, Itor2 i2)
Construct from two iterators.
bool has_curr() const noexcept
Check if both iterators have current elements.
bool was_traversed() const noexcept
Check if both iterators were completely traversed.
bool has_curr2() const noexcept
Check if second iterator has current element.
void next()
Advance both iterators (bounds-checked).
auto get_curr() const
Get current pair (bounds-checked).
void next_ne() noexcept
Advance both iterators (no bounds check).
void for_each(Operation &operation)
Traverse all the container and performs an operation on each element.
auto get_it() const
Return a properly initialized iterator positioned at the first item on the container.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Freq_Node * pred
Predecessor node in level-order traversal.
constexpr T ranges_fold_left(Container &&c, T init, BinaryOp &&op)
Fallback fold_left using range-based for loop.
Main namespace for Aleph-w library functions.
std::pair< DynList< T >, size_t > unique_sequential(const Container< T > &c, Equal &eq)
Extract unique consecutive items.
std::tuple< bool, size_t, typename C1::Item_Type, typename C2::Item_Type > are_eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Detailed equality check returning mismatch position and values.
DynList< T > flatten(const C2< C1< T > > &c)
Flatten a nested container of one level.
Container< T > nrange(const T start, const T end, const size_t n)
Generate exactly n values evenly spaced between [start, end].
auto group_by_reduce(const Container< T > &c, KeyFunc key_func, Reducer reducer) -> DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, std::invoke_result_t< Reducer, const DynList< T > & > > >
Group consecutive elements and apply a reducer to each group.
std::pair< const typename Container::Item_Type *, const typename Container::Item_Type * > minmax_ptr(const Container &container, Cmp cmp=Cmp())
Find both min and max elements in a single pass.
const Container::Item_Type * min_ptr(const Container &container, Cmp cmp=Cmp())
Find the minimum element in a container.
DynList< std::pair< std::optional< typename Container1::Item_Type >, std::optional< typename Container2::Item_Type > > > zip_longest_opt(const Container1 &a, const Container2 &b)
Zip two containers using optionals for missing values.
auto unzip(const Container &l)
Separate a list of pairs into two lists.
bool all(Container &container, Operation &operation)
Return true if all elements satisfy a predicate.
void reverse(Itor beg, Itor end)
Reverse elements in a range.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
DynList< T > scanl(const Container &container, const T &init, Op op)
Prefix scan with custom operation.
Itor unique(Itor __first, Itor __last, BinaryPredicate __binary_pred=BinaryPredicate())
Remove consecutive duplicates in place.
T Item_Type
Type of elements from the first container.
bool operator==(const DynList< T > &l1, const DynList< T > &l2)
Equality operator for DynList.
DynList< typename Container::Item_Type > drop_while(const Container &c, Pred pred)
Skip elements while predicate is true (drop_while).
auto set_range(const T start, const T end, const T step, Op &op) -> Container< std::decay_t< decltype(op(start))> >
Generate a range [start, end] and apply an operation to each value.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zipEq(const Container1 &a, const Container2 &b)
Zip two containers; throw if lengths differ.
DynList< T > intercept(const Container< T > &c1, const Container< T > &c2)
std::pair< TgtContainer< typename SrcContainer::Item_Type >, TgtContainer< typename SrcContainer::Item_Type > > partition(const SrcContainer &c, std::function< bool(const typename SrcContainer::Item_Type &)> operation)
Partition a container into two based on a predicate.
bool containers_eq(const C1 &c1, const C2 &c2, Eq e)
DynList< std::pair< T, size_t > > repeated_with_index(const Container< T > &c)
Container2< typename Container1::Item_Type > filter(Container1 &container, Operation &operation)
Filter elements that satisfy operation.
bool is_inside(const T &val, const DynList< T > &values)
Check if a value is present in a list.
DynList< T > repeated(const Container< T > &c)
DynList< typename Container::Item_Type > take_while(const Container &c, Pred pred)
Return elements while predicate is true (take_while).
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip(const Container1 &a, const Container2 &b)
Zip two containers into a list of pairs.
Pair_Iterator< typename C1::Iterator, typename C2::Iterator > get_pair_it(const C1 &c1, const C2 &c2)
Create a Pair_Iterator for two containers.
T foldr(const Container &container, const T &init, Operation operation)
Right fold (reduce).
auto enumerate(const Container &c)
Return pairs of (element, index).
size_t append_in_container(C &c, Args ... args)
Append multiple items into a container.
bool is_equal(const T &val)
Variadic check for equality against multiple values.
T foldl(const Container &container, const T &init, Operation operation)
Classic left fold (reduce).
std::decay_t< typename HeadC::Item_Type > T
bool exists(Container &container, Operation &operation)
Return true if at least one element satisfies a predicate.
auto gen_seq_list_tuples(const Container &c, size_t n)
Generate all sequential tuples (sliding windows) of size n.
bool contains(const std::string_view &str, const std::string_view &substr)
Check if substr appears inside str.
DynList< T > build_dynlist(Args ... args)
Build a DynList with the given items.
std::optional< typename Container::Item_Type > find_opt(const Container &container, Pred &pred)
Find the first element satisfying pred (safe version).
auto flat_map(const Container &container, Op op) -> DynList< typename std::decay_t< decltype(op(std::declval< typename Container::Item_Type >()))>::Item_Type >
Apply operation and flatten results (flatMap/concatMap).
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzip(const Container1 &a, const Container2 &b)
Zip two containers into a list of tuples.
T product(const Container &container, const T &init=T{1})
Compute product of all elements.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
DynList< typename Container::Item_Type * > pointers_list(Container &c)
Create a list of pointers to items in a container.
DynList< std::pair< size_t, typename Container::Key_Type > > indexes(const Container &c)
Return pairs of (index, key).
DynList< typename Container::Item_Type > sublist(const Container &c, size_t pos, size_t stride)
Extract a sublist using a stride.
bool lesser(const C1 &c1, const C2 &c2, Cmp cmp=Cmp())
Lexicographical comparison between two containers.
TgtC assign_container(const SrcC &srcc)
Convert one container type to another.
DynList< std::tuple< size_t, typename Container::Item_Type > > enumerate_tuple(const Container &container)
Zip containers with an index (enumerate with zip).
const Container::Item_Type * max_ptr(const Container &container, Cmp cmp=Cmp())
Find the maximum element in a container.
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzipEq(const Container1 &a, const Container2 &b)
Zip two containers into tuples; throw if lengths differ.
Operation for_each(Itor beg, const Itor &end, Operation op)
Apply an operation to each element in a range.
std::pair< DynList< DynList< T > >, size_t > sequential_groups(const Container< T > &c, Equal &eq)
Group consecutive equal elements together.
size_t insert_in_container(C &c, Args ... args)
Insert multiple items into a container.
DynList< std::tuple< size_t, typename Container::Key_Type > > tindexes(const Container &c)
Return tuples of (index, key).
Itor::difference_type count_if(Itor beg, const Itor &end, Operation op)
Count elements satisfying a predicate.
DynList< T > scanl_sum(const Container &container, const T &init)
Compute running sums (scanl with addition).
DynList< std::tuple< typename Container1::Item_Type, typename Container2::Item_Type > > tzip_longest(const Container1 &a, const Container2 &b, const typename Container1::Item_Type &fill_a=typename Container1::Item_Type(), const typename Container2::Item_Type &fill_b=typename Container2::Item_Type())
Zip two containers into tuples, padding the shorter one.
DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, DynList< T > > > group_by_eq(const Container< T > &c, KeyFunc key_func, KeyEqual key_equal)
Group consecutive elements by a key function with custom equality.
std::string concat(const Args &... args)
Concatenate multiple streamable arguments into a single std::string.
DynList< std::pair< typename Container1::Item_Type, typename Container2::Item_Type > > zip_longest(const Container1 &a, const Container2 &b, const typename Container1::Item_Type &fill_a=typename Container1::Item_Type(), const typename Container2::Item_Type &fill_b=typename Container2::Item_Type())
Zip two containers, padding the shorter one with a fill value.
std::ostream & join(const C &c, const std::string &sep, std::ostream &out)
Join elements of an Aleph-style container into a stream.
Container::Item_Type * find_ptr(Container &container, Pred &pred)
Find the first element satisfying pred.
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
void enum_for_each(const Container &container, Operation &operation)
Apply an operation to each element and its index.
C build_container(Args ... args)
Build a container with the given items.
DynList< std::pair< std::invoke_result_t< KeyFunc, const T & >, DynList< T > > > group_by(const Container< T > &c, KeyFunc key_func)
Group consecutive elements by a key function.
Container< T > contiguous_range(T start, const size_t n)
Generate n contiguous values starting from start.
bool none(const Container &container, Operation &operation)
Return true if no element satisfies operation.
void each(size_t start, size_t end, Op &op)
Execute an operation repeatedly over a range of indices.
size_t remove_from_container(C &c, Args ... args)
Remove multiple items from a container.
std::tuple< Container< T1 >, Container< T2 > > tunzip(const Container< std::tuple< T1, T2 > > &l)
Separate a list of tuples into two containers.
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.
DynList< T > rep(size_t n, const T &item)
Create a sequence of repeated items.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Default filter operation (always true).
Default folding operation (returns default-constructed accumulator).
Default mapping operation (identity).
Abstract base class for optional-like results.
virtual bool is_found() const noexcept=0
virtual const T & get_item() const =0
Represents a missing value.
virtual T & get_item() override
virtual const T & get_item() const override
virtual bool is_found() const noexcept override
Represents a found value (stored by reference).
virtual bool is_found() const noexcept override
virtual const T & get_item() const override
virtual T & get_item() override