-
Notifications
You must be signed in to change notification settings - Fork 0
/
3.cpp
137 lines (116 loc) · 3.27 KB
/
3.cpp
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
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
struct Symbol {
int x;
char value;
};
struct Number {
int x;
int y;
int value;
int length;
int getAdjacentMinX() {
return x == 0 ? 0 : x - 1;
}
int getAdjacentMaxX() {
return x + length;
}
};
int getNumberLength(int value) {
if (value <= 0) return 0;
if (value < 10) return 1;
if (value < 100) return 2;
if (value < 1000) return 3;
if (value < 10000) return 4;
return 0;
}
int getSumForLine(Number& number, std::vector<Symbol>& symbols) {
int sum = 0;
for (const Symbol symbol : symbols) {
if (symbol.x >= number.getAdjacentMinX() && symbol.x <= number.getAdjacentMaxX()) {
sum += number.value;
}
}
return sum;
}
int main(int argc, char** argv) {
if (argc != 2) return 0;
std::ifstream fileStream(argv[1]);
if (fileStream.is_open()) {
int sum = 0;
std::string fileStreamLine;
char lineChar;
std::unordered_map<int, std::vector<Symbol>> symbolsByLine;
std::vector<Number> numbers;
int x = 0, y = 0, number = 0, numberLength = 0;
while (std::getline(fileStream, fileStreamLine)) {
for (x = 0; x < fileStreamLine.size(); x++) {
lineChar = fileStreamLine.at(x);
// check if space symbol
if (lineChar == '.') {
// check if we need to push a number
if (number > 0) {
numberLength = getNumberLength(number);
Number nb = { x - numberLength, y, number, numberLength };
numbers.push_back(nb);
number = 0;
}
continue;
}
// check if symbol
int symbolValue = lineChar - '0';
if (symbolValue < 0 || symbolValue > 9) {
// check if we need to push a number
if (number > 0) {
numberLength = getNumberLength(number);
Number nb = { x - numberLength, y, number, numberLength };
numbers.push_back(nb);
number = 0;
}
// add the symbol
Symbol sb = { x, lineChar };
symbolsByLine[y].push_back(sb);
continue;
}
// add number digit
number *= 10;
number += symbolValue;
}
// check if number is at end of line
if (number > 0) {
numberLength = getNumberLength(number);
Number nb = { x - numberLength, y, number, numberLength };
numbers.push_back(nb);
number = 0;
}
y++;
}
for (Number number : numbers) {
// get symbols on previous line
if (number.y > 0) {
auto symbolsIt = symbolsByLine.find(number.y - 1);
if (symbolsIt != symbolsByLine.end()) {
sum += getSumForLine(number, symbolsIt->second);
}
}
// get symbols on the same line
auto symbolsIt = symbolsByLine.find(number.y);
if (symbolsIt != symbolsByLine.end()) {
sum += getSumForLine(number, symbolsIt->second);
}
// get symbols on the next line
if (number.y < y) {
auto symbolsIt = symbolsByLine.find(number.y + 1);
if (symbolsIt != symbolsByLine.end()) {
sum += getSumForLine(number, symbolsIt->second);
}
}
}
std::cout << sum << std::endl;
fileStream.close();
}
return 0;
}