瓜分游戏币,红包拆分正态分布

2024-01-14 20:59

本文主要是介绍瓜分游戏币,红包拆分正态分布,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

背景

需要做一个给每个人参加活动的人瓜分固定奖池的游戏币,有平均瓜分和随机分2种分配方案。

平均瓜分

平均分很简单,就是总money/总person取整数就行,无论整除不整除,不整除有结余也无所谓。

随机瓜分

需求详情

根据一个时间段的参与人数设置一个总游戏币数,所有人进行瓜分,每个人最少获得一个币,同时可以无限次重新随机计算,计算出来的列表进行分页展示,而且支持对单个人获得币进行修改,然后统一生成奖励。

思路

  1. 可以多次进行重新随机计算,所以不能直接将计算的结果持久化,防止大量操作删表新增操作,所以先保存数据到redis中做缓存
  2. 在缓存中需要做分页查询,类似查询榜单,list,zset类型可实现分页查询,不需要每次查询都将所有数据拉出来进行分页筛选,zset占用空间大,而且也不需要格外的value做实时排列。所以暂时选用list做存储类型
  3. 缓存中需要保存用户与随机得到的游戏币的对应,选用person+分隔符+币 的String拼接实现
  4. 需要针对一个用户获得币进行修改,list类型可根据下标索引进行修改,可支持
  5. 计算出来后,每个用户对应一个随机游戏币,需要按币的大小进行排序,存入redis,重写list,String排序实现

代码实现

涉及的redis操作(简化)

jedis.lpush(key,value); //存放key,value value是可变类型,LPUSH mylist a b c
jedis.lrange(key, startNumber, endNumber);//查询
jedis.lset(key,index,value); //根据index进行修改
jedis.lindex(key, index); //根据当前index获取list中的值
随机算法工具类
  1. 模拟微信红包算法(简单实现)
    1. 每个人最少得到1游戏币,所以先给每个人分配一个游戏币,保证在随机下每个人所得不为0

    2. 随机每个人所得范围在(0-money / people * 2)

    3. 同时利用Random产生的随机数固定种子下产生的随机序列数相同来排查记录。

    4. 当前利用微信抢红包不需要一次性将整个分布计算下来,可以在每个人领红包的时候再进行计算

    5. 利用excel工具直观查看随机数分布是否满足预想在这里插入图片描述

    6. 废话不多说,贴代码:

@Testpublic void randTestTest(){randTest(1000,100);}public static void randTest(int sum,int count){List<Integer> list = new ArrayList<>();sum = sum-count*1;Random random = new Random();long factor = System.currentTimeMillis();System.out.println("固定种子是:"+factor);random.setSeed(factor);//当random设置相同的种子时,随机序列数相同for(int i = 0;i<count;i++){int rand = rand(sum, count-i, list,random);sum = rand;}int summoneny = 0;int min =list.get(0);int max =-1;for(Integer entry :list){summoneny = summoneny+entry.intValue();min = Math.min(min,entry.intValue());max = Math.max(max,entry.intValue());}System.out.println(list.toString());System.out.println(min);System.out.println(max);}/**** @param money 剩余的钱* @param people 剩余的人数* @param l   红包列表* @return*/public static int rand(int money, int people, List<Integer> l ,Random random) {if (people == 1) {int red = money;l.add(red+1);return 0;}int min = 0;int max = money / people * 2;int red = random.nextInt(max);red = red <= min ? min : red;l.add(red+1);int remain = money-red;return remain;}
  1. 以上思想是每个人口袋能得到多少游戏币,随机在奖池中取钱。现我们转变一下思想,利用游戏币找口袋,游戏币随机落入口袋。
    1. 分布图展示,看起来后者分布更加均匀在这里插入图片描述

    2. 利用钱找人,有可能一个人没有被找过一次,当然可以先给每个人先分一个游戏币,然后剩下的币找人,上代码

 @Testpublic void rand1Test(){Random random = new Random();long factor = System.currentTimeMillis();System.out.println("固定种子是:"+factor);random.setSeed(factor);//当random设置相同的种子时,随机序列数相同int[] ints = rand1(1000, 100, random);int a = 0;int min =ints[0];int max =-1;for (int integer : ints) {a+=integer;min = Math.min(min,integer);max = Math.max(max,integer);}System.out.println(Arrays.toString(ints));System.out.println(a);System.out.println(min);System.out.println(max);}/**** @param money 总钱* @param count 剩余的人数* @return*/public int[] rand1(int money, int count ,Random random) {int[] nums = new int[count];for(int i= 0;i<money;i++){int person = random.nextInt(count);nums[person] +=1;}return nums;}
重写排序工具类
 public static void sortListString(List list){System.out.println("排序前:"+list.toString());Collections.sort(list, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return Integer.valueOf(o1.substring(o1.indexOf(":")+1,o1.length())).compareTo(Integer.valueOf((o2.substring(o2.indexOf(":")+1,o2.length()))));}});System.out.println("排序后:"+list.toString());}

