day21 - with the AoC website being wrong (or me just being stupid)
This commit is contained in:
parent
81562d7441
commit
b8e78e8472
183
day21/day.go
Normal file
183
day21/day.go
Normal 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_test
Normal file
3
inputs/21_test
Normal file
@ -0,0 +1,3 @@
|
||||
Hit Points: 104
|
||||
Damage: 8
|
||||
Armor: 1
|
||||
2
main.go
2
main.go
@ -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},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user