开发者

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 0s. [] 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]]
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