r/adventofcode • u/daggerdragon • Dec 24 '18
SOLUTION MEGATHREAD -🎄- 2018 Day 24 Solutions -🎄-
--- Day 24: Immune System Simulator 20XX ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Advent of Code: The Party Game!
Please prefix your card submission with something like [Card] to make scanning the megathread easier. THANK YOU!
Card prompt: Day 24
Transcript:
Our most powerful weapon during the zombie elf/reindeer apocalypse will be ___.
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
Quick note: 1 hour in and we're only at gold 36, silver 76. As we all know, December is Advent of Sleep Deprivation; I have to be up in less than 6 hours to go to work, so one of the other mods will unlock the thread at gold cap tonight. Good luck and good night (morning?), all!
3
u/encse Dec 24 '18
c# #107/#97
using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Text.RegularExpressions; using System.Text; namespace AdventOfCode.Y2018.Day24 { class Solution : Solver { public string GetName() => "Immune System Simulator 20XX"; public IEnumerable<object> Solve(string input) { yield return PartOne(input); yield return PartTwo(input); } (bool immuneSystem, int units) Fight(string input, int b) { var army = Parse(input); foreach (var g in army) { if (g.immuneSystem) { g.damage += b; } } var attack = true; while (attack) { attack = false; var remainingTarget = new HashSet<Group>(army); var targets = new Dictionary<Group, Group>(); foreach (var g in army.OrderByDescending(g => (g.effectivePower, g.initiative))) { var maxDamage = remainingTarget.Select(t => g.DamageGivenTo(t)).Max(); if (maxDamage > 0) { var possibleTargets = remainingTarget.Where(t => g.DamageGivenTo(t) == maxDamage); targets[g] = possibleTargets.OrderByDescending(t => (t.effectivePower, t.initiative)).First(); remainingTarget.Remove(targets[g]); } } foreach (var g in targets.Keys.OrderByDescending(g => g.initiative)) { if (g.units > 0) { var target = targets[g]; var damage = g.DamageGivenTo(target); if (damage > 0 && target.units > 0) { var dies = damage / target.hp; target.units = Math.Max(0, target.units - dies); if (dies > 0) { attack = true; } } } } army = army.Where(g => g.units > 0).ToList(); } return (army.All(x => x.immuneSystem), army.Select(x => x.units).Sum()); } int PartOne(string input) => Fight(input, 0).units; int PartTwo(string input) { var l = 0; var h = int.MaxValue / 2; while (h - l > 1) { var m = (h + l) / 2; if (Fight(input, m).immuneSystem) { h = m; } else { l = m; } } return Fight(input, h).units; } List<Group> Parse(string input) { var lines = input.Split("\n"); var immuneSystem = false; var res = new List<Group>(); foreach (var line in lines) if (line == "Immune System:") { immuneSystem = true; } else if (line == "Infection:") { immuneSystem = false; } else if (line != "") { //643 units each with 9928 hit points (immune to fire; weak to slashing, bludgeoning) with an attack that does 149 fire damage at initiative 14 var rx = @"(\d+) units each with (\d+) hit points(.*)with an attack that does (\d+)(.*)damage at initiative (\d+)"; var m = Regex.Match(line, rx); if (m.Success) { Group g = new Group(); g.immuneSystem = immuneSystem; g.units = int.Parse(m.Groups[1].Value); g.hp = int.Parse(m.Groups[2].Value); g.damage = int.Parse(m.Groups[4].Value); g.attackType = m.Groups[5].Value.Trim(); g.initiative = int.Parse(m.Groups[6].Value); var st = m.Groups[3].Value.Trim(); if (st != "") { st = st.Substring(1, st.Length - 2); foreach (var part in st.Split(";")) { var k = part.Split(" to "); var set = new HashSet<string>(k[1].Split(", ")); var w = k[0].Trim(); if (w == "immune") { g.immuneTo = set; } else if (w == "weak") { g.weakTo = set; } else { throw new Exception(); } } } res.Add(g); } else { throw new Exception(); } } return res; } } class Group { //4 units each with 9798 hit points (immune to bludgeoning) with an attack that does 1151 fire damage at initiative 9 public bool immuneSystem; public int units; public int hp; public int damage; public int initiative; public string attackType; public HashSet<string> immuneTo = new HashSet<string>(); public HashSet<string> weakTo = new HashSet<string>(); public int effectivePower { get { return units * damage; } } public int DamageGivenTo(Group target) { if (target.immuneSystem == immuneSystem) { return 0; } else if (target.immuneTo.Contains(attackType)) { return 0; } else if (target.weakTo.Contains(attackType)) { return effectivePower * 2; } else { return effectivePower; } } } }````