BitTigerio 2018-02-05
辛苦工作一年,大大小小的公司或单位组织都会搞一个年会。年会少不了抽奖,每个人都期待自己是抽中一等奖,然而现实是残酷的,我今年也没抽中,毛都没中一根。这是为什么呢?我们就来聊聊抽奖算法的那些事。年会抽奖,按照形式,可以分为实物抓阄和程序随机算法。
这个大家都知道,搞一个抽奖箱,每个人入场的时候把自己的名字写在纸条上,折起来,投入箱子里就可以。接下来你的命运就掌握在上台抽奖的领导大佬们的手上了。抽奖必定是先从最差的末等奖开始抽,有些公司或单位组织是5等奖,有些直接三等奖,没办法,得留意预算。这种抽奖的情况,如果主持人不摇一摇,并且排除领导同志喜欢海底捞的癖好,那么越靠后投进箱子的朋友越容易被抽中。可是也别靠太后。我知道你们又想被抽中,又不想被早点抽中。如果三等奖就是一张电影券,你若被抽中,那还不如拿个杨光普照。反过来想想,如果一家公司三等奖是一张电影票,你等到一等奖,也不会有什么期待,或许是一把牙刷雷死你不偿命。
另外一种形式,那就是程序抓阄了。程序抓阄,就是通过编写一个电子抽奖程序,实现一个随机算法,以科学的手段来抽奖。高大上的名字,有种科学算命的感觉。我们排除一下程序员主观意愿的作弊行为,来思考一下他们写的随机算法到底公平不公平。一般电子抽奖的流程是,让领导喊开始,随便过一段时间后,领导再喊停。在这个过程中,程序只有这两个输入控制命令。并且,为了效果,一般都会在大屏幕随机滚动一下各位参加抽奖同事们的头像或名字什么的。这里就有两个问题,滚动过程中,到底选哪些头像上大屏幕滚动?滚动结束后,如何随机抽取n(n>1)个中奖者,从哪里抽?
假设参与抽奖者有大概1000名。每次大屏幕只能显示顶多9名(九宫格,好看)。
按照参与者签到先来后到的顺序排序,每次从前面按顺序提取9名同事上墙。直到大佬喊停。这下好了。想露脸的同事们,赶紧早点去年会现场签到吧。如果去晚了,就石沉大海,杳无音讯了。这样写的程序员肯定是在想,1000名一次从数据库中读取出来,怕性能有问题,或者将就之前写好的一个分页接口,正好在这里派上了用场。
他会用点心思想想什么叫公平。为了省下那一点点性能,在抽奖前一次读取所有1000名同事的头像信息,以空间换取时间嘛。然后调用随机数函数9次,按照9个随机数的结果从集合里抽取。抽取完后从集合中剔除,重新排序,总数作为下一次的随机范围,直到大佬喊停。如果轮完一圈了,大佬玩心大起,还未喊停。那就把剔除的同事再次放入集合中,类似扑克洗牌。这里的随机函数稍微懂程序的朋友们,也就是利用了一些系统自带的,比如javascript
的random
。这个好像稍微公平点吧?
当大佬终于喊停的时候,就开始启动抽奖随机算法,选择中奖者了。虽然你上墙了,但是没有被抽中,那有个屁用。所以关键还是要看看程序员是如何实现抽奖算法的。即使没上墙,也不必气馁,有机会,就看你碰上了什么样的程序员。
从前面上墙的参与者里选择n个中奖者,n必须小于上墙者总数。碰上这样的,还是那句话,叫你们早点去年会现场,这下吃亏了吧?另外,有些领导就喜欢一开始就喊停,那大屏幕都还没滚动一屏,所以,你更应该早点去现场了。
首先他明白,待抽奖的集合千万不能只从上墙集合里抽取,那个仅仅是一个噱头,类似篮球比赛暂停期间的拉拉队表演而已。你见过有从啦啦队成员里选择一个MVP吗?所以,样本空间还是1000个参与者。其实也很简单,利用系统随机数,从1000范围内抽取n个序号,按照序号找到中奖者就可以了。这样一来,甭管你是早来,还是晚来,都没关系了。
前面说过,抽奖都是一轮一轮的抽的。所以,最起码,肯定要保证每抽完一轮,就要将这些中奖者从参与者中剔除。否则一个人运气爆棚,祖坟冒青烟把所有奖都拿了,你们可别怪他作弊。
这个我就不好多做论述了,个人能力有限,有兴趣的朋友们,可以去google一下,看看那个random方法,到底是怎么返回一个随机数字的,它到底公平不公平。如果查到了的话,记得来这里评论留言分享哦。
最后,祝兄弟姐妹们年会中大奖,千万别碰到倒霉催的程序员和没领证的程序员。