aboutsummaryrefslogtreecommitdiff
path: root/src/2016/day23/aoc.cpp
blob: 9b6a6ba3c263acbe88b85489b24bc27cf0e62bf8 (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
117
118
119
120
121
#include "aoc.h"

namespace aoc2016 {

static int registers[4] = {7, 0, 0, 0};

static int& get(int i) { return registers[i]; }
// c = a,b,c,d
static int& get(char c) { return get(c - 'a'); }

struct instruction23 {
  mutable size_t toggles = 0;
  line_view todo;

  instruction23(line_view l) : todo(l) {}

  int which() {
    std::cout << todo << std::endl;
    const char* p = todo.line;
    switch (*p) {
    case 'c':
      return 0;
    case 'i':
      return 1;
    case 'd':
      return 2;
    case 'j':
      return 3;
    case 't':
      return 4;
    default:
      break;
    }
    return 4;
  }
};

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

typedef void (*todo_f)(size_t*, const char*, const std::vector<instruction23>&);
static void cpy(size_t* i, const char* p, const std::vector<instruction23>& todos) {
  int d{0};
  if (*p >= '0' && *p <= '9') {
    get_number(&p, &d);
    p += 1;
  } else {
    d = get(*p);
    p += 2;
  }
  get(*p) = d;
  *i += 1;
}

static void inc(size_t* i, const char* p, const std::vector<instruction23>& todos) {
  get(*p) += 1;
  *i += 1;
}

static void dec(size_t* i, const char* p, const std::vector<instruction23>& todos) {
  get(*p) -= 1;
  *i += 1;
}

static void jnz(size_t* i, const char* p, const std::vector<instruction23>& todos) {
  bool condition = *p >= '0' && *p <= '9' ? *p - '0' : get(*p) != 0;
  if (condition) {
    p += 2;
    int offset{0};
    get_number(&p, &offset);
    *i += offset;
  } else {
    *i += 1;
  }
}

static void tgl(size_t* i, const char* p, const std::vector<instruction23>& todos) {
  size_t next = *i + get(*p);
  if (next < todos.size()) {
    todos[next].toggles += 1;
  }
  *i += 1;
}

static void non(size_t* i, const char* p, const std::vector<instruction23>&) { *i += 1; }

static size_t exec(size_t i, const std::vector<instruction23>& todos) {
  if (i < todos.size()) {
    todo_f fs[6] = {cpy, inc, dec, jnz, tgl, non};
    auto d = todos[i];
    fs[d.which()](&i, d.todo.line + 4, todos);
  }
  return i;
}

std::pair<int64_t, int64_t> day23(line_view file) {
  std::vector<instruction23> todos;
  per_line(file, [&todos](line_view lv) {
    todos.emplace_back(line_view{lv.line, lv.length - 1});
    return true;
  });
  size_t i = 0;
  while (i < todos.size()) {
    i = exec(i, todos);
  }

  return {0, 0};
}
} // namespace aoc2016