Para controlar a circulação de carros e motos nas ruas das cidades, algum órgão governamental associa uma placa a cada veículo. Para emitir uma multa ou denunciar um roubo à polícia, informa-se a placa que identifica o veículo. A placa é formada de letras e números e funciona como uma chave para encontrar o veículo desejado.
Faça um programa que leia as seguintes informações das infrações registradas no último ano: placa do carro, local, grau da infração, descrição da infração. O programa deve exibir as placas dos carros e respectivas infrações dos motoristas que devem ter a carteira suspensa (soma dos pontos>=20)
Dica: crie também um dicionário para a pontuação por grau de infração.

Passo 1

O que o enunciado pede e quais são os dados que ele fornece.
  • Dados que serão fornecidos (para cada infração registrada): placa do veículo, local, grau da infração e descrição da infração.
  • O que o programa deve fazer: exibir as placas dos carros e as respectivas infrações dos motoristas cuja soma dos pontos das infrações é maior ou igual a 20 (ou seja, acumulou \ge 20 pontos).
  • Dica obrigatória: usar um dicionário para mapear o grau da infração para sua pontuação (por exemplo, grau “leve” → 3 pontos, grau “grave” → 5 pontos, etc.). Esse mapeamento deve ser configurável.
  • Observação importante: o enunciado não especifica o formato exato de entrada (quantas infrações, se há um arquivo, etc.). Vou supor um modo interativo simples: o programa vai ler infrações até que a placa seja deixada em branco (enter) ou até EOF. Isso é prático para teste manual e para provas em que pedem um esqueleto de programa.

Passo 2

Escolha das estruturas de dados e a ideia geral do algoritmo (explicada passo a passo).
  • Dicionário para pontuação por grau: um dicionário chamado \texttt{grau\_para\_pontos} que associa strings de grau (por exemplo, \texttt{"leve"}) a inteiros (por exemplo, 3). Isso facilita converter o grau lido em número de pontos.
  • Dicionário para acumular pontos por placa: \texttt{pontos\_por\_placa}. Chave = placa (string); valor = total de pontos acumulados (inteiro).
    • Por que usar dicionário? Porque queremos consultar/atualizar rapidamente o total de pontos para uma placa específica. Dicionários fornecem acesso e atualização em tempo médio constante.
  • Dicionário para registrar infrações por placa: \texttt{infracoes\_por\_placa}. Chave = placa; valor = lista de infrações (cada infração pode ser um pequeno dicionário contendo local, grau, descrição e pontos).
    • Por que guardar as infrações? Porque o pedido é exibir “as placas dos carros e respectivas infrações”, ou seja, não apenas as placas e pontos, mas também os detalhes das infrações.
  • Fluxo do algoritmo:
    1. Inicializar \texttt{grau\_para\_pontos}, \texttt{pontos\_por\_placa} e \texttt{infracoes\_por\_placa}.
    2. Ler registros de infração em loop: para cada registro ler \texttt{placa}, \texttt{local}, \texttt{grau}, \texttt{descricao}.
    3. Converter \texttt{grau} para pontos usando \texttt{grau\_para\_pontos}. Se o grau não estiver presente, permitir que o usuário informe quantos pontos esse grau vale (ou assumir 0 se preferir).
    4. Atualizar \texttt{pontos\_por\_placa[placa]} somando os pontos da infração.
    5. Acrescentar a infração à lista em \texttt{infracoes\_por\_placa[placa]}.
    6. Depois de ler todos os registros, filtrar as placas cuja soma de pontos \ge 20 e exibir essas placas juntamente com o total de pontos e com as infrações registradas.

Passo 3

