Lógica¶
Objetivos de aprendizagem¶
Explicar a diferença entre níveis abstrato, lógico-filosófico e lógico-matemático da lógica, bem como identificar proposições e operadores lógicos básicos;
Construir tabelas-verdade usando Python para expressões proposicionais simples e compostas.
Analisar a interpretação lógica de expressões em Python, distinguindo entre valores booleanos, truthiness, _short-circuiting_ e o comportamento semântico dos operadores;
Desenvolver pequenos exemplos aplicados que combinem conceitos de lógica matemática e implementação em Python, criando mini-experimentos que relacionem representação formal, interpretação computacional e comportamento lógico.
Lógica, em sentido amplo, é a disciplina que dá subsídios para o raciocínio correto e para a análise de argumentações. Indispensável para o exercício filosófico, para a formação de leis, para a retórica de alto nível e para julgar fatos do cotidiano, a lógica também se insere na matemática e na computação fornecendo um arcabouço fundamental para interpretar sentenças, criar algoritmos e resolver diversos problemas. A este arcabouço daremos o nome de lógica matemática.
Organização conceitual¶
Para melhor compreender conceitos e aplicações da lógica à computação, é razoável organizar conceitos em níveis. Embora alguns conceitos sejam dispensáveis, vale a pena reconhecê-los. Consideraremos quatro níveis:
Lógico-matemático
Lógico-filosófico
Abstrato
O primeiro nível representa a camada mais específica e útil para nossos interesses. Porém, faremos nossa exposição em ordem inversa, começando pelo nível mais geral, pois a experiência antecede o formalismo.
Nível abstrato¶
No nível abstrato ocorre a ponte de ligação entre o mundo observado (natureza) e a abstração. Neste nível é onde se começa a buscar compreensão sobre os fenômenos. Conceitos básicos deste nível são:
Realidade: tudo o que nos cerca no mundo natural observável. Ex.: rebanho de ovelhas campestres; carros quem competem nos circuito da Stock Car brasileira; orquídeas de jardins suspensos;
Observação: exercício empírico que analisa a realidade;
Evidência: informação que confirma ou refuta uma asserção.
Fato: um estado de coisas ou situação ocorrida que pode ser provada e condizente com a realidade observada. Mas, sob o ponto de vista matemático, fato é uma sentença sempre verdadeira.
Modelo: representação de um fenômeno observável empiricamente;
Nível lógico-filosófico¶
No nível lógico-filosófico ocorre o exercício da razão, o surgimento das indagações a expressão das ideias e a estruturação do pensamento. Conceitos relevantes deste nível são:
Sentença (ou declaração): um enunciado linguístico completo. Na prática, seu significado pode se desdobrar em proposição, asserção, julgamento, hipótese, princípio, tese ou ainda, lei. Para nossos interesses, uma sentença equivalerá a uma proposição, conforme definição a seguir.
Proposição: uma sentença que pode ser verdadeira ou falsa, mas não ambas as coisas.
Asserção: uma proposição admitida como verdadeira e que, geralmente, requer algum julgamento sobre seu valor-verdade.
Valor-verdade: uma das duas condições:
verdadeirooufalso.Hipótese: uma proposição que é assumida (candidata) com verdadeira.
Tese: uma conclusão argumentada.
Argumento: uma sequência logicamente estruturada de proposições que conduzem a uma conclusão.
Nível lógico-matemático¶
No nível lógico-matemático ocorre o formalismo e a imposição de restrições “fortes” ao uso dos termos. Conceitos propagados neste nível são:
Premissa: proposição básica aceita como ponto de partida para um argumento.
Axioma: premissa fundacional sobre um modelo, não demonstrada, admitida como verdadeira e básica para estruturação de um sistema formal.
Sistema (formal): uma estrutura constituída por símbolos, axiomas, regras de formação e regras de inferência.
Teoria: um sistema formal acrescido de teoremas que tentam descrever um modelo.
Teorema: proposição provada a partir de axiomas e regras de inferência.
Corolário: conclusão imediata de um teorema que não exige demonstrações adicionais.
Lema: teorema auxiliar usado para provar outro teorema.
Prova (ou demonstração): argumento rigoroso que mostra que uma proposição é verdadeira.
Regra de inferência: regras que transformam proposições em outras. Em computação, são mecanismos de prova.
Dedução: sequência de inferências que produz uma conclusão. Em geral, o raciocínio dedutivo é aquele que extrai conclusões sobre fenômenos ou comportamentos a partir de argumentos.
Indução: matematicamente, é o processo que obtém conclusões para casos infinitos a partir de um esquema finito. Em sentido mais amplo, o raciocínio indutivo é o que permite tirar conclusões a partir de fatos (não matemáticos) ou observações.
Consistência: é a propriedade de um sistema formal que garante que nenhuma proposição poderá ter mais de um valor-verdade. Ou seja, é a garantia da inexistência de provas que concluem que uma proposição é simultaneamente verdadeira e falsa.
Lógica proposicional¶
A lógica (ou cálculo) proposicional é a forma mais básica da lógica matemática. Nela, a proposição é o elemento básico. A lógica proposicional difere da lógica de predicados – assunto que veremos posteriormente – no fato de que uma proposição não admite variáveis. Isto significa que seu valor é sempre verdadeiro ou falso de maneira objetiva. Em outras palavras, não haverá a possibilidade de uma proposição ter seu valor-verdade alterado em função de alguma variável.
Por exemplo, as sentenças abaixo são proposições:
2 + 3 = 5 (sempre verdadeira);
0 - 2 = -3 (sempre falsa);
Por outro lado, as sentenças abaixo não são proposições:
Está chovendo agora? (determinação de valor-verdade não objetiva);
+ 2 = 4 (pode ser verdadeira ou falsa dependendo do valor de );
(sempre verdadeira, mas não é proposição por depender do valor de );
(sempre falsa, mas não é proposição por causa da variável);
Representação de proposições¶
Considere a seguinte declaração:
“Adenor Gonçalves ataca como pivô pelo Jeribó desde 2017 e rompeu o tendão patelar no último jogo contra o Temperão. Tupanabiaca, um dos zagueiros do time adversário, foi o autor do sinistro.”
Seria possível decompor essa declaração em proposições de formas diversas sem perder o sentido. Por exemplo:
Adenor Gonçalves é o único atacante do Jeribó.
O zagueiro adversário Tupanabiaca cometeu falta sobre o atacante.
Adenor Gonçalves rompeu o tendão patelar.
Poderíamos levar isso ao computador como strings isoladas ou como uma lista de strings:
[
"Adenor Gonçalves é o único atacante do Jeribó.",
"O zagueiro adversário Tupanabiaca cometeu falta sobre Adenor.",
"Adenor Gonçalves rompeu o tendão patelar."
]['Adenor Gonçalves é o único atacante do Jeribó.',
'O zagueiro adversário Tupanabiaca cometeu falta sobre Adenor.',
'Adenor Gonçalves rompeu o tendão patelar.']A dificuldade é que, para o computador, essas frases são apenas sequências longas de caracteres e difíceis de serem trabalhadas como proposições lógicas. A convenção matemática para denotar proposições é usar letras minúsculas puras, tais como , , etc., ou com subscritos, como .
Enquanto é razoável escrever (simplificando o contexto)
: Adenor é atacante.
: O zagueiro adversário cometeu falta em Adenor.
: Adenor rompeu o tendão patelar.
o argumento “ E IMPLICAM EM ”, escrito em símbolos matemáticos, seria representado como:
Seria ainda difícil operar com essas declarações, ainda que fizéssemos a seguinte representação dessas proposições:
p1 = "Adenor é atacante."
p2 = "O zagueiro adversário cometeu falta em Adenor."
p3 = "Adenor rompeu o tendão patelar."
print(p1, p2, p3, sep="\n")Adenor é atacante.
O zagueiro adversário cometeu falta em Adenor.
Adenor rompeu o tendão patelar.
Por quê? Em Python, como em muitas outras linguagens:
Não haverá um operador nativo para “implicação” ();
Não será possível trabalhar com as proposições da forma direta;
Vejamos:
Caso 1
p1 => p2 # retorna erro porque o operador "=>" não existe em Python File "/var/folders/ll/g0vl8b194pbfyp4cwpzz4p740000gn/T/ipykernel_18248/1993335092.py", line 1
p1 => p2 # retorna erro porque o operador "=>" não existe em Python
^
SyntaxError: invalid syntax
Caso 2
p1 and p2 # Uso do "and" como operador lógico não resulta no esperado'O zagueiro adversário cometeu falta em Adenor.'Mais tarde vamos entender os motivos desses problemas. O importante a entender neste capítulo é que a lógica proposicional nos dá subsídio para operar expressões lógicas gerais, as quais permeiam o cotidiano da programação. Para começar, vamos explorar tabelas-verdade e operadores lógicos.
Tabelas-verdade e operadores lógicos¶
Podemos criar a tabela-verdade de uma ou mais expressões proposicionais utilizando os operadores interpretáveis pelo módulo truth-table-generator. Os operadores possíveis de trabalho são os abaixo:
| operador | significado | representação |
|---|---|---|
| negação | not, ou -, ou ~ | |
| disjunção | or | |
| conjunção | and | |
| disjunção exclusiva | xor, ou != | |
| ou | implicação | =>, ou implies |
| ou | bicondicional | = |
| nand | nand | |
| nor | nor |
Obs.: Note que os operadores nand e nor decorrem das Leis de de Morgan. Isto será visto mais adiante no curso.
import ttg # importa o módulo truth-table-generator Considere que são proposições. A tabela-verdade de linhas e colunas dos valores possíveis pode ser impressa com o comando
print(ttg.Truths(['p1','p2',...,'pn']))onde cada proposição deve ser explicitamente escrita na lista como uma string.
# Exemplo com 2 proposições
print(ttg.Truths(['p1','p2']))+------+------+
| p1 | p2 |
|------+------|
| 1 | 1 |
| 1 | 0 |
| 0 | 1 |
| 0 | 0 |
+------+------+
Atente-se para os valores 0 e 1, que correspondem a True e False, respectivamente.
# Exemplo com 3 proposições
print(ttg.Truths(['p1','p2','p3']))+------+------+------+
| p1 | p2 | p3 |
|------+------+------|
| 1 | 1 | 1 |
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 1 |
| 0 | 1 | 0 |
| 0 | 0 | 1 |
| 0 | 0 | 0 |
+------+------+------+
# Exemplo com 4 proposições
print(ttg.Truths(['p1','p2','p3','p4']))+------+------+------+------+
| p1 | p2 | p3 | p4 |
|------+------+------+------|
| 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 0 |
| 1 | 1 | 0 | 1 |
| 1 | 1 | 0 | 0 |
| 1 | 0 | 1 | 1 |
| 1 | 0 | 1 | 0 |
| 1 | 0 | 0 | 1 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 1 | 1 |
| 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 |
| 0 | 1 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 0 | 0 | 1 | 0 |
| 0 | 0 | 0 | 1 |
| 0 | 0 | 0 | 0 |
+------+------+------+------+
Podemos usar qualquer string para as proposições.
print(ttg.Truths(['Marcos é estudioso','João é curioso']))+----------------------+------------------+
| Marcos é estudioso | João é curioso |
|----------------------+------------------|
| 1 | 1 |
| 1 | 0 |
| 0 | 1 |
| 0 | 0 |
+----------------------+------------------+
print(ttg.Truths(['p','q','r']))+-----+-----+-----+
| p | q | r |
|-----+-----+-----|
| 1 | 1 | 1 |
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 1 |
| 0 | 1 | 0 |
| 0 | 0 | 1 |
| 0 | 0 | 0 |
+-----+-----+-----+
Exemplo:
print(ttg.Truths(['p','q'],['p and q']))+-----+-----+-----------+
| p | q | p and q |
|-----+-----+-----------|
| 1 | 1 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 0 | 0 | 0 |
+-----+-----+-----------+
Exemplo:
print(ttg.Truths(['p','q'],['p or q']))+-----+-----+----------+
| p | q | p or q |
|-----+-----+----------|
| 1 | 1 | 1 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
+-----+-----+----------+
Exemplo:
print(ttg.Truths(['p','q','r'],['p and q and r']))+-----+-----+-----+-----------------+
| p | q | r | p and q and r |
|-----+-----+-----+-----------------|
| 1 | 1 | 1 | 1 |
| 1 | 1 | 0 | 0 |
| 1 | 0 | 1 | 0 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 0 | 0 | 0 | 0 |
+-----+-----+-----+-----------------+
Exemplo:
print(ttg.Truths(['p','q'],['p xor q']))+-----+-----+-----------+
| p | q | p xor q |
|-----+-----+-----------|
| 1 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 1 |
| 0 | 0 | 0 |
+-----+-----+-----------+
Exemplo:
print(ttg.Truths(['p','q','r'],['p nor q', 'p nor q and r']))+-----+-----+-----+-----------+-----------------+
| p | q | r | p nor q | p nor q and r |
|-----+-----+-----+-----------+-----------------|
| 1 | 1 | 1 | 0 | 0 |
| 1 | 1 | 0 | 0 | 0 |
| 1 | 0 | 1 | 0 | 0 |
| 1 | 0 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 | 0 |
| 0 | 1 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 1 |
| 0 | 0 | 0 | 1 | 0 |
+-----+-----+-----+-----------+-----------------+
Imprimindo True e False em vez de 0 e 1¶
Para imprimirmos os valores booleanos como palavras, devemos adicionar o argumento
ints=False na função geradora da tabela-verdade.
# Exemplo: p xor q
print(ttg.Truths(['p','q'],['p xor q'],ints=False))+-------+-------+-----------+
| p | q | p xor q |
|-------+-------+-----------|
| True | True | False |
| True | False | True |
| False | True | True |
| False | False | False |
+-------+-------+-----------+
# Exemplo: p xor q
print(ttg.Truths(['p','q','r'],['p nor q', 'p nor q and r'],ints=False))+-------+-------+-------+-----------+-----------------+
| p | q | r | p nor q | p nor q and r |
|-------+-------+-------+-----------+-----------------|
| True | True | True | False | False |
| True | True | False | False | False |
| True | False | True | False | False |
| True | False | False | False | False |
| False | True | True | False | False |
| False | True | False | False | False |
| False | False | True | True | True |
| False | False | False | True | False |
+-------+-------+-------+-----------+-----------------+
Imprimindo tabelas com visual “mais bonito”¶
Além da forma padrão vista anteriormente, podemos imprimir as tabelas usando
PrettyTable: renderiza a tabela reduzindo espaços em branco.Tabulate: renderiza a tabela adicionando a primeira coluna como uma indexaçãoPandas: renderiza a tabela usando o módulopandas
Com o formato padrão, temos:
tbl = ttg.Truths(['p', 'q'], ['p => q', 'p = q'])
print(tbl)+-----+-----+----------+---------+
| p | q | p => q | p = q |
|-----+-----+----------+---------|
| 1 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 0 | 0 | 1 | 1 |
+-----+-----+----------+---------+
PrettyTable¶
Note a redução da largura das colunas.
print(tbl.as_prettytable())+---+---+--------+-------+
| p | q | p => q | p = q |
+---+---+--------+-------+
| 1 | 1 | 1 | 1 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 1 | 0 |
| 0 | 0 | 1 | 1 |
+---+---+--------+-------+
Tabulate¶
Note a indexação na primeira coluna.
print(tbl.as_tabulate())+----+-----+-----+----------+---------+
| | p | q | p => q | p = q |
|----+-----+-----+----------+---------|
| 1 | 1 | 1 | 1 | 1 |
| 2 | 1 | 0 | 0 | 0 |
| 3 | 0 | 1 | 1 | 0 |
| 4 | 0 | 0 | 1 | 1 |
+----+-----+-----+----------+---------+
Pandas¶
Com pandas, a renderização fica sob encargo do notebook e não precisamos da função print. Esta talvez seja a forma melhor estilizada.
tbl.as_pandasPodemos estilizar a saída ainda mais aplicando propriedades. Por exemplo, para alinhar o texto e remover a coluna de indexação, podemos fazer:
tbl.as_pandas.style.set_properties(**{'text-align': 'center'}).hide()Interpretação¶
Interpretação é o processo de atribuir significado a símbolos de uma linguagem formal. Em nossos exemplos, serão proposições, conectivos e valores. A interpretação de proposições tem imagem binária (valor-verdade) e pode ser descrita matematicamente como
em que é uma fórmula (ou expressão computacional), é o valor-verdade True e , False e a função denominada interpretação.
A interpretação diz como ler ou como avaliar uma expressão, porque símbolos por si só não têm significado. Em Python, o valor-verdade é obtido através da interpretação de construções lógicas. Nos exemplos de tabela-verdade, vimos os resultados da interpretação.
Expressões atômicas¶
Vejamos exemplos de expressões que poassuem apenas uma avaliação lógica e interpretadas com os valores-verdade booleanos.
2 > 3False- 4 == 4False2/4 - 1/2 == 0True((2 * 5) + 3**3)/7 > - 2 Truefrom math import sqrt, exp
sqrt(16) - 3.2 > exp(1.2)/3FalseExpressões compostas¶
Quando combinanos duas ou mais proposições atômicas usando conectivos lógicos, obtemos uma proposição composta que será interpretada sequencialmente da esquerda para a direita.
Vejamos exemplos de expressões compostas:
(2 > 3) and (4 == 4)False(3 != 1) or (5 < 2)True# interpretação baseada em precedência dos operadores lógicos
True and 2 - 1 > 0 and 8 <= sqrt(16)False# avaliação diferente da anterior por causa dos agrupamentos com parênteses
(True and 2 - 1 > 0) or 8 <= sqrt(16) and 8 <= sqrt(16) TrueTruthiness¶
Truthiness – que poderíamos chamar de veracidade implícita – é a propriedade que um objeto tem de ser interpretado como verdadeiro ou falso, mesmo sem ser literalmente o booleando True ou False. Isto significa que todo objeto possui um “valor-verdade implícito” para quando a linguagem precisa decidir se algo é verdadeiro ou falso dentro de expressões lógicas.
Para compreender melhor o conceito de veracidade implícita, vamos combinar objetos truthy e falsey com expressões lógicas e estruturas de controle de fluxo (if, for e while).
# Números são sempre truthy. Logo, a avaliação
# lógica de 1 em um contexto condicional resulta em True.
if 1:
print("Entrei no bloco condicional.")Entrei no bloco condicional.
# Avaliação é False porque 1 é truthy, mas 0 é falsey.
if (1 and 0):
print("Entrei no bloco condicional.")# Conjunto não vazio é truthy. Logo, a avaliação
# lógica da condição é True.
if {1,2,3}:
print("Entrei no bloco condicional.")Entrei no bloco condicional.
A = {1,2,3,5}
B = {3,5}
if (3 in A) and (3 in B):
print("3 pertence a ambos os conjuntos.")
3 pertence a ambos os conjuntos.
if A > B:
print("A é subconjunto próprio de B.")A é subconjunto próprio de B.
if 2 in [1,2,3] and not []:
print("2 pertence à lista e a negação da lista vazia é truthy.")2 pertence à lista e a negação da lista vazia é truthy.
not {1}Falsen = 0
if n:
print("n é truthy.")
else:
print("n é falsey.")n é falsey.
while 1:
print("Loop infinito.")
breakLoop infinito.
while 0:
print("Isso nunca será impresso.")if -1:
print(",".join(str(x) for x in set(range(-4,3))))0,1,2,-1,-4,-3,-2
def bhaskara(a, b, c):
delta = b**2 - 4*a*c
if delta < 0:
return "Não existem raízes reais."
else:
x1 = (-b + sqrt(delta)) / (2*a)
x2 = (-b - sqrt(delta)) / (2*a)
return x1, x2
if bhaskara(-1,2,3)[0] > -2:
print("A primeira raiz é maior que -2.")A primeira raiz é maior que -2.
bool(0), bool(1), bool(0.0), bool(-5)(False, True, False, True)bool(None), bool([]), bool(set()), bool(tuple()), bool(range(0))(False, False, False, False, False)bool({5, 5}), bool([1,2,3]), bool({"a":0,"b":1})(True, True, True)Retornando aos problemas iniciais¶
Vamos discutir os dois casos simultaneamente, pois eles estão intimamente relacionados.
Como Python não possui um operador lógico de implicação, devemos usar a expressão lógica equivalente. Uma vez que
podemos testar implicações usando essa identidade:
nao_equiv_p_to_q = ttg.Truths(['p','q'],['p implies q', 'not p or q'],ints=False)
print(nao_equiv_p_to_q)+-------+-------+---------------+--------------+
| p | q | p implies q | not p or q |
|-------+-------+---------------+--------------|
| True | True | True | True |
| True | False | False | False |
| False | True | True | True |
| False | False | True | True |
+-------+-------+---------------+--------------+
Portanto, seria possível substituir a implicação original por uma construção alternativa.
not p1 or p2'O zagueiro adversário cometeu falta em Adenor.'Porém, esta não é a conclusão esperada do argumento. Por quê? Porque p1 e p2 apenas armazenam strings (cadeias de caracteres) e não proposições no sentido lógico absoluto. Elas representam nossa “intenção” de contexto, mas os conectivos lógicos testam a verdade implícita sem qualquer capacidade de julgamento por inferência ou contexto.
De igual forma a construção abaixo gera uma resposta isenta de contexto.
p1 and p2'O zagueiro adversário cometeu falta em Adenor.'Tendo em vista a noção de truthiness, o que acontece nesses casos é:
p1ep2são strings não vazias e comportam-se como truthy;not p1nega algo truthy e torna-se falsey:not p1 or p2é uma disjunção de valores-verdadeFalseeTrue, que equivale aFalse or p2. Portanto,p2é a resposta por serTrue.p1 and p2é uma conjunção de valores-verdadeTrueeTrue, que equivale aTrue and True. Neste caso,p2é a resposta final porqueand, como operador lógico não retorna valores booleanos mas considera um short-circuit.
Short-circuiting¶
Short-circuiting é a estratégia de um operador lógico parar a avaliação cedo, assim que já sabe o resultado final, sem precisar avaliar o restante da expressão para economizar computação e escapar avaliações desnecessárias. Abaixo temos uma tabela de short-circuiting segundo a semântica de Python para os dois operadores lógicos que usam essa abordagem: and e or.
| Operador | Primeiro operando | Avalia o segundo? | Resultado retornado |
|---|---|---|---|
and | falsey | Não | Primeiro operando |
and | truthy | Sim | Segundo operando |
or | truthy | Não | Primeiro operando |
or | falsey | Sim | Segundo operando |
O short-circuiting é útil em várias situações. Exemplos:
# Primeira condição False impede o
# cálculo dos números grandes posteriores
(1 > 6) and 1e215 > 29**101 False# Divisão por zero escapada
25 > 12.3 or 1/0True# Se o nome do usuário for None, usa 'Anonymous'
# Se o endereço do usuário for desconhecido, usa 'N/A'
user = {"name": "Elsie",
"CPF": 22222211199,
"address": ""}
user_name = user['name'] or 'Anonymous'
address_name = user['address'] or 'N/A'
print(user_name, address_name, sep=", ")
Elsie, N/A
Exercícios aplicados resolvidos¶
I. Considere:
em que
é lida como: “ é um ano de matrícula entre aqueles dos estudantes da turma de Matemática Discreta atual”.
é lida como: “ e , nesta ordem, são o número mínimo e máximo de vogais encontradas no sobrenome dos estudantes da turma de Matemática Discreta atual”.
Plote histogramas (número de estudantes x ano) que, além das propriedades acima, atendam os seguintes requisitos:
a. Ano de matrícula maior do que 2019 e sobrenome contendo de 4 a 6 vogais;
b. Ano de matrícula maior do que 2022 e sobrenome contendo de 1 a 5 vogais;
c. Ano de matrícula maior do que 2023 e sobrenome contendo de 7 a 12 vogais;
# Conteúdo resumido de '2-students.csv'.
Matrícula,Nome
20200025160,ABNER SOUZA DA SILVA
20250019830,ADIEL EMILSON DA SILVA
20250018996,ALONSO DA COSTA SOUSA ARAUJO
...
20240008682,FILIPE JUSCELINO QUEIROGA LACERDA
20240102254,GABRIEL LINO AZAMBUJA
20250018735,GERALDO NUNES DE OLIVEIRA NETO
...
20240011347,VINICIUS ALENCAR DE MEDEIROS
20250108645,VITOR DI PACE PORTO
20210094385,YAN FEITOSA CLAUDIO
Resolução¶
import pandas as pd
import re
import matplotlib.pyplot as plt
# Define limites de contagem de vogais
b1, b2 = 4,6
a = 2019
# Lê CSV
df = pd.read_csv("../examples/2-students.csv")
# Cria coluna com sobrenome
df["Sobrenome"] = df["Nome"].str.split().str[-1]
# Conta vogais maiúsculas no sobrenome
def conta_vogais(s):
return len(re.findall(r"[AEIOU]", s))
# Cria coluna com contagem de vogais
df["N_Vogais"] = df["Sobrenome"].apply(conta_vogais)
# Extrai ano de entrada (4 primeiros dígitos da matrícula) e converte para inteiro
df["Ano de Entrada"] = df["Matrícula"].astype(str).str[:4].astype(int)
# Define expressões complexa para filtro
p = f"(`N_Vogais` >= {b1}) and (`N_Vogais` <= {b2}) and (`Ano de Entrada` >= {a})"
# Filtra estudantes com base na expressão lógica
df_ = df.query(p)
# Checa se há estudantes no filtro
if (len(df_) == 0):
print(f"Nenhum estudante atende o critério de filtro.")
else:
# Conta quantidade por ano de entrada
contagem = df_["Ano de Entrada"].value_counts().sort_index()
# Plota da distribuição por ano
contagem.plot(kind="bar", figsize=(4,2))
plt.xlabel("Ano de Entrada")
plt.ylabel("Quantidade")
plt.title(f"Estudantes com [{b1}, {b2}] vogais no sobrenome")
II Usando o Exercício I, crie uma função que execute a mesma tarefa, porém automatizando a entrada dos critérios definidores da expressão lógica.
Resolução¶
def conta_vogais(s):
from re import findall
return len(findall(r"[AEIOU]", s))
def filtra_e_plota(b1, b2, a):
from pandas import read_csv
import matplotlib.pyplot as plt
# Lê CSV
df = read_csv("../examples/2-students.csv")
# Cria coluna com sobrenome
df["Sobrenome"] = df["Nome"].str.split().str[-1]
# Cria coluna com contagem de vogais
df["N_Vogais"] = df["Sobrenome"].apply(conta_vogais)
# Extrai ano de entrada (4 primeiros dígitos da matrícula) e converte para inteiro
df["Ano de Entrada"] = df["Matrícula"].astype(str).str[:4].astype(int)
# Define expressões complexa para filtro
p = f"(`N_Vogais` >= {b1}) and (`N_Vogais` <= {b2}) and (`Ano de Entrada` >= {a})"
# Filtra estudantes com base na expressão lógica
df_ = df.query(p)
# Checa se há estudantes no filtro
if (len(df_) == 0):
print(f"Nenhum estudante atende o critério de filtro.")
else:
# Conta quantidade por ano de entrada
contagem = df_["Ano de Entrada"].value_counts().sort_index()
# Plota da distribuição por ano
contagem.plot(kind="bar", figsize=(4,2))
plt.xlabel("Ano de Entrada")
plt.ylabel("Quantidade")
plt.title(f"Estudantes com [{b1}, {b2}] vogais no sobrenome")
return df_Caso b.
b1, b2 = 1,5
a = 2022
_ = filtra_e_plota(b1, b2, a)
Caso c.
b1, b2 = 7,12
a = 2023
_ = filtra_e_plota(b1, b2, a)Nenhum estudante atende o critério de filtro.