181 lines
4.4 KiB
C++
181 lines
4.4 KiB
C++
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <vector>
|
||
|
#include <set>
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
vector<vector<char>> parseGrid(const char *path) {
|
||
|
vector<vector<char>> grid;
|
||
|
ifstream input(path);
|
||
|
string line;
|
||
|
char c;
|
||
|
|
||
|
while (getline(input, line)) {
|
||
|
stringstream line_stream;
|
||
|
line_stream << line;
|
||
|
vector<char> row;
|
||
|
while (line_stream >> c) {
|
||
|
row.push_back(c);
|
||
|
}
|
||
|
grid.push_back(row);
|
||
|
}
|
||
|
return grid;
|
||
|
}
|
||
|
|
||
|
void printGrid(vector<vector<char>> grid) {
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[y].size(); x++) {
|
||
|
cout << grid[y][x];
|
||
|
}
|
||
|
cout << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void printAntinodes(vector<vector<char>> grid, vector<vector<bool>> antinodes) {
|
||
|
for (int y = 0; y < antinodes.size(); y++) {
|
||
|
for (int x = 0; x < antinodes[y].size(); x++) {
|
||
|
if (antinodes[y][x]) {
|
||
|
cout << '#';
|
||
|
} else {
|
||
|
cout << grid[y][x];
|
||
|
}
|
||
|
}
|
||
|
cout << endl;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int countAntinodes(vector<vector<char>> grid, vector<vector<bool>> &antinodes, int y1, int x1, char c) {
|
||
|
int sum = 0;
|
||
|
for (int y2 = 0; y2 < grid.size(); y2++) {
|
||
|
for (int x2 = 0; x2 < grid[y2].size(); x2++) {
|
||
|
if (grid[y2][x2] == c && y1 != y2 && x1 != x2) {
|
||
|
// distance vector
|
||
|
int x_delta = x1 - x2;
|
||
|
int y_delta = y1 - y2;
|
||
|
|
||
|
// first antinode
|
||
|
int x3 = x1 + x_delta;
|
||
|
int y3 = y1 + y_delta;
|
||
|
if (x3 >= 0 && x3 < grid[0].size() && y3 >= 0 && y3 < grid.size() && !antinodes[y3][x3]) {
|
||
|
antinodes[y3][x3] = true;
|
||
|
sum++;
|
||
|
}
|
||
|
|
||
|
// second antinode
|
||
|
x3 = x2 - x_delta;
|
||
|
y3 = y2 - y_delta;
|
||
|
if (x3 >= 0 && x3 < grid[0].size() && y3 >= 0 && y3 < grid.size() && !antinodes[y3][x3]) {
|
||
|
antinodes[y3][x3] = true;
|
||
|
sum++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// cout << "Antinodes after " << c << ":" << endl;
|
||
|
// printAntinodes(grid, antinodes);
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
int countAntinodesAdjusted(vector<vector<char>> grid, vector<vector<bool>> &antinodes, int y1, int x1, char c) {
|
||
|
int sum = 0;
|
||
|
for (int y2 = 0; y2 < grid.size(); y2++) {
|
||
|
for (int x2 = 0; x2 < grid[y2].size(); x2++) {
|
||
|
if (grid[y2][x2] == c && y1 != y2 && x1 != x2) {
|
||
|
// distance vector
|
||
|
int x_delta = x1 - x2;
|
||
|
int y_delta = y1 - y2;
|
||
|
|
||
|
int x3 = x1;
|
||
|
int y3 = y1;
|
||
|
|
||
|
while (x3 >= 0 && x3 < grid[0].size() && y3 >= 0 && y3 < grid.size()) {
|
||
|
if(!antinodes[y3][x3]) {
|
||
|
sum++;
|
||
|
antinodes[y3][x3] = true;
|
||
|
}
|
||
|
x3 += x_delta;
|
||
|
y3 += y_delta;
|
||
|
}
|
||
|
|
||
|
x3 = x2;
|
||
|
y3 = y2;
|
||
|
|
||
|
while (x3 >= 0 && x3 < grid[0].size() && y3 >= 0 && y3 < grid.size()) {
|
||
|
if(!antinodes[y3][x3]) {
|
||
|
sum++;
|
||
|
antinodes[y3][x3] = true;
|
||
|
}
|
||
|
x3 -= x_delta;
|
||
|
y3 -= y_delta;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// cout << "Antinodes after " << c << ":" << endl;
|
||
|
// printAntinodes(grid, antinodes);
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
int part1(const char *path) {
|
||
|
vector<vector<char>> grid = parseGrid(path);
|
||
|
vector<vector<bool>> antinodes;
|
||
|
// initialize antinodes grid
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
vector<bool> row;
|
||
|
for (int x = 0; x < grid[y].size(); x++) {
|
||
|
row.push_back(false);
|
||
|
}
|
||
|
antinodes.push_back(row);
|
||
|
}
|
||
|
|
||
|
set<char, greater<char>> visited;
|
||
|
|
||
|
int sum = 0;
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[y].size(); x++) {
|
||
|
if (grid[y][x] != '.' && visited.count(grid[y][x]) == 0) {
|
||
|
sum += countAntinodes(grid, antinodes, y, x, grid[y][x]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
int part2(const char *path) {
|
||
|
vector<vector<char>> grid = parseGrid(path);
|
||
|
vector<vector<bool>> antinodes;
|
||
|
// initialize antinodes grid
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
vector<bool> row;
|
||
|
for (int x = 0; x < grid[y].size(); x++) {
|
||
|
row.push_back(false);
|
||
|
}
|
||
|
antinodes.push_back(row);
|
||
|
}
|
||
|
|
||
|
set<char, greater<char>> visited;
|
||
|
|
||
|
int sum = 0;
|
||
|
for (int y = 0; y < grid.size(); y++) {
|
||
|
for (int x = 0; x < grid[y].size(); x++) {
|
||
|
if (grid[y][x] != '.' && visited.count(grid[y][x]) == 0) {
|
||
|
sum += countAntinodesAdjusted(grid, antinodes, y, x, grid[y][x]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[]) {
|
||
|
cout << "example1: " << part1("example") << endl;
|
||
|
cout << "input1: " << part1("input") << endl;
|
||
|
cout << "example2: " << part2("example") << endl;
|
||
|
cout << "input2: " << part2("input") << endl;
|
||
|
return 0;
|
||
|
}
|