aboutsummaryrefslogtreecommitdiff
path: root/src/2019/day3/aoc.h
blob: 48b6812d842aa3402c01bf6c34de2e0b9a9de0b4 (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
#pragma once
#include "common.h"
#include <algorithm>
#include <functional>
#include <vector>

namespace aoc2019 {

struct day3point {
  int x;
  int y;

  int distance() const noexcept { return std::abs(x) + std::abs(y); }
  bool operator<(const day3point& other) const noexcept { return distance() < other.distance(); }
};

struct wire {
  struct part {
    enum dir_t {
      up,
      right,
      down,
      left,
    } dir;
    int distance;
  };

  day3point mov(day3point p, part pa) const noexcept {
    auto addy = [&p](int d) -> day3point { return {p.x, p.y + d}; };
    auto addx = [&p](int d) -> day3point { return {p.x + d, p.y}; };
    auto suby = [&p](int d) -> day3point { return {p.x, p.y - d}; };
    auto subx = [&p](int d) -> day3point { return {p.x - d, p.y}; };
    std::function<day3point(int)> fs[] = {addy, addx, suby, subx};
    return fs[int(pa.dir)](pa.distance);
  }

  struct line {
    day3point a;
    day3point b;
  };

  std::vector<line> psh;
  std::vector<line> psv;

  void sort() {
    std::sort(psh.begin(), psh.end(),
              [](const line& l1, const line& l2) { return std::abs(l1.a.y) < std::abs(l2.a.y); });
    std::sort(psv.begin(), psv.end(),
              [](const line& l1, const line& l2) { return std::abs(l1.a.x) < std::abs(l2.a.x); });
  }

  void get_part(const char** pp, int* d) {
    *d = 0;
    const char* p = *pp + 1;
    while (*p >= '0' && *p <= '9') {
      *d = *d * 10 + *p - '0';
      p++;
    }
    *pp = p;
  }

  void largest(day3point* cp, day3point* mp) {
    if (std::abs(cp->x) > std::abs(mp->x)) {
      mp->x = cp->x;
    }
    if (std::abs(cp->y) > std::abs(mp->y)) {
      mp->y = cp->y;
    }
  }

  void parse(line_view lv, day3point* cp, day3point* mp) {
    part p;
    const char* p1 = lv.line;
    auto make_part = [&p, &p1, cp, mp, this](part::dir_t d) {
      p.dir = d;
      get_part(&p1, &p.distance);
      day3point a = *cp;
      *cp = mov(*cp, p);
      // printf("%d, %d\n", cp->x, cp->y);
      largest(cp, mp);
      if (d == part::right || d == part::left) {
        psh.push_back({a, *cp});
      }
      if (d == part::up || d == part::down) {
        psv.push_back({a, *cp});
      }
    };
    while (p1 < lv.line + lv.length) {
      switch (*p1) {
      case 'R':
        make_part(part::right);
        break;
      case 'L':
        make_part(part::left);
        break;
      case 'U':
        make_part(part::up);
        break;
      case 'D':
        make_part(part::down);
        break;
      default:
        break;
      }
      p1++;
    }
  }
};

int day3(line_view);

} // namespace aoc2019