Como ler os dados (formato de entrada) e regras de validação — passo a passo prático.
  • Formato de entrada escolhido (interativo):
    • Perguntar a \texttt{Placa}. Se usuário pressionar Enter sem digitar nada, finalizar a leitura.
    • Perguntar \texttt{Local}.
    • Perguntar \texttt{Grau da infração}çã (string livre; será procurado em \texttt{grau\_para\_pontos}).
    • Perguntar \texttt{Descrição}çã.
  • Validação do grau:
    • Se o grau digitado não existir em \texttt{grau\_para\_pontos}, o programa pergunta quantos pontos esse novo grau deve valer (um número inteiro). Assim estimamos/atualizamos o dicionário dinamicamente.
    • Se preferir, em provas pode assumir que todos os graus estarão no dicionário inicial; aqui ofereço uma opção robusta para evitar erro em entrada inesperada.
  • Terminação:
    • Leitura termina quando a placa é vazia ou quando ocorre EOF (por exemplo, redirecionamento a partir de arquivo).

Passo 4

Como acumular os pontos e guardar as infrações — teoria aplicada com exemplos pequenos.
  • Acumular pontos:
    • Suponha que a placa \texttt{"ABC-1234"} tenha duas infrações: uma de grau \texttt{"leve"} ( 3 pontos) e outra de grau \texttt{"grave"} ( 5 pontos). O total será somado assim: \texttt{pontos\_por\_placa["ABC-1234"]} = 3 + 5 = 8.
    • Em código Python usamos algo como: \texttt{pontos\_por\_placa[placa] = pontos\_por\_placa.get(placa, 0) + pontos\_da\_infração}çã
      • Explicação do método \texttt{get}: \texttt{d.get(chave, valor\_padrao)} retorna \texttt{d[chave]} se existir; caso contrário retorna \texttt{valor\_padrao}. Muito útil para inicializar contadores sem checar se a chave existe.
  • Guardar a infração:
    • Para cada placa, mantemos uma lista. Ao receber uma nova infração, fazemos: \texttt{infracoes\_por\_placa.setdefault(placa, []).append(infracao)}
      • \texttt{setdefault} assegura que haja uma lista no dicionário para a placa, criando-a se necessário, e retorna a lista para podermos usar \texttt{append}.
  • Filtragem final:
    • Para obter as placas a suspender, filtramos onde total de pontos \ge 20: \text{placas\_suspensas} = \{placa \mid pontos\_por\_placa[placa] \ge 20\}.

Passo 5

Boas práticas na apresentação do resultado e ordenação.
  • É agradável e útil imprimir:
    • Placa
    • Total de pontos (por exemplo, 23)
    • Lista numerada de infrações com local, grau, descrição e pontos atribuídos a cada infração
  • Ordenação:
    • Ordenar as placas suspensas por ordem decrescente de pontos facilita ver os piores casos primeiro.
    • Em código: usar \texttt{sorted(placas, key=lambda p: pontos\_por\_placa[p], reverse=True)}.
  • Formato de saída simples e legível é importante numa prova prática e em verificação manual.

Passo 6

O programa em Python (explicado) — leia-o com calma e use em testes.
  • Vou fornecer um programa completo que implementa tudo o que expliquei. Ele:
    • Define um dicionário inicial \texttt{grau\_para\_pontos} (pode ajustar conforme necessidade).
    • Lê infrações até placa vazia.
    • Atualiza os dicionários \texttt{pontos\_por\_placa} e \texttt{infracoes\_por\_placa}.
    • Ao final, imprime as placas com soma de pontos \ge 20 com seus detalhes.
  • Exemplo de mapeamento inicial sugerido dentro do programa:
    • \texttt{"leve"}: 3
    • \texttt{"media"}: 4
    • \texttt{"grave"}: 5
    • \texttt{"gravissima"}: 7
  • Atenção: caso, durante a leitura, um grau novo seja digitado, o programa pede quantos pontos ele vale e adiciona ao dicionário.

Passo 7

