Day 22 solution.
This commit is contained in:
parent
8bc0ff81c3
commit
581e2571de
122
2020/day22.go
Normal file
122
2020/day22.go
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.annabunch.es/annabunches/adventofcode/2020/lib/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func parseInput(input []string) [][]int {
|
||||||
|
decks := make([][]int, 2)
|
||||||
|
decks[0] = make([]int, 0)
|
||||||
|
decks[1] = make([]int, 0)
|
||||||
|
player := 0
|
||||||
|
for _, line := range input {
|
||||||
|
if strings.HasPrefix(line, "Player") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if line == "" {
|
||||||
|
player++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
decks[player] = append(decks[player], util.MustAtoi(line))
|
||||||
|
}
|
||||||
|
|
||||||
|
return decks
|
||||||
|
}
|
||||||
|
|
||||||
|
func playGame(decks [][]int, step string) (int, [][]int) {
|
||||||
|
gameStates := make(map[string]struct{})
|
||||||
|
found := struct{}{}
|
||||||
|
|
||||||
|
for len(decks[0]) > 0 && len(decks[1]) > 0 {
|
||||||
|
state := serializeGame(decks)
|
||||||
|
if _, ok := gameStates[state]; ok && step == "2" {
|
||||||
|
return 0, decks
|
||||||
|
}
|
||||||
|
gameStates[state] = found
|
||||||
|
|
||||||
|
var winner int
|
||||||
|
// take the top cards
|
||||||
|
card0 := decks[0][0]
|
||||||
|
card1 := decks[1][0]
|
||||||
|
decks[0] = decks[0][1:]
|
||||||
|
decks[1] = decks[1][1:]
|
||||||
|
|
||||||
|
// determine the winner, put the cards in order
|
||||||
|
if card0 > card1 {
|
||||||
|
winner = 0
|
||||||
|
} else {
|
||||||
|
winner = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// if each card is >= the number of cards in that deck
|
||||||
|
if step == "2" && card0 <= len(decks[0]) && card1 <= len(decks[1]) {
|
||||||
|
newDecks := make([][]int, 2)
|
||||||
|
newDecks[0] = make([]int, card0)
|
||||||
|
newDecks[1] = make([]int, card1)
|
||||||
|
copy(newDecks[0], decks[0][:card0])
|
||||||
|
copy(newDecks[1], decks[1][:card1])
|
||||||
|
// Recursive Combat throws out the "normal" winner above
|
||||||
|
winner, _ = playGame(newDecks, step)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stack the cards for adding to the winner's bottom
|
||||||
|
cards := make([]int, 2)
|
||||||
|
if winner == 0 {
|
||||||
|
cards[0] = card0
|
||||||
|
cards[1] = card1
|
||||||
|
} else {
|
||||||
|
cards[0] = card1
|
||||||
|
cards[1] = card0
|
||||||
|
}
|
||||||
|
|
||||||
|
// and add them to the winner's bottom
|
||||||
|
decks[winner] = append(decks[winner], cards...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(decks[0]) > 0 {
|
||||||
|
return 0, decks
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1, decks
|
||||||
|
}
|
||||||
|
|
||||||
|
func serializeGame(decks [][]int) string {
|
||||||
|
out := ""
|
||||||
|
for _, deck := range decks {
|
||||||
|
for _, card := range deck {
|
||||||
|
out = out + string(card) + ","
|
||||||
|
}
|
||||||
|
out = out + "|"
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func calculateScore(decks [][]int) int {
|
||||||
|
score := 0
|
||||||
|
var index int
|
||||||
|
if len(decks[0]) > 0 {
|
||||||
|
index = 0
|
||||||
|
} else {
|
||||||
|
index = 1
|
||||||
|
}
|
||||||
|
deckSize := len(decks[index])
|
||||||
|
for i := deckSize - 1; i >= 0; i-- {
|
||||||
|
score += decks[index][i] * (deckSize - i)
|
||||||
|
}
|
||||||
|
|
||||||
|
return score
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
step := os.Args[1]
|
||||||
|
values := util.InputParserStrings(os.Args[2])
|
||||||
|
input := parseInput(values)
|
||||||
|
|
||||||
|
_, decks := playGame(input, step)
|
||||||
|
fmt.Println(calculateScore(decks))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user