Part 1
In this puzzle we have descriptions of two different armies for an immune system and an infection. Each army consists of multiple groups of units. Each unit has a number of units, an attack value, hit points, inititiave, attack type, weaknesses and immunities. Each round the units attack each other in an order based on their inititiave. During an attack, each unit selects an individual target of the opposing side with the largest potential damage. Each unit can only be chosen once as a target. Whenever a unit is hit by an attack it has a weakness to, it gets double damage. When hit by an attack which it is immune to, it gets no damage. After target select each group deals damage and only whole units of the groups are removed based on the damage received. We should simulate a fight until there is only one side left and count how many units the winning side has left.
The implementation of this was straight forward. We used a class for the units to keep data of a group close together. For the target selection we keep a dictionary of which group already targeted which other group. For ranking the targets of a new group, we only look at the groups not already targeted. The weaknesses, immunities and attack types are saved as list of strings and we just check if the attack type is in the list of weaknesses / immunities. Finally we check after each round if just one side is left and count the remaining units if so.
Part 2
In part 2, we introduce a boost the immune system. The boost increases the attack values of all units of the immune system side for the complete duration of the fight. We should find the lowest boost which results in the immune system winning and count the remaining units left after its win.
We reused the code for part 1 and also returned the winning side after the simulation. We start increasing the boost starting with 1 and simulate a new fight. As soon as the immune system side wins, we can count the remaining units for the answer.