Pular para o conteúdo principal

Exercícios da Aula 03

Solução dos exercícios da aula 03

Exercício 1

Modifique os programas acima para ler 7 notas no lugar de 5.

In [1]:
# Programa para cálculo da média de 7 notas
notas = [6, 7, 5, 8, 9, 4, 8]
soma = 0
i = 0
while i < 7:
    soma += notas[i]
    i += 1
print(f"Média: {soma/i:4.1f}")
    
Média:  6.7
In [3]:
# Versão do programa onde o professor pode entrar com 7 notas
notas = [0,0,0,0,0,0,0]
soma = 0
i = 0
while i < 7:
    notas[i] = float(input(f"Nota {i}: "))
    soma += notas[i]
    i += 1
print(f"Média: {soma/i:4.1f}")
Nota 0: 6
Nota 1: 7
Nota 2: 5
Nota 3: 8
Nota 4: 9
Nota 5: 4
Nota 6: 8
Média:  6.7

Exercício 2

Reescreva o programa para calcular médias de modo que o professor primeiro entra com o número de notas e em seguida o programa lê este número de notas e calcula a média.

[6, 7, 5, 8, 9, 4, 8]

In [6]:
notas = []
soma = 0
i = 0
num_notas = int(input(f"Entre com o número de notas: "))
while i < num_notas:
    notas.append(float(input(f"Nota {i}: ")))
    i += 1
i = 0    
while i < num_notas:
    soma += notas[i]
    i += 1
print(f"Média: {soma/i:4.1f}")
Entre com o número de notas: 7
Nota 0: 6
Nota 1: 7
Nota 2: 5
Nota 3: 8
Nota 4: 9
Nota 5: 4
Nota 6: 8
Média:  6.7

Exercício 3

Faça um programa que percorra duas listas inteiras e gere uma terceira sem elementos repetidos

In [10]:
L1 = [1,2,3,5,6,7] # Primeira lista
L2 = [1,0,3,4,0,7,8] # Segunda lista
n1 = len(L1) # Comprimento da primeira lista
n2 = len(L2) # Comprimento da segunda lista
L = [] # Lista que será gerada
i = 0 # Contador

while i < n1: # Vamos percorrer a primeira lista
    x = L1[i]
    k = 0
    n = len(L)
    achou = False
    while k < n:  # Vamos percorrer a terceira que estamos 
                  # construindo
        y = L[k]
        if y == x: # Achou um igual. Não pode ser inserido
            achou = True
            break
        k += 1
    if not achou:
        L.append(x)
    i += 1
    
# Repetir com a lista 2:
i = 0
while i < n2: # Vamos percorrer a primeira lista
    x = L2[i]
    k = 0
    n = len(L)
    achou = False
    while k < n:  # Vamos percorrer a terceira que estamos 
                  # construindo
        y = L[k]
        if y == x: # Achou um igual. Não pode ser inserido
            achou = True
            break
        k += 1
    if not achou:
        L.append(x)
    i += 1

        
L
Out[10]:
[1, 2, 3, 5, 6, 7, 0, 4, 8]

Exercício 4

O que acontece quando não verificamos se a lista está vazia antes de chamar o método pop?

Que tal testar? O bom do computador é que nada de ruim pode acontecer. (ou pode...)

Para testar vamos diminuir o comprimento da file

In [12]:
# Simulação de fila de banco:
último = 4  # Tamanho menor
fila = list(range(1, último + 1))
while True:
    print(f"\nExistem {len(fila)} clientes na fila")
    print(f"Fila atual: {fila}")
    print("Digite F para adicionar um cliente ao fim da fila, ")
    print("ou A para realizar o atendimento. S para sair.")
    operação = input("Operação (F, A ou S): ")
    if operação == "A":
        atendido = fila.pop(0)
        print(f"Cliente {atendido} atendido")
    elif operação == "F":
        último += 1 # Incrementa o ticket
        fila.append(último)
    elif operação == 'S':
        break
    else:
        print("Operação inválida. Digite apenas A, F ou S!")
