.NET平台開源項目速覽(11)KwCombinatorics排列組合使用案例(1)


    今年上半年,我在KwCombinatorics系列文章中,重點介紹了KwCombinatorics組件的使用情況,其實這個組件我5年前就開始用了,非常方便,麻雀雖小五臟俱全。所以一直非常喜歡,才寫了幾篇文章推薦給大家。最近在計算足球彩票結果組合過程中,使用的到了其功能,生成排列,非常具有代表性,而且也有網友咨詢過類似的問題,所以就封裝為擴展方法,方便調用。

        NET開源目錄:【目錄】本博客其他.NET開源項目文章目錄

彩票數據資料目錄【目錄】C#搭建足球賽事資料庫與預測平台與彩票數據分析目錄 

本文原文地址:.NET平台開源項目速覽(11)KwCombinatorics排列組合使用案例(1)

1.KwCombinatorics基本介紹

    KwCombinatorics,它是.NET平台一個高效的生成排列組合序列的開源類庫,它提供了4種生成排列與組合序列的方式。雖然原理和功能都很簡單,但是這個類庫在軟件測試、組合數學以及密碼學等方面都有很大的用處。很早就接觸了這個類庫,以前在一些小程序中也使用過,有時候為了遍歷所有可能的組合,自己去寫循環,生成,的確很繁瑣,有了KwCombinatorics 之后,都變得簡單寫了,接下來將詳細介紹該類庫的使用。

 KwCombinatorics類庫的主頁是:http://kwcombinatorics.codeplex.com/

   關於KwCombinatorics基本使用入門的文章有: 

1.【原創】開源.NET排列組合組件KwCombinatorics使用(一)組合生成 

 2.【原創】開源.NET排列組合組件KwCombinatorics使用(二)排列生成 

3.【原創】開源.NET排列組合組件KwCombinatorics使用(三)笛卡爾積組合 

2.足球彩票排列組合應用

     在足球彩票玩法中,經常要選擇幾場比賽,以及每場比賽不同的結果組合,進行投注,這個時候就要生成所有的排列組合了,以便進行下一步的平衡投注計算。例如,看下面一個截圖:

    例如,上午選擇了3場比賽,前2場,每場選擇2個結果,第三場做膽,進行3串1玩法,當然這里的例子很簡單,大家腦袋想一想就知道是4個結果。如果是其他玩法,每個有3,4個選擇,有5串1 ,那就麻煩了,何苦都必須要自動生成出組合來。所以必須得考慮一個通用的情況。而且在進行預測以及分析的時候,通常要對包含所有結果的幾場比賽進行串分析,就需要計算所有排列組合的結果形式了例如下面這種總進球的多串1選擇:

3.排列組合生成代碼與測試

3.1 N場單個玩法所有結果的組合

    比如勝平負有3個玩法,【3,1,0】,那么我有N場比賽,要進行串組合,計算所有的組合情況。寫一個通用的函數,使用KwCombinatorics的笛卡爾積來完成,直接看代碼和注釋,注意使用之前要引用對應的dll和命名空間:

/// <summary>單個不同玩法,任意場次數的結果全部結果組合</summary>
/// <typeparam name="T">結果類型,主要分字符串,整數</typeparam>
/// <param name="source">該玩法的所有結果列表</param>
/// <param name="count">場次數量:每一個場次都可能會出現source中的結果</param>
/// <returns>所有組合的列表</returns>
public static IEnumerable<List<T>> PermuteResultForSingle<T>(this List<T> source, int count)
{
	//實例化N場比賽的所有結果數組,每一個List都包括所有結果
	List<T>[] sourceList = new List<T>[count];
	Int32[] sizes = new Int32[count];

	for (int i = 0; i < count; i++)
	{
		sourceList[i] = source;
		sizes[i] = source.Count;
	}
	//使用笛卡爾積的形式來生成
	var pt = new Product(sizes);
	//依次生產所有組合,每一個組合都是結果的集合
	foreach (var row in pt.GetRows())
	{
		yield return Product.Permute(row, sourceList);
	}
}

    考慮到調用方便,這里寫成了擴展方法,並使用了泛型,也就是說可以直接處理整數結果形式,也可以處理漢字字符串結果形式。那我們進行一下測試看看。

先看測試代碼,我們假設勝平負玩法,2場比賽,應該是有9種結果:

static void Test1()
{
	//先定義每一個玩法的所有結果類型,勝平負有3個結果
	var result = new List<Int32>() { 3,1,0};
	//直接擴展方法計算,並傳入場次數量參數,我們計算2場的所有組合
	var combList = result.PermuteResultForSingle<Int32>(2);
	foreach (var item in combList)
	{
		//將結果轉換為字符串依次打印
		//ArrayToString是一個將數組列表轉換為字符串的擴展方法
		Console.WriteLine(item.ArrayToString());
	}
}

看看結果:

    其實還可以處理字符串類型的情況,例如我們把代碼改成這樣:

var result = new List<String>() { "勝","平","負"};
//直接擴展方法計算,並傳入場次數量參數,我們計算2場的所有組合
var combList = result.PermuteResultForSingle<String>(2);
foreach (var item in combList)
{
	//將結果轉換為字符串依次打印	
	Console.WriteLine(item.ArrayToString());
}

    結果如下,當然你可以修改數量,計算更多復雜的情況,一 一進行處理。

3.2 混合玩法的多個結果組合

    在競彩的混投玩法中,可以選擇任意場次的不同玩法進行組合,比如,你A比賽可以選擇勝平負結果,而B比賽選擇大小球,然后串起來進行投注。情況有時候會更復雜,這種情況下,玩家為了刺激,會適當增加結果數量,然后進行串投注。其實整體思路和3.1差不多,只不過由於每個玩法的結果類型不一樣,需要將參數轉換為object,才更好處理。看看代碼,也是擴展方法:

/// <summary>混合不同玩法,任意場次的多個結果的組合</summary>
/// <param name="source">場次按順序選擇的玩法的所有結果列表</param>
/// <returns></returns>
public static IEnumerable<List<Object>> PermuteResultForMixture(this List<Object>[] source)
{
	//初始化所有場次玩法結果的數據
	Int32[] sizes = new Int32[source.Length];
	for (int i = 0; i < source.Length; i++) sizes[i] = source[i].Count;
	//使用笛卡爾積,只不過這里都是Object,不在針對同一種玩法了
	var pt = new Product(sizes);
	foreach (var row in pt.GetRows())
	{
		yield return Product.Permute(row, source);
	}
}

    看看實際的測試結果,當然你也可以把所有玩法都搞一樣的,相對是同一種玩法的N場比賽,選擇不同部分結果進行的組合了:

//勝平負場次的結果選擇
var R1 = new List<Object>() { "勝","平"};
//總進球數結果的選擇
var R2 = new List<Object>() { 2,3,4 };
//半全場結果的選擇
var R3 = new List<Object>() { "勝負" ,"平負"};
//綜合所有選擇
var result = new List<Object>[] { R1, R2, R3 };
//計算所有組合
var combList = result.PermuteResultForMixture();
foreach (var item in combList)
{
	//打印組合,逗號分割,應該有2*3*2=12種組合
	Console.WriteLine(item.ArrayToString());
}

    看結果:

    其他使用很簡單了,依次類推吧。KwCombinatorics的確是很強大,只要和排列組合相關的需求,沒有搞不定的。代碼,效率都值得點贊。本文代碼很簡單,就不列舉了,詳細的可以看上面的系列文章。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM