Finding perfect numbers (optimization) - c#

I coded up a program in C# to find perfect numbers within a certain range as part of a programming challenge . However, I realized it is very slow when calculating perfect numbers upwards of 10000. Are there any methods of optimization that exist for finding perfect numbers? My code is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleTest
{
class Program
{
public static List<int> FindDivisors(int inputNo)
{
List<int> Divisors = new List<int>();
for (int i = 1; i<inputNo; i++)
{
if (inputNo%i==0)
Divisors.Add(i);
}
return Divisors;
}
public static void Main(string[] args)
{
const int limit = 100000;
List<int> PerfectNumbers = new List<int>();
List<int> Divisors=new List<int>();
for (int i=1; i<limit; i++)
{
Divisors = FindDivisors(i);
if (i==Divisors.Sum())
PerfectNumbers.Add(i);
}
Console.Write("Output =");
for (int i=0; i<PerfectNumbers.Count; i++)
{
Console.Write(" {0} ",PerfectNumbers[i]);
}
Console.Write("\n\n\nPress any key to continue . . . ");
Console.ReadKey(true);
}
}
}

Use the formula
testPerfect = 2n-1(2n - 1)
to generate possiblities then check wether the number is in fact perfect.
try this for some bedtime reading

Do perfect numbers change? No. Look here. Surely, they should be calculated once and then stored.
In your case, the only results will be
6
28
496
8128
The next one is 33550336. Outside your range.

Just the obvious one from me: you don't need to check every divisor. No point looking for divisors past inputNo/2. That cuts down half of the calculations, but this is not an order of magnitude faster.

One way to solve things like this involves building a huge array in memory of every number, and then crossing numbers out.

if your still looking for something to calculate perfect numbers.
this goes through the first ten thousand pretty quick, but the 33 million number is a little slower.
public class Perfect {
private static Perfect INSTANCE = new Perfect();
public static Perfect getInstance() {
return INSTANCE;
}
/**
* the method that determines if a number is perfect;
*
* #param n
* #return
*/
public boolean isPerfect(long n) {
long i = 0;
long value = 0;
while(++i<n){
value = (0 == n%i?value+i:value);
}
return n==value;
}
}

For anyone interested in a LINQ based approach, the following method worked quite well and efficiently for me in determining whether or not a caller supplied integer value is a perfect number.
bool IsPerfectNumber(int value)
{
var isPerfect = false;
int maxCheck = Convert.ToInt32(Math.Sqrt(value));
int[] possibleDivisors = Enumerable.Range(1, maxCheck).ToArray();
int[] properDivisors = possibleDivisors.Where(d => (value % d == 0)).Select(d => d).ToArray();
int divisorsSum = properDivisors.Sum();
if (IsPrime(divisorsSum))
{
int lastDivisor = properDivisors.Last();
isPerfect = (value == (lastDivisor * divisorsSum));
}
return isPerfect;
}
For simplicity and clarity, my implementation for IsPrime(), which is used within IsPerfectNumber(), is omitted.

To continue from Charles Gargent's answer there is a very quick way to check if a Mersenne Number a.k.a. 2^n - 1 is prime. It is called the Lucas-Lehmer test
The basic pseudocode though (taken from the Wikipedia page) is:
// Determine if Mp = 2p − 1 is prime for p > 2
Lucas–Lehmer(p)
var s = 4
var M = 2p − 1
repeat p − 2 times:
s = ((s × s) − 2) mod M
if s == 0 return PRIME else return COMPOSITE

Related

How can I make this a recursive statement in C#?

