-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
338 lines (286 loc) · 8.92 KB
/
main.cpp
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
/*
L'entrée représente les statistiques d'un boss d'un RPG
Dans ce RPG, un marchand propose la vente d'objets avec les caractéristiques suivantes :
Armes : Coût Dommages Armure
Dagger 8 4 0
Shortsword 10 5 0
Warhammer 25 6 0
Longsword 40 7 0
Greataxe 74 8 0
Armures: Coût Dommages Armure
Leather 13 0 1
Chainmail 31 0 2
Splintmail 53 0 3
Bandedmail 75 0 4
Platemail 102 0 5
Anneaux: Coût Dommages Armure
Damage +1 25 1 0
Damage +2 50 2 0
Damage +3 100 3 0
Defense +1 20 0 1
Defense +2 40 0 2
Defense +3 80 0 3
Le joueur doit respecter les règles suivantes pour se préparer au combat contre le boss :
- Il est obligé d'avoir une arme, et seulement une.
- Il peut choisir au maximum une armure, mais elle n'est pas obligatoire.
- Il peut choisir entre 0, 1 ou 2 anneaux, cependant, il ne peut pas prendre deux fois le même.
L'objectif de la partie 1 est de trouver l'équipement le moins cher qui lui permettra de battre le boss. La réponse
attendue est le coût de l'équipement.
L'objectif de la partie 2 est de trouver l'équipement le plus cher qui ne permet pas de battre le boss. La réponse
attendue est le coût de l'équipement.
*/
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <Utils/MeasureExecutionTime.cpp>
#include <Utils/SplitString.cpp>
using namespace std;
class Item
{
public:
string name; // Nom de l'objet
int cost; // Coût de l'objet
int damage; // Dommages infligés par l'objet
int armor; // Valeur d'armure fournie par l'objet
Item(string name, int cost, int damage, int armor)
{
this->name = name;
this->cost = cost;
this->damage = damage;
this->armor = armor;
}
};
class Entity
{
public:
int HP; // Points de vie
int damage; // Valeur de Dommages
int armor; // Valeur d'armure
vector<Item> items; // Liste d'objets équipés
int costItem = 0; // Coût total des objets équipés
// Constructeur par défaut
Entity() = default;
// Constructeur avec paramètres
Entity(int HP, int damage, int armor)
{
this->HP = HP;
this->damage = damage;
this->armor = armor;
}
// Méthode pour ajouter un objet à l'inventaire
void addItem(Item item)
{
items.push_back(item);
damage += item.damage;
armor += item.armor;
costItem += item.cost;
}
// Opérateur d'affectation
Entity &operator=(const Entity &other)
{
if (this != &other)
{
HP = other.HP;
damage = other.damage;
armor = other.armor;
costItem = other.costItem;
items.clear();
for (const auto &item : other.items)
{
items.push_back(item);
}
}
return *this;
}
// Opérateur de comparaison pour la fonction de tri
bool operator<(const Entity &other) const
{
return costItem < other.costItem;
}
};
// Définition des vecteurs constants d'objets
const vector<Item> WEAPONS = {{"Dagger", 8, 4, 0},
{"Shortsword", 10, 5, 0},
{"Warhammer", 25, 6, 0},
{"Longsword", 40, 7, 0},
{"Greataxe", 74, 8, 0}};
const vector<Item> ARMOR = {{"Leather", 13, 0, 1},
{"Chainmail", 31, 0, 2},
{"Splintmail", 53, 0, 3},
{"Bandedmail", 75, 0, 4},
{"Platemail", 102, 0, 5}};
const vector<Item> RINGS = {{"Damage +1", 25, 1, 0}, {"Damage +2", 50, 2, 0}, {"Damage +3", 100, 3, 0},
{"Defense +1", 20, 0, 1}, {"Defense +2", 40, 0, 2}, {"Defense +3", 80, 0, 3}};
Entity boss; // Instance de l'entité du boss
vector<Entity> AllPlayers; // Vecteur contenant les différentes configurations d'équipement des joueurs
// Fonction pour choisir les anneaux pour une entité donnée
vector<Entity> chooseRings(Entity player)
{
vector<Entity> players = {player};
// Ajout d'un seul anneau
for (Item ring : RINGS)
{
Entity p = player;
p.addItem(ring);
players.push_back(p);
}
// Ajout de deux anneaux différents
for (int i = 0; i < RINGS.size(); i++)
{
for (int j = i + 1; j < RINGS.size(); j++)
{
Entity p = player;
p.addItem(RINGS[i]);
p.addItem(RINGS[j]);
players.push_back(p);
}
}
return players;
}
// Fonction pour choisir l'armure pour une entité donnée
vector<Entity> chooseArmor(Entity player)
{
vector<Entity> players;
// Essayer chaque pièce d'armure séparément
for (Item armor : ARMOR)
{
Entity p = player;
p.addItem(armor);
// Combiner avec les choix d'anneaux
vector<Entity> _players = chooseRings(p);
for (Entity _p : _players)
{
players.push_back(_p);
}
}
// Aucune armure choisie
Entity p = player;
vector<Entity> _players = chooseRings(p);
for (Entity _p : _players)
{
players.push_back(_p);
}
return players;
}
// Fonction pour choisir l'arme
void chooseWaypon()
{
for (Item weapon : WEAPONS)
{
Entity p(100, 0, 0); // Initialiser un joueur avec 100 points de vie et aucun dommage/armure
p.addItem(weapon);
// Combiner avec les choix d'armure et d'anneaux
vector<Entity> _players = chooseArmor(p);
for (Entity _p : _players)
{
AllPlayers.push_back(_p);
}
}
}
int parseInput()
{
MEASURE_FUNCTION_EXECUTION_TIME
string filename = "input.txt";
ifstream file(filename);
if (!file.is_open())
{
cerr << "Erreur : impossible d'ouvrir le fichier " << filename;
return 1;
}
string line;
while (getline(file, line))
{
vector<string> splitedLine = splitString(line, ": ");
if (splitedLine[0] == "Hit Points")
{
boss.HP = stoi(splitedLine[1]);
}
else if (splitedLine[0] == "Damage")
{
boss.damage = stoi(splitedLine[1]);
}
else if (splitedLine[0] == "Armor")
{
boss.armor = stoi(splitedLine[1]);
}
}
file.close();
chooseWaypon();
return 0;
}
// Cette fonction simule un combat entre le joueur et le boss, en prenant en compte les points de vie, les dégâts et
// l'armure de chacun.
bool simu(Entity &player)
{
int bossHP = boss.HP;
int playerHP = player.HP;
// Calcul des dégâts infligés par le joueur et le boss en tenant compte de l'armure
int playerDamage = player.damage - boss.armor;
int bossDamage = boss.damage - player.armor;
playerDamage = playerDamage <= 0 ? 1 : playerDamage;
bossDamage = bossDamage <= 0 ? 1 : bossDamage;
while (true)
{
bossHP -= playerDamage;
playerHP -= bossDamage;
// Vérification des points de vie restants
if (bossHP <= 0)
{
return true; // Le joueur a gagné
}
else if (playerHP <= 0)
{
return false; // Le joueur a perdu
}
}
}
// Cette fonction traite la première partie du problème en cherchant la configuration d'équipement la moins chère
// permettant au joueur de battre le boss.
int processPart1()
{
MEASURE_FUNCTION_EXECUTION_TIME
// Trie les configurations d'équipement par coût croissant
sort(AllPlayers.begin(), AllPlayers.end());
// Parcourt les configurations d'équipement pour trouver celle qui permet de battre le boss
for (Entity p : AllPlayers)
{
if (simu(p))
{
return p.costItem;
}
}
// Aucune configuration n'a permis de battre le boss
return -1;
}
// Cette fonction traite la deuxième partie du problème en cherchant la configuration d'équipement la plus chère qui ne
// permet pas au joueur de battre le boss.
int processPart2()
{
MEASURE_FUNCTION_EXECUTION_TIME
// Inverse l'ordre des configurations d'équipement (du plus cher au moins cher)
reverse(AllPlayers.begin(), AllPlayers.end());
// Parcourt les configurations d'équipement pour trouver celle qui perd contre le boss
for (Entity p : AllPlayers)
{
if (!simu(p))
{
return p.costItem;
}
}
// Toutes les configurations permettent de battre le boss
return -1;
}
int main()
{
if (parseInput() == 1)
{
return 1;
}
int part1 = processPart1();
int part2 = processPart2();
cout << "\nPart1: " << part1;
cout << "\nPart2: " << part2;
return 0;
}