Last active
December 30, 2020 21:45
-
-
Save jreisinger/47998c1d7b1258f8c2b3213f4a8ac1c1 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/* | |
Rball simulates a game of racquetball to find out whether | |
a slightly better player can win significant number of games. | |
*/ | |
package main | |
import ( | |
"flag" | |
"fmt" | |
"math/rand" | |
"time" | |
) | |
var ( | |
probA = flag.Float64("probA", 0.5, "probability player A wins a serve") | |
probB = flag.Float64("probB", 0.5, "probability player B wins a serve") | |
n = flag.Uint("n", 100000, "number of games to simulate") | |
) | |
func init() { | |
rand.Seed(time.Now().UnixNano()) | |
flag.Parse() | |
} | |
func main() { | |
r := new(Results) | |
// Simulate n games. | |
var swapServe bool | |
for i := 1; i <= int(*n); i++ { | |
g := new(Game) | |
g.SimGame(*probA, *probB, swapServe) | |
swapServe = !swapServe | |
r.Update(g) | |
} | |
r.Print() | |
} | |
type Game struct { | |
scoreA int | |
scoreB int | |
} | |
func (g *Game) SimGame(probA, probB float64, swapServe bool) { | |
serving := "A" | |
if swapServe { | |
serving = "B" | |
} | |
for { | |
if isGameOver(g.scoreA, g.scoreB) { | |
return | |
} | |
if serving == "A" { | |
if rand.Float64() < probA { | |
g.scoreA += 1 | |
} else { | |
serving = "B" | |
} | |
} else { | |
if rand.Float64() < probB { | |
g.scoreB += 1 | |
} else { | |
serving = "A" | |
} | |
} | |
} | |
} | |
type Results struct { | |
WinsA int | |
WinsB int | |
} | |
func (r *Results) Update(g *Game) { | |
if g.scoreA > g.scoreB { | |
r.WinsA += 1 | |
} else { | |
r.WinsB += 1 | |
} | |
} | |
func (r *Results) Print() { | |
n := r.WinsA + r.WinsB | |
fmt.Printf("Simulated games: %d\n", n) | |
fmt.Printf("Wins for A: %d (%.2f%%)\n", r.WinsA, percentWon(r.WinsA, n)) | |
fmt.Printf("Wins for B: %d (%.2f%%)\n", r.WinsB, percentWon(r.WinsB, n)) | |
} | |
func isGameOver(scoreA, scoreB int) bool { | |
return scoreA == 15 || scoreB == 15 | |
} | |
func percentWon(wins, total int) float64 { | |
return float64(wins) / float64(total) * 100 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment