2010-01-24 20 views
5

Mi objetivo final es convertir el código siguiente en python en C#, pero me gustaría hacerlo yo solo aprendiendo la sintaxis de python. Entiendo que el código es recursivo.Python a C# Explicación del código

El código produce polinomios de grado n con k variables. Más específicamente, la lista de exponentes para cada variable.

def multichoose(n,k): 
    if k < 0 or n < 0: return "Error" 
    if not k: return [[0]*n] 
    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)] 

Aquí es la conversión que tengo hasta ahora:

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)] 
} 

Mi pregunta es: ¿Cómo se convierte el código Python?

+0

Entonces, ¿cuál es tu pregunta? –

Respuesta

3

usaría LINQ en C# para traducir el código:

  • [] es la lista vacía.

    Enumerable.Empty<T>() 
    
  • [x] es la lista que contiene un solo elemento, x.

    Enumerable.Repeat(x, 1) 
    
  • [[0]*n] es la lista que contiene la lista que contiene N copias de 0.

    Enumerable.Repeat(Enumerable.Repeat(0, n), 1) 
    
  • [X for Y in Z] es una lista por comprensión.

    from Y in Z select X 
        - or - 
    Z.Select(Y => X); 
    
  • X + Y (donde X e Y son listas) es la lista de concatenación.

    Enumerable.Concat(X, Y) 
    

La firma de MultiChoose sería:

public IEnumerable<IEnumerable<double>> MultiChoose(int n, int k); 
+0

Nice =) ¿Es posible hacer esto también con genéricos, es decir, para usar 'Enumerable ' (o 'IEnumerable ') en lugar de 'Enumerable'? –

+0

Enumerable es una clase estática. Tiene métodos genéricos que producen IEnumerable 's (omití los parámetros de tipo genérico donde se pueden inferir), así que sí. – dtb

+0

Creo que obtuvo el [[0] * n] incorrecto, debería Enumerable.Repeat (Enumerable.Repeat (0, n), 1), también el Repeat externo podría no ser necesario en absoluto. –

1

[0] * n devuelve una lista con n 0 s. [] es una lista vacía. [[k]] es una lista que contiene una lista que contiene k.

La última parte usa la lista de comprensiones. Las formas básicas de una lista por comprensión son:

[<new value> for <name> in <sequence>] 
[<new value> for <name> in <sequence> if <condition>] 

Se crea una nueva lista que contiene los nuevos valores cada vez que la condición opcional es cierto.

1

Algunos comentarios:

pitones return "Error" no es una excepción. Devuelve el valor de cadena "Error".

Pythons if not k: no es equivalente a if (k == 0) hay más cosas que son "no", como listas vacías, el valor Ninguno, etc. (que puede no hacer la diferencia en este caso).

Pythons foo = [for x in bar] es una lista de comprensión.Es equivalente a:

foo = [] 
for x in bar: 
    foo.append(x) 
1

Me pareció que éste era intrigante y después de un poco de ayuda con la comprensión del código Python Tomé una puñalada en ella. C# 3.0 y .NET Framework 3.5 necesarios.

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))); 
} 

Aquí hay una versión en 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 

y algunos ejemplos de salida:

>> 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

+1 - muy agradable. – dtb