190 lines
3.8 KiB
Go
190 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Queue struct {
|
|
arr []int
|
|
head uint
|
|
tail uint
|
|
}
|
|
|
|
func (s *Queue) Dequeue() int {
|
|
s.head++
|
|
return s.arr[s.head - 1]
|
|
}
|
|
|
|
func (s *Queue) Enqueue(num int) {
|
|
if len(s.arr) <= int(s.tail) {
|
|
s.arr = append(s.arr, num)
|
|
} else {
|
|
s.arr[s.tail] = num
|
|
}
|
|
s.tail++
|
|
}
|
|
|
|
func (s *Queue) Print() string {
|
|
str := ""
|
|
for i := s.head; i < s.tail; i++ {
|
|
str += strconv.Itoa(s.arr[i]) + ","
|
|
}
|
|
return str
|
|
}
|
|
|
|
func main() {
|
|
content, err := os.ReadFile("./input.txt")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
players := strings.Split(string(content), "\n\n")
|
|
|
|
player1 := strings.Split(players[0], "\n")[1:]
|
|
player2 := strings.Split(players[1], "\n")[1:]
|
|
|
|
player1Cards := Queue{
|
|
arr: make([]int, 0),
|
|
head: 0,
|
|
tail: 0,
|
|
}
|
|
player2Cards := Queue{
|
|
arr: make([]int, 0),
|
|
head: 0,
|
|
tail: 0,
|
|
}
|
|
|
|
for _, v := range player1 {
|
|
n, err := strconv.Atoi(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
player1Cards.Enqueue(n)
|
|
}
|
|
|
|
for _, v := range player2 {
|
|
if len(v) == 0 {
|
|
continue
|
|
}
|
|
n, err := strconv.Atoi(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
player2Cards.Enqueue(n)
|
|
}
|
|
|
|
/*
|
|
rounds := 0
|
|
for {
|
|
if player1Cards.head == player1Cards.tail || player2Cards.head == player2Cards.tail {
|
|
break
|
|
}
|
|
|
|
player1Card := player1Cards.Dequeue()
|
|
player2Card := player2Cards.Dequeue()
|
|
if player1Card > player2Card {
|
|
player1Cards.Enqueue(player1Card)
|
|
player1Cards.Enqueue(player2Card)
|
|
} else {
|
|
player2Cards.Enqueue(player2Card)
|
|
player2Cards.Enqueue(player1Card)
|
|
}
|
|
|
|
rounds++
|
|
}
|
|
|
|
*/
|
|
|
|
_, p1, p2 := PlayGame(player1Cards, player2Cards)
|
|
|
|
var winningScore uint = 0
|
|
if p1.tail - p1.head < p2.tail - p2.head {
|
|
for i := p2.head; i < p2.tail; i++ {
|
|
winningScore += (p2.tail - i) * uint(p2.arr[i])
|
|
}
|
|
} else {
|
|
for i := p1.head; i < p1.tail; i++ {
|
|
winningScore += (p1.tail - i) * uint(p1.arr[i])
|
|
}
|
|
}
|
|
|
|
fmt.Println(winningScore)
|
|
}
|
|
|
|
// true = player1, false = player2
|
|
func PlayGame(player1 Queue, player2 Queue) (bool, *Queue, *Queue) {
|
|
cache1 := make(map[string]bool)
|
|
cache2 := make(map[string]bool)
|
|
for {
|
|
if player1.head == player1.tail || player2.head == player2.tail {
|
|
return player2.head == player2.tail, &player1, &player2
|
|
}
|
|
|
|
// Before drawing, check.
|
|
player1string := player1.Print()
|
|
player2string := player2.Print()
|
|
|
|
_, exists := cache1[player1string]
|
|
if exists {
|
|
return true, &player1, &player2
|
|
}
|
|
|
|
_, exists = cache2[player2string]
|
|
if exists {
|
|
return true, &player1, &player2
|
|
}
|
|
|
|
cache1[player1string] = true
|
|
cache2[player2string] = true
|
|
|
|
|
|
player1Card := player1.Dequeue()
|
|
player2Card := player2.Dequeue()
|
|
|
|
if int(player1.tail) - int(player1.head) >= player1Card && int(player2.tail) - int(player2.head) >= player2Card {
|
|
// Recursive case!
|
|
player1Copy := Queue{
|
|
arr: slices.Clone(player1.arr),
|
|
head: player1.head,
|
|
tail: player1.head + uint(player1Card),
|
|
}
|
|
|
|
player2Copy := Queue{
|
|
arr: slices.Clone(player2.arr),
|
|
head: player2.head,
|
|
tail: player2.head + uint(player2Card),
|
|
}
|
|
|
|
winner, _, _ := PlayGame(player1Copy, player2Copy)
|
|
if winner {
|
|
player1.Enqueue(player1Card)
|
|
player1.Enqueue(player2Card)
|
|
} else {
|
|
player2.Enqueue(player2Card)
|
|
player2.Enqueue(player1Card)
|
|
}
|
|
} else {
|
|
if player1Card > player2Card {
|
|
player1.Enqueue(player1Card)
|
|
player1.Enqueue(player2Card)
|
|
} else {
|
|
player2.Enqueue(player2Card)
|
|
player2.Enqueue(player1Card)
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
func GetString(arr []int) string {
|
|
s := ""
|
|
for _, v := range arr {
|
|
s += "," + strconv.Itoa(v)
|
|
}
|
|
return s
|
|
}
|