Um sistema de apostas para jogos de futebol é concebido conforme a especificação a seguir:
  • deve-se armazenar um dicionário com os nomes das pessoas que apostaram em cada time e o valor individual investido por cada apostador;
  • ao final do jogo, todo o montante do time perdedor é distribuído entre os apostadores do time vencedor, na mesma proporção das apostas. Além disso, o valor investido por cada usuário do time vencedor é devolvido.
Considerando esse mecanismo:
a) codifique uma classe ControladorAposta, que conta com um construtor que inicializa dicionários vazios para cada lado das apostas.
b) implemente o método adicionar_aposta, que recebe um nome de usuário (string), o valor da aposta e um lado (1 ou 2). Se não for a primeira vez que esse usuário aposta naquele time, o valor deve ser somado ao das apostas anteriores. Se esse usuário tiver apostado no outro time, o sistema deve negar a operação, retornando False. Analogamente, se a aposta for feita com sucesso, o método deve retornar True.
c) implemente o método definir_resultado recebe o lado vencedor ( 1 ou 2) e retorna um dicionário onde as chaves são nomes de usuários do lado vencedor e os valores são números contendo o saldo final de cada apostador após a definição do resultado. O saldo final de cada apostador vencedor é dado pela seguinte expressão:
S=\frac{u}{V} \cdot P
onde:
  • u é o valor investido por aquele usuário vencedor;
  • V é o valor total de apostas no lado vencedor e
  • P é o valor total de apostas no lado perdedor.

Passo 1

Resumo do que o enunciado pede e informações dadas:
  • Deve-se armazenar, para cada lado da aposta, um dicionário que mapeia o nome de cada apostador para o valor total que ele investiu naquele lado.
  • Ao final do jogo, o montante total apostado no time perdedor deve ser distribuído entre os apostadores do time vencedor na mesma proporção das apostas de cada um. Além disso, o valor investido por cada usuário do time vencedor é devolvido.
  • Perguntas que o enunciado faz:
    1. (a) Criar uma classe ControladorAposta cujo construtor inicializa dicionários vazios para cada lado das apostas.
    2. (b) Implementar o método adicionar_aposta(nome, valor, lado) que:
      • soma o valor à aposta anterior do mesmo usuário caso ele já tenha apostado naquele mesmo lado;
      • recusa (retorna False) se o usuário já tiver apostado no outro lado;
      • retorna True se a aposta foi aceita com sucesso.
    3. (c) Implementar definir_resultado(vencedor) que recebe o lado vencedor (1 ou 2) e retorna um dicionário cujas chaves são os nomes dos apostadores vencedores e os valores são os saldos finais após a definição do resultado.
  • Informação matemática fornecida no enunciado: a parcela do montante do lado perdedor atribuída a cada apostador vencedor é dada por
\\ S = \frac{u}{V}\cdot P
onde u é o valor apostado por aquele usuário, V é o total apostado no lado vencedor e P é o total apostado no lado perdedor.
  • Observação importante (para não me perder na implementação): além da parcela vinda do time perdedor, o valor investido por cada apostador vencedor é devolvido. Portanto o montante final recebido por um apostador vencedor será o seu investimento u acrescido da parcela S acima, ou seja
T = u + S = u + \frac{u}{V}\cdot P.

Passo 2

Escolha das estruturas e raciocínio para implementar:
  • Usar dicionários do Python para armazenar, por lado, a associação nome -> valor acumulado. Dicionário é ideal porque:
    • permite checar rapidamente se um nome já existe (operações de busca em tempo médio constante);
    • permite acumular valores com facilidade via d[name] = d.get(name, 0.0) + valor.
  • Representação interna proposta:
    • self.lado1 é um dicionário com apostas do lado 1;
    • self.lado2 é um dicionário com apostas do lado 2.
  • Regras implementadas no método adicionar_aposta:
    • se lado é 1 e nome já existe em self.lado2, retorna False (não pode apostar nos dois lados);
    • se lado é 2 e nome já existe em self.lado1, retorna False;
    • caso contrário, soma valor ao dicionário do respectivo lado e retorna True.
  • No método definir_resultado:
    • identificar dicionário dos vencedores e dos perdedores;
    • calcular V=\sum das apostas do lado vencedor e P=\sum das apostas do lado perdedor;
    • para cada vencedor com aposta u, calcular a parcela recebida do lado perdedor como \displaystyle S=\frac{u}{V}\cdot P e o total final como \displaystyle T=u+S;
    • montar e retornar um dicionário {nome: T}.

Passo 3

Detalhes da construção do construtor:
  • O construtor (__init__) deve criar os dois dicionários vazios e inicializá-los. Em código isso será (explicação, não o método inteiro):
    • self.lado1 = {}
    • self.lado2 = {}
  • Comentário didático: em Python {} cria um dicionário vazio; vamos usar chaves do tipo str (nome do apostador) e valores do tipo float (valor acumulado apostado).

