| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <cstddef> | ||
| 4 | #include <fstream> | ||
| 5 | #include <iostream> | ||
| 6 | #include <sstream> | ||
| 7 | #include <stdexcept> | ||
| 8 | #include <string> | ||
| 9 | #include <tuple> | ||
| 10 | #include <utility> | ||
| 11 | #include <vector> | ||
| 12 | |||
| 13 | #include "task/include/task.hpp" | ||
| 14 | |||
| 15 | namespace guseva_a_jarvis { | ||
| 16 | |||
| 17 | using InType = std::tuple<int, int, std::vector<int>>; | ||
| 18 | using OutType = std::vector<int>; | ||
| 19 | using TestFromFileType = std::tuple<int, int, std::vector<int>, std::vector<int>>; | ||
| 20 | using TestType = std::string; | ||
| 21 | using BaseTask = ppc::task::Task<InType, OutType>; | ||
| 22 | |||
| 23 | 110 | inline TestFromFileType ReadTestDataFromFile(const std::string &filename) { | |
| 24 | 110 | std::ifstream file(filename); | |
| 25 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
|
110 | if (!file.is_open()) { |
| 26 | ✗ | throw std::runtime_error("Cannot open file: " + filename); | |
| 27 | } | ||
| 28 | 110 | int width = 0; | |
| 29 | 110 | int height = 0; | |
| 30 | 110 | std::vector<int> input; | |
| 31 | 110 | std::vector<int> output; | |
| 32 |
2/4✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 110 times.
✗ Branch 5 not taken.
|
110 | file >> width >> height; |
| 33 | std::string line; | ||
| 34 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
110 | std::getline(file, line); |
| 35 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
110 | std::getline(file, line); |
| 36 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
110 | std::stringstream ss(line); |
| 37 | 110 | int num = 0; | |
| 38 |
3/4✓ Branch 1 taken 222090 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 221980 times.
✓ Branch 4 taken 110 times.
|
222090 | while (ss >> num) { |
| 39 | input.push_back(num); | ||
| 40 | } | ||
| 41 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
110 | std::getline(file, line); |
| 42 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
110 | ss.clear(); |
| 43 | ss.str(line); | ||
| 44 |
3/4✓ Branch 1 taken 222090 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 221980 times.
✓ Branch 4 taken 110 times.
|
222090 | while (ss >> num) { |
| 45 | output.push_back(num); | ||
| 46 | } | ||
| 47 |
1/2✓ Branch 1 taken 110 times.
✗ Branch 2 not taken.
|
110 | file.close(); |
| 48 | 110 | return std::make_tuple(width, height, input, output); | |
| 49 | 220 | } | |
| 50 | |||
| 51 | inline int CrossProduct(const std::pair<int, int> &a, const std::pair<int, int> &b, const std::pair<int, int> &c) { | ||
| 52 | 591954 | return ((b.first - a.first) * (c.second - a.second)) - ((b.second - a.second) * (c.first - a.first)); | |
| 53 | } | ||
| 54 | |||
| 55 | inline int DistanceSquared(const std::pair<int, int> &a, const std::pair<int, int> &b) { | ||
| 56 | int dx = b.first - a.first; | ||
| 57 | int dy = b.second - a.second; | ||
| 58 | 8121 | return (dx * dx) + (dy * dy); | |
| 59 | } | ||
| 60 | |||
| 61 | 119 | inline size_t FindLeftmostBottommostPoint(const std::vector<std::pair<int, int>> &points) { | |
| 62 | size_t start_idx = 0; | ||
| 63 |
2/2✓ Branch 0 taken 99814 times.
✓ Branch 1 taken 119 times.
|
99933 | for (size_t i = 1; i < points.size(); ++i) { |
| 64 |
4/4✓ Branch 0 taken 99734 times.
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 2065 times.
✓ Branch 3 taken 97669 times.
|
99814 | if (points[i].first < points[start_idx].first || |
| 65 |
1/2✓ Branch 0 taken 2065 times.
✗ Branch 1 not taken.
|
2065 | (points[i].first == points[start_idx].first && points[i].second < points[start_idx].second)) { |
| 66 | start_idx = i; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | 119 | return start_idx; | |
| 70 | } | ||
| 71 | |||
| 72 | 717 | inline size_t FindNextHullPoint(const std::vector<std::pair<int, int>> &points, size_t current_idx, | |
| 73 | size_t candidate_idx) { | ||
| 74 | size_t next_idx = candidate_idx; | ||
| 75 | |||
| 76 |
2/2✓ Branch 0 taken 592671 times.
✓ Branch 1 taken 717 times.
|
593388 | for (size_t i = 0; i < points.size(); ++i) { |
| 77 |
2/2✓ Branch 0 taken 717 times.
✓ Branch 1 taken 591954 times.
|
592671 | if (i == current_idx) { |
| 78 | 717 | continue; | |
| 79 | } | ||
| 80 | |||
| 81 | const std::pair<int, int> ¤t_point = points[current_idx]; | ||
| 82 | const std::pair<int, int> &next_point = points[next_idx]; | ||
| 83 | const std::pair<int, int> &check_point = points[i]; | ||
| 84 | |||
| 85 | int cross = CrossProduct(current_point, next_point, check_point); | ||
| 86 | |||
| 87 |
2/2✓ Branch 0 taken 9165 times.
✓ Branch 1 taken 582789 times.
|
591954 | if (cross < 0) { |
| 88 | next_idx = i; | ||
| 89 |
2/2✓ Branch 0 taken 8121 times.
✓ Branch 1 taken 574668 times.
|
582789 | } else if (cross == 0) { |
| 90 | int dist_to_next = DistanceSquared(current_point, next_point); | ||
| 91 | int dist_to_check = DistanceSquared(current_point, check_point); | ||
| 92 |
2/2✓ Branch 0 taken 3762 times.
✓ Branch 1 taken 4359 times.
|
8121 | if (dist_to_check > dist_to_next) { |
| 93 | next_idx = i; | ||
| 94 | } | ||
| 95 | } | ||
| 96 | } | ||
| 97 | |||
| 98 | 717 | return next_idx; | |
| 99 | } | ||
| 100 | |||
| 101 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 119 times.
|
121 | inline std::vector<std::pair<int, int>> BuildConvexHull(const std::vector<std::pair<int, int>> &points) { |
| 102 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 119 times.
|
121 | if (points.size() <= 3) { |
| 103 | 2 | return points; | |
| 104 | } | ||
| 105 | |||
| 106 | 119 | std::vector<std::pair<int, int>> hull; | |
| 107 | |||
| 108 |
1/2✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
|
119 | const size_t start_idx = FindLeftmostBottommostPoint(points); |
| 109 | size_t current_idx = start_idx; | ||
| 110 | bool returned_to_start = false; | ||
| 111 | |||
| 112 |
1/2✓ Branch 1 taken 119 times.
✗ Branch 2 not taken.
|
119 | hull.reserve(points.size()); |
| 113 | |||
| 114 | while (!returned_to_start) { | ||
| 115 | hull.push_back(points[current_idx]); | ||
| 116 | |||
| 117 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 598 times.
|
717 | size_t next_idx = (current_idx + 1) % points.size(); |
| 118 | 717 | next_idx = FindNextHullPoint(points, current_idx, next_idx); | |
| 119 | |||
| 120 |
2/2✓ Branch 0 taken 119 times.
✓ Branch 1 taken 598 times.
|
717 | if (next_idx == start_idx) { |
| 121 | returned_to_start = true; | ||
| 122 | } else { | ||
| 123 | current_idx = next_idx; | ||
| 124 | } | ||
| 125 | } | ||
| 126 | |||
| 127 | return hull; | ||
| 128 | } | ||
| 129 | |||
| 130 | } // namespace guseva_a_jarvis | ||
| 131 |