Capítulo 5: Funções e Modularização#

ch5

Definindo Funções#

🎙️ Ouça a explicação sobre condicionais (if-elif-else):

Funções são blocos de código (subprogramas) reutilizáveis que executam tarefas específicas e são essenciais para a estruturação de programas em Python. Elas permitem modularizar seu código, tornando-o mais gerenciável, legível e fácil de manter. Neste capítulo, exploraremos os conceitos essenciais sobre funções, incluindo diferentes tipos de funções e boas práticas de utilização.

Para definir uma função, utilizamos a palavra reservada def. A estrutura básica de uma função inclui:

  • Palavra-chave def: Indica o início da definição de uma função.

  • Nome da função: Deve ser descritivo e seguir as convenções de nomenclatura de Python, conforme descrito na PEP 8. Use letras minúsculas com palavras separadas por underscores (convenção snake_case).

  • Parênteses () contendo os parâmetros (se houver) separados por vírgulas.

  • Dois pontos : para terminar a linha de cabeçalho.

  • Bloco de código indentado que constitui o corpo da função.

  • (Opcional) return para retornar um valor da função. Se omitido, a função retorna None por padrão.

Exemplo simples de uma função para calcular e retornar a soma de dois números.

function
Figura: Fluxo dos dados em uma função

Compare o fluxo dos dados com a função real abaixo:

def soma2(parametro1, parametro2):
    resultado = parametro1 + parametro2
    return resultado 

# Chamando a função
resultado = soma2(3, 4)
print(resultado)

Saída do Código:

7

Docstrings e Type Hints#

Antes de avançar no uso de funções em Python, é importante conhecer docstrings e type hints. Essas práticas são recomendadas para tornar o código mais claro, documentado e fácil de usar.

  • Docstrings são strings de documentação que ficam logo após a definição de uma função, classe ou módulo. Elas descrevem o que a função faz, explicam os parâmetros e informam o valor de retorno. Isso melhora a compreensão do código e permite que ferramentas de documentação capturem essas informações automaticamente. As docstrings também aparecem quando usamos a função help no Python, facilitando o acesso às informações sobre a função sem precisar ler o código fonte.

    Exemplo de docstring:

    def saudacao(nome):
        """
        Exibe uma saudação personalizada para o usuário.
    
        Args:
            nome: O nome da pessoa a ser saudada.
        
        Retorna:
            None.
        """
        print(f"Olá, {nome}!")
    

    Aqui, a docstring explica o propósito da função saudacao, descreve o parâmetro nome e informa que o valor de retorno é None. Para ver essa docstring em ação, podemos chamar help(saudacao) no console, e o Python exibirá a explicação, o que é muito útil para quem estiver usando ou revisando o código.

  • Type hints (ou anotações de tipo) permitem especificar os tipos esperados dos parâmetros e do valor de retorno de uma função. Isso melhora a legibilidade, ajuda na identificação de inconsistências de tipo e facilita o uso de ferramentas que verificam tipos.

    Exemplo de docstring e type hints:

    def soma(a: float, b: float) -> float:
        """
        Calcula a soma de dois números.
    
        Args:
            a (float): Primeiro número.
            b (float): Segundo número.
        
        Retorna:
            float: A soma de 'a' e 'b'.
        """
        return a + b
    

    Neste exemplo, estamos indicando que a e b devem ser float, e que a função soma retorna um valor float. Usando help(soma), você verá a docstring com os detalhes dos parâmetros e do retorno.

Funções sem Retorno (Procedimentos)#

Uma função sem retorno, também conhecida como procedimento, é um bloco de código que executa uma tarefa específica, mas não retorna nenhum valor explicitamente (retorna None implicitamente). É útil quando você deseja realizar uma ação ou exibir informações sem a necessidade de obter um resultado para uso posterior.

Exemplo:

def saudacao(nome_pessoa: str) -> None:
    """
    Exibe uma saudação personalizada.
    
    Args:
        nome_pessoa: Nome da pessoa a ser saudada.
    """
    print(f"Olá, {nome_pessoa}!")

# Chamando a função
saudacao("Aurora")

Saída do Código:

Olá, Aurora!

Observe o uso de type hints (str e None) no exemplo acima. Eles ajudam a documentar os tipos esperados dos parâmetros e do retorno da função, tornando o código mais claro e facilitando a detecção de erros.

Funções com Retorno#

Funções com retorno são aquelas que devolvem um valor para a parte do código que as chamou. Esse valor pode ser atribuído a variáveis ou usado em cálculos adicionais. Abaixo, apresentamos um exemplo sem valor padrão e, em seguida, um exemplo que utiliza type hints e um valor padrão.

Exemplo sem Valor Padrão:

def soma(a: float, b: float) -> float:
    """
    Calcula a soma de dois números.
    
    Args:
        a: Primeiro número a ser somado.
        b: Segundo número a ser somado.
    
    Retorna:
        A soma dos valores 'a' e 'b'.
    """
    return a + b

# Chamando a função com argumentos
resultado = soma(3.5, 5.0)
print(f"Resultado: {resultado}")

Saída do Código:

Resultado: 8.5

Exemplo com Type Hints e Valor Padrão:

def somaP(a: float, b: float = 0.0) -> float:
    """
    Calcula a soma de dois números.

    Args:
        a: Primeiro número a ser somado.
        b: Segundo número a ser somado, padrão é 0.0.
    
    Retorna:
        A soma dos valores 'a' e 'b'.
    """
    return a + b

# Chamando a função com diferentes argumentos
resultado1 = somaP(3.5, 5.0)  # Dois argumentos
resultado2 = somaP(3.5)       # Usando o valor padrão de b
print(f"Resultados: {resultado1}, {resultado2}")

Saída do Código:

Resultados: 8.5, 3.5

No segundo exemplo, b tem um valor padrão de 0.0, o que permite chamar a função apenas com o primeiro argumento. Isso demonstra como o uso de type hints e valores padrão facilita a flexibilidade e a clareza do código.

Parâmetros Posicionais e Nomeados (Chave-Valor)#

Python permite que funções aceitem dois tipos principais de argumentos: posicionais e nomeados (chave-valor).

  • Parâmetros Posicionais: São aqueles que são passados para a função na ordem em que aparecem na definição da função.

    Exemplo:

    def exibir_info(nome: str, idade: int) -> None:
        print(f"Nome: {nome}, Idade: {idade}")
    
    # Chamando a função com parâmetros posicionais
    exibir_info("Alice", 30)
    

    Saída do Código:

    Nome: Alice, Idade: 30
    
  • Parâmetros Nomeados (Chave-Valor): São aqueles que são passados para a função utilizando a sintaxe chave=valor.

    Exemplo:

    def exibir_info(nome: str, idade: int) -> None:
        print(f"Nome: {nome}, Idade: {idade}")
    
    # Chamando a função com parâmetros nomeados
    exibir_info(idade=30, nome="Alice")
    

    Saída do Código:

    Nome: Alice, Idade: 30
    

Funções com Múltiplos Valores de Retorno#

Em Python, uma função pode retornar múltiplos valores, o que é muito útil para obter diferentes informações de um cálculo ou processamento em uma única chamada. Isso permite retornar resultados relacionados sem a necessidade de criar estruturas mais complexas, como classes ou dicionários.

Exemplo: Retornando Dois Valores

No exemplo abaixo, a função soma_dif_valores calcula a soma e a diferença de dois números, retornando ambos os valores ao mesmo tempo.

def soma_dif_valores(a: float, b: float) -> tuple[float, float]:
    """
    Calcula a soma e a diferença de dois números.

    Args:
        a: Primeiro número.
        b: Segundo número.

    Retorna:
        Uma tupla contendo a soma e a diferença dos números.
    """
    soma_resultado = a + b
    diferenca_resultado = a - b
    return soma_resultado, diferenca_resultado

# Chamando a função
soma_valores, diferenca_valores = soma_dif_valores(10, 5)
print(f"A soma é: {soma_valores}")
print(f"A diferença é: {diferenca_valores}")

Saída do Código:

A soma é: 15.0
A diferença é: 5.0

O retorno múltiplo em Python utiliza tuplas. No momento da chamada, você pode “desempacotar” os valores em variáveis distintas, facilitando o uso.

Exemplo: Retornando Valores de Tipos Diferentes

A seguir, a função analise_lista retorna a soma dos elementos de uma lista e um valor booleano indicando se todos os números são positivos.

def analise_lista(numeros: list[int]) -> tuple[int, bool]:
    """
    Analisa uma lista de números inteiros.

    Args:
        numeros: Lista de números inteiros.

    Retorna:
        - A soma dos elementos.
        - Um valor booleano indicando se todos os números são positivos.
    """
    soma_total = sum(numeros)
    
    # Verificando se todos os números são positivos sem usar all
    todos_positivos = True
    for num in numeros:
        if num <= 0:
            todos_positivos = False
            break

    return soma_total, todos_positivos

# Chamando a função
soma, positivos = analise_lista([3, -1, 5, 7, 2])
print(f"Soma dos elementos: {soma}")
print(f"Todos os elementos são positivos? {positivos}")

Saída do Código:

Soma dos elementos: 16
Todos os elementos são positivos? False

A função retorna a soma dos elementos e verifica se todos são positivos, retornando False caso algum não seja.

Funções que Recebem Outras Funções como Argumentos#

Em Python, é possível passar funções como argumentos para outras funções, o que facilita a criação de soluções flexíveis e reutilizáveis. Essa abordagem é útil para transformar, filtrar ou aplicar operações em dados.

Exemplo: Passando Funções como Argumentos

O exemplo abaixo mostra uma função que aplica uma operação, definida por outra função, a cada elemento de uma lista.

def aplicar_operacao(operacao, lista: list[int]) -> list[int]:
    """
    Aplica uma operação a cada elemento de uma lista.

    Args:
        operacao: Função que define a operação a ser aplicada.
        lista: Lista de elementos.

    Retorna:
        Uma nova lista com os resultados da operação aplicada.
    """
    return [operacao(elemento) for elemento in lista]

# Funções para operações matemáticas
def quadrado(x: int) -> int:
    return x * x

def cubo(x: int) -> int:
    return x * x * x

# Aplicando a função quadrado a uma lista
numeros = [1, 2, 3, 4, 5]
resultado_quadrado = aplicar_operacao(quadrado, numeros)
print(f"O quadrado de cada número na lista é: {resultado_quadrado}")

# Aplicando a função cubo a uma lista
resultado_cubo = aplicar_operacao(cubo, numeros)
print(f"O cubo de cada número na lista é: {resultado_cubo}")

Saída do Código:

O quadrado de cada número na lista é: [1, 4, 9, 16, 25]
O cubo de cada número na lista é: [1, 8, 27, 64, 125]
  • A função aplicar_operacao recebe:

    • Uma função (operacao) que define a lógica de transformação.

    • Uma lista (lista) cujos elementos serão processados.

  • Usamos uma compreensão de lista para aplicar a operação a cada elemento da lista.

  • As funções quadrado e cubo são exemplos de operações que podem ser passadas para aplicar_operacao.

Esse modelo permite reutilizar o mesmo código para diferentes operações, simplificando a criação de soluções modulares e flexíveis.

Funções Anônimas (Lambda)#

As funções anônimas, também conhecidas como lambdas, são funções pequenas e temporárias definidas sem um nome formal. Elas são criadas usando a palavra-chave lambda seguida dos parâmetros da função, dois pontos (:) e a expressão a ser retornada.

A sintaxe básica de uma função lambda é:

lambda parâmetros: expressão

Exemplo com uma variável#

(lambda x: x * 2)(3)

Saída do Código:

6

Neste exemplo, uma função lambda que dobra um número é definida e imediatamente chamada com o valor 3. A função calcula 3 * 2 e retorna 6.

As funções lambda são úteis quando você precisa de uma função simples e de uso único, sem a necessidade de defini-la formalmente usando a palavra-chave def.

Exemplo com duas variáveis#

soma = lambda x, y: x + y
print(f"A soma de 5 e 7 é: {soma(5, 7)}")

Saída do Código:

A soma de 5 e 7 é: 12

Aqui, a função lambda lambda x, y: x + y recebe dois parâmetros, x e y, e retorna sua soma. Ao atribuí-la à variável soma, ela pode ser chamada como uma função comum. Na última linha, o código demonstra como calcular a soma de dois valores, exibindo o resultado.

Exemplo com listas e map()#

numeros = [1, 2, 3, 4, 5]
quadrados = list(map(lambda x: x ** 2, numeros))
print(f"Os quadrados dos números {numeros} são: {quadrados}")

Saída do Código:

Os quadrados dos números [1, 2, 3, 4, 5] são: [1, 4, 9, 16, 25]

Neste exemplo, temos uma lista de números chamada numeros. Utilizamos a função map() juntamente com uma função lambda para calcular o quadrado de cada número na lista. A função lambda lambda x: x ** 2 recebe um parâmetro x e retorna o quadrado desse valor. A função map() aplica a função lambda a cada elemento da lista numeros, retornando um objeto map. Em seguida, convertemos esse objeto em uma lista usando a função list() e atribuímos o resultado à variável quadrados. Por fim, imprimimos a lista original numeros e a lista quadrados.

Exemplo com múltiplos retornos#

quadrado_e_cubo = lambda x: (x ** 2, x ** 3)
resultado = quadrado_e_cubo(5)
print(f"O quadrado e o cubo de 5 são: {resultado}")

Saída do Código:

O quadrado e o cubo de 5 são: (25, 125)

Neste exemplo, a função lambda lambda x: (x ** 2, x ** 3) recebe um parâmetro x e retorna dois valores: o quadrado e o cubo de x, dentro de uma tupla. Ao passar 5 como argumento, a função retorna a tupla (25, 125), que é impressa na tela.

As funções lambda são uma forma concisa e elegante de criar funções simples e de uso único em Python, especialmente quando usadas em conjunto com funções de ordem superior, como map(), filter() e reduce(). Além disso, sua flexibilidade permite trabalhar com múltiplas variáveis, facilitando a criação de soluções rápidas e legíveis.

Funções Recursivas#

A recursividade é uma técnica em que uma função chama a si mesma, direta ou indiretamente, até atingir uma condição de parada. Essa abordagem é útil para problemas que podem ser divididos em subproblemas menores do mesmo tipo.

Exemplo: Soma de Números de 1 até N#

A soma dos números de 1 até um número n pode ser calculada recursivamente:

def soma(n):
    if n == 1:  # Condição de parada
        return 1
    else:
        return n + soma(n - 1)  # Chamada recursiva

# Teste da função
print(soma(5))

Saída do Código:

15

A função soma(5) chama soma(4), que chama soma(3), e assim por diante, até atingir soma(1), que retorna 1. Os valores são somados de volta ao longo da cadeia de chamadas.

Representação Recursiva

A execução da função pode ser visualizada como uma pilha de chamadas:

soma(5)
  |
  +--> 5 + soma(4)
             |
             +--> 4 + soma(3)
                    |
                    +--> 3 + soma(2)
                           |
                           +--> 2 + soma(1)
                                  |
                                  +--> 1 (condição de parada)

Resolução acumulada na volta:

soma(1) = 1
soma(2) = 2 + 1 = 3
soma(3) = 3 + 3 = 6
soma(4) = 4 + 6 = 10
soma(5) = 5 + 10 = 15

Exemplo: Soma de Números em um Intervalo#

Para calcular a soma dos números entre a e b:

def soma_intervalo(a, b):
    if a > b:  # Condição de parada
        return 0
    else:
        return a + soma_intervalo(a + 1, b)  # Chamada recursiva

# Teste da função
print(soma_intervalo(3, 7))

Saída do Código:

23

A função soma os números incrementando a até que a > b.

Exemplo: Fatorial de um Número#

O cálculo do fatorial de um número n é feito multiplicando todos os inteiros de 1 até n:

def fatorial(n):
    if n == 0 or n == 1:  # Condição de parada
        return 1
    else:
        return n * fatorial(n - 1)  # Chamada recursiva

# Teste da função
print(fatorial(5))

Saída do Código:

120

A função chama a si mesma com n - 1 até que n seja 0 ou 1, retornando 1.

Exemplo: Soma dos Elementos de uma Lista#

A soma dos elementos de uma lista pode ser feita de forma recursiva:

def soma_lista(lista):
    if len(lista) == 0:  # Caso base: lista vazia
        return 0
    else:
        return lista[0] + soma_lista(lista[1:])  # Chamada recursiva

# Teste da função
lista_exemplo = [1, 2, 3, 4, 5]
print(f"A soma dos números na lista é: {soma_lista(lista_exemplo)}")

Saída do Código:

A soma dos números na lista é: 15

A função pega o primeiro elemento da lista e chama a si mesma com o restante. O processo continua até que a lista esteja vazia.

Vantagens e Desvantagens da Recursividade#

Vantagens

Desvantagens

Torna o código mais elegante e claro.

Consome mais memória devido ao empilhamento de chamadas.

Ideal para problemas que seguem uma estrutura recursiva natural, como árvores.

Pode ser ineficiente para problemas grandes.

Evita o uso de variáveis auxiliares ou estruturas de controle complexas.

Erros como loops infinitos podem ocorrer caso a condição de parada não seja bem definida.

A recursividade é uma ferramenta poderosa, mas deve ser utilizada com cuidado. Em problemas de grande escala, pode ser melhor optar por uma abordagem iterativa para economizar recursos computacionais.

Funções Built-in#

As funções built-in do Python são ferramentas essenciais que simplificam tarefas comuns e oferecem funcionalidades robustas prontas para uso. Estão sempre disponíveis sem a necessidade de importação, com exceção de algumas funções que pertencem a módulos específicos, como math.

A tabela abaixo apresenta uma lista ampliada das principais funções built-in, categorizadas para facilitar a consulta.

Categoria

Função

Descrição

Exemplo

Saída

Saída e Entrada

print()

Imprime mensagens ou valores na saída padrão.

print("Olá, mundo!")

Olá, mundo!

input()

Solicita entrada do usuário.

nome = input("Digite seu nome: ")

(aguarda entrada do usuário)

Conversão de Tipo

int()

Converte para inteiro.

int("123")

123

float()

Converte para ponto flutuante.

float("3.14")

3.14

str()

Converte para string.

str(123)

'123'

list()

Converte para lista.

list("abc")

['a', 'b', 'c']

tuple()

Converte para tupla.

tuple([1, 2, 3])

(1, 2, 3)

set()

Converte para conjunto.

set([1, 2, 2, 3])

{1, 2, 3}

dict()

Cria um dicionário.

dict(a=1, b=2)

{'a': 1, 'b': 2}

Manipulação de Sequências

len()

Retorna o tamanho de uma sequência.

len("Python")

6

max()

Retorna o valor máximo em uma sequência.

max([2, 8, 5])

8

min()

Retorna o valor mínimo em uma sequência.

min([2, 8, 5])

2

sum()

Soma os elementos de uma sequência numérica.

sum([1, 2, 3])

6

sorted()

Retorna uma lista ordenada.

sorted([3, 1, 2])

[1, 2, 3]

Tipo e Valor

type()

Retorna o tipo de um objeto.

type("texto")

<class 'str'>

id()

Retorna o identificador único de um objeto.

id([1, 2, 3])

(depende do objeto)

isinstance()

Verifica se um objeto é de um tipo específico.

isinstance(10, int)

True

hash()

Retorna o valor hash de um objeto.

hash("texto")

(valor numérico do hash)

Matemática

abs()

Retorna o valor absoluto de um número.

abs(-10)

10

pow()

Retorna x elevado à potência y.

pow(2, 3)

8

math.sqrt()

Retorna a raiz quadrada de um número.

math.sqrt(16)

4.0

math.factorial()

Calcula o fatorial de um número.

math.factorial(5)

120

round()

Arredonda um número para o inteiro mais próximo ou para casas decimais específicas.

round(3.14159, 2)

3.14

Tratar Erros

assert

Verifica uma condição e gera um erro se for falsa.

assert x > 0, "Erro"

(depende da condição)

Iteração

range()

Cria um intervalo para iteração.

list(range(5))

[0, 1, 2, 3, 4]

Outros

help()

Exibe a documentação de um objeto.

help(print)

(documentação do print)

dir()

Lista os atributos e métodos de um objeto.

dir("texto")

(lista de métodos e atributos)

open()

Abre um arquivo e retorna um objeto de arquivo.

open('arquivo.txt', 'r')

(objeto de arquivo)

eval()

Avalia uma expressão em forma de string.

eval("2 + 2")

4

exec()

Executa um código Python em forma de string.

exec("x = 5")

(define x no ambiente atual)


Observação sobre o módulo math#

As funções matemáticas como math.sqrt() e math.factorial() exigem a importação do módulo math. Por exemplo:

import math
raiz = math.sqrt(16)
print(raiz)

Saída do Código:

4

Para explorar todas as funções built-in e obter mais informações, consulte a documentação oficial do Python.

Exercícios#

  1. Menor e Maior entre Três Números

Desenvolva um programa que determine o menor e o maior número entre três valores fornecidos pelo usuário. O programa deve utilizar funções para realizar as operações necessárias. Siga as instruções:

  • Crie uma função chamada ler_numeros() que solicite ao usuário que insira três números e retorne esses valores.

  • Implemente uma função chamada encontrar_menor_maior(a, b, c) que receba três números como parâmetros e retorne uma tupla contendo o menor e o maior valor, nesta ordem.

  • No programa principal, utilize as funções criadas para:

    • Obter os três números do usuário.

    • Calcular o menor e o maior valor.

    • Exibir os resultados.

