Click here to Skip to main content
15,893,337 members
Articles / Programming Languages / C#

Combinatorial algorithms in C#

Rate me:
Please Sign up or sign in to vote.
4.88/5 (28 votes)
19 Aug 20024 min read 173.5K   2.4K   69  
Some basic combinatorial algoritms for use in the NET framework
using System;

namespace Combinatorial
{
	/// <summary>
	/// Generates all the variations but NOT in lexicographical oreder
	/// </summary>
	public class Variations : CombinatorialBase {

		bool m_bPermutateNow = true;
		protected int[] m_arrayIndecesPermutation;
		protected int[] m_arrayIndecesCombination;

		public Variations(Array arrayObjects, int nKlass) : 
			base(arrayObjects, nKlass) 
		{
			m_arrayIndecesPermutation = new int[nKlass];
			m_arrayIndecesCombination = new int[nKlass];
		}

		public Variations(System.Collections.IList listObjects, int nKlass) : 
			base(listObjects, nKlass) 
		{
			m_arrayIndecesPermutation = new int[nKlass];
			m_arrayIndecesCombination = new int[nKlass];
		}

		public Variations(System.Collections.IEnumerator enumeratorObjects, int nKlass) : 
			base(enumeratorObjects, nKlass) 
		{
			m_arrayIndecesPermutation = new int[nKlass];
			m_arrayIndecesCombination = new int[nKlass];
		}

		private void FirstIndecesPermutation() {

			// Reinitialize the permutation index.
			for (int i = 0; i < m_arrayIndecesPermutation.Length; i++)
				m_arrayIndecesPermutation[i] = i;
		}

		override protected int[] FirstIndeces(bool bReturnDublicate) {

			// Do some extra initializing.
			FirstIndecesPermutation();

			// Reinitialize the combination index.
			for (int i = 0; i < m_arrayIndecesCombination.Length; i++)
				m_arrayIndecesCombination[i] = i;

			// Call the father method, because it is needed.
			return base.FirstIndeces(bReturnDublicate);
		}


		/*virtual*/
		override protected int[] NextIndeces(bool bReturnDublicate) {

			if (!m_bInitialized) {
				return FirstIndeces(false);
			}


			if (m_bPermutateNow) {
				// Generate a permutation of the current variation.
				int[] array = NextIndecesPermutation(bReturnDublicate);

				if (array.Length != 0)
					return array;

				// If we got here we cannot generate more permutations from
				// the current combination so we advance to the next combination
				// by allowing the CODE FLOW to execute the code bellow.
				m_bPermutateNow = false;
			}

			// Find the first item that has not reached its maximum value.
			int nIndex = m_nKlass;
			for (int i = m_arrayIndecesCombination.Length - 1; i >= 0; i--) {
				if (m_arrayIndecesCombination[i] < m_nMaxIndex - (m_nKlass - 1 - i)) {
					nIndex = i;
					break;
				}
			}

			// No more combinations to be generated. Every item has reached its
			// maximum value.
			if (nIndex == m_nKlass) 
				return new int[0];

			// Genereate the next combination in lexographical order.
			m_arrayIndecesCombination[nIndex]++;
			for (int i = nIndex + 1; i < m_arrayIndecesCombination.Length; i++) {
				m_arrayIndecesCombination[i] = m_arrayIndecesCombination[i-1] + 1;
			}

			// A new cobination has been generated. The next time we must
			// permutate it.
			m_bPermutateNow = true;
			FirstIndecesPermutation();

			// Absolutely needed copy.
			Array.Copy(m_arrayIndecesCombination, m_arrayIndeces, m_nKlass);

			if (bReturnDublicate) {
				// Copy not to allow modification of m_arrayIndeces.
				Array.Copy(m_arrayIndeces, m_arrayIndecesDummy, m_nKlass);
				return m_arrayIndecesDummy;
			} else {
				return m_arrayIndeces;
			}
		} // End of NextIndeces

		protected int[] NextIndecesPermutation(bool bReturnDublicate) {

			int nIndexLast = m_arrayIndecesPermutation.Length-1;

			// Find the first item so that a[i] < a[i+1];
			int nIndexI = m_nKlass;
			for (int i = nIndexLast - 1; i >= 0; i--) {
				if (m_arrayIndecesPermutation[i] < m_arrayIndecesPermutation[i+1] ) {
					nIndexI = i;
					break;
				}
			}

			// Find the smallest a[j] , so that j > i & a[j] > a[i]
			int nIndexJ = nIndexLast;
			for (int j = nIndexJ; j > nIndexI; j--) {
				if (m_arrayIndecesPermutation[j] > m_arrayIndecesPermutation[nIndexI]) {
					nIndexJ = j;
					break;
				}
			}

			// No more permutations to be generated. 
			if (nIndexI == m_nKlass) 
				return new int[0];

			// Exchange the a[i] and the last item (a[n]).
			int nTmp = m_arrayIndecesPermutation[nIndexI];
			m_arrayIndecesPermutation[nIndexI] = m_arrayIndecesPermutation[nIndexJ];
			m_arrayIndecesPermutation[nIndexJ] = nTmp;

			// Reverse the items from a[i+1] till a[n];
			int i0 = nIndexI+1;
			int j0 = nIndexLast;
			while (i0 < j0) {
				nTmp = m_arrayIndecesPermutation[i0];
				m_arrayIndecesPermutation[i0] = m_arrayIndecesPermutation[j0];
				m_arrayIndecesPermutation[j0] = nTmp;
				i0++;
				j0--;
			}

			for (int i1 = 0; i1 < m_nKlass; i1++) {
				int nIndex = m_arrayIndecesPermutation[i1];
				m_arrayIndeces[i1] = m_arrayIndecesCombination[nIndex];
			}

			// The RETURN section.
			if (bReturnDublicate) {
				// Copy not to allow modification of m_arrayIndeces.
				Array.Copy(m_arrayIndeces, m_arrayIndecesDummy, m_nKlass);
				return m_arrayIndecesDummy;
			} else {
				return m_arrayIndeces;
			}

		} // End of NextIndecesPermutation

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Bulgaria Bulgaria
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions