#pragma once #include #include #include template struct CyclicVector { std::vector vector; size_t offset{0}; CyclicVector(const std::initializer_list& vector) : vector{vector} { } CyclicVector(const std::vector& vector) : vector{vector} { } template >> CyclicVector(const std::string& str) : vector{str.begin(), str.end()} { } template >> CyclicVector(const char (&str)[N]) { vector.resize(N - 1); // don't include \0 character for (size_t i = 0; i < N - 1; i++) { vector[i] = str[i]; } } void Rotate(int i) { if (i < 0) RotateLeft(-i); else RotateRight(i); } void RotateRight(int i) { offset = (offset + vector.size() - (i % vector.size())) % vector.size(); } void RotateLeft(size_t i) { offset = (offset + i) % vector.size(); } T& operator[](size_t i) { return vector[(i + offset) % vector.size()]; } const T& operator[](size_t i) const { return vector[(i + offset) % vector.size()]; } size_t size() const { return vector.size(); } bool empty() const { return vector.empty(); } size_t Find(const T& t) const { return std::find(begin(), end(), t).GetPos(); } struct iterator; struct const_iterator; iterator begin() { return iterator{*this, 0}; } iterator end() { return iterator{*this, vector.size()}; } const_iterator begin() const { return const_iterator{*this, 0}; } const_iterator end() const { return const_iterator{*this, vector.size()}; } const_iterator cbegin() const { return const_iterator{*this, 0}; } const_iterator cend() const { return const_iterator{*this, vector.size()}; } friend std::ostream& operator<<(std::ostream& os, const CyclicVector& vector) { os << "["; if (!vector.empty()) os << vector[0]; for (auto it = vector.cbegin() + 1; it != vector.cend(); it++) { os << ", " << *it; } os << "]"; return os; } class iterator { private: CyclicVector& data; size_t pos; public: using iterator_category = std::random_access_iterator_tag; using value_type = T; using difference_type = int; using pointer = T*; using reference = T&; iterator(CyclicVector& data, size_t pos) : data{data}, pos{pos} { } size_t GetPos() const { return pos; } reference operator*() const { return data[pos]; } pointer operator->() const { return &data[pos]; } iterator& operator++() { ++pos; return *this; } iterator operator++(int) { iterator ret = *this; ++(*this); return ret; } iterator& operator--() { --pos; return *this; } iterator operator--(int) { iterator ret = *this; --(*this); return ret; } iterator& operator+=(size_t advance) { if (std::numeric_limits::max() - pos < advance) { pos = data.size(); } else { pos += advance; if (pos >= data.size()) pos = data.size(); } return *this; } iterator& operator-=(size_t advance) { if (advance > pos) { pos = data.size(); } else { pos -= advance; } return *this; } iterator operator+(size_t advance) const { iterator ret = *this; ret += advance; return ret; } iterator operator-(size_t advance) const { iterator ret = *this; ret -= advance; return ret; } bool operator==(const iterator& other) const { return pos == other.pos; } bool operator!=(const iterator& other) const { return !(*this == other); } }; class const_iterator { private: const CyclicVector& data; size_t pos; public: using iterator_category = std::random_access_iterator_tag; using value_type = T; using difference_type = int; using pointer = const T*; using reference = const T&; const_iterator(const CyclicVector& data, size_t pos) : data{data}, pos{pos} { } size_t GetPos() const { return pos; } reference operator*() const { return data[pos]; } pointer operator->() const { return &data[pos]; } const_iterator& operator++() { ++pos; return *this; } const_iterator operator++(int) { const_iterator ret = *this; ++(*this); return ret; } const_iterator& operator--() { --pos; return *this; } const_iterator operator--(int) { const_iterator ret = *this; --(*this); return ret; } const_iterator& operator+=(size_t advance) { if (std::numeric_limits::max() - pos < advance) { pos = data.size(); } else { pos += advance; if (pos >= data.size()) pos = data.size(); } return *this; } const_iterator& operator-=(size_t advance) { if (advance > pos) { pos = data.size(); } else { pos -= advance; } return *this; } const_iterator operator+(size_t advance) const { const_iterator ret = *this; ret += advance; return ret; } const_iterator operator-(size_t advance) const { const_iterator ret = *this; ret -= advance; return ret; } bool operator==(const const_iterator& other) const { return pos == other.pos; } bool operator!=(const const_iterator& other) const { return !(*this == other); } }; };