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 ...
随机推荐
- php实用类
<?php class DBDA { public $host="localhost";//服务器地址 public $uid="root";//用户名 ...
- oracle触发器书写方法
CREATE SEQUENCE 序列名[INCREMENT BY n] --每次加几[START WITH n] --序列从几开始[{MAXVALUE/ MINVALUE n|NOMAXVALUE}] ...
- Java基础(55):Exception类详解(转)
Java中的异常 Exception java.lang.Exception类是Java中所有异常的直接或间接父类.即Exception类是所有异常的根类. 比如程序: public class Ex ...
- javax.servlet.jsp.JspException cannot be resolved to a type
javax.servlet.jsp.PageContext cannot be resolved to a type javax.servlet.jsp.JspException cannot be ...
- 夺命雷公狗—angularjs—19—angular-route
ngRoute包括的内容 ng的路由机制是靠ngRoute提供的,通过hash和history两种方式实现了路由,可以检测浏览器是否支持history来灵活调用相应的方式.ng的路由(ngRoute) ...
- 夺命雷公狗---DEDECMS----8dedecms干掉首页和-文档页-栏目页的页面的广告
我们首先来将首页生成静态页面,如下图所示: 成功后,如下显示: 如果成功后则在文件夹下多了一个index.html的文件.. 我们的首页静态页面是通过模版文件生成,所以我们只需要把模版文件的广告标签删 ...
- [tp3.2.1]sql查询语句(一)
基本查询方式 字符串条件查询, 索引数组条件查询 对象条件查询 SQL语句大小写是一样的,但是,执行的时候有一个小写到大写的转换,所以最好写大写 $condition=new ...
- sp_addlinkedserver 方法应用
EXEC sp_addlinkedserver @server='DBVIP',--被访问的服务器别名 @srvproduct='', @provider='SQLO ...
- java对redis的基本操作(转)
本文转自:http://www.cnblogs.com/edisonfeng/p/3571870.html 2.主要类 1)功能类 package com.redis; import java.uti ...
- 【python cookbook】【数据结构与算法】13.通过公共键对字典列表排序
问题:想根据一个或多个字典中的值来对列表排序 解决方案:利用operator模块中的itemgetter()函数对这类结构进行排序是非常简单的. # Sort a list of a dicts on ...