总结

  1. 整个过程也看过网上很多介绍正态分布的算法,还有网上各位大神的分析与实现,以上是一个简单的实现同时也很好的契合要求,故实现如此,作此记录。
  2. 在redis的操作文档中只发现如下的存储方式,RPUSH mylist a b c,所以选择String作为载体进行存储,当然可以选择list中保存可序列化对象,将对象序列化后再保存到redis中,可以添加更多的属性。由于时间问题并未依此方案实现。

这篇关于瓜分游戏币,红包拆分正态分布的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/606498

相关文章

隐私计算实训营:SplitRec:当拆分学习遇上推荐系统

拆分学习的概念 拆分学习的核心思想是拆分网络结构。每一个参与方拥有模型结构的一部分,所有参与方的模型合在一起形成一个完整的模型。训练过程中,不同参与方只对本地模型进行正向或者反向传播计算,并将计算结果传递给下一个参与方。多个参与方通过联合模型进行训练直至最终收敛。 一个典型的拆分学习例子: Alice持有数据和基础模型。Bob只有数据、基础模型和fuse模型。 Alice使用自己的数据

动态规划---单词拆分

题目: 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。如果可以利用字典中出现的一个或多个单词拼接出 s 则返回 true。 注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。 思路:本题属于完全背包问题,字符串s的长度为背包容量,字符串列表wordDict中的每一个元素相当于物品。 动态规划五部曲: 1.确定dp数组及含义 dp数组为元素类型是布

AI艺术创作福利:免费领取红包封面,Meo喵、龙小金与你共庆佳节!

🎉🐉🐱 亲爱的朋友们,佳节将至,北京时间24年9月6日18:00,我们通过Midjourney的AI艺术创作和ComfyUI设计,特别为大家准备了一份特别的礼物——1588个独家设计的微信红包封面!欢迎关注我们网站的动态,福利不定时发放,🧧🎁红包封面如下: 🌟红包封面特色 我们的红包封面设计融合了现代科技与传统文化,龙小金与Meo喵的形象通过Midjourney的AI艺术创作和

拼手气红包如何设计?

微信是我们日常生活中必不可少的聊天工具,里面的红包功能我们也经常使用,其中,拼手气红包有时候可以抢到很大,有时候就只有0.01,那这个功能应该是如何实现的呢? 红包的分配需要遵循几个规则: 所有人抢到的红包金额之和要等于总金额,不能多也不能少最低红包金额是一分钱保证所有人抢到的红包金额随机 一. 随机算法 先将总金额减去每个红包的最低金额一分钱,在0~剩余金额中取随机数,加上一分钱就是第一

代码随想录:343. 整数拆分

343. 整数拆分   class Solution {public:int integerBreak(int n) {int dp[100]={0};//拆分i的最大乘积为dp[i]dp[1]=1;//初始化,主要是为了dp[2]初始for(int i=2;i<=n;i++){for(int j=1;j<i;j++){ dp[i]=max(dp[i],max(j,dp[j])*ma

双十一红包

天猫双十一红包 http://s.click.taobao.com/JVTnXQx 红包名称: 双11红包 红包面额: 双11红包:1元、2元、5元、1111元;双11购物券:10元 领用起止时间: 2016年10月21日00:00:00 至 2016年11月10日23:00:00 红包使用时间: 2016年11月11日00:00:00 至 2016年1

【动态规划】343. 整数拆分

力扣链接:343. 整数拆分 - 力扣(LeetCode) dp数组的含义:dp[i]表示对i拆分,得到最大的积为dp[i] 递推公式:拆成两个数是 j*(i-j),拆成三个及以上是 j*dp[i-j],所以递推公式取两者大值 遍历顺序:从小到大 public int integerBreak(int n) {int[] dp = new int[n+1];dp[1]=0;dp[2]=

为什么在很多应用中常采用正态分布/高斯分布、中心极限定理

为什么在很多应用中常采用正态分布/高斯分布? 当我们由于缺乏关于某个实数上分布的先验知识而不知道该选择怎么样的形式时,正态分布是默认的比较好的选择,有两个原因: 一,我们想要建模的很多分布的真实情况是比较接近正态分布的。 中心极限定理说明很多独立随机变量的和近似服从正态分布。 二,在具有相同方差的所有可能的概率分布中,正态分布在实数上具有最大的不确定性。 因此,我们可以认为正态分布是对模型加入的

2157. 优秀的拆分(power)

代码 #include<bits/stdc++.h>using namespace std;int a[10001];int main(){int n,t=1,k=0;bool flag=false;cin>>n;if(n%2==1) {cout<<-1;return 0;}while(n>0){if(n%2==1){k++;a[k]=t; }n=n/2;t=t*2;}if(k

2014年2月17日 微信红包

大年三十晚上1月30号开始发布微信红包,一共有500W用户抢红包,总金额大约2.4亿 而之前支付宝也推出过一个抢红包的应用,但是总金额只有1800W 微信之后联合嘀嘀打车,开始竞争打车市场,每个用户补贴10元,每个师傅补贴10元,总投资2亿 之后支付宝坐不住了,投资5亿,开始和微信竞争 他们的这种竞争慢慢的进入了线下交易市场 以后,我们的衣食住行可能都会使用微信支付,或者支付宝支付,手机支