Projetos de Algoritmos Imperativos
Construa projetos de algoritmos imperativos: fatorial, Fibonacci, verificador de primos, bubble sort e um jogo de adivinhação com implementações Python completas.
Projetos de Algoritmos Imperativos
Esta lição reúne tudo que você aprendeu para construir implementações completas de algoritmos. Escreveremos programas Python imperativos que resolvem problemas computacionais clássicos.
O que é Programação Imperativa?
Programação imperativa descreve COMO resolver um problema passo a passo, usando instruções que mudam o estado do programa. Isso contrasta com programação declarativa, que descreve QUAL deve ser o resultado.
Projeto 1: Calculadora de Fatorial
O fatorial de n (escrito n!) é o produto de todos os inteiros positivos de 1 a n.
Fluxograma do Algoritmo
Implementação
# fatorial.py
"""Calculadora de fatorial usando abordagem imperativa."""
def fatorial_iterativo(n):
"""
Calcula fatorial usando um loop.
Args:
n: Inteiro não negativo
Returns:
int: n! (fatorial de n)
Raises:
ValueError: Se n for negativo
"""
if n < 0:
raise ValueError("Fatorial não é definido para números negativos")
resultado = 1
for i in range(2, n + 1):
resultado *= i
return resultado
def fatorial_com_passos(n):
"""Calcula fatorial mostrando cada passo."""
if n < 0:
raise ValueError("Fatorial não é definido para números negativos")
print(f"Calculando {n}!:")
resultado = 1
for i in range(1, n + 1):
resultado *= i
print(f" Passo {i}: resultado = {resultado}")
return resultado
# Testa a função fatorial
print("=== Calculadora de Fatorial ===\n")
# Casos de teste
valores_teste = [0, 1, 5, 10, 20]
for n in valores_teste:
resultado = fatorial_iterativo(n)
print(f"{n:2d}! = {resultado}")
print("\nCálculo detalhado de 5!:")
fatorial_com_passos(5)Saída:
=== Calculadora de Fatorial ===
0! = 1
1! = 1
5! = 120
10! = 3628800
20! = 2432902008176640000
Cálculo detalhado de 5!:
Calculando 5!:
Passo 1: resultado = 1
Passo 2: resultado = 2
Passo 3: resultado = 6
Passo 4: resultado = 24
Passo 5: resultado = 120
Projeto 2: Gerador de Sequência Fibonacci
A sequência Fibonacci: cada número é a soma dos dois anteriores.
Fluxograma do Algoritmo
Implementação
# fibonacci.py
"""Gerador de sequência Fibonacci."""
def sequencia_fibonacci(n):
"""
Gera os primeiros n números Fibonacci.
Args:
n: Número de Fibonacci para gerar
Returns:
list: Primeiros n números Fibonacci
"""
if n <= 0:
return []
if n == 1:
return [0]
fib = [0, 1]
for i in range(2, n):
proximo = fib[i - 1] + fib[i - 2]
fib.append(proximo)
return fib
def fibonacci_nesimo(n):
"""
Obtém o n-ésimo número Fibonacci (indexado em 0).
Args:
n: Posição na sequência
Returns:
int: O n-ésimo número Fibonacci
"""
if n < 0:
raise ValueError("n deve ser não negativo")
if n <= 1:
return n
a, b = 0, 1
for _ in range(2, n + 1):
a, b = b, a + b
return b
def razao_fibonacci(n):
"""Mostra como as razões Fibonacci se aproximam da razão áurea."""
print(f"{'n':>4} {'F(n)':>12} {'F(n)/F(n-1)':>14}")
print("-" * 35)
anterior = 0
for i in range(1, n + 1):
atual = fibonacci_nesimo(i)
if anterior > 0:
razao = atual / anterior
print(f"{i:4d} {atual:12d} {razao:14.10f}")
else:
print(f"{i:4d} {atual:12d} {'N/A':>14}")
anterior = atual
# Testa Fibonacci
print("=== Gerador de Sequência Fibonacci ===\n")
# Gera sequências
print("Primeiros 10 números Fibonacci:")
print(sequencia_fibonacci(10))
print("\nPrimeiros 15 números Fibonacci:")
print(sequencia_fibonacci(15))
# Convergência da razão áurea
print("\nRazões Fibonacci se aproximando da razão áurea (φ ≈ 1.6180339887):")
razao_fibonacci(15)Saída:
=== Gerador de Sequência Fibonacci ===
Primeiros 10 números Fibonacci:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Primeiros 15 números Fibonacci:
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]
Razões Fibonacci se aproximando da razão áurea (φ ≈ 1.6180339887):
n F(n) F(n)/F(n-1)
-----------------------------------
1 1 N/A
2 1 1.0000000000
3 2 2.0000000000
4 3 1.5000000000
5 5 1.6666666667
6 8 1.6000000000
7 13 1.6250000000
8 21 1.6153846154
9 34 1.6190476190
10 55 1.6176470588
11 89 1.6181818182
12 144 1.6179775281
13 233 1.6180555556
14 377 1.6180257511
15 610 1.6180371353
Projeto 3: Verificador de Números Primos
Um número primo é um número natural maior que 1 que não tem divisores positivos além de 1 e ele mesmo.
Fluxograma do Algoritmo
Implementação
# verificador_primos.py
"""Verificador e gerador de números primos."""
def eh_primo(n):
"""
Verifica se um número é primo usando divisão por tentativa otimizada.
Args:
n: Inteiro para verificar
Returns:
bool: True se primo, False caso contrário
"""
if n <= 1:
return False
if n <= 3:
return True
if n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def encontrar_primos_ate(limite):
"""
Encontra todos os números primos até um limite.
Args:
limite: Limite superior (inclusive)
Returns:
list: Todos os números primos até o limite
"""
primos = []
for num in range(2, limite + 1):
if eh_primo(num):
primos.append(num)
return primos
def contar_primos_no_intervalo(inicio, fim):
"""Conta primos em um intervalo."""
contagem = 0
for num in range(inicio, fim + 1):
if eh_primo(num):
contagem += 1
return contagem
# Testa verificador de primos
print("=== Verificador de Números Primos ===\n")
# Verifica números individuais
numeros_teste = [1, 2, 3, 4, 17, 25, 29, 97, 100]
print("Verificação de primos:")
for n in numeros_teste:
status = "Primo" if eh_primo(n) else "Não primo"
print(f" {n:3d}: {status}")
# Encontra primos até 50
print("\nPrimos até 50:")
primos = encontrar_primos_ate(50)
print(f" {primos}")
print(f" Contagem: {len(primos)}")
# Densidade de primos
print("\nDensidade de primos:")
for limite in [10, 100, 1000]:
contagem = contar_primos_no_intervalo(2, limite)
densidade = contagem / limite * 100
print(f" Até {limite:4d}: {contagem:4d} primos ({densidade:.1f}%)")Saída:
=== Verificador de Números Primos ===
Verificação de primos:
1: Não primo
2: Primo
3: Primo
4: Não primo
17: Primo
25: Não primo
29: Primo
97: Primo
100: Não primo
Primos até 50:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
Contagem: 15
Densidade de primos:
Até 10: 4 primos (40.0%)
Até 100: 25 primos (25.0%)
Até 1000: 168 primos (16.8%)
Projeto 4: Bubble Sort (Ordenação por Bolha)
Bubble sort é um algoritmo de ordenação simples que percorre repetidamente a lista, compara elementos adjacentes e os troca se estiverem na ordem errada.
Fluxograma do Algoritmo
Implementação
# bubble_sort.py
"""Implementação de bubble sort com visualização."""
def bubble_sort(arr):
"""
Ordena uma lista usando o algoritmo bubble sort.
Args:
arr: Lista de elementos comparáveis
Returns:
list: Lista ordenada (nova lista, original inalterada)
"""
resultado = arr.copy()
n = len(resultado)
for i in range(n - 1):
trocado = False
for j in range(n - i - 1):
if resultado[j] > resultado[j + 1]:
# Troca
resultado[j], resultado[j + 1] = resultado[j + 1], resultado[j]
trocado = True
if not trocado:
break # Já ordenada
return resultado
def bubble_sort_visual(arr):
"""Ordena com visualização passo a passo."""
resultado = arr.copy()
n = len(resultado)
passadas = 0
print(f"Inicial: {resultado}")
for i in range(n - 1):
trocado = False
passadas += 1
for j in range(n - i - 1):
if resultado[j] > resultado[j + 1]:
resultado[j], resultado[j + 1] = resultado[j + 1], resultado[j]
trocado = True
print(f" Passada {passadas}, Troca {j},{j+1}: {resultado}")
if not trocado:
print(f" Passada {passadas}: Sem trocas necessárias (ordenada!)")
break
print(f"Final: {resultado}")
print(f"Total de passadas: {passadas}")
return resultado
# Testa bubble sort
print("=== Bubble Sort ===\n")
# Ordenação simples
numeros = [64, 34, 25, 12, 22, 11, 90]
print(f"Original: {numeros}")
ordenados = bubble_sort(numeros)
print(f"Ordenada: {ordenados}")
print(f"Original inalterada: {numeros}\n")
# Ordenação visual
print("Bubble sort visual:")
bubble_sort_visual([5, 3, 8, 1, 2])Saída:
=== Bubble Sort ===
Original: [64, 34, 25, 12, 22, 11, 90]
Ordenada: [11, 12, 22, 25, 34, 64, 90]
Original inalterada: [64, 34, 25, 12, 22, 11, 90]
Bubble sort visual:
Inicial: [5, 3, 8, 1, 2]
Passada 1, Troca 0,1: [3, 5, 8, 1, 2]
Passada 1, Troca 2,3: [3, 5, 1, 8, 2]
Passada 1, Troca 3,4: [3, 5, 1, 2, 8]
Passada 2, Troca 1,2: [3, 1, 5, 2, 8]
Passada 2, Troca 2,3: [3, 1, 2, 5, 8]
Passada 3, Troca 0,1: [1, 3, 2, 5, 8]
Passada 3, Troca 1,2: [1, 2, 3, 5, 8]
Passada 4: Sem trocas necessárias (ordenada!)
Final: [1, 2, 3, 5, 8]
Total de passadas: 4
Projeto 5: Jogo de Adivinhação de Números
Um jogo interativo completo que combina todos os conceitos aprendidos neste curso.
Fluxograma do Jogo
Implementação
# jogo_adivinhacao.py
"""Jogo de adivinhação com pontuação e níveis de dificuldade."""
import random
def obter_dificuldade():
"""Permite ao jogador escolher o nível de dificuldade."""
print("\nSelecione a dificuldade:")
print(" 1. Fácil (1-50, 10 tentativas)")
print(" 2. Médio (1-100, 7 tentativas)")
print(" 3. Difícil (1-200, 5 tentativas)")
while True:
escolha = input("Escolha (1-3): ").strip()
if escolha == "1":
return 50, 10
elif escolha == "2":
return 100, 7
elif escolha == "3":
return 200, 5
print("Escolha inválida. Digite 1, 2 ou 3.")
def jogar():
"""Joga uma rodada do jogo de adivinhação."""
max_num, max_tentativas = obter_dificuldade()
secreto = random.randint(1, max_num)
tentativas = 0
palpites = []
print(f"\n{'=' * 40}")
print(f" Adivinhe o número entre 1 e {max_num}")
print(f" Você tem {max_tentativas} tentativas")
print(f"{'=' * 40}\n")
while tentativas < max_tentativas:
# Obtém palpite válido
while True:
try:
palpite = int(input(f"Tentativa {tentativas + 1}/{max_tentativas}: "))
if 1 <= palpite <= max_num:
break
print(f" Digite um número entre 1 e {max_num}.")
except ValueError:
print(" Digite um número válido.")
tentativas += 1
palpites.append(palpite)
# Verifica palpite
if palpite == secreto:
print(f"\n 🎉 Parabéns! Você acertou!")
print(f" O número era {secreto}.")
print(f" Tentativas: {tentativas}/{max_tentativas}")
# Cálculo da pontuação
pontuacao = max(0, (max_tentativas - tentativas + 1) * 100)
print(f" Pontuação: {pontuacao} pontos")
return True, pontuacao
elif palpite < secreto:
diff = secreto - palpite
dica = "Muito baixo!" if diff > 20 else "Baixo! Tente um número maior."
print(f" {dica}")
else:
diff = palpite - secreto
dica = "Muito alto!" if diff > 20 else "Alto! Tente um número menor."
print(f" {dica}")
# Fim de jogo
print(f"\n 😔 Fim de jogo! O número era {secreto}.")
print(f" Seus palpites: {palpites}")
return False, 0
def exibir_estatisticas(jogos_jogados, jogos_ganhos, pontuacao_total):
"""Exibe estatísticas do jogo."""
print(f"\n{'=' * 40}")
print(" ESTATÍSTICAS DO JOGO")
print(f"{'=' * 40}")
print(f" Jogos jogados: {jogos_jogados}")
print(f" Jogos ganhos: {jogos_ganhos}")
print(f" Jogos perdidos: {jogos_jogados - jogos_ganhos}")
if jogos_jogados > 0:
taxa_vitoria = jogos_ganhos / jogos_jogados * 100
media_pontuacao = pontuacao_total / jogos_jogados
print(f" Taxa vitória: {taxa_vitoria:.1f}%")
print(f" Média pontos: {media_pontuacao:.0f}")
print(f" Pontuação total: {pontuacao_total}")
print(f"{'=' * 40}")
def principal():
"""Loop principal do jogo."""
print("=" * 40)
print(" JOGO DE ADIVINHAÇÃO")
print("=" * 40)
jogos_jogados = 0
jogos_ganhos = 0
pontuacao_total = 0
while True:
jogos_jogados += 1
ganhou, pontuacao = jogar()
if ganhou:
jogos_ganhos += 1
pontuacao_total += pontuacao
# Jogar novamente?
while True:
novamente = input("\nJogar novamente? (sim/nao): ").strip().lower()
if novamente in ("sim", "s", "nao", "n", "não"):
break
print("Digite 'sim' ou 'nao'.")
if novamente in ("nao", "n", "não"):
break
exibir_estatisticas(jogos_jogados, jogos_ganhos, pontuacao_total)
print("\nObrigado por jogar! Até mais! 👋")
# Executa o jogo
if __name__ == "__main__":
principal()Saída de exemplo:
========================================
JOGO DE ADIVINHAÇÃO
========================================
Selecione a dificuldade:
1. Fácil (1-50, 10 tentativas)
2. Médio (1-100, 7 tentativas)
3. Difícil (1-200, 5 tentativas)
Escolha (1-3): 2
========================================
Adivinhe o número entre 1 e 100
Você tem 7 tentativas
========================================
Tentativa 1/7: 50
Alto! Tente um número menor.
Tentativa 2/7: 25
Baixo! Tente um número maior.
Tentativa 3/7: 37
Baixo! Tente um número maior.
Tentativa 4/7: 43
🎉 Parabéns! Você acertou!
O número era 43.
Tentativas: 4/7
Pontuação: 400 pontos
Jogar novamente? (sim/nao): nao
========================================
ESTATÍSTICAS DO JOGO
========================================
Jogos jogados: 1
Jogos ganhos: 1
Jogos perdidos: 0
Taxa vitória: 100.0%
Média pontos: 400
Pontuação total: 400
========================================
Obrigado por jogar! Até mais! 👋
Exercícios Práticos
Exercício 1: Fatorial Aprimorado
Modifique a função fatorial para usar um loop while em vez de um loop for.
Exercício 2: Busca Fibonacci
Escreva uma função que verifica se um dado número é um número Fibonacci.
Exercício 3: Fatoração Prima
Escreva uma função que retorna a fatoração prima de um número como uma lista de fatores primos.
Exercício 4: Selection Sort
Implemente selection sort: encontre o elemento mínimo, troque-o para o início, repita para os elementos restantes.
Exercício 5: Busca Binária
Implemente busca binária em uma lista ordenada. Compare sua eficiência com busca linear.
Exercício 6: Jogo de Adivinhação Aprimorado
Adicione recursos ao jogo de adivinhação:
- Rastreie melhor pontuação (menos tentativas)
- Adicione um sistema de dicas (revela se número é par/ímpar)
- Adicione um cronômetro para medir quanto tempo cada jogo leva
Exercício 7: Crivo de Eratóstenes
Implemente o algoritmo Crivo de Eratóstenes para encontrar todos os primos até n. Compare sua velocidade com o método de divisão por tentativa.
Exercício 8: Comparação de Algoritmos
Escreva um programa que compara o tempo de execução do bubble sort vs o sorted() embutido do Python para listas de diferentes tamanhos (100, 1000, 10000 elementos).
Resumo
Nesta lição, você construiu projetos completos de algoritmos imperativos:
- Fatorial: Cálculo iterativo com visualização passo a passo
- Fibonacci: Geração de sequência e convergência da razão áurea
- Verificador de Primos: Divisão por tentativa otimizada para teste de primalidade
- Bubble Sort: Ordenação passo a passo com visualização de trocas
- Jogo de Adivinhação: Jogo interativo completo com níveis de dificuldade e pontuação
Estes projetos demonstram como variáveis, loops, condicionais, funções e estruturas de dados trabalham juntos para resolver problemas computacionais reais. Pratique modificar e estender estes algoritmos para aprofundar seu entendimento.