C#之桶中取黑白球问题

C#之桶中取黑白球问题

《编程之美》284页,问题4.6:桶中取黑白球。

有一个桶,里面有白球、黑球各100个,人们必须按照以下规则把球取出来:

1. 每次从桶中拿两个球;

2. 如果两球同色,再放入一个黑球;

3. 如果两球异色,再放入一个白球;

问:最后桶里面只剩下一个黑球的概率是多少?

于是我开始分析,桶里装球,每次摸球是随机的,所以不能用队列和栈,那就用万能的动态列表来做桶吧。按照题目描述的顺序,写出取球的过程,最后剩的是黑球返回1,白球返回2,其他情况(没球了)返回3,然后根据概率在大数据量下将会趋于稳定的性质无限取球,最后趋于稳定的那个数就是答案。

代码如下(注释的部分为调试程序过程中用到的测试代码,用来显示操作过程中取球、放球、以及桶中球的详细变化过程):

using System; using System.Collections.Generic; using System.Linq; namespace BucketBall { class Program { static void Main(string[] args) { int count = 0; int targetCount = 0; int result; double probability; while (true) { List<string> bucketBalls = new List<string>(); result = Play(bucketBalls); //Console.WriteLine("result:" + result); if (result == 1) { targetCount++; //Console.WriteLine("targetCount:" + targetCount);  } count++; //Console.WriteLine("count:" + count); probability = Math.Round((double)1.0 * targetCount / count, 2); Console.WriteLine(probability); //Console.Read();  } }
private static int Play(List<string> bucketBalls) { for (int i = 1; i <= 2; i++) { bucketBalls.Add("BlackBall"); bucketBalls.Add("WhiteBall"); } //PrintList(bucketBalls); Random ran = new Random(); while (bucketBalls.Count() > 1) { var balls = Take(bucketBalls, 2, ran); //Console.WriteLine("Take the balls " + balls[0] + " " + balls[1]); //PrintList(bucketBalls); if (balls[0] == balls[1]) { Put(bucketBalls, "BlackBall"); //Console.WriteLine("Put the BlackBall"); //PrintList(bucketBalls); } else { Put(bucketBalls, "WhiteBall"); //Console.WriteLine("Put WhiteBall over!"); //PrintList(bucketBalls); } //Console.WriteLine(bucketBalls.Count()); } if (bucketBalls.Count() == 1) { //Console.WriteLine("result is " + bucketBalls[0]); return bucketBalls[0] == "BlackBall" ? 1 : 2; } else { return 0; } } private static void PrintList(List<string> bucketBalls) { Console.WriteLine(); foreach (var ball in bucketBalls) { Console.Write(ball + " "); } Console.WriteLine(); } private static void Put(List<string> bucketBalls, string v) { bucketBalls.Add(v); } private static List<string> Take(List<string> bucketBalls, int v, Random ran) { List<string> balls = new List<string>(); int pos; for (int i = 1; i <= v; i++) { pos = ran.Next(0, bucketBalls.Count()); balls.Add(bucketBalls[pos]); bucketBalls.RemoveAt(pos); } return balls; } } }

我因为不小心将一处的“WhiteBall”写成了“WhileBall”而一度修改却得不到正确的答案,最终一步一步的通过上面的测试代码,才将出错范围最终锁定在了初始化bucketBalls的for循环内,最终发现我将“WhiteBall”写成了“WhileBall”。改过来以后,运行结果终于正确了。下面是去掉测试代码的最终版:

using System; using System.Collections.Generic; using System.Linq; namespace BucketBall { class Program { static void Main(string[] args) { int count = 0; int targetCount = 0; int result; double probability; while (true) { List<string> bucketBalls = new List<string>(); result = Play(bucketBalls); if (result == 1) { targetCount++; } count++; probability = Math.Round((double)1.0 * targetCount / count, 2); Console.WriteLine(probability); } }
private static int Play(List<string> bucketBalls) { for (int i = 1; i <= 100; i++) { bucketBalls.Add("BlackBall"); bucketBalls.Add("WhiteBall"); } Random ran = new Random(); while (bucketBalls.Count() > 1) { var balls = Take(bucketBalls, 2, ran); if (balls[0] == balls[1]) { Put(bucketBalls, "BlackBall"); } else { Put(bucketBalls, "WhiteBall"); } } if (bucketBalls.Count() == 1) { return bucketBalls[0] == "BlackBall" ? 1 : 2; } else { return 0; } }

private static void Put(List<string> bucketBalls, string v) { bucketBalls.Add(v); } private static List<string> Take(List<string> bucketBalls, int v, Random ran) { List<string> balls = new List<string>(); int pos; for (int i = 1; i <= v; i++) { pos = ran.Next(0, bucketBalls.Count()); balls.Add(bucketBalls[pos]); bucketBalls.RemoveAt(pos); } return balls; } } }

通过运行结果可以看出来,概率一直很稳定,为1:

C#之桶中取黑白球问题

所以答案是在白球和黑球各100个的前提下取球放球,最后都只剩下黑球,概率为1。

修改程序中的初始化参数还可以用来求解课后题中的拓展情况,不用动脑。大家可以试试。

总结过程中遇到的问题:

1、字符串赋值的时候一定要仔细,别写错了!

2、Random.Next()函数返回值的范围包括 minValue 但不包括 maxValue如果 minValue 等于 maxValue,则返回 minValue

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/109241.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 使用systemctl命令启动和关闭mysql

    使用systemctl命令启动和关闭mysql以前都用service命令管理mysql,现在liunx系统升级了,又有了新的更好的方法管理系统进程,现在我们来学习如何用systemctl命令管理mysql。Systemctl是一个systemd工具,主要负责控制systemd系统和服务管理器。Systemd是一个系统管理守护进程、工具和库的集合,用于取代SystemV初始进程。Systemd的功能是用于集中管理和配置类UNIX系统。在

    2022年10月29日
  • ajax跨域请求结合springmvc后台代码学习整理

    ajax跨域请求,在工作中遇到使用ajax发起请求获取数据,但是请求的数据不在同一个域下,这样子就要使用到ajax的跨域请求了! 我使用的框架 SpringMVC,我在PC端的项目里面写一个接口方法,但是在wap项目中也要用改接口!下面贴出示例代码:

  • 【19】进大厂必须掌握的面试题-50个React面试

    【19】进大厂必须掌握的面试题-50个React面试

    2020年11月13日
  • Memcache分布式部署方案

    Memcache分布式部署方案

  • cloudsim4.0中CloudSimExample2分析

    cloudsim4.0中CloudSimExample2分析CloudSimExample2展示如何创建一个只含一个主机的数据中心,并在其上运行两个云任务。(两个云任务运行在具有相同计算能力的虚拟机上,即两个云任务的执行需要相同的时间)首先附上CloudSimExample1全部代码:/**Title:CloudSimToolkit*Description:CloudSim(CloudSimulation)…

    2022年10月13日
  • opencv高斯金字塔_高斯求和公式

    opencv高斯金字塔_高斯求和公式一、图像金字塔图像金字塔是一种以多分辨率来解释图像的结构,通过对原始图像进行多尺度像素采样的方式,生成N个不同分辨率的图像。把具有最高级别分辨率的图像放在底部,以金字塔形状排列,往上是一系列像素(尺寸)逐渐降低的图像,一直到金字塔的顶部只包含一个像素点的图像,这就构成了传统意义上的图像金字塔。获得图像金字塔一般包括二个步骤:1.利用低通滤波器平滑图像 2.对平

    2022年10月15日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号