BinCoeffBase BCB; // Holds ref to actual binomial coeff class - Bincoeff (uint), BinCoeffL (ulong), or BinCoeffBigInt (BigInteger). // public BinCoeffGen(int numItems, int groupSize, bool initTable = false) { // This constructor builds the index tables used to retrieve the index to the binomial coefficient table. // n is the number of items and k is the number of items in a group, and reflects the case n choose k. // // Get the total number of unique combinations. BigInteger totalCombos = BinCoeffBase.GetCombosCountBigInt(numItems, groupSize); // If n & k result in overflow of ulong, then use BigInteger. Otherwise either use int or long for best performance. if (totalCombos > ulong.MaxValue) { BCB = new BinCoeffBigInt(numItems, groupSize, totalCombos); } else if (totalCombos <= int.MaxValue) { BCB = new BinCoeff <T>(numItems, groupSize, (uint)totalCombos, initTable); } else { BCB = new BinCoeffL(numItems, groupSize, (ulong)totalCombos); } }
public static void OutputCombos <U>(string filePath, string[] dispChars, string sep, string groupSep, int maxCharsInLine, BinCoeffBase bcb, U startRank, U endRank) { // This function writes out the K indexes in sorted order to either a file or a list. It is used by all 3 implementations. // U specifies uint, ulong, or BigInteger. // filePath - path & name of file. // dispChars - if not null, then the string in DispChars is displayed instead of the // numeric value of the corresponding combination. // sep - String used to separate each individual combination in a group. // groupSep - String used to separate each combination group. // maxCharsInLine - maximum number of chars in an output line. // bcb - the type to be worked on - either Bincoeff (uint), BincoeffL (ulong), or BinCoeffBig (BigInteger). // startRank - the first combo that should be output. Range is zero to NumCombos - 1. // endRank - the last combo that should be output. If startRank > endRank, then output is in descending order. // // No more than 2^31 combinations are output. // const int bufferSize = 65536; int loop1, n, outPos = 0; int offset = 0, inc, outCount = 0, elemCount = 0; int maxCharsInN = bcb.NumItems / 10 + 1; var kIndexes = new int[bcb.GroupSize]; var outbuf = new byte[maxCharsInLine + 2]; string s, s1; StringBuilder sb = new StringBuilder(); FileStream outFile = new FileStream(filePath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize, FileOptions.None); // Set to output in ascending or descending order depending if startRank < endRank. dynamic dynStart = startRank, dynEnd = endRank; inc = (dynStart > dynEnd) ? -1 : 1; outCount = (dynEnd - dynStart) * inc; // Output the K Indexes do { bcb.GetCombFromRank(startRank, offset, kIndexes); offset += inc; for (loop1 = 0; loop1 < bcb.GroupSize; loop1++) { n = kIndexes[loop1]; if (dispChars != null) { s = dispChars[n]; } else { s1 = "{0, " + maxCharsInN.ToString() + "}"; s = String.Format(s1, kIndexes[loop1]); } sb.Append(s); if (loop1 < bcb.GroupSizeM1) { sb.Append(sep); } } if (outPos + sb.Length >= maxCharsInLine) { outbuf[outPos++ - groupSep.Length] = (byte)'\r'; outbuf[outPos - groupSep.Length] = (byte)'\n'; outFile.Write(outbuf, 0, outPos - groupSep.Length); outPos = 0; } sb.Append(groupSep); // Move the string value to the output buffer. for (loop1 = 0; loop1 < sb.Length; loop1++) { outbuf[outPos++] = (byte)sb[loop1]; } sb.Remove(0, sb.Length); elemCount++; } while (elemCount <= outCount); if (outPos > 0) { outFile.Write(outbuf, 0, outPos - groupSep.Length); } outFile.Close(); outFile.Dispose(); }