Maior número ímpar
Peça ao usuário para inserir 10 inteiros e, em seguida, imprimir o maior número ímpar inserido. Se nenhum número ímpar foi inserido, imprima uma mensagem para esse efeito.
Tenho tentado resolver esse problema com o python e acho que descobri uma maneira que cobre todos os casos possíveis, dada a definição matemática de um número ímpar. Para ter certeza, gostaria de verificar se meu código está correto de acordo com seus próprios critérios.
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))
Respostas
Para seu programa atual, podemos melhorar algumas coisas:
- Renomeie
odd
paraodds
(visto que é umlist
). - Use em
not odds
vez delen(odds) == 0
(consulte Como verifico se uma lista está vazia? Para saber por que isso é preferido). - Excluir
counter
. Visto que usamos apenascounter
nawhile
condição, podemos substituir o todowhile
porfor _ in range(10)
. - Siga o PEP 8 . Por exemplo, usando 4 espaços para cada nível de indentação.
Considerando todas essas mudanças, obtemos:
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))
Mas também podemos melhorar a eficiência deste programa. No momento, monitoramos todos os números ímpares antes de escolher o máximo. Isso significa que a complexidade do espaço é O (N). Podemos mudar isso para O (1), mantendo o controle do maior número ímpar, assim:
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)
Observe que usamos None
para significar que nenhum número ímpar foi inserido até agora, caso em que, após a inserção de um número ímpar, definimos max_odd
como x
diretamente. Caso contrário, definimos max_odd
como max(max_odd, x)
.
Para este tipo de programa você não notará o aumento da eficiência devido à redução da complexidade do espaço. Mas aprender a reconhecer onde essas reduções são possíveis permitirá que você veja os mesmos padrões em programas onde isso é importante.
Finalmente, há mais uma coisa que você pode fazer. Se você quiser permitir que o programa continue acumulando números no caso de um str
acidentalmente digitado que não possa ser analisado como um número (como ""
), podemos usar um try
/ except
envolvido em um while
assim:
while True:
try:
x = int(input("Enter a number: "))
break
except ValueError:
continue
Isso substituiria:
x = int(input("Enter a number: "))
no código original. Isso continuaria solicitando que o usuário digite um str
que seja analisável como um int
até que o faça. Como tudo isso está acontecendo na mesma iteração do for
, a contagem de números que eles conseguem digitar (10 em nosso caso) não seria reduzida.
Adicionando à revisão anterior:
- Quando
x
é um inteiro,abs(x) % 2
é equivalente ax % 2
em Python. A saída do operador módulo%
tem o mesmo sinal do segundo operando. - Ao executar o código fora de um método / classe, é uma boa prática colocar o código dentro de um guarda principal . Veja aqui para mais explicações.
No Python 3.8, o código pode ser encurtado usando o operador de atribuição :=
junto com a max
função.
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}")
O empacotamento int(input("Enter a number: "))
em uma função fornece melhor legibilidade:
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}")
Outra variante que lida com entradas de usuário inválidas é a seguinte:
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")
Posso perguntar qual linguagem de programação você praticava antes do python?
Quero mencionar uma linha para isso:
max(l,key=lambda x:(x%2,x))
presumindo que você já tenha l
inserido de alguma forma, como
s='Enter a number: '
l=[int(input(s)) for i in range(10)]
Como funciona o código? Procura no máximo key(x)
para x
em l
e retorna tal x
. A chave aqui é a função lambda que retorna tupla (1,x)
para ímpar x
e (0,x)
par x
. As tuplas são comparadas da esquerda para a direita, por exemplo, (1,x)>(0,y)
para cada x
e y
. Portanto, estamos apenas dizendo "dê-me o máximo de l
, assumindo que um número ímpar é sempre maior do que um número par".
Portanto, todo o programa será semelhante
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')
Curto, agradável e fácil, como python.
Mas concordo que um bloco try-except em torno int(input())
da resposta aceita é útil, junto com nenhum pré-armazenamento de toda a lista de valores ímpares.
Eu só queria demonstrar o paradigma da programação funcional em python, quando você apenas diz a python 'Eu quero que isso seja feito (por exemplo, um valor máximo)' e ele faz isso por você, você não precisa explicar como deveria fazer.
Obrigado pela leitura.
Tentarei aproveitar a última sugestão da resposta aceita.
while True:
try:
x = int(input("Enter a number: "))
break
except ValueError:
continue
Eu definitivamente endosso essa sugestão, ela permite que seu programa trate entradas inválidas normalmente em vez de apenas travar.
No entanto, isso cria um problema de usabilidade. O usuário que acabou de digitar uma letra em um número provavelmente não percebeu. Eles pensarão que inseriram o número pretendido, continuarão com o próximo e ficarão confusos no final, quando acharem que inseriram todos os números, mas o computador ainda está pedindo o próximo.
Melhor dar feedback:
while True:
try:
x = int(input("Enter a number: "))
break
except ValueError:
print("Invalid number will be ignored.")
continue
... ou melhor ainda, imprima o número digitado de volta para eles:
while True:
try:
inputString = input("Enter a number: ")
x = int(inputString)
break
except ValueError:
print("Invalid number will be ignored: {}".format(inputString))
continue
Também consideraria manter a lista completa de números válidos inseridos, não apenas os ímpares, e imprimi-los todos de volta para o usuário antes do resultado, para dar a eles uma última chance de detectar erros de digitação. Afinal, eles podem ter digitado incorretamente um número válido, mas não intencional. Observe que isso aumentaria o uso de memória e alguns considerariam um excesso de comunicação.
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))
Se você fizer isso, a próxima etapa será livrar-se da variável "probabilidades" e calcular a maior ímpar diretamente da lista completa.
O ponto principal aqui: cada etapa do processo faz apenas uma coisa simples. Você cria programas dessa maneira - uma etapa incremental e bem definida de cada vez. Não misture tudo em uma confusão - por exemplo, um loop onde interagimos com um usuário enquanto também fazemos conversões e cálculos necessários mais tarde.
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))