背景
有一天晚上还在加班时,一个朋友打电话让帮忙统计下几个数字符合某种条件的所有可能结果,描述了好大一会才明白。编程不麻烦,抽空一会就写好了,这里做个简单的记录。
问题描述
有5个变量,分别为a、b、c、d、e, 取值范围都是0~9。 5个变量相加,个位数字为0。按照以下条件统计:
- 统计所有符合条件的结果
- 统计0~9个数字分别出现1~5次的结果
分析
记录所有符合条件的结果比较简单,使用一个集合即可。但是记录每个数字分别出现不同次数的结果有点复杂。经过分析,应该有3层结构:
- 记录所有数字
- 记录所有数字重复的次数
- 记录所有数字不同重复次数对应的组合串
最终确定使用一下数据结构:Dictionary<int, Dictionary<int, List<string>>>
编程
处理步骤
- 初始化存储数据结构
- 记录所有符合条件的统计结果
- 记录每个数字不同重复次数的统计结果,使用正则匹配个数
- 以一定格式输出到文件中
代码
public class Stastistics
{
/// <summary>
/// 统计可选数字最小值
/// </summary>
private static readonly int MinNum = 0;
/// <summary>
/// 统计可选数字最大值
/// </summary>
private static readonly int MaxNum = 9;
/// <summary>
/// 组合字串中某个数字的最小重复个数
/// </summary>
private static readonly int MinRepeatCount = 1;
/// <summary>
/// 组合字串中某个数字的最大重复个数
/// </summary>
private static readonly int MaxRepeatCount = 5;
/// <summary>
/// 符合条件的所有统计结果
/// </summary>
static readonly List<string> AllStatisticsResult = new List<string>();
/*
* 符合条件,且所有重复次数的统计结果
*
* 数据结构:(可选数字,重复次数,组合字串)
* 例如:
* [
* (0,
* (1, [01117, 01126, ...]),
* (2, [00118, 00127, ...]),
* .....
* )
* ]
*/
private static readonly Dictionary<int, Dictionary<int, List<string>>> SpecialStatisticsResult = new Dictionary<int, Dictionary<int, List<string>>>(10);
/// <summary>
/// 数字组合格式
/// </summary>
private static string sortFormat = "{0}{1}{2}{3}{4}";
/// <summary>
/// 输出路径
/// </summary>
private static string OutputPath = @"D:\StatisticsResult.txt";
public static void Run()
{
Initialize();
// 统计并记录所有符合条件的结果
for (int i = MinNum; i <= MaxNum; i++)
{
for (int j = MinNum; j <= MaxNum; j++)
{
for (int k = MinNum; k <= MaxNum; k++)
{
for (int l = MinNum; l <= MaxNum; l++)
{
for (int m = MinNum; m <= MaxNum; m++)
{
var total = i + j + k + l + m;
if (total % 10 == 0)
{
AllStatisticsResult.Add(string.Format(sortFormat, i, j, k, l, m));
}
}
}
}
}
}
// 统计符合条件,不同重复次数的结果
foreach (var numCombs in AllStatisticsResult)
{
CalculateSpecial(numCombs);
}
//获取所有分类统计结果的字符串格式
string statisticsResult = GetStastisticsResult();
//将统计结果输出并保存到文件中
Output(statisticsResult);
}
/// <summary>
/// 初始化数据存储结构
/// </summary>
private static void Initialize()
{
for (int i = MinNum; i <= MaxNum; i++)
{
var numRepeatCountDic = new Dictionary<int, List<string>>();
for (int j = MinRepeatCount; j <= MaxRepeatCount; j++)
{
numRepeatCountDic.Add(j, new List<string>());
}
SpecialStatisticsResult.Add(i, numRepeatCountDic);
}
}
/// <summary>
/// 计算并保存当前组合字串中不同数字的重复个数
/// </summary>
/// <param name="numComb">组合子串</param>
/// <returns></returns>
private static void CalculateSpecial(string numComb)
{
for (int i = MinNum; i <= MaxNum; i++)
{
//当前数字对应的字典
var currentNumRepeatCountDic = SpecialStatisticsResult.FirstOrDefault(s => s.Key == i);
for (int j = MinRepeatCount; j <= MaxRepeatCount; j++)
{
//当前重复个数对应的字典
var currentRepeatCountDic = currentNumRepeatCountDic.Value.FirstOrDefault(s => s.Key == j);
if (Regex.Matches(numComb, i.ToString()).Count == j)
{
currentRepeatCountDic.Value.Add(numComb);
}
}
}
}
/// <summary>
/// 获取统计结果,并以字符串方式输出
/// </summary>
/// <returns>统计结果</returns>
private static string GetStastisticsResult()
{
StringBuilder statisticsResultBuilder = new StringBuilder();
statisticsResultBuilder.AppendFormat("--------所有样本总数:{0}--------", AllStatisticsResult.Count);
foreach (var s in AllStatisticsResult)
{
statisticsResultBuilder.AppendFormat("{0},", s);
}
statisticsResultBuilder.AppendLine().AppendLine();
for (int i = MinNum; i <= MaxNum; i++)
{
var currentValue = SpecialStatisticsResult.FirstOrDefault(s => s.Key == i);
if (currentValue.Value.Count <= 0)
{
continue;
}
for (int j = MinRepeatCount; j <= MaxRepeatCount; j++)
{
var currentNumComb = currentValue.Value.FirstOrDefault(s => s.Key == j);
if (currentNumComb.Value.Count <= 0)
{
continue;
}
statisticsResultBuilder.AppendFormat("--------{0} 重复 {1} 次的总数:{2}--------", i, j, currentNumComb.Value.Count);
foreach (var s in currentNumComb.Value)
{
statisticsResultBuilder.Append(s + ", ");
}
statisticsResultBuilder.AppendLine().AppendLine();
}
}
return statisticsResultBuilder.ToString();
}
/// <summary>
/// 将统计结果保存到文件中
/// </summary>
/// <param name="statisticsResult">统计结果</param>
private static void Output(string statisticsResult)
{
using (StreamWriter writer = new StreamWriter(OutputPath))
{
writer.WriteLine(statisticsResult);
writer.Flush();
}
}
}
统计结果