194 lines
4.4 KiB
C++
194 lines
4.4 KiB
C++
#include <array>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
|
|
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<Line> &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<Line> &_lines;
|
|
std::vector<std::vector<int>> floor;
|
|
};
|
|
|
|
std::pair<std::pair<int, int>, std::vector<Line>>
|
|
getLines(const std::string &file_name) {
|
|
int maxY = 0;
|
|
int maxX = 0;
|
|
std::vector<Line> 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;
|
|
}
|