Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <functional>
- #include <limits>
- #include <queue>
- #include <stdexcept>
- #include <string>
- #include <unordered_map>
- #include <utility>
- #include <variant>
- #include <any>
- #include "match_syntax.hpp"
- #include "scl/traits.hpp"
- static std::array keyboard_array = {
- std::array { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' },
- std::array { 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P' },
- std::array { 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ';' },
- std::array { 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/' }
- };
- inline auto get_keyboard_pos(char symbol) {
- static std::array<std::pair<size_t, size_t>, 256> map = []() {
- std::array<std::pair<size_t, size_t>, 256> result;
- std::fill(result.begin(), result.end(),
- std::pair{std::numeric_limits<size_t>::max(),
- std::numeric_limits<size_t>::max()});
- for (size_t i = 0; i < keyboard_array.size(); ++i)
- for (size_t j = 0; j < keyboard_array[i].size(); ++j)
- result[keyboard_array[i][j]] = std::pair{i, j};
- return result;
- }();
- if (symbol >= 'a' && symbol <= 'z')
- symbol += 'A' - 'a';
- return map[symbol];
- }
- inline ssize_t abs(ssize_t n) {
- return n < 0 ? -n : n;
- }
- size_t estimate_char(char target, char actual) {
- auto [ti, tj] = get_keyboard_pos(target);
- auto [ai, aj] = get_keyboard_pos(actual);
- return size_t(abs(ssize_t(ti) - ssize_t(ai)) + abs(ssize_t(tj) - ssize_t(aj)));
- }
- template <typename IterT1, typename IterT2>
- size_t estimate_region(IterT1 t, IterT2 a, size_t count) {
- size_t cost = 0;
- for (size_t i = 0; i < count; ++i)
- cost += estimate_char(*(t + i), *(a + i));
- return cost;
- }
- template <typename StrT1, typename StrT2>
- size_t estimate_string(const StrT1& target, const StrT2& actual) {
- size_t diff_symbols_cost = 4;
- size_t cost = 0;
- size_t min = target.size(), max = actual.size();
- if (min > max)
- std::swap(min, max);
- cost += (max - min) * diff_symbols_cost;
- for (size_t ti = 0, ai = 0; ti < target.size() && ai < actual.size(); ++ti, ++ai) {
- if (ai != actual.size() - 1 && estimate_char(target[ti], actual[ai]) > 1) {
- auto cur_cost = estimate_region(target.begin() + ti, actual.begin() + ai, min - ti);
- auto shift_cost = estimate_region(target.begin() + ti, actual.begin() + ai + 1, min - ti);
- if (cur_cost > shift_cost) {
- ++ai;
- cost -= diff_symbols_cost - 1;
- }
- }
- cost += estimate_char(target[ti], actual[ai]);
- }
- return cost;
- }
- template <typename IterT>
- void keyboard_sort(IterT begin, IterT end, const std::string& target) {
- std::stable_sort(begin, end, [&](const auto& lhs, const auto& rhs) {
- return estimate_string(target, lhs) < estimate_string(target, rhs);
- });
- }
- template <typename T, typename AllocT = std::allocator<T>>
- class HeapyVector : public std::vector<T, AllocT> {
- public:
- template <typename FunctionT>
- HeapyVector(FunctionT&& comparator): _comparator(std::forward<FunctionT>(comparator)) {}
- template <typename V>
- void push(V&& value) {
- this->push_back(std::forward<T>(value));
- std::push_heap(this->begin(), this->end(), _comparator);
- }
- auto get_sorted(size_t count = std::numeric_limits<size_t>::max()) {
- if (count > this->size())
- count = this->size();
- std::vector<T, AllocT> result;
- result.reserve(count);
- std::vector<T, AllocT> tmp = *this;
- while (count--)
- result.emplace_back(pop());
- std::swap(tmp, *this);
- return result;
- }
- void make_heap() {
- std::make_heap(this->begin(), this->end(), _comparator);
- }
- T pop() {
- std::pop_heap(this->begin(), this->end(), _comparator);
- auto result = std::move(this->back());
- this->pop_back();
- return result;
- }
- T& top() {
- return this->front();
- }
- const T& top() const {
- return this->front();
- }
- private:
- std::function<bool(const T& lhs, const T& rhs)> _comparator;
- };
- class StringSimilarityVector : public HeapyVector<std::string> {
- public:
- StringSimilarityVector(const std::string& target):
- HeapyVector<std::string>([target](const auto& lhs, const auto& rhs) {
- return estimate_string(target, lhs) >= estimate_string(target, rhs); }) {};
- };
- class CommandArgsBadCast : public std::exception {
- public:
- explicit CommandArgsBadCast(std::string error): msg(std::move(error)) {}
- const char* what() const noexcept override { return msg.data(); }
- private:
- std::string msg;
- };
- class CommandArgsInvalidCount : public std::exception {
- public:
- explicit CommandArgsInvalidCount(std::string error): msg(std::move(error)) {}
- const char* what() const noexcept override { return msg.data(); }
- private:
- std::string msg;
- };
- class CommandArg {
- public:
- CommandArg(const std::string& str) {
- nma::match(str,
- "true" doo { var = true; },
- "on" doo { var = true; },
- "false" doo { var = false; },
- "off" doo { var = false; },
- condx(true) doo {
- try {
- var = std::stod(str);
- } catch (const std::exception& e) {
- var = str;
- }
- });
- }
- bool asBool() const {
- return nma::match(var,
- [](bool v) { return v; },
- [](auto) { throw CommandArgsBadCast("Argument not a Bool"); return false; } );
- }
- double asNumber() const {
- return nma::match(var,
- [](double v) { return v; },
- [](auto) { throw CommandArgsBadCast("Argument not a Double"); return 0.0; } );
- }
- std::string asString() const {
- return nma::match(var,
- [](bool v) { return std::string(v ? "true" : "false"); },
- [](double v) { return std::to_string(v); },
- [](const auto& v) { return std::string(v); });
- }
- private:
- std::variant<double, std::string, bool> var;
- };
- class AnyCommand {
- public:
- template <typename T>
- static auto wrap_command_arg(const CommandArg& arg)
- -> std::enable_if_t<std::is_floating_point_v<T> || std::is_integral_v<T>, T> {
- return T(arg.asNumber());
- }
- template <typename T>
- static auto wrap_command_arg(const CommandArg& arg)
- -> std::enable_if_t<std::is_same_v<std::string, std::decay_t<T>>, std::string> {
- return arg.asString();
- }
- template <typename T>
- static auto wrap_command_arg(const CommandArg& arg)
- -> std::enable_if_t<std::is_same_v<bool, std::decay_t<T>>, bool> {
- return arg.asBool();
- }
- template <typename T, size_t>
- using WrapTypeSequence = T;
- template <typename F, size_t... _ArgsCount>
- static auto generate_wrapper(F function, std::index_sequence<_ArgsCount...>&&) {
- return std::function{[=](const WrapTypeSequence<CommandArg, _ArgsCount>&... args) {
- function(wrap_command_arg<scl::arg_type_of_t<F, _ArgsCount>>(args)...);
- }};
- }
- template <typename FunctionT>
- AnyCommand(FunctionT function):
- _f(generate_wrapper(function, std::make_index_sequence<scl::args_count_of_v<FunctionT>>())) {}
- template <size_t... _Idxs>
- void _call(const std::vector<CommandArg>& args, std::index_sequence<_Idxs...>&&) {
- auto f = std::any_cast<const std::function<void(const decltype(args[_Idxs])&...)>>(_f);
- f(args[_Idxs]...);
- }
- template <size_t _ArgsMax = 16, size_t _ArgCounter = 0>
- void call(const std::vector<CommandArg>& args) {
- if constexpr (_ArgCounter == _ArgsMax)
- return;
- else {
- if (_ArgCounter == args.size()) {
- try {
- _call(args, std::make_index_sequence<_ArgCounter>());
- } catch (const std::bad_any_cast&) {
- throw CommandArgsInvalidCount("Invalid arguments count");
- }
- }
- call<_ArgsMax, _ArgCounter + 1>(args);
- }
- }
- private:
- std::any _f;
- };
- class CommandMgr {
- public:
- template <typename F>
- void add(const std::string& name, F function) {
- _commands.emplace(name, function);
- }
- void exec(const std::string& command) {
- }
- private:
- std::unordered_map<std::string, AnyCommand> _commands;
- };
- std::ostream& operator<< (std::ostream& os, const std::vector<std::string>& vec) {
- for (auto& e : vec)
- std::cout << e << " ";
- return os;
- }
- void hello(const std::string& name, int number) {
- std::cout << "Hello, " << name << " " << number << std::endl;
- }
- int main() {
- auto cmd = AnyCommand(hello);
- cmd.call({CommandArg("pidor"), CommandArg("9")});
- //std::vector<std::string> strs = {"ypdatw", "uppdate", "h[date", "ipfaate", "updatw", "upppdate"};
- //StringSimilarityVector sorter("update");
- //for (auto& s : strs)
- // sorter.push(s);
- //std::vector<std::string> strs = { "uppdate", "update" };
- //keyboard_sort(strs.begin(), strs.end(), "update");
- //std::cout << sorter.get_sorted() << "\n" << sorter.get_sorted(4) << std::endl;
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement