#pragma once #include #include #include #include #include #include namespace utils { using std::size_t; using IdType = size_t; const std::string ClassInternalVarName = "self"; const size_t MaxOperatorPrecedence = 4; enum class ReferenceModifier { Reference = 0, UniqueReference = 1, Dereference = 2 }; enum class IsConstModifier { Const = 0, Var = 1 }; enum class ClassModifier { Struct = 0, Class = 1 }; enum class AssignmentModifier { Assign = 0, Move = 1 }; enum class AliasModifier { Alias = 0, Type = 1, Let = 2 }; enum class AbstractTypeModifier { Basic = 0, Abstract = 1 }; enum class PartitionModifier { Exec = 0, Test = 1 }; enum class ValueType { Const = 0, Var = 1, Tmp = 2 }; inline ValueType IsConstModifierToValueType(IsConstModifier modifier) { switch (modifier) { case IsConstModifier::Const: return ValueType::Const; case IsConstModifier::Var: return ValueType::Var; } // unreachable exit(1); } template class Storage { public: Storage() = default; IdType GetId(const T& value) { IdType id = 0; auto value_position = value_to_id_.find(value); if (value_position == value_to_id_.end()) { id = id_to_value_.size(); value_to_id_[value] = id; id_to_value_.push_back(value); } else { id = value_position->second; } return id; } const T& GetValue(IdType id) { return id_to_value_[id]; } private: std::vector id_to_value_; std::unordered_map value_to_id_; }; template class Trie { // optimize ?? public: Trie() { verticles_.emplace_back(); } bool Insert(const std::vector& path, const Value& value) { return RecursiveInsert(verticles_[0], path, 0, value); } std::optional Find(const std::vector& path) { return RecursiveFind(verticles_[0], path, 0); } std::vector FindByPrefix(const std::vector& path) { return RecursiveFindByPrefix(verticles_[0], path, 0); } private: struct Vertex { std::unordered_map children_; std::optional value; }; bool RecursiveInsert(Vertex& vertex, const std::vector& path, size_t path_position, const Value& value) { if (path_position == path.size()) { if (vertex.value.has_value()) { return false; } vertex.value = value; return true; } auto child_iter = vertex.children_.find(path[path_position]); if (child_iter != vertex.children_.end()) { return RecursiveInsert(verticles_[child_iter->second], path, path_position + 1, value); } vertex.children_[path[path_position]] = verticles_.size(); verticles_.emplace_back(); return RecursiveInsert(verticles_.back(), path, path_position + 1, value); } std::optional RecursiveFind(Vertex& vertex, const std::vector& path, size_t path_position) { if (path_position == path.size()) { if (vertex.value.has_value()) { return std::nullopt; } return &vertex.value.value(); } auto child_iter = vertex.children_.find(path[path_position]); if (child_iter != vertex.children_.end()) { return RecursiveFind(verticles_[child_iter->second], path, path_position + 1); } return std::nullopt; } std::vector RecursiveFindByPrefix(Vertex& vertex, const std::vector& path, size_t path_position) { if (path_position == path.size()) { std::vector ans; RecursiveGetAll(vertex, ans); return ans; } auto child_iter = vertex.children_.find(path[path_position]); if (child_iter != vertex.children_.end()) { return RecursiveFindByPrefix(verticles_[child_iter->second], path, path_position + 1); } return {}; } void RecursiveGetAll(Vertex& vertex, std::vector& accumulator) { std::vector ans; if (vertex.value.has_value()) { accumulator.push_back(&vertex.value.value()); } for (auto& child : vertex.children_) { RecursiveGetAll(verticles_[child.second], accumulator); } } private: std::vector verticles_; }; class GroupsManager { // TODO: recall right algorithm name public: GroupsManager() = default; explicit GroupsManager(size_t n) { edges_.resize(n); ranks_.resize(n); for (size_t i = 0; i < n; ++i) { edges_[i] = i; ranks_[i] = 1; } } void Unite(size_t u, size_t v) { // TODO: recall choice algorithm u = GetGroupRoot(u); v = GetGroupRoot(v); if (ranks_[v] >= ranks_[u]) { edges_[u] = v; ranks_[v] = std::max(ranks_[u] + 1, ranks_[v]); } else { edges_[v] = u; // always ranks_[u] > ranks_[v] } } bool IsInOneGroup(size_t u, size_t v) { return GetGroupRoot(u) == GetGroupRoot(v); } size_t AddElement() { size_t id = edges_.size(); edges_.push_back(id); ranks_.push_back(1); return id; } size_t GetGroupRoot(size_t v) { if (edges_[v] == v) { return v; } return edges_[v] = GetGroupRoot(edges_[v]); } private: std::vector edges_; std::vector ranks_; }; // static void BackVisitDfs(size_t id, // std::vector& verticles, // std::vector& marks, // const std::vector>& edges, // size_t mark) { // if (marks[id] != 0) { // return; // } // // marks[id] = mark; // verticles.push_back(id); // // for (size_t i = 0; i < edges[id].size(); ++i) { // BackVisitDfs(id, verticles, marks, edges, mark); // } // } // // static std::vector BackTopSort(const std::vector>& edges_) { // std::vector sorted_verticles; // std::vector marks(edges_.size(), 0); // // for (size_t i = 0; i < marks.size(); ++i) { // BackVisitDfs(i, sorted_verticles, marks, edges_, 1); // } // // return sorted_verticles; // } } // namespace utils