This generates a new list, and appends to it every time the current list value satisfies the condition. It then recursively calls the filter on the next value.
111 lines
2.1 KiB
C++
111 lines
2.1 KiB
C++
/* list.cpp
|
|
* Date: 2021-11-20
|
|
* Author: Aryadev Chavali
|
|
*/
|
|
|
|
#include <cstdio>
|
|
#include <iostream>
|
|
#include <cstdlib>
|
|
|
|
template <typename T>
|
|
struct List
|
|
{
|
|
T value;
|
|
struct List<T> *next;
|
|
|
|
~List()
|
|
{
|
|
if (next == nullptr)
|
|
return;
|
|
delete next;
|
|
}
|
|
};
|
|
|
|
template <typename T>
|
|
List<T> *append(List<T> *lst, T value)
|
|
{
|
|
List<T> *node;
|
|
if (lst == nullptr)
|
|
{
|
|
node = new List<T>;
|
|
node->value = value;
|
|
node->next = nullptr;
|
|
return node;
|
|
}
|
|
|
|
for (node = lst; node->next != nullptr; node = node->next)
|
|
continue;
|
|
|
|
node->next = new List<T>;
|
|
node->next->value = value;
|
|
node->next->next = nullptr;
|
|
return lst;
|
|
}
|
|
|
|
/** Reverse a list
|
|
*/
|
|
template <typename T>
|
|
List<T> *reverse(List<T> *lst, List<T> *prev = nullptr)
|
|
{
|
|
auto next = lst->next;
|
|
lst->next = prev;
|
|
if (next == nullptr)
|
|
return lst;
|
|
return reverse(next, lst);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
void map(List<T> *lst, U (*f)(T))
|
|
{
|
|
if (!lst)
|
|
return;
|
|
lst->value = f(lst->value);
|
|
map(lst->next, f);
|
|
}
|
|
|
|
template <typename T>
|
|
T reduce(List<T> *lst, T (*reducer) (T, T), T init = 0)
|
|
{
|
|
if (!lst)
|
|
return init;
|
|
if (!init)
|
|
init = lst->value;
|
|
else
|
|
init = reducer(init, lst->value);
|
|
return reduce(lst->next, reducer, init);
|
|
}
|
|
|
|
template <typename T>
|
|
List<T> *filter(List<T> *lst, bool (*f)(T), List<T> *new_lst = nullptr)
|
|
{
|
|
if (!lst)
|
|
return new_lst;
|
|
if (f(lst->value))
|
|
new_lst = append(new_lst, lst->value);
|
|
return filter(lst->next, f, new_lst);
|
|
}
|
|
|
|
template <typename T>
|
|
std::ostream& operator<<(std::ostream& ostream, const List<T> *lst)
|
|
{
|
|
if (!lst)
|
|
return ostream;
|
|
ostream << "|" << lst->value << lst->next;
|
|
return ostream;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
auto lst = append<int>(nullptr, 1);
|
|
for (int i = 2; i < 10; ++i)
|
|
lst = append(lst, i);
|
|
std::cout << lst << std::endl;
|
|
lst = reverse(lst);
|
|
std::cout << lst << std::endl;
|
|
map<int, int>(lst = reverse(lst), [](int x){ return x * 2; });
|
|
std::cout << lst << std::endl;
|
|
std::cout << reduce<int>(lst, [](int a, int b) { return a + b; }, 0) << std::endl;
|
|
delete lst;
|
|
return 0;
|
|
}
|