Created
April 23, 2019 04:49
-
-
Save wahyd4/b5b31bd7287198aecc24768ceed93c9c to your computer and use it in GitHub Desktop.
oz-lotto-multiple-goroutine
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
package main | |
import ( | |
"flag" | |
"fmt" | |
"math/rand" | |
"sort" | |
"sync" | |
"time" | |
) | |
// const | |
const ( | |
NumberCount = 7 | |
MaximumResults = 50 | |
Routines = 10 | |
) | |
var ( | |
syncWinners sync.Map | |
signals = make(chan bool, 100) | |
) | |
func main() { | |
timesInput := flag.Int("t", 100000, "an int") | |
flag.Parse() | |
times := *timesInput | |
now := time.Now() | |
startTime := now.Unix() | |
fmt.Printf("Started at %v to run lottery for %v times \n", now, times) | |
for routine := 0; routine < Routines; routine++ { | |
go func() { | |
for i := 0; i < times/Routines; i++ { | |
winner := run() | |
if currentTimes, ok := syncWinners.Load(winner); ok { | |
currentTimesInt := currentTimes.(int) | |
syncWinners.Store(winner, currentTimesInt+1) | |
} else { | |
syncWinners.Store(winner, 1) | |
} | |
} | |
signals <- true | |
}() | |
} | |
routineReturnTimes := 0 | |
for range signals { | |
routineReturnTimes++ | |
fmt.Println(routineReturnTimes) | |
if routineReturnTimes == Routines { | |
close(signals) | |
} | |
} | |
fmt.Printf("Calculation finished at : %v \n", time.Now()) | |
// only print out top numbers | |
type kv struct { | |
Key [NumberCount]int | |
Value int | |
} | |
var ss []kv | |
syncWinners.Range(func(key interface{}, value interface{}) bool { | |
winningTimes := value.(int) | |
winningNumber := key.([7]int) | |
if winningTimes > 1 { | |
ss = append(ss, kv{winningNumber, winningTimes}) | |
} | |
return true | |
}) | |
sort.Slice(ss, func(i, j int) bool { | |
return ss[i].Value > ss[j].Value | |
}) | |
fmt.Printf("Sorting finished at : %v \n", time.Now()) | |
index := 0 | |
for _, kv := range ss { | |
// only pick the top numbers | |
if index > MaximumResults { | |
break | |
} | |
fmt.Printf("%v, %d \n", kv.Key, kv.Value) | |
index++ | |
} | |
fmt.Printf("The process takes about: %v seconds", time.Now().Unix()-startTime) | |
} | |
func run() [7]int { | |
var winNumbers []int | |
// generate the randomised numbers | |
list := rand.Perm(45) | |
// because perm generate [0,45) but we need [1,45] | |
for index, item := range list { | |
list[index] = item + 1 | |
} | |
rand.Seed(time.Now().UnixNano()) | |
indexes := make([]int, 0) | |
for i := 0; i < NumberCount; i++ { | |
pickedIndex := pickIndex(indexes, len(list)) | |
indexes = append(indexes, pickedIndex) | |
//pick random number | |
chosen := list[pickedIndex] | |
winNumbers = append(winNumbers, chosen) | |
} | |
sort.Ints(winNumbers) | |
var arr [NumberCount]int | |
copy(arr[:], winNumbers) | |
return arr | |
} | |
func pickIndex(indexes []int, length int) int { | |
chosen := rand.Intn(length - 1) | |
// make sure the index only exist once | |
for _, value := range indexes { | |
if value == chosen { | |
return pickIndex(indexes, length) | |
} | |
} | |
return chosen | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment