Untitled
unknown
c_cpp
2 years ago
2.9 kB
10
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