Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 501e562

Browse files
Solved Day 21 part 2 (2015) - RPG Simulator 20XX
1 parent 0ab3e7c commit 501e562

File tree

1 file changed

+196
-17
lines changed
  • src/main/java/com/sbaars/adventofcode/year15/days

1 file changed

+196
-17
lines changed
Lines changed: 196 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,202 @@
11
package com.sbaars.adventofcode.year15.days;
22

33
import com.sbaars.adventofcode.year15.Day2015;
4+
import java.util.*;
5+
import java.util.stream.Collectors;
46

57
public class Day21 extends Day2015 {
6-
public Day21() {
7-
super(21);
8-
}
9-
10-
public static void main(String[] args) {
11-
new Day21().printParts();
12-
}
13-
14-
@Override
15-
public Object part1() {
16-
return "";
17-
}
18-
19-
@Override
20-
public Object part2() {
21-
return "";
22-
}
8+
private static final int PLAYER_HP = 100;
9+
private static final List<Item> WEAPONS = Arrays.asList(
10+
new Item("Dagger", 8, 4, 0),
11+
new Item("Shortsword", 10, 5, 0),
12+
new Item("Warhammer", 25, 6, 0),
13+
new Item("Longsword", 40, 7, 0),
14+
new Item("Greataxe", 74, 8, 0)
15+
);
16+
17+
private static final List<Item> ARMOR = Arrays.asList(
18+
new Item("Leather", 13, 0, 1),
19+
new Item("Chainmail", 31, 0, 2),
20+
new Item("Splintmail", 53, 0, 3),
21+
new Item("Bandedmail", 75, 0, 4),
22+
new Item("Platemail", 102, 0, 5)
23+
);
24+
25+
private static final List<Item> RINGS = Arrays.asList(
26+
new Item("Damage +1", 25, 1, 0),
27+
new Item("Damage +2", 50, 2, 0),
28+
new Item("Damage +3", 100, 3, 0),
29+
new Item("Defense +1", 20, 0, 1),
30+
new Item("Defense +2", 40, 0, 2),
31+
new Item("Defense +3", 80, 0, 3)
32+
);
33+
34+
private record Item(String name, int cost, int damage, int armor) {}
35+
private record Character(int hp, int damage, int armor) {}
36+
private record Equipment(Item weapon, Item armor, Item ring1, Item ring2) {
37+
public int getTotalCost() {
38+
return weapon.cost() +
39+
(armor != null ? armor.cost() : 0) +
40+
(ring1 != null ? ring1.cost() : 0) +
41+
(ring2 != null ? ring2.cost() : 0);
42+
}
43+
44+
public int getTotalDamage() {
45+
return weapon.damage() +
46+
(armor != null ? armor.damage() : 0) +
47+
(ring1 != null ? ring1.damage() : 0) +
48+
(ring2 != null ? ring2.damage() : 0);
49+
}
50+
51+
public int getTotalArmor() {
52+
return (armor != null ? armor.armor() : 0) +
53+
(ring1 != null ? ring1.armor() : 0) +
54+
(ring2 != null ? ring2.armor() : 0);
55+
}
56+
}
57+
58+
public Day21() {
59+
super(21);
60+
}
61+
62+
public static void main(String[] args) {
63+
Day21 day = new Day21();
64+
day.printParts();
65+
new com.sbaars.adventofcode.network.Submit().submit(day.part2(), 2015, 21, 2);
66+
}
67+
68+
@Override
69+
public Object part1() {
70+
Character boss = parseBoss();
71+
return findMinGoldToWin(boss);
72+
}
73+
74+
@Override
75+
public Object part2() {
76+
Character boss = parseBoss();
77+
return findMaxGoldToLose(boss);
78+
}
79+
80+
private Character parseBoss() {
81+
List<String> lines = dayStream().collect(Collectors.toList());
82+
int hp = Integer.parseInt(lines.get(0).split(": ")[1]);
83+
int damage = Integer.parseInt(lines.get(1).split(": ")[1]);
84+
int armor = Integer.parseInt(lines.get(2).split(": ")[1]);
85+
return new Character(hp, damage, armor);
86+
}
87+
88+
private int findMinGoldToWin(Character boss) {
89+
int minGold = Integer.MAX_VALUE;
90+
91+
// Try all possible equipment combinations
92+
for (Item weapon : WEAPONS) {
93+
// Try with no armor and no rings
94+
minGold = Math.min(minGold, tryEquipment(weapon, null, null, null, boss));
95+
96+
// Try with armor but no rings
97+
for (Item armor : ARMOR) {
98+
minGold = Math.min(minGold, tryEquipment(weapon, armor, null, null, boss));
99+
}
100+
101+
// Try with one ring, no armor
102+
for (Item ring1 : RINGS) {
103+
minGold = Math.min(minGold, tryEquipment(weapon, null, ring1, null, boss));
104+
}
105+
106+
// Try with two rings, no armor
107+
for (int i = 0; i < RINGS.size(); i++) {
108+
for (int j = i + 1; j < RINGS.size(); j++) {
109+
minGold = Math.min(minGold, tryEquipment(weapon, null, RINGS.get(i), RINGS.get(j), boss));
110+
}
111+
}
112+
113+
// Try with armor and one ring
114+
for (Item armor : ARMOR) {
115+
for (Item ring1 : RINGS) {
116+
minGold = Math.min(minGold, tryEquipment(weapon, armor, ring1, null, boss));
117+
}
118+
}
119+
120+
// Try with armor and two rings
121+
for (Item armor : ARMOR) {
122+
for (int i = 0; i < RINGS.size(); i++) {
123+
for (int j = i + 1; j < RINGS.size(); j++) {
124+
minGold = Math.min(minGold, tryEquipment(weapon, armor, RINGS.get(i), RINGS.get(j), boss));
125+
}
126+
}
127+
}
128+
}
129+
130+
return minGold;
131+
}
132+
133+
private int tryEquipment(Item weapon, Item armor, Item ring1, Item ring2, Character boss) {
134+
Equipment equipment = new Equipment(weapon, armor, ring1, ring2);
135+
Character player = new Character(PLAYER_HP, equipment.getTotalDamage(), equipment.getTotalArmor());
136+
137+
return simulateFight(player, boss) ? equipment.getTotalCost() : Integer.MAX_VALUE;
138+
}
139+
140+
private boolean simulateFight(Character player, Character boss) {
141+
int playerDamagePerTurn = Math.max(1, player.damage() - boss.armor());
142+
int bossDamagePerTurn = Math.max(1, boss.damage() - player.armor());
143+
144+
// Player goes first, so they need to kill the boss in equal or fewer turns
145+
int turnsToKillBoss = (boss.hp() + playerDamagePerTurn - 1) / playerDamagePerTurn;
146+
int turnsToKillPlayer = (player.hp() + bossDamagePerTurn - 1) / bossDamagePerTurn;
147+
148+
return turnsToKillBoss <= turnsToKillPlayer;
149+
}
150+
151+
private int findMaxGoldToLose(Character boss) {
152+
int maxGold = 0;
153+
154+
// Try all possible equipment combinations
155+
for (Item weapon : WEAPONS) {
156+
// Try with no armor and no rings
157+
maxGold = Math.max(maxGold, tryEquipmentToLose(weapon, null, null, null, boss));
158+
159+
// Try with armor but no rings
160+
for (Item armor : ARMOR) {
161+
maxGold = Math.max(maxGold, tryEquipmentToLose(weapon, armor, null, null, boss));
162+
}
163+
164+
// Try with one ring, no armor
165+
for (Item ring1 : RINGS) {
166+
maxGold = Math.max(maxGold, tryEquipmentToLose(weapon, null, ring1, null, boss));
167+
}
168+
169+
// Try with two rings, no armor
170+
for (int i = 0; i < RINGS.size(); i++) {
171+
for (int j = i + 1; j < RINGS.size(); j++) {
172+
maxGold = Math.max(maxGold, tryEquipmentToLose(weapon, null, RINGS.get(i), RINGS.get(j), boss));
173+
}
174+
}
175+
176+
// Try with armor and one ring
177+
for (Item armor : ARMOR) {
178+
for (Item ring1 : RINGS) {
179+
maxGold = Math.max(maxGold, tryEquipmentToLose(weapon, armor, ring1, null, boss));
180+
}
181+
}
182+
183+
// Try with armor and two rings
184+
for (Item armor : ARMOR) {
185+
for (int i = 0; i < RINGS.size(); i++) {
186+
for (int j = i + 1; j < RINGS.size(); j++) {
187+
maxGold = Math.max(maxGold, tryEquipmentToLose(weapon, armor, RINGS.get(i), RINGS.get(j), boss));
188+
}
189+
}
190+
}
191+
}
192+
193+
return maxGold;
194+
}
195+
196+
private int tryEquipmentToLose(Item weapon, Item armor, Item ring1, Item ring2, Character boss) {
197+
Equipment equipment = new Equipment(weapon, armor, ring1, ring2);
198+
Character player = new Character(PLAYER_HP, equipment.getTotalDamage(), equipment.getTotalArmor());
199+
200+
return simulateFight(player, boss) ? 0 : equipment.getTotalCost();
201+
}
23202
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /