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 = ;
int targetCount = ;
int result;
double probability;
while (true)
{
List<string> bucketBalls = new List<string>();
result = Play(bucketBalls);
//Console.WriteLine("result:" + result);
if (result == )
{
targetCount++;
//Console.WriteLine("targetCount:" + targetCount);
}
count++;
//Console.WriteLine("count:" + count);
probability = Math.Round((double)1.0 * targetCount / count, );
Console.WriteLine(probability);
//Console.Read();
}
}
private static int Play(List<string> bucketBalls)
{
for (int i = ; i <= ; i++)
{
bucketBalls.Add("BlackBall");
bucketBalls.Add("WhiteBall");
}
//PrintList(bucketBalls);
Random ran = new Random();
while (bucketBalls.Count() > )
{ var balls = Take(bucketBalls, , ran);
//Console.WriteLine("Take the balls " + balls[0] + " " + balls[1]);
//PrintList(bucketBalls);
if (balls[] == balls[])
{
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() == )
{
//Console.WriteLine("result is " + bucketBalls[0]);
return bucketBalls[] == "BlackBall" ? : ;
}
else
{
return ;
}
} 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 = ; i <= v; i++)
{
pos = ran.Next(, 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 = ;
int targetCount = ;
int result;
double probability;
while (true)
{
List<string> bucketBalls = new List<string>();
result = Play(bucketBalls);
if (result == )
{
targetCount++;
}
count++;
probability = Math.Round((double)1.0 * targetCount / count, );
Console.WriteLine(probability);
}
}
private static int Play(List<string> bucketBalls)
{
for (int i = ; i <= ; i++)
{
bucketBalls.Add("BlackBall");
bucketBalls.Add("WhiteBall");
}
Random ran = new Random();
while (bucketBalls.Count() > )
{ var balls = Take(bucketBalls, , ran);
if (balls[] == balls[])
{
Put(bucketBalls, "BlackBall");
}
else
{
Put(bucketBalls, "WhiteBall");
}
}
if (bucketBalls.Count() == )
{
return bucketBalls[] == "BlackBall" ? : ;
}
else
{
return ;
}
} 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 = ; i <= v; i++)
{
pos = ran.Next(, bucketBalls.Count());
balls.Add(bucketBalls[pos]);
bucketBalls.RemoveAt(pos);
}
return balls;
}
}
}
通过运行结果可以看出来,概率一直很稳定,为1:

所以答案是在白球和黑球各100个的前提下取球放球,最后都只剩下黑球,概率为1。
修改程序中的初始化参数还可以用来求解课后题中的拓展情况,不用动脑。大家可以试试。
总结过程中遇到的问题:
1、字符串赋值的时候一定要仔细,别写错了!
2、Random.Next()函数返回值的范围包括 minValue 但不包括 maxValue。如果 minValue 等于 maxValue,则返回 minValue。
C#之桶中取黑白球问题的更多相关文章
- 今盒子里有n个小球,A、B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个
/* 题目描述 今盒子里有n个小球,A.B两人轮流从盒中取球,每个人都可以看到另一个人取了多少个,也可以看到盒中还剩下多少个,并且两人都很聪明,不会做出错误的判断. 我们约定: 每个人从盒子中取出的球 ...
- 压缩感知中的lp球:p范数最优化为什么总会导致一个稀疏的解的原因
转自:彬彬有礼. 压缩感知中的lp球:p范数最优化为什么总会导致一个稀疏的解的原因 http://blog.csdn.net/jbb0523/article/details/40268943 题目: ...
- 定时从远程的数据库中取数据,然后把取出来的数据插入或更新本地的oracle数据库的表
最近项目中有一种需求: 大致需求是这样的 通过给定的 用户名和密码 要定时从远程的数据库中取数据,然后把取出来的数据插入或更新本地的oracle数据库的表 项目的结构式struts1 hibernat ...
- LoadRunner中取Request、Response
LoadRunner中取Request.Response LoadRunner两个“内置变量”: 1.REQUEST,用于提取完整的请求头信息. 2.RESPONSE,用于提取完整的响应头信息. 响应 ...
- DataGrid中取HyperLinkColumn列的值,处理DataGrid中绑定的特殊字符
DataGrid中取HyperLinkColumn列的值. /// <summary> /// 对datagrid中标签进行编码,处理特殊字符 /// </summary> / ...
- 【算法与数据结构】在n个数中取第k大的数(基础篇)
(转载请注明出处:http://blog.csdn.net/buptgshengod) 题目介绍 在n个数中取第k大的数(基础篇),之所以叫基础篇是因为还有很多更高级的算法,这些 ...
- Java中取小数点后两位(四种方法)
摘自http://irobot.iteye.com/blog/285537 Java中取小数点后两位(四种方法) 一 Long是长整型,怎么有小数,是double吧 java.text.D ...
- 使用回溯法求所有从n个元素中取m个元素的组合
不多说了,直接上代码,代码中有注释,应该不难看懂. #include <stdlib.h> #include <stdio.h> typedef char ELE_TYPE; ...
- 总结C++中取成员函数地址的几种方法
这里, 我整理了4种C++中取成员函数地址的方法, 第1,2,4种整理于网上的方法, 第3种cdecl_cast是我自己想到的. 其中, 第4种(汇编)的方法不能在VC6上编译通过. 推荐使用第1,2 ...
随机推荐
- JAVA JDBC连接 SQLServer2012 连接失败 端口号错误
SQLServer2012的SQL Sever 网络配置 我有4个 SQLEXPRESS的协议 SQLSERVER2008的协议 MSSQLSERVER的协议 SQLSERVER2012的协议 他们都 ...
- 动画--过渡属性 transition-property
早期在Web中要实现动画效果,都是依赖于JavaScript或Flash来完成.但在CSS3中新增加了一个新的模块transition,它可以通过一些简单的CSS事件来触发元素的外观变化,让效果显得更 ...
- CCSprite的使用方法大全
一.精灵创建及初始化 1.从图片文件创建: CCSprite *sprite = [CCSprite spriteWithFile:@"ImageFileName.png"]; 默 ...
- CCF真题之画图
201409-2 问题描述 在一个定义了直角坐标系的纸上,画一个(x1,y1)到(x2,y2)的矩形指将横坐标范围从x1到x2,纵坐标范围从y1到y2之间的区域涂上颜色. 下图给出了一个画了两个矩形的 ...
- 3D语音天气球(源码分享)——通过天气服务动态创建3D球
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 开篇废话: 这个项目准备分四部分介绍: 一:创建可旋转的"3D球":3 ...
- 夺命雷公狗—angularjs—21—解决angularjs压缩问题
我们在实际的开发中往往离不开js的代码压缩,因为这样可以减轻服务器的压力,是的的方法如下所示: <!DOCTYPE html> <html lang="en" n ...
- JSP-05- JSP总结
1 客户端请求新页面 <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- 【sinatra】安装测试
$ gem install sinatra 测试: $ subl app.rb app.rb内容: require 'sinatra' get '/' do "Hello, World!&q ...
- js表单提交一种方式
在一个html和php混编的文件中,用到js提交表单的方法: 定义表单id为form1,提交按钮type为submit, var data_info = document.getElementById ...
- Inside TSQL Querying - Chapter 2. Physical Query Processing
Summary Description The SQL language is spoken by most database experts, and all relational database ...