I use Winforms and C#. And I have more than 300 integers in a list and this is short example:
List<int> lst = new List<int>();
lst.Add(4);
lst.Add(25);
lst.Add(26);
lst.Add(27);
lst.Add(38);
lst.Add(51);
lst.Add(52);
lst.Add(53);
lst.Add(75);
//Etc.
I need to remove values (25, 26) but keep 27. Then again remove values (51, 52) but keep 53.. etc.
So basically if three consecutive values such as (1, 2, 3) are found, we need to remove (1, 2) and keep value (3).
As far as attempts are concerned, I couldn't scratch my head around any solution so far therefore I would appreciate any help.
Thanks
You could try the following. The key is marking the items to remove by detecting the sequence and picking the first two.
var excludeList = lst.Distinct()
.GroupBy(num =>
Enumerable.Range(num, int.MaxValue - num + 1)
.TakeWhile(lst.Contains)
.Last())
.Where(seq => seq.Count() >= 3)
.SelectMany(seq => seq.OrderBy(num => num).Take(2));
var result = lst.Where(x=> !excludeList.Contains(x));
Output
4
27
38
53
75
You can try this:
static void Test()
{
var list = new List<int>();
list.Add(4);
list.Add(25);
list.Add(26);
list.Add(27);
list.Add(38);
list.Add(51);
list.Add(52);
list.Add(53);
list.Add(75);
var result = new List<int>();
int count = list.Count;
bool passover;
if ( count > 0 )
for ( int index = 0; index < count; )
{
passover = false;
if ( index < count - 3 )
{
int v1 = list[index];
int v2 = list[index + 1];
int v3 = list[index + 2];
if ( v3 == v2 + 1 && v2 == v1 + 1 )
passover = true;
}
if ( passover )
{
result.Add(list[index + 2]);
index += 3;
}
else
{
result.Add(list[index]);
index++;
}
}
foreach ( var item in result )
Console.WriteLine(item);
}
Output:
4
27
38
53
75
Related
I have an sorted array having values like below: I need to calculate total as below:
Scenario 1 - Array values 12,15,17
12+15 = 27
27+17 = 44
44+27 = 71
Total = 71
Scenario 2 Array values 12,15,17,19
12+15 = 27
27+17 = 44
44+19 = 63
27+44+63 = 134
Total = 134
Scenario 3 Array values 12,15,17,19,23
12+15 = 27
27+17 = 44
44+19 = 63
63+23 = 86
27+44+63+86 = 220
Total = 220
Scenario 4 till N Array values 12,15,17,19,23.....N
I have to bring the above logic to C# code
I have written as below :
int[] myNumbers = new int[] { 100,250,1000};
Array.Sort(myNumbers);
int sum = 0;
int temp = 0;
foreach (int y in myNumbers)
{
sum = sum + y;
}
for(int i=0;i<myNumbers.Length-1;i++)
{
temp = temp + myNumbers[i];
}
sum = sum + temp;
Console.Write(sum);
The above code works fine for array values 100,250,1000
But it fails for any other array values
Need help!
Option 1
So if you want to get exact results as in your examples, you can use this method.
It will return you an array of partial sums, that you can later sum up to get the result:
private static long[] CumulativeSums(long[] values)
{
if (values == null || values.Length <= 1) return new long[0];
var results = new long[values.Length];
results[0] = values[0] + values[1];
for (var i = 1; i < values.Length - 1; i++)
{
results[i] = results[i - 1] + values[i + 1];
}
return results;
}
And the use it as this:
var numbers = new long[] { 12, 15, 17, 19 };
var sumOfCumulativeSums = CumulativeSums(numbers).Sum();
And sumOfCumulativeSums will be 134.
Option 2
But the actual correct representation of cumulative sum is: a, a+b, a+b+c, .... So if you want the correct representation of method that returns you proper cumulative sums, you can use this method instead:
public static long[] CumulativeSums(long[] values)
{
if (values == null || values.Length == 0) return new long[0];
var results = new long[values.Length];
results[0] = values[0];
for (var i = 1; i < values.Length; i++)
{
results[i] = results[i - 1] + values[i];
}
return results;
}
Edit
Hope this helps you to solve your problem in either of ways, and if you have any questions or edits about the code, please ask.
You can also obtain the sum without any intermediary array allocation:
static int Cumulate( int[] numbers )
{
if ( numbers == null || numbers.Length < 2 )
return 0;
Array.Sort( numbers );
var prevsum = numbers[0] + numbers[1];
var sum = prevsum;
for ( int i = 2 ; i < numbers.Length ; i++ )
{
prevsum += numbers[i];
sum += prevsum;
}
return sum;
}
I am having trouble with a small bit of code, which in a random size array, with random number pairs, except one which has no pair.
I need to find that number which has no pair.
arLength is the length of the array.
but i am having trouble actually matching the pairs, and finding the one which has no pair..
for (int i = 0; i <= arLength; i++)
{ // go through the array one by one..
var number = nArray[i];
// now search through the array for a match.
for (int e = 0; e <= arLength; e++)
{
if (e != i)
{
}
}
}
I have also tried this :
var findValue = nArray.Distinct();
I have searched around, but so far, i haven't been able to find a method for this.
This code is what generates the array, but this question isn't about this part of the code, only for clarity.
Random num = new Random();
int check = CheckIfOdd(num.Next(1, 1000000));
int counter = 1;
while (check <= 0)
{
if (check % 2 == 0)
{
check = CheckIfOdd(num.Next(1, 1000000)); ;
}
counter++;
}
int[] nArray = new int[check];
int arLength = 0;
//generate arrays with pairs of numbers, and one number which does not pair.
for (int i = 0; i < check; i++)
{
arLength = nArray.Length;
if (arLength == i + 1)
{
nArray[i] = i + 1;
}
else
{
nArray[i] = i;
nArray[i + 1] = i;
}
i++;
}
You can do it using the bitwise operator ^, and the complexity is O(n).
Theory
operator ^ aka xor has the following table:
So suppose you have only one number without pair, all the pairs will get simplified because they are the same.
var element = nArray[0];
for(int i = 1; i < arLength; i++)
{
element = element ^ nArray[i];
}
at the end, the variable element will be that number without pair.
Distict will give you back the array with distinct values. it will not find the value you need.
You can GroupBy and choose the values with Count modulo 2 equals 1.
var noPairs = nArray.GroupBy(i => i)
.Where(g => g.Count() % 2 == 1)
.Select(g=> g.Key);
You can use a dictionary to store the number of occurrences of each value in the array. To find the value without pairs, look for a (single) number of occurrences smaller than 2.
using System.Linq;
int[] data = new[] {1, 2, 3, 4, 5, 3, 2, 4, 1};
// key is the number, value is its count
var numberCounts = new Dictionary<int, int>();
foreach (var number in data) {
if (numberCounts.ContainsKey(number)) {
numberCounts[number]++;
}
else {
numberCounts.Add(number, 1);
}
}
var noPair = numberCounts.Single(kvp => kvp.Value < 2);
Console.WriteLine(noPair.Key);
Time complexity is O(n) because you traverse the array only a single time and then traverse the dictionary a single time. The same dictionary can also be used to find triplets etc.
.NET Fiddle
An easy and fast way to do this is with a Frequency Table. Keep a dictionary with as key your number and as value the number of times you found it. This way you only have to run through your array once.
Your example should work too with some changes. It will be a lot slower if you have a big array.
for (int i = 0; i <= arLength; i++)
{
bool hasMatch = false;
for (int e = 0; e <= arLength; e++)
{
if (nArray[e] == nArray[i])//Compare the element, not the index.
{
hasMatch = true;
}
}
//if hasMatch == false, you found your item.
}
All you have to do is to Xor all the numbers:
int result = nArray.Aggregate((s, a) => s ^ a);
all items which has pair will cancel out: a ^ a == 0 and you'll have the distinc item: 0 ^ 0 ^ ...^ 0 ^ distinct ^ 0 ^ ... ^0 == distinct
Because you mentioned you like short and simple in a comment, how about getting rid of most of your other code as well?
var total = new Random().Next(500000) * 2 + 1;
var myArray = new int[total];
for (var i = 1; i < total; i+=2)
{
myArray[i] = i;
myArray[i -1] = i;
}
myArray[total - 1] = total;
Then indeed use Linq to get what you are looking for. Here is a slight variation, returning the key of the item in your array:
var key = myArray.GroupBy(t => t).FirstOrDefault(g=>g.Count()==1)?.Key;
//List Style
using System;
using System.Collections.Generic;
using System.Linq;
public class pr{
static public void Main (){
int n, i, j, k, l, sum,flag = 0;
//int sum = i+j;
//int k = (n-i);
//int l = (n-j);
//System.Console.WriteLine ("Enter a number");
//n = Convert.ToInt32 (Console.ReadLine());
//List <int> primes = new List <int>(); //list to handle the numbers
//HashSet <int> myPrimes = new HashSet <int> (primes);
System.Console.WriteLine ("Enter a number");
n = Convert.ToInt32 (Console.ReadLine());
//myPrimes.Add(n);
//myPrimes.Add(i);
//myPrimes.Add(j);
// var count = string.Join(", ", primes);
//System.Console.WriteLine("The value of n is {0}",myPrimes);
for(i=3; i<n/2; i++){
for(j=3; j<n/2; j++){
if(checkPrime(i) == 1){
if(checkPrime(j) == 1){
if (checkPrime(n-i) == 1){
if (checkPrime(n-j) == 1){
//if(i == j){
//sum = i+j;
System.Console.WriteLine("{0}={1}+{2}\n",n,i,n-i);
//}
}
}
}
}
if (flag == 0 && (n-i) <= 0 && (n-j) <= 0){ //check to avoid dupes
if (n <= 0 && i <= 0 && j <= 0){
Console.Write("{0}\n",n);
}
}
}
}
}
public static int checkPrime(int n){
int i, j, flag = 1;
for (i = 2; i<=(Math.Sqrt(n)); i++){
for (j = 2; j<=(Math.Sqrt(n)); j++){
if (n%i == 0 && n%j == 0 ){ //even number check
i++;
j++;
flag = 0;
}
}
}
return flag;
}
}
So I have been experimenting with this for a while now. I cant seem to print all possible solutions. For example for 24 I am able to print 7+17 but not 2+5+17. There are also some answers being repeated and this might have to do with the fact that I dont have duplicate checks. I tried to push the integers in a list and then use a hashset to only have distinct integers but I got stuck and tried to brute force it. All the numbers to be printed are supposed to be distinct prime integers. I dont understand how to print all distinct numbers and is there an elegant way to print out all the possible.
Thanks for the help!
Don't know if it's elegant enough for you, but I've just mashed a dirty way to make it work:
static void Main()
{
Console.WriteLine("Enter a number");
var numberToSum = Convert.ToInt32(Console.ReadLine());
var primesInRange = GetPrimesUpTo(numberToSum);
var foundSolutions = primesInRange.SubSetsOf().Where(prime => prime.Sum() == numberToSum);
foreach (var solution in foundSolutions.ToList())
{
var formatOperation = solution
.Select(x => x.ToString())
.Aggregate((a, n) => a + " + " + n) + " = " + numberToSum;
Console.WriteLine(formatOperation);
}
Console.ReadLine();
}
public static IEnumerable<int> GetPrimesUpTo(int end)
{
var primes = new HashSet<int>();
for (var i = 2; i <= end; i++)
{
var ok = true;
foreach (var prime in primes)
{
if (prime * prime > i)
break;
if (i % prime == 0)
{
ok = false;
break;
}
}
if (ok)
primes.Add(i);
}
return primes;
}
public static IEnumerable<IEnumerable<T>> SubSetsOf<T>(this IEnumerable<T> source)
{
if (!source.Any())
return Enumerable.Repeat(Enumerable.Empty<T>(), 1);
var element = source.Take(1);
var haveNots = SubSetsOf(source.Skip(1));
var haves = haveNots.Select(set => element.Concat(set));
return haves.Concat(haveNots);
}
I've found your solution quite dirty so I divided the problem to be more understandable. GetPrimesUpTo returns all prime number from 2 to the number you've provided in the input, SubSetsOf returns combination of numbers that summed up equals the input number you've provided and finally the foreach in Main produces formatted output that is easy on the eye. Hope it helps!
Providing that you have collection of primes and IsPrime method
private static int[] primes = new[] {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 };
private static bool IsPrime(int value) {
return primes.Contains(value);
}
You can implement recoursive solution
private List<List<int>> ToListOfPrimes(int value, List<int> parts = null) {
if (null == parts)
parts = new List<int>();
List<List<int>> result = new List<List<int>>();
if (value == 0) {
result.Add(parts.ToList());
return result;
}
int minPrime = parts.Count <= 0 ? 0 : parts[parts.Count - 1];
if (value <= minPrime)
return result;
// not that efficient: binary search will be a better choice here
for (int i = 0; i < primes.Length; ++i) {
int p = primes[i];
if (p <= minPrime)
continue;
else if (p > value)
break;
var list = parts.ToList();
list.Add(p);
var outcome = ToListOfPrimes(value - p, list);
foreach (var solution in outcome)
result.Add(solution);
}
return result;
}
Test
var result = ToListOfPrimes(28);
string report = String.Join(Environment.NewLine, result
.Select(line => String.Join(", ", line)));
Console.Write(report);
Outcome (28)
2, 3, 5, 7, 11
2, 3, 23
2, 7, 19
3, 5, 7, 13
5, 23
11, 17
For 24
2, 3, 19
2, 5, 17
5, 19
7, 17
11, 13
If you really want to implement it in other languages just throw your solution to rubbish bin. You should be more explicit about what is happening during execution. Nested for loops with multiple if statements are not explicit at all. What's even worse in the sample - you'll need to add new for loop every time you want more numbers in the sum. I do believe it's hard to understand it for a novice, but I find recursion the only way to go here.
See for yourself:
it's hard to say why output of your program is wrong, because of the logic
Variables should be named meaningfully so you know what they store instead of blind guessing.
Your checkPrime method returns int even though you return 0 or 1 so it should really return bool type
Use debugger and a piece of paper to understand how recursion works either in my previous answer or the one provided by Dmitry Bychenko
Given a large list of integers (more than 1 000 000 values) find how many ways there are of selecting two of them that add up to 0.... Is the question
What I have done is create a positive random integer list:
Random pos = new Random();
int POSNO = pos.Next(1, 1000000);
lstPOS.Items.Add(POSNO);
lblPLus.Text = lstPOS.Items.Count.ToString();
POSCount++;
And created a negative list:
Random neg = new Random();
int NEGNO = neg.Next(100000, 1000000);
lstNEG.Items.Add("-" + NEGNO);
lblNegative.Text = lstNEG.Items.Count.ToString();
NegCount++;
To do the sum checking I am using:
foreach (var item in lstPOS.Items)
{
int POSItem = Convert.ToInt32(item.ToString());
foreach (var negItem in lstNEG.Items)
{
int NEGItem = Convert.ToInt32(negItem.ToString());
int Total = POSItem - NEGItem;
if (Total == 0)
{
lstADD.Items.Add(POSItem + "-" + NEGItem + "=" + Total);
lblAddition.Text = lstADD.Items.Count.ToString();
}
}
}
I know this is not the fastest route. I have considered using an array. Do you have any suggestions?
Let's see; your array is something like this:
int[] data = new int[] {
6, -2, 3, 2, 0, 0, 5, 7, 0, -2
};
you can add up to zero in two different ways:
a + (-a) // positive + negative
0 + 0 // any two zeros
in the sample above there're five pairs:
-2 + 2 (two pairs): [1] + [3] and [3] + [9]
0 + 0 (three pairs): [4] + [5], [4] + [8] and [5] + [8]
So you have to track positive/negative pairs and zeros. The implementation
Dictionary<int, int> positives = new Dictionary<int, int>();
Dictionary<int, int> negatives = new Dictionary<int, int>();
int zeros = 0;
foreach(var item in data) {
int v;
if (item < 0)
if (negatives.TryGetValue(item, out v))
negatives[item] = negatives[item] + 1;
else
negatives[item] = 1;
else if (item > 0)
if (positives.TryGetValue(item, out v))
positives[item] = positives[item] + 1;
else
positives[item] = 1;
else
zeros += 1;
}
// zeros: binomal coefficent: (2, zeros)
int result = zeros * (zeros - 1) / 2;
// positive/negative pairs
foreach (var p in positives) {
int n;
if (negatives.TryGetValue(-p.Key, out n))
result += n * p.Value;
}
// Test (5)
Console.Write(result);
Note, that there's no sorting, and dictionaries (i.e. hash tables) are used for positives and negatives so the execution time will be linear, O(n); the dark side of the implementation is that two additional structures (i.e. additional memory) required. In your case (millions integers only - Megabytes) you have that memory.
Edit: terser, but less readable Linq solution:
var dict = data
.GroupBy(item => item)
.ToDictionary(chunk => chunk.Key, chunk => chunk.Count());
int result = dict.ContainsKey(0) ? dict[0] * (dict[0] - 1) / 2 : 0;
result += dict
.Sum(pair => pair.Key > 0 && dict.ContainsKey(-pair.Key) ? pair.Value * dict[-pair.Key] : 0);
Fastest way without sorting!.
First of all you know that the sum of two integers are only 0 when they have equal absolute value but one is negative and the other is positive. So you dont need to sort. what you need is to Intersect positive list with negative list (by comparing absolute value). the result is numbers that ended up 0 sum.
Intersect has time complexity of O(n+m) where n is size of first list and m is size of second one.
private static void Main(string[] args)
{
Random random = new Random();
int[] positive = Enumerable.Range(0, 1000000).Select(n => random.Next(1, 1000000)).ToArray();
int[] negative = Enumerable.Range(0, 1000000).Select(n => random.Next(-1000000, -1)).ToArray();
var zeroSum = positive.Intersect(negative, new AbsoluteEqual());
foreach (var i in zeroSum)
{
Console.WriteLine("{0} - {1} = 0", i, i);
}
}
You also need to use this IEqualityComparer.
public class AbsoluteEqual : IEqualityComparer<int>
{
public bool Equals(int x, int y)
{
return (x < 0 ? -x : x) == (y < 0 ? -y : y);
}
public int GetHashCode(int obj)
{
return obj < 0 ? (-obj).GetHashCode() : obj.GetHashCode();
}
}
You tried to avoid check two numbers that are close (1, 2 are close, 3, 4 are close), but you didn't avoid check like (-100000, 1), (-1, 100000). Time complexity is O(n^2).
To avoid that you need to sort them first, then search from two direction.
var random = new Random();
var input = Enumerable.Range(1, 100).Select(_ => random.Next(200) - 100).ToArray();
Array.Sort(input); // This causes most computation. Time Complexity is O(n*log(n));
var expectedSum = 0;
var i = 0;
var j = input.Length - 1;
while (i < j) // This has liner time complexity O(n);
{
var result = input[i] + input[j];
if(expectedSum == result)
{
var anchori = i;
while (i < input.Length && input[i] == input[anchori] )
{
i++;
}
var anchorj = j;
while (j >= 0 && input[j] == input[anchorj])
{
j--;
}
// Exclude (self, self) combination
Func<int, int, int> combination = (n, k) =>
{
var mink = k * 2 < n ? k : n - k;
return mink == 0 ? 1
: Enumerable.Range(0, mink).Aggregate(1, (x, y) => x * (n - y))
/ Enumerable.Range(1, mink).Aggregate((x, y) => x * y);
};
var c = i < j ? (i - anchori) * (anchorj - j) : combination(i - anchori, 2);
for (int _ = 0; _ < c; _++)
{
// C# 6.0 String.Format
Console.WriteLine($"{input[anchori]}, {input[anchorj]}");
}
}
else if(result < expectedSum) {
i++;
}
else if(result > expectedSum) {
j--;
}
}
Here is another solution using (huh) LINQ. Hope the code is self explanatory
First some data
var random = new Random();
var data = new int[1000000];
for (int i = 0; i < data.Length; i++) data[i] = random.Next(-100000, 100000);
And now the solution
var result = data
.Where(value => value != int.MinValue)
.GroupBy(value => Math.Abs(value), (key, values) =>
{
if (key == 0)
{
var zeroCount = values.Count();
return zeroCount * (zeroCount - 1) / 2;
}
else
{
int positiveCount = 0, negativeCount = 0;
foreach (var value in values)
if (value > 0) positiveCount++; else negativeCount++;
return positiveCount * negativeCount;
}
})
.Sum();
Theoretically the above should have O(N) time and O(M) space complexity, where M is the count of the unique absolute values in the list.
So I have a list of ulong prime numbers, with variable lengths.
Ex: 2,5,7,3
And I want to create every multiplying combination, excluding ALL the numbers multiplied together.
(2*5*7*3 in this case).
Ex: 2,3,5,6,7,10,14,15,21,30,35,42,70,105.
I have tried a couple solutions using the "foreach" loop, but I just can't seem to get it. It seems too easy. What might be an efficient way to going about this?
My main issue that I run into is that when I add a new value to the list, the "foreach" loop causes an error because I changed it. I can't think of a way around that other than do a whole bunch of new lists. It seems to me like there should be a really simple, clean solution that I am just overcomplicating.
I tried the "Build-up" approaching, multiplying the base factors together, to create larger ones and so on, and the "Build-down" approaching, starting with the large number, and then factoring it (shown in my example). This is what I tried:
List<ulong> c, f;
ulong i;
//Some code then sets c to the factors (2, 3, 5, and 7)
//i is then set to the c set multiplied together (2*3*5*7)
//if the c is a factor, divide and add it to the new list f (the final list)
foreach (ulong u in c)
{
if (i % u == 0)
{
f.Add(i/u);
Console.WriteLine(i / u);
}
}
// Keep on dividing the numbers down, until you get the original factors added to the list
for (int j = 0; j < f.Count -1; j++)
{
foreach (ulong u in c)
{
foreach (ulong v in f)
{
if (v % u == 0)
{
if (v / u != 1 && !f.Contains(v / u))
{
f.Add(v / u);
}
}
}
}
}
Expected Output with input (2 5 7 3):
2
5
3
7
2 * 3 = 6
2 * 5 = 10
2 * 7 = 14
5 * 7 = 35
5 * 3 = 15
7 * 3 = 21
2 * 5 * 7 = 70
2 * 5 * 3 = 30
2 * 3 * 7 = 42
5 * 7 * 3 = 105
This works to get the numbers you want:
Func<IEnumerable<ulong>, IEnumerable<ulong>> f = null;
f = xs =>
{
if (xs.Any())
{
return f(xs.Skip(1))
.SelectMany(x =>
new [] { xs.First() * x, x });
}
else
{
return new ulong[] { 1 };
}
};
You use it like this:
var primes = new ulong[] { 2, 5, 7, 3 };
var results = f(primes)
.OrderBy(x => x)
.ToArray();
results = results
.Skip(1)
.Take(results.Length - 2)
.ToArray();
I had to do the Skip/Take to get rid of the two cases you wanted to avoid.
The result I get is:
If you'd like it as an (almost) one-liner here it is:
Func<IEnumerable<ulong>, IEnumerable<ulong>> f = null;
f = xs => xs.Any() ? f(xs.Skip(1)).SelectMany(x => new [] { xs.First() * x, x }) : new ulong[] { 1 };
The following code should give you exactly what you need with any number of items in your list
class Program
{
static void Main(string[] args)
{
MultiplyFactors(new List<ulong>() { 2, 3, 5, 7 });
Console.ReadLine();
}
public static void MultiplyFactors(List<ulong> numbers)
{
var factorCombinations = CreateSubsets(numbers.ToArray());
foreach (var factors in factorCombinations)
{
// set initial result to identity value. (any number multiplied by itself is 1)
ulong result = 1;
// multiply all factors in combination together
for (int i = 0; i < factors.Count(); i++)
{
result *= factors[i];
}
// Output for Display
Console.WriteLine(String.Format("{0}={1}", String.Join("x", factors), result));
}
}
private static List<T[]> CreateSubsets<T>(T[] originalArray)
{
// From http://stackoverflow.com/questions/3319586/getting-all-possible-permutations-from-a-list-of-numbers
var subsets = new List<T[]>();
for (int i = 0; i < originalArray.Length; i++)
{
int subsetCount = subsets.Count;
subsets.Add(new T[] {originalArray[i]});
for (int j = 0; j < subsetCount; j++)
{
T[] newSubset = new T[subsets[j].Length + 1];
subsets[j].CopyTo(newSubset, 0);
newSubset[newSubset.Length - 1] = originalArray[i];
subsets.Add(newSubset);
}
}
return subsets;
}
}
This will give you the following results for your inputs of 2,3,5,7.
2=2
3=3
2x3=6
5=5
2x5=10
3x5=15
2x3x5=30
7=7
2x7=14
3x7=21
2x3x7=42
5x7=35
2x5x7=70
3x5x7=105
2x3x5x7=210
This could have been through recursion but this method was probably just as simple. The trick is creating your list of subsets. Once you have that, you simply multiply all of the elements of each subset together.