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)
上一篇 2021年9月10日 下午9:00
下一篇 2021年9月10日 下午10:00


相关推荐

  • CMD命令行杀进程[通俗易懂]

    CMD命令行杀进程[通俗易懂]1、打开CMD,输入tasklist2、根据进程名杀进程taskkill/f/t/imGoogleCrashHandler.exe

    2025年7月26日
    5
  • centos7卸载软件命令_linux安装docker

    centos7卸载软件命令_linux安装docker1首先搜索已经安装的docker安装包[root@localhost~]#yumlistinstalled|grepdocker或者使用该命令[root@localhost~]#rpm-qa|grepdockerdocker.x86_642:1.12.6-16.el7.centos@extras

    2022年8月30日
    8
  • sql中使用什么语句创建索引_索引的创建方式有

    sql中使用什么语句创建索引_索引的创建方式有创建索引的sql语句是【CREATEINDEXindexNameONtable_name(column_name)】,这是最基本的索引,它没有任何限制。本文操作环境:windows10系统、mysql5.7、thinkpadt480电脑。创建索引的sql语句如下所示:下面是最基本的创建索引的语法,它没有任何限制。CREATEINDEXindexNameONtable_name(column_name)如果是CHAR,VARCHAR类型,length可以小.

    2025年9月24日
    8
  • flash视频器播放器代码

    flash视频器播放器代码flash视频器播放器代码代码整理:

    2022年7月3日
    23
  • 【SpringBoot】40、SpringBoot中使用Aspose将文件转为PDF实现在线预览

    【SpringBoot】40、SpringBoot中使用Aspose将文件转为PDF实现在线预览一 简介 Aspose 是 NET 和 Java 开发组件以及为 MicrosoftSQL 和 JasperReport 等平台提供渲染扩展的领先供应商 它的核心重点是提供最完整和最强大的文件管理产品 Aspose 产品支持一些商业上最流行的文件格式 包括 Word 文档 Excel 电子表格 PowerPoint 演示文稿 PDF 文档 Flash 演示文稿和项目文件 二 下载下载 Aspose 的依赖 Jar 包可以通过一下仓库下载 Aspo

    2026年3月26日
    2
  • 京东面板搭建 青龙面板多容器的安装与使用2022年8月22日

    京东面板搭建 青龙面板多容器的安装与使用2022年8月22日系统环境的准备与Docker的安装首先需要准备一台服务器或VPS,当然自家能够安装Docker的路由器也可以,例如N1或OpenWrt等。代挂http://183.56.232.117:5701/下面以Centos为例国内一键安装Dockersudocurl-sSLhttps://get.daocloud.io/docker|shDocker安装(全家桶-推荐)wgethttps://ghproxy.com/https://raw.githubusercon.

    2026年1月19日
    5

发表回复

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

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