// Experimental sliding window class. (1.00)
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <iterator>
// class MaxQueue
// Queue that evicts oldest elements when a specified
// size is exceeded.
template<typename T>
class MaxQueue : std::deque<T> {
typedef std::deque<T> _Base;
std::size_t m_maxlen;
public:
using _Base::front;
using _Base::empty;
using _Base::size;
using _Base::clear;
using _Base::begin;
using _Base::end;
MaxQueue(std::size_t maxlen)
: m_maxlen(maxlen)
{}
void push(T x) {
if (m_maxlen == 0)
return;
if (m_maxlen == _Base::size())
_Base::pop_front();
_Base::push_back(std::move(x));
}
void pop() {
_Base::pop_front();
}
};
// class SlidingWindow.
// Group a sequence into sequential n-element chunks.
// SlidingWindow(string("ABCDEF"), 4) -> ABCD, BCDE, CDEF
template<typename Iterable>
class SlidingWindow {
typedef typename Iterable::const_iterator iterator;
typedef typename Iterable::value_type value_type;
public:
typedef MaxQueue<value_type> result_type;
template<typename Iter>
SlidingWindow(Iter, Iter, std::size_t n);
SlidingWindow(Iterable, std::size_t n);
const result_type& next();
private:
Iterable m_v;
result_type m_q;
iterator m_first, m_last;
};
#if __cplusplus >= 201703
template<typename Iter>
SlidingWindow(Iter, Iter, std::size_t) ->
SlidingWindow<std::vector<typename std::iterator_traits<Iter>::value_type>>;
#endif // C++17
template<typename Iterable>
template<typename Iter>
SlidingWindow<Iterable>::SlidingWindow(Iter first, Iter last, std::size_t n)
: SlidingWindow({first, last}, n)
{}
template<typename Iterable>
SlidingWindow<Iterable>::SlidingWindow(Iterable v, std::size_t n)
: m_v(move(v)), m_q(n), m_first(begin(m_v)), m_last(end(m_v))
{
for (std::size_t i = 1; i < n && m_first != m_last; i++)
m_q.push(*m_first++);
}
template<typename Iterable>
auto SlidingWindow<Iterable>::next() -> const result_type&
{
if (m_first != m_last)
m_q.push(*m_first++);
else
m_q.clear();
return m_q;
}
// .
int main()
{
using std::cout;
using std::endl;
// max queue.
MaxQueue<int> q(5);
// push.
for (int i = 0; i < 10; i++) {
q.push(i);
for (auto x : q) cout << x << ' ';
cout << endl;
}
// copy.
MaxQueue<int> p = q;
// empty/pop.
while (!p.empty()) {
p.pop();
cout << endl;
for (auto x : p) cout << x << ' ';
}
// sliding window.
std::string s = "ABCDEFGH";
for (size_t i = 0; i <= s.size()+1; i++) {
// construct(iterable, n).
#if __cplusplus >= 201703
SlidingWindow sw(s, i);
#else
SlidingWindow<decltype(s)> sw(s, i);
#endif // C++17
cout << endl << i << "> ";
for (;;) {
auto window = sw.next();
if (window.empty())
break; // done.
for (auto x : window) cout << x;
cout << ' ';
}
}
for (size_t i = 0; i <= s.size()+1; i++) {
// construct(iterator, iterator, n).
#if __cplusplus >= 201703
SlidingWindow sw(begin(s), end(s), i);
#else
// The deduction guide uses vector but any iterable container
// can be used (here we use string).
SlidingWindow<decltype(s)> sw(begin(s), end(s), i);
#endif // C++17
cout << endl << i << "> ";
for (;;) {
auto window = sw.next();
if (window.empty())
break; // done.
for (auto x : window) cout << x;
cout << ' ';
}
}
}