-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdayEight.cpp
More file actions
165 lines (139 loc) · 5.44 KB
/
dayEight.cpp
File metadata and controls
165 lines (139 loc) · 5.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <utility>
#include <unordered_map>
#include <set>
namespace DayEight
{
namespace {
using square_vect_t = std::vector<std::vector<char>>;
using coord_t = std::pair<int, int>;
coord_t getReverseCoordMovement(const coord_t movementCopy);
bool isCoordWithinBounds(const coord_t& nextCoord, const int kSquareLen);
void coutSquareVector(const std::string prefix, const square_vect_t& charSquare);
coord_t getAToBMovement(const coord_t a, const coord_t b);
void coutModifiedSquareVector(square_vect_t charSquareCopy, const std::set<coord_t>& antinodes);
const bool toLog = false; // true false
const int kTestFileLineLen = 12;
const int kFullFileLineLen = 50; // files validated and pre checked for length and valid chars only.
const char kEmptySpaceChar = '.';
std::unordered_map<char, std::vector<coord_t>> antennas;
std::set<coord_t> antinodes;
void insertAntiNodesCoords(std::vector<coord_t> antennaCharCoords, const size_t kSquareLen, const square_vect_t charSquare)
{
size_t size = antennaCharCoords.size();
if (size < 2) return;
for (size_t i = 0; i < size; ++i) {
for (size_t j = i + 1; j < size; ++j) {
coord_t movementToB = getAToBMovement(antennaCharCoords[i], antennaCharCoords[j]);
coord_t reverseMovement = getReverseCoordMovement(movementToB);
coord_t aAntinode = { antennaCharCoords[i].first + reverseMovement.first, antennaCharCoords[i].second + reverseMovement.second };
coord_t bAntinode = { antennaCharCoords[j].first + movementToB.first, antennaCharCoords[j].second + movementToB.second };
if (isCoordWithinBounds(aAntinode, kSquareLen) && antinodes.find(aAntinode) == antinodes.end()) { // c++14, no contains()
antinodes.insert(aAntinode);
}
if (isCoordWithinBounds(bAntinode, kSquareLen) && antinodes.find(bAntinode) == antinodes.end()) {
antinodes.insert(bAntinode);
}
}
if (toLog) coutModifiedSquareVector(charSquare, antinodes);
}
}
size_t calculateAntinodes(const square_vect_t charSquare, const int kSquareLen)
{
for (const auto& antennaCharCoords : antennas) {
insertAntiNodesCoords(antennaCharCoords.second, kSquareLen, charSquare);
}
if (toLog) coutModifiedSquareVector(charSquare, antinodes);
return antinodes.size();
}
void fillLineInVector(const std::string line, square_vect_t& charSquare, const int kSquareLen, const int currentRow) {
for (int col = 0; col < kSquareLen; ++col) {
charSquare[currentRow][col] = line[col];
if (line[col] != kEmptySpaceChar) antennas[line[col]].push_back({ currentRow, col });
}
}
void handleFile(std::ifstream& inputFile, square_vect_t charSquare, const int kSquareLen)
{
coord_t startingGuardCoord;
if (inputFile.is_open()) {
std::string line;
int currentRow = 0;
while (getline(inputFile, line)) {
if (currentRow >= kSquareLen) throw std::runtime_error("Line read out of bounds");
fillLineInVector(line, charSquare, kSquareLen, currentRow);
currentRow++;
}
std::cout << "Finished reading file\n";
inputFile.close(); // automatically happens when going out of scope but no longer needed. More about explicitness.
size_t antiNodes = calculateAntinodes(charSquare, kSquareLen);
std::cout << "Antinodes: " << antiNodes << '\n';
std::cout << "\nFinished running program";
}
else {
std::cout << "Unable to open file\n";
}
}
coord_t getReverseCoordMovement(coord_t movementCopy)
{
return { -movementCopy.first, -movementCopy.second };
}
coord_t getAToBMovement(const coord_t a, const coord_t b)
{
coord_t movement = { b.first - a.first, b.second - a.second };
return movement;
}
bool isCoordWithinBounds(const coord_t& nextCoord, const int kSquareLen)
{
return nextCoord.first >= 0 && nextCoord.first < kSquareLen && nextCoord.second >= 0 && nextCoord.second < kSquareLen;
}
void coutModifiedSquareVector(square_vect_t charSquareCopy, const std::set<coord_t>& antinodes) {
for (const auto& coord : antinodes) {
int row = coord.first;
int col = coord.second;
if (row >= 0 && row < charSquareCopy.size() && col >= 0 && col < charSquareCopy[row].size()) {
charSquareCopy[row][col] = (charSquareCopy[row][col] == kEmptySpaceChar) ? '!' : '&';
}
}
std::cout << "Modified Character Square:\n";
for (const auto& row : charSquareCopy) {
for (const auto& ch : row) {
std::cout << ch;
}
std::cout << '\n';
}
std::cout << '\n';
}
void coutSquareVector(const std::string prefix, const square_vect_t& charSquare) {
std::cout << prefix << '\n';
for (const auto& row : charSquare) {
for (const auto& ch : row) {
std::cout << ch;
}
std::cout << '\n';
}
std::cout << '\n';
}
}
void dayEight() { // Antenna coord can have an antinode
std::system("cls"); // clear terminal pre-boot
std::cout << "Running program Day Eight" << '\n';
const bool isFullFile = true; // true false
const int kSquareLen = isFullFile ? kFullFileLineLen : kTestFileLineLen;
square_vect_t charSquare(kSquareLen, std::vector<char>(kSquareLen));
std::string line;
std::ifstream inputFile;
if (isFullFile) {
std::cout << "Using full file\n\n";
}
else {
std::cout << "Using test file\n\n";
}
(isFullFile) ? inputFile.open("dayEightFull.txt") : inputFile.open("dayEightTest.txt");
handleFile(inputFile, charSquare, kSquareLen);
}
}
// 434 too high