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.

fluxograma_encontrar_carta.png

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:

  1. Seja \(r\) o resto da divisão de \(m\) por \(n\).
  2. Se \(r = 0\), o algoritmo termina, \(n\) é a resposta.
  3. 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)
  1. O código deve imprimir todos os números inteiros no intervalo \([10, 20)\).
  2. O código deve imprimir todos os números inteiros no intervalo \([10, 20]\).
  3. O código deve imprimir todos os números pares no intervalo \([10, 20]\).
  4. O código deve imprimir os números \(10, 9, 8, \ldots, 0\), nessa ordem.
  5. O código deve imprimir os números \(-10, -9, -8, \ldots, -5\), nessa ordem.
  6. O código deve imprimir os números \(-10, -11, -12, \ldots, -15\), nessa ordem.
  7. 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.

Author: Pedro Belin Castellucci

Created: 2024-03-18 seg 09:54

Validate