185 lines
3.7 KiB
Go
185 lines
3.7 KiB
Go
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
|
|
for _, weaponStats := range weapons {
|
|
for _, armorStats := range armor {
|
|
goldSpent = weaponStats["cost"] + armorStats["cost"]
|
|
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 < minGold {
|
|
minGold = goldSpent
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|