#!/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 3. Estruturas Condicionais
# ##### Instrutor: Pedro C. de Siracusa
# Condicionais são estruturas de decisão fundamentais nas linguagens de programação que permitem que um programa altere seu comportamento em tempo de execução, dependendo do estado em que se encontra.
# Podemos imaginar um programa em execução como um trem viajando sobre um trilho. Algumas bifurcações podem existir ao longo do percurso, e o caminho tomado pelo trem nestes pontos deve ser selecionado através de manivelas de controle. Dependendo da posição em que se encontra a manivela, o trem pode tomar um ou outro caminho, mas nunca seguir nos dois ao mesmo tempo.
#
#
# Estruturas condicionais permitem alterar o fluxo de execução de um programa através da verificação de **condições**, que podem ser codificadas em nosso programa por meio de **expressões lógicas**.
# ### Objetivos.
#
# Após esta aula você deverá ser capaz de:
# * Reconhecer os principais **operadores lógicos** e de **comparação**;
# * Construir e computar **expressões lógicas**;
# * Construir **estruturas condicionais**.
# ## 1. Expressões lógicas
# Expressões lógicas são aquelas cuja avaliação resulta em valores do tipo **booleano**: verdadeiro (**True**) ou falso (**False**).
# Os dois principais tipos de operadores para construir expressões lógicas são:
# * **operadores de comparação**: permitem comparar os valores de um par de objetos, e retornam `True` caso sejam equivalentes e `False` caso contrário;
# * **operadores lógicos**: úteis para combinar resultados booleanos obtidos de várias comparações, permitindo construir estruturas de decisão mais complexas.
# | Operador | Descrição |
# | -------- | --------- |
# | **Operadores de comparação** | |
# | `==` | `True` se valores de dois operandos são iguais |
# | `!=` | `True` se valores de dois operandos são diferentes |
# | `<` | `True` se valor do operando à esquerda é menor que o da direita |
# | `<=` | `True` se valor do operando à esquerda é menor ou igual ao da direita|
# | `>` | `True` se valor do operando à esquerda é maior que o da direita |
# | `>=` | `True` se valor do operando à esquerda é maior ou igual ao da direita |
# | **Operadores lógicos**| |
# | `and` | Operador lógico "E" |
# | `or` | Operador lógico "OU" |
# | `not` |Operador lógico "NÃO" |
# Vamos escrever algumas expressões lógicas.
# ##### Operações de comparação
# In[1]:
# A expressão 5=5 é válida?
5==5
# In[2]:
# A expressão 5=3 é válida?
5==3
# In[3]:
# 5 é diferente de 7?
5 != 7
# In[4]:
# 5 é maior ou igual a 5?
5 >= 5
# In[5]:
# 7 é menor que 10?
7 < 10
# ##### Operações lógicas
# In[6]:
p = True
q = True
print("P and Q:", p and q )
print("P or Q:", p or q )
print("not P:", not p )
print("not Q:", not q)
# In[7]:
p = True
q = False
print("P and Q:", p and q )
print("P or Q:", p or q )
print("not P:", not p )
print("not Q:", not q)
# In[8]:
p = False
q = True
print("P and Q:", p and q )
print("P or Q:", p or q )
print("not P:", not p )
print("not Q:", not q)
# In[9]:
p = False
q = False
print("P and Q:", p and q )
print("P or Q:", p or q )
print("not P:", not p )
print("not Q:", not q)
# In[10]:
True and not False and True
# In[11]:
True or False and True
# ##### Operações lógicas envolvendo comparação
# In[12]:
# False and True -> False
(4 > 5) and (3==3)
# In[13]:
# True or False -> True
(4 > 5) or (3==3)
# In[14]:
# not(True or False) -> False
not( 4>5 or 3==3 )
# In[15]:
# True and True and False -> False
4<5 and 3==3 and 5>5
# In[16]:
# True or True or False -> True
4<5 or 3==3 or 5>5
# Agora que já sabemos codificar **condições**, podemos de fato construir estruturas condicionais.
# ## 2. Construindo Condicionais
# Estruturas condicionais podem ter diferentes níveis de complexidade, dependendo do conjunto de condições
# ### A construção `if`
# A construção `if` é a estrutura mais simples de escrevermos um bloco de código $A$ que somente deve ser executado caso uma determinada condição **seja satisfeita** (ou seja, avaliada como `True`). Caso contrário, o código $A$ é simplesmente ignorado.
#
# In[17]:
cond = False
print("Antes de chegar na estrutura condicional (sempre executa)")
if cond:
print("Executo código A")
print("Depois da estrutura condicional (sempre executa)")
# ### A construção `if` `else`
# Um `if` pode ser associado a um `else`, contendo um bloco de código que é executado casa a condição do `if` **não seja satisfeita** (ou seja, avaliada como `False`).
#
#
# In[18]:
cond = False
print("Antes de chegar na estrutura condicional (sempre executa)")
if cond:
print("Executo código A")
else:
print("Executo código B")
print("Depois da estrutura condicional (sempre executa)")
# As duas construções tratadas acima se baseiam na verificação de apenas uma condição, que dependendo de como for avaliada (`True` ou `False`), desencadeia um dentre dois possíveis comportamentos.
# Mas e se desejarmos construir uma estrutura condicional que permita **mais do que apenas dois "caminhos" diferentes**?
# Neste caso precisamos verificar mais do que uma única condição.
# ### Condicionais aninhadas
# A primeira forma de incluir mais mais do que uma condição a ser testada na estrutura condicional é por **aninhamento**. Como resultado, teremos uma estrutura hierárquica, em que a execução de uma segunda condição depende do resultado de uma primeira condição.
# Não há limites para o número de níveis hierárquicos em uma estrutura condicional, apesar de que muitos níveis hierárquicos podem tornar o código mais difícil de entender.
#
# **Cuidado!** Em *Python* é fundamental respeitar o nível de indentação dos blocos de código em cada nível hierárquico!
#
# In[19]:
cond1 = False
cond2 = False
print("Antes de chegar na estrutura condicional (sempre executa)")
if cond1:
print("Executo código A. Não importa a cond2")
else:
if cond2:
print("Executo código B. A cond1 foi False")
else:
print("Executo código C. A cond1 foi False")
print("Depois da estrutura condicional (sempre executa)")
# ### A construção `if` `elif` `else`
# Uma sequência de vários `if` e `else` aninhados pode inserir muitos níveis de indentação no código, tornando-o confuso. Para evitar este problema, usamos a construção podemos inserir novas condições a serem verificadas usando a palavra `elif`. Pense no `elif` como uma fusão entre um `else` e um `if`. O `else` no final captura qualquer caso em que nenhuma das condições anteriores foram satisfeitas.
# In[20]:
cond1 = False
cond2 = False
print("Antes de chegar na estrutura condicional (sempre executa)")
if cond1:
print("Executo código A. Não importa a cond2")
elif cond2:
print("Executo código B. A cond1 foi False")
else:
print("Executo código C. A cond1 foi False")
print("Depois da estrutura condicional (sempre executa)")
# ---
# ## Exercícios
# **Ex 1.** Verifique se as igualdades abaixo são verdadeiras:
# **(a)** $2 \times 2.0 = 4$
# In[21]:
2*2.0==4
# **(b)** $2 \times 3 = 5$
# In[22]:
2*3==5
# **(c)** $4a + 3 = b$, para $a=3$ e $b=15$ (primeiro declare as variáveis `a` e `b`)
# In[23]:
a=3
b=15
4*a+3 == b
# **Ex 2.** Complete o código na célula abaixo para imprimir uma mensagem informando se um aluno foi aprovado ou reprovado em uma disciplina com base em sua nota final. A nota mínima necessária para aprovação é $5$.
# In[24]:
notaAluno = 5 # insira aqui a nota do aluno
if notaAluno >= 5:
print("Aprovado! =]")
else:
print("Reprovado =(")
# **Ex 3.** Construa uma função que calcule a média final e menção dos alunos com base nas notas das três provas (com pesos de 20% para as duas primeiras e 60% para a terceira). Divida o problema em duas etapas. Primeiro, você deverá calcular a média das provas com os devidos pesos. Depois, atribuir a menção conforme a seguinte regra:
#
# $
# se \quad média \ final \geq 9 : menção = SS \\
# se \quad 7 \leq média \ final < 9 : menção = MS \\
# se \quad 5 \leq média \ final < 7 : menção = MM \\
# se \quad 3 \leq média \ final < 5 : menção = MI \\
# se \quad média \ final < 3 : menção = II \\
# $
# In[25]:
def calculaMedia(p1,p2,p3):
return p1*0.2 + p2*0.2 + p3*0.6
def calculaMencao( p1,p2,p3 ):
media = calculaMedia(p1,p2,p3)
print("Média foi",media)
if media >= 9:
return "SS"
elif media >= 7:
return "MS"
elif media >= 5:
return "MM"
elif media >= 3:
return "MI"
else:
return "II"
# In[26]:
calculaMencao(3,2,3)
# In[27]:
calculaMencao(3,3,4)
# In[28]:
calculaMencao(3,3,7)
# In[29]:
calculaMencao(7,8,10)
# **Ex 4.** Construa uma pequena **chave dicotômica** para identificar uma determinada planta como membro de um dos principais grupos: *Bryophyta*, *Pteridophyta*, *Gymnospermae* ou *Angiospermae*.
# A identificação se dá com base na presença (1) ou ausência (0) de três caracteres: **vascularização**, **sementes** e **flores**.
# Utilize a tabela abaixo como referência.
# | Grupo | Vascularização| Sementes| Flores |
# |--|--|--|--|
# | Bryophyta | 0 | 0 | 0 |
# | Pteridophyta | 1| 0 | 0 |
# | Gymnospermae | 1 | 1 | 0 |
# | Angiospermae | 1 | 1 | 1 |
#
# In[30]:
# Estas variáveis armazenam a presença (1) ou ausência (0) de cada caractere
vasc = 1
sem = 1
flor = 0
if vasc==0 and sem==0 and flor==0:
print("Bryophyta")
elif vasc==1 and sem==0 and flor==0:
print("Pteridophyta")
elif vasc==1 and sem==1 and flor==0:
print("Gymnospermae")
elif vasc==1 and sem==1 and flor==1:
print("Angiospermae")
else:
print("Não há plantas com estas características")
# **Ex 5.** Encapsule o código que você construiu no exercício anterior. Para isso, construa uma função de nome `chave`, que recebe como argumentos cada um dos caracteres e retorna o nome do devido grupo botânico.
# In[31]:
def chave(vasc, sem, flor):
if vasc==0 and sem==0 and flor==0:
return "Bryophyta"
elif vasc==1 and sem==0 and flor==0:
return "Pteridophyta"
elif vasc==1 and sem==1 and flor==0:
return "Gymnospermae"
elif vasc==1 and sem==1 and flor==1:
return "Angiospermae"
else:
print("Não há plantas com estas características")
return
return
# In[32]:
chave(vasc=0, sem=0, flor=0)
# In[33]:
chave(vasc=1, sem=0, flor=0)
# In[34]:
chave(vasc=1, sem=1, flor=0)
# In[35]:
chave(vasc=1, sem=1, flor=1)
# In[36]:
chave(vasc=0, sem=1, flor=0)