Created
December 23, 2021 01:34
-
-
Save echojc/e57557e70121917852ef6250c34f8e6c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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