#!/usr/bin/env python
# coding: utf-8
# ##
Introdução à Lógica de Programação
# ### Um curso prático para estudantes das Ciências da Vida
# ---
# ## Aula 5. Estruturas de Repetição
# ##### Instrutor: Pedro C. de Siracusa
# Computadores são muito eficientes em realizar tarefas bem definidas e repetitivas. E muito menos suscetíveis a cometer erros de cálculo do que nós humanos.
# Nesta aula vamos aprender a inserir **automação** em nossos programas utilizando **estruturas de repetição**.
# **Loops** (em português "laços de repetição") são estruturas que garantem que uma parte do código seja repetida várias vezes. Existem dois tipos fundamentais de loops: (i) ***for* loops** e (ii) ***while* loops**. Por simplicidade, veremos apenas o primeiro tipo neste curso.
# ### Objetivos.
#
# Após esta aula você deverá ser capaz de:
# * Escrever trechos de código repetitivos usando estruturas de repetição;
# * Compreender o conceito de iteração;
# * Reconhecer casos de uso de variáveis de iteração e variáveis contadoras;
# * Percorrer programaticamente elementos em listas.
# ## 1. Loops e Iterações
# No jargão da computação, chamamos de **loop** uma estrutura contendo código que será executado múltiplas vezes. Cada repetição do loop é chamada **iteração**.
#
# A estrutura de um loop do tipo "**for**" é composta por:
#
# * uma **variável de iteração** (normalmente chamada `i` ou `j`, mas poderia ser qualquer outro nome, como por exemplo `dinossauro`);
# * uma **lista** com os elementos que desejamos percorrer.
#
# Para exemplificar, vamos construir uma estrutura que imprima no console a frase "nova iteração" algumas vezes.
#
# In[1]:
print("Antes do loop...")
for i in range(10):
print("Nova iteração")
print("Depois do loop")
# Uma característica da variável de iteração é que ela, a cada iteração, assumirá o valor seguinte na lista percorrida. Podemos então imprimir no console o número de cada nova iteração.
# In[2]:
print("Antes do loop...")
for i in range(10):
print("Iteração",i)
print("Depois do loop")
# Podemos também percorrer listas com elementos não-numéricos por meio de loops.
# In[3]:
minhaLista = ["Olá", "Dinossauro", True, False, ["a", "b", "c"], 42.5 ]
for el in minhaLista: # neste caso a variável `el` é a variável de iteração
print("Nova iteração: elemento", el)
# **Variáveis contadoras** (normalmente chamadas `ctr`) podem ser usadas para armazenar resultados de forma gradativa durante as iterações. Elas são usualmente inicializadas com valor zero e, a cada iteração, são atualizadas (normalmente somando-se 1).
# Usando variáveis contadoras podemos, por exemplo, calcular a soma de números em uma lista.
# In[4]:
minhaLista = [ 1,2,3,4,5,6,7,8,9,10 ]
ctr = 0
print("Antes do loop")
print("Valor inicial de ctr:", ctr)
print("")
for i in minhaLista:
print("Dentro do loop: nova iteração")
print("Valor anterior de ctr:",ctr)
print("Somando", i)
ctr = ctr + i # é assim que atualizamos o valor de uma variável usando como base seu valor antigo
print("Novo valor de ctr:",ctr)
print("")
print("Fora do loop")
print("Valor final de ctr:", ctr)
# Podemos também usar loops para percorrer strings, como se fossem uma lista de caracteres.
# In[5]:
meuNome = "Luke Skywalker"
for caractere in meuNome: # neste caso a variável `caractere` é a variável de iteração
print("Nova iteração: caractere", caractere)
# ---
# ## Exercícios.
# **Ex 1.** Escreva a função `conta_sup` que recebe: uma lista `l` contendo valores numéricos; e um número `limite`. A função deve contar quantos elementos na lista `l` têm valor maior ou igual a `limite`.
# In[6]:
def conta_sup(l, limite):
ctr=0
for i in l:
if i >= limite:
ctr = ctr + 1
return ctr
# In[7]:
minhaLista = [42, 52,6,30,42,68,28,48,2,100,29,172,0,-1,-50]
# Existem 2 elementos com valor maior ou igual a 100 na lista
conta_sup(minhaLista, 100)
# **Ex 2.** Escreva a função `busca_max` que recebe uma lista `l` contendo valores numéricos e retorna o valor máximo encontrado nela. O comportamento dessa função é equivalente ao da função `max`. No entanto, não use a função `max` neste exercício.
# In[8]:
def busca_max(l):
elem_max = l[0] # a princípio assumiremos que o primeiro elemento da lista é o máximo
# agora no loop vamos atualizar o valor em `elem_max` sempre que encontrarmos algum com valor maior
for el in l:
if el > elem_max:
elem_max = el
return elem_max
# In[9]:
minhaLista = [42, 52,6,30,42,68,28,48,2,100,29,172,0,-1,-50]
# O elemento de valor máximo na lista é o 172
busca_max(minhaLista)
# **Ex 3.** Escreva uma função `busca_primeiro_sup` que recebe: uma lista `l` contendo valores numéricos; e um número `limite`. A função deve retornar imediatamente assim que encontrar um elemento na lista `l` com valor maior que `limite`. Caso encontre um valor maior que o limtie, este valor deve ser retornado como resultado. Caso contrário, a função deve retornar uma string `"Não encontrado"`.
# In[10]:
def busca_primeiro_sup(l, limite):
for el in l:
if el > limite:
return el
return "Não encontrado"
# In[11]:
minhaLista = [42, 52,6,30,42,68,28,48,2,100,29,172,0,-1,-50]
# In[12]:
busca_primeiro_sup(minhaLista, 100)
# In[13]:
busca_primeiro_sup(minhaLista,200)
# **Ex 4.** Escreva uma função `complementaBases` que recebe como input uma sequência de bases de um fragmento de DNA e retorna as bases complementares.
# In[14]:
def complementaBases(dna):
complemento = ""
for base in dna:
if base=="A":
complemento = complemento + "T"
elif base=="T":
complemento = complemento + "A"
elif base=="G":
complemento = complemento + "C"
elif base=="C":
complemento = complemento + "G"
return complemento
# In[15]:
complementaBases("GATTACA")