Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package Advent2018;
- import util.AdventOfCode;
- import util.FileIO;
- import java.util.*;
- import java.util.concurrent.atomic.AtomicInteger;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- import java.util.stream.Collectors;
- import static java.util.Comparator.*;
- public class Day24 extends AdventOfCode {
- List<Group> groups;
- List<Group> original;
- enum AttackType {
- COLD, FIRE, RADIATION, BLUDGEONING, SLASHING
- }
- class Target {
- int damage;
- Group group;
- Target(Group group) {
- //this.damage = damage;
- this.group = group;
- }
- Target setDamage(int damage) {
- this.damage = damage;
- return this;
- }
- int getDamage() { return damage;}
- int getPower() { return group.effectivePower(); }
- int getInitiative() { return group.initiative; }
- }
- class Group {
- boolean immuneSystem;
- boolean alive = true;
- boolean chosen;
- int units;
- int hitPoints;
- int attackDamage;
- AttackType type;
- int initiative;
- List<AttackType> weak = new ArrayList<>();
- List<AttackType> immune = new ArrayList<>();
- Group cloneGroup() {
- Group g = new Group();
- g.immuneSystem = this.immuneSystem;
- g.units = this.units;
- g.hitPoints = this.hitPoints;
- g.attackDamage = attackDamage;
- g.type = this.type;
- g.initiative = this.initiative;
- g.weak = this.weak;
- g.immune = this.immune;
- return g;
- }
- int getInitiative() { return initiative; }
- int effectivePower() {
- return units * attackDamage;
- }
- boolean isWeakTo(Group other) {
- return other.weak.contains(this.type);
- }
- boolean isImmuneTo(Group other) {
- return other.immune.contains(this.type);
- }
- int damageVs(Group target) {
- if (isImmuneTo(target)) return 0;
- return effectivePower() + (isWeakTo(target) ? effectivePower() : 0);
- }
- void takeDamage(int damage) {
- units -= damage / hitPoints;
- if (units <= 0) alive = false;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Group group = (Group) o;
- if (immuneSystem != group.immuneSystem) return false;
- if (alive != group.alive) return false;
- if (chosen != group.chosen) return false;
- if (units != group.units) return false;
- if (hitPoints != group.hitPoints) return false;
- if (attackDamage != group.attackDamage) return false;
- if (initiative != group.initiative) return false;
- if (type != group.type) return false;
- if (weak != null ? !weak.equals(group.weak) : group.weak != null) return false;
- return immune != null ? immune.equals(group.immune) : group.immune == null;
- }
- @Override
- public int hashCode() {
- int result = (immuneSystem ? 1 : 0);
- result = 31 * result + (alive ? 1 : 0);
- result = 31 * result + (chosen ? 1 : 0);
- result = 31 * result + units;
- result = 31 * result + hitPoints;
- result = 31 * result + attackDamage;
- result = 31 * result + (type != null ? type.hashCode() : 0);
- result = 31 * result + initiative;
- result = 31 * result + (weak != null ? weak.hashCode() : 0);
- result = 31 * result + (immune != null ? immune.hashCode() : 0);
- return result;
- }
- @Override
- public String toString() {
- return "Group " + initiative + "{" +
- "immuneSystem=" + immuneSystem +
- ", units=" + units +
- ", hitPoints=" + hitPoints +
- '}';
- }
- }
- void resetGroups() {
- groups = new ArrayList<>();
- for (int i = 0; i < original.size(); i++) {
- groups.add(original.get(i).cloneGroup());
- }
- }
- public Day24(List<String> input) {
- super(input);
- }
- void fight() {
- // target selection
- groups.forEach(x -> x.chosen = false);
- Map<Group, Target> opponents = new HashMap<>();
- List<Group> avail = groups.stream()
- .filter(x -> x.alive)
- .sorted(comparing(Group::effectivePower)
- .thenComparing(Group::getInitiative)
- .reversed())
- .collect(Collectors.toList());
- for (Group each : avail) {
- List<Target> targets = avail.stream()
- .filter(x -> x.immuneSystem != each.immuneSystem)
- .filter(x -> !x.chosen)
- .filter(x -> !each.isImmuneTo(x))
- .map(Target::new)
- .map(x -> x.setDamage(each.damageVs(x.group)))
- .sorted(comparing(Target::getDamage)
- .thenComparing(Target::getPower)
- .thenComparing(Target::getInitiative)
- .reversed())
- .collect(Collectors.toList());
- if (targets.size() > 0) {
- Target t = targets.get(0);
- opponents.put(each, t);
- t.group.chosen = true;
- }
- }
- // attack phase
- opponents.entrySet().stream()
- .sorted(Map.Entry.comparingByKey(comparing(Group::getInitiative).reversed()))
- .forEach(x -> {
- //System.out.println(x.getKey() + " attacks");
- //System.out.println(x.getValue().group);
- x.getValue().group.takeDamage(x.getKey().damageVs(x.getValue().group));
- //System.out.println(x.getValue().group);
- });
- //System.out.println("end fight");
- }
- boolean fightOver() {
- return groups.stream().filter(x -> x.immuneSystem && x.alive).count() == 0 ||
- groups.stream().filter(x -> !x.immuneSystem && x.alive).count() == 0;
- }
- @Override
- public Object part1() {
- resetGroups();
- while (!fightOver()) {
- fight();
- }
- return groups.stream().filter(x -> x.alive).mapToInt(x -> x.units).sum() - 1;
- }
- @Override
- public Object part2() {
- AtomicInteger boost = new AtomicInteger(52);
- int immuneScore = 0;
- while (immuneScore == 0) {
- resetGroups();
- groups.stream().filter(x -> x.immuneSystem).forEach(x -> x.attackDamage += boost.get());
- while (!fightOver()) {
- fight();
- }
- boost.incrementAndGet();
- immuneScore = groups.stream()
- .filter(x -> x.immuneSystem)
- .filter(x -> x.alive)
- .mapToInt(x -> x.units).sum();
- }
- return immuneScore;
- }
- @Override
- public void parse() {
- //input = FileIO.getFileAsList("puzzle_input/test24.txt");
- original = new ArrayList<>();
- Pattern p = Pattern.compile("(\\d+) units each with (\\d+) hit points \\(?.*\\)? ?with an attack that does (\\d+) (\\w+) damage at initiative (\\d+)");
- boolean immune = true;
- for (String line : input) {
- if (line.equals("Immune System:")) continue;
- if (line.isEmpty()) continue;
- if (line.equals("Infection:")) {
- immune = false;
- continue;
- }
- Group g = new Group();
- Matcher m = p.matcher(line);
- if (m.find()) {
- g.immuneSystem = immune;
- g.units = Integer.parseInt(m.group(1));
- g.hitPoints = Integer.parseInt(m.group(2));
- g.attackDamage = Integer.parseInt(m.group(3));
- g.type = AttackType.valueOf(m.group(4).toUpperCase());
- g.initiative = Integer.parseInt(m.group(5));
- }
- if (line.contains("(")) {
- String[] special = line.substring(line.indexOf('(') + 1, line.lastIndexOf(')')).split("; ");
- if (special.length > 0) {
- for (String each : special) {
- each = each.replaceAll(",", "");
- String[] split = each.split(" ");
- if (split[0].equals("immune")) {
- for (int i = 2; i < split.length; i++) {
- g.immune.add(AttackType.valueOf(split[i].toUpperCase()));
- }
- } else {
- if (split[0].equals("weak")) {
- for (int i = 2; i < split.length; i++) {
- g.weak.add(AttackType.valueOf(split[i].toUpperCase()));
- }
- }
- }
- }
- }
- }
- original.add(g);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement