aboutsummaryrefslogtreecommitdiff
path: root/src/2022/day24/aoc.cpp
blob: 373e4ace493dc4b88fd4413c0afdc1aacc88a23c (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
#include "aoc.h"

namespace aoc2022 {

struct pos {
  int x;
  int y;

  bool operator==(pos p) const noexcept {
    return x == p.x && y == p.y;
  }
};

bool is_valid(pos p, const std::map<blizzard, int>&m, valley& v) {
  auto b = p.x >= 0 && p.x < v.width && p.y >= 0 && p.y < v.height;
  return b && m.find(blizzard{p.x, p.y, '.'}) == m.end() && v.get(p.y, p.x) == '.';
}

void expedition(int m, pos p, pos target, valley& v, int* min, bool pass) {
  if (*min < INT32_MAX && m > *min) return;
  if (p == target) {
    printf("arrived by %d !!!\n", m);
    if (*min > m) *min = m;
  }
  else {
    auto& t = v.get_time(p.y, p.x);

    if (m < t || pass) {
      // printf("(%d, %d) in %d, was %d\n", p.x, p.y, m, t);
      if (!pass) t = m;

      v.next();
      std::map<blizzard, int> mp; 
      for (auto& b: v.blz) {
        auto p = mp.insert({b, 1});
        if (!p.second) {
          p.first->second += 1;
        }
      }

      pos mv0[5] = {
        {p.x, p.y+1},
        {p.x+1, p.y},
        {p.x, p.y-1},
        {p.x-1, p.y},
        p,
      };
      for (int i = 0; i < 5; i++) {
        auto mv = mv0[i];
        if (is_valid(mv, mp, v)) {
          auto blz = v.blz;
          expedition(m + 1, mv, target, v, min, i > 2);
          v.blz = blz;
        }
      }
    }
  }
}

std::pair<int, int> day24(line_view file) {
  // valley v{8,6}; //sample
  valley v{152,22};

  int height{0};
  per_line(file, [&v, &height](line_view lv) {
    v.load(height++, lv);
    return true;
  });

  int min{INT32_MAX};
  // v.print();
  expedition(0, {1, 0}, {150, 21}, v, &min, false);

  return {min, 0};
}
}