aboutsummaryrefslogtreecommitdiff
path: root/src/2019/day10/aoc.cpp
blob: 60de3ea3af10a3fbb6d24ab6a007398a3040c173 (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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "aoc.h"
#include <algorithm>
#include <vector>

namespace aoc2019 {

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

enum dim {
  xe0yl0,
  xg0yl0,
  xg0ye0,
  xg0yg0,
  xe0yg0,
  xl0yg0,
  xl0ye0,
  xl0yl0
};

dim dimention(belt::distance d) {
  if (d.dx == 0 && d.dy < 0) return xe0yl0;
  if (d.dx > 0 && d.dy < 0) return xg0yl0;
  if (d.dx > 0 && d.dy == 0) return xg0ye0;
  if (d.dx > 0 && d.dy > 0) return xg0yg0;
  if (d.dx == 0 && d.dy > 0) return xe0yg0;
  if (d.dx < 0 && d.dy > 0) return xl0yg0;
  if (d.dx < 0 && d.dy == 0) return xl0ye0;
  return xl0yl0;
}

bool dimcmp(dim m, belt::distance d1, belt::distance d2) {
  int x1 = std::abs(d1.dx);
  int y1 = std::abs(d1.dy);
  int x2 = std::abs(d2.dx);
  int y2 = std::abs(d2.dy);

  switch (m) {
    case xe0yl0: return y1 < y2;
    case xg0yl0: return y1 > y2 ? true : y1 < y2 ? false : x1 < x2;
    case xg0ye0: return x1 < x2;
    case xg0yg0: return y1 < y2 ? true : y1 > y2 ? false : x1 < x2;
    case xe0yg0: return y1 < y2;
    case xl0yg0: return y1 > y2 ? true : y1 < y2 ? false : x1 < x2;
    case xl0ye0: return x1 < x2;
    case xl0yl0: return y1 < y2 ? true : y1 > y2 ? false : x1 < x2;
  }
  return false;
}

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) {
      dim m1 = dimention(d1.d);
      dim m2 = dimention(d2.d);
      if (m1 == m2) {
        return dimcmp(m1, d1.d, d2.d);
      }
      else {
        return (int) m1 < (int) m2;
      }
  });

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

} // namespace aoc2019