這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
普通抽獎問題
問題描述
使用者隨機抽獎,資料如下:
// map中,key代表使用者名稱,value代表成使用者下單數var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "f": 1,}
思路
隨機問題,一般就是通過隨機函數從某個範圍內隨機取出某個數值,則該數值對應的就是中獎使用者
在這裡,如果我們能給map中每個元素設定對應的索引,即轉化為數組,是不是就可以解決問題了呢?
代碼實現
func GetAwardUserName(users map[string]int64) (name string) { size := len(users) awardIndex := rand.Intn(size) i := 0 for userName, _ := range users { if i == awardIndex { name = userName return } i++ } return}
單元測試
func Test_GetAwardUserName(t *testing.T) { var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "f": 1, } rand.Seed(time.Now().Unix()) awardCount := make(map[string]int) for i := 0; i <= 1000000; i++ { awardName := GetAwardUserName(users) if count, ok := awardCount[awardName]; ok { awardCount[awardName] = count + 1 } else { awardCount[awardName] = 0 } } for n, c := range awardCount { fmt.Printf("%v:%v\n",n,c) }}
測試結果:
為了驗證獲獎機率的正確性,迴圈執行100萬次,每個使用者獲獎的次數基本在20萬左右,每個使用者的獲獎機率相等
c:200102f:199853b:198942a:200395d:200704
權重抽獎
問題描述:
資料結構和上面抽獎問題一致,只是這裡,要求中獎機率和使用者的訂單數成正比
思路
==本質==還是隨機函數獲得一個數值,數值對應的使用者即獲獎使用者;這裡要實現訂單數對獲獎機率的影響問題,即==訂單數對應隨機數的某個範圍,訂單數越大,範圍越大,隨機數落在範圍內的機率越大==
代碼實現
func getAwardUser_weight(users map[string]int64) (name string) { type awardUser struct { name string offset int64 count int64 } userSli := make([]*awardUser, 0,len(users)) var sumCount int64 = 0 for n, c := range users { a := awardUser{ name: n, offset: sumCount, count: c, } //整理所有使用者的count資料為數軸 userSli = append(userSli, &a) sumCount += c } awardIndex := rand.Int63n(sumCount) for _, u := range userSli { //判斷獲獎index落在那個使用者區間內 if u.offset+u.count>awardIndex { name = u.name return } } return}
單元測試
func Test_getAwardUser_weight(t *testing.T) { var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "f": 1, } rand.Seed(time.Now().Unix()) awardCount := make(map[string]int) for i := 0; i <= 100000; i++ { awardName := getAwardUser_weight(users) if count, ok := awardCount[awardName]; ok { awardCount[awardName] = count + 1 } else { awardCount[awardName] = 0 } } for n,c := range awardCount { fmt.Printf("%v:%v \n",n,c) }}
測試結果:
迴圈遍曆了100萬次,獲獎的次數,與使用者的訂單數成正比
c:93479 f:31206 d:375614 b:186933 a:312764
總結
解決實際問題,往往都有數學模型去對應,比如抽獎問題,就可以轉化為初中所學習的數軸知識,畫個草圖,簡單易理解,也不需要多高深的數學知識
問題本身並不難,重要的是轉換思路,將抽象問題簡化為具體的數學問題,然後去解決