my advent of code solutions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 83 lines 3.2 kB view raw
1namespace Solutions._2015; 2 3/// <summary> 4/// Day 21: <a href="https://adventofcode.com/2015/day/21"/> 5/// </summary> 6public sealed class Day21RpgSimulator20Xx() : Day(2015, 21, "RPG Simulator 20XX") 7{ 8 private const int PlayerHp = 100; 9 private IEnumerable<Combination>? _combinations; 10 private Dictionary<string, int>? _boss; 11 12 private record Combination(Item Weapon, Item Armor, Item Ring1, Item Ring2) 13 { 14 public int TotalDamage => Weapon.Damage + Ring1.Damage + Ring2.Damage; 15 public int TotalArmor => Armor.Armor + Ring1.Armor + Ring2.Armor; 16 public int TotalCost => Weapon.Cost + Armor.Cost + Ring1.Cost + Ring2.Cost; 17 } 18 19 private record Item(string Name, int Cost = 0, int Damage = 0, int Armor = 0); 20 21 public override void ProcessInput() 22 { 23 _boss = Input.ToDictionary(k => k.Split(": ")[0], v => int.Parse(v.Split(": ")[1])); 24 25 var weapons = new Item[] 26 { 27 new(Name: "Dagger", Cost: 8, Damage: 4), 28 new(Name: "Shortsword", Cost: 10, Damage: 5), 29 new(Name: "Warhammer", Cost: 25, Damage: 6), 30 new(Name: "Longsword", Cost: 40, Damage: 7), 31 new(Name: "Greataxe", Cost: 74, Damage: 8), 32 }; 33 34 var armor = new Item[] 35 { 36 new(Name: "No armor", Cost: 0, Armor: 0), 37 new(Name: "Leather", Cost: 13, Armor: 1), 38 new(Name: "Chainmail", Cost: 31, Armor: 2), 39 new(Name: "Splintmail", Cost: 53, Armor: 3), 40 new(Name: "Bandedmail", Cost: 75, Armor: 4), 41 new(Name: "Platemail", Cost: 102, Armor: 5), 42 }; 43 44 var rings = new Item[] 45 { 46 new(Name: "No ring", Cost: 0, Damage: 0, Armor: 0), 47 new(Name: "Damage +1", Cost: 25, Damage: 1, Armor: 0), 48 new(Name: "Damage +2", Cost: 50, Damage: 2, Armor: 0), 49 new(Name: "Damage +3", Cost: 100, Damage: 3, Armor: 0), 50 new(Name: "Defense +1", Cost: 20, Damage: 0, Armor: 1), 51 new(Name: "Defense +2", Cost: 40, Damage: 0, Armor: 2), 52 new(Name: "Defense +3", Cost: 80, Damage: 0, Armor: 3), 53 }; 54 55 _combinations = 56 from w in weapons 57 from a in armor 58 from ring1 in rings 59 from ring2 in rings 60 where ring1.Cost == 0 || ring1.Cost != ring2.Cost 61 select new Combination(w, a, ring1, ring2); 62 } 63 64 private bool StillAlive(Combination combination) 65 { 66 var myDamage = Math.Max(combination.TotalDamage - _boss!["Armor"], 1); 67 var bossDamagePerTurn = Math.Max(_boss["Damage"] - combination.TotalArmor, 1); 68 69 var turnsToLose = PlayerHp / bossDamagePerTurn; 70 if (PlayerHp % bossDamagePerTurn > 0) turnsToLose++; 71 72 var turnsToKillBoss = _boss["Hit Points"] / myDamage; 73 if (_boss["Hit Points"] % myDamage > 0) turnsToKillBoss++; 74 75 return turnsToLose >= turnsToKillBoss; 76 } 77 78 public override object Part1() => 79 _combinations!.Where(StillAlive).Min(c => c.TotalCost); 80 81 public override object Part2() => 82 _combinations!.Where(c => !StillAlive(c)).Max(c => c.TotalCost); 83}