The program needs to solve powers of 2 in a table showing n and 2n for n = 1 to 10. Here is my program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Power
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine($"Number Power of 2");
Console.WriteLine("------------------------");
for (long counter = 1; counter <= 10; ++counter)
{
Console.WriteLine($"{counter, 2} {Power(counter), 20}");
}
Console.ReadLine();
}
static long Power(long number, long exponentValue = 2)
{
long result = 1;
for (int i = 1; i <= number; i++)
{
result *= exponentValue;
}
return result;
}
}
}
But it needs to be recursive. How can I make this function recursive?
This code will look like this:
static long Power(long number, long exponentValue = 2)
{
if (number < 1)
{
return 0; // or throw exception because this shouldn't happen
}
if (number == 1)
{
return exponentValue;
}
return exponentValue * Power(number - 1, exponentValue);
}
[RANT]
This one of those artificial problems meant to teach you about recursion, but doesn't do a good job because there are better non-recursive solutions (such as your current one). In fact, you usually want to convert a recursive solution TO a loop, to avoid possible stack-overflow errors!
[/RANT]
In very general terms: To convert a loop to a recursive solution, you need to find a way of computing part of the solution, and then calling the method again to compute the remainder of the solution, until it is completely solved. There must also be a way to detect when no further recursion is needed.
In the case of computing a power, the answer will be:
Pow(X,N) => N * Pow(X,N-1)
And:
Pow(X,1) => X (this will be the state that terminates the recursion).
So think about how this works for X = 2 and N = 3:
Pow(2,3) => 2 * Pow(2,2)
Pow(2,2) => 2 * Pow(2,1)
Pow(2,1) => 2 (the terminating condition)
Here you wind up with 2*2*2 = 8, which is indeed 2^3.
Note how the N value goes down by 1 each time until it reaches 1, at which point no more recursion is required.
Writing this in C# terms:
static long Power(long number, long exponentValue)
{
if (exponentValue == 1)
return number;
else
return number * Power(number, exponentValue - 1);
}
Note: I did not write any error handling in order to focus on the recursive part. Real code would check that exponentValue was >= 1 and so on.
Further note: The correct terminology for the power is "Exponent" so I have used that terminology. You have it the wrong way around, so I would urge you to correct that! An exponent is the number of times the number is multiplied by itself.
static long Power(long number, long exponentValue = 2)
{
if (number == 1)
{
return 1;
}
else
{
return Power(number - 1, exponentValue) * exponentValue;
}
}

Fast and low-memory-consumption way to read in pair of numbers from file and process them?

