advent2024

Advent of Code 2024
git clone git://bsandro.tech/advent2024
Log | Files | Refs

main.cpp (3073B)


      1 #include <iostream>
      2 #include <filesystem>
      3 #include <fstream>
      4 #include <vector>
      5 #include <cstring>
      6 #include <cstdio>
      7 #include <tuple>
      8 #include <algorithm>
      9 #include <sstream>
     10 
     11 enum class Op {
     12     sum,
     13     mul,
     14     con
     15 };
     16 
     17 //@todo make generic function using template
     18 void genVariations(std::vector<Op> &v, const std::vector<Op> &ops, size_t len, std::vector<std::vector<Op>> &vs) {
     19     if (v.size()==len) {
     20         vs.push_back(v);
     21         return;
     22     }
     23     for (Op o:ops) {
     24         v.push_back(o);
     25         genVariations(v, ops, len, vs);
     26         v.pop_back();
     27     }
     28 }
     29 
     30 class Equation {
     31 public:
     32     int64_t res;
     33     std::vector<int64_t> numbers;
     34     std::vector<std::vector<Op>> ps1; // operator permutations for part 1
     35     std::vector<std::vector<Op>> ps2; // operator permutations for part 1
     36 
     37     Equation(std::string in) {
     38         char tmp[256] = {0};
     39         std::sscanf(in.c_str(), "%ld: %[^\n]", &res, tmp);
     40         std::istringstream iss(tmp);
     41         int64_t num;
     42         while (iss >> num) numbers.push_back(num);
     43         populate();
     44     }
     45 
     46     int64_t calc(const std::vector<Op> &ops) {
     47         int64_t r = numbers.front();
     48         for (size_t i=0; i<ops.size(); ++i) {
     49             if (ops[i]==Op::mul) r *= numbers[i+1];
     50             if (ops[i]==Op::sum) r += numbers[i+1];
     51             if (ops[i]==Op::con) {
     52                 std::stringstream ss;
     53                 ss << r << numbers[i+1];
     54                 //r = std::stoi(ss.str());
     55                 ss >> r;
     56             }
     57         }
     58         return r;
     59     }
     60 
     61 private:
     62     void populate() {
     63         std::vector<Op> v;
     64         std::vector<Op> ops = {Op::sum, Op::mul};
     65         genVariations(v, ops, numbers.size()-1, ps1);
     66         v.clear();
     67         ops.push_back(Op::con);
     68         genVariations(v, ops, numbers.size()-1, ps2);
     69     }
     70 };
     71 
     72 typedef std::vector<Equation> Data;
     73 
     74 template<typename T>
     75 T read_file(const std::string &path) {
     76     std::ifstream ifs(path, std::ios::binary);
     77     if (!ifs.is_open()) {
     78         throw std::runtime_error(path+":"+std::strerror(errno));
     79     }
     80     T buf;
     81     while (1) {
     82         std::string str;
     83         std::getline(ifs, str);
     84         if (!str.empty()) buf.push_back(Equation(str));
     85         if (!ifs) break;
     86     }
     87     return buf;
     88 }
     89 //@todo threads!
     90 int64_t part1(Data &input [[ maybe_unused ]]) {
     91     int64_t r = 0;
     92     for (auto &e:input) {
     93         for (auto &v:e.ps1) {
     94             if (e.res==e.calc(v)) {
     95                 r+=e.res;
     96                 break;
     97             }
     98         }
     99     }
    100     return r;
    101 }
    102 int64_t part2(Data &input [[ maybe_unused ]]) {
    103     int64_t r = 0;
    104     for (auto &e:input) {
    105         for (auto &v:e.ps2) {
    106             if (e.res==e.calc(v)) {
    107                 r+=e.res;
    108                 break;
    109             }
    110         }
    111     }
    112     return r;
    113 }
    114 
    115 int main(int argc, char **argv) {
    116     const std::string fname = argc>1 ? argv[1] : "test1.txt";
    117     std::cout << "AoC 2024 day 07 " << fname << std::endl;
    118     Data input = read_file<Data>(fname);
    119     std::cout << "part1: " << part1(input) << std::endl;
    120     std::cout << "part2: " << part2(input) << std::endl;
    121 
    122     return 0;
    123 }