aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2024-11-20 22:46:18 +0100
committerThomas Schmucker <ts@its1.de>2024-11-20 22:46:18 +0100
commitab1af5a087d4dba1b928cb2e430457661c4be3d2 (patch)
tree7e7bf5e433c34e54d71157914173af5184a2aafb
parentb84bb5aa6b3139a2a097c7ece914bf1866d6a162 (diff)
downloadadvent-of-code-ab1af5a087d4dba1b928cb2e430457661c4be3d2.tar.gz
advent-of-code-ab1af5a087d4dba1b928cb2e430457661c4be3d2.tar.bz2
advent-of-code-ab1af5a087d4dba1b928cb2e430457661c4be3d2.zip
aoc 2015, day 21
-rw-r--r--2015/src/day21.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/2015/src/day21.cpp b/2015/src/day21.cpp
new file mode 100644
index 0000000..2a38c86
--- /dev/null
+++ b/2015/src/day21.cpp
@@ -0,0 +1,181 @@
1#include <array>
2#include <fstream>
3#include <iostream>
4#include <sstream>
5using namespace std;
6
7struct Item {
8 Item(string_view name, int cost, int damage, int armor)
9 : name_(name)
10 , cost_(cost)
11 , damage_(damage)
12 , armor_(armor)
13 {
14 }
15
16 const string name_;
17 const int cost_;
18 const int damage_;
19 const int armor_;
20};
21
22struct Boss {
23 int hit_points_;
24 int damage_;
25 int armor_;
26};
27
28struct Player {
29 Player(const Item& weapon, const Item& armor, const tuple<Item, Item>& rings)
30 : damage_(weapon.damage_ + armor.damage_ + get<0>(rings).damage_ + get<1>(rings).damage_)
31 , armor_(weapon.armor_ + armor.armor_ + get<0>(rings).armor_ + get<1>(rings).armor_)
32 {
33 }
34
35 int hit_points_{ 100 };
36 int damage_;
37 int armor_;
38
39 bool would_win_against(Boss boss)
40 {
41 while ( true ) {
42 auto player_damage = max(1, damage_ - boss.armor_);
43 boss.hit_points_ -= player_damage;
44 if ( boss.hit_points_ <= 0 ) {
45 return true;
46 }
47
48 auto boss_damage = max(1, boss.damage_ - armor_);
49 hit_points_ -= boss_damage;
50 if ( hit_points_ <= 0 ) {
51 return false;
52 }
53 }
54 }
55};
56
57const array<Item, 5> weapons = {
58 Item("Dagger", 8, 4, 0),
59 Item("Shortsword", 10, 5, 0),
60 Item("Warhammer", 25, 6, 0),
61 Item("Longsword", 40, 7, 0),
62 Item("Greataxe", 74, 8, 0)
63};
64
65const array<Item, 6> armors = {
66 Item("Leather", 13, 0, 1),
67 Item("Chainmail", 31, 0, 2),
68 Item("Splintmail", 53, 0, 3),
69 Item("Bandedmail", 75, 0, 4),
70 Item("Platemail", 102, 0, 5),
71 Item("Noting", 0, 0, 0)
72};
73
74vector<tuple<Item, Item>>
75generate_ring_pairs()
76{
77 const array<Item, 7> rings = {
78 Item("Damage +1", 25, 1, 0),
79 Item("Damage +2", 50, 2, 0),
80 Item("Damage +3", 100, 3, 0),
81 Item("Defense +1", 20, 0, 1),
82 Item("Defense +2", 40, 0, 2),
83 Item("Defense +3", 80, 0, 3),
84 Item("Nothing 0", 0, 0, 0)
85 };
86
87 vector<tuple<Item, Item>> pairs;
88
89 for ( size_t i = 0; i < rings.size(); ++i ) {
90 for ( size_t j = i + 1; j < rings.size(); ++j ) {
91 pairs.emplace_back(rings.at(i), rings.at(j));
92 }
93 }
94
95 pairs.emplace_back(rings.back(), rings.back());
96
97 return pairs;
98}
99
100auto
101split(const string& line, char sep = ' ')
102{
103 vector<string> parts;
104 stringstream input{ line };
105
106 for ( string part; getline(input, part, sep); ) {
107 parts.emplace_back(part);
108 }
109
110 return parts;
111}
112
113Boss
114read_file(string_view filename)
115{
116 fstream input{ filename };
117 Boss boss{};
118
119 for ( string line; getline(input, line); ) {
120 auto parts = split(line);
121
122 if ( parts[0] == "Hit" ) {
123 boss.hit_points_ = stoi(parts[2]);
124 }
125 else if ( parts[0] == "Damage:" ) {
126 boss.damage_ = stoi(parts[1]);
127 }
128 else if ( parts[0] == "Armor:" ) {
129 boss.armor_ = stoi(parts[1]);
130 }
131 }
132 return boss;
133}
134
135void
136part1(const Boss& boss)
137{
138 auto rings = generate_ring_pairs();
139
140 auto min_cost = numeric_limits<int>::max();
141 for ( const auto& weapon: weapons ) {
142 for ( const auto& armor: armors ) {
143 for ( const auto& ring_pair: rings ) {
144 Player player(weapon, armor, ring_pair);
145
146 if (player.would_win_against(boss)) {
147 min_cost = min(min_cost, weapon.cost_ + armor.cost_ + get<0>(ring_pair).cost_ + get<1>(ring_pair).cost_);
148 }
149 }
150 }
151 }
152 cout << min_cost << endl;
153}
154
155void
156part2(const Boss& boss)
157{
158 auto rings = generate_ring_pairs();
159
160 auto max_cost = numeric_limits<int>::min();
161 for ( const auto& weapon: weapons ) {
162 for ( const auto& armor: armors ) {
163 for ( const auto& ring_pair: rings ) {
164 Player player(weapon, armor, ring_pair);
165
166 if (!player.would_win_against(boss)) {
167 max_cost = max(max_cost, weapon.cost_ + armor.cost_ + get<0>(ring_pair).cost_ + get<1>(ring_pair).cost_);
168 }
169 }
170 }
171 }
172 cout << max_cost << endl;
173}
174
175int
176main()
177{
178 auto boss = read_file("data/day21.txt");
179 part1(boss);
180 part2(boss);
181}