Passo 4

Lógica do método adicionar_aposta passo a passo:
  1. Validar o parâmetro lado — aceitar apenas 1 ou 2. Se for outro valor, podemos recusar (retornando False) pois o enunciado define só esses dois lados.
  2. Se lado == 1:
    • verificar se nome existe em self.lado2. Se sim, retornar False (usuário já apostou no outro lado).
    • caso contrário, fazer self.lado1[nome] = self.lado1.get(nome, 0.0) + float(valor) e retornar True.
  3. Se lado == 2:
    • verificar se nome existe em self.lado1. Se sim, retornar False.
    • caso contrário, acumular em self.lado2 análogo ao caso anterior e retornar True.
  • Observação prática: usar dict.get(nome, 0.0) evita ter que checar if nome in dict separadamente para somar.

Passo 5

Lógica do método definir_resultado passo a passo com fórmulas:
  1. Recebemos vencedor em \{1,2\}. Determinamos:
    • winners = dicionário do lado vencedor;
    • losers = dicionário do lado perdedor.
  2. Calculamos os totais:
    • V = \sum_{x\in \text{winners}} \text{aposta}(x) (soma de todos os valores no dicionário dos vencedores).
    • P = \sum_{y\in \text{losers}} \text{aposta}(y) (soma de todas as apostas do lado perdedor).
  3. Para cada apostador vencedor com aposta u:
    • calculamos a parcela proveniente do lado perdedor por S=\frac{u}{V}\cdot P.(Se V=0 não faz sentido dividir; nesse caso não há apostadores vencedores e o método pode retornar um dicionário vazio.)
    • o total final que o apostador recebe é T=u+S = u + \frac{u}{V}\cdot P.
  4. Montamos um dicionário resultado tal que resultado[nome] = T para cada nome no dicionário dos vencedores, e retornamos resultado.
  • Observação sobre casos extremos:
    • Se não houver apostas no lado vencedor ( V=0), retornamos {} porque não há ninguém pra receber nada.
    • Se não houver apostas no lado perdedor ( P=0), então cada vencedor simplesmente recebe de volta o seu investimento: T = u.

Passo 6

Exemplo numérico para fixar o raciocínio (faço passo a passo para você entender e poder repetir na prova):
  • Suponha que no lado 1 temos duas apostas: Alice u_A=30 e Bob u_B=20. No lado 2 temos Carol u_C=50.
  • Então o total do lado vencedor (supondo que o vencedor seja o lado 1) é V = u_A + u_B = 30 + 20 = 50.O total do lado perdedor é P = u_C = 50.
  • Para Alice: S_A = \frac{u_A}{V}\cdot P = \frac{30}{50}\cdot 50 = 30.Logo o total final dela é T_A = u_A + S_A = 30 + 30 = 60.
  • Para Bob: S_B = \frac{20}{50}\cdot 50 = 20,\qquad T_B = 20 + 20 = 40.
  • Resultado retornado seria {'Alice': 60.0, 'Bob': 40.0}.
  • Isso confirma a regra: cada vencedor recupera sua aposta e ganha uma parte proporcional do total perdido.

Passo 7

Complexidade e observações finais rápidas para a prova:
  • Operações de adicionar aposta são O(1) em média (acesso e atualização de dicionário).
  • Calcular o resultado exige somar as apostas (duas somas) e depois iterar sobre os vencedores — tempo O(n) onde n é número de apostadores no lado vencedor.
  • Trate casos inválidos (valor de lado ou vencedor fora de \{1,2\}) de forma simples: recusar ou lançar erro, conforme necessidade. Aqui optei por recusar na adição e lançar ValueError em definir_resultado para sinalizar uso incorreto.
  • Força e coragem — isso é só implementação direta de dicionários e proporção. Você já consegue fazer isso na prova se lembrar: somar, dividir para achar fração e multiplicar pela parte perdida.

Resposta

class ControladorAposta:
def init(self):
self.lado1 = {}
self.lado2 = {}
def adicionar_aposta(self, nome, valor, lado):
    if lado not in (1, 2):
        return False
    valor = float(valor)
    if lado == 1:
        if nome in self.lado2:
            return False
        self.lado1[nome] = self.lado1.get(nome, 0.0) + valor
        return True
    else:
        if nome in self.lado1:
            return False
        self.lado2[nome] = self.lado2.get(nome, 0.0) + valor
        return True

def definir_resultado(self, vencedor):
    if vencedor not in (1, 2):
        raise ValueError("vencedor deve ser 1 ou 2")
    winners = self.lado1 if vencedor == 1 else self.lado2
    losers = self.lado2 if vencedor == 1 else self.lado1
    V = sum(winners.values())
    P = sum(losers.values())
    resultado = {}
    if V == 0:
        return resultado
    for nome, u in winners.items():
        share = (u / V) * P if P > 0 else 0.0
        resultado[nome] = u + share
    return resultado

Exercícios relacionados