2^{\underline{2}}. Questão: Implemente uma função que receba o valor total de uma compra e um código de cupom de desconto. A função deve verificar se o cupom informado existe em uma estrutura previamente definida de cupons válidos e, em caso positivo, aplicar o percentual de desconto correspondente ao valor da compra, retornando o valor final a ser pago. Caso o cupom não exista, a função deve retornar o valor original da compra. Considere, por exemplo, que os cupons DESC10, DESC20 e DESC30 concedem, respectivamente, 10 \%, 20 \% e 30 \% de desconto.

Passo 1

O que o enunciado pede e o que foi dado.
  • Pedido: Implementar uma função que receba o valor total de uma compra e um código de cupom de desconto; verificar se o cupom existe numa estrutura pré-definida de cupons válidos; se existir, aplicar o percentual de desconto correspondente e retornar o valor final a pagar; se não existir, retornar o valor original da compra.
  • Informações fornecidas (exemplo de cupons):
    • O cupom DESC10 concede 10\% de desconto.
    • O cupom DESC20 concede 20\% de desconto.
    • O cupom DESC30 concede 30\% de desconto.
  • Entradas esperadas para a função:
    • valor total da compra (um número).
    • código do cupom (uma string).
  • Saída esperada:
    • o valor final a ser pago (número), já com o desconto aplicado quando o cupom for válido.

Passo 2

Escolha da estrutura de dados para os cupons e justificativa.
  • Precisamos de um jeito rápido de consultar, dado o código do cupom, qual o percentual associado. Uma boa estrutura para isso é um dicionário (mapa) que associa a chave (código do cupom) ao valor (percentual).
  • Exemplo de mapeamento (representação conceitual):
    • \text{cupons}[\text{`DESC10`}]=10
    • \text{cupons}[\text{`DESC20`}]=20
    • \text{cupons}[\text{`DESC30`}]=30
  • Por que usar dicionário:
    • A busca pelo cupom é O(1) em média — é rápida.
    • É fácil adicionar/remover cupons.
  • Observação prática: normalmente guardamos as chaves em uma forma padrão (por exemplo, maiúsculas e sem espaços) para evitar diferenças de caixa/formatos na entrada.

Passo 3

Validação de entrada: o que checar antes de calcular o desconto.
  • Verificar se o valor total pode ser tratado como número real (converte-lo para float). Se não puder, sinalizar erro ou lançar exceção.
  • Verificar se o valor total é não-negativo. Compras com valor negativo não fazem sentido aqui — tratar como erro.
  • Normalizar o código do cupom: remover espaços nas extremidades e tratar em caixa única (por exemplo, converter para maiúsculas) para que entradas como " desc10 " ou "desc10" sejam reconhecidas.
  • Decisão de comportamento para cupom inválido: retornar o valor original da compra (conforme enunciado).

Passo 4

Fórmula do desconto e interpretação das variáveis.
  • Se d for o percentual de desconto (por exemplo d=10 para 10\%) e \text{valor\_total} for o valor antes do desconto, então o valor final \text{valor\_final} é dado por:
\text{valor\_final} = \text{valor\_total} \cdot \left(1 - \frac{d}{100}\right)
  • Onde:
    • \text{valor\_total} é o que o usuário passou (ex.: 100,0).
    • d é o percentual de desconto associado ao cupom (ex.: 10 para 10\%).
    • O fator 1 - \frac{d}{100} é a fração do valor que permanece após desconto (ex.: para 10\% fica 0,90).
  • Exemplo numérico rápido:
    • Se \text{valor\_total}=100,0 e d=10, então
    \text{valor\_final}=100,0\cdot\left(1-\frac{10}{100}\right)=100,0\cdot 0,90=90,0.

Passo 5

Detalhes de implementação práticos e decisões de projeto (comportamento esperado).
  • Caso o cupom não exista na estrutura de cupons, simplesmente retornar \text{valor\_total} sem alteração.
  • Tratar cupom com insensibilidade à caixa (usar maiúsculas) e remover espaços em excesso (usar trim).
  • Se o percentual de desconto for \geq 100\%, por segurança, limitar o valor final para 0,0 (não retornar número negativo).
  • Decidir sobre precisão: normalmente retornar um número de ponto flutuante; se quiser formato monetário, pode-se arredondar para duas casas decimais usando arredondamento explícito (ex.: formatar com duas casas).
  • Lidar com entradas inválidas (por exemplo valor não numérico ou negativo) lançando uma exceção (ou retornando erro) — é melhor falhar rápido do que ocultar um bug.

