Comprender un ejemplo

votos
-1
def solve(numLegs, numHeads):
    for numChicks in range(0, numHeads + 1):
        numPigs = numHeads - numChicks
        totLegs = 4*numPigs + 2*numChicks
        if totLegs == numLegs:
            return [numPigs, numChicks]
    return [None, None]

def barnYard(heads, legs):
    pigs, chickens = solve(legs, heads)
    if pigs == None:
        print There is no solution.
    else:
        print 'Number of pigs: ', pigs
        print 'Number of Chickens: ', chickens

Estoy aprendiendo Python y encontré este ejemplo. ¿Puede alguien explicar en inglés simple (o pseudocódigo) qué está haciendo línea por línea?

Muchas gracias

Publicado el 11/10/2009 a las 05:08
fuente por usuario
En otros idiomas...                            


5 respuestas

votos
1

Está iterando a través de cada combinación posible de cerdos y pollos (con el número especificado de cabezas) hasta que encuentre uno que tenga el número correcto de patas, y luego devuelva los números de cerdos y pollos. Si pasa por cada combinación sin encontrar una respuesta válida, devuelve [Ninguno, Ninguno] para indicar la falla.

Respondida el 11/10/2009 a las 05:15
fuente por usuario

votos
1

Esencialmente, solveitera a través de todas las combinaciones posibles de pollos y cerdos, y cuando encuentra una coincidencia, la devuelve).

NumChickens + NumPigs deben ser iguales a NumHeads, por lo que comprueba cada NumChickens de 0 a NumHeads (eso es lo que for range(0,NumHeads+1)hace), y establece que NumPigs sea NumHeads-NumChickens.

A partir de ahí, solo es cuestión de multiplicar el número de pies y ver si coinciden.

Respondida el 11/10/2009 a las 05:19
fuente por usuario

votos
8

solve está calculando cuántos pollitos (1 cabeza, 2 patas) y cuántos cerdos (1 cabeza, 4 patas) se necesitan para sumar hasta el número dado de cabezas y patas.

Utiliza una "fuerza bruta", es decir, un enfoque de máxima sencillez:

  • intenta incluso el número posible de pollitos de ninguno a todos los que se especificaron como número de cabezas (esa es la función del bucle for numChicks in range(0, numHeads + 1):, ya que rangeda números enteros del valor inicial incluido al valor final excluido);
  • para cada dado numChicks, calcula cuántos cerdos habría para dar el número solicitado de cabezas, por la declaraciónnumPigs = numHeads - numChicks
  • luego calcula cuántas patas totales tendrían esos pollitos y cerdos, por totLegs = 4*numPigs + 2*numChicks
  • luego verifica si el número es totLegsigual al solicitado: si es así, devuelve una lista con dos elementos, el número de pollos y cerdos que resuelven el problema
  • por último, si "cae de la parte inferior" del forciclo sin haber devuelto un valor aún, sabe que no hay solución, y significa que devolviendo una lista de cada uno de los dos elementos None.

barnYardsimplemente delega la solución solvee imprime de una forma agradable y legible, ya sea como "ninguna solución" o como números de pollos y cerdos muy bien decorados.

Ahora, para seguir progresando, pregúntate si solvepodría escribirse de manera más eficiente. Claramente, no hay solución si el número de patas es menos del doble del número de cabezas, o más de cuatro veces el número de cabezas, o impar - tal vez solvepodría probar esos casos y regresar [None, None]inmediatamente. ¿Podrías codificar eso ...?

Puede que no sea obvio, pero cualquier otra combinación de números de cabezas y piernas tiene una solución, y HAY una forma de encontrarla simplemente mediante aritmética, sin bucles. Piénselo, tal vez con la ayuda del álgebra primaria de la escuela media ...

Respondida el 11/10/2009 a las 05:22
fuente por usuario

votos
1

Básicamente, está tratando de encontrar la respuesta al problema: "¿Cuántos pollos y cerdos hay en un corral si hay cabezas X y patas Y en el corral?" El for numChicks in range(0, numHeads + 1):código crea una variable numChicks, y la recorre desde numChicks = 0 a numChicks = numHeads. (Nota: la función de rango no incluye el valor más alto).

