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 ...
随机推荐
- zabbix监控企业esxi虚拟机
zabbix监控企业esxi虚拟机 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我来公司有一段时间了,最近也发现模型部有测试和开发反应某台机器登陆不上去了,结果登陆esxi服务器 ...
- Codeforce Round #221 Div2
每次的CF都是一把辛酸泪! 什么时候能打破这局面,昨天做着睡着了! 有时候有的题目也就差一线! 哎,! A:杠杆原理! B:算最后负的和! B:没弄出来当时就脑短路... C:事后写了个n*log(n ...
- codevs 1506 传话
http://codevs.cn/problem/1506/ 1506 传话 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题解 题目描述 D ...
- [转]数据库高可用架构(MySQL、Oracle、MongoDB、Redis)
一.MySQL MySQL小型高可用架构 方案:MySQL双主.主从 + Keepalived主从自动切换 服务器资源:两台PC Server 优点:架构简单,节省资源 缺点:无法线性扩展,主从失 ...
- [原创] 关于quartz (spring 中的任务调度器)时间配置
1. CronTrigger时间格式配置说明 CronTrigger配置格式: 格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 ...
- [原创]java WEB学习笔记56:Struts2学习之路---Struts 版本的 登录 demo
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- UML: 序列图
摘自http://www.umlonline.org/school/thread-37-1-1.html 大家都进过餐馆吃饭吧?你是如何和餐厅服务员“眉来眼去”的呢?回忆一下从你进餐馆开始到你离开餐馆 ...
- eclipse key
让我们按照使用频率来看看我最爱用的一些热键组合.(注:以下内容在Eclipse3.02及一上版本通过测试) . Control-Shift-T: 打开类型(Open type).如果你不是有意磨洋工, ...
- 关于用php插入汉字到oracle中出现不乱码问题
$conn = oci_pconnect("IBADMINTON", "5206576360", $db,'utf8'); 在代码中加入‘utf8’即可: ...
- 表单和验证事件以及marquee标签
1.表单验证<form></form> (1).非空验证(去空格) (2).对比验证(跟一个值对比) (3).范围验证(根据一个范围进行判断) (4).固定格式验证:电话号码, ...