This is a creation in
Article, where the information may have evolved or changed.
General Lottery question
Problem description
User random draw, data as follows:
// map中,key代表用户名,value代表成用户下单数var users map[string]int64 = map[string]int64{ "a": 10, "b": 6, "c": 3, "d": 12, "f": 1,}
Ideas
Random problem, usually is a random function from a certain range of random extraction of a value, then the value corresponding to the winning user
Here, if we can set a corresponding index for each element in the map, that is, to convert to an array , is it possible to solve the problem?
Code implementation
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}
Unit Test
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) }}
Test results:
In order to verify the correctness of the winning probability, the loop executes 1 million times, each user wins the number basically is about 200,000, each user's winning probability is equal
c:200102f:199853b:198942a:200395d:200704
Weight Draw
Problem Description:
The data structure is consistent with the lottery, but here the probability of winning is proportional to the number of users ' orders.
Ideas
= = or random function to obtain a numerical value, the value corresponding to the user is the award-winning user ; here to achieve the number of orders to the winning probability of the problem, that is, = = order number corresponding to a certain range of random numbers, the larger the number of orders, the larger the range, random chatter in the range of the probability of the greater =
Code implementation
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}
Unit Test
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) }}
Test results:
Loop traversed 1 million times, the number of awards, in proportion to the number of orders of the user
Summarize
solve practical problems, often have a mathematical model to correspond to, such as lottery problems, can be converted to junior high school axis knowledge, draw a sketch, easy to understand, do not need more advanced mathematical knowledge
The problem itself is not difficult, it is important to switch ideas, to simplify the abstract problem into a specific mathematical problems, and then to solve