Estruturas de repetição
Table of Contents
1. Introdução
Considere o problema encontrar o maior valor inteiro entre três fornecidos pelo usuário. Uma possível implementação é a seguinte:
maior = int(input("Digite um valor: ")) aux = int(input("Digite um valor: ")) if aux > maior: maior = aux aux = int(input("Digite um valor: ")) if aux > maior: maior = aux print(f"Maior = {maior}")
(Outras implementações são possíveis, utilizando, por exemplo, a
função max do Python).
Mas imagine que o usuário deseja digitar 10 valores, ou trata-se de uma lista com milhares, talvez milhões de valores. Simplesmente repetir a mesma estrutura por 10, milhares ou milhões de vezes não é parece muito divertido.
De fato, para esse tipo de situação podemos utilizar laços de repetição. Uma estrutura que permite a repetição da mesma sequência de passos (possivelmente com valores diferentes) até que uma determinada condição seja atingida.
Em termos gráficos, o fluxograma reprenta um algoritmo que utiliza um laço de repetição.
Em Python, há duas formas de implementar um laço de repetição, laços
do tipo while e laços do tipo for. Discutidas na sequência.
2. Laço do tipo while
Considere o algoritmo de Euclides para encontrar o máximo divisor comum. Dados dois inteiros \(n\) e \(m\), \(m > n\), encontre o máximo divisor comum entre ambos da seguinte forma:
- Seja \(r\) o resto da divisão de \(m\) por \(n\).
- Se \(r = 0\), o algoritmo termina, \(n\) é a resposta.
- Senão atualize \(m \leftarrow n\) e \(n \leftarrow r\) e volte ao passo 1.
Construa um fluxograma que representa o algoritmo de Euclides.
Em termos de pseudocódigo, podemos escrever o seguinte
leia (m, n) r <- m % n enquanto r != 0 faça m = n n = r r = m % n imprima (n)
Note que o laço enquanto avalia uma condição booleana (True ou
False). Caso a condição seja avaliada como verdadeira (True),
então os comandos dentro do bloco while são executados. Após o
comando r = m % n, reavalia-se a condição r!=0, caso ela seja
verdadeira, repete-se os comandos do laço, caso contrário, o programa
segue a partir do fim do laço (o comando imprima(n) neste
caso). Cada repetição dos comandos do laço é chamada de iteração.
Em algoritmos iterativos, ao final de cada iteração é importante verificar o que deve ser feito para que a iteração seguinte inicie corretamente.
Para os valores \(m = 544\) e \(n = 119\), monte uma tabela com os valores de \(m\), \(n\) e \(r\) para cada iteração do laço.
2.1. Laço do tipo while em Python
Em Python, o laço while tem a seguinte estrutura sintática.
while cond:
instrucoes
O campo cond é uma expressão avaliada como True ou False. O
algoritmo de Euclides apresentado anteriormente pode ser implementado
da seguinte for em Python.
m = int(input("Digite m: ")) n = int(input("Digite n: ")) r = m % n while r != 0: m = n n = r r = m % n print("mdc = ", n)
Modifique o algoritmo anterior para garantir o seu funcionamento seja correto caso \(m < n\).
2.1.1. Alguns exemplos
Considere que se deseja fazer um programa que lê números do usuário até que seja fornecido um número negativo. O programa deve imprimir o número de valores positivos fornecidos. Uma possibilidade de implementação é a seguinte.
value = int(input("Digite um valor: ")) count = 0 while value > 0: count = count + 1 # Contador value = int(input("Digite um valor: ")) print(f"Positivos = {count}")
Monte uma tabela para acompanhar o valor das variáveis count e
value ao longo das iterações.
Considere que se deseja fazer um programa que calcula \(S = 1 + 2 + \ldots + n\), com \(n\) fornecido pelo usuário. Um programa que realiza todas as somas é dado a seguir.
n = int(input("Digite n: ")) acc = 0 # Inicia com o valor nulo da soma i = 0 # Conta os elementos somados ate' o momento while i <= n: acc = acc + i i = i + 1 print(f"S = {acc}")
Monte uma tabela com o valor das variáveis i e acc ao longo das
iterações do algoritmo. Note o significado delas em relação a soma pedida.
Para o mesmo problema, pode-se observar a propriedade comutativa da adição e alterar o código para o seguinte.
n = int(input("Digite n: ")) acc = 0 # Inicia com o valor nulo da soma while n > 0: acc = acc + n n = n - 1 print(f"S = {acc}")
Monte uma tabela com o valor das variáveis acc e n ao longo das
iterações do algoritmo. Note o significado delas em relação a soma pedida.
Considere que se deseja fazer um programa que lê números inteiros do usuário até que seja fornecido o caracter 'n'. O programa deve imprimir o maior valor fornecido. Uma possibilidade de implementação é a seguinte. Considere que pelo menos um valor numérico será fornecido.
largest = int(input("Digite um valor: ")) aux = largest while aux != 'n': aux = int(aux) if aux > largest: largest = aux aux = input("Digite um valor: ") print(f"Maior = {largest}")
Monte uma tabela com o valor das variáveis aux e largest ao longo das
iterações do algoritmo. Note o significado delas em relação a soma pedida.
3. Laço do tipo for
Laços do tipo for são uma alternativa aos laços do tipo while. São
particularmente úteis quando as iterações seguem um padrão "linear"
como, por exemplo, iterar sobre todos os valores de uma coleção, ou de
intervalo, um a um, ou dois a dois, ou três a três, etc.
Como exemplo considere o pseudocódigo a seguir, para imprimir todos os números inteiros no intervalo \([1, 10)\).
para i = 1, 2, ..., 9 faça imprime (i)
Em Python, um código equivalente seria o seguinte.
for i in range(10): print(i)
Note que foi utilizada a função range,
3.1. Range
A função range é utilizada para gerar sequências que seguem um
padrão de progressão aritmética. Em seu uso mais simples podemos
utilizar range(n) para gerar a sequência \((0, 1, \ldots, n-1)\). Mas
também é possível utilizá-la com dois ou três
argumentos. Resumidamente, tem-se:
range(n): gera a sequência \((0, 1, \ldots, n-1)\).range(start, end): gera a sequência \((start, start+1, \ldots, end-1)\).range(start, end, step): gera a sequência \((start, start+step, start + 2*step, \ldots, start + m*step)\), em que \(m\) é o maior valor tal que \(start + m*step < end\)
Altere a função range do script a seguir para atender cada um dos itens.
for i in range(10): print(i)
- O código deve imprimir todos os números inteiros no intervalo \([10, 20)\).
- O código deve imprimir todos os números inteiros no intervalo \([10, 20]\).
- O código deve imprimir todos os números pares no intervalo \([10, 20]\).
- O código deve imprimir os números \(10, 9, 8, \ldots, 0\), nessa ordem.
- O código deve imprimir os números \(-10, -9, -8, \ldots, -5\), nessa ordem.
- O código deve imprimir os números \(-10, -11, -12, \ldots, -15\), nessa ordem.
- O código não deve imprimir nada.
Como exemplo, considere que se deseja calcular a soma de todos os números no intervalo \([10, 20]\).
total = 10 for i in range(10, 21): total = total + i print(f"Total = {total}")
Para calcular a soma de todos os números pares, há pelo menos duas
alternativas. A primeira, e mais elegante (em Python) é alterar a
chamada da função range para iterar apenas sobre os números pares.
total = 0 for i in range(10, 21, 2): total = total + i print(f"Total = {total}")
A segunda é utilizar uma estrutura condicional para checar a paridade dos números.
total = 0 for i in range(10, 21): if (i % 2 == 0): total = total + i print(f"Total = {total}")
Laços do tipo for também são bastante convenientes para iterar em
cada elemento de listas e strings.
4. Referências e outros materiais
- Knuth, Donald E. The Art of Computer Programming: Fundamental Algorithms, volume 1. Addison-Wesley Professional, 1997.