aboutsummaryrefslogtreecommitdiff
path: root/src/2022/day24/aoc.h
blob: 3e7b590db19957e2217528da062300416c6f585d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "common.h"
#include <map>
#include <vector>

namespace aoc2022 {

struct blizzard {
  int x;
  int y;
  char c;

  blizzard next(int height, int width) {
    switch (c) {
    case '>':
      return {x + 1 == width - 1 ? 1 : x + 1, y, c};
    case '<':
      return {x - 1 == 0 ? width - 2 : x - 1, y, c};
    case '^':
      return {x, y - 1 == 0 ? height - 2 : y - 1, c};
    case 'v':
      return {x, y + 1 == height - 1 ? 1 : y + 1, c};
    default:
      break;
    }
    return *this;
  }

  friend bool operator<(blizzard b1, blizzard b2) { return b1.x < b2.x ? true : b1.x > b2.x ? false : b1.y < b2.y; }
  friend bool operator==(blizzard b1, blizzard b2) { return b1.x == b2.x && b1.y == b2.y; }
};

struct valley {
  int width;
  int height;

  char* pixel;
  std::vector<std::vector<blizzard>> blzs;

  valley(int w, int h) : width(w), height(h) {
    pixel = (char*)malloc(width * height);
    blzs.resize(1);
  }

  char& get(int h, int w) { return *(pixel + h * width + w); }

  void load(int h, line_view lv) {
    for (size_t i = 0; i < lv.length - 1; i++) {
      char c = *(lv.line + i);
      get(h, i) = c;
      if (c == '<' || c == '>' || c == '^' || c == 'v') {
        get(h, i) = '.';
        blzs[0].emplace_back(blizzard{(int)i, h, c});
      }
    }
  }

  std::vector<blizzard> at(int t) {
    t %= width * height;
    while (blzs.size() < (size_t)t + 1) {
      auto l = blzs.size() - 1;
      std::vector<blizzard> n = blzs[l];
      for (size_t i = 0; i < n.size(); i++) {
        n[i] = n[i].next(height, width);
      }
      blzs.push_back(n);
    }
    return blzs[t];
  }

  void print(int t) {
    std::map<blizzard, int> m;
    auto blz = at(t);
    for (auto& b : blz) {
      auto p = m.insert({b, 1});
      if (!p.second) {
        p.first->second += 1;
      }
    }

    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        auto it = m.find(blizzard{x, y, '.'});
        if (it == m.end()) {
          printf("%c", get(y, x));
        } else {
          if (it->second > 1) {
            printf("%d", it->second);
          } else {
            printf("%c", it->first.c);
          }
        }
      }
      printf("\n");
    }
  }
};

std::pair<int, int> day24(line_view);
} // namespace aoc2022