aboutsummaryrefslogtreecommitdiff
path: root/src/2019/day3/aoc.h
blob: abd0c544d5767f70233f20ca1e83af42e6f86df3 (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
#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 {
    int id;
    line_view label;
    day3point a;
    day3point b;
    int length;
  };

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

  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 parse(line_view lv, day3point* cp) {
    part p;
    const char* p1 = lv.line;
    int i{0};
    auto make_part = [&i, &p, &p1, cp, this](part::dir_t d) {
      p.dir = d;
      const char* p0 = p1;
      get_part(&p1, &p.distance);
      day3point a = *cp;
      *cp = mov(*cp, p);
      line l{i++, {p0, p1}, a, *cp, p.distance};
      ps.push_back(l);
      if (d == part::right || d == part::left) {
        psh.push_back(l);
      }
      if (d == part::up || d == part::down) {
        psv.push_back(l);
      }
    };
    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++;
    }
  }
};

std::pair<int, int> day3(line_view);

} // namespace aoc2019