1package main23import (4 "fmt"5 "math/rand"6 "os"7 "runtime"8 "strconv"9)1011type simulationOutput struct {12 each int13 num int6414}1516func simulateOnce(each int, r *rand.Rand) int {17 nWhite := each18 nRed := each1920 for i := 0; i < 19; i++ {21 if r.Intn(nWhite+nRed)+1 > nWhite {22 nRed--23 } else {24 nWhite--25 }26 }2728 // pickedWhite - pickedRed == (each - nWhite) - (each - nRed) == nRed - nWhite29 return nRed - nWhite30}3132func simulateNTimes(each, n int, r *rand.Rand) int64 {33 var count int64 = 034 for i := 0; i < n; i++ {35 if simulateOnce(each, r) == 3 {36 count++37 }38 }3940 return count41}4243func worker(workCh chan int, outCh chan simulationOutput, iters int) {44 r := rand.New(rand.NewSource(rand.Int63()))45 for each := range workCh {46 outCh <- simulationOutput{47 each: each,48 num: simulateNTimes(each, iters, r),49 }50 }51}5253func main() {54 if len(os.Args) != 3 {55 fmt.Println("usage: count <MAX_BALLS> <ITERS>")56 os.Exit(1)57 }5859 maxBalls, err := strconv.Atoi(os.Args[1])60 if err != nil {61 fmt.Printf("Unable to convert %q to an int\n", os.Args[1])62 os.Exit(1)63 }6465 iters, err := strconv.Atoi(os.Args[2])66 if err != nil {67 fmt.Printf("Unable to convert %q to an int\n", os.Args[2])68 os.Exit(1)69 }7071 workCh := make(chan int)72 outCh := make(chan simulationOutput)7374 for i := 0; i < runtime.NumCPU(); i++ {75 go worker(workCh, outCh, iters)76 }7778 go func() {79 for i := 11; i <= maxBalls; i++ {80 workCh <- i81 }8283 close(workCh)84 }()8586 for i := 11; i <= maxBalls; i++ {87 out := <-outCh88 fmt.Printf("%d %d\n", out.each, out.num)89 }9091 close(outCh)92}