Untitled
unknown
c_cpp
2 years ago
2.9 kB
12
Indexable
#include <cassert>
#include <fstream>
#include <iostream>
#include <numeric>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;
class Decoder {
private:
vector<string> encoded_strings;
int rows, cols;
unordered_map<int, vector<int>> gears;
int f(int r, int c) { return c + r * cols; }
public:
Decoder(fstream file) {
if (file.is_open()) {
string line;
while (getline(file, line)) {
encoded_strings.push_back(line);
}
file.close();
}
rows = encoded_strings.size();
cols = encoded_strings.front().size();
}
Decoder(const string file_name) : Decoder(fstream(file_name, ios::in)) {}
~Decoder() {}
vector<tuple<int, int, int>> get_num_metadata(string &s) {
vector<tuple<int, int, int>> results;
int current_num = 0, start_idx = -1;
for (int idx = 0; idx <= s.size(); ++idx) {
if (idx < s.size() && isdigit(s[idx])) {
current_num = current_num * 10 + (s[idx] - '0');
if (start_idx == -1)
start_idx = idx;
} else if (start_idx != -1) {
results.emplace_back(current_num, start_idx, idx - start_idx);
current_num = 0;
start_idx = -1;
}
}
return results;
}
bool within_bounds(int row, int col) {
return 0 <= row and row < rows and 0 <= col and col < cols;
}
bool is_valid_symbol(int r, int c) {
return within_bounds(r, c) ? encoded_strings[r][c] == '*' : false;
}
optional<int> is_valid(int row, int start_col, int end_col) {
for (int r = row - 1; r <= row + 1; r++) {
for (int c = start_col - 1; c <= end_col + 1; c++) {
if ((r != row || c < start_col || c > end_col) &&
is_valid_symbol(r, c)) {
return f(r, c);
}
}
}
return nullopt;
}
int get_total() {
vector<int> numbers;
int row = 0;
for (auto encoded_string : encoded_strings) {
// on each line, get the numbers
vector<tuple<int, int, int>> num_metadata =
get_num_metadata(encoded_string);
// check if a number is bordered by a symbol (i.e., not period nor digits)
for (auto &[number, start_idx, length] : num_metadata) {
auto loc = is_valid(row, start_idx, start_idx + length - 1);
if (loc.has_value()) {
gears[loc.value()].push_back(number);
}
}
row++;
}
for (auto &[_, gear_list] : gears) {
if (gear_list.size() == 2) {
numbers.push_back(gear_list.front() * gear_list.back());
}
}
return accumulate(numbers.begin(), numbers.end(), 0);
}
};
int main(int argc, char *argv[]) {
if (argc < 2) {
cerr << "Usage: " << argv[0] << " <file_name>" << std::endl;
return 1;
}
string file_name = argv[1];
cout << Decoder(file_name).get_total() << endl;
return 0;
}
Editor is loading...
Leave a Comment