Skip to content

Instantly share code, notes, and snippets.

@wahyd4
Created April 23, 2019 04:49
Show Gist options
  • Save wahyd4/b5b31bd7287198aecc24768ceed93c9c to your computer and use it in GitHub Desktop.
Save wahyd4/b5b31bd7287198aecc24768ceed93c9c to your computer and use it in GitHub Desktop.
oz-lotto-multiple-goroutine
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