Existem 4 clientes na fila
Fila atual: [1, 2, 3, 4]
Digite F para adicionar um cliente ao fim da fila, 
ou A para realizar o atendimento. S para sair.
Operação (F, A ou S): A
Cliente 1 atendido

Existem 3 clientes na fila
Fila atual: [2, 3, 4]
Digite F para adicionar um cliente ao fim da fila, 
ou A para realizar o atendimento. S para sair.
Operação (F, A ou S): A
Cliente 2 atendido

Existem 2 clientes na fila
Fila atual: [3, 4]
Digite F para adicionar um cliente ao fim da fila, 
ou A para realizar o atendimento. S para sair.
Operação (F, A ou S): A
Cliente 3 atendido

Existem 1 clientes na fila
Fila atual: [4]
Digite F para adicionar um cliente ao fim da fila, 
ou A para realizar o atendimento. S para sair.
Operação (F, A ou S): A
Cliente 4 atendido

Existem 0 clientes na fila
Fila atual: []
Digite F para adicionar um cliente ao fim da fila, 
ou A para realizar o atendimento. S para sair.
Operação (F, A ou S): A
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
/tmp/ipykernel_3519/3875226094.py in <module>
      9     operação = input("Operação (F, A ou S): ")
     10     if operação == "A":
---> 11         atendido = fila.pop(0)
     12         print(f"Cliente {atendido} atendido")
     13     elif operação == "F":

IndexError: pop from empty list

É dá erro! Não é possível tirar um elemento de uma lista vazia

Exercício 5

Altere o programa da fila de modo que se possa trabalhar com vários comandos digitados de uma só vez. No programa acima, apenas uma operação pode ser digitada por vez. Faça com que o programa aceite strings com vários comandos

Exemplo: FFFAAAS significa três chegadas de novos clientes, três atendimentos e saída do programa.

In [13]:
último = 10
fila = list(range(1, último + 1))
operações = "FFFAAAS"
Nop = len(operações)
i = 0
while i < Nop:
    print(f"\nExistem {len(fila)} clientes na fila")
    print(f"Fila atual: {fila}")
    operação = operações[i]
    print(f"A operação é {operação}.")
    i += 1  # Não podemos esquecer...
    if operação == "A":
        if len(fila) > 0:
            atendido = fila.pop(0)
            print(f"Cliente {atendido} atendido")
        else:
            print("Fila vazia! Nenhum cliente para atender.")
    elif operação == "F":
        último += 1 # Incrementa o ticket
        fila.append(último)
    elif operação == 'S':
        break
    else:
        print("Operação inválida. Ela deve ser apenas A, F ou S!")
Existem 10 clientes na fila
Fila atual: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
A operação é F.

Existem 11 clientes na fila
Fila atual: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
A operação é F.

Existem 12 clientes na fila
Fila atual: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
A operação é F.

Existem 13 clientes na fila
Fila atual: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
A operação é A.
Cliente 1 atendido

Existem 12 clientes na fila
Fila atual: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
A operação é A.
Cliente 2 atendido