Passo 6

Pseudocódigo / lógica passo a passo antes do código final.
  1. Definir o dicionário de cupons:
    • \text{cupons} = \{\text{`DESC10`}:10,\; \text{`DESC20`}:20,\; \text{`DESC30`}:30\}.
  2. Receber \text{valor\_total} e \text{codigo}.
  3. Tentar converter \text{valor\_total} para número real; se falhar, indicar erro.
  4. Se \text{valor\_total} < 0: erro.
  5. Normalizar \text{codigo} com \text{codigo} = \text{codigo.strip().upper()}.
  6. Procurar \text{codigo} nas chaves de \text{cupons}.
    • Se não existir: retornar \text{valor\_total}.
    • Se existir: obter d=\text{cupons}[\text{codigo}].
  7. Calcular:
\text{valor\_final} = \text{valor\_total} \cdot \left(1 - \frac{d}{100}\right)
  1. Se \text{valor\_final} < 0 (por conta de d\ge 100), definir \text{valor\_final} = 0,0.
  2. Retornar \text{valor\_final} (possivelmente arredondado para duas casas, se desejado).

Passo 7

Exemplos de uso (casos de teste) com os cupons fornecidos.
  • Exemplo 1:
    • Entrada: \text{valor\_total}=100,0, \text{codigo}=\text{`DESC10`}.
    • Esperado: \text{valor\_final} = 90,0.
  • Exemplo 2:
    • Entrada: \text{valor\_total}=200,0, \text{codigo}=\text{`DESC20`}.
    • Esperado: \text{valor\_final} = 160,0.
  • Exemplo 3:
    • Entrada: \text{valor\_total}=50,0, \text{codigo}=\text{`INVALID`}.
    • Esperado: \text{valor\_final} = 50,0 (cupom inválido → sem desconto).
  • Exemplo 4 (teste de normalização):
    • Entrada: \text{valor\_total}=100,0, \text{codigo}=\text{` desc30 `}.
    • Esperado: \text{valor\_final} = 70,0 (espaços e caixa diversa são tratados).

Passo 8

Observações finais e recomendação para uso em prova/entrega rápida.
  • Para a prova, foque em:
    • Declarar claramente o dicionário de cupons.
    • Fazer a normalização do código (strip + upper).
    • Validar o tipo/valor do total.
    • Aplicar a fórmula do desconto sem esquecer de dividir por 100.
  • Se pedir também tratamento de erros, explique que o ideal é lançar exceção quando o valor total não for válido.
  • Em implementação real para produção, considere armazenar os cupons em banco de dados e tratar percentuais como decimais seguros (ex.: Decimal em Python) para evitar problemas de precisão monetária. Para a prova, float e arredondamento são suficientes.

Resposta

def aplicar_desconto(valor_total, codigo_cupom):
“”"
Recebe o valor total da compra e um código de cupom.
Se o cupom for válido, aplica o desconto correspondente e retorna o valor final.
Se o cupom for inválido, retorna o valor_total original.
Lança ValueError se valor_total não puder ser convertido para número ou for negativo.
“”"
# Dicionário de cupons válidos (chave -> percentual)
cupons = {
“DESC10”: 10,
“DESC20”: 20,
“DESC30”: 30
}
# Validação e conversão do valor_total
try:
    valor = float(valor_total)
except (TypeError, ValueError):
    raise ValueError("valor_total deve ser um número válido")

if valor < 0:
    raise ValueError("valor_total não pode ser negativo")

# Normalizar o código do cupom
if not isinstance(codigo_cupom, str):
    codigo_norm = ""
else:
    codigo_norm = codigo_cupom.strip().upper()

# Verificar existência do cupom
percentual = cupons.get(codigo_norm)
if percentual is None:
    # Cupom inválido: retorna o valor original
    return valor

# Calcular o valor final usando a fórmula:
# valor_final = valor_total * (1 - percentual / 100)
valor_final = valor * (1 - percentual / 100.0)

# Segurança: não retornar valor negativo mesmo que percentual >= 100
if valor_final < 0:
    valor_final = 0.0

# Opcional: arredondar para duas casas (comum em valores monetários)
return round(valor_final, 2)

Exercícios relacionados