Мне это показалось интригующим, и после некоторой помощи в понимании кода Python я попытался это сделать. Требуется C # 3.0 и .NET Framework 3.5.
public static IEnumerable<IEnumerable<int>> MultiChoose(int n, int k)
{
if (k < 0 || n < 0) throw new Exception();
if (k == 0) return Enumerable.Repeat(Enumerable.Repeat(0, n), 1);
if (n == 0) return Enumerable.Repeat(Enumerable.Empty<int>(), 0);
if (n == 1) return Enumerable.Repeat(Enumerable.Repeat(k, 1), 1);
return (from val in MultiChoose(n - 1, k) select new [] { 0 }.Concat(val))
.Concat(from val in MultiChoose(n, k - 1) select new [] { val.First() + 1 }.Concat(val.Skip(1)));
}
Вот версия на Ruby
def multichoose(n,k)
if k<0 || n<0: raise "Error" end
if k==0: return [[0]*n] end
if n==0: return [] end
if n==1: return [[k]] end
multichoose(n-1,k).map{|val| [0]+val} + \
multichoose(n,k-1).map{|val| [val.first+1]+val[1..-1]}
end
и некоторые примеры вывода:
>> multichoose(2,2)
=> [[0, 2], [1, 1], [2, 0]]
>> multichoose(3,2)
=> [[0, 0, 2], [0, 1, 1], [0, 2, 0], [1, 0, 1], [1, 1, 0], [2, 0, 0]]
>> multichoose(3,3)
=> [[0, 0, 3], [0, 1, 2], [0, 2, 1], [0, 3, 0], [1, 0, 2], [1, 1, 1], [1, 2, 0], [2, 0, 1], [2, 1, 0], [3, 0, 0]]