抽奖问题分析

时间:2022-05-06
本文章向大家介绍抽奖问题分析,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
普通抽奖问题问题描述

用户随机抽奖,数据如下:

// 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:%vn",n,c)

    }

}

测试结果:

为了验证获奖概率的正确性,循环执行100万次,每个用户获奖的次数基本在20万左右,每个用户的获奖概率相等

c:200102

f:199853

b:198942

a:200395

d: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

总结

解决实际问题,往往都有数学模型去对应,比如抽奖问题,就可以转化为初中所学习的数轴知识,画个草图,简单易理解,也不需要多高深的数学知识

问题本身并不难,重要的是转换思路,将抽象问题简化为具体的数学问题,然后去解决