bastien.monsarrat 6 سال پیش
والد
کامیت
3b05d5a890
10فایلهای تغییر یافته به همراه385 افزوده شده و 4 حذف شده
  1. 16 4
      Adv2015.sln
  2. 9 0
      D22.1/D22.1.csproj
  3. 33 0
      D22.1/Player.cs
  4. 141 0
      D22.1/Program.cs
  5. 8 0
      D22.1/Properties/launchSettings.json
  6. 128 0
      D22.1/Spell.cs
  7. 2 0
      D22.1/input.txt
  8. 13 0
      D22.2/D22.2.csproj
  9. 27 0
      D22.2/Program.cs
  10. 8 0
      D22.2/Properties/launchSettings.json

+ 16 - 4
Adv2015.sln

@@ -71,13 +71,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D18.2", "D18.2\D18.2.csproj
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D19.1", "D19.1\D19.1.csproj", "{8FDDC40C-F103-4B7D-AF53-A5BAC95B3566}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D19.2", "D19.2\D19.2.csproj", "{BE97EB79-038F-445E-9604-C77CA4CEE115}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D19.2", "D19.2\D19.2.csproj", "{BE97EB79-038F-445E-9604-C77CA4CEE115}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D20.1", "D20.1\D20.1.csproj", "{5365CA31-8F39-4B5D-9F42-AD3B7D23CA8D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D20.1", "D20.1\D20.1.csproj", "{5365CA31-8F39-4B5D-9F42-AD3B7D23CA8D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D20.2", "D20.2\D20.2.csproj", "{2303B37A-6752-415A-824C-BCF146EB613D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D20.2", "D20.2\D20.2.csproj", "{2303B37A-6752-415A-824C-BCF146EB613D}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D21", "D21.1\D21.csproj", "{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D21", "D21.1\D21.csproj", "{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "D22.1", "D22.1\D22.1.csproj", "{9A896029-9525-4AA6-8803-F30FE4592D57}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "D22.2", "D22.2\D22.2.csproj", "{63AEC02B-5420-4D45-B48E-BBBEA9F6FA5F}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -237,6 +241,14 @@ Global
 		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{CEA47E9A-0933-4F73-BE0F-F069A9AE6784}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9A896029-9525-4AA6-8803-F30FE4592D57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9A896029-9525-4AA6-8803-F30FE4592D57}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9A896029-9525-4AA6-8803-F30FE4592D57}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9A896029-9525-4AA6-8803-F30FE4592D57}.Release|Any CPU.Build.0 = Release|Any CPU
+		{63AEC02B-5420-4D45-B48E-BBBEA9F6FA5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{63AEC02B-5420-4D45-B48E-BBBEA9F6FA5F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{63AEC02B-5420-4D45-B48E-BBBEA9F6FA5F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{63AEC02B-5420-4D45-B48E-BBBEA9F6FA5F}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 9 - 0
D22.1/D22.1.csproj

@@ -0,0 +1,9 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <RootNamespace>D22._1</RootNamespace>
+  </PropertyGroup>
+
+</Project>

+ 33 - 0
D22.1/Player.cs

@@ -0,0 +1,33 @@
+namespace D21._1
+{
+    public abstract class Player
+    {
+        protected int OrigHitPoints { get; set; }
+        public int HitPoints { get; set; }
+        public int Damage { get; set; }
+        public int Armor { get; set; }
+
+        public void Heal() => HitPoints = OrigHitPoints;
+    }
+
+    public class Heroe : Player
+    {
+        public Heroe()
+        {
+            HitPoints = 50;
+            OrigHitPoints = 50;
+            Mana = 500;
+        }
+
+        public int Mana { get; set; }
+    }
+
+    public class MonsterBoss : Player
+    {
+        public MonsterBoss(int hp)
+        {
+            HitPoints = hp;
+            OrigHitPoints = hp;
+        }
+    }
+}

+ 141 - 0
D22.1/Program.cs

@@ -0,0 +1,141 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace D21._1
+{
+    public class Program
+    {
+        public enum EnumDifficulty
+        {
+            Normal = 0,
+            Hard = 1
+        }
+
+        public static EnumDifficulty Difficulty { get; set; }
+
+        static bool Attack(MonsterBoss boss, SpellSequence spellBook)
+        {
+            var heroe = new Heroe();
+            boss.Heal();
+
+            var activeEffects = new Queue<(Spell, int)>();
+            var spellSequence = spellBook;
+
+            while (heroe.HitPoints > 0 && boss.HitPoints > 0 && spellSequence != null)
+            {
+                HeroeTakesTurn(boss, heroe, activeEffects, spellSequence);
+
+                if (heroe.Mana <= 0 || heroe.HitPoints <= 0 || boss.HitPoints <= 0)
+                    break;
+
+                BossTakesTurn(boss, heroe, activeEffects);
+
+                spellSequence = spellSequence?.NextEntry;
+            }
+
+            return boss.HitPoints <= 0 && heroe.HitPoints > 0;
+        }
+
+        private static void BossTakesTurn(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects)
+        {
+            ResolveActiveEffects(boss, heroe, activeEffects);
+            if (boss.HitPoints <= 0) return;
+
+            var batk = Math.Max(boss.Damage - heroe.Armor, 1);
+            heroe.HitPoints -= batk;
+        }
+
+        public static void HeroeTakesTurn(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects, SpellSequence spellSequence)
+        {
+            heroe.HitPoints -= (int) Difficulty;
+            if (heroe.HitPoints <= 0) return;
+
+            ResolveActiveEffects(boss, heroe, activeEffects);
+            if (boss.HitPoints <= 0) return;
+
+            var spell = spellSequence?.Spell;
+            heroe.Mana -= spell?.Cost ?? 0;
+
+            spell?.ActiveEffect(heroe, boss);
+            if (spell?.EffectDuration.HasValue ?? false)
+                activeEffects.Enqueue((spell, spell.EffectDuration.Value));
+        }
+
+        private static void ResolveActiveEffects(MonsterBoss boss, Heroe heroe, Queue<(Spell, int)> activeEffects)
+        {
+            int active = activeEffects.Count;
+            while (active-- > 0)
+            {
+                (Spell s, int duration) = activeEffects.Dequeue();
+                s.ApplyEffect(heroe, boss);
+                if (--duration != 0) activeEffects.Enqueue((s, duration));
+                else s.WornOutEffect(heroe, boss);
+            }
+        }
+
+        public static void TrySpellSequence(List<Spell> spellBook, MonsterBoss boss, ref int best, int cost = 0, HashSet<SpellSequence> triedSpellSequence = null, SpellSequence spellSequence = null, int depth = 0)
+        {
+            if (depth > 9) return;
+
+            if (triedSpellSequence == null) triedSpellSequence = new HashSet<SpellSequence>();
+            if (triedSpellSequence.Contains(spellSequence) == false)
+            {
+                if (Attack(boss, spellSequence) && cost < best) best = cost;
+
+                triedSpellSequence.Add(spellSequence);
+            }
+
+            foreach (Spell spell in spellBook)
+            {
+                var firstOccurence = spellSequence?.Position(spell) ?? -1;
+                if (spellSequence != null && spell.EffectDuration > 0
+                    && firstOccurence != -1 && firstOccurence < (spell.EffectDuration - 1) / 2)
+                    continue;
+
+                var newSpellSequence = new SpellSequence() { Spell = spell, NextEntry = spellSequence };
+                TrySpellSequence(spellBook, boss, ref best, cost + spell.Cost, triedSpellSequence, newSpellSequence, depth + 1);
+            }
+        }
+
+        static void Main(string[] args)
+        {
+            if (args.Length < 1) throw new ArgumentException();
+            if (File.Exists(args[0]) == false) throw new FileNotFoundException();
+
+            var spellBook = BuildSpellBook();
+
+            MonsterBoss boss = ParseFile(args);
+
+            int best = int.MaxValue;
+            TrySpellSequence(spellBook, boss, ref best);
+
+            Console.WriteLine($"Best spell sequence costs {best} MP");
+        }
+
+        public static MonsterBoss ParseFile(string[] args)
+        {
+            int hp = 0, atk = 0;
+            using (var file = File.OpenText(args[0]))
+            {
+                hp = int.Parse(file.ReadLine().Split(": ")[1]);
+                atk = int.Parse(file.ReadLine().Split(": ")[1]);
+            }
+
+            return new MonsterBoss(hp)
+            {
+                Damage = atk
+            };
+        }
+
+        public static List<Spell> BuildSpellBook() => new List<Spell>
+            {
+                new MagicMissile(),
+                new Drain(),
+                new Shield(),
+                new Poison(),
+                new Recharge()
+            };
+    }
+}

+ 8 - 0
D22.1/Properties/launchSettings.json

@@ -0,0 +1,8 @@
+{
+  "profiles": {
+    "D22.1": {
+      "commandName": "Project",
+      "commandLineArgs": "\"..\\..\\..\\..\\D22.1\\input.txt\""
+    }
+  }
+}

+ 128 - 0
D22.1/Spell.cs

@@ -0,0 +1,128 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace D21._1
+{
+    public class SpellSequence : IEnumerable<Spell>
+    {
+        public Spell Spell;
+        public SpellSequence NextEntry;
+
+        public int Count() => (NextEntry?.Count() ?? 0) + 1;
+        public override int GetHashCode() => HashCode.Combine(Spell, NextEntry);
+        public bool Contains(Spell i)
+        {
+            var cur = this;
+            while (cur != null)
+            {
+                if (i.Equals(cur.Spell)) return true;
+                cur = cur.NextEntry;
+            }
+            return false;
+        }
+
+        public int Position(Spell i)
+        {
+            var cur = this;
+            int pos = 0;
+            while (cur != null)
+            {
+                if (i.Equals(cur.Spell)) return pos;
+                cur = cur.NextEntry;
+                pos++;
+            }
+            return -1;
+        }
+
+        public IEnumerator<Spell> GetEnumerator()
+        {
+            var cur = this;
+            while (cur != null)
+            {
+                yield return cur.Spell;
+                cur = cur.NextEntry;
+            }
+        }
+
+        IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
+    }
+
+    public abstract class Spell
+    {
+        public int Cost { get; protected set; }
+        public string Name { get; protected set; }
+        public int? EffectDuration { get; protected set;  }
+
+        public override bool Equals(object obj) => obj is Spell item && Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase);
+
+        public override int GetHashCode() => HashCode.Combine(Name);
+
+        public virtual void ActiveEffect(Heroe h, MonsterBoss b) { }
+        public virtual void ApplyEffect(Heroe h, MonsterBoss b) { }
+        public virtual void WornOutEffect(Heroe h, MonsterBoss b) { }
+    }
+
+    public class MagicMissile : Spell
+    {
+        public MagicMissile()
+        {
+            Name = "Magic Missile";
+            Cost = 53;
+        }
+
+        public override void ActiveEffect(Heroe h, MonsterBoss b) => b.HitPoints -= 4;
+    }
+
+    public class Drain : Spell
+    {
+        public Drain()
+        {
+            Name = "Drain";
+            Cost = 73;
+        }
+
+        public override void ActiveEffect(Heroe h, MonsterBoss b)
+        {
+            b.HitPoints -= 2;
+            h.HitPoints += 2;
+        }
+    }
+
+    public class Shield : Spell
+    {
+        public Shield()
+        {
+            Name = "Shield";
+            EffectDuration = 6;
+            Cost = 113;
+        }
+
+        public override void ActiveEffect(Heroe h, MonsterBoss b) => h.Armor += 7;
+        public override void WornOutEffect(Heroe h, MonsterBoss b) => h.Armor -= 7;
+    }
+
+    public class Poison : Spell
+    {
+        public Poison()
+        {
+            Name = "Poison";
+            EffectDuration = 6;
+            Cost = 173;
+        }
+
+        public override void ApplyEffect(Heroe h, MonsterBoss b) => b.HitPoints -= 3;
+    }
+
+    public class Recharge : Spell
+    {
+        public Recharge()
+        {
+            Name = "Recharge";
+            EffectDuration = 5;
+            Cost = 229;
+        }
+
+        public override void ApplyEffect(Heroe h, MonsterBoss b) => h.Mana += 101;
+    }
+}

+ 2 - 0
D22.1/input.txt

@@ -0,0 +1,2 @@
+Hit Points: 55
+Damage: 8

+ 13 - 0
D22.2/D22.2.csproj

@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>netcoreapp2.1</TargetFramework>
+    <RootNamespace>D22._2</RootNamespace>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\D22.1\D22.1.csproj" />
+  </ItemGroup>
+
+</Project>

+ 27 - 0
D22.2/Program.cs

@@ -0,0 +1,27 @@
+using D21._1;
+using System;
+using System.IO;
+
+namespace D22._2
+{
+    class Program : D21._1.Program
+    {
+        static void Main(string[] args)
+        {
+
+            if (args.Length < 1) throw new ArgumentException();
+            if (File.Exists(args[0]) == false) throw new FileNotFoundException();
+
+            var spellBook = BuildSpellBook();
+
+            MonsterBoss boss = ParseFile(args);
+
+            Difficulty = EnumDifficulty.Hard;
+
+            int best = int.MaxValue;
+            TrySpellSequence(spellBook, boss, ref best);
+
+            Console.WriteLine($"Best spell sequence costs {best} MP");
+        }
+    }
+}

+ 8 - 0
D22.2/Properties/launchSettings.json

@@ -0,0 +1,8 @@
+{
+  "profiles": {
+    "D22.2": {
+      "commandName": "Project",
+      "commandLineArgs": "\"..\\..\\..\\..\\D22.1\\input.txt\""
+    }
+  }
+}