#include #include #include #include #include class Point { public: Point(int x, int y) { _x = x; _y = y; } ~Point() = default; int getX() const { return _x; } int getY() const { return _y; } void addPoint(const Point &other) { _x += other.getX(); _y += other.getY(); } bool operator==(const Point &other) { return _x == other.getX() && _y == other.getY(); } bool operator!=(const Point &other) { return !(*this == other); } private: int _x; int _y; }; class Line { public: Line(Point a, Point b) : _a(a), _b(b) {} const Point &getStart() const { return _a; } const Point &getEnd() const { return _b; } bool isHorizontalOrVertical() const { return _a.getX() == _b.getX() || _a.getY() == _b.getY(); } Point getDirection() const { auto x = _b.getX() - _a.getX(); auto y = _b.getY() - _a.getY(); if (abs(x) > abs(y)) { x /= abs(x); y /= abs(x); } else { x /= abs(y); y /= abs(y); } return Point(x, y); } private: int abs(int x) const { if (x < 0) { return -x; } return x; } Point _a; Point _b; }; class OceanFloor { public: OceanFloor(int maxX, int maxY, const std::vector &lines) : _x(maxX), _y(maxY), _lines(lines) { floor.resize(_y + 1); for (int i = 0; i <= _y; i++) { floor[i].resize(_x + 1); } } ~OceanFloor() = default; void findLines(bool horizontal_or_vertical_only) { clearFloor(); for (auto &line : _lines) { if (horizontal_or_vertical_only && !line.isHorizontalOrVertical()) { continue; } auto direction = line.getDirection(); Point start(line.getStart()); while (start != line.getEnd()) { floor[start.getY()][start.getX()] += 1; start.addPoint(direction); } floor[start.getY()][start.getX()] += 1; } } int findCrossings(int minimum_crossing) { int result = 0; for (int i = 0; i <= _y; i++) { for (int j = 0; j <= _x; j++) { if (floor[i][j] >= minimum_crossing) { result++; } } } return result; } private: void clearFloor() { for (int i = 0; i <= _y; i++) { for (int j = 0; j <= _x; j++) { floor[i][j] = 0; } } } int _x; int _y; const std::vector &_lines; std::vector> floor; }; std::pair, std::vector> getLines(const std::string &file_name) { int maxY = 0; int maxX = 0; std::vector lines{}; std::ifstream file(file_name); int tmp_x{}; int tmp_y{}; char tmp_char{}; std::string str; while (std::getline(file, str)) { std::stringstream ss(str); ss >> tmp_x; ss >> tmp_char; ss >> tmp_y; Point a(tmp_x, tmp_y); if (tmp_x > maxX) { maxX = tmp_x; } if (tmp_y > maxY) { maxY = tmp_y; } ss >> tmp_char; ss >> tmp_char; ss >> tmp_x; ss >> tmp_char; ss >> tmp_y; Point b(tmp_x, tmp_y); if (tmp_x > maxX) { maxX = tmp_x; } if (tmp_y > maxY) { maxY = tmp_y; } lines.emplace_back(a, b); } return { { maxX, maxY }, lines }; } int part1(OceanFloor &floor) { floor.findLines(true); return floor.findCrossings(2); } int part2(OceanFloor &floor) { floor.findLines(false); return floor.findCrossings(2); } int main(int argc, char **argv) { if (argc < 2) { std::cerr << "You must provide input file!" << std::endl; return 1; } auto input = getLines(argv[1]); OceanFloor floor(input.first.first, input.first.second, input.second); std::cout << "The number of overlapping points without diagonals is \033[91;1m" << part1(floor) << "\033[0m." << std::endl; std::cout << "The number of overlapping points with diagonals is \033[91;1m" << part2(floor) << "\033[0m." << std::endl; return 0; }