Exemplo de uso no programa principal:

num1, num2, num3 = ler_numeros()
menor, maior = encontrar_menor_maior(num1, num2, num3)
print(f"O menor número é: {menor}")
print(f"O maior número é: {maior}")

Certifique-se de que o programa trate adequadamente diferentes tipos de entrada, incluindo números inteiros e decimais.

# Teste 1
Entrada: 10, 5, 8
Saída: 
O menor número é: 5
O maior número é: 10

# Teste 2
Entrada: 3.14, 1.71, 1.41
Saída:
O menor número é: 1.41
O maior número é: 3.14

# Teste 3
Entrada: -5, 0, -10
Saída:
O menor número é: -10
O maior número é: 0

# Teste 4
Entrada: 1, 3.14, 2
Saída:
O menor número é: 1
O maior número é: 3.14
  1. Cálculo do IMC Utilizando Funções

Desenvolva um programa em Python para calcular o Índice de Massa Corporal (IMC) de uma pessoa, utilizando funções para organizar e modularizar o código.

O programa deve incluir as seguintes funções:

  • Uma função para ler os dados do usuário (peso em kg e altura em metros).

  • Uma função para calcular o IMC usando a fórmula: IMC = peso / (altura * altura).

  • Uma função para classificar o IMC de acordo com as faixas padrão.

A classificação do IMC deve seguir a tabela abaixo:

IMC (kg/m²)

Classificação

< 18.5

Abaixo do peso

18.5 - 24.9

Peso normal

25.0 - 29.9

Sobrepeso

30.0 - 34.9

Obesidade grau 1

35.0 - 39.9

Obesidade grau 2

≥ 40.0

Obesidade grau 3

No programa principal, chame as funções na ordem adequada para:

  • Obter os dados do usuário.

  • Calcular o IMC.

  • Determinar a classificação.

Por exemplo:

peso, altura = ler_dados()
imc = calcular_imc(peso, altura)
classificacao = classificar_imc(imc)
print(f"Seu IMC é {imc:.2f} - Classificação: {classificacao}")

Certifique-se de tratar possíveis erros de entrada do usuário, como valores negativos ou zero para peso e altura. O programa deve ser robusto e capaz de lidar com diferentes cenários de entrada.

# Teste 1
Entrada: 90.5, 1.85
Saída: Seu IMC é 26.44 - Classificação: Sobrepeso

# Teste 2
Entrada: 65.0, 1.75
Saída: Seu IMC é 21.22 - Classificação: Peso normal

# Teste 3
Entrada: 45.0, 1.60
Saída: Seu IMC é 17.58 - Classificação: Abaixo do peso

# Teste 4
Entrada: 120.0, 1.70
Saída: Seu IMC é 41.52 - Classificação: Obesidade grau 3
  1. Calculadora de Área de Formas Geométricas

Crie um programa que funcione como uma calculadora de área para diferentes formas geométricas, incluindo triângulo, círculo e retângulo. O programa deve fornecer um menu fácil de usar para que o usuário selecione a forma desejada e, em seguida, insira as dimensões necessárias para calcular a área.

Crie uma função principal chamada calcular_area() que representa a abstração de um menu ao usuário com as seguintes opções:

  • Opção 1: Calcular a área de um triângulo (base e altura)

  • Opção 2: Calcular a área de um círculo (raio)

  • Opção 3: Calcular a área de um retângulo (comprimento e largura)

  • Opção 4: Sair do programa

Crie individualmente uma função para o cálculo das áreas de cada forma geométrica:

  • area_triangulo(base, altura)

  • area_circulo(raio)

  • area_retangulo(comprimento, largura)

Exemplos de teste:

# Teste 1
Entrada: 
1
5
10
Saída: A área do triângulo é: 25.00

# Teste 2
Entrada:
2
3
Saída: A área do círculo é: 28.27

# Teste 3
Entrada:
3
4
6
Saída: A área do retângulo é: 24.00

# Teste 4
Entrada: 4
Saída: Programa encerrado.

Observações:

  • Use a biblioteca math para obter o π (pi) nos cálculos do círculo.

  • Arredonde todos os resultados para duas casas decimais.

4. Sistema de Bonificação para Atletas Olímpicos

O Comitê Olímpico Nacional decidiu criar um sistema de bonificação para atletas que ganharam medalhas nas Olimpíadas. O sistema funciona da seguinte forma:

Cada atleta recebe uma bonificação base de acordo com a medalha:

  • Ouro: R$ 50.000

  • Prata: R$ 30.000

  • Bronze: R$ 10.000

Além disso, há bônus adicionais baseados em critérios específicos:

  • Quebra de recorde mundial: +R$ 100.000

  • Primeira medalha do país na modalidade: +R$ 50.000

Crie uma função chamada calcular_bonificacao que receba os seguintes parâmetros:

  • medalhas: uma lista de strings representando as medalhas ganhas (“ouro”, “prata” ou “bronze”)

  • recorde_mundial: Uma String, Sim ou Nao, indicando se o atleta quebrou um recorde mundial

  • primeira_medalha_pais: Uma String, Sim ou Nao, indicando se é a primeira medalha do país na modalidade

A função deve retornar o valor total da bonificação do atleta.

# Teste 1
Entrada:Ouro,Sim,Nao
Saída: 150000

# Teste 2
Entrada:Prata,Bronze,Nao,Sim
Saída: 90000

# Teste 3
Entrada:Bronze,Bronze,Bronze,Nao,Nao
Saída: 30000

# Teste 4
Entrada:Ouro,Prata,Bronze,Nao,Sim
Saída: 140000

5. Calculando as Raízes de Equações Quadráticas

Neste exercício, você terá a oportunidade de aplicar conceitos matemáticos para resolver o problema de Bhaskara, escrevendo um código para calcular as raízes de uma equação quadrática.

Dada uma equação quadrática na forma \(Ax^2 + Bx + C = 0\), escreva um programa que leia três valores de ponto flutuante e calcule as raízes da equação usando a Fórmula de Bhaskara. Se não for possível calcular as raízes, mostre a mensagem “Impossível calcular”, caso haja uma divisão por zero ou raiz de número negativo.

\( R1 = \frac{-B + \sqrt{B^2 - 4AC}}{2A} \)

\( R2 = \frac{-B - \sqrt{B^2 - 4AC}}{2A} \)

Observações:

  • Se \(A\) é igual a zero, não é possível calcular as raízes.

  • Se o discriminante \(\Delta = B^2 - 4AC \) é negativo, não é possível calcular as raízes.

  • As raízes da equação devem ter 2 dígitos após o ponto decimal.

  • Escreva uma função para leitura dos dados, outra para verificar se é possível calcular as raízes, e uma terceira para calcular e retornar as raízes.

# Teste 1
Entrada: 10.0, 19.1, 5.2
Saída:
R1 = -0.33
R2 = -1.58

# Teste 2
Entrada: 0.0, 20.0, 5.0
Saída: Impossível calcular

# Teste 3
Entrada: 1.0, -3.0, 2.0
Saída:
R1 = 2.00
R2 = 1.00

# Teste 4
Entrada: 1.0, 2.0, 5.0
Saída: Impossível calcular

6. Contando: Pares, Ímpares, Positivos e Negativos

Escreva uma função chamada contar_pares_impares que receba uma lista de números como argumento e retorne duas variáveis: a contagem de números pares e a contagem de números ímpares na lista.

Escreva outra função chamada contar_positivos_negativos que receba a mesma lista de números como argumento e retorne duas variáveis: a contagem de números positivos e a contagem de números negativos na lista.

O programa principal deve ler uma lista de números inteiros na entrada, passar essa lista para as funções acima. Em seguida, o programa deve imprimir as contagens de números pares, ímpares, positivos e negativos, cada uma em uma linha separada.

# Teste 1
Entrada: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, -18, -19, -20, -21, -22, -23, -24, -25
Saída:
Quantidade de números pares: 24
Quantidade de números ímpares: 26
Quantidade de números positivos: 25
Quantidade de números negativos: 25

# Teste 2
Entrada: 30, -31, 32, -33, 34, -35, 36, -37, 38, -39, 40, -41, 42, -43, 44, -45, 46, -47, 48, -49, 50, -51, 52, -53, 54, -55, 56, -57, 58, -59, 60, -61, 62, -63, 64, -65, 66, -67, 68, -69, 70, -71, 72, -73, 74, -75
Saída:
Quantidade de números pares: 23
Quantidade de números ímpares: 23
Quantidade de números positivos: 23
Quantidade de números negativos: 23

7. Soma Recursiva de uma Lista

Escreva uma função recursiva chamada soma_recursiva que receba uma lista de números inteiros como entrada e retorne a soma de todos os elementos da lista.

Por exemplo, se a lista de entrada for [1, 2, 3, 4, 5], a função deve retornar 15 (que é a soma de todos os números na lista).

Observações:

  • A função soma_recursiva deve ter uma condição base, que é quando a lista está vazia.

  • A função deve chamar a si mesma com uma versão menor da lista, até chegar na condição base.

  • A função deve realizar a soma dos elementos da lista de forma recursiva.

Teste sua função com as seguintes entradas:

# Teste 1
entrada = 1, 2, 3, 4, 5, 50, 60, 70, 80, 90, 0, 1
saida = 366

# Teste 2
entrada = 10, 20, 30, 40, 50, 1, 2, 3, 4, 5, 6, 7, -15, -20
saida = 143

8. Cálculo da Sequência de Fibonacci

Imagine que você tem uma lista de números. O objetivo é calcular o n-ésimo número da sequência de Fibonacci para cada número dessa lista e imprimir a soma total desses números.

A sequência de Fibonacci é como uma escada em espiral, onde cada número é a soma dos dois anteriores. Ela começa com 0 e 1, e continua infinitamente: 0, 1, 1, 2, 3, 5, 8, 13, 21…

Para isso, você precisará criar duas funções recursivas:

  1. A função Fibonacci: Essa função será o coração da operação. Ela receberá um número como entrada e, usando a recursão, calculará o número correspondente na sequência de Fibonacci.

  2. A função Soma Recursiva: Essa função receberá a lista de resultados da função Fibonacci e, novamente usando a recursão, somará todos os elementos dessa lista.

No final, você imprimirá na tela a soma total de todos os números da sequência de Fibonacci calculados para cada número da lista de entrada.

Lembre-se: a recursão é como um espelho que reflete a si mesmo. A função chama a si mesma para resolver problemas menores até chegar a um ponto de parada, chamado de “condição base”. É como descer uma escada: você dá um passo de cada vez até chegar ao chão.

# Teste 1
Entrada: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
Saída: 1596

# Teste 2
Entrada: 10, 11, 9, 15, 17, 23, 13, 27, 12, 11, 22
Saída: 245637

9. Cálculo da Potência de Forma Recursiva

Escreva uma função recursiva chamada calcular_potencia que receba dois números como entrada: a base (base) e o expoente (expoente). A função deve calcular e retornar o resultado da base elevada ao expoente, sem utilizar a função math.pow() ou qualquer outra função matemática avançada, apenas operações matemáticas elementares.

Por exemplo, se a base for 2 e o expoente for 3, a função deve retornar 8 (que é o resultado de 2 elevado a 3).

Observações:

  • A função calcular_potencia deve ter uma condição base, que é quando o expoente é igual a 0.

  • A função deve chamar a si mesma com uma versão menor do expoente, até chegar na condição base.

  • A função deve realizar o cálculo da potência de forma recursiva, usando apenas operações matemáticas básicas (multiplicação, divisão, adição e subtração).

Teste sua função com as seguintes entradas:

# Teste 1
Entrada: 2, 3
Saída: 2^3 = 8

# Teste 2
Entrada: 4, 5
Saída: 4^5 = 1024

# Teste 3
Entrada: 6, 4
Saída: 6^4 = 1296

# Teste 4
Entrada: 34, 0
Saída: 34^0 = 1

Lembre-se de implementar a função calcular_potencia de forma recursiva, usando apenas operações matemáticas básicas.

10. Torre de Hanói: Um Desafio Recursivo da Computação e Matemática

A Torre de Hanói é um problema clássico e intrigante no campo da computação e matemática. Envolve a movimentação estratégica de discos entre três pinos, seguindo um conjunto específico de regras. O desafio parece simples à primeira vista, mas sua complexidade aumenta exponencialmente à medida que o número de discos cresce.

O Problema: Imagine três pinos, rotulados como A, B e C. No início do jogo, todos os discos, que variam em tamanho, estão empilhados em ordem decrescente de tamanho no pino A, com o disco maior embaixo e o menor no topo. O objetivo é transferir todos os discos do pino A para o pino C.

As Regras:

  • Você só pode mover um disco por vez.

  • Cada movimento envolve tirar o disco de cima de uma pilha e colocá-lo em cima de outra pilha.

  • Nunca coloque um disco maior em cima de um menor. Os discos devem ser empilhados em ordem de tamanho.

  • O pino B é auxiliar. Você pode usá-lo como um pino intermediário para ajudar na movimentação dos discos.

Visualizando o Jogo:

Estado inicial:

    |         |         |
    |         |         |
   ===        |         |
  =====       |         |
 =======      |         |
-----------------------------
   A         B         C

Estado intermediário (após mais duas jogadas):

    |         |         |
    |         |         |
    |         |         |
    |         |         |
 =======    =====      ===
-----------------------------
   A         B         C

Estado final:

    |         |         |
    |         |         |
    |         |        ===
    |         |       =====
    |         |      =======   
-----------------------------
   A         B         C

Sua Tarefa: Implemente uma função recursiva chamada torre_de_hanoi que resolva esse problema. A função deve receber como entrada o número de discos (n) e os nomes dos pinos de origem, auxiliar e destino. Ela deve executar e imprimir os movimentos necessários para transferir todos os discos do pino de origem para o pino de destino.

Protótipo da Função:

def torre_de_hanoi(n, origem, auxiliar, destino):
    # Implementação aqui

Dicas e Observações:

  • A função deve ter uma condição base para quando houver apenas um disco.

  • Use a recursividade para dividir o problema em subproblemas menores.

  • Imprima cada movimento no formato: “Mover disco de [origem] para [destino]”.

  • A solução recursiva deve:

    • Mover n-1 discos para o pino auxiliar

    • Mover o disco maior para o pino de destino

    • Mover os n-1 discos do pino auxiliar para o pino de destino

Testes:

# Teste 1
Entrada: 3, A, B, C
Saída:
Mover disco de A para C
Mover disco de A para B
Mover disco de C para B
Mover disco de A para C
Mover disco de B para A
Mover disco de B para C
Mover disco de A para C

# Teste 2
Entrada: 4, A, B, C
Saída:
Mover disco de A para B
Mover disco de A para C
Mover disco de B para C
Mover disco de A para B
Mover disco de C para A
Mover disco de C para B
Mover disco de A para B
Mover disco de A para C
Mover disco de B para C
Mover disco de B para A
Mover disco de C para A
Mover disco de B para C
Mover disco de A para B
Mover disco de A para C
Mover disco de B para C

Exercícios (Extra)#

1. Analisador de Desempenho: Planeje seus Estudos!

Este exercício ajuda você a analisar seu desempenho acadêmico e planejar seus estudos de maneira eficiente. Com base nas notas obtidas em 7 disciplinas, o sistema calculará métricas essenciais como médias, desvios padrões e a nota necessária para alcançar a meta de aprovação (5.0). Além disso, ele criará um ranking de prioridades de estudo com base na consistência, instabilidade e dificuldade de alcançar a média.

As disciplinas são analisadas na seguinte ordem, cada uma com 3 unidades:

  1. Linguagem de Programação

  2. Álgebra Linear

  3. Modelagem do Mundo Físico I

  4. Práticas de Leitura e Escrita II

  5. Química Geral

  6. Cálculo Diferencial e Integral I

  7. Meio Ambiente e Desenvolvimento Urbano

  • Entrada dos Dados:

    • Para cada disciplina, você fornecerá 6 notas:

      • 3 avaliações da 1ª unidade.

      • 3 avaliações da 2ª unidade.

    • O sistema calculará a nota necessária na 3ª unidade para atingir a média de 5.0.

Total: 42 notas para 7 disciplinas.

Cálculos Importantes:

O sistema calculará as seguintes métricas:

  • Média da Unidade:

    \( \text{Média da Unidade} = \frac{\text{soma das 3 notas}}{3} \)

  • Nota necessária na 3ª unidade para atingir a média de 5.0:

    \( \text{Nota Necessária} = 3 \times \text{Meta (5.0)} - (\text{Média da 1ª Unidade} + \text{Média da 2ª Unidade}) \)

  • Consistência da Disciplina: Avalia a estabilidade no desempenho entre as duas primeiras unidades.
    Quanto menor a diferença percentual entre as médias, maior a consistência.

    \( \text{Consistência} = 1 - \frac{|\text{Média da 2ª Unidade} - \text{Média da 1ª Unidade}|}{\text{Média da 1ª Unidade}} \)

    • Consistência próxima de 1: Desempenho estável entre as unidades.

    • Consistência próxima de 0: Variação significativa entre as unidades.

  • Instabilidade da Disciplina: Mede a variação na dispersão das notas entre as duas primeiras unidades.

    \( \text{Instabilidade} = \frac{\text{Desvio Padrão da 2ª Unidade}}{\text{Desvio Padrão da 1ª Unidade}} \)

    • Instabilidade = 1: Mesma dispersão entre as unidades.

    • Instabilidade > 1: A segunda unidade foi mais dispersa.

    • Instabilidade < 1: A primeira unidade foi mais dispersa.

  • Ranking de Prioridade para Estudo: Determina quais disciplinas requerem mais atenção.
    \( \text{Prioridade} = \text{Peso}_1 \times (1 - \text{Consistência}) + \text{Peso}_2 \times \text{Instabilidade} + \text{Peso}_3 \times \text{Nota Necessária} \)

    • Pesos padrão:

      • Consistência: \( \text{Peso}_1 = 2.0 \)

      • Instabilidade: \( \text{Peso}_2 = 1.5 \)

      • Nota Necessária: \( \text{Peso}_3 = 1.0 \)

Tarefa:

Implemente a função principal analisar_desempenho para calcular todas as métricas acima e gerar os resultados para cada disciplina.

Observação: Para criar o ranking de prioridades, você pode utilizar funções de ordenação disponíveis na linguagem, como sorted em Python, para facilitar a implementação.

Protótipo

def analisar_desempenho(
    notas: list[float],
    calcular_media,
    calcular_desvio_padrao,
    calcular_nota_necessaria,
    avaliar_consistencia,
    gerar_ranking_prioridade
) -> None:
    """
    Analisa o desempenho acadêmico com base nas notas das disciplinas.

    Parâmetros:
        notas (list[float]): Lista com as notas das disciplinas (42 valores).
        calcular_media (function): Função para calcular a média.
        calcular_desvio_padrao (function): Função para calcular o desvio padrão.
        calcular_nota_necessaria (function): Função para calcular a nota necessária.
        avaliar_consistencia (function): Função para avaliar a consistência.
        gerar_ranking_prioridade (function): Função para gerar o ranking de prioridade.
    """
    pass

Teste:

# Teste 1
Entrada:
6.0, 7.0, 8.0, 5.0, 6.5, 6.0,  
4.0, 5.5, 6.0, 4.5, 5.0, 4.0,  
7.0, 8.0, 7.5, 6.0, 7.0, 6.5,  
6.0, 6.5, 7.0, 6.0, 6.0, 5.5,  
5.0, 5.5, 5.0, 4.5, 4.0, 4.0,  
6.0, 7.0, 6.5, 5.5, 6.0, 5.0,  
7.0, 6.5, 6.0, 6.5, 6.0, 5.5   

Saída:
Ranking de prioridade para estudo:
1. Química Geral:
   - Consistência: 0.81
   - Instabilidade: 1.00
   - Nota necessária na 3ª unidade: 5.67
   - Prioridade: 7.55
2. Álgebra Linear:
   - Consistência: 0.87
   - Instabilidade: 0.48
   - Nota necessária na 3ª unidade: 5.33
   - Prioridade: 6.31
3. Cálculo Diferencial e Integral I:
   - Consistência: 0.85
   - Instabilidade: 1.00
   - Nota necessária na 3ª unidade: 3.00
   - Prioridade: 4.81
4. Meio Ambiente e Desenvolvimento Urbano:
   - Consistência: 0.92
   - Instabilidade: 1.00
   - Nota necessária na 3ª unidade: 2.50
   - Prioridade: 4.15
5. Práticas de Leitura e Escrita II:
   - Consistência: 0.90
   - Instabilidade: 0.58
   - Nota necessária na 3ª unidade: 2.67
   - Prioridade: 3.74
6. Linguagem de Programação:
   - Consistência: 0.83
   - Instabilidade: 0.76
   - Nota necessária na 3ª unidade: 2.17
   - Prioridade: 3.65
7. Modelagem do Mundo Físico I:
   - Consistência: 0.87
   - Instabilidade: 1.00
   - Nota necessária na 3ª unidade: 1.00
   - Prioridade: 2.77