js打乱数组的顺序_如何用 js 实现一个类似微信红包的随机算法
如何用 js 实现一个类似微信红包的随机算法
js, 微信红包, 随机算法
"use strict";
/** * * @author xgqfrms * @license MIT * @copyright xgqfrms * @created 2020-09-16 * @modified * * @description 如何用 js 实现一个类似微信红包的随机算法, 最简单的方法实现微信红包的随机算法 * @difficulty Hard * @complexity O(n) * @augments * @example * @link https://www.cnblogs.com/xgqfrms/p/13689802.html * @link https://www.cnblogs.com/xgqfrms/tag/%E7%BA%A2%E5%8C%85/ * @link https://www.zhihu.com/question/22625187/answer/1478941580 * @solutions * */
const log = console.log;
const shuffle = (arr = []) => {let len = arr.length;while (len > 1){const index = Math.floor(Math.random() * len--); [ arr[len], arr[index], ] = [ arr[index], arr[len], ]; }return arr;}
/**算法需要满足条件:1. 每个人都可以分到至少 0.01 元;2. 所有人的分到的红包之和与发出的金额相等,不多不少,刚好分完;3. 每个人分到金额的概率相等;*/
/**假设,发出一个 100元红包,给 10个人分!算法实现:1. 按照人数,生成一个等长的数组,且每一个元素的初始化值为 0.01;✅2. 将剩余的金额(100 - 10 * 0.01), 按照微信设计的规则(假如是正态分布)进行分配出 10 份; ❓3. 将分配好的红包,依次加入到生成的数组中;✅4. 最后使用 shuffle 算法打乱数组,并返回; ✅5. 将计算好的数组,按照抢红包的顺序作为索引值依次取出红包即可.✅*/
// 精度损失解决方案, 扩大后,再还原 ✅?const autoRandomRedPackage = (money, num, limit = 0.01) => {if((money / num) < limit) {// alert log(`? 请重新输入红包数量! 减少红包数量,或增加红包金额!`); log(`❌ 你输入的红包数量太多了,每个人至少要能分到 0.01 元!`);return false; } else {const originMoney = money;const originLimit = limit;let multi = 100 * (100 / money); money *= multi; limit *= multi;// log(`multi =`, multi);const result = [...new Uint8Array(num)].fill(limit, 0, num);// 1. 将剩余的红包,均分✅,如果有余数,随机的添加到数组的一个元素上const restLimit = (money - limit * num) / limit;const reminderLimit = (restLimit % num);const reminderMoney = reminderLimit * limit;const averageLimit = (restLimit - reminderLimit) / num;for (let i = 0; i < num; i++) {const index = parseInt(Math.random() * averageLimit);const randomMoney = index * limit;const leftMoney = (averageLimit - index) * limit;// 2. 在平均后的范围内,计算出一个随机数,将分配好的红包,依次加入到生成的数组中;✅ result[i] += randomMoney;// 3. 分配后剩余的红包,随机加入到生成的数组中;✅const j = parseInt(Math.random() * num); result[j] += leftMoney; }// 4. 将平均后的余数红包,随机加入到生成的数组中;✅if(reminderMoney > 0) {const index = parseInt(Math.random() * num); result[index] += reminderMoney; }const temp = shuffle(result).map(i => i / multi);// log(`temp =`, temp);const total = temp.reduce((acc, i) => acc += i*multi, 0) / multi;// log(`total !== originMoney`, total !== originMoney, total, originMoney);if(total !== originMoney) {return autoRandomRedPackage(originMoney, num, originLimit); }const [min, ...rest1] = temp.sort((a, b) => a - b > 0 ? 1 : -1);const [max, ...rest2] = temp.sort((a, b) => a - b > 0 ? -1 : 1);return {total: total,result: temp,desc: ` ?️♂️ 你输入的红包总额是 ${originMoney} 元, 红包数量是 ${num} 个! ? 最大的红包是 ${max} 元! ? 最小的红包是 ${min} 元! `,// desc: `// ?️♂️ 你输入的红包总额是 ${originMoney} 元, 红包数量是 ${num} 个!\n// ? 最大的红包是 ${max} 元!\n// ? 最小的红包是 ${min} 元!\n// `, };// return temp; }}
const total = arr => arr.result.reduce((acc, i) => acc += i*100, 0) / 100;
// 测试const test = autoRandomRedPackage(0.1, 11);// ❌ 异常处理const test0 = autoRandomRedPackage(0.1, 5);const test1 = autoRandomRedPackage(0.1, 10); // ✅ okconst test2 = autoRandomRedPackage(1, 10);const test3 = autoRandomRedPackage(10, 10);const test4 = autoRandomRedPackage(100, 10);const test5 = autoRandomRedPackage(100, 11);
log(`\ntest =`, test);log(`total =`, test && total(test));
log(`\ntest =`, test0);log(`total =`, test0 && total(test0));
log(`\ntest =`, test1);log(`total =`, test1 && total(test1));
log(`\ntest =`, test2);log(`total =`, test2 && total(test2));
log(`\ntest =`, test3);log(`total =`, test3 && total(test3));
log(`\ntest =`, test4);log(`total =`, test4 && total(test4));
log(`\ntest =`, test5);log(`total =`, test5 && total(test5));
/*$ node node perfect-solution.js? 请重新输入红包数量! 减少红包数量,或增加红包金额!❌ 你输入的红包数量太多了,每个人至少要能分到 0.01 元!test = falsetotal = falsetest = { total: 0.1, result: [ 0.03, 0.03, 0.02, 0.01, 0.01 ], desc: '\n' + ' ?️♂️ 你输入的红包总额是 0.1 元, 红包数量是 5 个!\n' + ' ? 最大的红包是 0.03 元!\n' + ' ? 最小的红包是 0.01 元!\n' + ' '}total = 0.1test = { total: 0.1, result: [ 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01 ], desc: '\n' + ' ?️♂️ 你输入的红包总额是 0.1 元, 红包数量是 10 个!\n' + ' ? 最大的红包是 0.01 元!\n' + ' ? 最小的红包是 0.01 元!\n' + ' '}total = 0.1test = { total: 1, result: [ 0.16, 0.13, 0.13, 0.12, 0.09, 0.08, 0.08, 0.08, 0.07, 0.06 ], desc: '\n' + ' ?️♂️ 你输入的红包总额是 1 元, 红包数量是 10 个!\n' + ' ? 最大的红包是 0.16 元!\n' + ' ? 最小的红包是 0.06 元!\n' + ' '}total = 1test = { total: 10, result: [ 2.43, 1.73, 1.43, 1.36, 1, 0.78, 0.66, 0.28, 0.25, 0.08 ], desc: '\n' + ' ?️♂️ 你输入的红包总额是 10 元, 红包数量是 10 个!\n' + ' ? 最大的红包是 2.43 元!\n' + ' ? 最小的红包是 0.08 元!\n' + ' '}total = 10test = { total: 100, result: [ 23.71, 16.9, 13.24, 12, 10, 8.6, 8.33, 3.6, 1.92, 1.7 ], desc: '\n' + ' ?️♂️ 你输入的红包总额是 100 元, 红包数量是 10 个!\n' + ' ? 最大的红包是 23.71 元!\n' + ' ? 最小的红包是 1.7 元!\n' + ' '}total = 100test = { total: 100, result: [ 17.59, 11.68, 11.55, 10.2, 8.83, 8.81, 8.24, 7.55, 7.44, 6.66, 1.45 ], desc: '\n' + ' ?️♂️ 你输入的红包总额是 100 元, 红包数量是 11 个!\n' + ' ? 最大的红包是 17.59 元!\n' + ' ? 最小的红包是 1.45 元!\n' + ' '}total = 100*/
refs
https://www.cnblogs.com/xgqfrms/tag/红包/
©xgqfrms 2012-2020
www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
xgqfrms
标签: 微信, 随机算法, 红包, js, 微信红包
js打乱数组的顺序_如何用 js 实现一个类似微信红包的随机算法相关推荐
- 如何用js给图片重置宽_如何用js给老婆每天发情话
作者: 加百利真胖 原文:https://juejin.cn/events/all 一.引言 最近家里添了小孩,在家带娃陪产了一些天,深刻体会到老婆带孩子的辛苦. 工作的时候不能在家陪她,就想着写个程 ...
- 微信红包随机数字_微信红包的随机算法
概况:2014年微信红包使用数据库硬抗整个流量,2015年使用cache抗流量. 微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储.采取实时计算金额的考虑:预算需要 ...
- python模拟微信发红包算法_微信红包的随机算法是怎样实现的?
有人问过微信的人,大致是这样: 先上代码: public static double getRandomMoney(RedPackage _redPackage) { // remainSize 剩余 ...
- php将数组中元素打乱顺序,PHP公开课|学会随机打乱数组元素顺序的函数,你的PHP会学的更好...
[摘要]PHP作为一种超文本预处理器,已经成为了我们常用的网站编程语言,并且结合了C语言,Java等我们常见的编程语言,所以,有很多web开发领域的新人都看中了他的使用广泛性,有很多人都想了解php的 ...
- js对象数组计算总计_如何计算数组中的对象
js对象数组计算总计 Knowing how to quickly iterate through an array and count objects is deceptively simple. ...
- js 只准输入数字_基于TensorFlow.js的JavaScript机器学习
Credits: aijs.rocks 虽然python或r编程语言有一个相对容易的学习曲线,但是Web开发人员更喜欢在他们舒适的javascript区域内做事情.目前来看,node.js已经开始向每 ...
- python 题库自动答题,自动匹配题库_如何用python写一个从题库自动匹配的答题脚本_淘题吧...
A. web数据库题目:根据用户输入的用户名和密码于数据库中的记录是否匹配制作一个用户登录模块 http://blog.csdn.net/love_leve/article/details/43226 ...
- python可视化迷宫求解_如何用 Python 制作一个迷宫游戏
相信大家都玩过迷宫的游戏,对于简单的迷宫,我们可以一眼就看出通路,但是对于复杂的迷宫,可能要仔细寻找好久,甚至耗费数天,然后可能还要分别从入口和出口两头寻找才能找的到通路,甚至也可能找不到通路. 虽然 ...
- python监听文件更改记录_如何用机器人监听老板微信?
随着微信社交的兴起,我们加入的群也越来越多,一个不经意就被拉入好几个群,群是大家协同交流的平台,但是微信群却越来越泛滥,不知道大家有没有统计过自己浪费在毫无营养的群中的时间? 因为群质量或者群太吵的 ...
最新文章
- UniT | Facebook发布全新智能通用Agent!
- [译]函数式响应编程入门指南
- 机器如何区分和判定指令和数据
- vue/cli 3.0 脚手架【进阶】 使用 amfe-flexible 和 postcss-px2rem进行移动端适
- 时永方:做到这三点,你就是多媒体内行了
- javascript 计算两个坐标的距离 米_土方全面应用计算
- (转)淘淘商城系列——发布dubbo服务
- Web端QR二维码扫描实现
- Qt + 运动控制 (固高运动控制卡)【2】运动控制卡初始化和关闭
- 2020 IJCAI 接受论文 list 分类排列(一)
- Java语言十五讲(第十一讲 Script)
- 【AIOT】手表调研
- c 语言 sqlite,SQLite 的 C 语言编程
- 华为S5700交换机登录认证配置学习笔记
- 简记_硬件工程师解读RS-422/RS-485接口
- 2-18-python基础学习-0409
- Flutter 自定义View之 饼状图
- 新仙剑奇侠传H5上线测试了
- uploader.lib php,Lib/Upload.php · 跳跳虎1986/cwj - Gitee.com
- 队名 Booqmz 具体读音可以详见谷歌翻译声优~
热门文章
- 使用SAP云平台portal service之前,需要做好哪些准备
- 我们在tool里给ui element设置断点,然后操作的时候,断点就触发了。Framework是咋实现的
- CRM one order性能调优指南
- 如何对SAP Leonardo上的机器学习模型进行重新训练
- deletion in request load scenario
- How AET fields are retrieved from backend
- SAP CRM呼叫中心里的Java stack
- SAP One Order redesign里的新CDS view
- JavaScript对象根据自定义属性进行排序
- mysql qps提升_上亿数据MYSQL的innodb优化 QPS轻松过5000