diff --git a/barinov.egor/T2/t2.cpp b/barinov.egor/T2/t2.cpp deleted file mode 100644 index c0a2bbc4..00000000 --- a/barinov.egor/T2/t2.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace barinov -{ - struct DelimiterIO - { - char expected; - }; - - struct LongLongIO - { - long long& value; - }; - - struct RationalIO - { - std::pair& value; - }; - - struct StringIO - { - std::string& value; - }; - - std::istream& operator>>(std::istream& in, DelimiterIO&& dest) - { - std::istream::sentry sentry(in); - if (!sentry) - { - return in; - } - char c = '\0'; - in >> c; - if (in && c != dest.expected) - { - in.setstate(std::ios::failbit); - } - return in; - } - - std::istream& operator>>(std::istream& in, LongLongIO&& dest) - { - std::istream::sentry sentry(in); - if (!sentry) - { - return in; - } - long long value = 0; - in >> value; - if (!in) - { - return in; - } - char c1 = '\0', c2 = '\0'; - if (in.get(c1) && in.get(c2)) - { - if ((c1 == 'L' || c1 == 'l') && (c2 == 'L' || c2 == 'l')) - { - dest.value = value; - return in; - } - } - in.setstate(std::ios::failbit); - return in; - } - - std::istream& operator>>(std::istream& in, RationalIO&& dest) - { - std::istream::sentry sentry(in); - if (!sentry) - { - return in; - } - in >> DelimiterIO{ '(' }; - in >> DelimiterIO{ ':' }; - std::string label; - in >> label; - if (label != "N") - { - in.setstate(std::ios::failbit); - return in; - } - long long numerator = 0; - in >> numerator; - in >> DelimiterIO{ ':' }; - in >> label; - if (label != "D") - { - in.setstate(std::ios::failbit); - return in; - } - unsigned long long denominator = 0; - in >> denominator; - in >> DelimiterIO{ ':' }; - in >> DelimiterIO{ ')' }; - if (denominator == 0) - { - in.setstate(std::ios::failbit); - return in; - } - dest.value = { numerator, denominator }; - return in; - } - - std::istream& operator>>(std::istream& in, StringIO&& dest) - { - std::istream::sentry sentry(in); - if (!sentry) - { - return in; - } - in >> DelimiterIO{ '"' }; - std::getline(in, dest.value, '"'); - return in; - } - - class IofGuard - { - public: - IofGuard(std::basic_ios& s) : - s_(s), - fill_(s.fill()), - precision_(s.precision()), - fmt_(s.flags()) - { - } - - ~IofGuard() - { - s_.fill(fill_); - s_.precision(precision_); - s_.flags(fmt_); - } - - private: - std::basic_ios& s_; - char fill_; - std::streamsize precision_; - std::basic_ios::fmtflags fmt_; - }; - - struct DataStruct - { - long long key1; - std::pair key2; - std::string key3; - }; - - struct DataStructComparator - { - bool operator()(const DataStruct& a, const DataStruct& b) const - { - if (a.key1 != b.key1) - { - return a.key1 < b.key1; - } - double valA = static_cast(a.key2.first) - / static_cast(a.key2.second); - double valB = static_cast(b.key2.first) - / static_cast(b.key2.second); - if (std::fabs(valA - valB) > 1e-10) - { - return valA < valB; - } - return a.key3.length() < b.key3.length(); - } - }; - - std::istream& operator>>(std::istream& in, DataStruct& dest) - { - std::istream::sentry sentry(in); - if (!sentry) - { - return in; - } - DataStruct temp; - bool hasKey1 = false; - bool hasKey2 = false; - bool hasKey3 = false; - in >> DelimiterIO{ '(' }; - in >> DelimiterIO{ ':' }; - while (in && (!hasKey1 || !hasKey2 || !hasKey3)) - { - std::string label; - in >> label; - if (label == "key1" && !hasKey1) - { - in >> LongLongIO{ temp.key1 }; - in >> DelimiterIO{ ':' }; - hasKey1 = true; - } - else if (label == "key2" && !hasKey2) - { - in >> RationalIO{ temp.key2 }; - in >> DelimiterIO{ ':' }; - hasKey2 = true; - } - else if (label == "key3" && !hasKey3) - { - in >> StringIO{ temp.key3 }; - in >> DelimiterIO{ ':' }; - hasKey3 = true; - } - else - { - in.setstate(std::ios::failbit); - return in; - } - } - in >> DelimiterIO{ ')' }; - if (in && hasKey1 && hasKey2 && hasKey3) - { - dest = temp; - } - else - { - in.setstate(std::ios::failbit); - } - return in; - } - - std::ostream& operator<<(std::ostream& out, const DataStruct& src) - { - std::ostream::sentry sentry(out); - if (!sentry) - { - return out; - } - IofGuard guard(out); - out << "(:key1 " << src.key1 << "ll"; - out << ":key2 (:N " << src.key2.first - << ":D " << src.key2.second << ":)"; - out << ":key3 \"" << src.key3 << "\":)"; - return out; - } -} - -int main() -{ - using barinov::DataStruct; - using barinov::DataStructComparator; - - std::vector data; - - while (!std::cin.eof()) - { - DataStruct temp; - if (std::cin >> temp) - { - data.push_back(temp); - } - else - { - std::cin.clear(); - std::cin.ignore(std::numeric_limits::max(), '\n'); - } - } - - std::sort(data.begin(), data.end(), DataStructComparator()); - - std::copy( - data.begin(), - data.end(), - std::ostream_iterator(std::cout, "\n") - ); - - return 0; -} diff --git a/barinov.egor/T3/commands.cpp b/barinov.egor/T3/commands.cpp new file mode 100644 index 00000000..170894fb --- /dev/null +++ b/barinov.egor/T3/commands.cpp @@ -0,0 +1,202 @@ +#include "commands.hpp" +#include +#include +#include + +bool isEven(int n) +{ + return n % 2 == 0; +} + +bool isOdd(int n) +{ + return n % 2 != 0; +} + +double getAreaEven(const std::vector& polygons) +{ + double sum = 0.0; + for (const auto& polygon : polygons) + { + if (isEven(polygon.points.size())) + { + sum += getArea(polygon); + } + } + return sum; +} + +double getAreaOdd(const std::vector& polygons) +{ + double sum = 0.0; + for (const auto& polygon : polygons) + { + if (isOdd(polygon.points.size())) + { + sum += getArea(polygon); + } + } + return sum; +} + +double getAreaMean(const std::vector& polygons) +{ + if (polygons.empty()) + { + return 0.0; + } + double sum = 0.0; + for (const auto& polygon : polygons) + { + sum += getArea(polygon); + } + return sum / static_cast(polygons.size()); +} + +double getAreaByVertexCount(const std::vector& polygons, size_t vertexCount) +{ + double sum = 0.0; + for (const auto& polygon : polygons) + { + if (polygon.points.size() == vertexCount) + { + sum += getArea(polygon); + } + } + return sum; +} + +double getMaxArea(const std::vector& polygons) +{ + if (polygons.empty()) + { + return 0.0; + } + double maxArea = getArea(polygons[0]); + for (const auto& polygon : polygons) + { + double area = getArea(polygon); + if (area > maxArea) + { + maxArea = area; + } + } + return maxArea; +} + +size_t getMaxVertexes(const std::vector& polygons) +{ + if (polygons.empty()) + { + return 0; + } + size_t maxVertexes = polygons[0].points.size(); + for (const auto& polygon : polygons) + { + if (polygon.points.size() > maxVertexes) + { + maxVertexes = polygon.points.size(); + } + } + return maxVertexes; +} + +double getMinArea(const std::vector& polygons) +{ + if (polygons.empty()) + { + return 0.0; + } + double minArea = getArea(polygons[0]); + for (const auto& polygon : polygons) + { + double area = getArea(polygon); + if (area < minArea) + { + minArea = area; + } + } + return minArea; +} + +size_t getMinVertexes(const std::vector& polygons) +{ + if (polygons.empty()) + { + return 0; + } + size_t minVertexes = polygons[0].points.size(); + for (const auto& polygon : polygons) + { + if (polygon.points.size() < minVertexes) + { + minVertexes = polygon.points.size(); + } + } + return minVertexes; +} + +size_t countEven(const std::vector& polygons) +{ + size_t count = 0; + for (const auto& polygon : polygons) + { + if (isEven(polygon.points.size())) + { + ++count; + } + } + return count; +} + +size_t countOdd(const std::vector& polygons) +{ + size_t count = 0; + for (const auto& polygon : polygons) + { + if (isOdd(polygon.points.size())) + { + ++count; + } + } + return count; +} + +size_t countByVertexCount(const std::vector& polygons, size_t vertexCount) +{ + size_t count = 0; + for (const auto& polygon : polygons) + { + if (polygon.points.size() == vertexCount) + { + ++count; + } + } + return count; +} + +size_t echoCommand(std::vector& polygons, const Polygon& target) +{ + size_t added = 0; + for (size_t i = 0; i < polygons.size(); ++i) + { + if (polygons[i] == target) + { + polygons.insert(polygons.begin() + i + 1, target); + ++added; + ++i; + } + } + return added; +} + +bool inframeCommand(const std::vector& polygons, const Polygon& target) +{ + if (polygons.empty()) + { + return false; + } + Point bottomLeft, topRight; + getBoundingBox(polygons, bottomLeft, topRight); + return isPolygonInBoundingBox(target, bottomLeft, topRight); +} diff --git a/barinov.egor/T3/commands.hpp b/barinov.egor/T3/commands.hpp new file mode 100644 index 00000000..b90cd191 --- /dev/null +++ b/barinov.egor/T3/commands.hpp @@ -0,0 +1,28 @@ +#ifndef COMMANDS_HPP +#define COMMANDS_HPP + +#include "polygon.hpp" +#include +#include + +bool isEven(int n); +bool isOdd(int n); + +double getAreaEven(const std::vector& polygons); +double getAreaOdd(const std::vector& polygons); +double getAreaMean(const std::vector& polygons); +double getAreaByVertexCount(const std::vector& polygons, size_t vertexCount); + +double getMaxArea(const std::vector& polygons); +size_t getMaxVertexes(const std::vector& polygons); +double getMinArea(const std::vector& polygons); +size_t getMinVertexes(const std::vector& polygons); + +size_t countEven(const std::vector& polygons); +size_t countOdd(const std::vector& polygons); +size_t countByVertexCount(const std::vector& polygons, size_t vertexCount); + +size_t echoCommand(std::vector& polygons, const Polygon& target); +bool inframeCommand(const std::vector& polygons, const Polygon& target); + +#endif diff --git a/barinov.egor/T3/main.cpp b/barinov.egor/T3/main.cpp new file mode 100644 index 00000000..f080f6f8 --- /dev/null +++ b/barinov.egor/T3/main.cpp @@ -0,0 +1,267 @@ +#include "polygon.hpp" +#include "commands.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool readPolygonsFromFile(const std::string& filename, std::vector& polygons) +{ + std::ifstream file(filename); + if (!file.is_open()) + { + return false; + } + std::string line; + while (std::getline(file, line)) + { + if (line.empty()) + { + continue; + } + std::istringstream iss(line); + Polygon polygon; + if (iss >> polygon) + { + polygons.push_back(polygon); + } + } + return true; +} + +bool parsePolygon(const std::vector& tokens, size_t start, Polygon& polygon) +{ + if (start >= tokens.size()) + { + return false; + } + size_t vertexCount = 0; + std::istringstream countStream(tokens[start]); + countStream >> vertexCount; + if (vertexCount < 3 || start + 1 + vertexCount > tokens.size()) + { + return false; + } + polygon.points.clear(); + for (size_t i = 0; i < vertexCount; ++i) + { + Point p; + std::istringstream pointStream(tokens[start + 1 + i]); + if (!(pointStream >> p)) + { + return false; + } + polygon.points.push_back(p); + } + return true; +} + +int main(int argc, char* argv[]) +{ + if (argc != 2) + { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + std::vector polygons; + if (!readPolygonsFromFile(argv[1], polygons)) + { + std::cerr << "Error: cannot read file" << std::endl; + return 1; + } + std::cout << std::fixed << std::setprecision(1); + std::string line; + while (std::getline(std::cin, line)) + { + if (line.empty()) + { + continue; + } + std::istringstream iss(line); + std::string command; + iss >> command; + if (command == "AREA") + { + std::string param; + iss >> param; + if (param == "EVEN") + { + std::cout << getAreaEven(polygons) << std::endl; + } + else if (param == "ODD") + { + std::cout << getAreaOdd(polygons) << std::endl; + } + else if (param == "MEAN") + { + if (polygons.empty()) + { + std::cout << "" << std::endl; + } + else + { + std::cout << getAreaMean(polygons) << std::endl; + } + } + else + { + size_t vertexCount = 0; + std::istringstream countStream(param); + countStream >> vertexCount; + if (vertexCount >= 3) + { + std::cout << getAreaByVertexCount(polygons, vertexCount) << std::endl; + } + else + { + std::cout << "" << std::endl; + } + } + } + else if (command == "MAX") + { + std::string param; + iss >> param; + if (param == "AREA") + { + if (polygons.empty()) + { + std::cout << "" << std::endl; + } + else + { + std::cout << getMaxArea(polygons) << std::endl; + } + } + else if (param == "VERTEXES") + { + if (polygons.empty()) + { + std::cout << "" << std::endl; + } + else + { + std::cout << getMaxVertexes(polygons) << std::endl; + } + } + else + { + std::cout << "" << std::endl; + } + } + else if (command == "MIN") + { + std::string param; + iss >> param; + if (param == "AREA") + { + if (polygons.empty()) + { + std::cout << "" << std::endl; + } + else + { + std::cout << getMinArea(polygons) << std::endl; + } + } + else if (param == "VERTEXES") + { + if (polygons.empty()) + { + std::cout << "" << std::endl; + } + else + { + std::cout << getMinVertexes(polygons) << std::endl; + } + } + else + { + std::cout << "" << std::endl; + } + } + else if (command == "COUNT") + { + std::string param; + iss >> param; + if (param == "EVEN") + { + std::cout << countEven(polygons) << std::endl; + } + else if (param == "ODD") + { + std::cout << countOdd(polygons) << std::endl; + } + else + { + size_t vertexCount = 0; + std::istringstream countStream(param); + countStream >> vertexCount; + if (vertexCount >= 3) + { + std::cout << countByVertexCount(polygons, vertexCount) << std::endl; + } + else + { + std::cout << "" << std::endl; + } + } + } + else if (command == "ECHO") + { + std::vector tokens; + std::string token; + std::istringstream tokenStream(line); + while (tokenStream >> token) + { + tokens.push_back(token); + } + if (tokens.size() < 2) + { + std::cout << "" << std::endl; + continue; + } + Polygon target; + if (!parsePolygon(tokens, 1, target)) + { + std::cout << "" << std::endl; + continue; + } + size_t added = echoCommand(polygons, target); + std::cout << added << std::endl; + } + else if (command == "INFRAME") + { + std::vector tokens; + std::string token; + std::istringstream tokenStream(line); + while (tokenStream >> token) + { + tokens.push_back(token); + } + if (tokens.size() < 2) + { + std::cout << "" << std::endl; + continue; + } + Polygon target; + if (!parsePolygon(tokens, 1, target)) + { + std::cout << "" << std::endl; + continue; + } + bool result = inframeCommand(polygons, target); + std::cout << (result ? "" : "") << std::endl; + } + else + { + std::cout << "" << std::endl; + } + } + return 0; +} diff --git a/barinov.egor/T3/polygon.cpp b/barinov.egor/T3/polygon.cpp new file mode 100644 index 00000000..21d99a49 --- /dev/null +++ b/barinov.egor/T3/polygon.cpp @@ -0,0 +1,150 @@ +#include "polygon.hpp" +#include +#include +#include +#include +#include + +bool operator==(const Point& a, const Point& b) +{ + return a.x == b.x && a.y == b.y; +} + +bool operator!=(const Point& a, const Point& b) +{ + return !(a == b); +} + +bool operator==(const Polygon& a, const Polygon& b) +{ + if (a.points.size() != b.points.size()) + { + return false; + } + for (size_t i = 0; i < a.points.size(); ++i) + { + if (a.points[i] != b.points[i]) + { + return false; + } + } + return true; +} + +bool operator!=(const Polygon& a, const Polygon& b) +{ + return !(a == b); +} + +std::istream& operator>>(std::istream& in, Point& point) +{ + char c = '\0'; + in >> c; + if (c != '(') + { + in.setstate(std::ios::failbit); + return in; + } + in >> point.x; + in >> c; + if (c != ';') + { + in.setstate(std::ios::failbit); + return in; + } + in >> point.y; + in >> c; + if (c != ')') + { + in.setstate(std::ios::failbit); + return in; + } + return in; +} + +std::istream& operator>>(std::istream& in, Polygon& polygon) +{ + polygon.points.clear(); + size_t vertexCount = 0; + in >> vertexCount; + if (!in || vertexCount < 3) + { + in.setstate(std::ios::failbit); + return in; + } + for (size_t i = 0; i < vertexCount; ++i) + { + Point p; + in >> p; + if (!in) + { + in.setstate(std::ios::failbit); + return in; + } + polygon.points.push_back(p); + } + return in; +} + +double getArea(const Polygon& polygon) +{ + double area = 0.0; + size_t n = polygon.points.size(); + for (size_t i = 0; i < n; ++i) + { + const Point& p1 = polygon.points[i]; + const Point& p2 = polygon.points[(i + 1) % n]; + area += static_cast(p1.x * p2.y - p2.x * p1.y); + } + return std::fabs(area) / 2.0; +} + +void getBoundingBox(const std::vector& polygons, + Point& bottomLeft, + Point& topRight) +{ + if (polygons.empty()) + { + bottomLeft = Point{0, 0}; + topRight = Point{0, 0}; + return; + } + int minX = std::numeric_limits::max(); + int minY = std::numeric_limits::max(); + int maxX = std::numeric_limits::lowest(); + int maxY = std::numeric_limits::lowest(); + for (const auto& polygon : polygons) + { + for (const auto& point : polygon.points) + { + if (point.x < minX) minX = point.x; + if (point.y < minY) minY = point.y; + if (point.x > maxX) maxX = point.x; + if (point.y > maxY) maxY = point.y; + } + } + bottomLeft = Point{minX, minY}; + topRight = Point{maxX, maxY}; +} + +bool isPointInBoundingBox(const Point& point, + const Point& bottomLeft, + const Point& topRight) +{ + return point.x >= bottomLeft.x && point.x <= topRight.x && + point.y >= bottomLeft.y && point.y <= topRight.y; +} + +bool isPolygonInBoundingBox(const Polygon& polygon, + const Point& bottomLeft, + const Point& topRight) +{ + for (const auto& point : polygon.points) + { + if (!isPointInBoundingBox(point, bottomLeft, topRight)) + { + return false; + } + } + return true; +} diff --git a/barinov.egor/T3/polygon.hpp b/barinov.egor/T3/polygon.hpp new file mode 100644 index 00000000..05ac8813 --- /dev/null +++ b/barinov.egor/T3/polygon.hpp @@ -0,0 +1,42 @@ +#ifndef POLYGON_HPP +#define POLYGON_HPP + +#include +#include + +struct Point +{ + int x, y; +}; + +struct Polygon +{ + std::vector points; +}; + +bool operator==(const Point& a, const Point& b); +bool operator!=(const Point& a, const Point& b); + +bool operator==(const Polygon& a, const Polygon& b); +bool operator!=(const Polygon& a, const Polygon& b); + +std::istream& operator>>(std::istream& in, Point& point); +std::istream& operator>>(std::istream& in, Polygon& polygon); + +double getArea(const Polygon& polygon); + +void getBoundingBox( + const std::vector& polygons, + Point& bottomLeft, + Point& topRight +); + +bool isPointInBoundingBox(const Point& point, + const Point& bottomLeft, + const Point& topRight); + +bool isPolygonInBoundingBox(const Polygon& polygon, + const Point& bottomLeft, + const Point& topRight); + +#endif