Reputation: 8225
I have a listbox where users can enter decimal numbers. Let's say they'll enter 5 numbers:
1.1
1.2
1.3
1.4
1.5
I need to get the sum of all the variations in those 5 numbers. For example sum of 1.1 and 1.2
then 1.1 1.2 1.3
then 1.1 1.2 1.3 1.4
, then 1.2 1.4 1.5
then 1.1 1.3 1.5
.
I started something but that goes through all the variations only skipping one number at a time:
List<Double[]> listNumber = new List<double[]>();
Double[] array;
for (int i = 0; i < listBox1.Items.Count; i++)
{
array = new Double[listBox1.Items.Count];
for (int k = 0; k < listBox1.Items.Count; k++)
{
if (!k.Equals(i))
{
array[k] = (Convert.ToDouble(listBox1.Items[k]));
}
}
listNumber.Add(array);
}
I need to find a way how to calculate the way I want.
Upvotes: 5
Views: 1808
Reputation: 18960
Take your listBox
and, in front of each number, either put a 0
to indicate that it will not participate to your sum or a 1
to indicate that it will participate to your sum. With your example list of 1.1
, 1.2
, 1.3
, 1.4
, 1.5
and the sums of 1.1
, 1.2
then 1.1 1.2 1.3
then 1.1 1.2 1.3 1.4
then 1.2 1.4 1.5
then 1.1 1.3 1.5
this would give you (I only write 1
s for clarity, the empty spaces mean 0
):
| | | 1.1 | |
| | 1.1 | 1.2 | 1.2 | 1.1
| | 1.2 | 1.3 | 1.4 | 1.3
1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.5
---+-----+-----+-----+-----+-----+-----
1.1| 1 1 1 1
1.2| 1 1 1 1
1.3| 1 1 1
1.4| 1 1
1.5| 1 1
As you can now see with such a representation, listing all combinations of these numbers is now similar to counting in from 0 to 31 (11111 in binary, 2⁵ - 1
). If you are not interested in the empty sequence then start counting from 1.
Here is sample code to transform this counting into an listNumber
like you want. Please excuse the syntax as I do not know C#. This also means that this is untested code.
Double[] array = new Double[listBox1.Items.Count];
for (int i = 0; i < listBox1.Items.count; i++)
array[k] = Convert.ToDouble(listBox1.Items[i]);
int count = 2 ^ array.Items.Count;
List<Double>[] listNumber = new List<Double>[count];
for (int i = 0; i < listNumber.Items.Count; i++) {
listNumber[i] = new List<Double>();
for (j = 0; j < array.Items.Count)
if (i & (1 << j) != 0)
listNumber[i].Add(array[j]);
}
Upvotes: 0
Reputation: 18533
In your initial attempt, your code only calculates the sum of all possible pairs. From your description, you also want to find the sum of three numbers, etc..
If there are always 5 decimal numbers, then you can simply have 5 for loops. However a more generic design would be cleaner
double[] input = double[5]; //Pretend the user has entered these
int[] counters = int[input.Length]; //One for each "dimension"
List<double> sums = new List<double>();
for (int i = 0; i < counters.Length; i++)
counters[i] = -1; //The -1 value allows the process to begin with sum of single digits, then pairs, etc..
while (true)
{
double thisSum = 0;
//Apply counters
for (int i = 0; i < counters.Length; i++)
{
if (counters[i] == -1) continue;
thisSum += input[counters[i]];
}
//Increment counters
counters[0]++; //Increment at base
for (int i = 0; i < counters.Length; i++)
{
if (counters[i] >= counters.Length)
{
if (i == counters.Length - 1) //Check if this is the last dimension
return sums; //Exhausted all possible combinations
counters[i] = 0;
counters[i+1]++;
}
else
break;
}
}
Here it is without any code for avoiding the addition of the same number twice (I'll let you try to finish that off. HINT: You can simply do so after the increment counters section, containing both the "Increment Counters" section and the new "Check Counters" section inside a while loop, breaking outside the while loop when the counters are unique...
NOTE: I haven't tested this code, but it'll be close, and will likely have one or two bugs in it - let me know if you need any help with the bugs.
Upvotes: 1
Reputation: 50114
Just an outline as I'm on my phone:
Start with your input list and an output list that contains a zero.
For each number in your input, create a new list of doubles by adding the current input number to each of the numbers in the current output list; then concatenate this list to the end of the output list.
Optionally, remove the zero and the first instance of each of the input numbers, and any duplicates:
E.g. for your example input up to 1.4:
0
0 1.1
0 1.1 1.2 2.3
0 1.1 1.2 2.3 1.3 2.4 2.5 3.6
0 1.1 1.2 2.3 1.3 2.4 2.5 3.6 1.4 2.5 2.6 3.7 2.7 3.8 3.9 5.0
1.2 2.3 2.4 2.5 3.6 2.6 3.7 2.7 3.8 3.9 5.0
Upvotes: 1
Reputation: 41
While I'm not very proficient in C#, I'm positively sure there's a much more simple way of doing what you want to do; unless of course, I'm missing something.
Why not make a for loop for every element in the List or Array, and then tell it to skip itself. Example:
Double[] array = new Double[3];
array[0] = 1,1;
array[1] = 1,2;
array[2] = 1,3;
Double sum = 0;
for ( int i = 0; i < array.Length ; i++ )
{
for ( int x = 0 ; x < array.Length ; x++ ) {
if ( array[i] != array[x] )
{
sum = array[x] + array[x+1] // or [x-1] depending on the value of x, you should be able to work this out.
}
}
}
You should be able to understand what I mean by examining this example. Of course, this is a very basic prototype, what you'll do is expand this to check backwards depending on the value of x, and to have multiple "sum" variables to store your sums - depending on what kind of results you're looking for.
-I hope this helps, Merry Christmas.
Upvotes: 0