房间内有 100 人,每人有 100 块,有钱的人每分钟随机给另一个人 1 块,最后这个房间内的财富分布怎样?
2017-07-14 23:54
253 查看
摘要: java8 新特性初试
在知乎看到一个有意思的问题:房间内有 100 人,每人有 100 块,有钱的人每分钟随机给另一个人 1 块,最后这个房间内的财富分布怎样?
最近在研究 java8 的新特性,就用相关代码写了一个demo。使用lambda表达式和函数式风格编程,代码简洁,看起来跟Scala非常相似!
使用Stream操作对象,只需要几行代码就能解决复杂的循环问题。
代码输出结果(最后一次的结果,排序是为了方便观察规律):
打印结果,list=[61, 62, 53, 4, 34, 206, 29, 21, 156, 0, 115, 117, 138, 411, 1, 16, 302, 253, 163, 227, 140, 23, 92, 41, 89, 16, 142, 9, 171, 150, 116, 39, 68, 178, 621, 291, 53, 13, 79, 58, 8, 155, 92, 110, 3, 28, 79, 152, 68, 61, 5, 24, 67, 1, 71, 119, 182, 214, 84, 31, 106, 177, 208, 169, 33, 32, 8, 90, 99, 20, 20, 49, 377, 78, 60, 155, 50, 163, 71, 99, 12, 96, 163, 57, 201, 64, 124, 20, 121, 28, 259, 88, 27, 8, 21, 233, 68, 0, 13, 21]
打印排序后的结果,list=[0, 0, 1, 1, 3, 4, 5, 8, 8, 8, 9, 12, 13, 13, 16, 16, 20, 20, 20, 21, 21, 21, 23, 24, 27, 28, 28, 29, 31, 32, 33, 34, 39, 41, 49, 50, 53, 53, 57, 58, 60, 61, 61, 62, 64, 67, 68, 68, 68, 71, 71, 78, 79, 79, 84, 88, 89, 90, 92, 92, 96, 99, 99, 106, 110, 115, 116, 117, 119, 121, 124, 138, 140, 142, 150, 152, 155, 155, 156, 163, 163, 163, 169, 171, 177, 178, 182, 201, 206, 208, 214, 227, 233, 253, 259, 291, 302, 377, 411, 621]
问题的答案挺有意思的,结果金钱并不会平均分布,最大的能到600多元,最少的0元,会有很大的差别。
我已开始也以为钱会平均分布,实在理解不到原因。不过知乎上已经有相关的原理和公式推导,有兴趣的同学可以去搜索一下。其实这是一个热力学问题,一个封闭的系统中,在粒子数量足够大,系统处于平衡态时,粒子处在某一状态下的概率应呈指数形式分布。
在知乎看到一个有意思的问题:房间内有 100 人,每人有 100 块,有钱的人每分钟随机给另一个人 1 块,最后这个房间内的财富分布怎样?
最近在研究 java8 的新特性,就用相关代码写了一个demo。使用lambda表达式和函数式风格编程,代码简洁,看起来跟Scala非常相似!
使用Stream操作对象,只需要几行代码就能解决复杂的循环问题。
import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; public class Main { //解决问题:房间内有 100 人,每人有 100 块,有钱的人每分钟随机给另一个人 1 块,最后这个房间内的财富分布怎样? public static void main(String[] args) { //基于java8,stream特性,创建对象,100长度list,每个元素为100,即100个人,每人100元钱 List<Integer> money= Stream.iterate(100 , n -> 100).limit(100).collect(Collectors.toList()); //循环给钱,注意给钱是每分钟一次批量给,有钱的人才给 for(int i=0;i<200000;i++){ //被给钱的对象,临时记录(有钱的人减一元) List<Integer> moneyTemp=money.stream().map(n -> {return n>0?n-1:0;}).collect(Collectors.toList()); //同一时间,钱大于0的人,给一元到随机的一个人 money.stream().filter(n -> n>0).forEach(n -> {int a=(int)(Math.random()*100);moneyTemp.set(a,moneyTemp.get(a)+1);}); //赋值给money money=moneyTemp; //排序之后再打印结果 System.out.println("打印结果,list="+money.toString()); System.out.println("打印排序后的结果,list="+money.stream().sorted().collect(Collectors.toList()).toString()); } } }
代码输出结果(最后一次的结果,排序是为了方便观察规律):
打印结果,list=[61, 62, 53, 4, 34, 206, 29, 21, 156, 0, 115, 117, 138, 411, 1, 16, 302, 253, 163, 227, 140, 23, 92, 41, 89, 16, 142, 9, 171, 150, 116, 39, 68, 178, 621, 291, 53, 13, 79, 58, 8, 155, 92, 110, 3, 28, 79, 152, 68, 61, 5, 24, 67, 1, 71, 119, 182, 214, 84, 31, 106, 177, 208, 169, 33, 32, 8, 90, 99, 20, 20, 49, 377, 78, 60, 155, 50, 163, 71, 99, 12, 96, 163, 57, 201, 64, 124, 20, 121, 28, 259, 88, 27, 8, 21, 233, 68, 0, 13, 21]
打印排序后的结果,list=[0, 0, 1, 1, 3, 4, 5, 8, 8, 8, 9, 12, 13, 13, 16, 16, 20, 20, 20, 21, 21, 21, 23, 24, 27, 28, 28, 29, 31, 32, 33, 34, 39, 41, 49, 50, 53, 53, 57, 58, 60, 61, 61, 62, 64, 67, 68, 68, 68, 71, 71, 78, 79, 79, 84, 88, 89, 90, 92, 92, 96, 99, 99, 106, 110, 115, 116, 117, 119, 121, 124, 138, 140, 142, 150, 152, 155, 155, 156, 163, 163, 163, 169, 171, 177, 178, 182, 201, 206, 208, 214, 227, 233, 253, 259, 291, 302, 377, 411, 621]
问题的答案挺有意思的,结果金钱并不会平均分布,最大的能到600多元,最少的0元,会有很大的差别。
我已开始也以为钱会平均分布,实在理解不到原因。不过知乎上已经有相关的原理和公式推导,有兴趣的同学可以去搜索一下。其实这是一个热力学问题,一个封闭的系统中,在粒子数量足够大,系统处于平衡态时,粒子处在某一状态下的概率应呈指数形式分布。
相关文章推荐
- 知乎问题"房间里100个人,每人1000元,他们玩一个游戏,每轮游戏中,每个人拿出1元,随机给另一个人,最后他们的财富分布是怎样的"实践解答
- “房间里有100个人,每人都有100元钱,每轮每人要拿一元钱随机给另一个人”最后分布的python结果
- 10个人,每人100块,每分钟每个人拿1块钱,随机给其他人,一小时钱是怎样的?
- 系统会随机给你一个日期(yyyy-MM-dd)字符串,你需要计算这个时间上一个月的最后一天的具体日期,最后以yyyy年MM月dd日的字符形式返回
- lesson 10:用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”、“猜大了”或“猜
- 写一个函数int get(),这个函数运行一次可以从V[N]里随机取出一个数,而这个数必须是符合1/N平均分布的
- C#中怎样随机输出从0到100的数字且不重复(不用数组)
- 【算法】100人没人100元赠送,最后分布
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”、“猜大了”或“猜对
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”、“猜大了”或“猜对了”。猜数之前,要
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。
- 随机生成一个0到100的数,让用户猜,允许猜5次,每次猜大了或猜小了,都要给出提示,最后给出正确答案
- 【codeforces 680 C】【数学题+交互题】C. Bear and Prime 1【底数是[2,100]中的数,现在你最多询问20次,询问为这个数是不是底数的因数,最后判断这个数是不是素数】
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”、“猜大了”或“猜对
- 用多线程的方式实现对一个数随机自增N次, 随机自减M次,最后打印出这个数字 (不能用原子操作类AtomicInteger)
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”、“猜大了”或“猜对
- 用两个线程玩猜数字游戏,第一个线程负责随机给出1~100之间的一个整数,第二个线程负责猜出这个数。要求每当第二个线程给出自己的猜测后,第一个线程都会提示“猜小了”、“猜大了”或“猜对了”。猜数之前,要
- 微软100题第18题(求出在这个圆圈中剩下的最后一个数字)
- 编写10个线程,第一个线程从1加到10,第二个线程从11加到20…第十个线程从91加到100, 最后再把10个线程结果相加。