aboutsummaryrefslogtreecommitdiff
path: root/src/2015/day21/aoc.h
blob: ad6a68cabbce64710d00fbbd1abcf3a44d194628 (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
#pragma once
#include "common.h"
#include <algorithm>
#include <vector>

namespace aoc2015 {

struct Role {
  int hitpoints;
  int damage;
  int armor;
  int cost;
};

struct RPG {
  struct item {
    const char* name;
    int cost;
    int damage;
    int armor;
  };

  // 1 in 5
  item weapons[5] = {
      {"dagger", 8, 4, 0},     {"shortsword", 10, 5, 0}, {"warhammer", 25, 6, 0},
      {"longsword", 40, 7, 0}, {"greataxe", 74, 8, 0},
  };

  // 0, 1 in 5
  item armors[6] = {
      {"leather", 13, 0, 1},    {"chainmail", 31, 0, 2},  {"splintmail", 53, 0, 3},
      {"bandedmail", 75, 0, 4}, {"platemail", 102, 0, 5}, {"none", 0, 0, 0},
  };

  // 0, 1, 2 in 6
  item rings[7] = {
      {"ring1", 25, 1, 0}, {"ring2", 50, 2, 0}, {"ring3", 100, 3, 0}, {"ring4", 20, 0, 1},
      {"ring5", 40, 0, 2}, {"ring6", 80, 0, 3}, {"none", 0, 0, 0},
  };

  bool has_same_ring(std::vector<item*> is) {
    int x[ARRAY_SIZE(rings)] = {0};
    for (item* i : is) {
      line_view lv{i->name};
      const char* p = lv.contains("ring");
      if (p != nullptr && ++(x[*(p + 4) - '1']) > 1) {
        return true;
      }
    }
    return false;
  }

  // backtrace
  void shop(size_t i, std::vector<item*>& v, std::vector<Role>& rs, const Role& r) {
    static item* items[] = {weapons, armors, rings, rings};
    static size_t sizes[] = {ARRAY_SIZE(weapons), ARRAY_SIZE(armors), ARRAY_SIZE(rings), ARRAY_SIZE(rings)};
    if (i < ARRAY_SIZE(items)) {
      item* is = items[i];
      for (size_t x = 0; x < sizes[i]; x++) {
        v.push_back(&is[x]);
        shop(i + 1, v, rs, r);
        v.pop_back();
      }
    } else {
      if (!has_same_ring(v)) {
        Role x = r;
        std::for_each(v.begin(), v.end(), [&x](item* i) {
          x.cost += i->cost;
          x.armor += i->armor;
          x.damage += i->damage;
        });
        rs.push_back(x);
      }
    }
  }

  std::vector<Role> shop(Role r) {
    std::vector<item*> is;
    std::vector<Role> rs;
    shop(0, is, rs, r);
    return rs;
  }

  bool battle(Role& r1, Role& r2) {
    while (r1.hitpoints > 0 && r2.hitpoints > 0) {
      r2.hitpoints -= (r1.damage - r2.armor) > 0 ? r1.damage - r2.armor : 1;
      r1.hitpoints -= (r2.damage - r1.armor) > 0 ? r2.damage - r1.armor : 1;
    }
    return r1.hitpoints > 0 || r2.hitpoints <= 0;
  }
};

std::pair<int,int> day21();

} // namespace aoc2015