From 341cb77b62f60e3a04a78d67a74b459ee09acf36 Mon Sep 17 00:00:00 2001 From: "polevshikov.vladislav" Date: Sun, 31 May 2026 21:50:39 +0300 Subject: [PATCH 1/6] lab T3 --- polevshikov.vladislav/T3/commands.cpp | 169 ++++++++++++++++++++++++++ polevshikov.vladislav/T3/commands.h | 19 +++ polevshikov.vladislav/T3/main.cpp | 61 ++++++++++ polevshikov.vladislav/T3/polygon.cpp | 88 ++++++++++++++ polevshikov.vladislav/T3/polygon.h | 20 +++ 5 files changed, 357 insertions(+) create mode 100644 polevshikov.vladislav/T3/commands.cpp create mode 100644 polevshikov.vladislav/T3/commands.h create mode 100644 polevshikov.vladislav/T3/main.cpp create mode 100644 polevshikov.vladislav/T3/polygon.cpp create mode 100644 polevshikov.vladislav/T3/polygon.h diff --git a/polevshikov.vladislav/T3/commands.cpp b/polevshikov.vladislav/T3/commands.cpp new file mode 100644 index 00000000..190e5c3a --- /dev/null +++ b/polevshikov.vladislav/T3/commands.cpp @@ -0,0 +1,169 @@ +#include "commands.h" +#include +#include +#include +#include + +void doArea(const std::vector& polygons, std::istream& in, std::ostream& out) { + std::string subCmd; + in >> subCmd; + + double res = 0.0; + if (subCmd == "EVEN") { + res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [](double sum, const Polygon& p) { + return (p.points.size() % 2 == 0) ? sum + getArea(p) : sum; + }); + + } else if (subCmd == "ODD") { + res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [](double sum, const Polygon& p) { + return (p.points.size() % 2 != 0) ? sum + getArea(p) : sum; + }); + + } else if (subCmd == "MEAN") { + if (polygons.empty()) { + throw std::logic_error("Empty collection"); + } + + double totalArea = std::accumulate(polygons.begin(), polygons.end(), 0.0, [](double sum, const Polygon&p) { + return sum + getArea(p); + }); + + res = totalArea / polygons.size(); + + } else { + size_t num = std::stoi(subCmd); + res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [num](double sum, const Polygon& p) { + return (p.points.size() == num) ? sum + getArea(p) : sum; + }); + } + out << std::fixed << std::setprecision(1) << res << '\n'; +} + +void doMax(const std::vector& polygons, std::istream& in, std::ostream& out) { + if (polygons.empty()) { + throw std::logic_error("Empty collection"); + } + + std::string subCmd; + in >> subCmd; + + if (subCmd == "AREA") { + auto it = std::max_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { + return getArea(a) < getArea(b); + }); + out << std::fixed << std::setprecision(1) << getArea(*it) << '\n'; + + } else if (subCmd == "VERTICES") { + auto it = std::max_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { + return a.points.size() < b.points.size(); + }); + out << it->points.size() << "\n"; + } +} + +void doMin(const std::vector& polygons, std::istream& in, std::ostream& out) { + if (polygons.empty()) { + throw std::logic_error("Empty collection"); + } + + std::string subCmd; + in >> subCmd; + + if (subCmd == "AREA") { + auto it = std::min_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { + return getArea(a) < getArea(b); + }); + out << std::fixed << std::setprecision(1) << getArea(*it) << '\n'; + + } else if (subCmd == "VERTICES") { + auto it = std::min_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { + return a.points.size() < b.points.size(); + }); + out << it->points.size() << "\n"; + } +} + +void doCount(const std::vector& polygons, std::istream& in, std::ostream& out) { + std::string subCmd; + in >> subCmd; + + size_t cnt = 0; + + if (subCmd == "EVEN") { + cnt = std::count_if(polygons.begin(), polygons.end(), [](const Polygon& p) { + return p.points.size() % 2 == 0; + }); + + } else if (subCmd == "ODD") { + cnt = std::count_if(polygons.begin(), polygons.end(), [](const Polygon& p) { + return p.points.size() % 2 != 0; + }); + + } else { + size_t num = std::stoi(subCmd); + cnt = std::count_if(polygons.begin(), polygons.end(), [num](const Polygon& p) { + return p.points.size() == num; + }); + } + out << cnt << '\n'; +} + +void printError(std::ostream& out) { + out << "\n"; +} + +void doRightShapes(const std::vector& polygons, std::ostream& out) { + long long count = std::count_if(polygons.begin(), polygons.end(), hasRightAngle); + out << count << '\n'; +} + +void doInFrame(const std::vector& polygons, std::istream& in, std::ostream& out) { + Polygon target; + if (!(in >> target)) { + printError(out); + return; + } + + if (polygons.empty()) { + out << "\n"; + return; + } + + auto findMinX = [](int cur, const Polygon& p) { + auto it = std::min_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { + return a.x < b.x; + }); + return std::min(cur, it->x); + }; + + auto findMaxX = [](int cur, const Polygon& p) { + auto it = std::max_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { + return a.x < b.x; + }); + return std::max(cur, it->x); + }; + + auto findMinY = [](int cur, const Polygon& p) { + auto it = std::min_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { + return a.y < b.y; + }); + return std::min(cur, it->y); + }; + + auto findMaxY = [](int cur, const Polygon& p) { + auto it = std::max_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { + return a.y < b.y; + }); + return std::max(cur, it->y); + }; + + int minX = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::max(), findMinX); + int maxX = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::min(), findMaxX); + int minY = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::max(), findMinY); + int maxY = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::min(), findMaxY); + + bool inInside = std::all_of(target.points.begin(), target.points.end(), [minX, maxX, minY, maxY](const Point& p) { + return p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY; + }); + out << (inInside ? "" : "") << '\n'; +} diff --git a/polevshikov.vladislav/T3/commands.h b/polevshikov.vladislav/T3/commands.h new file mode 100644 index 00000000..7e488616 --- /dev/null +++ b/polevshikov.vladislav/T3/commands.h @@ -0,0 +1,19 @@ +#ifndef COMMANDS_H +#define COMMANDS_H + +#include +#include +#include +#include "polygon.h" + +void doArea(const std::vector& polygons, std::istream& in, std::ostream& out); +void doMax(const std::vector& polygons, std::istream& in, std::ostream& out); +void doMin(const std::vector& polygons, std::istream& in, std::ostream& out); +void doCount(const std::vector& polygons, std::istream& in, std::ostream& out); + +void doInFrame(const std::vector& polygons, std::istream& in, std::ostream& out); +void doRightShapes(const std::vector& polygons, std::ostream& out); + +void printError(std::ostream& out); + +#endif diff --git a/polevshikov.vladislav/T3/main.cpp b/polevshikov.vladislav/T3/main.cpp new file mode 100644 index 00000000..8e5e9341 --- /dev/null +++ b/polevshikov.vladislav/T3/main.cpp @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include "polygon.h" +#include "commands.h" + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + std::ifstream file(argv[1]); + if (!file.is_open()) { + std::cerr << "Cannot open file: " << argv[1] << '\n'; + return 1; + } + + std::vector polygons; + + while (file) { + Polygon p; + if (file >> p) { + polygons.push_back(p); + } else if (!file.eof()) { + file.clear(); + file.ignore(std::numeric_limits::max(), '\n'); + } + } + + std::map> cmds; + + cmds["AREA"] = [&](std::istream& in, std::ostream& out) {doArea(polygons, in, out);}; + cmds["MAX"] = [&](std::istream& in, std::ostream& out) {doMax(polygons, in, out);}; + cmds["MIN"] = [&](std::istream& in, std::ostream& out) {doMin(polygons, in, out);}; + cmds["COUNT"] = [&](std::istream& in, std::ostream& out) {doCount(polygons, in, out); }; + cmds["RIGHTSHAPES"] = [&](std::istream&, std::ostream& out) {doRightShapes(polygons, out); }; + cmds["INFRAME"] = [&](std::istream& in, std::ostream& out) {doInFrame(polygons, in, out); }; + + std::string cmd; + while(std::cin >> cmd) { + try { + if (cmds.count(cmd)) { + cmds[cmd](std::cin, std::cout); + } else { + printError(std::cout); + std::cin.ignore(std::numeric_limits::max(), '\n'); + } + + } catch (...) { + printError(std::cout); + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + } + } + return 0; +} diff --git a/polevshikov.vladislav/T3/polygon.cpp b/polevshikov.vladislav/T3/polygon.cpp new file mode 100644 index 00000000..08edfe46 --- /dev/null +++ b/polevshikov.vladislav/T3/polygon.cpp @@ -0,0 +1,88 @@ +#include "polygon.h" +#include +#include +#include +#include +#include + +struct DelimiterI0 { + char expected; +}; + +std::istream& operator>>(std::istream& in, DelimiterI0&& dest) { + std::istream::sentry sentry(in); + if (!sentry) { + return in; + } + + char c = ' '; + in >> c; + + if (in && (c != dest.expected)) { + in.setstate(std::ios::failbit); + } + + return in; +} + +std::istream& operator>>(std::istream& in, Point& dest) { + std::istream::sentry sentry(in); + if (!sentry) { + return in; + } + + return in >> DelimiterI0{'('} >> dest.x >> DelimiterI0{';'} >> dest.y >> DelimiterI0{')'}; +} + +std::istream& operator>>(std::istream& in, Polygon& dest) { + std::istream::sentry sentry(in); + if (!sentry) { + return in; + } + + size_t cnt = 0; + if (!(in >> cnt) || cnt < 3) { + in.setstate(std::ios::failbit); + return in; + } + + std::vector tmp_points; + for (size_t i = 0; i < cnt; ++i) { + Point p; + + if (in >> p) { + tmp_points.push_back(p); + } else { + return in; + } + } + dest.points = std::move(tmp_points); + return in; +} + +double getArea(const Polygon& poly) { + size_t n = poly.points.size(); + std::vector idx(n); + + std::iota(idx.begin(), idx.end(), 0); + long long area = std::accumulate(idx.begin(), idx.end(), 0.0, [&](double sum, size_t i) { + const Point& a = poly.points[i]; + const Point& b = poly.points[(i + 1) % n]; + return sum + ((long long)a.x * b.y - (long long)a.y * b.x); + }); + return std::abs(double(area)) / 2.0; +} + +bool hasRightAngle(const Polygon& poly) { + size_t n = poly.points.size(); + std::vector idx(n); + std::iota(idx.begin(), idx.end(), 0); + return std::any_of(idx.begin(), idx.end(), [&](size_t i) { + const Point& a = poly.points[i]; + const Point& b = poly.points[(i + 1) % n]; + const Point& c = poly.points[(i + 2) % n]; + long long v1x = b.x - a.x, v1y = b.y - a.y; + long long v2x = c.x - b.x, v2y = c.y - b.y; + return (v1x * v2x + v1y * v2y) == 0; + }); +} diff --git a/polevshikov.vladislav/T3/polygon.h b/polevshikov.vladislav/T3/polygon.h new file mode 100644 index 00000000..c5f44dd8 --- /dev/null +++ b/polevshikov.vladislav/T3/polygon.h @@ -0,0 +1,20 @@ +#ifndef POLYGON_H +#define POLYGON_H + +#include +#include + +struct Point { + int x, y; +}; + +struct Polygon { + std::vector points; +}; + +std::istream& operator>>(std::istream& in, Polygon& dest); + +double getArea(const Polygon& poly); +bool hasRightAngle(const Polygon& poly); + +#endif From aa52ef05f333f2fb777fd6e36be9ce9335996224 Mon Sep 17 00:00:00 2001 From: "polevshikov.vladislav" Date: Sun, 31 May 2026 22:10:06 +0300 Subject: [PATCH 2/6] Fix T3: resolve old-style cast and add algorithm include --- polevshikov.vladislav/T3/polygon.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/polevshikov.vladislav/T3/polygon.cpp b/polevshikov.vladislav/T3/polygon.cpp index 08edfe46..00292f0a 100644 --- a/polevshikov.vladislav/T3/polygon.cpp +++ b/polevshikov.vladislav/T3/polygon.cpp @@ -4,6 +4,7 @@ #include #include #include +#include struct DelimiterI0 { char expected; @@ -68,7 +69,7 @@ double getArea(const Polygon& poly) { long long area = std::accumulate(idx.begin(), idx.end(), 0.0, [&](double sum, size_t i) { const Point& a = poly.points[i]; const Point& b = poly.points[(i + 1) % n]; - return sum + ((long long)a.x * b.y - (long long)a.y * b.x); + return sum + (static_cast(a.x) * b.y - static_cast(a.y) * b.x); }); return std::abs(double(area)) / 2.0; } From 9a5459b027bcb737062096ad2b1a4a44ec965cb1 Mon Sep 17 00:00:00 2001 From: "polevshikov.vladislav" Date: Sun, 31 May 2026 22:50:39 +0300 Subject: [PATCH 3/6] fix T3: correct VERTEXES typo, add vertex count validation, fix INFRAME error handling --- polevshikov.vladislav/T3/commands.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/polevshikov.vladislav/T3/commands.cpp b/polevshikov.vladislav/T3/commands.cpp index 190e5c3a..5b93a258 100644 --- a/polevshikov.vladislav/T3/commands.cpp +++ b/polevshikov.vladislav/T3/commands.cpp @@ -32,6 +32,9 @@ void doArea(const std::vector& polygons, std::istream& in, std::ostream } else { size_t num = std::stoi(subCmd); + if (num < 3) { + throw std::invalid_argument("bad vertex count"); + } res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [num](double sum, const Polygon& p) { return (p.points.size() == num) ? sum + getArea(p) : sum; }); @@ -53,7 +56,7 @@ void doMax(const std::vector& polygons, std::istream& in, std::ostream& }); out << std::fixed << std::setprecision(1) << getArea(*it) << '\n'; - } else if (subCmd == "VERTICES") { + } else if (subCmd == "VERTEXES") { auto it = std::max_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { return a.points.size() < b.points.size(); }); @@ -75,7 +78,7 @@ void doMin(const std::vector& polygons, std::istream& in, std::ostream& }); out << std::fixed << std::setprecision(1) << getArea(*it) << '\n'; - } else if (subCmd == "VERTICES") { + } else if (subCmd == "VERTEXES") { auto it = std::min_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { return a.points.size() < b.points.size(); }); @@ -101,6 +104,9 @@ void doCount(const std::vector& polygons, std::istream& in, std::ostrea } else { size_t num = std::stoi(subCmd); + if (num < 3) { + throw std::invalid_argument("bad vertex count"); + } cnt = std::count_if(polygons.begin(), polygons.end(), [num](const Polygon& p) { return p.points.size() == num; }); @@ -120,6 +126,8 @@ void doRightShapes(const std::vector& polygons, std::ostream& out) { void doInFrame(const std::vector& polygons, std::istream& in, std::ostream& out) { Polygon target; if (!(in >> target)) { + in.clear(); + in.ignore(std::numeric_limits::max(), '\n'); printError(out); return; } From 8d8a1d4d319448982c3f51a6c48c731f31b7d5b3 Mon Sep 17 00:00:00 2001 From: "polevshikov.vladislav" Date: Sun, 31 May 2026 23:01:21 +0300 Subject: [PATCH 4/6] fix: INFRAME input validation --- polevshikov.vladislav/T3/commands.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/polevshikov.vladislav/T3/commands.cpp b/polevshikov.vladislav/T3/commands.cpp index 5b93a258..2a31ffe5 100644 --- a/polevshikov.vladislav/T3/commands.cpp +++ b/polevshikov.vladislav/T3/commands.cpp @@ -132,6 +132,13 @@ void doInFrame(const std::vector& polygons, std::istream& in, std::ostr return; } + char c; + if (in.get(c) && c != '\n') { + in.ignore(std::numeric_limits::max(), '\n'); + printError(out); + return; + } + if (polygons.empty()) { out << "\n"; return; From 6071bf99996b6da04c8906dd1d6251c764558dd4 Mon Sep 17 00:00:00 2001 From: "polevshikov.vladislav" Date: Mon, 1 Jun 2026 20:29:01 +0300 Subject: [PATCH 5/6] fix T3: add trailing symbols check for commands, reduce lambdas count, replace loop with copy_n, fix buffer reading after in >> target in doInFrame --- polevshikov.vladislav/T3/commands.cpp | 145 +++++++++++--------------- polevshikov.vladislav/T3/commands.h | 3 +- polevshikov.vladislav/T3/main.cpp | 14 +-- polevshikov.vladislav/T3/polygon.cpp | 91 +++++++++++----- polevshikov.vladislav/T3/polygon.h | 19 ++++ 5 files changed, 158 insertions(+), 114 deletions(-) diff --git a/polevshikov.vladislav/T3/commands.cpp b/polevshikov.vladislav/T3/commands.cpp index 2a31ffe5..aae08b37 100644 --- a/polevshikov.vladislav/T3/commands.cpp +++ b/polevshikov.vladislav/T3/commands.cpp @@ -4,40 +4,54 @@ #include #include +bool checkAndConsumeRestOfLine(std::istream& in) { + while (in.peek() == ' ' || in.peek() == '\t') { + in.get(); + } + char next = in.peek(); + if (next == '\n' || next == EOF) { + if (next == '\n') { + in.get(); + } + return true; + } + return false; +} + void doArea(const std::vector& polygons, std::istream& in, std::ostream& out) { std::string subCmd; - in >> subCmd; + if (!(in >> subCmd) || !checkAndConsumeRestOfLine(in)) { + throw std::invalid_argument("extra symbols"); + } double res = 0.0; if (subCmd == "EVEN") { - res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [](double sum, const Polygon& p) { - return (p.points.size() % 2 == 0) ? sum + getArea(p) : sum; - }); + std::vector filtered; + + std::copy_if(polygons.begin(), polygons.end(), std::back_inserter(filtered), isEven); + res = std::accumulate(filtered.begin(), filtered.end(), 0.0, sumArea); } else if (subCmd == "ODD") { - res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [](double sum, const Polygon& p) { - return (p.points.size() % 2 != 0) ? sum + getArea(p) : sum; - }); + std::vector filtered; + + std::copy_if(polygons.begin(), polygons.end(), std::back_inserter(filtered), isOdd); + res = std::accumulate(filtered.begin(), filtered.end(), 0.0, sumArea); } else if (subCmd == "MEAN") { if (polygons.empty()) { throw std::logic_error("Empty collection"); } - double totalArea = std::accumulate(polygons.begin(), polygons.end(), 0.0, [](double sum, const Polygon&p) { - return sum + getArea(p); - }); - - res = totalArea / polygons.size(); + res = std::accumulate(polygons.begin(), polygons.end(), 0.0, sumArea) / polygons.size(); } else { size_t num = std::stoi(subCmd); if (num < 3) { throw std::invalid_argument("bad vertex count"); } - res = std::accumulate(polygons.begin(), polygons.end(), 0.0, [num](double sum, const Polygon& p) { - return (p.points.size() == num) ? sum + getArea(p) : sum; - }); + std::vector filtered; + std::copy_if(polygons.begin(), polygons.end(), std::back_inserter(filtered), HasNVertices{num}); + res = std::accumulate(filtered.begin(), filtered.end(), 0.0, sumArea); } out << std::fixed << std::setprecision(1) << res << '\n'; } @@ -48,19 +62,20 @@ void doMax(const std::vector& polygons, std::istream& in, std::ostream& } std::string subCmd; - in >> subCmd; + if (!(in >> subCmd) || !checkAndConsumeRestOfLine(in)) { + throw std::invalid_argument("extra symbols"); + } if (subCmd == "AREA") { - auto it = std::max_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { - return getArea(a) < getArea(b); - }); + auto it = std::max_element(polygons.begin(), polygons.end(), compareByArea); out << std::fixed << std::setprecision(1) << getArea(*it) << '\n'; } else if (subCmd == "VERTEXES") { - auto it = std::max_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { - return a.points.size() < b.points.size(); - }); + auto it = std::max_element(polygons.begin(), polygons.end(), compareBySize); out << it->points.size() << "\n"; + + } else { + throw std::invalid_argument("bad subcommand"); } } @@ -70,46 +85,43 @@ void doMin(const std::vector& polygons, std::istream& in, std::ostream& } std::string subCmd; - in >> subCmd; + if (!(in >> subCmd) || !checkAndConsumeRestOfLine(in)) { + throw std::invalid_argument("extra symbols"); + } if (subCmd == "AREA") { - auto it = std::min_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { - return getArea(a) < getArea(b); - }); + auto it = std::min_element(polygons.begin(), polygons.end(), compareByArea); out << std::fixed << std::setprecision(1) << getArea(*it) << '\n'; } else if (subCmd == "VERTEXES") { - auto it = std::min_element(polygons.begin(), polygons.end(), [](const Polygon& a, const Polygon& b) { - return a.points.size() < b.points.size(); - }); + auto it = std::min_element(polygons.begin(), polygons.end(), compareBySize); out << it->points.size() << "\n"; + + } else { + throw std::invalid_argument("bad subcommand"); } } void doCount(const std::vector& polygons, std::istream& in, std::ostream& out) { std::string subCmd; - in >> subCmd; + if (!(in >> subCmd) || !checkAndConsumeRestOfLine(in)) { + throw std::invalid_argument("extra symbols"); + } size_t cnt = 0; if (subCmd == "EVEN") { - cnt = std::count_if(polygons.begin(), polygons.end(), [](const Polygon& p) { - return p.points.size() % 2 == 0; - }); + cnt = std::count_if(polygons.begin(), polygons.end(), isEven); } else if (subCmd == "ODD") { - cnt = std::count_if(polygons.begin(), polygons.end(), [](const Polygon& p) { - return p.points.size() % 2 != 0; - }); + cnt = std::count_if(polygons.begin(), polygons.end(), isOdd); } else { size_t num = std::stoi(subCmd); if (num < 3) { throw std::invalid_argument("bad vertex count"); } - cnt = std::count_if(polygons.begin(), polygons.end(), [num](const Polygon& p) { - return p.points.size() == num; - }); + cnt = std::count_if(polygons.begin(), polygons.end(), HasNVertices{num}); } out << cnt << '\n'; } @@ -118,64 +130,33 @@ void printError(std::ostream& out) { out << "\n"; } -void doRightShapes(const std::vector& polygons, std::ostream& out) { +void doRightShapes(const std::vector& polygons, std::istream& in, std::ostream& out) { + if (!checkAndConsumeRestOfLine(in)) { + printError(out); + return; + } + long long count = std::count_if(polygons.begin(), polygons.end(), hasRightAngle); out << count << '\n'; } void doInFrame(const std::vector& polygons, std::istream& in, std::ostream& out) { Polygon target; - if (!(in >> target)) { + if (!(in >> target) || !checkAndConsumeRestOfLine(in)) { in.clear(); in.ignore(std::numeric_limits::max(), '\n'); printError(out); return; } - char c; - if (in.get(c) && c != '\n') { - in.ignore(std::numeric_limits::max(), '\n'); - printError(out); - return; - } - if (polygons.empty()) { - out << "\n"; - return; + throw std::logic_error("Empty collection"); } - auto findMinX = [](int cur, const Polygon& p) { - auto it = std::min_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { - return a.x < b.x; - }); - return std::min(cur, it->x); - }; - - auto findMaxX = [](int cur, const Polygon& p) { - auto it = std::max_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { - return a.x < b.x; - }); - return std::max(cur, it->x); - }; - - auto findMinY = [](int cur, const Polygon& p) { - auto it = std::min_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { - return a.y < b.y; - }); - return std::min(cur, it->y); - }; - - auto findMaxY = [](int cur, const Polygon& p) { - auto it = std::max_element(p.points.begin(), p.points.end(), [](const Point& a, const Point& b) { - return a.y < b.y; - }); - return std::max(cur, it->y); - }; - - int minX = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::max(), findMinX); - int maxX = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::min(), findMaxX); - int minY = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::max(), findMinY); - int maxY = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::min(), findMaxY); + int minX = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::max(), getMinX); + int maxX = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::min(), getMaxX); + int minY = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::max(), getMinY); + int maxY = std::accumulate(polygons.begin(), polygons.end(), std::numeric_limits::min(), getMaxY); bool inInside = std::all_of(target.points.begin(), target.points.end(), [minX, maxX, minY, maxY](const Point& p) { return p.x >= minX && p.x <= maxX && p.y >= minY && p.y <= maxY; diff --git a/polevshikov.vladislav/T3/commands.h b/polevshikov.vladislav/T3/commands.h index 7e488616..da330a7f 100644 --- a/polevshikov.vladislav/T3/commands.h +++ b/polevshikov.vladislav/T3/commands.h @@ -10,9 +10,8 @@ void doArea(const std::vector& polygons, std::istream& in, std::ostream void doMax(const std::vector& polygons, std::istream& in, std::ostream& out); void doMin(const std::vector& polygons, std::istream& in, std::ostream& out); void doCount(const std::vector& polygons, std::istream& in, std::ostream& out); - void doInFrame(const std::vector& polygons, std::istream& in, std::ostream& out); -void doRightShapes(const std::vector& polygons, std::ostream& out); +void doRightShapes(const std::vector& polygons, std::istream& in, std::ostream& out); void printError(std::ostream& out); diff --git a/polevshikov.vladislav/T3/main.cpp b/polevshikov.vladislav/T3/main.cpp index 8e5e9341..da7f3c73 100644 --- a/polevshikov.vladislav/T3/main.cpp +++ b/polevshikov.vladislav/T3/main.cpp @@ -8,6 +8,8 @@ #include "polygon.h" #include "commands.h" +using namespace std::placeholders; + int main(int argc, char* argv[]) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " \n"; @@ -34,12 +36,12 @@ int main(int argc, char* argv[]) { std::map> cmds; - cmds["AREA"] = [&](std::istream& in, std::ostream& out) {doArea(polygons, in, out);}; - cmds["MAX"] = [&](std::istream& in, std::ostream& out) {doMax(polygons, in, out);}; - cmds["MIN"] = [&](std::istream& in, std::ostream& out) {doMin(polygons, in, out);}; - cmds["COUNT"] = [&](std::istream& in, std::ostream& out) {doCount(polygons, in, out); }; - cmds["RIGHTSHAPES"] = [&](std::istream&, std::ostream& out) {doRightShapes(polygons, out); }; - cmds["INFRAME"] = [&](std::istream& in, std::ostream& out) {doInFrame(polygons, in, out); }; + cmds["AREA"] = std::bind(doArea, std::cref(polygons), _1, _2); + cmds["MAX"] = std::bind(doMax, std::cref(polygons), _1, _2); + cmds["MIN"] = std::bind(doMin, std::cref(polygons), _1, _2); + cmds["COUNT"] = std::bind(doCount, std::cref(polygons), _1, _2); + cmds["RIGHTSHAPES"] = std::bind(doRightShapes, std::cref(polygons), _1, _2); + cmds["INFRAME"] = std::bind(doInFrame, std::cref(polygons), _1, _2); std::string cmd; while(std::cin >> cmd) { diff --git a/polevshikov.vladislav/T3/polygon.cpp b/polevshikov.vladislav/T3/polygon.cpp index 00292f0a..0b24c62c 100644 --- a/polevshikov.vladislav/T3/polygon.cpp +++ b/polevshikov.vladislav/T3/polygon.cpp @@ -5,6 +5,7 @@ #include #include #include +#include struct DelimiterI0 { char expected; @@ -31,7 +32,6 @@ std::istream& operator>>(std::istream& in, Point& dest) { if (!sentry) { return in; } - return in >> DelimiterI0{'('} >> dest.x >> DelimiterI0{';'} >> dest.y >> DelimiterI0{')'}; } @@ -47,43 +47,86 @@ std::istream& operator>>(std::istream& in, Polygon& dest) { return in; } - std::vector tmp_points; - for (size_t i = 0; i < cnt; ++i) { - Point p; - - if (in >> p) { - tmp_points.push_back(p); - } else { - return in; - } - } + std::vector tmp_points(cnt); + std::copy_n(std::istream_iterator(in), cnt, tmp_points.begin()); + if (!in) return in; dest.points = std::move(tmp_points); return in; } -double getArea(const Polygon& poly) { - size_t n = poly.points.size(); - std::vector idx(n); - - std::iota(idx.begin(), idx.end(), 0); - long long area = std::accumulate(idx.begin(), idx.end(), 0.0, [&](double sum, size_t i) { +struct CrossProductAccum { + const Polygon& poly; + double operator()(double sum, size_t i) const { const Point& a = poly.points[i]; - const Point& b = poly.points[(i + 1) % n]; + const Point& b = poly.points[(i + 1) % poly.points.size()]; return sum + (static_cast(a.x) * b.y - static_cast(a.y) * b.x); - }); - return std::abs(double(area)) / 2.0; -} + } +}; -bool hasRightAngle(const Polygon& poly) { +double getArea(const Polygon& poly) { size_t n = poly.points.size(); std::vector idx(n); std::iota(idx.begin(), idx.end(), 0); - return std::any_of(idx.begin(), idx.end(), [&](size_t i) { + double area = std::accumulate(idx.begin(), idx.end(), 0.0, CrossProductAccum{poly}); + return std::abs(area) / 2.0; +} + +struct rightAngle { + const Polygon& poly; + bool operator()(size_t i) const { + size_t n = poly.points.size(); const Point& a = poly.points[i]; const Point& b = poly.points[(i + 1) % n]; const Point& c = poly.points[(i + 2) % n]; long long v1x = b.x - a.x, v1y = b.y - a.y; long long v2x = c.x - b.x, v2y = c.y - b.y; return (v1x * v2x + v1y * v2y) == 0; - }); + } +}; + +bool hasRightAngle(const Polygon& poly) { + size_t n = poly.points.size(); + std::vector idx(n); + std::iota(idx.begin(), idx.end(), 0); + return std::any_of(idx.begin(), idx.end(), rightAngle{poly}); +} + +bool isEven(const Polygon& p) { + return p.points.size() % 2 == 0; +} + +bool isOdd(const Polygon& p) { + return p.points.size() % 2 != 0; +} + +bool compareByArea(const Polygon& a, const Polygon& b) { + return getArea(a) < getArea(b); +} + +bool compareBySize(const Polygon& a, const Polygon& b) { + return a.points.size() < b.points.size(); +} + +double sumArea(double sum, const Polygon& p) { + return sum + getArea(p); +} + +bool cmpByX(const Point& a, const Point& b) { + return a.x < b.x; +} +bool cmpByY(const Point& a, const Point& b) { + return a.y < b.y; +} + +int getMinX(int cur, const Polygon& p) { + return std::min(cur, std::min_element(p.points.begin(), p.points.end(), cmpByX)->x); +} +int getMaxX(int cur, const Polygon& p) { + return std::max(cur, std::max_element(p.points.begin(), p.points.end(), cmpByX)->x); +} +int getMinY(int cur, const Polygon& p) { + return std::min(cur, std::min_element(p.points.begin(), p.points.end(), cmpByY)->y); +} +int getMaxY(int cur, const Polygon& p) { + return std::max(cur, std::max_element(p.points.begin(), p.points.end(), cmpByY)->y); } diff --git a/polevshikov.vladislav/T3/polygon.h b/polevshikov.vladislav/T3/polygon.h index c5f44dd8..81d48541 100644 --- a/polevshikov.vladislav/T3/polygon.h +++ b/polevshikov.vladislav/T3/polygon.h @@ -12,9 +12,28 @@ struct Polygon { std::vector points; }; +struct HasNVertices { + size_t n; + bool operator()(const Polygon& p) const { return p.points.size() == n; } +}; + std::istream& operator>>(std::istream& in, Polygon& dest); double getArea(const Polygon& poly); bool hasRightAngle(const Polygon& poly); +bool compareByArea(const Polygon& a, const Polygon& b); +bool compareBySize(const Polygon& a, const Polygon& b); +bool isEven(const Polygon& p); +bool isOdd(const Polygon& p); +double sumArea(double sum, const Polygon& p); + +bool cmpByX(const Point& a, const Point& b); +bool cmpByY(const Point& a, const Point& b); + +int getMinX(int cur, const Polygon& p); +int getMaxX(int cur, const Polygon& p); +int getMinY(int cur, const Polygon& p); +int getMaxY(int cur, const Polygon& p); + #endif From 163e778b5845f140ceb54bc36ec9ffe5591fae22 Mon Sep 17 00:00:00 2001 From: "polevshikov.vladislav" Date: Mon, 1 Jun 2026 20:56:54 +0300 Subject: [PATCH 6/6] fix T3: replace throw with printError+return for invalid vertex count in AREA/COUNT --- polevshikov.vladislav/T3/commands.cpp | 40 ++++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/polevshikov.vladislav/T3/commands.cpp b/polevshikov.vladislav/T3/commands.cpp index aae08b37..5250a6c0 100644 --- a/polevshikov.vladislav/T3/commands.cpp +++ b/polevshikov.vladislav/T3/commands.cpp @@ -45,13 +45,23 @@ void doArea(const std::vector& polygons, std::istream& in, std::ostream res = std::accumulate(polygons.begin(), polygons.end(), 0.0, sumArea) / polygons.size(); } else { - size_t num = std::stoi(subCmd); - if (num < 3) { - throw std::invalid_argument("bad vertex count"); + try { + size_t pos = 0; + long long val = std::stoll(subCmd, &pos); + if (pos != subCmd.size() || val < 3) { + printError(out); + return; + } + + size_t num = static_cast(val); + std::vector filtered; + std::copy_if(polygons.begin(), polygons.end(), std::back_inserter(filtered), HasNVertices{num}); + res = std::accumulate(filtered.begin(), filtered.end(), 0.0, sumArea); + + } catch (const std::exception&) { + printError(out); + return; } - std::vector filtered; - std::copy_if(polygons.begin(), polygons.end(), std::back_inserter(filtered), HasNVertices{num}); - res = std::accumulate(filtered.begin(), filtered.end(), 0.0, sumArea); } out << std::fixed << std::setprecision(1) << res << '\n'; } @@ -117,11 +127,21 @@ void doCount(const std::vector& polygons, std::istream& in, std::ostrea cnt = std::count_if(polygons.begin(), polygons.end(), isOdd); } else { - size_t num = std::stoi(subCmd); - if (num < 3) { - throw std::invalid_argument("bad vertex count"); + try { + size_t pos = 0; + long long val = std::stoll(subCmd, &pos); + if (pos != subCmd.size() || val < 3) { + printError(out); + return; + } + + size_t num = static_cast(val); + cnt = std::count_if(polygons.begin(), polygons.end(), HasNVertices{num}); + + } catch (std::exception&) { + printError(out); + return; } - cnt = std::count_if(polygons.begin(), polygons.end(), HasNVertices{num}); } out << cnt << '\n'; }