Existem 11 clientes na fila
Fila atual: [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
A operação é A.
Cliente 3 atendido

Existem 10 clientes na fila
Fila atual: [4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
A operação é S.

Exercício 6

Faça um programa que leia uma expressão com parênteses. Usando pilhas, verifique se os parênteses foram abertos e fechados na ordem correta. Exemplo:

  • (()) OK
  • ()()(()()) OK
  • ()) Erro
In [20]:
expressão = "((())()(())))"
n = len(expressão)
pilha = []
i = 0
ocorreu_erro = False
while i < n:
    c = expressão[i]
    i += 1
    if c == ')':
        if len(pilha) > 0:
            pilha.pop(-1)
        else:
            ocorreu_erro = True
            break
    elif c == '(':
        pilha.append(1)
    else: # Qualquer outro caracter, ignorar!
        continue  
if len(pilha) > 0:  # Se sobrou algo na pila, tá desbalanceado
    ocorreu_erro = True

if ocorreu_erro:
    print("Erro")
else:
    print("Ok")
Erro

Exercício 7

Modifique o programa de modo que realize a mesma tarefa sem usar a variável achou. Dica: observe a condição de saída do while.

In [22]:
L = [15, 7, 27, 39]
p = int(input("Digite o valor a procurar: "))
i = 0
while i < len(L):
    if L[i] == p:
        print(f"{p} foi encontrado na posição {i}.")
        break
    i += 1
else:
    print(f"{p} não foi encontrado na lista.")
Digite o valor a procurar: 6
6 não foi encontrado na lista.

Exercício 8

Modifique o exemplo para pesquisar dois valores. Em vez de apenas p, leia outro valor v que também será procurado. Na impressão, indique qual dos dois valores foi encontrado primeiro.

In [32]:
L = [15, 7, 27, 39]
p = int(input("Digite o valor a procurar: "))
v = int(input("Digite o valor a procurar: "))
achou_p = False
achou_v = False
i = 0
while i < len(L):
    if L[i] == p:
        achou_p = True
        break
    i += 1
ip = i
i = 0
while i < len(L):
    if L[i] == v:
        achou_v = True
        break
    i += 1
iv = i

if achou_p:
    print(f"{p} foi encontrado na posição {ip}.")
else:
    print(f"{p} não foi encontrado na lista.")

if achou_v:
    print(f"{v} foi encontrado na posição {iv}.")
else:
    print(f"{v} não foi encontrado na lista.")
if achou_p and achou_v:
    if ip < iv:
        print(f"{p} foi achado antes que {v}")
    elif iv < ip:
        print(f"{v} foi achado antes que {p}")

    
    
Digite o valor a procurar: 5
Digite o valor a procurar: 6
5 não foi encontrado na lista.
6 não foi encontrado na lista.

Exercício 9

Tente converter este programa (exemplo acima)

# Programa para adicionar números a uma lista
L = []
while True:
    n = int(input("Digite um número (0 sai): "))
    if n == 0:
        break
    L.append(n)

usando for.

Explique se for pode ser sempre usado no lugar de while e porquê.

Estritamente falando, este programa não poderia ser escrito usando for pois não sabemos o número de repetições necessárias. O usuário pode parar a qualquer momento!

Tendo dito isso, este programa tem um problema: pode não sair nunca. É muito comum que se tenha um limite. Com esse limite (arbitrário vai depender do contexto), podemos usar o for. Sempre que possível, é recomendado fazer isso.

In [34]:
nmax = 5
L = []
for i in range(nmax):
    n = int(input("Digite um número (0 sai): "))
    if n == 0:
        break
    L.append(n)
L
Digite um número (0 sai): 1
Digite um número (0 sai): 2
Digite um número (0 sai): 3
Digite um número (0 sai): 4
Digite um número (0 sai): 5
Out[34]:
[1, 2, 3, 4, 5]

Exercício 10

Escreva um programa que acha o menor elemento de uma lista

In [35]:
L = [123,15, 12, 4352, 1, 4567]
emin = L[0]
for e in L:
    if e < emin:
        emin = e
print(f"O menor elemento da lista é {emin}.")
O menor elemento da lista é 1.

Exercício 11

Modifique o programa para achar o máximo de modo que encontre o máximo mas também encontre o índice onde este máximo ocorre.

In [37]:
L = [123,15, 12, 4352, 1, 4567]
emax = L[0]
imax = 0
for i,e in enumerate(L):
    if e > emax:
        emax = e
        imax = i
print(f"O maior elemento da lista é {emax} e ocorre no índice {imax}.")
O maior elemento da lista é 4567 e ocorre no índice 5.

Exercício 12

Escreva um programa que encontra o máximo e o mínimo de uma lista

In [40]:
L = [123,15, 12, 4352, 1, 4567]
emin = L[0]
emax = emin
for e in L:
    if e < emin:
        emin = e
    elif e > emax:
        emax = e
        
print(f"O menor elemento da lista é {emin}.")
print(f"O maior elemento da lista é {emax}.")
O menor elemento da lista é 1.
O maior elemento da lista é 4567.

Exercício 13

Modifique o programa anterior para que ordene a lista em modo decrescente

In [41]:
L = [9, 2, 4, 3, 8, 6]
N = len(L)
for i in range(N):
    trocou = False
    for k in range(N-i-1):
        if L[k] < L[k+1]: # Inverter a posição
            trocou = True
            tmp = L[k]
            L[k] = L[k+1]
            L[k+1] = tmp
    if not trocou:
        break

L
        
            
Out[41]:
[9, 8, 6, 4, 3, 2]

Exercício 14

O que acontece se você tentar usar o programa acima com uma lista de strings? Tente e brinque um pouquinho.

Por outro lado, o que acontece se misturarmos números e strings?

In [43]:
L = ["LIXO", "BOLA", "ZEBRA", "TELEFONE", "FACA", "PULGA"]
N = len(L)
for i in range(N):
    trocou = False
    for k in range(N-i-1):
        if L[k] < L[k+1]: # Inverter a posição
            trocou = True
            tmp = L[k]
            L[k] = L[k+1]
            L[k+1] = tmp
    if not trocou:
        break

L
        
Out[43]:
['ZEBRA', 'TELEFONE', 'PULGA', 'LIXO', 'FACA', 'BOLA']
In [44]:
L = ["LIXO", 3, "ZEBRA", "TELEFONE", "FACA", "PULGA"]
N = len(L)
for i in range(N):
    trocou = False
    for k in range(N-i-1):
        if L[k] < L[k+1]: # Inverter a posição
            trocou = True
            tmp = L[k]
            L[k] = L[k+1]
            L[k+1] = tmp
    if not trocou:
        break

L
        
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/tmp/ipykernel_3519/3902378855.py in <module>
      4     trocou = False
      5     for k in range(N-i-1):
----> 6         if L[k] < L[k+1]: # Inverter a posição
      7             trocou = True
      8             tmp = L[k]

TypeError: '<' not supported between instances of 'str' and 'int'

Exercício 15

Um aspecto importante é saber p quão eficiente é este algorítimo. Para tanto, precisamos saber quanto tempo leva para ordenar a lista.

Mas isso vai depender do tamanho da lista, do tipo de dados dentro da lista e do computador que está executando o programa. No entanto, para efeito comparativo, podemos estimar o número de operações. Neste caso, podemos falar em quantas comparações foram realizadas (A linha L[k] > L[k+1]). Também é interessante saber quantas inversões foram realizadas. Estime esse custo para os dois seguintes casos:

  1. Uma lista ordenada de maneira crescente de comprimento N
  2. Uma lista ordenada de maneira decrescente de comprimento N
In [55]:
#L = [9, 2, 4, 3, 8, 6]
#L = list(range(18))
L = list(range(18))[::-1]
N = len(L)
ntroca = 0
ncomp = 0
for i in range(N):
    trocou = False
    for k in range(N-i-1):
        ncomp += 1
        if L[k] > L[k+1]: # Inverter a posição
            ntroca += 1
            trocou = True
            tmp = L[k]
            L[k] = L[k+1]
            L[k+1] = tmp
    if not trocou:
        break

N, ncomp, ntroca
        
            
Out[55]:
(18, 153, 153)
Lista Compr. Núm comparações Núm trocas
Original 6 12 7
Crescente 6 5 0
Crescente 12 11 0
Crescente 18 17 0
Decrescente 6 15 15
Decrescente 12 66 66
Decrescente 18 153 153

Assim, para uma lista ordenada de N elementos, o algorítimo fará N-1 comparações e nenhuma troca. O custo é linear: $\mathcal{O}(N)$

Por outro lado se a lista estiver ordenada em ordem contrária, o custo aumenta rapidamente segundo esta equação:

$$ N = \frac{N\times(N-1)}{2} $$

Isso é um custo de ordem $\mathcal{O}(N^2)$. Dobrou o tamanho da lista, quadruplicou o custo! Este não é um algorítimo muito bom...

Exercício 16

Explore os métodos das listas

Não tem solução...

Exercício 17

Não são apenas as listas que têm métodos. Números e strings também têm métodos. Explore-os da mesma maneira que você fez com os métodos das listas.

Não tem solução

Comentários

Comments powered by Disqus