diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 75c643d..5b1d307 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -11,8 +11,11 @@ + + + - + - + @@ -184,6 +187,16 @@ + + + + + + + + + + @@ -287,6 +300,7 @@ + @@ -311,39 +325,59 @@ - + - + + + + + - + - - + + - - + + - - + + - + + + + + + + + + + + + + + + + + @@ -364,9 +398,20 @@ - + - + + + + + + + file://$PROJECT_DIR$/day22/day22.go + 115 + + + \ No newline at end of file diff --git a/day22/day22.go b/day22/day22.go new file mode 100644 index 0000000..98ff758 --- /dev/null +++ b/day22/day22.go @@ -0,0 +1,180 @@ +package main + +import ( + "AoC2020/helper" + "fmt" + "os" + "sort" + "strconv" + "strings" +) + +type Player struct { + deck []int + previousDecks [][]int +} + +type Game struct { + players [2]Player + winner int +} + +var lineBreak = "\n" + +func main() { + game := Game{} + args := os.Args[1:] + input, err := helper.GetFile(args[0]) + if err != nil { + fmt.Println(err) + } + playerInput := strings.Split(input, lineBreak+lineBreak) + player1 := parsePlayer(playerInput[0]) + player2 := parsePlayer(playerInput[1]) + game.players[0] = player1 + game.players[1] = player2 + for game.winner == 0 { + game = game.runRoundRecursive() + fmt.Println(game.players[0]) + fmt.Println(game.players[1]) + } + fmt.Println(game.winner) + fmt.Println(game.players[game.winner-1].deck) + fmt.Println(game.caculateWinnerScore()) +} + +func parsePlayer(input string) Player { + var player = Player{} + playerInput := strings.Split(input, lineBreak) + for _, val := range playerInput[1:] { + number, _ := strconv.Atoi(val) + player.deck = append(player.deck, number) + } + return player +} + +func (g Game) runRound() Game { + g = g.saveCurrentDeck() + var cardP0 int + var cardP1 int + g.players[0], cardP0 = g.players[0].drawCard() + g.players[1], cardP1 = g.players[1].drawCard() + winnerCards := []int{cardP0, cardP1} + sort.Sort(sort.Reverse(sort.IntSlice(winnerCards))) + if cardP0 > cardP1 { + g.players[0] = g.players[0].addToDeck(winnerCards) + } + if cardP1 > cardP0 { + g.players[1] = g.players[1].addToDeck(winnerCards) + } + if len(g.players[0].deck) == 0 { + g.winner = 2 + } + if len(g.players[1].deck) == 0 { + g.winner = 1 + } + return g +} + +func (g Game) caculateWinnerScore() int { + winnerDeck := g.players[g.winner-1].deck + return calculateScoreForDeck(winnerDeck) +} + +func calculateScoreForDeck(deck []int) int { + deckLen := len(deck) + sum := 0 + for i := 0; i < deckLen; i++ { + sum += deck[i] * (deckLen - i) + } + return sum +} + +func (g Game) saveCurrentDeck() Game { + for i, _ := range g.players { + g.players[i] = g.players[i].saveCurrentDeck() + } + return g +} + +func (g Game) runRoundRecursive() Game { + p1 := g.players[0] + p2 := g.players[1] + for i, _ := range p1.previousDecks { + if helper.Equal(p1.previousDecks[i], p1.deck) && helper.Equal(p2.previousDecks[i], p2.deck) { + g.winner = 1 + return g + } + } + var roundWinner int + p1 = p1.saveCurrentDeck() + p2 = p2.saveCurrentDeck() + var cardP1 int + var cardP2 int + p1, cardP1 = p1.drawCard() + p2, cardP2 = p2.drawCard() + if len(p1.deck) >= cardP1 && len(p2.deck) >= cardP2 { + var newGame Game + var newPlayer1 Player + var newPlayer2 Player + newPlayer1.deck = make([]int, cardP1) + newPlayer2.deck = make([]int, cardP2) + copy(newPlayer1.deck, p1.deck[:cardP1]) + copy(newPlayer2.deck, p2.deck[:cardP2]) + newGame.players = [2]Player{newPlayer1, newPlayer2} + roundWinner = newGame.runRecursive().winner + } else { + if cardP1 > cardP2 { + roundWinner = 1 + } + if cardP2 > cardP1 { + roundWinner = 2 + } + } + if roundWinner == 1 { + p1 = p1.addToDeck([]int{cardP1, cardP2}) + } + if roundWinner == 2 { + p2 = p2.addToDeck([]int{cardP2, cardP1}) + } + if len(p1.deck) == 0 { + g.winner = 2 + } + if len(p2.deck) == 0 { + g.winner = 1 + } + g.players = [2]Player{p1, p2} + return g +} + +func (g Game) run() Game { + for g.winner == 0 { + g = g.runRound() + } + return g +} + +func (g Game) runRecursive() Game { + for g.winner == 0 { + g = g.runRoundRecursive() + } + return g +} + +func (p Player) drawCard() (Player, int) { + card := p.deck[0] + p.deck = helper.DeleteAt(p.deck, 0) + return p, card +} + +func (p Player) saveCurrentDeck() Player { + copyOfDeck := make([]int, len(p.deck)) + copy(copyOfDeck, p.deck) + p.previousDecks = append(p.previousDecks, copyOfDeck) + return p +} + +func (p Player) addToDeck(cards []int) Player { + p.deck = append(p.deck, cards...) + return p +} diff --git a/day22/day22Input.txt b/day22/day22Input.txt new file mode 100644 index 0000000..960bb35 --- /dev/null +++ b/day22/day22Input.txt @@ -0,0 +1,53 @@ +Player 1: +26 +16 +33 +8 +5 +46 +12 +47 +39 +27 +50 +10 +34 +20 +23 +11 +43 +14 +18 +1 +48 +28 +31 +38 +41 + +Player 2: +45 +7 +9 +4 +15 +19 +49 +3 +36 +25 +24 +2 +21 +37 +35 +44 +29 +13 +32 +22 +17 +30 +42 +40 +6 \ No newline at end of file diff --git a/day22/day22Test.txt b/day22/day22Test.txt new file mode 100644 index 0000000..24d78bf --- /dev/null +++ b/day22/day22Test.txt @@ -0,0 +1,13 @@ +Player 1: +9 +2 +6 +3 +1 + +Player 2: +5 +8 +4 +7 +10 \ No newline at end of file diff --git a/day22/day22Test2.txt b/day22/day22Test2.txt new file mode 100644 index 0000000..dce7e1a --- /dev/null +++ b/day22/day22Test2.txt @@ -0,0 +1,8 @@ +Player 1: +43 +19 + +Player 2: +2 +29 +14 \ No newline at end of file diff --git a/helper/helper.go b/helper/helper.go index 0e2eee0..4767ea1 100644 --- a/helper/helper.go +++ b/helper/helper.go @@ -37,9 +37,9 @@ func MapToNumber(strings []string) ([]int, error) { return numbers, nil } -func FindAddendsForSum (possibleAddends []int, sum int) (int, int, error) { - var array = make([]int,len(possibleAddends)) - copy(array,possibleAddends) +func FindAddendsForSum(possibleAddends []int, sum int) (int, int, error) { + var array = make([]int, len(possibleAddends)) + copy(array, possibleAddends) sort.Ints(array) p1 := 0 p2 := len(array) - 1 @@ -51,10 +51,10 @@ func FindAddendsForSum (possibleAddends []int, sum int) (int, int, error) { p2-- } if array[p1]+array[p2] == sum { - return array[p1] , array[p2], nil + return array[p1], array[p2], nil } } - return 0,0,errors.New("No fitting Addends found") + return 0, 0, errors.New("No fitting Addends found") } func SliceIndex(limit int, predicate func(i int) bool) int { @@ -64,4 +64,20 @@ func SliceIndex(limit int, predicate func(i int) bool) int { } } return -1 -} \ No newline at end of file +} + +func DeleteAt(a []int, i int, ) []int { + return append(a[:i], a[i+1:]...) +} + +func Equal(a, b []int) bool { + if len(a) != len(b) { + return false + } + for i, v := range a { + if v != b[i] { + return false + } + } + return true +}