#pragma once #include #include #include #include #include #include #include #include namespace Utils { using namespace std::literals::string_literals; template constexpr typename std::underlying_type::type to_underlying(E e) noexcept { return static_cast::type>(e); } template static constexpr T wrap(T val, T min, T max) { return (val > max) ? min : (val < min) ? max : val; } static std::vector split(const std::string& s, const char delimiter = ' ') { std::vector tokens; std::string token; std::istringstream tokenStream(s); while (std::getline(tokenStream, token, delimiter)) { tokens.push_back(token); } return tokens; } static constexpr std::string_view WHITEPACE{" \t\n\r\f\v"}; static inline void rtrim(std::string& s, std::string_view t = WHITEPACE) { s.erase(s.find_last_not_of(t) + 1); } static inline void ltrim(std::string& s, std::string_view t = WHITEPACE) { s.erase(0, s.find_first_not_of(t)); } static inline void trim(std::string& s, std::string_view t = WHITEPACE) { rtrim(s, t); ltrim(s, t); } template static constexpr T clamp(T val, T min, T max) noexcept { return val < min ? min : val > max ? max : val; } template static void sort(Container& c) { std::sort(std::begin(c), std::end(c)); } template static typename Container::iterator find(const Container& c, const typename Container::value_type& value) { return std::find(std::begin(c), std::end(c), value); } template static typename Container::const_iterator find(const Container& c, const typename Container::value_type& value) { return std::find(std::begin(c), std::end(c), value); } template static typename Container::iterator find_if(const Container& c, Predicate pred) { return std::find_if(std::begin(c), std::end(c), pred); } template static void quick_remove_at(std::vector& v, std::size_t i) { assert(i < v.size()); v[i] = std::move(v.back()); v.pop_back(); } template static void quick_remove_at(std::vector& v, typename std::vector::iterator it) { assert(it != std::end(v)); *it = std::move(v.back()); v.pop_back(); } template static void insert_sorted(Container& v, const typename Container::value_type& item) { assert(true == std::is_sorted(begin(v), end(v))); const auto insert_pos(std::lower_bound(std::begin(v), std::end(v), item)); v.insert(insert_pos, item); } template static void print(const Container &v, const std::string& sep = ", "s) { using T = typename Container::value_type; std::copy(std::begin(v), std::end(v), std::ostream_iterator{std::cout, sep}); } template static void print_map(const AssociativeContainer &map, const std::string& sep = "\n"s) { for (auto& elem : map) { std::cout << elem.first << ": " << elem.second << sep; } } //removing from sequence containers template static void remove(std::vector& vector, T const& value) { vector.erase(std::remove(std::begin(vector), std::end(vector), value), std::end(vector)); } template static void remove(std::deque& deque, T const& value) { deque.erase(std::remove(std::begin(deque), std::end(deque), value), std::end(deque)); } static void remove(std::string& string, char letter) { string.erase(std::remove(std::begin(string), std::end(string), letter), std::end(string)); } template static void remove(AssociativeContainer& c, const T& key) { c.erase(key); } //filtered remove from sequence containers template static void remove_if(std::vector& vector, Predicate pred) { vector.erase(std::remove_if(std::begin(vector), std::end(vector), pred), std::end(vector)); } template static void remove_if(std::deque& deque, Predicate pred) { deque.erase(std::remove_if(std::begin(deque), std::end(deque), pred), std::end(deque)); } template static void remove_if(std::string& string, Predicate pred) { string.erase(std::remove_if(std::begin(string), std::end(string), pred), std::end(string)); } template static void remove_if(AssociativeContainer& c, Predicate pred) { auto i = std::begin(c); const auto last = std::end(c); while ((i = std::find_if(i, last, pred)) != last) { i = c.erase(i); } } //remove duplicates from sequence containers template static void unique(std::vector& vector) { vector.erase(std::unique(std::begin(vector), std::end(vector)), std::end(vector)); } template static void unique(std::deque& deque) { deque.erase(std::unique(std::begin(deque), std::end(deque)), std::end(deque)); } static void unique(std::string& string) { string.erase(std::unique(std::begin(string), std::end(string)), std::end(string)); } }