Advertisement
Guest User

aoc2023-3

a guest
Dec 3rd, 2023
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.49 KB | Source Code | 0 0
  1. #include <array>
  2. #include <fstream>
  3. #include <functional>
  4. #include <iostream>
  5. #include <string>
  6. #include <vector>
  7.  
  8. bool issymbol(char c)
  9. {
  10.     return !std::isdigit(c) && c != '.';
  11. }
  12.  
  13. bool isgear(char c)
  14. {
  15.     return c == '*';
  16. }
  17.  
  18. /**
  19.  * Returns if row is in the interval [0, max_row) and col is in the
  20.  * interval [0, max_col).
  21.  */
  22. bool is_inbounds(int row, int col, int max_row, int max_col)
  23. {
  24.     return row >= 0 && row < max_row
  25.         && col >= 0 && col < max_col;
  26. }
  27.  
  28. /**
  29.  * Sets adjacent numbers in nums_field to the given bool value in set_to.
  30.  *
  31.  * Returns number of adjacent numbers (not digits) that were set.
  32.  */
  33. int set_adjacents(const std::vector<std::string> &strs, std::vector<std::vector<bool>> &nums_field, bool set_to, int row, int col)
  34. {
  35.     int nadjs_set = 0;
  36.  
  37.     /* Adding these to row/column will give all possible adjacent positions. */
  38.     constexpr std::array<std::array<int, 2>, 8> adjacents { {
  39.         { -1, -1 },
  40.         { -1, 0 },
  41.         { 0, -1 },
  42.         { -1, 1 },
  43.         { 1, -1 },
  44.         { 1, 0 },
  45.         { 0, 1 },
  46.         { 1, 1 },
  47.     } };
  48.  
  49.     for (const auto &a : adjacents) {
  50.         int adj_row = row + a[0];
  51.         int adj_col = col + a[1];
  52.         int max_row = static_cast<int>(strs.size());
  53.         int max_col = static_cast<int>(strs[row].size());
  54.  
  55.         if (is_inbounds(adj_row, adj_col, max_row, max_col)) {
  56.             /* Check if the number has already been marked. */
  57.             if (nums_field[adj_row][adj_col] == set_to) {
  58.                 continue;
  59.             }
  60.  
  61.             if (std::isdigit(strs[adj_row][adj_col])) {
  62.                 nadjs_set++;
  63.  
  64.                 /* Find the start of the first digit of the found number. */
  65.                 int first_digit_col = adj_col;
  66.                 while (is_inbounds(adj_row, first_digit_col - 1, max_row, max_col)
  67.                     && std::isdigit(strs[adj_row][first_digit_col - 1])) {
  68.  
  69.                     first_digit_col--;
  70.                 }
  71.  
  72.                 /* Mark all the digits in number as found. */
  73.                 for (int i = first_digit_col; i < max_col && std::isdigit(strs[adj_row][i]); i++) {
  74.                     nums_field[adj_row][i] = set_to;
  75.                 }
  76.             }
  77.         }
  78.     }
  79.  
  80.     return nadjs_set;
  81. }
  82.  
  83. /**
  84.  * Returns the value of all numbers in strs inidicated by nums_field using the
  85.  * calculation from the reducer function fn to get the result.
  86.  */
  87. int reduce(const std::vector<std::string> &strs, const std::vector<std::vector<bool>> &nums_field, std::function<int(int, int)> fn, int initial_value)
  88. {
  89.     int result = initial_value;
  90.  
  91.     for (size_t i = 0; i < nums_field.size(); i++) {
  92.         size_t num_start = 0;
  93.         size_t num_size = 0;
  94.         for (size_t j = 0; j < nums_field[i].size(); j++) {
  95.             if (nums_field[i][j]) {
  96.                 if (num_size == 0) {
  97.                     num_start = j;
  98.                 }
  99.                 num_size++;
  100.             } else if (!nums_field[i][j] && num_size != 0) {
  101.                 result = fn(result, std::stoi(strs[i].substr(num_start, num_size)));
  102.  
  103.                 num_start = 0;
  104.                 num_size = 0;
  105.             } else {
  106.                 num_start = 0;
  107.                 num_size = 0;
  108.             }
  109.         }
  110.  
  111.         /* If the last column of a row is a digit it has not yet been added to
  112.          * result, so do it now. */
  113.         if (num_size != 0) {
  114.             result = fn(result, std::stoi(strs[i].substr(num_start, num_size)));
  115.         }
  116.     }
  117.  
  118.     return result;
  119. }
  120.  
  121. int main()
  122. {
  123.     std::ifstream input("../input.txt");
  124.     if (!input.is_open()) {
  125.         perror("Error");
  126.         exit(EXIT_FAILURE);
  127.     }
  128.  
  129.     int result_p1 = 0; /* Part 1 answer. */
  130.     int result_p2 = 0; /* Part 2 answer. */
  131.  
  132.     /* Indicates valid digit positions. */
  133.     std::vector<std::vector<bool>> nums_field_p1 {};
  134.     std::vector<std::vector<bool>> nums_field_p2 {};
  135.  
  136.     std::vector<std::string> lines {};
  137.  
  138.     std::string line("");
  139.     while (std::getline(input, line)) {
  140.         lines.push_back(line);
  141.         nums_field_p1.push_back(std::vector<bool>(line.size(), false));
  142.         nums_field_p2.push_back(std::vector<bool>(line.size(), false));
  143.     }
  144.  
  145.     /* Find symbol/gear and mark all adjacent numbers as valid. */
  146.     for (size_t i = 0; i < lines.size(); i++) {
  147.         for (size_t j = 0; j < lines[i].size(); j++) {
  148.             /* Part 1 */
  149.             if (issymbol(lines[i][j])) {
  150.                 set_adjacents(lines, nums_field_p1, true, static_cast<int>(i), static_cast<int>(j));
  151.             }
  152.  
  153.             /* Part 2 */
  154.             int num_adjs = 0;
  155.             if (isgear(lines[i][j])) {
  156.                 num_adjs = set_adjacents(lines, nums_field_p2, true, static_cast<int>(i), static_cast<int>(j));
  157.             }
  158.  
  159.             if (num_adjs == 2) {
  160.                 result_p2 += reduce(
  161.                     lines, nums_field_p2, [](int a, int b) {
  162.                         return a * b;
  163.                     },
  164.                     1);
  165.             }
  166.  
  167.             /* Reset adjacent numbers for gears so they are not used in future
  168.              * result calculations. */
  169.             set_adjacents(lines, nums_field_p2, false, static_cast<int>(i), static_cast<int>(j));
  170.         }
  171.     }
  172.  
  173.     result_p1 = reduce(
  174.         lines, nums_field_p1, [](int a, int b) {
  175.             return a + b;
  176.         },
  177.         0);
  178.  
  179.     std::cout << "Part 1: " << result_p1 << "\n";
  180.     std::cout << "Part 2: " << result_p2 << "\n";
  181.  
  182.     return EXIT_SUCCESS;
  183. }
  184.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement