aboutsummaryrefslogtreecommitdiff
path: root/src/2019/day10/aoc.cpp
blob: 177ee613efe4460a3b754a6fde0947892fb3c18c (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
#include "aoc.h"
#include <algorithm>
#include <vector>
#include <math.h>

namespace aoc2019 {

struct posd {
  belt::pos p;
  belt::distance d;
  int count = 0;
};

float angle(int x, int y) {
  auto a = atan2(y, x);
  auto r = a * 180 / M_PI;
  if (r > 360) {
    r -= 360;
  }
  if (r < 0) {
    r += 360;
  }
  r += 90;
  return r >= 360 ? r - 360 : r;
}


belt::pos vaporize(belt b, belt::pos& m, std::vector<posd>& ps, int* count) {
  belt bx = b;
  for (auto& dp : ps) {
    if (dp.count == 0 && !bx.blocked(dp.p, m)) {
      dp.count = 1;
      b.get(dp.p) = '.';
      *count += 1;
      // printf("%d asteroid to be vaporized is at (%d, %d)\n", *count, dp.p.x, dp.p.y);
      if (*count == 200) {
        return dp.p;
      }
    }
  }
  return vaporize(b, m, ps, count);
}

std::pair<int, int> day10(line_view file) {
  belt b;
  int r{0};
  per_line(file, [&b, &r](line_view lv) {
    b.load(lv, r++);
    return true;
  });

  std::vector<posd> ps;
  b.iterate([&ps, &b](belt::pos p){
    if (b.get(p) == '#') {
      posd d;
      d.p = p;
      b.count(p, &d.count);
      ps.push_back(d);
    }
  });

  std::sort(ps.begin(), ps.end(), [](const posd& d1, const posd& d2){
      return d1.count > d2.count;
  });

  int max = ps[0].count;
  belt::pos monitor = ps[0].p;

  for (auto& a : ps) {
    a.d = b.dist(a.p, monitor);
    a.count = a.p == monitor ? 1 : 0; // mark as not lazered
  }

  std::sort(ps.begin(), ps.end(), [](const posd& d1, const posd& d2) {
      return angle(d1.d.dx, d1.d.dy) < angle(d2.d.dx, d2.d.dy);
  });

  int count{0};
  belt::pos xp = vaporize(b, monitor, ps, &count);
  return {max, xp.x * 100 + xp.y};
}

} // namespace aoc2019