Para cada número de numChicks, comprueba si los numChicks y los valores numPigs correspondientes aparecen con el valor correcto de numLegs. numHeads siempre será correcto ya que numChicks + numPigs = numHeads, pero numLegs varía en función de la distribución, de ahí el bucle. Si en algún momento se encuentra la solución (cuando totLegs == numLegs), se devuelve ese valor. Si se completa todo el ciclo y no se encontró ninguna solución, se devuelve la lista [Ninguno, Ninguno], lo que significa que no hay solución para esta entrada.

Respondida el 11/10/2009 a las 05:22
fuente por usuario

votos
2

Alex Martelli alude a una solución algebraica que incluiré aquí para completarla. Se puede resolver con el uso de ecuaciones simultáneas. Siendo una solución matemática simple, es posiblemente más rápido, al menos para un gran número de patas y cabezas :-)

Dejar:

  • H ser el número de cabezas;
  • L ser el número de piernas;
  • Cser el número de polluelos; y
  • P ser el número de cerdos.

Dado Cy P, podemos calcular las otras dos variables con:

H =  C +  P (1)
L = 2C + 4P (2)

Detallaré cada paso en los cálculos a continuación. Los matemáticamente inclinados sin duda pueden señalar que los pasos podrían combinarse, pero preferiría ser explícito. De (1), podemos calcular:

   H = C + P
=> 0 = C + P - H       [subtract H from both sides]
=> 0 = H - C - P       [multiply both sides by -1]
=> P = H - C           [add P to both sides] (3)

y sustituirlo en (2):

    L = 2C + 4P
=>  L = 2C + 4(H - C)   [substitute H-C for P]
=>  L = 2C + 4H - 4C    [expand 4(H-C) to 4H-4C]
=>  L = 4H - 2C         [combine 2C-4C into -2C]
=>  0 = 4H - 2C - L     [subtract L from both sides]
=> 2C = 4H - L          [add 2C to both sides]
=>  C = 2H - L/2        [divide both sides by 2] (4)

Ahora tiene dos fórmulas, una que puede calcular el número de polluelos de la cabeza y las patas (4), la otra que puede calcular el número de cerdos de los polluelos y las cabezas (3).

Así que aquí está el código de Python para hacerlo, con las comprobaciones apropiadas para garantizar que no permita algunas de las soluciones matemáticas más extrañas, como 2 cabezas y 7 patas que nos dan un cerdo y medio junto con la mitad de un pollito, o 1 cabeza y 12 piernas dando 5 cerdos y -4 polluelos :-)

def solve (numLegs, numHeads):
    # Use the formulae (these make integers).
    chicks = numHeads * 2 - int (numLegs / 2)
    pigs = numHeads - chicks

    # Don't allow negative number of animals.
    if chicks < 0 or pigs < 0:
        return [None, None]

    # Don't allow fractional animals.
    if chicks * 2 + pigs * 4 != numLegs:
        return [None, None]
    if chicks + pigs != numHeads:
        return [None, None]

    return [pigs, chicks]

Por supuesto, si pasas números fraccionarios de cabeza o piernas, todas las apuestas estarán desactivadas. Aquí hay un programa de prueba completo para que pueda probar varios valores para asegurarse de que ambos métodos devuelvan los mismos valores:

import sys

def usage (reason):
    print "Error: %s"%(reason)
    print "Usage: solve <numHeads> <numLegs>"
    sys.exit (1);

def solve1 (numLegs, numHeads):
    for numChicks in range (0, numHeads + 1):
        numPigs = numHeads - numChicks
        totLegs = 4 * numPigs + 2 * numChicks
        if totLegs == numLegs:
            return [numPigs, numChicks]
    return [None, None]

def solve2 (numLegs, numHeads):
    chicks = numHeads * 2 - int (numLegs / 2)
    pigs = numHeads - chicks
    if chicks < 0 or pigs < 0:           return [None, None]
    if chicks * 2 + pigs * 4 != numLegs: return [None, None]
    if chicks + pigs != numHeads:        return [None, None]
    return [pigs, chicks]

if len (sys.argv) != 3:
    usage ("Wrong number of parameters (%d)"%(len (sys.argv)))

try:    heads = int (sys.argv[1])
except: usage ("Invalid <numHeads> of '%s'"%(sys.argv[1]))

try:    legs = int (sys.argv[2])
except: usage ("Invalid <numLegs> of '%s'"%(sys.argv[2]))

print "[pigs, chicks]:"
print "  ", solve1 (legs, heads)
print "  ", solve2 (legs, heads)
Respondida el 12/10/2009 a las 04:06
fuente por usuario

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more