Python to C# Code Explanation
My ultimate aim is to convert the below code in python to C#, but I'd like to do it my self by learning the python syntax. I understand that the code is recursive.
The code produces polynomials of degree n with k variables. More specifically the list of exponents for each variable.
def multichoose(n,k):
if k < 0 or n < 0: return "Error"
if not k: return [[0]*n]
开发者_Python百科 if not n: return []
if n == 1: return [[k]]
return [[0]+val for val in multichoose(n-1,k)] + \
[[val[0]+1]+val[1:] for val in multichoose(n,k-1)]
Here is the conversion I have so far:
public double[] MultiChoose(int n, int k)
{
if (k < 0 || n < 0)
{
throw new Exception();
}
if (k == 0)
{
return [[0]*n]; // I have no idea what the [[0]*n] syntax means
}
if (n == 0)
{
return new double[0]; // I think this is just an empty array
}
if (n == 1)
{
return new double[1] {k}; // I think this is just an empty array
}
//Part I don't understand
return [[0]+val for val in MultiChoose(n-1,k)] + \
[[val[0]+1]+val[1:] for val in MultiChoose(n,k-1)]
}
My question is: How do I convert the python code?
I would use LINQ in C# to translate the code:
[]
is the empty list.Enumerable.Empty<T>()
[x]
is the list containing a single item, x.Enumerable.Repeat(x, 1)
[[0]*n]
is the list containing the list containing n copies of 0.Enumerable.Repeat(Enumerable.Repeat(0, n), 1)
[X for Y in Z]
is a list comprehension.from Y in Z select X - or - Z.Select(Y => X);
X + Y
(where X and Y are lists) is list concatenation.Enumerable.Concat(X, Y)
The signature of MultiChoose would be:
public IEnumerable<IEnumerable<double>> MultiChoose(int n, int k);
[0] * n
returns a list with n 0
s. []
is an empty list. [[k]]
is a list that contains a list that contains k
.
The last part uses list comprehensions. The basic forms of a list comprehension are:
[<new value> for <name> in <sequence>]
[<new value> for <name> in <sequence> if <condition>]
It creates a new list containing the new values each time the optional condition is true.
Some comments:
Pythons return "Error"
is not throwing an exception. It returns the string value "Error".
Pythons if not k:
is not equivalent to if (k == 0)
there are more things that are "not", like empty lists, the None value, etc (that may not make a difference in this case).
Pythons foo = [for x in bar]
is a list comprehension. It's equivalent to:
foo = []
for x in bar:
foo.append(x)
I found this one intriguing and after some help with understanding the Python code I took a stab at it. C# 3.0 and .NET Framework 3.5 needed.
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)));
}
Here's a version in 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
and some output examples:
>> 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]]
精彩评论