aboutsummaryrefslogtreecommitdiff
path: root/src/2018/day9/aoc.h
blob: 016ee2bcb728139f4eb28231947d65dff3e83fdc (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
#pragma once
#include "common.h"
#include <vector>

namespace aoc2018 {

struct marble {
  marble* prev = nullptr;
  marble* next = nullptr;
  size_t value = 0;
};

struct marble_circle {
  std::vector<marble> marbles;
  std::vector<size_t> players;
  marble* current;
  size_t point;

  void insert(marble* p, marble* n, marble* x) noexcept {
    p->next = x;
    x->next = n;
    x->prev = p;
    n->prev = x;
  }

  size_t high() const noexcept {
    size_t score = 0;
    for (auto& p : players) {
      score = std::max(score, p);
    }
    return score;
  }

  void remove(marble* x) noexcept {
    x->prev->next = x->next;
    x->next->prev = x->prev;
  }

  marble* next(marble* c, int n) noexcept {
    while (n-- > 0) {
      c = c->next;
    }
    return c;
  }

  marble* prev(marble* c, int n) noexcept {
    while (n-- > 0) {
      c = c->prev;
    }
    return c;
  }

  void print() {
    marble* x = &marbles[0];
    while (true) {
      if (x->next == &marbles[0]) {
        printf("%zu\n", x->value);
        break;
      } else {
        printf("%zu -> ", x->value);
        x = x->next;
      }
    }
  }

  marble_circle(size_t n, size_t p) : marbles(n + 1), players(p) {
    marbles[0].next = &marbles[1];
    marbles[0].prev = &marbles[1];
    marbles[0].value = 0;

    marbles[1].prev = &marbles[0];
    marbles[1].next = &marbles[0];
    marbles[1].value = 1;

    current = &marbles[1];
    point = 1;
  }

  void alloc(int a, int b, int c) {
    size_t i = 2;
    while (point < marbles.size() - 1) {
      // print();
      size_t p = point + 1;
      marbles[p].value = p;

      if (p % c == 0) {
        marble* m = prev(current, b);
        players[i - 1] += p + m->value;
        current = m->next;
        remove(m);
      } else {
        marble* m = next(current, a);
        insert(m, m->next, &marbles[p]);
        current = &marbles[p];
      }
      point = p;
      i = i == players.size() ? 1 : i + 1;
    }
  }
};

size_t day9(size_t players, size_t point);

} // namespace aoc2018