summary refs log tree commit diff stats
path: root/day22.fsx
diff options
context:
space:
mode:
authorBrian Chu <brianmchu42@gmail.com>2021-12-30 15:11:21 -0800
committerBrian Chu <brianmchu42@gmail.com>2021-12-30 15:11:21 -0800
commite7085453864431ace3ad8f3123b259ed0829ae74 (patch)
tree2ef1fbb0e9d02fc934b5e09d96dd187f3e371ea6 /day22.fsx
downloadAdventOfCode2015-main.tar.gz
all solutions for 2015 main
Diffstat (limited to 'day22.fsx')
-rw-r--r--day22.fsx72
1 files changed, 72 insertions, 0 deletions
diff --git a/day22.fsx b/day22.fsx
new file mode 100644
index 0000000..7944d25
--- /dev/null
+++ b/day22.fsx
@@ -0,0 +1,72 @@
+type Spell = 
+    { Name : string
+      Cost : int
+      Damage : int
+      Heal : int
+      Armor : int
+      Mana : int
+      Duration : int }
+
+let allSpells = 
+    [ { Name = "Magic Missile"; Cost = 53;  Damage = 4; Heal = 0; Armor = 0; Mana = 0;   Duration = 1}
+      { Name = "Drain";         Cost = 73;  Damage = 2; Heal = 2; Armor = 0; Mana = 0;   Duration = 1}
+      { Name = "Shield";        Cost = 113; Damage = 0; Heal = 0; Armor = 7; Mana = 0;   Duration = 6}
+      { Name = "Poison";        Cost = 173; Damage = 3; Heal = 0; Armor = 0; Mana = 0;   Duration = 6}
+      { Name = "Recharge";      Cost = 229; Damage = 0; Heal = 0; Armor = 0; Mana = 101; Duration = 5} ]
+
+let cheapestWin part (hp, mana) (bossHp, bossDamage) =
+    let rec play part myTurn best spent (hp, mana, spells) (bossHp, bossDamage) : int =
+        // if we have already spent more than the known cheapest win, bail
+        if spent >= best then best else
+
+        // part 2, check if I die before any effects play out
+        if part = 2 && myTurn && hp = 1 then best else
+
+        // apply effects
+        let mana  = (spells |> List.sumBy (fun s -> s.Mana)) + mana
+        let damage = spells |> List.sumBy (fun s -> s.Damage)
+        let armor  = spells |> List.sumBy (fun s -> s.Armor)
+
+        // does the boss die from effects?
+        let bossHp = bossHp - damage
+        if bossHp <= 0 then spent else
+
+        // decrement duration of all effects, and groom expired ones
+        let spells =
+            spells
+            |> List.map (fun s -> {s with Duration = s.Duration - 1})
+            |> List.filter (fun s -> s.Duration > 0)
+
+        if myTurn then
+            // part 2, I lose 1 HP on my turn
+            let hp = if part = 2 then hp - 1 else hp
+
+            // what spells can I afford and don't already have running?
+            match allSpells |> List.filter (fun s -> (s.Cost <= mana) && not (spells |> List.exists (fun s' -> s.Name = s'.Name))) with
+            | [] -> best
+            | buyableSpells ->
+                // play out the rest of the game with each possible purchase
+                let mutable newBest = best
+                for s in buyableSpells do
+                    let extraDamage, heal, spells = 
+                        if s.Duration = 1 then s.Damage, s.Heal, spells
+                        else 0, 0, s :: spells
+                    let spent = spent + s.Cost
+                    let mana = mana - s.Cost
+                    let hp = hp + heal
+                
+                    let bossHp = bossHp - extraDamage
+                    if bossHp <= 0 then newBest <- min newBest spent
+                    else newBest <- min newBest (play part false newBest spent (hp, mana, spells) (bossHp, bossDamage))
+                newBest
+        // boss's turn
+        else
+            let damage = max (bossDamage - armor) 1
+            let hp = hp - damage
+            if hp <= 0 then best else
+            play part true best spent (hp, mana, spells) (bossHp, bossDamage)
+
+    play part true 999999 0 (hp, mana, []) (bossHp, bossDamage)
+
+printfn "Part 1 - min to win: %d" (cheapestWin 1 (50, 500) (55, 8))
+printfn "Part 2 - min to win: %d" (cheapestWin 2 (50, 500) (55, 8))
-0800 committer Kartik K. Agaram <vc@akkartik.com> 2015-02-19 22:48:25 -0800 797 - comparison instructions' href='/akkartik/mu/commit/cpp/.traces/greater_or_equal3?h=hlt&id=9dc2948276388d2ca6556f4a8d13d55406775ac7'>9dc29482 ^
57699011 ^
6f5d7864 ^
249a5672 ^
9dc29482 ^




57699011 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32