aboutsummaryrefslogtreecommitdiff
path: root/src/2016/day12/aoc.cpp
blob: bd3a395547fe8a66d079019e53eb58aa9eb49ecf (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
#include "aoc.h"

namespace aoc2016 {

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

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

struct instruction {
  line_view todo;

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

  int which() {
    const char* p = todo.line;
    switch (*p) {
    case 'c':
      return 0;
    case 'i':
      return 1;
    case 'd':
      return 2;
    case 'j':
      return 3;
    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*);
void cpy(size_t* i, const char* p) {
  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;
}

void inc(size_t* i, const char* p) {
  get(*p) += 1;
  *i += 1;
}

void dec(size_t* i, const char* p) {
  get(*p) -= 1;
  *i += 1;
}

void jnz(size_t* i, const char* p) {
  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;
  }
}

void non(size_t* i, const char* p) { *i += 1; }

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

std::pair<int64_t, int64_t> day12(line_view file) {
  std::vector<instruction> 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 {registers[0], 0};
}
} // namespace aoc2016