Mayor número impar

Aug 19 2020

Pídale al usuario que ingrese 10 enteros y luego imprima el número impar más grande que se ingresó. Si no ingresó ningún número impar, imprima un mensaje a tal efecto.

He estado tratando de resolver este problema con Python y creo que he descubierto una forma que cubre todos los casos que son posibles dada la definición matemática de un número impar. Para estar seguro, me gustaría comprobar si mi código es correcto según sus propios criterios.

counter = 0
odd = []

while counter < 10:
    x = int(input("Enter a number: "))
    if abs(x)%2 != 0:
        odd.append(x)
    counter += 1

if len(odd) == 0:
    print("No odd number was entered")
else:
    print("The largest odd number is:", max(odd))

Respuestas

19 MarioIshac Aug 19 2020 at 07:14

Para su programa actual, podemos mejorar un par de cosas:

  1. Cambiar el nombre odda odds(ya que es a list).
  2. Úselo en not oddslugar de len(odds) == 0(consulte ¿Cómo verifico si una lista está vacía? Por una razón de por qué es preferible).
  3. Eliminar counter. Dado que solo usamos counteren la whilecondición, en realidad podemos reemplazar el conjunto whilecon for _ in range(10).
  4. Siga PEP 8 . Por ejemplo, usando 4 espacios para cada nivel de sangría.

Teniendo en cuenta todos estos cambios, obtenemos:

odds = []

for _ in range(10):
    x = int(input("Enter a number: "))
    if abs(x) % 2 != 0:
        odds.append(x)

if not odds:
    print("No odd number was entered")
else:
    print("The largest odd number is:", max(odds))

Pero también podemos mejorar la eficiencia de este programa. Ahora mismo hacemos un seguimiento de todos los números impares, antes de elegir el máximo. Esto significa que la complejidad del espacio es O (N). Podemos cambiar esto a O (1) haciendo un seguimiento del número impar más grande así:

max_odd = None

for _ in range(10):
    x = int(input("Enter a number: "))

    if abs(x) % 2 != 0:
        max_odd = x if max_odd is None else max(max_odd, x)

if max_odd is None:
    print("No odd number was entered")
else:
    print("The largest odd number is: ", max_odd)

Tenga en cuenta que usamos Nonepara significar que hay un número impar se ha introducido hasta el momento, en cuyo caso a un número impar de ser introducida nos propusimos max_odda xdirectamente. De lo contrario, nos configuramos max_odden max(max_odd, x).

Para este tipo de programa no notará el aumento de eficiencia debido a la reducción de la complejidad del espacio. Pero aprender a reconocer dónde son posibles estas reducciones le permitirá ver los mismos patrones en los programas donde sí importa.

Finalmente, hay una cosa más que puedes hacer. Si desea permitir que el programa siga acumulando números en el caso de que strse escriba accidentalmente a que no se puede analizar como un número (como ""), podemos usar un try/ exceptenvuelto en algo whileasí:

while True:
    try:
        x = int(input("Enter a number: "))
        break
    except ValueError:
        continue

Esto reemplazaría:

x = int(input("Enter a number: "))

en el código original. Esto seguiría solicitando al usuario que escriba un strque se pueda analizar como un inthasta que lo haga. Dado que todo esto sucede en la misma iteración del for, el recuento de números que llegan a escribir (10 en nuestro caso) no se reduciría.

6 GZ0 Aug 19 2020 at 08:58

Añadiendo a la revisión anterior:

  • Cuando xes un número entero, abs(x) % 2es equivalente a x % 2en Python. La salida del operador de módulo %tiene el mismo signo que el segundo operando.
  • Cuando se ejecuta código fuera de un método / clase, es una buena práctica colocar el código dentro de una protección principal . Consulte aquí para obtener más explicaciones.

En Python 3.8, el código se puede acortar usando el operador de asignación :=junto con maxfunction.

if __name__ == "__main__":
    # Number generator
    num_gen = (o for _ in range(10) if (o := int(input("Enter a number: "))) % 2 != 0)
    max_odd = max(num_gen, default=None)
    if max_odd is None:
        print("No odd number was entered")
    else:
        print(f"The largest odd number is: {max_odd}")

Envolver int(input("Enter a number: "))en una función proporciona una mejor legibilidad:

def read_input() -> int:
    return int(input("Enter a number: "))

if __name__ == "__main__":
    num_gen = (o for _ in range(10) if (o := read_input()) % 2 != 0)
    max_odd = max(num_gen, default=None)
    if max_odd is None:
        print("No odd number was entered")
    else:
        print(f"The largest odd number is: {max_odd}")

