1
2
3
4
5 package main
6
7 import (
8 "fmt"
9 "math/rand"
10 )
11
12 const (
13 win = 100
14 gamesPerSeries = 10
15 )
16
17
18
19 type score struct {
20 player, opponent, thisTurn int
21 }
22
23
24 type action func(current score) (result score, turnIsOver bool)
25
26
27
28
29 func roll(s score) (score, bool) {
30 outcome := rand.Intn(6) + 1
31 if outcome == 1 {
32 return score{s.opponent, s.player, 0}, true
33 }
34 return score{s.player, s.opponent, outcome + s.thisTurn}, false
35 }
36
37
38
39 func stay(s score) (score, bool) {
40 return score{s.opponent, s.player + s.thisTurn, 0}, true
41 }
42
43
44 type strategy func(score) action
45
46
47 func stayAtK(k int) strategy {
48 return func(s score) action {
49 if s.thisTurn >= k {
50 return stay
51 }
52 return roll
53 }
54 }
55
56
57 func play(strategy0, strategy1 strategy) int {
58 strategies := []strategy{strategy0, strategy1}
59 var s score
60 var turnIsOver bool
61 currentPlayer := rand.Intn(2)
62 for s.player+s.thisTurn < win {
63 action := strategies[currentPlayer](s)
64 s, turnIsOver = action(s)
65 if turnIsOver {
66 currentPlayer = (currentPlayer + 1) % 2
67 }
68 }
69 return currentPlayer
70 }
71
72
73 func roundRobin(strategies []strategy) ([]int, int) {
74 wins := make([]int, len(strategies))
75 for i := 0; i < len(strategies); i++ {
76 for j := i + 1; j < len(strategies); j++ {
77 for k := 0; k < gamesPerSeries; k++ {
78 winner := play(strategies[i], strategies[j])
79 if winner == 0 {
80 wins[i]++
81 } else {
82 wins[j]++
83 }
84 }
85 }
86 }
87 gamesPerStrategy := gamesPerSeries * (len(strategies) - 1)
88 return wins, gamesPerStrategy
89 }
90
91
92
93
94 func ratioString(vals ...int) string {
95 total := 0
96 for _, val := range vals {
97 total += val
98 }
99 s := ""
100 for _, val := range vals {
101 if s != "" {
102 s += ", "
103 }
104 pct := 100 * float64(val) / float64(total)
105 s += fmt.Sprintf("%d/%d (%0.1f%%)", val, total, pct)
106 }
107 return s
108 }
109
110 func main() {
111 strategies := make([]strategy, win)
112 for k := range strategies {
113 strategies[k] = stayAtK(k + 1)
114 }
115 wins, games := roundRobin(strategies)
116
117 for k := range strategies {
118 fmt.Printf("Wins, losses staying at k =% 4d: %s\n",
119 k+1, ratioString(wins[k], games-wins[k]))
120 }
121 }
122
View as plain text