Skip to content

Instantly share code, notes, and snippets.

@echojc
Created December 23, 2021 01:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save echojc/e57557e70121917852ef6250c34f8e6c to your computer and use it in GitHub Desktop.
Save echojc/e57557e70121917852ef6250c34f8e6c to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
)
func main() {
p1, p2 := 4, 8
p1Score, p2Score := 0, 0
d := &D100{}
scores := []int{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}
for {
p1 = (p1 + d.Roll() + d.Roll() + d.Roll()) % 10
p1Score += scores[p1]
if p1Score >= 1000 {
fmt.Println("Part 1:", p2Score*d.count,
"(", p1Score, p2Score, d.count, ")")
break
}
p2 = (p2 + d.Roll() + d.Roll() + d.Roll()) % 10
p2Score += scores[p2]
if p2Score >= 1000 {
fmt.Println("Part 1:", p1Score*d.count,
"(", p1Score, p2Score, d.count, ")")
break
}
}
games := genGames(4, 8)
wins := []int64{0, 0}
last := 0
for {
result, ok := <-games
if !ok {
break
}
if result.s1 > result.s2 {
wins[0] += countGames(result.turns)
} else {
wins[1] += countGames(result.turns)
}
if result.turns[0] != last {
last = result.turns[0]
fmt.Println(">", result)
}
}
if wins[0] > wins[1] {
fmt.Println("Part 2:", wins[0], "( >", wins[1], ")")
} else {
fmt.Println("Part 2:", wins[1], "( >", wins[0], ")")
}
}
type Result struct {
turns []int
s1, s2 int
}
func genGames(p1, p2 int) chan Result {
c := make(chan Result)
var gen func(in []int)
gen = func(in []int) {
for i := 3; i <= 9; i++ {
// duplicate input slice
next := make([]int, len(in)+1)
copy(next, in)
// append the next turn
next[len(in)] = i
// check and output if the game has finished
s1, s2 := scores(p1, p2, next)
if s1 >= 21 || s2 >= 21 {
c <- Result{next, s1, s2}
} else {
// otherwise, recursively generate the next turn
gen(next)
}
}
// close channel if this is the top level to indicate completion
if in == nil {
close(c)
}
}
go gen(nil)
return c
}
/* (0 1 2) 3 4 5 6 7 8 9 */
var multiplier = []int64{0, 0, 0, 1, 3, 6, 7, 6, 3, 1}
func countGames(turns []int) int64 {
var out int64 = 1
for _, i := range turns {
out *= multiplier[i]
}
return out
}
var score = []int{10, 1, 2, 3, 4, 5, 6, 7, 8, 9}
func scores(p1, p2 int, turns []int) (s1 int, s2 int) {
for i := range turns {
switch i % 2 {
case 0: //p1
p1 = (p1 + turns[i]) % 10
s1 += score[p1]
case 1: //p2
p2 = (p2 + turns[i]) % 10
s2 += score[p2]
}
}
return s1, s2
}
type D100 struct {
state int
count int
}
func (d *D100) Roll() int {
d.state++
if d.state == 101 {
d.state = 1
}
d.count++
return d.state
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment