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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Easyui Datagrid相同连续列合Demo之三

    Easyui Datagrid相同连续列合Demo之三

    2022年2月21日
    42
  • 什么是前端框架与后端框架

    什么是前端框架与后端框架什么是框架框架(Framework)是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架。

    2022年6月7日
    111
  • minicom指令_【教程】minicom使用教程

    minicom指令_【教程】minicom使用教程简介Linux下的Minicom的功能与Windows下的超级终端功能相似,可以通过串口控制外部的硬件设备.适于在linux通过超级终端对嵌入式设备行管理.同样也可以使用minicom对外置Modem进行控制.Minicom的配置第一次启动时:需对minicom进行配置:minicom-s启动出现配置菜单:+—–[configuration]——+|Filenamesand…

    2022年6月5日
    49
  • 矩阵范数与向量范数关系_矩阵范数的定义

    矩阵范数与向量范数关系_矩阵范数的定义范数是距离在向量和矩阵上的推广,在研究收敛性、判断矩阵非奇异等方面有广泛应用。本节包括以下内容:(1)向量范数;(2)矩阵范数;(3)从属范数;(4)谱半径;(5)矩阵的非奇异条件。1向量范数从向量到实数的映射/函数。定义(1)条件:非负性、齐次性、三角不等式(∥x+y∥≤∥x∥+∥y∥\|x+y\|\leq\|x\|+\|y\|)。

    2022年9月19日
    5
  • linux ln 软连接_ln命令建立软链接

    linux ln 软连接_ln命令建立软链接举例:1.对某个文件创建一个连接[root@www.linuxidc.com~]#ln-s/home/kk/ss.sh~#如果不写目标地址,即在当前目录建接立链接[root@www.linuxidc.com~]#lsCentOS-Base.repo.oldboyanaconda-ks.cfginstall.loginstall.log.syslogss.sh…

    2022年9月30日
    2
  • 安装下载App_windows server 2022下载

    安装下载App_windows server 2022下载安装指南入门标题页3WindowsServerAppFabric安装和配置指南3版权3版权所有3简介3清单:规划安装4硬件要求4使计算机作好安装准备5本节内容5安装关键的Windows更新5安装Windows更新6安装修补程序6KB9804236安装.NETFramework6安装W…

    2022年10月17日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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