Big update: Adding all advent of codes to same repo
This commit is contained in:
189
AdventOfCode2020/day22/day22.go
Normal file
189
AdventOfCode2020/day22/day22.go
Normal file
@@ -0,0 +1,189 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user