Okay, so this is my challenge taken from CodeEval. I have to read numbers from a file that is formatted in a standard way, it has a pair of numbers separated by a comma on each line (x, n). I have to read in the pair values and process them, then print out the smallest multiple of n which is greater than or equal to x, where n is a power of 2.
EXACT REQUIREMENT: Given numbers x and n, where n is a power of 2, print out the smallest multiple of n which is greater than or equal to x. Do not use division or modulo operator.
I have come up with a number of solutions, but none of them satisfy the computer's conditions to let me pass the challenge. I only get a partial completion with scores that vary from 30 to 80 (from 100).
I'm assuming that my solutions do not pass the speed but more likely the memory-usage requirements.
I would greatly appreciate it if anyone can enlighten me and offer some better, more efficient solutions.
Here are two of my solutions:
var filePath = #"C:\Users\myfile.txt";
int x;
int n;
using (var reader = new StreamReader(filePath))
{
string numsFile = string.Empty;
while ((numsFile = reader.ReadLine()) != null)
{
var nums = numsFile.Split(',').ToArray();
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
}
<<<>>>
var fileNums = File.ReadAllLines(filePath);
foreach (var line in fileNums)
{
var nums = line.Split(',').ToArray();
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
Method to check numbers
public static int DangleNumbers(int x, int n)
{
int m = 2;
while ((n * m) < x)
{
m += 2;
}
return m * n;
}
I'm fairly new to C# and programming but these two ways I found to get the best score from several others I have tried. I'm thinking that it's not too optimal for a new string to be created on each iteration, nor do I know how to use a StringBuilder and get the values into an Int from it.
Any pointers in the right direction would be appreciated as I would really like to get this challenge passed.
The smallest multiple of n that is larger or equal to x is likely this:
if(x <= n)
{
return n;
}
else
{
return x % n == 0 ? x : (x/n + 1) * n;
}
As x and n are integers, the result of x/n will be truncated (or effectively rounded down). So the next integer larger than x that is a multiple of n is (x/n + 1) * n
Since you missed the requirements, the modulo version was the most obvious choice. Though you still got your method wrong. m = 2 would not result in the smallest being returned but it could actually be the double of the smallest if n is already larger than x.
x = 7, n = 8 would get you 16 instead of 8.
Also adding 2 to m would result in a similar problem.
x = 5, n = 2 would get you 8 instead of 6.
use the following method instead:
public static int DangleNumbers(int x, int n)
{
int result = n;
while(result < x)
result += n;
return result;
}
Still capable of begin optimized but at least right according to the (now) stated constraints.
I have tried to improve the solution with some suggestions from you guys and take the variables outside the loop and drop the ToArray() call which was redundant.
static void Main(string[] args)
{
var filePath = #"C:\Users\sorin\Desktop\sorvas.txt";
int x;
int n;
string[] nums;
using (var reader = new StreamReader(filePath))
{
string numsFile = string.Empty;
while ((numsFile = reader.ReadLine()) != null)
{
nums = numsFile.Split(',');
x = int.Parse(nums[0]);
n = int.Parse(nums[1]);
Console.WriteLine(DangleNumbers(x, n));
}
}
}
public static int DangleNumbers(int x, int n)
{
int m = 2;
while ((n * m) < x)
{
m += 2;
}
return m * n;
}
So it looks like this. The thing is that even if now the numbers have slightly improved, I got a lower score.
May it be their system to blame ?
Using the first option of reading line by line (rather than reading all lines) is clearly going to use less memory (except potentially in the case where the file is very small (eg "1,1") in which case the overhead of the reader may cause problems but at that point the memory used is probably irrelevant.
Likewise declaring the variables outside the loop is generally better but in this case since the objects are value types I'm not sure it makes a difference.
Lastly the most efficient way of doing your DangleNumbers method is probably using bitwise logic operators and the fact that n is always a power of 2. Here is my attempt:
public static int DangleNumbers3(int x, int n)
{
return ((x-1) & ~(n-1))+n;
}
Essentially it relies on the fact that in binary a power of n is always a 1 followed by zero or more zeros. Thus a multiple of n will always end in that same number of zeros. So if n has M zeros after the one then you can take the binary form of x and if it already ends in M zeros then you have your answer. Otherwise you zero out the last M digits at which point you have the multiple of n that is just under x and then you add 1.
In the code ~(n-1) is a bitmask that has M zeros at the end and the leading digits are all 1. Thus when you AND it with a number it will zero out the trailing digits. I apply this to (x-1) to avoid having to do the check for if it is already the answer and have special cases.
It is important to note that this only works because of the special form of n as a power of 2. This method avoids the need for any loops and thus should run much faster (it has five operations total and no branching at all compared to other looping methods which will tend to have at the very least an operation and a comparison per loop.

How to cycle through an (n by 12) 2D array

I have a 2-D array (with dimensions magnitudes n by 5), which I'm picturing in my head like this (each box is an element of the array):
(http://tr1.cbsistatic.com/hub/i/2015/05/07/b1ff8c33-f492-11e4-940f-14feb5cc3d2a/12039.jpg)
In this image, n is 3. I.e, n is the number of columns, 5 is the number of rows in my array.
I want to find an efficient way to iterate (i.e walk) through every path that leads from any cell in the left most column, to any cell in right most column, choosing one cell from every column in between.
It cannot be simply solved by n nested loops, because n is only determined at run time.
I think this means recursion is likely the best way forward, but can't picture how to begin theoretically.
Can you offer some advice as to how to cycle through every path. It seems simple enough and I can't tell what I'm doing wrong. Even just a theoretical explanation without any code will be very much appreciated.
I'm coding in C#, Visual Studio in case that helps.
UPDATE:: resolved using code below from http://www.introprogramming.info/english-intro-csharp-book/read-online/chapter-10-recursion/#_Toc362296468
static void NestedLoops(int currentLoop)
{
if (currentLoop == numberOfLoops)
{
return;
}
for (int counter=1; counter<=numberOfIterations; counter++)
{
loops[currentLoop] = counter;
NestedLoops(currentLoop + 1);
}
}
This is a factorial problem and so you might run quite quickly into memory or value limits issues.
Took some code from this SO post by Diego.
class Program
{
static void Main(string[] args)
{
int n = 5;
int r = 5;
var combinations = Math.Pow(r, n);
var list = new List<string>();
for (Int64 i = 1; i < combinations; i++)
{
var s = LongToBase(i);
var fill = n - s.Length;
list.Add(new String('0', fill) + s);
}
// list contains all your paths now
Console.ReadKey();
}
private static readonly char[] BaseChars = "01234".ToCharArray();
public static string LongToBase(long value)
{
long targetBase = BaseChars.Length;
char[] buffer = new char[Math.Max((int)Math.Ceiling(Math.Log(value + 1, targetBase)), 1)];
var i = (long)buffer.Length;
do
{
buffer[--i] = BaseChars[value % targetBase];
value = value / targetBase;
}
while (value > 0);
return new string(buffer);
}
}
list will contain a list of numbers expressed in base 5 which can be used to found out the path. for example "00123" means first cell, then first cell then second cell, then third cell and finall fourth cell.
Resolved:: see the code posted in the edited question above, and the link to a recursion tutorial, where it takes you through using recursion to simulate N nested, iterative loops.

c# optimizing cycle working with big numbers

I have this code that finds numbers in a given range that contain only 3 and 5 and are polynoms(symetrical, 3553 for example). The problem is that the numbers are between 1 and 10^18, so there are cases in which I have to work with big numbers, and using BigInteger makes the program way too slow, so is there a way to fix this ? Here's my code:
namespace Lucky_numbers
{
class Program
{
static void Main(string[] args)
{
string startString = Console.ReadLine();
string finishString = Console.ReadLine();
BigInteger start = BigInteger.Parse(startString);
BigInteger finish = BigInteger.Parse(finishString);
int numbersFound = 0;
for (BigInteger i = start; i <= finish; i++)
{
if (Lucky(i.ToString()))
{
if (Polyndrome(i.ToString()))
{
numbersFound++;
}
}
}
}
static bool Lucky(string number)
{
if (number.Contains("1") || number.Contains("2") || number.Contains("4") || number.Contains("6") || number.Contains("7") || number.Contains("8") || number.Contains("9") || number.Contains("0"))
{
return false;
}
else
{
return true;
}
}
static bool Polyndrome(string number)
{
bool symetrical = true;
int middle = number.Length / 2;
int rightIndex = number.Length - 1;
for (int leftIndex = 0; leftIndex <= middle; leftIndex++)
{
if (number[leftIndex] != number[rightIndex])
{
symetrical = false;
break;
}
rightIndex--;
}
return symetrical;
}
}
}
Edit: Turns out it's not BigInteger, it's my shitty implementation.
You could use ulong:
Size: Unsigned 64-bit integer
Range: 0 to 18,446,744,073,709,551,615
But I would guess that BigInteger is not a problem here. I think you should create algorithm for palindrome creation instead of brute-force increment+check solution.
Bonus
Here is a palyndrome generator I wrote in 5 minutes. I think it will be much faster than your approach. Could you test it and tell how much faster it is? I'm curious about that.
public class PalyndromeGenerator
{
private List<string> _results;
private bool _isGenerated;
private int _length;
private char[] _characters;
private int _middle;
private char[] _currentItem;
public PalyndromeGenerator(int length, params char[] characters)
{
if (length <= 0)
throw new ArgumentException("length");
if (characters == null)
throw new ArgumentNullException("characters");
if (characters.Length == 0)
throw new ArgumentException("characters");
_length = length;
_characters = characters;
}
public List<string> Results
{
get
{
if (!_isGenerated)
throw new InvalidOperationException();
return _results.ToList();
}
}
public void Generate()
{
_middle = (int)Math.Ceiling(_length / 2.0) - 1;
_results = new List<string>((int)Math.Pow(_characters.Length, _middle + 1));
_currentItem = new char[_length];
GeneratePosition(0);
_isGenerated = true;
}
private void GeneratePosition(int position)
{
if(position == _middle)
{
for (int i = 0; i < _characters.Length; i++)
{
_currentItem[position] = _characters[i];
_currentItem[_length - position - 1] = _characters[i];
_results.Add(new string(_currentItem));
}
}
else
{
for(int i = 0; i < _characters.Length; i++)
{
_currentItem[position] = _characters[i];
_currentItem[_length - position - 1] = _characters[i];
GeneratePosition(position + 1);
}
}
}
}
Usage:
var generator = new PalyndromeGenerator(6, '3', '5');
generator.Generate();
var items = generator.Results.Select(x => ulong.Parse(x)).ToList();
Strange riddle, but can be simplified if I understand the requirement.
I would first map these numbers to binary as there is only two possible
"lucky" digits, then generate the numbers by counting in binary until
I have completed nine bits. Reflect it for the full number, then
convert 0 to 3 and 1 to 5.
Example 1101
Reflect it = 10111101 --> 53555535
Do this from 0 all the way to 111111111
Declare start and finish to be static inside the class.
Change the method Lucky to:
static bool Lucky(string number)
{
return !(number.Contains("1") || number.Contains("2") || number.Contains("4") || number.Contains("6") || number.Contains("7") || number.Contains("8") || number.Contains("9") || number.Contains("0"));
}
Also, you can use Parallel library to parallelize the computation.
Instead of using a regular for loop, you could use a Parallel.For.
Look at the problem a different way - how many strings of up to 9 characters (using only '3' and '5') can you make? for each string you have 2 palindromes (one repeating the last character, one not) that you can make.
e.g.
3 -> 33
5 ->, 55
33 -> 333, 3333
35 -> 353, 3553
53 -> 535, 5335
...
The only suggestion I have is to use a 3rd party library like intx, or some unmanaged code. The intx author reports that it can work faster than BigInteger in some situations: "System.Numerics.BigInteger class was introduced in .NET 4.0 so I was interested in performance of this solution. I did some tests (grab test code from GitHub) and it appears that BigInteger has performance in general comparable with IntX on standard operations but starts losing when FHT comes into play (when multiplying really big integers, for example)."
Since the number has to be symmetrical, you only need to check the first half of the number. You don't need to check 18 digits, you only have to check to 9 digits and then swap the order of the characters and add them to the back as a string.
One thing I can think of is if you are only going to count integers that are containing 3 or 5 you don't need to traverse the entire list of numbers between your beginning & ending range.
Instead, look at your character set as either '3' or '5'. Then you can simply go through the allowed permutations of half of the number itself, leaving the other half to be completed to successfully create a polyndrome.
There are some rules to this method which would help, such as :
if the starting number's left-most digit was greater than 5 there is no need to attempt for that specific number of digits.
if both numbers fall on the same amount of digits but left-most digits do not traverse / include 5 or 3, no need to process.
Developing some set of rules such as this may help other than attempting to check every possible permutation.
So, for example, your Lucky function would become something more along the lines of :
static bool Lucky(string number)
{
if((number[0] != '3') && (number[0] != '5'))
{
return false;
} //and you could continue this for the entire string
...
}

Help with maths/coding on possible combinations of a set to make up a total - C#

I have a coding/maths problem that I need help translating into C#. It's a poker chip calculator that takes in the BuyIn, the number of players and the total amount of chips for each colour (there are x amount of colours) and their value.
It then shows you every possible combination of chips per person to equal the Buy In. The user can then pick the chipset distribution they would like to use. It's best illustrated with a simple example.
BuyIn: $10
Number of Players: 1
10 Red Chips, $1 value
10 Blue Chips, $2 value
10 Green Chips, $5 value
So, the possible combinations are:
R/B/G
10/0/0
8/1/0
6/2/0
5/0/1
4/3/0
2/4/0
1/2/1
etc.
I have spent a lot of time trying to come up with an algorithm in C#/.NET to work this out. I am stumbling on the variable factor - there's usually only 3 or 4 different chips colours in a set, but there could be any amount. If you have more than one player than you have to count up until TotalChips / NumberOfPlayers.
I started off with a loop through all the chips and then looping from 0 up to NumberOfChips for that colour. And this is pretty much where I have spent the last 4 hours... how do I write the code to loop through x amount of chips and check the value of the sum of the chips and add it to a collection if it equals the BuyIn? I need to change my approach radically methinks...
Can anyone put me on the right track on how to solve this please? Pseudo code would work - thank you for any advice!
The below is my attempt so far - it's hopeless (and wont compile, just an example to show you my thought process so far) - Might be better not to look at it as it might biased you on a solution...
private void SplitChips(List<ChipSuggestion> suggestions)
{
decimal valueRequired = (decimal)txtBuyIn.Value;
decimal checkTotal = 0;
ChipSuggestion suggestion;
//loop through each colour
foreach (Chip chip in (PagedCollectionView)gridChips.ItemsSource)
{
//for each value, loop through them all again
foreach (Chip currentChip in (PagedCollectionView)gridChips.ItemsSource)
{
//start at 0 and go all the way up
for (int i = 0; i < chip.TotalChipsInChipset; i++)
{
checkTotal = currentChip.ChipValue * i;
//if it is greater than than ignore and stop
if (checkTotal > valueRequired)
{
break;
}
else
{
//if it is equal to then this is a match
if (checkTotal == valueRequired)
{
suggestion = new ChipSuggestion();
suggestion.SuggestionName = "Suggestion";
chipRed.NumberPerPlayer = i;
suggestion.Chips.Add(chipRed);
chipBlue.NumberPerPlayer = y;
suggestion.Chips.Add(chipBlue);
chipGreen.NumberPerPlayer = 0;
suggestion.Chips.Add(chipGreen);
//add this to the Suggestion
suggestions.Add(suggestion);
break;
}
}
}
}
}
}
Here's an implementation that reads the number of chips, the chips (their worth and amount) and the buyin and displays the results in your example format. I have explained it through comments, let me know if you have any questions.
class Test
{
static int buyIn;
static int numChips;
static List<int> chips = new List<int>(); // chips[i] = value of chips of color i
static List<int> amountOfChips = new List<int>(); // amountOfChips[i] = number of chips of color i
static void generateSolutions(int sum, int[] solutions, int last)
{
if (sum > buyIn) // our sum is too big, return
return;
if (sum == buyIn) // our sum is just right, print the solution
{
for (int i = 0; i < chips.Count; ++i)
Console.Write("{0}/", solutions[i]);
Console.WriteLine();
return; // and return
}
for (int i = last; i < chips.Count; ++i) // try adding another chip with the same value as the one added at the last step.
// this ensures that no duplicate solutions will be generated, since we impose an order of generation
if (amountOfChips[i] != 0)
{
--amountOfChips[i]; // decrease the amount of chips
++solutions[i]; // increase the number of times chip i has been used
generateSolutions(sum + chips[i], solutions, i); // recursive call
++amountOfChips[i]; // (one of) chip i is no longer used
--solutions[i]; // so it's no longer part of the solution either
}
}
static void Main()
{
Console.WriteLine("Enter the buyin:");
buyIn = int.Parse(Console.ReadLine());
Console.WriteLine("Enter the number of chips types:");
numChips = int.Parse(Console.ReadLine());
Console.WriteLine("Enter {0} chips values:", numChips);
for (int i = 0; i < numChips; ++i)
chips.Add(int.Parse(Console.ReadLine()));
Console.WriteLine("Enter {0} chips amounts:", numChips);
for (int i = 0; i < numChips; ++i)
amountOfChips.Add(int.Parse(Console.ReadLine()));
int[] solutions = new int[numChips];
generateSolutions(0, solutions, 0);
}
}
Enter the buyin:
10
Enter the number of chips types:
3
Enter 3 chips values:
1
2
5
Enter 3 chips amounts:
10
10
10
10/0/0/
8/1/0/
6/2/0/
5/0/1/
4/3/0/
3/1/1/
2/4/0/
1/2/1/
0/5/0/
0/0/2/
Break the problem down recursively by the number of kinds of chips.
For the base case, how many ways are there to make an $X buy-in with zero chips? If X is zero, there is one way: no chips. If X is more than zero, there are no ways to do it.
Now we need to solve the problem for N kinds of chips, given the solution for N - 1. We can take one kind of chip, and consider every possible number of that chip up to the buy-in. For example, if the chip is $2, and the buy-in is $5, try using 0, 1, or 2 of them. For each of these tries, we have to use only the remaining N - 1 chips to make up the remaining value. We can solve that by doing a recursive call, and then adding our current chip to each solution it returns.
private static IEnumerable<IEnumerable<Tuple<Chip, int>>> GetAllChipSuggestions(List<Chip> chips, int players, int totalValue)
{
return GetAllChipSuggestions(chips, players, totalValue, 0);
}
private static IEnumerable<IEnumerable<Tuple<Chip, int>>> GetAllChipSuggestions(List<Chip> chips, int players, int totalValue, int firstChipIndex)
{
if (firstChipIndex == chips.Count)
{
// Base case: we have no chip types remaining
if (totalValue == 0)
{
// One way to make 0 with no chip types
return new[] { Enumerable.Empty<Tuple<Chip, int>>() };
}
else
{
// No ways to make more than 0 with no chip types
return Enumerable.Empty<IEnumerable<Tuple<Chip, int>>>();
}
}
else
{
// Recursive case: try each possible number of this chip type
var allSuggestions = new List<IEnumerable<Tuple<Chip, int>>>();
var currentChip = chips[firstChipIndex];
var maxChips = Math.Min(currentChip.TotalChipsInChipset / players, totalValue / currentChip.ChipValue);
for (var chipCount = 0; chipCount <= maxChips; chipCount++)
{
var currentChipSuggestion = new[] { Tuple.Create(currentChip, chipCount) };
var remainingValue = totalValue - currentChip.ChipValue * chipCount;
// Get all combinations of chips after this one that make up the rest of the value
foreach (var suggestion in GetAllChipSuggestions(chips, players, remainingValue, firstChipIndex + 1))
{
allSuggestions.Add(suggestion.Concat(currentChipSuggestion));
}
}
return allSuggestions;
}
}
For some large combinations this is propably not solvable in finite time.
(It is a NP problem)
http://en.wikipedia.org/wiki/Knapsack_problem
There are also links with Code? that could help you.
Hope this helps a bit.

Categories