day21 - with the AoC website being wrong (or me just being stupid)

This commit is contained in:
Stefan Harmuth 2020-12-31 12:21:38 +01:00
parent 81562d7441
commit b8e78e8472
4 changed files with 191 additions and 0 deletions

183
day21/day.go Normal file
View File

@ -0,0 +1,183 @@
package day21
import (
"math"
"strconv"
"strings"
"tools"
)
var armor = map[string]map[string]int{
"none": {
"cost": 0,
"armor": 0,
},
"Leather": {
"cost": 13,
"armor": 1,
},
"Chainmail": {
"cost": 31,
"armor": 2,
},
"Splintmail": {
"cost": 53,
"armor": 3,
},
"Bandedmail": {
"cost": 75,
"armor": 4,
},
"Platemail": {
"cost": 102,
"armor": 5,
},
}
var weapons = map[string]map[string]int{
"Dagger": {
"cost": 8,
"damage": 4,
},
"Shortsword": {
"cost": 10,
"damage": 5,
},
"Warhammer": {
"cost": 25,
"damage": 6,
},
"Longsword": {
"cost": 40,
"damage": 7,
},
"Greataxe": {
"cost": 74,
"damage": 8,
},
}
var rings = map[string]map[string]int{
"none1": {
"cost": 0,
"damage": 0,
"armor": 0,
},
"none2": {
"cost": 0,
"damage": 0,
"armor": 0,
},
"Damage +1": {
"cost": 25,
"damage": 1,
"armor": 0,
},
"Damage +2": {
"cost": 50,
"damage": 2,
"armor": 0,
},
"Damage +3": {
"cost": 100,
"damage": 3,
"armor": 0,
},
"Armor +1": {
"cost": 20,
"damage": 0,
"armor": 1,
},
"Armor +2": {
"cost": 40,
"damage": 0,
"armor": 2,
},
"Armor +3": {
"cost": 80,
"damage": 0,
"armor": 3,
},
}
func fight(playerHp, playerPower, playerArmor, bossHp, bossPower, bossArmor int) bool {
playerStrike := float64(tools.Max(1, playerPower-bossArmor))
bossStrike := float64(tools.Max(1, bossPower-playerArmor))
return math.Ceil(float64(bossHp)/playerStrike) <= math.Ceil(float64(playerHp)/bossStrike)
}
func Part1(puzzle tools.AoCPuzzle) interface{} {
input := puzzle.GetInputArray()
hpLine := strings.Split(input[0], ": ")
powerLine := strings.Split(input[1], ": ")
armorLine := strings.Split(input[2], ": ")
bossHp, _ := strconv.Atoi(hpLine[1])
bossPower, _ := strconv.Atoi(powerLine[1])
bossArmor, _ := strconv.Atoi(armorLine[1])
playerHp := 100
playerPower := 0
playerArmor := 0
goldSpent := 0
minGold := math.MaxInt32
// completely ignoring rings for p1 as they are way too expensive in any case
for _, weaponStats := range weapons {
for _, armorStats := range armor {
goldSpent = weaponStats["cost"] + armorStats["cost"]
playerPower = weaponStats["damage"]
playerArmor = armorStats["armor"]
if fight(playerHp, playerPower, playerArmor, bossHp, bossPower, bossArmor) && goldSpent < minGold {
minGold = goldSpent
}
}
}
// REVISIT: The "correct" answer according to AoC website was 78, but that doesn't work!
// The only way to spent 78 Gold is by buying a Warhammer and the Splintmail
// That put the player damage at 6(weapon)-1(bossArmor) == 5
// And the boss damage becomes 8(input)-3(armor) == 5
// But the boss has 104 HP and the player only 100.
// Leaving the player dead after 20 Rounds with the boss still having 4 HP
return minGold
}
func Part2(puzzle tools.AoCPuzzle) interface{} {
input := puzzle.GetInputArray()
hpLine := strings.Split(input[0], ": ")
powerLine := strings.Split(input[1], ": ")
armorLine := strings.Split(input[2], ": ")
bossHp, _ := strconv.Atoi(hpLine[1])
bossPower, _ := strconv.Atoi(powerLine[1])
bossArmor, _ := strconv.Atoi(armorLine[1])
playerHp := 100
playerPower := 0
playerArmor := 0
goldSpent := 0
maxGold := 0
for _, weaponStats := range weapons {
for _, armorStats := range armor {
for ring1Name, ring1Stats := range rings {
for ring2Name, ring2Stats := range rings {
if ring1Name == ring2Name {
continue
}
goldSpent = weaponStats["cost"] + armorStats["cost"] + ring1Stats["cost"] + ring2Stats["cost"]
playerPower = weaponStats["damage"] + ring1Stats["damage"] + ring2Stats["damage"]
playerArmor = armorStats["armor"] + ring1Stats["armor"] + ring2Stats["armor"]
if !fight(playerHp, playerPower, playerArmor, bossHp, bossPower, bossArmor) && goldSpent > maxGold {
maxGold = goldSpent
}
}
}
}
}
return maxGold
}

3
inputs/21 Normal file
View File

@ -0,0 +1,3 @@
Hit Points: 104
Damage: 8
Armor: 1

3
inputs/21_test Normal file
View File

@ -0,0 +1,3 @@
Hit Points: 104
Damage: 8
Armor: 1

View File

@ -21,6 +21,7 @@ import (
"aoc2015/day18"
"aoc2015/day19"
"aoc2015/day20"
"aoc2015/day21"
"flag"
"fmt"
"os"
@ -58,6 +59,7 @@ func initDayFunctions() {
18: {1: day18.Part1, 2: day18.Part2},
19: {1: day19.Part1, 2: day19.Part2},
20: {1: day20.Part1, 2: day20.Part2},
21: {1: day21.Part1, 2: day21.Part2},
}
}