Exemplo rápido de uso manual (para testar mentalmente).
  • Suponha inserir as infrações (apenas ilustração, sem usar reais entradas de prova):
    1. Placa = \texttt{AAA-1111}; Grau = \texttt{grave} ( 5 pts ); descrição = “Ultrapassagem proibida”.
    2. Placa = \texttt{AAA-1111}; Grau = \texttt{gravissima} ( 7 pts ); descrição = “Dirigir sob efeito”.
    3. Placa = \texttt{AAA-1111}; Grau = \texttt{grave} ( 5 pts ); descrição = “Velocidade excessiva”.
    4. Placa = \texttt{BBB-2222}; Grau = \texttt{media} ( 4 pts ); descrição = “Estacionamento irregular”.
    5. Placa = (vazio) → fim.
  • Cálculo: \texttt{AAA-1111}: 5 + 7 + 5 = 17 (não suspenso, pois 17 < 20); \texttt{BBB-2222}: 4 (não suspenso).
  • Se acrescentar mais uma infração grave a \texttt{AAA-1111} (+5), totaliza 22 e então será listado porque 22 \ge 20.

Resposta

# Programa para ler infrações e listar placas com total de pontos >= 20
# Modo de uso: executar, inserir infrações uma a uma. Deixar "Placa" em branco para terminar.

def main():
    # Mapeamento inicial grau -> pontos (ajustar conforme necessário)
    grau_para_pontos = {
        "leve": 3,
        "media": 4,
        "grave": 5,
        "gravissima": 7
    }

    pontos_por_placa = {}      # placa -> total de pontos (int)
    infracoes_por_placa = {}   # placa -> lista de infrações (cada infraacao é dict)

    print("Cadastro de infrações. Para encerrar, digite Enter em 'Placa'.\n")

    while True:
        try:
            placa = input("Placa: ").strip()
        except EOFError:
            # fim de arquivo: encerra a leitura
            break

        if placa == "":
            break  # usuário pediu para encerrar

        local = input("Local: ").strip()
        grau = input("Grau da infração (ex: leve, media, grave, gravissima): ").strip().lower()
        descricao = input("Descrição: ").strip()

        # Se o grau não estiver no dicionário, perguntar quantos pontos ele vale
        if grau not in grau_para_pontos:
            while True:
                entrada = input(f"Grau '{grau}' não reconhecido. Informe pontos (inteiro) para esse grau ou Enter para 0: ").strip()
                if entrada == "":
                    pontos_grau = 0
                    grau_para_pontos[grau] = pontos_grau
                    break
                try:
                    pontos_grau = int(entrada)
                    grau_para_pontos[grau] = pontos_grau
                    break
                except ValueError:
                    print("Valor inválido. Digite um número inteiro ou Enter para 0.")

        pontos_da_infracao = grau_para_pontos[grau]

        # Atualiza total de pontos da placa
        pontos_por_placa[placa] = pontos_por_placa.get(placa, 0) + pontos_da_infracao

        # Registra a infração detalhada
        inf = {
            "local": local,
            "grau": grau,
            "descricao": descricao,
            "pontos": pontos_da_infracao
        }
        infracoes_por_placa.setdefault(placa, []).append(inf)

        print(f"Registro gravado: placa={placa}, pontos_infracao={pontos_da_infracao}\n")

    # Filtrar placas com total de pontos >= 20
    LIMITE_SUSPENSAO = 20
    placas_suspensas = [p for p, pts in pontos_por_placa.items() if pts >= LIMITE_SUSPENSAO]

    if not placas_suspensas:
        print("\nNenhum motorista com pontuação total >= 20.")
        return

    # Ordenar por pontos decrescentes
    placas_ordenadas = sorted(placas_suspensas, key=lambda p: pontos_por_placa[p], reverse=True)

    print("\nMotoristas que devem ter a carteira suspensa (soma dos pontos >= 20):\n")
    for placa in placas_ordenadas:
        total = pontos_por_placa[placa]
        print(f"Placa: {placa}  |  Total de pontos: {total}")
        print("Infrações:")
        lista = infracoes_por_placa.get(placa, [])
        for i, inf in enumerate(lista, start=1):
            print(f"  {i}) Local: {inf['local']}; Grau: {inf['grau']}; Pontos: {inf['pontos']}; Descrição: {inf['descricao']}")
        print("-" * 60)

if __name__ == "__main__":
    main()

Exercícios relacionados