2018 day 24 More work
This commit is contained in:
parent
4a7a0e872e
commit
10af09b200
@ -1,19 +1,33 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ArmyTypeImmune = 1 << iota
|
||||||
|
ArmyTypeInfection
|
||||||
|
)
|
||||||
|
|
||||||
type Army struct {
|
type Army struct {
|
||||||
tp int
|
id int
|
||||||
units int
|
tp int
|
||||||
hp int
|
units int
|
||||||
immunities []string
|
hp int
|
||||||
weaknesses []string
|
immunities []string
|
||||||
damageType string
|
weaknesses []string
|
||||||
strength int
|
damageType string
|
||||||
init int
|
strength int
|
||||||
|
init int
|
||||||
|
target *Army
|
||||||
|
targettedBy *Army
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArmy(inp string, tp int) *Army {
|
func NewArmy(inp string, tp, id int) *Army {
|
||||||
a := new(Army)
|
a := new(Army)
|
||||||
a.tp = tp
|
a.tp = tp
|
||||||
|
a.id = id
|
||||||
|
|
||||||
// Pull the parenthetical out, if one is there
|
// Pull the parenthetical out, if one is there
|
||||||
var prnth, other string
|
var prnth, other string
|
||||||
@ -43,38 +57,154 @@ func NewArmy(inp string, tp int) *Army {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
// Now parse out immunities and weaknesses
|
// Now parse out immunities and weaknesses
|
||||||
if len(prnth) > 3 {
|
if len(prnth) > 3 {
|
||||||
prnth = prnth[1:len(prnth)-1]
|
prnth = prnth[1 : len(prnth)-1]
|
||||||
var inImmune bool
|
var inImmune bool
|
||||||
for _, v := range strings.Fields(prnth) {
|
for _, v := range strings.Fields(prnth) {
|
||||||
if v == "immune" {
|
if v == "immune" {
|
||||||
inImmune = true
|
inImmune = true
|
||||||
} else if v == "weak" {
|
continue
|
||||||
inImmune = false
|
} else if v == "weak" {
|
||||||
}
|
inImmune = false
|
||||||
if v == "to" {
|
continue
|
||||||
continue
|
}
|
||||||
}
|
if v == "to" {
|
||||||
if v[len(v)-1] == ';' || v[len(v)-1] == ',' {
|
continue
|
||||||
v = v[:len(v)-1]
|
}
|
||||||
}
|
if v[len(v)-1] == ';' || v[len(v)-1] == ',' {
|
||||||
if inImmune {
|
v = v[:len(v)-1]
|
||||||
a.immunities = append(a.immunities, v)
|
}
|
||||||
} else {
|
if inImmune {
|
||||||
a.weaknesses = append(a.weaknesses, v)
|
a.immunities = append(a.immunities, v)
|
||||||
}
|
} else {
|
||||||
}
|
a.weaknesses = append(a.weaknesses, v)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Army) IsImmuneTo(val string) bool {
|
||||||
|
for _, v := range a.immunities {
|
||||||
|
if v == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Army) IsWeakTo(val string) bool {
|
||||||
|
for _, v := range a.weaknesses {
|
||||||
|
if v == val {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (a *Army) Power() int {
|
func (a *Army) Power() int {
|
||||||
return a.units * a.strength
|
return a.units * a.strength
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Army) FindTarget(group []*Army) {
|
||||||
|
var tgt *Army
|
||||||
|
var tgtDmg int
|
||||||
|
for _, v := range group {
|
||||||
|
if v.targettedBy != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
wrkDmg := a.CalculateDamage(v)
|
||||||
|
if tgt == nil || wrkDmg > tgtDmg {
|
||||||
|
tgt = v
|
||||||
|
tgtDmg = wrkDmg
|
||||||
|
} else if wrkDmg == tgtDmg {
|
||||||
|
if v.Power() > tgt.Power() {
|
||||||
|
tgt = v
|
||||||
|
tgtDmg = wrkDmg
|
||||||
|
} else if v.Power() == tgt.Power() {
|
||||||
|
if v.init > tgt.init {
|
||||||
|
tgt = v
|
||||||
|
tgtDmg = wrkDmg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
var tpTxt string
|
||||||
|
if a.tp == ArmyTypeImmune {
|
||||||
|
tpTxt = "Immune System"
|
||||||
|
} else {
|
||||||
|
tpTxt = "Infection"
|
||||||
|
}
|
||||||
|
fmt.Printf("%s group %d would deal defending group %d %d damage\n", tpTxt, a.id, tgt.id, tgtDmg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tgt != nil {
|
||||||
|
a.target = tgt
|
||||||
|
tgt.targettedBy = a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Army) CalculateDamage(b *Army) int {
|
||||||
|
if b.IsWeakTo(a.damageType) {
|
||||||
|
return a.Power() * 2
|
||||||
|
} else if b.IsImmuneTo(a.damageType) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return a.Power()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Army) Damage(b *Army) int {
|
||||||
|
var unitsDefeated int
|
||||||
|
dmg := a.CalculateDamage(b)
|
||||||
|
for dmg > 0 {
|
||||||
|
dmg -= b.hp
|
||||||
|
if dmg > 0 && b.units > 0 {
|
||||||
|
b.units--
|
||||||
|
unitsDefeated++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.targettedBy = nil
|
||||||
|
return unitsDefeated
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *Army) Fight() {
|
||||||
|
if a.target != nil {
|
||||||
|
var tpTxt string
|
||||||
|
if a.tp == ArmyTypeImmune {
|
||||||
|
tpTxt = "Immune System"
|
||||||
|
} else if a.tp == ArmyTypeInfection {
|
||||||
|
tpTxt = "Infection"
|
||||||
|
}
|
||||||
|
dmg := a.Damage(a.target)
|
||||||
|
if Debug {
|
||||||
|
fmt.Printf("%s group %d attacks defending group %d, killing %d units\n", tpTxt, a.id, a.target.id, dmg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a Army) String() string {
|
||||||
|
ret := fmt.Sprintf("%d units each with %d hit points ", a.units, a.hp)
|
||||||
|
if len(a.weaknesses) > 0 {
|
||||||
|
ret = ret + fmt.Sprintf("(weaknesses: %s) ", a.weaknesses)
|
||||||
|
}
|
||||||
|
if len(a.immunities) > 0 {
|
||||||
|
ret = ret + fmt.Sprintf("(immunities: %s) ", a.immunities)
|
||||||
|
}
|
||||||
|
ret = ret + fmt.Sprintf("with an attack that does %d %s damage at initiative %d\n",
|
||||||
|
a.strength, a.damageType, a.init,
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
// Army Sorting
|
// Army Sorting
|
||||||
type ByPower []Army
|
type ByPower []*Army
|
||||||
func (b ByPower) Len() int { return len(b) }
|
|
||||||
|
func (b ByPower) Len() int { return len(b) }
|
||||||
func (b ByPower) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
func (b ByPower) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||||
func (b ByPower) Less(i, j int) { b[i].Power() < b[j].Power() }
|
func (b ByPower) Less(i, j int) bool {
|
||||||
|
if b[i].Power() == b[j].Power() {
|
||||||
|
return b[i].init < b[j].init
|
||||||
|
}
|
||||||
|
return b[i].Power() < b[j].Power()
|
||||||
|
}
|
||||||
|
@ -1,10 +1,72 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
// All Battle Logic is in here
|
import (
|
||||||
func Battle(army1, army2 []Army) {
|
"fmt"
|
||||||
allCombatants = append(army1, army2...)
|
"sort"
|
||||||
sort.Sort(ByPower(allCombatants))
|
)
|
||||||
for _, v := range allCombatants {
|
|
||||||
fmt.Print("%d %d %d (%d)\n", v.tp, v.units, v.hp, v.Power())
|
type Battle struct {
|
||||||
}
|
immune []*Army
|
||||||
|
infect []*Army
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBattle(immune, infect []*Army) *Battle {
|
||||||
|
return &Battle{
|
||||||
|
immune: immune,
|
||||||
|
infect: infect,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Battle) PrintStatus() {
|
||||||
|
fmt.Println("Immune System:")
|
||||||
|
for _, v := range b.immune {
|
||||||
|
fmt.Printf("Group %d contains %d units\n", v.id, v.units)
|
||||||
|
}
|
||||||
|
fmt.Println("Infection:")
|
||||||
|
for _, v := range b.infect {
|
||||||
|
fmt.Printf("Group %d contains %d units\n", v.id, v.units)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All Battle Logic is in here
|
||||||
|
func (b *Battle) Fight() {
|
||||||
|
allCombatants := append(b.immune, b.infect...)
|
||||||
|
sort.Sort(ByPower(allCombatants))
|
||||||
|
for k := len(allCombatants) - 1; k >= 0; k-- {
|
||||||
|
b.FindTargetFor(allCombatants[k])
|
||||||
|
}
|
||||||
|
if Debug {
|
||||||
|
fmt.Println("")
|
||||||
|
}
|
||||||
|
for k := len(allCombatants) - 1; k >= 0; k-- {
|
||||||
|
allCombatants[k].Fight()
|
||||||
|
}
|
||||||
|
i := 0
|
||||||
|
for _, x := range b.immune {
|
||||||
|
if x.units > 0 {
|
||||||
|
b.immune[i] = x
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.immune = b.immune[:i]
|
||||||
|
i = 0
|
||||||
|
for _, x := range b.infect {
|
||||||
|
if x.units > 0 {
|
||||||
|
b.infect[i] = x
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.infect = b.infect[:i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Battle) FindTargetFor(a *Army) {
|
||||||
|
if a.tp == ArmyTypeImmune {
|
||||||
|
a.FindTarget(b.infect)
|
||||||
|
} else if a.tp == ArmyTypeInfection {
|
||||||
|
a.FindTarget(b.immune)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Battle) IsOver() bool {
|
||||||
|
return len(b.immune) == 0 || len(b.infect) == 0
|
||||||
}
|
}
|
||||||
|
@ -4,43 +4,50 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ArmyTypeImmune = 1 << iota
|
Debug = true
|
||||||
ArmyTypeInfection
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
inp := StdinToStringSlice()
|
inp := StdinToStringSlice()
|
||||||
immune, infect := ParseInput(inp)
|
immune, infect := ParseInput(inp)
|
||||||
for _, v := range immune {
|
|
||||||
fmt.Println("++ ", v.immunities)
|
b := NewBattle(immune, infect)
|
||||||
fmt.Println("-- ", v.weaknesses)
|
//for !b.IsOver() {
|
||||||
}
|
if Debug {
|
||||||
_, _ = immune, infect
|
b.PrintStatus()
|
||||||
|
fmt.Println("")
|
||||||
|
}
|
||||||
|
b.Fight()
|
||||||
|
//}
|
||||||
|
|
||||||
|
fmt.Println("")
|
||||||
|
fmt.Println("The battle is over!")
|
||||||
|
b.PrintStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseInput(inp []string) ([]Army, []Army) {
|
func ParseInput(inp []string) ([]*Army, []*Army) {
|
||||||
var immune, infection []Army
|
var immune, infection []*Army
|
||||||
var tp int
|
var tp, id int
|
||||||
for _, v := range inp {
|
for _, v := range inp {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if v == "Immune System:" {
|
if v == "Immune System:" {
|
||||||
tp = ArmyTypeImmune
|
tp, id = ArmyTypeImmune, 0
|
||||||
continue
|
continue
|
||||||
} else if v == "Infection:" {
|
} else if v == "Infection:" {
|
||||||
tp = ArmyTypeInfection
|
tp, id = ArmyTypeInfection, 0
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
id++
|
||||||
switch tp {
|
switch tp {
|
||||||
case ArmyTypeImmune:
|
case ArmyTypeImmune:
|
||||||
immune = append(immune, *NewArmy(v, tp))
|
immune = append(immune, NewArmy(v, tp, id))
|
||||||
case ArmyTypeInfection:
|
case ArmyTypeInfection:
|
||||||
infection = append(infection, *NewArmy(v, tp))
|
infection = append(infection, NewArmy(v, tp, id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return immune, infection
|
return immune, infection
|
||||||
|
7
2018/day24/testinput
Normal file
7
2018/day24/testinput
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Immune System:
|
||||||
|
17 units each with 5390 hit points (weak to radiation, bludgeoning) with an attack that does 4507 fire damage at initiative 2
|
||||||
|
989 units each with 1274 hit points (immune to fire; weak to bludgeoning, slashing) with an attack that does 25 slashing damage at initiative 3
|
||||||
|
|
||||||
|
Infection:
|
||||||
|
801 units each with 4706 hit points (weak to radiation) with an attack that does 116 bludgeoning damage at initiative 1
|
||||||
|
4485 units each with 2961 hit points (immune to radiation; weak to fire, cold) with an attack that does 12 slashing damage at initiative 4
|
Loading…
Reference in New Issue
Block a user