Otra variante que maneja entradas de usuario no válidas es la siguiente:

def read_input() -> int:
    while True:
        try:
            return int(input("Enter a number: "))
        except ValueError:
            continue

if __name__ == "__main__":
    try:
        max_odd = max(o for _ in range(10) if (o := read_input()) % 2 != 0)
        print(f"The largest odd number is: {max_odd}")
    except ValueError:
        # Since read_input() no longer raises ValueError, the except
        # statement here only handles the cases where max() gets no inputs
        print("No odd number was entered")
3 AlexeyBurdin Aug 19 2020 at 12:56

¿Puedo preguntar qué lenguaje de programación practicaba antes de Python?
Quiero mencionar un resumen para esto:

max(l,key=lambda x:(x%2,x))

asumiendo que ya lo has lintroducido de alguna manera, como

s='Enter a number: '
l=[int(input(s)) for i in range(10)]

¿Cómo funciona el código? Busca máximo de key(x)for xin ly devuelve tal x. Clave aquí es la función lambda que los rendimientos tupla (1,x)para odd xy (0,x)para aún x. Las tuplas se comparan de izquierda a derecha, por ejemplo, (1,x)>(0,y)para todos xy y. Entonces solo estamos diciendo "dame el máximo de l, asumiendo que un número impar es siempre mayor que un número par".

Entonces todo el programa se verá como

s='Enter a number: '
l=[int(input(s)) for i in range(10)]
m=max(l,key=lambda x:(x%2,x))
if m%2:
    print('The largest odd number is: %d'%m)
else: #the greatest is even, therefore no odd numbers
    print('No odd number was entered')

Corto, agradable y fácil, como Python.

Pero estoy de acuerdo en que un bloque try-except alrededor de int(input())la respuesta aceptada es útil, además de no almacenar previamente la lista completa de valores impares.

Solo quería demostrar el paradigma de la programación funcional en Python, cuando le dices a Python 'Quiero que se haga (por ejemplo, un valor máximo)' y lo hace por ti, no necesitas explicar cómo debería hacerlo.

Gracias por leer.

3 EmilioMBumachar Aug 19 2020 at 21:36

Intentaré basarme en la última sugerencia de la respuesta aceptada.

while True:
    try:
        x = int(input("Enter a number: "))
        break
    except ValueError:
        continue

Definitivamente apoyo esta sugerencia, le permite a su programa manejar la entrada inválida con gracia en lugar de simplemente fallar.

Sin embargo, crea un problema de usabilidad. El usuario que acaba de escribir una letra en un número probablemente no lo notó. Pensarán que ingresaron el número deseado, continuarán con el siguiente y luego se confundirán al final, cuando crean que ingresaron todos los números, pero la computadora todavía está pidiendo el siguiente.

Mejor darles retroalimentación:

while True:
    try:
        x = int(input("Enter a number: "))
        break
    except ValueError:
        print("Invalid number will be ignored.")
        continue

... o mejor aún, imprímales el número escrito a máquina:

while True:
    try:
        inputString = input("Enter a number: ")
        x = int(inputString)
        break
    except ValueError:
        print("Invalid number will be ignored: {}".format(inputString))
        continue

También consideraría mantener la lista completa de números válidos ingresados, no solo los impares, e imprimirlos todos al usuario antes del resultado, para darle una última oportunidad de detectar errores tipográficos. Después de todo, pueden haber escrito mal un número válido pero no intencionado. Tenga en cuenta que esto aumentaría el uso de la memoria y algunos lo considerarían un exceso de comunicación.

print("Numbers provided are: {}".format(all_valid_numbers_inputted))
if not odds:
    print("No odd number was entered")
else:
    print("The largest odd number is:", max(odds))

Si hace esto, el siguiente paso sería deshacerse de la variable "probabilidades" y calcular la cuota más grande directamente de la lista completa.

1 FMc Aug 25 2020 at 12:23

El punto clave aquí: cada paso del proceso hace solo una cosa simple. Usted construye programas de esa manera: un paso incremental y bien definido a la vez. No mezcle todo en un revoltijo, por ejemplo, un bucle en el que interactuamos con un usuario al mismo tiempo que hacemos las conversiones y los cálculos necesarios más adelante.

def as_int(s):
    try:
        return int(s)
    except Exception:
        return 0

N = 3
MSG = 'Enter number: '

replies = [input(MSG) for _ in range(N)]  # Interact.
nums = [as_int(r) for r in replies]       # Convert.
odds = [n for n in nums if n % 2]         # Compute.

if odds:                                  # Report.
    print(max(odds))