#include #include #include #include #include class Diagnostics { public: Diagnostics(size_t report_size) { most_common.resize(report_size); } ~Diagnostics() = default; void addReport(const std::string &report) { reports.push_back(report); for (size_t i = 0; i < report.length(); i++) { switch (report[i]) { case '0': most_common[i].first += 1; break; case '1': most_common[i].second += 1; default: break; } } } int getPowerConsumption() const { return getGammaRate() * getEpsilonRate(); } int getLifeSupportRating() const { return getOxygenRating() * getCO2Rating(); } private: int getGammaRate() const { return getRate(true); } int getEpsilonRate() const { return getRate(false); } int getRate(bool gamma) const { std::vector rate{}; for (size_t i = 0; i < most_common.size(); i++) { if (gamma) { rate.push_back(getMostCommon(i)); } else { rate.push_back(getLeastCommon(i)); } } return binaryToDecimal(rate); } int binaryToDecimal(const std::vector &binary) const { int result = 0; int multiplier = 1; for (size_t i = binary.size() - 1; i > 0; i--) { result += multiplier * binary[i]; multiplier *= 2; } result += multiplier * binary[0]; return result; } int binaryToDecimal(const std::string &binary) const { std::vector binary_vec{}; for (auto &bit : binary) { switch (bit) { case '0': binary_vec.push_back(0); break; case '1': binary_vec.push_back(1); default: break; } } return binaryToDecimal(binary_vec); } int getMostCommon(int index) const { if (most_common[index].first > most_common[index].second) { return 0; } return 1; } int getLeastCommon(int index) const { return (getMostCommon(index) + 1) % 2; } std::unordered_set getInitialOptions() const { std::unordered_set options{}; for (size_t i = 0; i < reports.size(); i++) { options.insert(i); } return options; } int getOxygenRating() const { return getPart2Rating(true); } int getCO2Rating() const { return getPart2Rating(false); } int getPart2Rating(bool oxygen) const { auto options = getInitialOptions(); std::unordered_set to_remove{}; size_t cmp_index = 0; while (options.size() != 1) { for (auto &option : options) { if ((oxygen && reports[option][cmp_index] != getMostCommonChar(options, cmp_index)) || (!oxygen && reports[option][cmp_index] != getLeastCommonChar(options, cmp_index))) { to_remove.insert(option); } } for (auto &remove : to_remove) { options.erase(remove); } to_remove.clear(); cmp_index++; } return binaryToDecimal(reports[*options.begin()]); } char getMostCommonChar(const std::unordered_set &options, int index) const { int zeros = 0; int ones = 0; for (auto &option : options) { if (reports[option][index] == '0') { zeros += 1; } else { ones += 1; } } if (zeros > ones) { return '0'; } return '1'; } char getLeastCommonChar(const std::unordered_set &options, int index) const { if (getMostCommonChar(options, index) == '0') { return '1'; } return '0'; } std::vector reports; std::vector> most_common; }; Diagnostics getDiagnostics(const std::string &file_name) { std::ifstream file(file_name); std::string tmp{}; std::string str; std::getline(file, str); Diagnostics result(str.length()); do { std::stringstream ss(str); ss >> tmp; result.addReport(tmp); } while (std::getline(file, str)); return result; } int part1(const Diagnostics &diagnostics) { return diagnostics.getPowerConsumption(); } int part2(const Diagnostics &diagnostics) { return diagnostics.getLifeSupportRating(); } int main(int argc, char **argv) { if (argc < 2) { std::cerr << "You must provide input file!" << std::endl; return 1; } auto diagnostics = getDiagnostics(argv[1]); std::cout << "The submarine's power conusmption is \033[91;1m" << part1(diagnostics) << "\033[0m." << std::endl; std::cout << "The submarine's life support rating is \033[91;1m" << part2(diagnostics) << "\033[0m." << std::endl; return 0; }