Advertisement
Guest User

Untitled

a guest
Dec 12th, 2023
289
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.10 KB | None | 0 0
  1. #include <iostream>
  2. #include <fstream>
  3. #include <string>
  4. #include <string_view>
  5. #include <vector>
  6. #include <cstdint>
  7. #include <span>
  8. #include <optional>
  9. #include "../cpp/timer.hpp"
  10.  
  11. struct input {
  12.     std::string pattern;
  13.     std::vector<int> damaged;
  14. };
  15.  
  16. bool can_place_here(std::string_view pattern, int damaged) {
  17.     if (pattern[damaged] == '#') return false;
  18.     for (int i = 0; i < damaged; ++i) {
  19.         if (pattern[i] == '.') return false;
  20.     }
  21.     return true;
  22. }
  23.  
  24. struct memo {
  25.     memo(std::string_view pattern, std::span<const int> damaged)
  26.         : data(pattern.length() + 1, std::vector<int64_t>(damaged.size() + 1, -1)) {}
  27.     std::vector<std::vector<int64_t>> data;
  28.  
  29.     struct node {
  30.         int64_t& value;
  31.         explicit operator bool() const { return value != -1; }
  32.         int64_t memoize(int64_t v) { return value = v; }
  33.     };
  34.  
  35.     node get(std::string_view pattern, std::span<const int> damaged) {
  36.         return {data[pattern.length()][damaged.size()]};
  37.     }
  38. };
  39.  
  40. int64_t count(std::string_view pattern, std::span<const int> damaged, memo& m) {
  41.     auto k = m.get(pattern, damaged);
  42.     if (k) return k.value;
  43.  
  44.     if (damaged.empty()) {
  45.         return k.memoize(std::find(pattern.begin(), pattern.end(), '#') == pattern.end());
  46.     }
  47.  
  48.     auto cur = damaged.front();
  49.  
  50.     if (pattern.length() <= cur) return k.memoize(0);
  51.  
  52.     int64_t found = 0;
  53.  
  54.     if (can_place_here(pattern, cur)) {
  55.         found += count(pattern.substr(cur + 1), damaged.subspan(1), m);
  56.     }
  57.  
  58.     if (pattern[0] == '#') return k.memoize(found);
  59.  
  60.     found += count(pattern.substr(1), damaged, m);
  61.     return k.memoize(found);
  62. }
  63.  
  64. int64_t count(const input& in) {
  65.     std::string aug_pattern = in.pattern + '.'; // add trailing dot to make it easier to count
  66.     memo m(aug_pattern, in.damaged);
  67.     return count(aug_pattern, in.damaged, m);
  68. }
  69.  
  70. int64_t solve(std::span<const input> inputs) {
  71.     int64_t found = 0;
  72.     for (auto& in : inputs) {
  73.         found += count(in);
  74.     }
  75.     return found;
  76. }
  77.  
  78. int main() {
  79.     std::ifstream file(INPUT_PATH"/input.txt");
  80.     std::string line;
  81.     std::vector<input> inputs;
  82.     while (std::getline(file, line)) {
  83.         auto& in = inputs.emplace_back();
  84.  
  85.         auto space = line.find(' ');
  86.         in.pattern = line.substr(0, space);
  87.  
  88.         auto rest = std::string_view(line).substr(space + 1);
  89.  
  90.         while (true) {
  91.             auto comma = rest.find(',');
  92.             in.damaged.push_back(std::stoi(std::string(rest.substr(0, comma))));
  93.             if (comma == std::string_view::npos) break;
  94.             rest = rest.substr(comma + 1);
  95.         }
  96.     }
  97.  
  98.     timer t;
  99.  
  100.     // a
  101.     std::cout << solve(inputs) << '\n';
  102.  
  103.     // b
  104.     for (auto& in : inputs) {
  105.         auto orig_pattern = in.pattern;
  106.         auto orig_damaged = in.damaged;
  107.         for (int i = 0; i < 4; ++i) {
  108.             in.pattern += '?';
  109.             in.pattern += orig_pattern;
  110.             in.damaged.insert(in.damaged.end(), orig_damaged.begin(), orig_damaged.end());
  111.         }
  112.     }
  113.     std::cout << solve(inputs) << '\n';
  114.  
  115.     return 0;
  116. }
  117.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement