Welcome to challenge two (and happy new years everyone)!
Today, our target is partition
- an algorithm that has a surprising number of uses. Partitions are useful concepts in algorithms such as quicksort
but also have a place in databases and divide and conquer
processing strategies.
Given some predicate function, the partition algorithm will place all elements that satisfy the predicate to the front of the list and return the index to the first element that doesn’t satisfy the predicate (we’ll call that index last
). That way, slice[0..last]
will return a sub range where each element satisfies the predicate.
It will be up to you to decide how to report any errors. For instance, if the range is empty, you could return a value (as you’ll see in the example code) or perhaps you prefer to return null
and use optionals instead.
Note:
Takes an input range as an argument
Takes a predicate function as an argument
Returns a handle to the first element where Predicate(x) -> false
Output range does not need to be sorted.
Example:
input = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }
Predicate: p(x) -> (x % 2) == 0
last = partition(input, p); // modifies "input" range
input[0..last] -> { 0, 2, 4, 6, 8 } // all even numbers.
Possible Implementation from: std::partition - cppreference.com
template<class ForwardIt, class UnaryPredicate>
ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p)
{
first = std::find_if_not(first, last, p);
if (first == last)
return first;
for (auto i = std::next(first); i != last; ++i)
if (p(*i))
{
std::iter_swap(i, first);
++first;
}
return first;
}
Bonus:
Write an iterator that mimics the partition functionality. The iterator has a
"next" function that returns the next value that satisfies the predicate or `null`
if it reaches the end of the input range.