2020 Day 22 Complete
This commit is contained in:
parent
aaf3054c8a
commit
5a37a6e964
53
2020/day22/input
Normal file
53
2020/day22/input
Normal file
@ -0,0 +1,53 @@
|
||||
Player 1:
|
||||
4
|
||||
25
|
||||
3
|
||||
11
|
||||
2
|
||||
29
|
||||
41
|
||||
23
|
||||
30
|
||||
21
|
||||
50
|
||||
8
|
||||
1
|
||||
24
|
||||
27
|
||||
10
|
||||
42
|
||||
43
|
||||
38
|
||||
15
|
||||
18
|
||||
13
|
||||
32
|
||||
37
|
||||
34
|
||||
|
||||
Player 2:
|
||||
12
|
||||
6
|
||||
36
|
||||
35
|
||||
40
|
||||
47
|
||||
31
|
||||
9
|
||||
46
|
||||
49
|
||||
19
|
||||
16
|
||||
5
|
||||
26
|
||||
39
|
||||
48
|
||||
7
|
||||
44
|
||||
45
|
||||
20
|
||||
17
|
||||
14
|
||||
33
|
||||
28
|
||||
22
|
193
2020/day22/main.go
Normal file
193
2020/day22/main.go
Normal file
@ -0,0 +1,193 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
h "git.bullercodeworks.com/brian/adventofcode/helpers"
|
||||
)
|
||||
|
||||
var debugLevel int
|
||||
|
||||
const (
|
||||
debugLo = 1
|
||||
debugMd = 2
|
||||
debugHi = 3
|
||||
debugNo = -1
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("# Day 22")
|
||||
inp := h.StdinToStringSlice()
|
||||
|
||||
debugLevel = h.Atoi(h.OptArgNumber(2, "-1"))
|
||||
|
||||
solve(inp, h.Atoi(h.OptArgNumber(1, "2")))
|
||||
}
|
||||
|
||||
func print(s string, lvl int) {
|
||||
if debugLevel != -1 && lvl >= debugLevel {
|
||||
fmt.Print(s)
|
||||
}
|
||||
}
|
||||
|
||||
func solve(inp []string, part int) {
|
||||
var player int
|
||||
decks := make(map[int]*Deck)
|
||||
for k := range inp {
|
||||
if strings.TrimSpace(inp[k]) == "" {
|
||||
continue
|
||||
} else if strings.HasPrefix(inp[k], "Player ") {
|
||||
player = h.Atoi(inp[k][7 : len(inp[k])-1])
|
||||
decks[player] = &Deck{Player: player}
|
||||
continue
|
||||
} else {
|
||||
decks[player].Add(h.Atoi(inp[k]))
|
||||
}
|
||||
}
|
||||
|
||||
if part == 1 {
|
||||
solveNormal(decks[1], decks[2])
|
||||
} else {
|
||||
solveRecursive(decks[1], decks[2])
|
||||
}
|
||||
}
|
||||
|
||||
func solveNormal(deck1, deck2 *Deck) {
|
||||
round := 1
|
||||
winner := Winner(deck1, deck2)
|
||||
for winner == -1 {
|
||||
|
||||
print(fmt.Sprintf("-- Round %d --\n%s\n%s\n", round, deck1, deck2), debugLo)
|
||||
|
||||
cmp1 := deck1.Draw()
|
||||
cmp2 := deck2.Draw()
|
||||
print(fmt.Sprintf("Player 1 plays: %d\nPlayer 2 plays: %d\n", cmp1, cmp2), debugLo)
|
||||
if cmp1 > cmp2 {
|
||||
print(fmt.Sprintln("Player 1 wins the round!"), debugLo)
|
||||
deck1.Add(cmp1, cmp2)
|
||||
} else if cmp2 > cmp1 {
|
||||
print(fmt.Sprintln("Player 2 wins the round!"), debugLo)
|
||||
deck2.Add(cmp2, cmp1)
|
||||
}
|
||||
round++
|
||||
winner = Winner(deck1, deck2)
|
||||
}
|
||||
fmt.Printf("== Post-game results ==\n%s\n%s\n", deck1, deck2)
|
||||
var score int
|
||||
if winner == 1 {
|
||||
score = deck1.Score()
|
||||
} else {
|
||||
score = deck2.Score()
|
||||
}
|
||||
|
||||
fmt.Println("## Part 1:\nAnswer: ", score)
|
||||
}
|
||||
|
||||
func solveRecursive(deck1, deck2 *Deck) {
|
||||
winner := RPlayGame(deck1, deck2)
|
||||
|
||||
fmt.Printf("== Post-game results ==\n%s\n%s\n", deck1, deck2)
|
||||
var score int
|
||||
if winner == 1 {
|
||||
score = deck1.Score()
|
||||
} else {
|
||||
score = deck2.Score()
|
||||
}
|
||||
fmt.Println("## Part 2:\nAnswer: ", score)
|
||||
}
|
||||
|
||||
var totalGames int
|
||||
|
||||
func RPlayGame(deck1, deck2 *Deck) int {
|
||||
var history []string
|
||||
var repeat bool
|
||||
for deck1.Len() > 0 && deck2.Len() > 0 {
|
||||
history, repeat = RPlayRound(deck1, deck2, history)
|
||||
if repeat {
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return Winner(deck1, deck2)
|
||||
}
|
||||
|
||||
func RPlayRound(deck1, deck2 *Deck, history []string) ([]string, bool) {
|
||||
status := fmt.Sprintf("%s%s", deck1, deck2)
|
||||
if h.StringSliceContains(history, status) {
|
||||
return history, true
|
||||
}
|
||||
nextHistory := append(history, status)
|
||||
c1, c2 := deck1.Draw(), deck2.Draw()
|
||||
if deck1.Len() >= c1 && deck2.Len() >= c2 {
|
||||
winner := RPlayGame(deck1.Copy(c1), deck2.Copy(c2))
|
||||
switch winner {
|
||||
case 1:
|
||||
deck1.Add(c1, c2)
|
||||
case 2:
|
||||
deck2.Add(c2, c1)
|
||||
}
|
||||
return nextHistory, false
|
||||
}
|
||||
if c1 > c2 {
|
||||
deck1.Add(c1, c2)
|
||||
} else {
|
||||
deck2.Add(c2, c1)
|
||||
}
|
||||
|
||||
return nextHistory, false
|
||||
}
|
||||
|
||||
func Winner(deck1, deck2 *Deck) int {
|
||||
if deck2.Empty() {
|
||||
return 1
|
||||
} else if deck1.Empty() {
|
||||
return 2
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
type Deck struct {
|
||||
Player int
|
||||
cards []int
|
||||
}
|
||||
|
||||
func (d *Deck) Add(card ...int) {
|
||||
d.cards = append(d.cards, card...)
|
||||
}
|
||||
|
||||
func (d *Deck) Draw() int {
|
||||
var ret int
|
||||
ret, d.cards = d.cards[0], d.cards[1:]
|
||||
return ret
|
||||
}
|
||||
|
||||
func (d *Deck) Empty() bool {
|
||||
return len(d.cards) == 0
|
||||
}
|
||||
|
||||
func (d *Deck) Len() int {
|
||||
return len(d.cards)
|
||||
}
|
||||
|
||||
func (d *Deck) Score() int {
|
||||
var ret int
|
||||
for k := len(d.cards) - 1; k >= 0; k-- {
|
||||
ret = ret + (d.cards[k] * (len(d.cards) - k))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (d *Deck) Copy(num int) *Deck {
|
||||
ret := Deck{
|
||||
Player: d.Player,
|
||||
}
|
||||
for k := 0; k < num && k < len(d.cards); k++ {
|
||||
ret.Add(d.cards[k])
|
||||
}
|
||||
return &ret
|
||||
|
||||
}
|
||||
|
||||
func (d Deck) String() string {
|
||||
return fmt.Sprintf("Player %d's deck: %v", d.Player, d.cards)
|
||||
}
|
13
2020/day22/testinput
Normal file
13
2020/day22/testinput
Normal file
@ -0,0 +1,13 @@
|
||||
Player 1:
|
||||
9
|
||||
2
|
||||
6
|
||||
3
|
||||
1
|
||||
|
||||
Player 2:
|
||||
5
|
||||
8
|
||||
4
|
||||
7
|
||||
10
|
8
2020/day22/testinput2
Normal file
8
2020/day22/testinput2
Normal file
@ -0,0 +1,8 @@
|
||||
Player 1:
|
||||
43
|
||||
19
|
||||
|
||||
Player 2:
|
||||
2
|
||||
29
|
||||
14
|
Loading…
Reference in New Issue
Block a user