aoc2015/day21/day.go
2020-12-31 12:29:46 +01:00

162 lines
2.9 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 getMinMaxGold(puzzle tools.AoCPuzzle) (minGold int, maxGold int) {
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 {
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"]
playerWon := fight(playerHp, playerPower, playerArmor, bossHp, bossPower, bossArmor)
if playerWon && goldSpent < minGold {
minGold = goldSpent
} else if !playerWon && goldSpent > maxGold {
maxGold = goldSpent
}
}
}
}
}
return minGold, maxGold
}
func Part1(puzzle tools.AoCPuzzle) interface{} {
minGold, _ := getMinMaxGold(puzzle)
return minGold
}
func Part2(puzzle tools.AoCPuzzle) interface{} {
_, maxGold := getMinMaxGold(puzzle)
return maxGold
}