From 44fb58ff14ec3801372cf0b7a8aa7e43ca683e1d Mon Sep 17 00:00:00 2001 From: David Ashby Date: Tue, 22 Dec 2020 16:58:21 -0500 Subject: [PATCH] 22 done --- 22/main.go | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 22/main.go diff --git a/22/main.go b/22/main.go new file mode 100644 index 0000000..e57cc0b --- /dev/null +++ b/22/main.go @@ -0,0 +1,155 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "time" +) + +func main() { + start := time.Now() + partOne() + duration := time.Since(start) + partTwo() + duration2 := time.Since(start) + fmt.Printf("p1: %s, p2: %s\n", duration, duration2-duration) +} + +type deck struct { + cards []int +} + +type cacheKey struct { + one int + two int +} + +func countWinningDeck(deck []int) int { + sum := 0 + for i := range deck { + sum = sum + ((len(deck) - i) * deck[i]) + } + return sum +} + +// return values is who won/their score: true for player one, false for player two +func playCombat(one, two []int) (bool, int) { + round := 0 + for len(one) > 0 && len(two) > 0 { + round = round + 1 + if one[0] > two[0] { + one = append(one[1:], one[0], two[0]) + two = two[1:] + } else if one[0] < two[0] { + two = append(two[1:], two[0], one[0]) + one = one[1:] + } + } + if len(one) == 0 { + return false, countWinningDeck(two) + } + return true, countWinningDeck(one) +} + +func playRecursiveCombat(one, two []int) (bool, int) { + loopCache := make(map[cacheKey]bool, 0) + round := 0 + for len(one) > 0 && len(two) > 0 { + // check for loops + if loopCache[cacheKey{one: countWinningDeck(one), two: countWinningDeck(two)}] { + return true, countWinningDeck(one) + } + loopCache[cacheKey{one: countWinningDeck(one), two: countWinningDeck(two)}] = true + + // otherwise, play a round + round = round + 1 + if len(one[1:]) >= one[0] && len(two[1:]) >= two[0] { + // fuckin' go slice internals + subDeckOne := make([]int, len(one)) + subDeckTwo := make([]int, len(two)) + copy(subDeckOne, one) + copy(subDeckTwo, two) + winner, _ := playRecursiveCombat(subDeckOne[1:one[0]+1], subDeckTwo[1:two[0]+1]) + if winner { // p1 wins + one = append(one[1:], one[0], two[0]) + two = two[1:] + } else { // p2 wins + two = append(two[1:], two[0], one[0]) + one = one[1:] + } + } else if one[0] > two[0] { + one = append(one[1:], one[0], two[0]) + two = two[1:] + } else if one[0] < two[0] { + two = append(two[1:], two[0], one[0]) + one = one[1:] + } + } + if len(one) == 0 { + return false, countWinningDeck(two) + } + return true, countWinningDeck(one) +} + +func partOne() { + f, _ := os.Open("input") + reader := bufio.NewReader(f) + scanner := bufio.NewScanner(reader) + + // deal the decks + playerone := deck{} + for scanner.Scan() { + line := scanner.Text() + if line == "" { + break + } + i, err := strconv.Atoi(line) + if err == nil { + playerone.cards = append(playerone.cards, i) + } + } + playertwo := deck{} + for scanner.Scan() { + line := scanner.Text() + i, err := strconv.Atoi(line) + if err == nil { + playertwo.cards = append(playertwo.cards, i) + } + } + + // play a game and determine a winner + _, score := playCombat(playerone.cards, playertwo.cards) + fmt.Println(score) +} + +func partTwo() { + f, _ := os.Open("testinput") + reader := bufio.NewReader(f) + scanner := bufio.NewScanner(reader) + + // deal the decks + playerone := deck{} + for scanner.Scan() { + line := scanner.Text() + if line == "" { + break + } + i, err := strconv.Atoi(line) + if err == nil { + playerone.cards = append(playerone.cards, i) + } + } + playertwo := deck{} + for scanner.Scan() { + line := scanner.Text() + i, err := strconv.Atoi(line) + if err == nil { + playertwo.cards = append(playertwo.cards, i) + } + } + + _, score := playRecursiveCombat(playerone.cards, playertwo.cards) + fmt.Println(score) +}