我有一个
下的数组var x = new int[] { 1,2,3 };
并给出了限制
int limit=2;
我必须找到一个组合
1+2 = 3
1+3 = 4
2+3 = 5.
如果数组是
var x = new int[] { 1,2,3,4,5,6};
并给出了限制
int limit=3;
组合应
1+2+3 = 6
1+2+4 = 7
1+2+5 = 8
1+2+6 = 9
2+3+4 = 9
2+3+5 = 10
2+3+6 = 11
...........
............
等等
怎么做?
我的嫌疑人
var x = new int[] {1,2,3};
int limit = 2;
var m = from a1 in x
from a2 in x
select new
{
P1 = a1 ,
P2 = a2,
P3 = a1+a2
};
答案 0 :(得分:5)
我会使用这个有效的组合学项目,这也值得一读:
Permutations, Combinations, and Variations using C# Generics
然后很简单:
var x = new int[] { 1, 2, 3, 4, 5, 6 };
var combis = new Facet.Combinatorics.Combinations<int>(x, 3, Facet.Combinatorics.GenerateOption.WithoutRepetition);
foreach(var combi in combis)
Console.WriteLine(String.Join("+", combi) + "=" + combi.Sum());
Console.WriteLine("Total: " + combis.Sum(c => c.Sum())); // 201
输出:
1+2+3=6
1+2+4=7
1+2+5=8
1+2+6=9
1+3+4=8
1+3+5=9
1+3+6=10
1+4+5=10
1+4+6=11
1+5+6=12
2+3+4=9
2+3+5=10
2+3+6=11
2+4+5=11
2+4+6=12
2+5+6=13
3+4+5=12
3+4+6=13
3+5+6=14
4+5+6=15
Total: 210
答案 1 :(得分:4)
不使用外部库的解决方案:
public static IEnumerable<IEnumerable<T>> Combinations<T>(IEnumerable<T> elements, int k)
{
return k == 0 ? new[] { new T[0] } :
elements.SelectMany((e, i) =>
Combinations(elements.Skip(i + 1),k - 1).Select(c => (new[] {e}).Concat(c)));
}
public static void Main()
{
var x = new int[] { 1, 2, 3, 4, 5, 6 };
var limit = 3;
IEnumerable<IEnumerable<int>> result = Combinations(x, limit);
foreach(var combi in result)
Console.WriteLine(String.Join("+", combi.Select(a=>a.ToString()).ToArray()) + "=" + combi.Sum());
Console.WriteLine("Total: " + result.Sum(c => c.Sum())); // 201
}
修改:所有组合:
public static IEnumerable<IEnumerable<T>> AllCombinations<T>(IEnumerable<T> elements)
{
int length = elements.Count();
for(int k = 1; k<=length; k++){
var comb = Combinations(elements, k);
foreach (IEnumerable<T> c in comb)
yield return c;
}
}
答案 2 :(得分:1)
看起来你只需要一种方法
/// <summary>
/// Gets all combinations (of a given size) of a given list, either with or without reptitions.
/// </summary>
/// <typeparam name="T">The type of the elements in the list.</typeparam>
/// <param name="list">The list of which to get combinations.</param>
/// <param name="action">The action to perform on each combination of the list.</param>
/// <param name="resultSize">The number of elements in each resulting combination; or <see langword="null"/> to get
/// premutations of the same size as <paramref name="list"/>.</param>
/// <param name="withRepetition"><see langword="true"/> to get combinations with reptition of elements;
/// <see langword="false"/> to get combinations without reptition of elements.</param>
/// <exception cref="ArgumentNullException"><paramref name="list"/> is <see langword="null"/>. -or-
/// <paramref name="action"/> is <see langword="null"/>.</exception>
/// <exception cref="ArgumentException"><paramref name="resultSize"/> is less than zero.</exception>
/// <remarks>
/// The algorithm performs combinations in-place. <paramref name="list"/> is however not changed.
/// </remarks>
public static void GetCombinations<T>(IList<T> list, Action<IList<T>> action, int? resultSize = null,
bool withRepetition = false)
{
if (list == null)
throw new ArgumentNullException("list");
if (action == null)
throw new ArgumentNullException("action");
if (resultSize.HasValue && resultSize.Value <= 0)
throw new ArgumentException("error", "resultSize");
var result = new T[resultSize.HasValue ? resultSize.Value : list.Count];
var indices = new int[result.Length];
for (int i = 0; i < indices.Length; i++)
indices[i] = withRepetition ? -1 : indices.Length - i - 2;
int curIndex = 0;
while (curIndex != -1)
{
indices[curIndex]++;
if (indices[curIndex] == (curIndex == 0 ? list.Count : indices[curIndex - 1] + (withRepetition ? 1 : 0)))
{
indices[curIndex] = withRepetition ? -1 : indices.Length - curIndex - 2;
curIndex--;
}
else
{
result[curIndex] = list[indices[curIndex]];
if (curIndex < indices.Length - 1)
curIndex++;
else
action(result);
}
}
}
用法:
var x = new int[] { 1, 2, 3, 4, 5, 6 };
var combinationsResult = new List<int>();
GetCombinations<int>(x, (list => combinationsResult.Add(list.Sum())), limit, false);