Você está na página 1de 118

ALGORITMOS EM PYTHON

PRÁTICA DE LABORATÓRIO
EM PYTHON

PROF. ELOI LUIZ FAVERO

BELEM - PA
2020
© E.L.Favero Algoritmos em Python 2

SUMÁRIO

1 INTRODUÇÃO & PYTHON TUTOR ............................................................. 8


1.1 Conceito de variável...................................................................................... 8
1.1.1 Variáveis em Python ..................................................................................... 9
1.1.2 Python Tutor ................................................................................................. 9
1.1.3 Identificação de erros no Python Tutor ....................................................... 12
1.1.4 Lista de exercícios no python tutor (10) ...................................................... 14
2 TIPOS DE DADOS INT E FLOAT .............................................................. 16
2.1 Alguns conceitos do pensamento computacional ....................................... 16
2.2 Ambiente de programação em Python ........................................................ 16
2.3 Tipos de Dados ........................................................................................... 18
2.4 Expressões aritméticas ............................................................................... 19
2.4.1 Praticando o código .................................................................................... 20
2.4.2 Prioridade dos operadores aritméticos........................................................ 20
2.4.3 Lista de exercícios para o shell (3) ............................................................. 20
2.4.4 Lista de exercícios para o IDLE (11) ........................................................... 21
2.4.5 Perguntas conceituais (7) ........................................................................... 22
2.4.6 Nerd - tópico opcional: INT, Bit e Byte ....................................................... 23
2.4.7 Tipo (type) da variável................................................................................. 24
3 TIPO DE DADOS STRING ......................................................................... 25
3.1 Tipo STRING .............................................................................................. 25
3.1.1 Composição de string ................................................................................. 26
3.2 Indexação e fatiamento ............................................................................... 28
3.3 Chr() & Ord() - Carateres ASCII .................................................................. 28
3.3.1 Lista de exercícios (8) ................................................................................. 29
3.3.2 Perguntas conceituais (4) ........................................................................... 29
3.4 Nerd: Int para string & string para Int (OPCIONAL NUM COMEÇO) .......... 30
3.4.1 Exercícos sobre chr e ord *COMPLEXO..................................................... 31
4 COMANDOS DE ENTRADA E SAÍDA ....................................................... 33
4.1 Entrada de Dados ....................................................................................... 33
4.2 Leitura de Float ........................................................................................... 34
4.3 Leitura de strings......................................................................................... 34
4.4 Lista de exercícios (11) ............................................................................... 34
5 EXPRESSÕES LÓGICAS .......................................................................... 36
5.1.1 Tipo BOOL .................................................................................................. 36
5.2 Operadores lógicos ..................................................................................... 37
5.2.1 Tabelas Verdade ......................................................................................... 37
5.2.2 Prioridade na parentização implícita ........................................................... 39
5.3 Expressões Relacionais .............................................................................. 39
5.3.1 Operadores relacionais: quando o igual não é igual ................................... 40
5.3.2 Prioridade dos tipos de operadores ............................................................ 40
5.3.3 Lista de exercícios (8) ................................................................................. 41
5.3.4 Perguntas conceituais (8) ........................................................................... 42
© E.L.Favero Algoritmos em Python 3

6 COMANDOS DE DECISÃO (IF) ................................................................. 43


6.1 Comando IF ................................................................................................ 44
6.2 Comandos IF ELSE, aninhados .................................................................. 45
6.3 IFs mais complexos .................................................................................... 46
6.3.1 Exercícios (8) .............................................................................................. 47
6.3.2 Perguntas conceituais (3) ........................................................................... 48
7 RE-FATORANDO O CÓDIGO .................................................................... 49
7.1 Refatorando o código .................................................................................. 49
7.2 Refatorando com funções ........................................................................... 50
7.3 Pensamento computacional: refatorando com funções .............................. 51
7.3.1 Exercícios (2) .............................................................................................. 52
7.3.2 Perguntas conceituais (6) ........................................................................... 52
8 TIPO LISTA, TUPLA E FAIXA DE VALORES ........................................... 53
8.1 Listas........................................................................................................... 53
8.2 Índices e fatiamento .................................................................................... 54
8.3 Acrescentar e remover elementos .............................................................. 55
8.4 Comando for para percorrer listas............................................................... 55
8.5 Tuplas ......................................................................................................... 56
8.5.1 Lista de exercícios (9) ................................................................................. 56
8.5.2 Perguntas conceituais (5) ........................................................................... 57
9 COMANDO DE REPETIÇÃO: FOR............................................................ 58
9.1 O comando FOR ......................................................................................... 58
9.2 Somar com FOR ......................................................................................... 59
9.2.1 String como lista de valores ........................................................................ 59
9.3 Contar com FOR ......................................................................................... 60
9.3.1 Lista de exercícios (8) ................................................................................. 61
9.3.2 Perguntas conceituais (2) ........................................................................... 63
10 COMANDO DE REPETIÇÃO: WHILE........................................................ 64
10.1 Comando WHILE ........................................................................................ 64
10.2 Somar com WHILE ..................................................................................... 65
10.3 Contar com WHILE ..................................................................................... 66
10.3.1 Lista de Exercícios (8)................................................................................. 66
10.3.2 Perguntas conceituais (1) ........................................................................... 69
11 FUNÇÕES .................................................................................................. 70
11.1 Mais sobre funções ..................................................................................... 70
11.2 Função soma() ............................................................................................ 71
11.2.1 Função média() e desvio() .......................................................................... 71
11.2.2 Listas x Strings ............................................................................................ 72
11.2.3 Função reverse() e palíndromo()................................................................. 72
11.2.4 Funções recursivas ..................................................................................... 73
11.2.5 Problemas recursivos.................................................................................. 75
11.3 Exercícios (16) ............................................................................................ 76
11.3.1 Perguntas conceituais (2) ........................................................................... 78
12 MÉTODOS DE BUSCA E ORDENAÇÃO .................................................. 79
© E.L.Favero Algoritmos em Python 4

12.1.1 Função maxi() e imax() ............................................................................... 79


12.1.2 Função busca(), in1() e index1() ................................................................. 80
12.1.3 Ordenção: método da bolha........................................................................ 80
12.1.4 Ordenação: Seleçao direta ......................................................................... 83
12.2 Exercícios (18) ............................................................................................ 84
13 VETORES E MATRIZES ............................................................................ 88
13.1 Medidas de distância .................................................................................. 88
13.2 Distância euclidiana, conseno e norma....................................................... 90
13.3 Matriz como Listas ...................................................................................... 91
13.3.1 Trabalhar com números aleatórios: random ............................................... 91
13.3.2 Mais sobre valores aleatórios random ........................................................ 93
13.3.3 Perguntas conceituais (12) ......................................................................... 94
14 DICIONÁRIOS E CONJUNTOS: SET E DICT ........................................... 95
14.1 Dicionários e Conjuntos: Set e Dict ............................................................. 95
14.2 Moda da estatística ..................................................................................... 97
14.3 Pensamento computacional: Dicionários .................................................... 98
14.4 “Multiplos ifs” versus “um dicionário” ........................................................... 99
14.5 Estruturas de dados complexas ................................................................ 100
14.5.1 Dados json ................................................................................................ 101
14.5.2 Perguntas conceituais (4) ......................................................................... 103
15 PERFORMANCE DE FUNÇÕES.............................................................. 104
15.1 Vários fatoriais .......................................................................................... 104
15.2 Testando a performance de um algoritmo ................................................ 105
15.3 Exercícios (4) ............................................................................................ 106
15.3.1 Perguntas conceituais ............................................................................... 107
16 APLICAÇÃO DE CÁLCULO NUMÉRICO ................................................ 108
16.1 Cálculo númerico ...................................................................................... 108
16.1.1 Número harmônico.................................................................................... 108
16.1.2 Método de Newton .................................................................................... 109
16.1.3 Método de Herão de Alexandria ............................................................... 110
16.1.4 Aproximar exp() ou ex ............................................................................... 111
17 OPERAÇÕES SOBRE BITS E BYTES .................................................... 113
17.1 Operações sobre bits e bytes ................................................................... 113
17.2 Crivo de Eratostenes................................................................................. 115
17.3 Escovando os bits ..................................................................................... 115
17.3.1 Perguntas conceituais ............................................................................... 118
© E.L.Favero Algoritmos em Python 5
© E.L.Favero Algoritmos em Python 6

Prefácio
Este texto surgiu como um material de apoio a um curso de tele-ensino de uma
disciplina de Algoritmos de 60 a 68 horas. O texto foi elaborado para contemplar a
metodologia de ensino descrita a seguir.
Cada capítulo compreende um módulo, tema, de 4 horas aula. São 15 capítulos
principais e 3 opcionais. A metodologia é mais assíncrona, porém com encontros síncronos.
O essencial de uma disciplina de algoritmos é a prática do estudante, que deve ser
verificada, checada a cada módulo, com a correção dos exercícios propostos.
Nos encontros síncronos, os temas e conceitos são apresentados em aulas de 45
min de exposição e um tempo posterior de discussão para tirar dúvidas, respondendo
perguntas.
Nas atividades assíncronas, o estudante lê o material dos módulos e resolve os
exercícios. No ambiente virtual é feita a postagem de cada módulo. Cada módulo é
associado com uma atividade de resolução de exercícios práticos e/ou teóricos. Neste
ambiente, o estudante posta a sua resolução dos exercícios e o professor avaliando-os tem
feedback para tirar dúvidas e/ou redirecionar os exercícios do próximo módulo.
Os comandos condicionais, de repetição, etc. são inicialmente apresentados através
de fluxogramas e pseudocódigo. A seguir, exemplos de usos dos comandos são traduzidos
para a linguagem Python e são animados no ambiente Python Tutor. Após o estudante
compreender o comportamento do comando apresentado, ele é convidado a executá-los no
ambiente de programação da linguagem Python, IDLE.
Segue a lista dos módulos:
1 INTRODUÇÃO & PYTHON TUTOR
2 TIPOS DE DADOS INT E FLOAT
3 TIPO DE DADOS STRING
4 COMANDOS DE ENTRADA E SAÍDA
6 COMANDOS DE DECISÃO (IF)
7 RE-FATORANDO O CÓDIGO
8 LISTA E FAIXA DE VALORES
9 COMANDO DE REPETIÇÂO: FOR
10 COMANDO DE REPETIÇÃO: WHILE
11 FUNÇÕES
12 MÉTODOS DE BUSCA E ORDENAÇÃO
13 VETORES E MATRIZES
14 DICIONÁRIOS E CONJUNTOS: SET E DICT
15 PERFORMANCE DE FUNÇÕES

Este texto destina-se a ensinar algoritmos e programação do ponto de vista de


prático. Informação não é conhecimento. Se compro um livro de medicina sobre cirurgia e
leio todo o livro, eu tenho o conhecimento para fazer cirurgias? Não. Mas tenho a
informação. O que precisa para se transformar informação em conhecimento? Precisa-se da
experiência prática. Através da prática de laboratório o aluno adquire as habilidades e
competências de programação. Este texto é centrado em exemplos e exercícios para o
estudante praticar algoritmos, fixando os conceitos do pensamento computacional. O
estudante é convidado a animar os exemplos e exercícios no Python Tutor para depois
executá-los numa IDLE como programas.
No total temos mais de 10 exercícios por módulo, mais de 150 exercícios no total. A
maior parte dos exercícios é prática de laboratório. Mas, também temos exercícios
conceituais para o estudante fixar, formar, estabelecer os conceitos dos temas abordados.
Por exemplo, O que é uma variável? O que é um algoritmo? O que é uma função? O que
significa refatorar código? É importante o estudante firmar um conjunto de conceitos
conforme ele vai amadurecendo no desenvolvimento de algoritmos e programas. Firmar um
conceito é amadurecer o suficiente para poder falar sobre o conceito.
© E.L.Favero Algoritmos em Python 7

O texto aborda algoritmo segundo uma visão de pensamento computacional, onde o


pensamento sobre a solução de um determinado problema é organizado numa forma de
algoritmo, receita de bolo, que permite a sua resolução dentro de uma linguagem de
programação. Um algoritmo é uma sequência de comandos que executa uma determinada
função computacional. Um comando é um passo mínimo dentro de um algoritmo.
Comandos são “verbos” computacionais que agem sobre variáveis e objetos - fazendo uma
analogia com uma sentença de linguagem natural, onde verbos agem sobre sujeitos e
objetos. Um algoritmo codificado numa linguagem especifica é um programa. Um
programa precisa ser executado (run) para gerar uma ação.
O livro segue uma abordagem de baixo para cima, do pequeno para o grande, mas
também do geral para o especifico. Após a apresentação dos conceitos, vamos nos
aprofundar e familiarizar com eles aos poucos. Muitos assuntos são apenas introduzidos
para mais adiante serem mais detalhados. Seguindo a abordagem do geral para o mais
específico, a cada capítulo novos conceitos são introduzidos e ou antigos conceitos são
mais detalhados.
Definimos um kit de ferramentas de pensamento computacional, de pensamento de
algoritmos. A tabela abaixo apresenta um kit mínimo, começando por variáveis, comandos
de atribuição, comandos de sequência, comandos de entrada e saída, comandos
condicionais, comandos de repetição, comando de abstração. Vamos nos aprofundar bem
nos comandos de repetição, mostrando várias alternativas para codificar o mesmo
algoritmo. Vamos trabalhar com as funções, como uma ferramenta para organizar os
códigos através do conceito de abstração, dar nome para um grupo de comandos.

Estruturados Tipos de comandos Exemplos


Verticais 1-Variáveis, objetos e expressões a=1;
e/ou 2-Comando de atribuição c=[1,2,5,9]
horizontais 3-Sequência de comandos a=1;b=3+a;x=1+b;print(x)
4-Comandos de entrada e saida input(); print()
Só pela 5-Comando condicional if, elif, else:
indentação 6-Comandos de repetição for, while
7-Conceitos de abstração def

Vamos bater na tecla da refatoração de código, como uma forma de exercitar o


raciocínio do pensamento computacional. Fazer diferentes escritas para uma mesma
solução de um problema. Muitas vezes quando um programa funcionou pela primeria vez o
estudante abandona o seu desenvolvimento. Esta forma de trabalho não é uma boa prática.
Uma boa prática é quando o programa funciona reescreve-lo buscando uma versão
alternativa (com for, com while, com um dicionário) ou buscando um código mais simples,
mais limpo, mais compreensivo, que ainda dê o resultado correto. Esta prática de
programação dará a certificação para o estudante, ele tende a perfeição. O que faz, faz bem
feito.
Bom estudo ao leitor.

Eloi Favero, Belém 2020


© E.L.Favero Algoritmos em Python 8

Capítulo

1 INTRODUÇÃO & PYTHON TUTOR


Este capítulo apresenta uma introdução ao conceito de variáveil e ao ambiente Python
Tutor para execução de Algoritmos codificados na linguagem Python. Este ambiente
mostra a visualização do comportamento do algoritmo, permitindo caminhar passo a
passo na execução para frente e para trás sobre as linhas do código. Conceitos
apresentados: variável, comando de atribuição, expressões aritméticas, algoritmo, passo
de execução, memória, nomes de variáveis. Prática de laboratório com Lista de
exercícios.

1.1 Conceito de variável


Estamos familiarizados com o conceito matemático de variável. Por exemplo, seja a
equação y=x.x+3x-4. Se x=0 então y=-4. Se x=10 então y=100+30-4=126. E assim por
diante. Logo o valor da variável y está definido em função do valor da variável x.

O gráfico abaixo mostra uma lista de valores plotados a partir de um programa Python.

from matplotlib import pyplot as plt

X = list(range(0,20))
Y = [x*x+3*x-4 for x in X]

plt.scatter(X,Y)
plt.show()

print(X)
print(Y)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,..., 18, 19]
[-4, 0, 6, 14, 24, 36, 50, 66, 84, 104, 126,...
, 374, 414]

Aqui, neste simples programa temos inúmeros conceitos de programação, de pensamento


computacional. O range(0,20) é um intervalo fechado no 0 e aberto no 20. X maiúsculo é um
vetor (list) de x minúsculos, são os 20 x, [0,1,2,...19]. A equação x.x+3x-4 é representada
como x*x+3*x-4. O vetor Y maiúsculo é a coleção de valores resultantes da função aplicada
aos 20 valores do vetor X, o primeiro é -4 e o último é 414.

Com este exemplo se entende porque se chamam variáveis, porque os valores variam.
Neste exemplo, as variáveis nomeiam valores inteiros ou vetores de valores inteiros.
© E.L.Favero Algoritmos em Python 9

Variáveis em geral armazenam objetos computacionais: valores inteiros, reais, vetores de


inteiros, vetores de reais, nomes, listas de compras, atributos de um ser humano como cpf,
data nascimento, altura e cor dos olhos.

Observação: o programa acima não precisa ser compreendido agora. Foi apresentado só
para motivar a introdução do conceito de variável. O que é necessário compreender neste
módulo é como práticar os exercícios apresentados no final do módulo, sobre o conceito de
variável.

1.1.1 Variáveis em Python


As variáveis ocupam o espaço de memória de um computador. Uma variável em Python é
representada por um frame ou por um objeto. Para compreender melhor o que é um frame
ou um objeto vamos visualizar a execução de alguns comandos com o Python Tutor, ver na
web.
Para quem está aprendendo algoritmos ou iniciando em programação
recomendamos o uso do ambiente Python Tutor, pois ele permite a visualização do efeito
dos comandos mostrando a representação das variáveis e permitindo o acompanhamento
da execução passo a passo dos comandos, para frente e para traz. Visualizando assim o
efeito dos comandos sobre as variáveis.
Vamos examinar nosso primeiro programa. Neste exemplo, o símbolo de igual =
representa o comando de atribuição. Se a=1 e c=a, então c=1. Depois, c=c+1 então c=1+1.
O print() imprime o valor. Só nos próximos capítulos vamos diferenciar o comando de
atribuição do teste de igualdade, que é necessário nas expressões de condições.

a=1
b=2
c=a
c=c+1
print(a)
print(a+b)
print(a+c)
linhas de código

1.1.2 Python Tutor


Vamos trabalhar com o ambiente online do Python tutor. Marque, copie e cole as linhas de
código para uma janela do python tutor. Mantenha o tradutor do google para a língua
inglesa. Pois, senão ele vai confundir, vai traduzir só pela metade, e até tentar traduzir
palavras do programa.
© E.L.Favero Algoritmos em Python 10

Agora clicando em Visualize Execution, vamos visualizar a execução do código (code).


Segue uma tradução para os termos em Inglês, falando dos principais termos usados neste
ambiente:

 Print output (drag lower right corner to resize) :Escreva saída (araste canto direito
inferior para mudar o tamanho)
 Frames, Objects: Memorias, Objetos
 (known limitations) : limitações conhecidas
 line that just executed: linha recém executada
 next line to execute: próxima linha a executar
 Edit this code: edite este código
 First, Prev, Next, Last: primeiro, prévio, próximo, último
 Global Frame: Memoria Global
© E.L.Favero Algoritmos em Python 11

Agora com dois next chegamos na situação abaixo, onde na memória global é mostrado que
as variáveis possuem os valores a=1 e b=2.

Com mais um next c=1, e com mais um next c=2 no Global Frame. Podemos executar
também para trás com o botão prev. Assim vamos executanto para frete ou para trás o
código, até entendermos o que o programa esta fazendo, compreendendo o comportamento
da execução do algoritmo.
© E.L.Favero Algoritmos em Python 12

Nos passos 5, 6,e 7 ocorrem as impressões dos valores na tela de saída, respectivamente
os valores 1, 3, 3.

O nome de uma variável sempre começa por uma letra ou pelo _. Depois do primeiro
caractere podemos ter também números. A linguagem é case sensitive, isto é, nomes com
maiúscula e com minúsculas são diferentes, x ≠ X. Os comentários de linha em Python são
iniciados pelo símbolo #, e vão até o final da linha. Seguem alguns exemplos de declarações
de variáveis em comandos de atribuição.

# exemplos de variáveis
A1 = 76
a1 = 12 # comentario
aa_1 = a1+A1
zero = 0

1.1.3 Identificação de erros no Python Tutor


Identificação de erros de sintaxe ou de indentação. Abaixo, mostramos um caso de
erro de indentação.
© E.L.Favero Algoritmos em Python 13

O tradutor do google pode nos auxiliar na identificação do erro, mas é bom depois
voltar para o idioma inglês.
© E.L.Favero Algoritmos em Python 14

1.1.4 Lista de exercícios no python tutor (10)


Vamos adotar a seguinte convenção. Nos exercícios, os códigos dos algoritmos são
separados da sua saída pelo prompt >>>, então quando for copiar e colar; copie somente a
parte acima do prompt >>>. No próximo capítulo ficará mais claro porque utilizamos o
prompt >>>.
Pratique cada um dos exercícios abaixo no python tutor. Trabalhe até compreender o
que esta acontecendo com o código, até compreender o comportamento do algoritmo.

E1.1 a=1
b=2
c=a
c=c+1
print(a)
print(a+b)
print(a+c)
>>>
1
3
3
E1.2 # exemplos de variáveis & comentários
A1 = 76
a1 = 12
aa_1 = a1+A1 # o valor de aa_1 é 88
zero = 0

E1.3 Escreva o resultado de 2a x 3b. Onde a=3 e b=5.

a=3
b=5
res=2*a * 3*b
print(res)
>>>
90
E1.4 Escreva o resultado de 2a x 3b. Onde a=7 e b=11.

E1.5 Escreva o resultado de 4a x 2b. Onde a=3 e b=5.

E1.6 Calcule a soma de três variáveis, a=3;b=5;c=11.

a=3
b=5
c=11
abc=a+b+c
print(abc)
>>>
19
E1.7 Seja um salário (sal) de 1000. Como dar um aumento de 15%. Qual o valor do
aumento e do novo salário.

sal=1000
percent=15
aumento=sal*percent/100
novosal=sal+aumento
© E.L.Favero Algoritmos em Python 15

print(aumento, novosal)
>>>
150.0 1150.0

E1.8 Seja um salário (sal) de 1500. Como dar um aumento de 20%. Qual o valor do
aumento e do novo salário.

sal=1500
percent=20
aumento=sal*percent/100
novosal=sal+aumento
print(aumento, novosal)
>>>
300 1800

E1.9 Seja um salário (sal) de 1500. Como dar um aumento de 10%. Qual o valor do
aumento e do novo salário.

E1.10 Seja um salário (sal) de 1800. Como dar um aumento de 1%. Qual o valor do
aumento e do novo salário.

RESUMO
= comando de atribuição
+ - * / operadores aritméticos
print() comando de impressão
variável
nomes de variáveis
algoritmo é uma sequênciade comandos
© E.L.Favero Algoritmos em Python 16

Capítulo

2 TIPOS DE DADOS INT E FLOAT


Este capítulo aprofunda o conceito de variável, agora associado as tipos int e float.
Apresenta-se o ambiente de programação da linguagem Python. Conceitos de
pensamento computacional trabalhados: algoritmo, comandos, tipos de dados, variável,
expressões aritméticas, função, programa, arquivo de código. Prática de laboratório com
lista de exercícios práticos e conceituais. Conteúdo opcional bit e byte.

2.1 Alguns conceitos do pensamento computacional

sal = 1500
percent = 20
aumento = sal*percent/100
novosal = sal+aumento
print(aumento, novosal)

Um algoritmo é uma sequência de comandos que executa uma determinada função


computacional. Um comando é um passo mínimo dentro de um algoritmo. No exemplo
acima, cada linha é um comando. Comandos são “verbos” computacionais que agem sobre
variáveis e objetos - fazendo uma analogia com uma sentença de linguagem natural, onde
verbos agem sobre sujeitos e objetos.
Um algoritmo codificado numa linguagem especifica é um programa. No ambiente de
programação, um programa em Python normalmente é salvo em um arquivo com a
extensão .py (e.g. meu.py). Um programa precisa ser executado (run) para gerar uma
ação.
2.2 Ambiente de programação em Python
A linguagem Python tras alguma liberdade ao programador, pois ela pode ser programada
num ambiente como o IDLE, PyCharm, etc. como também pode ser programada num
ambiente web, por exemplo, o Python Tutor que é indicado para iniciantes.
Na web podemos também programar com um Python notebook, como Jupyter, que
permite criar um ambiente web, com texto, código fonte e dados, ambiente indicado para
estudantes já iniciados.
© E.L.Favero Algoritmos em Python 17

Interface do IDLE

Acima, no lado esquerdo criamos o programa meu.py. Depois de digitar estas linhas de
código o ambiente pede para salvarmos (save) o arquivo antes de executarmos (run) o
código. O resultado da execução é mostrado na tela Shell do IDLE, no lado direito. No topo
da tela, encima, no lado esquerdo, aparece o caminho (path) da pasta onde está o arquivo
do programa. Na tela da direita novamente o caminho é repetido dizendo RESTART (re-
iniciado, ou re-executado). No lado esquerdo da IDLE temos várias opções de menu: file,
edit, format, run, etc.
 No file é importante saber: new (novo arquivo), open (abrir), recent files (abrir um
recente), save (salva), save as (salvar como, com novo nome).
 No edit é importante saber: undo (ctr-z, desfazer um erro de edição), replace
(substituir um nome de variável por outro); além disso usa-se muito copiar e colar.
 No format é importante saber: indent (fazer uma indentação) e dedent (tirar a
indentação). Quando o ambiente diz que tem problema de indentação, uma forma de
corrigir é remover toda indentação e criar uma indentação nova e correta, com estes
dois comandos.
 No Run é importante saber: run module (F5) rodar o código.

Na tela da direta no shell do IDLE podemos executar diretamente comandos no prompt


>>>2*3. Neste lado deve-se executar um comando por vez. Este promt é muito útil para
testar operadores e/ou linhas de comandos individuais.

Para usuários iniciantes recomendamos o Python Tutor e o ambiente IDLE. O primeiro é


para o estudante compreender o que acontece com as variáveis e objetos usados no
algoritmo. O segundo ambiente também é recomendado pela simplicidade. Outros
ambientes exigem alguma experiência inicial já praticada nestes ambientes mais fáceis.

Praticando o código no lado direito (shell):


# Expressões + - * / % **
>>> 2**3
8
>>> 10 / 3
3.3333333333333335
>>> 10 % 3
1
>>> 8 / 3
2.6666666666666665
>>> 8 % 3
2
© E.L.Favero Algoritmos em Python 18

2.3 Tipos de Dados


Python tem dois principais tipos de dados numéricos: int e float. Int representa valores
inteiros positivos ou negativos. Float representa valores chamados de ponto flutuante ou
decimais ou reais. As funções int(), float() e round(), respectivamente inteiro, flutuante e
arredondar, permitem fazer a conversão de um tipo de valor para outro tipo de valor.

a = float(22/5)
b = int(4.5)
c = int(3)
d = int(0xff563)
print(a,b,c,d)
>>>
4.4 4 3 1045859

Esta notação acima, com várias linhas de comandos deve ser digitada no lado esquerdo; em
new file cria-se uma nova janela *untitled*; depois copia-se e cola-se, não incluir o prompt
>>>.
Quando pedimos para rodar (run) o ambiente pede para darmos um nome para o programa
ser salvo.
© E.L.Favero Algoritmos em Python 19

Quando é forçado o run, vemos o efeito do código que é o print mostrado depois do prompt.
A variável a representa um valor decimal 22/5 = 4.4. A variável b recebe a parte inteira do
valor 4.5 que é 4. Em d o valor hexadecimal FF563 equivale ao valor inteiro 1045859.

e = float(int(3.9))
f = int(float(3.9))
g = int(float(3))
h = round(3.9)
i = round(3.49)
j = round(3.5)
print(e,f,g,h,i,j)
>>>
3.0 3 3 4 3 4

Em e o valor 3.9 foi convertido para 3 e depois para float 3.0. Em f o 3.9 float é convertido
para o int 3. Em h o valor 3.9 é arredondado para o inteiro mais próximo que é 4. Em i o
valor 3.49 foi arredondado o int mais próximo 3. Em j o valor 3.5 é arredondado para o 4, e
não para o 3. O comando print() imprime os valores das variáveis.

BOX Conceito: Uma função é código computacional que executa uma


funcionalidade. Abaixo temos uma definição matemática de função y=f(x). O x
pertence ao dominio A e o y a imagem B. Na matemática, nas funções,
imagens, domínios e variáveis são tipicamente nomeadas por uma letras, ex.
A, B, x, y, f, g. Na programação preferimos nomes mais significativos. Tipo
Inteiros (int) e reais (float), round, trunc, etc.

2.4 Expressões aritméticas


Como em outras linguagens temos vários tipos de operadores aritméticos, (+ - * /). Na
divisão temos três operadores: / divisão float; // parte inteira da divisão; e % o resto da
divisão inteira.

>>> 1/3
0.3333333333333333
>>> 5//2
2
>>> 5%2
1

Aritméticos Parte e resto da divisão


© E.L.Favero Algoritmos em Python 20

+ - * / ** // (parte inteira)
% (resto da divisão)
Operadores aritméticos

Além dos 4 operadores aritméticos básicos + - * /, temos a combinação deles com o


operador de atribuição. Por exemplo, a+=1 é o mesmo que a=a+1 e a*=2 é o mesmo que
a=a*2. O operador ** representa a potenciação: 2**4 = 2*2*2*2 = 16.

2.4.1 Praticando o código


Seguem alguns exemplos de expressões para serem praticadas no shell, como comandos
individualizados.
>>> 2**3
8
>>> 10 / 3
3.3333333333333335
>>>10//3
3

>>> 10 % 3
1
>>> 8 / 3
2.6666666666666665
>>> 8 % 3
2

2.4.2 Prioridade dos operadores aritméticos


Na expressão 10*2**3 mesmo não colocando parênteses a parentização implícita fica
10*(2**3).

>>> 10*2**3
80
>>> (10*2)**3
8000
>>> 10*(2**3)
80

2.4.3 Lista de exercícios para o shell (3)


Execute estes comandos no python shell do IDLE. No Shell não é necessário salvar os
comandos como arquivos de programas. Usa-se o python como uma calculadora. No shell
para saber o valor de uma variável escreve-se: >>>x=4*5;x ou >>>x=4*5; >>>x.

E2.1 Qual é o valor de x nas expressões:

>>> x= 2**3
( ) 0 ( )6 ( )8 ( )9 ( )27

>>> x= 2 % 3
( ) 0 ( )1 ( )2 ( )3 ( )1.5
© E.L.Favero Algoritmos em Python 21

>>> x= float(20 % 3)
( ) 0 ( )1.0 ( )2 ( )2.0 ( )1.5

>>> x= int(20 / 3)
( )6 ( )6.0 ( )6.666 ( )3.333 ( )1.5

>>> x= 3 - 2 * 4
( ) 0 ( )4 ( )-5 ( )4.0 ( )-2

>>> x= 3 * 2 ** 2
( )0 ( )12 ( )36 ( )7 ( )100

E2.2 Converta para Python as expressões aritméticas: 10+2x30, 42+30, (94+2)x6-1

>>> 10+2*30
70
>>> 4**2+30
46
>>> (9**4+2)*6-1
39377

E2.3 Converta para Python as expressões aritméticas: a2+5b+30, (93+2)x6-1, onde


a=7, b=100.

2.4.4 Lista de exercícios para o IDLE (11)


Estes códigos devem ser salvos como arquivos de programas individuais na IDLE.

E2.1 Seja um salário (sal) de 1000. Como dar um aumento de 15%. Qual o valor do
aumento e do novo salário.

sal=1000
percent=15
aumento=sal*percent/100
novosal=sal+aumento
print(aumento, novosal)
>>>
150.0 1150.0

E2.2 Seja um salário (sal) de 1500. Como dar um aumento de 20%. Qual o valor do
aumento e do novo salário.

sal=1500
percent=20
aumento=sal*percent/100
novosal=sal+aumento
print(aumento, novosal)
>>>
300 1800
© E.L.Favero Algoritmos em Python 22

E2.3 Seja um salário (sal) de 1500. Como dar um aumento de 10%. Qual o valor do
aumento e do novo salário.

E2.4 Seja um salário (sal) de 1800. Como dar um aumento de 1%. Qual o valor do
aumento e do novo salário.

E2.5 Escreva o resultado de 2a x 3b. Onde a=3 e b=5.

a=3
b=5
res=2*a * 3*b
print(res)
>>>
90
E2.6 Escreva o resultado de 2a x 3b. Onde a=7 e b=11.

E2.7 Escreva o resultado de 4a x 2b. Onde a=3 e b=5.

E2.8 Calcule a soma de três variáveis, a=3;b=5;c=11.

a=3
b=5
c=11
abc=a+b+c
print(abc)
>>>
19
E1.9 Seja uma temperatura de 30 graus Celsius; converter para Fahrenheit:
F=(9*C)/5+32.
E1.10 Sejam 28 dias. Quantas horas e quantos minutos tem em 28 dias? Por
exemplo, 2 dias, são 48horas e 48*60=2880 minutos.

E1.11 Um senhor deixou um testamento para 3 filhas (A,B,C) e um filho (D). No


testamento diz que as filhas A,B,C receberão respectivamente, 1/4, 5/16 e 3/8
partes e o filho homem receberá o restante. O valor que ele deixou é 999000.
Imprima quanto cada um recebe.

2.4.5 Perguntas conceituais (7)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C2.1 Quais os tipos de operadores associados a divisão? Qual a diferença entre eles?
C2.2 O que é uma variável?
Variáveis armazenam objetos computacionais: inteiros, strings, etc. São usadas
dentro de expressões e/ou em comandos.
C2.3 O que é um comando?
C2.4 O que é um algoritmo?
C2.5 O que é uma função?
C2.6 O que é um programa?
C2.7 Qual a diferença entre bit e byte?
Um bit é a unidade mínima de informação, pode assumir os valores 0 ou 1;
sequencias de bits formam números; um byte são oito bits.
© E.L.Favero Algoritmos em Python 23

2.4.6 Nerd - tópico opcional: INT, Bit e Byte


Este tópico é opcional, podendo ser pulado numa primeira leitura. Mas em computação
falamos de bits e bytes então vamos examinar o que são bits e bytes. Valores int podem ser
representados em diferentes bases. Pessoas perguntam qual é o tamanho de um inteiro em
bytes. Podemos utilizar sys.getsizeof(73) para checar o tamanho em bytes ocupado na
memória pelo número inteiro 73, que são 14 bytes.

>>> import sys


>>> sys.getsizeof(73)
14

BOX: Um byte são oito bits. O valor binário do inteiro em hexa 0xFF é um byte
‘0b11111111’, que é o valor positivo 255. Num byte podemos representar a faixa de
0 até 255, que são 2**8=256 valores.

>>>bin(0xF)
'0b1111'
>>>bin(0xFF)
'0b11111111'
>>>bin(0xF0)
'0b11110000'

Em 32 bits podemos representar inteiros grandes. Por exemplo, int(0xF0080419)=


4.027.057.177, 4 bilhões, 27 milhoes, etc. O valor máximo é 2**32-1, que é
4.294.967.295.

>>>int(0xF0080419)
4027057177
>>>bin(0xF0080419)
'0b11110000000010000000010000011001'

Normalmente usa-se valores decimais (de base 10), mas pode-se definir valores octais (de
base 8) e hexadecimais (base 16) ou binários (base 2). Para declarar um inteiro octal,
hexadecimal ou binário usa-se os prefixos, 0o, 0x, 0b. Acima temos um hexa de oito dígitos
0xF0080419 que corresponde a 32 bits.

a = 42 #decimal
b = 0o10 #octal
c = 0xA1 #hexadecimal
d = 0b1010101
print(a,b,c,d)
>>>>
42 8 161 85

Podemos também converter um valor decimal para as diferentes bases usando-se as


funções bin(), oct() e hex(). Os dígitos binários são utilizados na representação internas dos
computadores, nas arquiteturas dos computadores. As operações internas na arquitetura
dependem de portas lógicas que operam sobre bits e bytes. A unidade mínima de
© E.L.Favero Algoritmos em Python 24

informação é o bit. Oito bits formam o byte. Alguns computadores possuem a memória
formada por palavras de 8 bytes, ou 64 bits. Na escrita destes bytes é mais fácil utilizar a
notação hexadecimal, por exemplo, dois dígitos hexa correspondem a um byte ou 8 bits.

dec = 344
print("O decimal",dec,"é:")
print(bin(dec),"em binario.")
print(oct(dec),"em octal.")
print(hex(dec),"em hexadecimal.")
>>>
O decimal 344 é:
0b101011000 em binario.
0o530 em octal.
0x158 em hexadecimal.

2.4.7 Tipo (type) da variável

A função type() permite testar o tipo de dados de um valor ou de uma variável. Por exemplo,

>>> type(10)
<class 'int'>
>>> type(12.1)
<class 'float'>

Neste caso cada tipo é visto como uma classe de objetos, deste ponto de vista vem a
palavra class. Assim os inteiros, os float e os boolean, são também objetos.

Inteiros são simples e óbvios, mas Float representa números reais com ou sem expoente (e
ou E). Esses números são comumente chamados de floating-point ou números de ponto
flutuante. Por exemplo: 0.0042, .005, 1.14159265 e 6.02e-23 (o mesmo que 6.02 x 10-²³).

Executando os prints abaixo, temos o tipo de dados dos valores numéricos testados,
diferenciando int de float.

print(type(5))
print(type(5.0))
print(type(4.3))
print(type(-2))
print(type(100))
print(type(1.333))
>>>
<class 'int'>
<class 'float'>
<class 'float'>
<class 'int'>
<class 'int'>
<class 'float'>
© E.L.Favero Algoritmos em Python 25

Capítulo
3 TIPO DE DADOS STRING
Este capítulo apresenta o tipo de dados string usado para representar nomes e
textos. Eles são muitos usados nos comandos de entrada e saída. Aqui tratamos de vários
operadores e métodos de manipulação de strings: operadores + % *; métodos lower(),
upper(), split(), strip(). Fatiamento de strings. Composição de strings. Caracteres ascii.

3.1 Tipo STRING


Para atribuirmos para uma variável um string, basta que coloquemos entre aspas simples,
ou triplas, como mostra o exemplo abaixo; pode ser também apóstrofo. Neste print
concatenamos as 3 strings usando o operador +. Entre eles colocamos o string fim de linha
“\n”.

A='Isso é uma String com apostrofo'


B="Isso é uma String com aspas"
A3='''Isso é uma String com 3 apostrofo'''
B3="""Isso é uma String com 3 aspas"""
print('varios strings:'+'\n'+A+'\n'+B+'\n'+A3+'\n'+B3+'\n')

Strings no início de uma linha, sem o comando de atribuição são considerados comentários.
O string com três aspas pode ocupar várias linhas. É útil em programas grandes para
colocar uma parte do código programa como comentário, ou para representar um texto
grande dentro do código do programa.

""" aqui é comentário


Exemplo com string
© E.L.Favero Algoritmos em Python 26

grande"""

b="""Este texto tem


algumas linhas
esta é a terceira
esta é a quarta"""
print(b.split())
>>>
['Este', 'texto', 'tem', 'algumas', 'linhas', 'esta', 'é', 'a',
'terceira', 'esta', 'é', 'a', 'quarta']

O método Split quebra o string e devolve uma lista, acima temos uma lista de palavras. Litas
só veremos mais adiante, mas aqui vamos nos familiarizando com a notação.

Os strings em python são não mutáveis. Portanto, se temos uma string a fazemos b=a;
serão duas cópias diferentes; se modificamos o a não modifica o b. Para isso acontecer as
variáveis string são referencias (apontam para) os conteúdos. Ver abaixo.

3.1.1 Composição de string


O tipo string permite muitas operações, entre elas, atribuição =, concatenação +,
multiplicação *, composição %. Nas linhas 1 e 2, abaixo, são criadas 2 variáveis as quais
atribuímos uma string. Na linha 3 usa-se a composição de strings %, um recurso que
preenche os marcadores escritos com %s, do tipo string, a partir de uma tupla de valores
(valores entre parênteses).

nome1 = "Linguagem Python"


nome2 = 'Algoritmos'
print ("Texto de %s para programação na %s" % (nome2, nome1))
>>>
Texto de Algoritmos para programação na Linguagem Python

>>> '-'*10
'----------'
© E.L.Favero Algoritmos em Python 27

Para a composição de strings temos inúmeros marcadores, para os diferentes tipos de


dados: caracteres, string, decimais com sinal e sem sinal, decimais em outras bases (ver
final do capítulo 2) e ponto flutuante.

Marcador do tipo de dados Conversão


%s String
%i, %d Decimal inteiro
%x, %X Hexadecimal Inteiro
%e, %E Notação exponencial
%f Ponto flutuante (Números reais)
Alguns formatos para a composição de strings

>>> 'tempo: %5.2f horas' % (42.232232)


'tempo: 42.23 horas'

No exemplo acima o tempo é mostrado apenas com duas casas decimais. 5 casas no total,
duas depois do ponto. Aos poucos vamos introduzindo o uso destes formatos para a
composição de strings.
Além dos operadores (+ % *) para strings temos vários outros métodos tais como
lower(), upper(), split(), strip(), etc. O método startswith(prefixo) retorna True se uma string
começa com o prefixo passado por argumento, e False caso contrário.
O termos lower(), upper(), split(), strip() significam:

 lower(), caixa baixa


 upper(), caixa alta
 split(), quebra
 strip(), limpa brancos
 startswith(), começa com
 len(), (length), comprimento
 capitalize(), primeira letra em maiúscula

Seguem alguns exemplo. Como trabalhar com letras maiúsculas e ou minúsculas: O


capitalize(), exibe em caixa alta apenas o primeiro caractere de cada palavra; o upper()
retorna em caixa alta e lower() retorna em caixa baixa.

>>> nome1 = "Linguagem Python"


>>> nome1.upper()
'LINGUAGEM PYTHON'
>>> nome1.lower()
'linguagem python'

Podemos testar como começa o início de um string, no caso o nome1 definido acima.
Depois o método strip() retorna uma cópia da string com os espaços em branco removidos
(antes e depois).

>>> nome1.startswith('lin')
False
>>> nome1.startswith('Lin')
True
© E.L.Favero Algoritmos em Python 28

>>> ' aaa '.strip()


'aaa'

Duas funções muito úteis são split() e len(). A Split() quebra e retorna uma lista com os
pedaços. A função len() determina o comprimento da string (quantas letras possui).

>>> x='2,5,7, 12, 15, 7'


>>> x.split(',')
['2', '5', '7', ' 12', ' 15', ' 7']
>>>
>>> len('abcd')
4

3.2 Indexação e fatiamento


Abaixo temos um exemplo de fatiamento de string [:], [início:fim]. nome1[10:] pega a partir
da posição 10 até o fim; nome[10:13] pega a partir da posição 10 até a 12; nome[:5] pega do
início até o 4. Note que o início conta mas o fim não conta, é exclusive fim: fim=13 na prática
é até 12; fim=5 na prática é até 4. Isto é porque a indexação (numeração) começa no
zero. Na prática nome1[:5] pega os primeiros 5 caracteres.

>>> nome1 = "Linguagem Python"


# 0123456789012345
>>> nome1[10:]
'Python'
>>> nome1[10:13]
'Py'
>>> nome1[:5]
'lingu'

3.3 Chr() & Ord() - Carateres ASCII


A tabela Ascii define o mapeamento do conjunto de caracteres para o valor inteiro
representável num byte. As funções chr() e ord() codificam o mapeamento. A função chr()
converte o valor inteiro num caractere e a função ord() retorna o valor inteiro do caractere.

>>> chr(48)
'0'
>>> chr(49)
'1'
>>> chr(65)
'A'
>>> chr(90)
'Z'
>>> chr(97)
'a'
>>> ord('3')
51
>>> ord('b')
98

Abaixo temos um resumo da tabela Ascii, para os principais grupos de letras. As letras de
controle são utilizadas internamente pelos sistemas computacionais principalmente para
© E.L.Favero Algoritmos em Python 29

comunicação de dados. O ord(' ')=32; ord('\t')=9; ord('\n')=10; respectivamente ord() do


espaço, tabulação e nova linha.

Tipo Valores Representação


controle 0..8,
14..31,
127
alfabéticos 65..90, ABCDEFGHIJKLMNOPQRSTUVWXYZ
97..122 abcdefghijklmnopqrstuvwxyz
dígitos 48..57 0123456789
espaços 9..13, 32
pontuação 33..47, !"#$%&'()*+,-./
58..64, :;<=>?@
91..96, [\]^_`
123..126 {|}~

3.3.1 Lista de exercícios (8)


Programe os exercícios utilizando fatiamento mais as funções e operadores sobre
string apresentados acima.
E3.1 Seja, a='jhon lenon’ . Imprima o conteúdo da variável a capitalizado.

E3.2 Seja, a='jhon lenon’ . Imprima o conteúdo da variável todo em caixa alta.
E3.3 Seja, a='jhon lenon’ . A partir de a, imprima “Lenon, Jhon”. Use fatiamento e
capitalize().
a='jhon lenon'
# 0123456789
print(a[5:].capitalize()+ ', ' + a[:4].capitalize())
>>>
Lenon, Jhon
E3.4 Seja, a='jhon lenon’ . A partir de a, imprima “Jhon, Jhon, Jhon, Lenon. Use
também o operador * para string.
E3.5 Seja, a='jhon lenon’ . A partir de a, imprima “----------Jhon---------“. Use também o
operador * para string.
E3.6 Seja, a='jhon lenon’ . A partir de a, imprima “J. Lenon”.

a='jhon lenon'
# 0123456789
print(a[0].upper()+ '. ' + a[5:].capitalize())
>>>
J. Lenon
E3.7 Seja b="tinoco". Escreva "TINoco", pegando fatias da string b.
E3.8 Seja a='jhon \nlenon \n'. Escreva "LENON, JHON", pegando fatias da string a.

3.3.2 Perguntas conceituais (4)


© E.L.Favero Algoritmos em Python 30

C3.1 Responda com no mínimo 10 palavras e no máximo 20 palavras:

C3.2 Qual a diferença entre uma string declarada com aspas (apóstrofos) ou 3 aspas?

C3.3 Quais os diferentes usos do operador %, para inteiros e para strings ?

C3.4 Qual o uso do “\n”?

RESUMO:
string com um apóstrofo ou aspas
string com três apóstrofos ou aspas (multi linhas)
string no início de linha como comentário
operadores sobre expressões de string: concatenação +, multiplicação *, composição %
lower(), caixa baixa
upper(), caixa alta
split(), quebra
strip(), limpa brancos
startswith(), começa com
len(), (length), comprimento
capitalize(), primeira letra em maiúscula
fatiamento [início:fim]
tabela ascii
ord() valor ascii do caractere
chr() char do valor ascii

3.4 Nerd: Int para string & string para Int (OPCIONAL NUM
COMEÇO)
Por exemplo, '1312'= (((((1*10)+3)*10)+1)*10)+2. Então para pegar o valor 1 a partir do '1'
devemos fazer ord('1')-ord('0’)=49-48=1, pois, em Ascii os números são sequênciais; o valor
7 a partir de '7' devemos fazer ord('7')-ord('0’)=55-48=7.

def str2int(S):
val=0; LEN=len(S)
for i in range(LEN):
dig=ord(S[i])-ord('0')
val = val*10+dig
return val
print(str2int('1312'), str2int('0'), str2int('100'))
print(int('1312'), int('0'), int('100'))

>>>
1312 0 100

Este algoritmo srt2int() simula a função int() do Python, mas nossa versão ainda é limitada,
pois o int() aceita [+-] o sinal na frete do número e aceita colocar caracteres de espaço antes
e/ou depois. Por fim, também se pode trabalhar com bases, 2, 8, 16, e.g., na base 2,
int('10101',2) = int('0b10101',2)=21.
© E.L.Favero Algoritmos em Python 31

>>> int(' +32 ')


32
>>> int(' -32 ')
-32
>>> int('10101',2)
21

A solução abaixo codifica o inverso, int para str, int2str(). Mas vamos fazer sem usar str().
Para um só dígito é simples: str(D) é equivalente a chr(D+ord('0')), por exemplo,
chr(7+ord('0'))='7' e str(7)='7'. Para converter um inteiro, >9, numa sequência de dígitos
fazemos: enquando for maior ou igual a 10, basta pegar sempre o resto da divisão inteira
por 10. Por exemplo, a partir de 312, 312//10 da 31 e 312%10 dá 2; depois a partir de 31,
31 // 10 dá 3 e 31%10 dá 1; depois 3<10, pega-se o 3. Juntando tudo da [2,1,3]. Revertendo
da [3,1,2].

def dig(x): return chr(x+ord('0'))


def int2str(I):
STR=[]
while I>=10:
STR.append( dig(I%10) )
I = I//10
else: STR.append( dig(I) )
return ''.join(reversed(STR))
print(int2str(312), int2str (0), int2str(10000))
>>>
312 0 10000

Este algoritmo facilmente pode manipular inteiros negativos, basta guardar o sinal do
número, neg=x<0;x=abs(x), e trabalhar com o valor abs(). No final, se for negativo
acrescentar o sinal no início da string.
Está solução também pode ser generalizada para outras bases, substituído-se o 10
pela base, por exemplo, 2, 8. Para a base 16 a função dig() deve ser ajustada para trabalhar
com os dígitos “0123456789abcdef”.

3.4.1 Exercícos sobre chr e ord *COMPLEXO


E3.1 Faça a função srt2int(), string para inteiro. '1312'= (((((1*10)+3)*10)+1)*10)+2. Para
criar o valor 7 a partir de '7' devemos fazer ord('7')-ord('0’)=55-48=7.

def str2int(S):
val=0; LEN=len(S)
for i in range(LEN):
dig=ord(S[i])-ord('0')
val = val+dig
if i<LEN-1: val*=10
return val
print(str2int('1312'), str2int('0'), str2int('100'))
>>>
1312 0 100

E3.2 Faça a função dig() que retorna o valor inteiro de um digito char
def dig(x): return chr(x+ord('0'))
© E.L.Favero Algoritmos em Python 32

E3.3 Faça a função int2str que transforma um inteiro para string usando dig()
def int2str(I):
STR=[]
while I>=10:
STR.append( dig(I%10) )
I = I//10
else: STR.append( dig(I) )
return ''.join(reversed(STR))
print(int2str(312), int2str (0), int2str(10000))
>>>
312 0 10000

E3.4 Faça a função int2str generalizada para trabalhar com hexadecimais. Está solução
também pode ser generalizada para outras bases, substituído-se o 10 pela base, por
exemplo, para 16 a função dig() deve ser ajustada para trabalhar com os dígitos
“0123456789abcdef”.
© E.L.Favero Algoritmos em Python 33

Capítulo

4 COMANDOS DE ENTRADA E SAÍDA


Este capítulo apresenta os comandos básicos de entrada e saída do python: input e
print.

4.1 Entrada de Dados


Em Python, a leitura de dados do teclado é feita através da função input(), onde se pode
colocar um texto. O print() escreve na saída.

Ler duas variáveis a e b do tipo int e imprimir a sua soma. Uma leitura em Python com o
comando input() retorna uma string, por exemplo '12' que pode ser convertido em 12 pela
função int('12'). Assim o programa fica como:

a=int(input('Digite a:'))
b=int(input('Digite b:'))
ab=a+b
print('a+b=',ab)

Vamos agora ler uma velocidade e uma distância e imprimir o tempo necessário para
percorrer a distância.

velo=int(input('Velocidade km/hora:'))
dist=int(input('Distância km :'))
tempo = dist/velo
print('para percorrer %d km numa vel %d km/h precisa %5.2f horas'
% (dist, velo, tempo))
>>>
© E.L.Favero Algoritmos em Python 34

Distância km :500
Velocidade km/hora:70
para percorrer 500 km numa vel 70 km/h precisa 7.14 horas

4.2 Leitura de Float


Toda leitura lê um string, para converter o string para float usa-se a função float(). Como
segue. De forma similar foi exemplificado acima para int.

velo=float(input('Velocidade km/hora:'))
dist=float(input('Distância km :'))
tempo = dist/velo
print('para percorrer %d km numa vel %d km/h precisa %5.2f horas'
% (dist, velo, tempo))

4.3 Leitura de strings


Toda leitura lê um string, portanto não precisa conversão.

nome=input('digite o Nome:')
print('O nome lido foi: ', nome)

4.4 Lista de exercícios (11)


E4.1 Ler um nome e escreve-lo capitalizado. Aqui, na solução usamos a variável nome
diferente de Nome.

nome=input('digite o nome:')
Nome=nome.capitalize()
print(nome, Nome)
>>>
digite o nome:claudio
claudio Claudio

E4.2 Ler um nome e escreve-lo capitalizado. Aqui, na solução usamos as variáveis a e


b.

a=input('digite o nome:')
b=a.capitalize()
print(a, b)
>>>
digite o nome:claudio
claudio Claudio

E4.3 Ler um nome e escreve-lo todo em caixa alta.

E4.4 Ler nome, identidade, cpf. Imprimir os dados lidos, um em cada linha.

E4.5 Ler um nome tipo “Paulo dos santos dos deuses”. Usando Split quebre no ‘dos’ em
três partes.

b= input('digite o nome:')
© E.L.Favero Algoritmos em Python 35

print(b.split('dos'))
>>>
digite o nome: Paulo dos santos dos deuses
['Paulo ', ' santos ', ' deuses']

E4.6 Ler um nome e escrever ele e seu comprimento, use len().

E4.7 Sejam as cotações a) Dólar Turismo R$ 5,6000; b) Euro R$ 6,20; c) Libra R$


6,9769 Peso Argentino d) R$ 0,0710; e) Bitcoin 10,4200. Isto é, para comprar 1
Dolar preciso pagar 5,6 reais e assim por diante. Leia um valor em real e converta
o mesmo para as 5 moedas, imprimindo o valor em real e o correspondente em
cada uma das moedas, caso fosse cambiar o real por uma das moedas.

E4.8 Ler um salário (sal). Dar um aumento de 20%. Qual o valor do aumento e do novo
salário.

sal=int(input(' digite o sal:'))


percent=20
aumento=sal*percent/100
novosal=sal+aumento
print('sal:', sal, 'aumento:',aumento, 'novosal:', novosal)
>>>
digite o sal:2000
sal: 2000 aumento: 400.0 novosal: 2400.0

E4.9 Ler um salário (sal). Dar um aumento de 2%. Qual o valor do sal, do aumento e do
novo salário.

E4.10 Considere a fórmula: C/5 = (F-32)/9 para conversão de temperatura. Programe a


conversão de Celsius para Fahrenheit. Leia um valor em Celsius e escreva o
correspondente em Fahrenheit.

E4.11 Considere que uma polegada é 2,54cm. Leia um valor em cm e escreva o


correspondente em polegadas.
© E.L.Favero Algoritmos em Python 36

Capítulo
5 EXPRESSÕES LÓGICAS
Este capítulo apresenta as expressões lógicas como uma preparação para vermos os
comandos condicionais e de repetição. São apresentadas as tabelas verdade para os
operadores lógicos: and, or, not. São apresentadas as expressões relacionais de
igualdade, desigualdade e pertinência.

5.1.1 Tipo BOOL


O nome Bool vem de George Boole (1815-1864), matemático inglês, criador da
"Álgebra Booleana" de onde vem a lógica proposicional ou boleana, a lógica das tabelas
verdade. A lógica do pensamento humano. Sempre utilizamos frases em linguagem natural
com (e), (ou) e (não).
Por exemplo, se dizemos “compre alho e cebola”. Neste caso queremos dizer
“compre alho e também cebola”.
Se dizemos “tempere com sal ou com açúcar”. Queremos dizer “tempere com um
dos dois: ou sal, ou açúcar”.
Podemos fazer frases em linguagem natural com vários conectivos lógicos: “vamos
pescar se faz sol e não venta ou se chove e está quente”. Aqui temos quatro conectivos
lógicos: e, não, ou, e.
O tipo lógico bool é uma especialização do tipo int. Os valores do tipo bool são:
True (int diferente de 0) e False (int igual a 0). True é verdadeiro e False é falso. CUIDADO
True é com T maiúsculo e False é com F maiúsculo, senão dá erro. bool() é a função que
converte inteiro para Bool.

>>> bool(1)
True
>>> bool(-10)
True
>>> bool(10)
True
>>> bool(0)
False
>>> a=True
>>> a and bool(2)
True
>>> True + 1
2
>>> False + 1
1
© E.L.Favero Algoritmos em Python 37

>>> True + True + False


2
>>> true+1
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module> true+1
NameError: name 'true' is not defined
>>>
>>> Bool(0)
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module> Bool(0)
NameError: name 'Bool' is not defined

5.2 Operadores lógicos


Estes três operadores básicos da lógica da linguagem natural (não, e, ou) são transportados
para o pensamento computacional com os operadores lógicos: and, or, not.

Operadores Lógicos
not and or

Estes três operadores podem ser combinados para fazer expressões lógica complexas,
seguem alguns exemplos.

>>> True and False


False
>>> True and True
True
>>> True and True and not True
False
>>> True or False and True
True
>>>

5.2.1 Tabelas Verdade


Podemos também imprimir uma tabela verdade para cada um dos operadores. O not é um
operador unário, só tem um operando. Vamos apresentar um pseudo código para imprimir a
tabela verdade do not.

Tabela Verdade not:

not True = False


not False = True

Em pseudo-código (código que não executa):


escreva('Tabela Verdade not:')
© E.L.Favero Algoritmos em Python 38

VF = [v-verdadeiro, f-falso]
para i in VF:
escreva('not', i, '=', not i)

>>>
Tabela Verdade not:
not True = False
not False = True

O pseudo código serve como uma notação informal para representar algoritmos, baseado
numa linguagem próxima da linguagem natural. Este pseudo código pode ser traduzido
para uma lingugem de programação que para nós é Python.

Em Python:
print('Tabela Verdade not:')
TF = [True, False]
for i in TF:
print( 'not', i,'=', not i)
>>>

Tabela Verdade not:


not True = False
not False = True

Tabela Verdade and:

True and True = True


True and False = False
False and True = False
False and False = False

O and é um operador binário, ocorre entre dois operandos. O and é sempre False exceto
quando o valor dos dois operandos for True então neste caso o valor dele também é True.

print('Tabela Verdade and:')


TF = [True, False]
for a in TF:
for b in TF:
print( a,'and', b, '=', a and b)
>>>
Tabela Verdade and:
True and True = True
True and False = False
False and True = False
False and False = False
© E.L.Favero Algoritmos em Python 39

Tabela Verdade or:

True and True = True


True and False = True
False and True = True
False and False = False

O or é sempre True exceto quando o valor dos dois operandos for False então neste caso o
valor dele também é False.

print('Tabela Verdade or:')


TF = [True, False]
for a in TF:
for b in TF:
print( a,'and', b, '=', a or b)
>>>
Tabela Verdade or:
True and True = True
True and False = True
False and True = True
False and False = False

5.2.2 Prioridade na parentização implícita


Se temos uma expressão “not A and B or C”, como ela será avaliada? Por exemplo,
se A=False; B= True; C=True. Parentização correta é ((not A) and B) or C. Primeiro
o not, depois o and e depois o or, nesta ordem. Fazendo um paralelo com a
aritmética, -A*B+C é parentizado de forma similar((-A)*B)+C. Se for B+C* -A será
parentizada B+(C*(-A)). Assim, B or C and not A fica B or (C and (not A)).

>>> A=False; B= True; C=True


>>> not A and B or C
True
>>> not (A and B or C)
False
>>> (not A) and (B or C)
True
>>> ((not A) and B) or C
True

5.3 Expressões Relacionais


Temos 3 tipos de operadores relacionais: de igualdade, de desilgualdades e de pertinência.

Igualdade Desigualdade Pertinência


© E.L.Favero Algoritmos em Python 40

== != > < >= <= in in not

5.3.1 Operadores relacionais: quando o igual não é igual


Os operadores lógicos normalmente são combinados em expressões com operadores
relacionais, operadores que comparam valores, como o maior, menor e igual, etc. > < == !=
<= >=. Muitas linguagens de programação usam o sinal de igual = para atribuição e == para
teste de igualde. Porque a atribuição é utilizada com muita mais frequência que o teste de
igualdade.
Se fizermos a=1;b=2;a=b. O comando a=b não é teste de igualdade: o valor de a é
substituído pelo valor de b.
Aqui o (;) é um separador de comandos, quando mais de um comando são escritos
na mesma linha.
O diferente é o não igual, representado pelo ponto de exclamação na frente do igual.
Assim, == e != ambos tem dois caracteres, assim ficam símbolos mais similares, no
tamanho.

>>> a=1;b=2
>>> a==b
False
>>> a==1
True
>>> a==2
False
>>> a!=2
True

5.3.2 Prioridade dos tipos de operadores


Na expressão materia1>7 and materia2>7 and materia3>7 temos operadores relacionais e
lógicos. Neste caso os operadores relacionais tem prioridade, são executas antes dos
lógicos. Então esta expressão com os parênteses fica: (materia1>7) and (materia2>7) and
(materia3>7). Se temos operadores aritméticos e relacionais, por exemplo, em x+7>4 os
operadores aritméticos tem prioridade então com parênteses fica: (x+7)>4.

>>> materia1=8;materia2=9;materia3=9.5
>>> materia1>7 and materia2>7 and materia3>7
True
>>> (materia1>7) and (materia2>7) and (materia3>7)
True
>>> x=3
>>> x+7>4
True
>>> (x+7)>4
True

Os operadores de comparação ou relacionais são parentes dos aritméticos. Os aritméticos


sempre retornam um valor numérico e os relacionais sempre retornam um valor Lógico.
Seguem alguns exemplos, de expressões agrupadas num código de programa.

a=4;b=2;c=10;d=5;f=4
© E.L.Favero Algoritmos em Python 41

print('a==c',a==c)
print('a<b' ,a<b)
print('d>b', d>b)
print('c!=f', c!=f)
print('a==b',a==b)
print('c<d',c<d)
print('b>a',b>a)
print('c>=f',c>=f)
print('f>=c',f>=c)
print('c<=c',c<=c)
print('c<=f',c<=f)
>>>

5.3.3 Lista de exercícios (8)


E5.1 Seja uma variável sal=900. Crie uma variável lógica que é verdadeira se
sal>1000. Imprima o valor da variável.

sal=900
salMaiorMil=sal>1000
print('maior que mil: ', salMaiorMil)
>>>
maior que mil: False
E5.2 Seja uma variável sal=2000. Crie uma variável lógica que é verdadeira se
sal>1000. Imprima o valor da variável.

sal=2000
salMaiorMil=sal>1000
print(salMaiorMil)
>>>
True
E5.3 Crie uma variável aprovado que é verdadeira se todas as três matérias
(materia1, materia2 e materia3) são maiores que 7. Inicialize as variáveis
com valor maior que sete.

materia1=8;materia2=9;matateria3=9.5
aprovado=materia1>7 and materia2>7 and materia3>7
print(aprovado)
>>>
True
E5.4 Crie uma variável aprovado que é verdadeira se todas as três matérias
(materia1, materia2 e materia3) são maiores que 7. Inicialize uma das
matérias com valor 6 e as outras com valor > 7. Escreva o valor da variável
aprovado.

materia1=6;materia2=9;matateria3=9.5
aprovado=materia1>7 and materia2>7 and materia3>7
print(aprovado)
>>>
False
E5.5 Seja a atribuição múltipla: A,B,C,D=1,2,True,False. Mostre o valor da
expressão 'A>B and C or D'
© E.L.Favero Algoritmos em Python 42

A,B,C,D=1,2,True,False
print('A>B and C or D =', A>B and C or D)
>>>
A>B and C or D = False
E5.6 Seja a atribuição múltipla: A,B,C,D=10,3,False,False. Mostre o valor da
expressão 'A>B and C or D'

A,B,C,D=10,3,False,False
print('A>B and C or D =', A>B and C or D)
>>>
A>B and C or D = False
E5.7 Seja a atribuição múltipla: A,B,C,D=5,1,True,True. Mostre o valor da
expressão 'A>B and C or D'

A,B,C,D=5,1,True,True
print('A>B and C or D =', A>B and C or D)
>>>
A>B and C or D = True
E5.8 Seja a atribuição múltipla: A,B,C,D=5,1,True,True. Mostre o valor da
expressão 'A>B and C or D'

A,B,C,D=5,1,True,True
print('A>B and C or D =', A>B and C or D)
>>>
A>B and C or D = True

5.3.4 Perguntas conceituais (8)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C5.1 Quais são os três principais operadores lógicos?
C5.2 O que retorna uma expressão lógica?
C5.3 Qual a diferença = e ==?
C5.4 Qual a diferença de um operador de igualdade e de desigualdade?
C5.5 Quais são os operadores de igualdade?
C5.6 Quais são os operadores de desigualdade?
C5.7 Quais são os operadores de pertinência?
C5.8 O que é um operador relacional?
© E.L.Favero Algoritmos em Python 43

Capítulo

6 COMANDOS DE DECISÃO (IF)

Neste capítulo apresentamos os comandos de decisão que permitem fazer


escolhas condicionais sobre a execução de blocos de comandos. São
variações sobre o comando if/elif/else. Fluxogramas dos comandos
condicionais. Pseudo código de comandos condicionais.

Diagramas: a) um comando if b) vários comandos ifs em cascata


simples

A figura acima ilustra dois fluxogramas do comando if. Um fluxograma representa um fluxo
de execução da sequência de passos de um comando. Um comando if simples, executa
© E.L.Favero Algoritmos em Python 44

condicionamente o bloco, isto é, se a condição for verdadeira então o bloco é executado,


caso contrário ele não é executado. Quando temos ifs em cascata, todos os blocos com a
condição verdadeira são executados.

6.1 Comando IF
Em Python temos vários usos do comando if/elif/else. Vamos ler um valor e dizer se é
negativo, positivo ou igual a zero. Vamos usar três vezes o if simples, que resulta num if em
cascata. Note que, no código executável, após a leitura do input() o valor é convertido para
inteiro int().

Pseudo código comando se então:

x=ler('Digite x:')
se x>0 então: escreva(x, 'é positivo')
se x==0 então: escreva(x, 'é zero')
se x<0 então: escreva(x, 'é negativo')

x=int(input('Digite x:'))
if x>0: print(x, 'é positivo')
if x==0: print(x, 'é zero')
if x<0: print(x, 'é negativo')
>>>
Digite x:1
1 é positivo

Estes ifs estão em cascata, assim mais de um comando poderia ser executado. Todas as
condições são testadas. Mas os três testes são mutualmente exclusivos, se um é verdade
os outros dois não são. Então só um deles é executado. Este mesmo código pode ser
escrito com if/elif, podem ser vários else/if=elif.

Pseudo código comando se então senão_se:

x=ler('Digite x:'))
se x>0 então: escreva(x, 'é positivo')
senão_se x==0 então: escreva(x, 'é zero')
senão_se x<0 então: escreva(x, 'é negativo')

x=int(input('Digite x:'))
if x>0: print(x, 'é positivo')
elif x==0: print(x, 'é zero')
elif x<0: print(x, 'é negativo')

A diferença desta versão para a versão em cascata é que aqui os testes são executados
somente até o primeira condição ser verdadeira. Quando um if ou um elif for verdadeiro
todos os que vem depois não são mais testados.
© E.L.Favero Algoritmos em Python 45

6.2 Comandos IF ELSE, aninhados

Fluxograma do comando if / else

O fluxograma do comando if/else executa uma ação quando a condição é verdadeia e outra
ação quando a condição é falsa.

Pseudo código comando se então senão

x=ler('Digite x:'))
se x>=0
então: escreva(x, 'é positivo')
senão: escreva(x, 'é negativo)

x=int(input('Digite x:'))
if x>=0: print(x, 'é positivo')
else: print(x, 'é negativo')

Novamente, codificamos o mesmo algoritmo anterior, agora com dois if/else aninhados. Por
aninhado entende-se um dentro do doutro. Note que não se pode escrever dois ifs na
mesma linha. O segundo tem que ser indentado dentro do bloco do else. Um bloco é uma
sequência de um ou mais comandos como uma unidade, dentro de uma indentação
(vertical) ou dentro de uma linha (horizontal) sequênciados pelo ponto e virgula.

x=int(input('Digite x:'))
if x>0: print(x, 'é positivo')
else:
if x==0: print(x, 'é zero')
else : print(x, 'é negativo')

Suponhamos agora uma conta de celular com diferentes taxas por minuto conforme o
consumo total. Se o usuário aumenta o número de minutos consumidos o valor por minuto
baixa, caindo numa faixa de valor por minuto mais baixa que vale para a conta toda.

min=int(input('digite o numero de minutos:'))


© E.L.Favero Algoritmos em Python 46

if min>400: preco=0.18
elif min>200: preco=0.20
elif min>100: preco=0.25
else: preco=0.30
print('minutos consumidos:',min)
print('preço por minutos :',preco)
print('valor total :',preco*min)

6.3 IFs mais complexos


Supondo que queremos formar uma conta de energia diferenciando os clientes em
industriais, comerciais e residenciais, cada um com tarifas diferenciadas, inclusive variando
por faixa de consumo.

Ind Acima de 10000kw preço 0.60


Abaixo/inclusive 10000kw preço 0.40
Com Acima de 5000kw preço 0.70
Abaixo/inclusive 5000kw preço 0.50
Res Acima de 500kw preço 0.80
Abaixo/inclusive de 500kw acima de 200Kw preço 0.60
Abaixo/inclusive de 200kw preço 0.40

Interpretando esta tabela, vamos considerar que a tarifa baixa é para o valor Kw consumido
dentro daquela faixa. Por exemplo, para um cliente residencial o consumo de 400Kw ele
pagará 200 a 0.40 e 200 a 0.60, que resultará em 200,00.

kw=int(input('quantos Kwh:'))
tipo= input(' tipo conta:')
if tipo not in ['r','i','c']:
print('tipo de conta Invalido:',tipo);
exit(1)
if tipo=='c':
if kw >= 5000: preço = (kw-5000)*0.80 + 5000*0.50
else: preço = kw*0.50
if tipo=='i':
if kw >= 10000: preço=(kw-10000)*0.60 + 10000 * 0.40
else: preço=kw*0.40
if tipo=='r':
if kw >= 5000: preço = (kw-500)*0.70 + 300*0.60 + 200*0.40
elif kw >= 200: preço = (kw-200)*0.60+ 200*0.40
else: preço = kw*0.40
print('pagar para %d valor = %5.2f' % (kw,preço))
>>>
quantos Kwh:400
tipo conta:r
pagar para 400 valor = 200.00

Aqui temos mais algumas construções: o exit(1), sair(1), termina o programa. A expressão
tipo not in ['r','i','c'] checa se o tipo não é uma das três letras válidas; “not in” significa não
pertence.
© E.L.Favero Algoritmos em Python 47

6.3.1 Exercícios (8)


E6.1 Ler A, B, C inteiros e imprimir o maior (pode ter mais de um maior).

a=int(input(' A:'));b=int(input(' B:'));c=int(input(' C:'))


if a>=b and a>=c:
print('o maior é a:', a)
if b>=a and b>=c:
print('o maior é b:', b)
if c>=a and c>=b:
print('o maior é c:', c)
>>>
A:3
B:7
C:1
o maior é b: 7

E6.2 Ler um valor de salário, sal, e se for maior que 1000 dar um aumento de 10% senão
dar um aumento de 15%. Imprimir o valor do salário, do aumento e o novo salário.

sal=float(input('sal:'))
if sal>1000:
percent=0.10
else:
percent=0.15
aumento=percent*sal
novoSal=sal+aumento
print('sal atual: R$%6.2f' % sal)
print(' aumento: R$%6.2f' % aumento)
print('novo sal : R$%6.2f' % novoSal)
>>>

E6.3 Calcular o imposto de um valor de salário lido, considerando:


se valor >3000: imposto = 25%
se valor >2000: imposto = 20%
se valor >1000: imposto = 10%
senao: imposto = 5%
Imprimir valor do salário, valor do imposto e salário liquido.

E6.4 Leia duas variáveis a, b. Leia o operador aritmético:{+,-,*, /}. Calcule o resultado da
operação. Se o operador não existir exiba operador inválido.

a=float(input('a:'))
b=float(input('b:'))
oper=input('o:')
if oper=='+':val=a+b
elif oper=='-':val=a-b
elif oper=='*':val=a*b
elif oper=='/':val=a/b
elif oper=='^':val=a**b
else:
print('operação invalida (+,-,*,/,^)')
exit
print('o valor de %5.2f %s %5.2f = %5.2f' % (a,oper,b,val))
© E.L.Favero Algoritmos em Python 48

>>>
a:3
b:7
o:+
o valor de 3.00 + 7.00 = 10.00

E6.5 Ler os minutos, min, da conta de celular. Se min for menor que 200 o preço é 0.20
de real; senão se min < 400, o preço é 0.18 ao min; senão o preço é 0.15 ao min;
imprima o valor da conta. Um só valor por minuto para toda a conta.

min=int(input('quantos min cel:'))


if min<200:
preco=0.20
elif min<400:
preco=0.18
else:
preco = 0.15
print('pagar R$ %6.2f' % (preco*min))

E6.6 Ler o número de km percorridos e calcular a conta do Uber. Considere 90 centavos


por km, mas a partir dos 100 km o valor por km diminui para 70 centavos (para todo
percurso).

E6.7 Seja as cotações:


a) Dólar Turismo R$ 5,6000;
b) Euro R$ 6,20;
c) Libra R$ 6,9769
d) Peso Argentino R$ 0,0710;
e) Bitcoin 10,4200.
Isto é, para comprar 1 Dolar preciso pagar 5,6 reais e assim por diante.
Leia um caracter (a..e) e um valor em real. Imprima o valor correspondente a
compra na moeda estrangeira.

E6.8 Leia a,b,c três valores inteiros e imprima o intermediário. Se os três são diferentes
então temos menor, intermediário e maior. Podemos ter situações com valores
iguais, então o intermediário pode ser igual a valores das pontas.

6.3.2 Perguntas conceituais (3)

Responda com no mínimo 10 palavras e no máximo 20 palavras:


C6.1 Para que serve a combinação if/else?
C6.2 Para que serve a combinação if/elif ?
C6.3 Qual a diferença entre else e elif ?
© E.L.Favero Algoritmos em Python 49

Capítulo

7 RE-FATORANDO O CÓDIGO
Apresentamos o conceito de abstração, uso de funções, para organizar e
refatorar o código dos programas. Por fim, apresentamos uma discussão do
pensamento computacional sobre um kit mínimo de comandos necessários
na programação.

7.1 Refatorando o código


Refatorar o código é reescrevê-lo de forma que ele ainda executa o mesmo
comportamento, tenha o mesmo efeito, mas onde o código esteja escrito de uma forma mais
simples, mais elegante, mais fácil de ler e compreender. No capítulo anterior, o programa
que diz se é positivo, zero ou negativo foi reescrito de várias formas, qual é a melhor
versão? Eh possível encontrar outra forma de escrita melhor?

Duas figura geométricas: um círculo e um quadrado

Sejam as duas figuras geométricas acima. Qual das duas é mais silenciosa? Figura
tem barulho? Tem. Pense um pouco e encontre uma resposta. Até quando refatorar um
código? Até ele ficar silencioso.

Vamos fazer um programa que lê duas variáveis int e mostra o valor da maior delas
(maior ou igual). Se forem iguais mostre uma delas.

#Ler dois valores e dizer qual é menor


x=int(input('digite x:'))
y=int(input('digite y:'))
print('valor lidos :',x, y)
if x<y:
© E.L.Favero Algoritmos em Python 50

print('o menor é x:',x)


elif y<x:
print('o menor é y:',y)
else:
print('eles são iguais:',y)

Para dificultar mais, agora vamos fazer o mesmo com 3 valores. Ler os 3 valores e dizer
quem é o menor.

#Ler 3 valores e dizer qual é menor


x=int(input('digite x:'))
y=int(input('digite y:'))
z=int(input('digite z:'))
print('valor lidos :',x, y,z)
if x<y and x<z:
print('o menor é x:',x)
elif y<x and y<z:
print('o menor é y:',y)
elif z<x and z<y:
print('o menor é z:',z)
else:
print('não tem só um mínimo:')

7.2 Refatorando com funções


Agora para refatorar estes códigos de escolha do menor, vamos introduzir o conceito de
abstração. Uma função é uma abstração, dar um nome a um pedaço de código. Já
introduzimos o conceito de função, já usamos algumas, mas como definir nossas próprias
funções?
Uma função delimita um bloco de comandos, iniciando com a palavra def(ine)
seguido de (), com ou sem parâmetros. No exemplo abaixo, em mini(a,b) entram as
variáveis a,b e sai ou a ou b, o menor deles. A saída é marcada por return (retorna).

def mini(a,b):
if a<b: return a
else : return b

Para usar esta função apresentamos abaixo um programa que le dois valores e chama a
função mini() para escolher o menor. Def define a função que é chamada neste caso dentro
de um comando de atribuição.

#ler dois valores e dizer quem é o menor


x=int(input('digite x:'))
y=int(input('digite y:'))
print('valores lidos :',x, y)
def mini(a,b):
if a<b: return a
else : return b
m=mini(x,y) # chama a função
print('o menor é:',m)
© E.L.Favero Algoritmos em Python 51

Quanto a escrita do código podemos mudar a posição da função, podemos trazer definição
dela no inicio do código, antes da leitura dos valores, como segue.

#ler dois valores e dizer quem é o menor


def mini(a,b):
if a<b: return a
else : return b
x=int(input('digite x:'))
y=int(input('digite y:'))
print('valores lidos :',x, y)
m=mini(x,y) # chama a função
print('o menor é:',m)

No cabeçalho da função entram os parâmetros, mini(a,b): a e b são dois parâmetros. Em


cada função deve existir um valor de saída que vem depois da palavra return. Tudo o que
está indentado dentro da função é o seu corpo. Assim a função tem nome, parâmetros de
entrada, comando(s) de saída e seu corpo. Segue mais um exemplo, agora vamos ler 3
valores e dizer quem é o menor dos três.

#ler três valores e dizer quem é o menor


def mini(a,b):
if a<b: return a
else : return b
x=int(input('digite x:'))
y=int(input('digite y:'))
z=int(input('digite z:'))
print('valor lidos :',x, y, z)
m=mini(x,y)
m=mini(m,z)
print('o(um) menor é:',m)

Utilizamos 2 linhas, uma para cada chamada, para definir quem é o valor mínimo, mas
poderíamos ter usado uma versão do print mais complexa, com menos linhas:
m=mini(mini(x,y),z). Aqui a função mini() está sendo reusada duas vezes, uma dentro da
outra. Uma das grandes vitórias do pensamento computacional é o reuso de fragmentos de
código, pois com isso os códigos ficam mais compactos, mais coesos e mais simples.
Até quando refatorar? Até que o código tende a ser silencioso. O barulho acontece
na mente. A mente humana divide um objeto maior em objetos menores para conquista-los.
Se tenho um quadrado posso dividir em 4 retas, uma reta é um objeto menor, duas verticais
e duas horizontais, etc. Estes pensamentos de dividir são o barulho: a mente ta tagarelando.
Se tenho um círculo, se corto pela metade ficam dois objetos geométricos mais complexos
que o próprio círculo. Então não posso mais dividir: o circulo já é o limite, já é o silencio das
operações mentais. Quais versões dos códigos são mais silenciosas as que usam funções
ou as sem o uso de funções?

7.3 Pensamento computacional: refatorando com funções


No percorrer do texto, vimos vários conceitos de programação. Vamos nos aprofundar e
familiarizar com eles aos poucos. Muitos assuntos são apenas introduzidos para mais
adiante serem mais detalhados. Consideramos uma abordagem do geral para o específico,
sendo que a cada capítulo novos conceitos são introduzidos e ou antigos conceitos são
mais detalhados.
Iniciamos com variáveis e expressões; depois vimos o comando de atribuição. Numa
linha de comandos podemos encadear vários comandos de atribuição numa sequência (ex.
© E.L.Favero Algoritmos em Python 52

a=1;b=3+a;x=1+b;print(x) ), onde um é executado depois do outro em uma sequência,


conforme a ordem de leitura. A sequência de comandos também pode seguir a ordem de
leitura de cima para baixo.
Para compor o kit de ferramentas de pensamento computacional, de pensamento de
algoritmos, vamos precisar de mais alguns elementos. Na tabela abaixo apresentamos um
kit mínimo, começando por variáveis, comandos de atribuição, comandos de sequência,
comandos de entrada e saída, comandos condicionais, comandos de repetição e comandos
de abstração.
Vamos nos aprofundar nos comandos de repetição no próximo capítulo. Já
apresentamos as funções como uma forma para organizar os códigos através do conceito
de abstração, dar nome para um grupo de comandos.

Estruturados Tipos de comandos Exemplos


Verticais 1-Variáveis, objetos e expressões a=1;
e/ou 2-Comando de atribuição c=[1,2,5,9]
horizontais 3-Sequência de comandos a=1;b=3+a;x=1+b;print(x)
4-Comandos de entrada e saida input() print()
Só verticais, 5-Comando condicional if,
só pela elif,
indentação else:
6-Comandos de repetição for,
while
7-Conceitos de abstração def

Esta tabela apresenta os tipos de comandos necessários para codificação de qualquer


algoritmo em Python. Os primeiros 4 tipos podem ser estruturados verticalmente ou
horizontalmente, mas os 3 últimos só verticalmente pela indentação.

7.3.1 Exercícios (2)


E7.1 Faça a função maxi() que retorna o máximo de dois valores. Similar a função mini().
E7.2 Usando maxi() leia a,b,c,d encontre o máximo dos 4 valores.

7.3.2 Perguntas conceituais (6)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C7.1 O que é bloco de comandos?
C7.2 Qual é o papel da indentação?
C7.3 Quais são os tipos de comandos estruturados pela indentação?
C7.4 Quais os comandos que podem ser programados numa sequência horizontal dentro
de uma mesma linha?
C7.5 O que é refatorar código?
C7.6 O que é reuso de código?
© E.L.Favero Algoritmos em Python 53

Capítulo
8 TIPO LISTA, TUPLA E FAIXA DE
VALORES

Neste capítulo apresentamos listas e tuplas. São os objetos computacionais que estão
associados a estruturas de dados para representação da repetição de elementos
como vetores da matemática. Mostramos o comando chamado “for” para percorrer as
listas. São introduzidos os conceitos de índices positivos, para caminhar para frente e
índices negativos, para caminhar para trás.

8.1 Listas

lista= ['a', 'b', 'c', 'd', 'e', 'f', 'g']


índice 0 1 2 3 4 5 6
índice (-) -7 -6 -5 -4 -3 -2 -1

Uma lista é um conjunto de valores indexados por um número inteiro chamado de índice,
que se inicia em zero. Os elementos contidos em uma lista podem ser de qualquer tipo, até
mesmo outras listas, e não precisam ser todos do mesmo tipo. len() retorna o tamanho da
lista.

>>>lista= ['a','b','c','d','e','f'
>>>len(lista)
7
>>>lista = [1, 2, 3]
>>>len(lista)
3

O índice permite acesso individual aos elementos, bem como permite trabalhar com as
fatias. Com índices negativos caminhamos na lista de trás para frente, onde -1, -2 são o
índice do último e penúltimo elementos.

>>> lista=[5,10,15]
>>> lista[0]
5
>>> lista[1]
10
>>> lista[-1]
© E.L.Favero Algoritmos em Python 54

15

8.2 Índices e fatiamento


Range(), faixa, intervalo é uma função iterável, que cria um intervalo. A sintaxe é
range(stop) ou range([star],stop, step). Isto é, início, fim e passo. Importante: no range() o
intevalo é sempre aberto no final. Se for até 10 na verdade o 10 é excluído, vai só até 9.
list(range()) força o desenrolar do objeto iterável dentro de uma lista.

Faixa de valores, intervalo

range(início, fim, passo)


range(início, fim)
range(fim)

>>>range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
list(range(10,0,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> list(range(0,10,2))
[0, 2, 4, 6, 8]

>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(2,10))
[2, 3, 4, 5, 6, 7, 8, 9]
>>> list(range(2,10,2)) # só pares
[2, 4, 6, 8]
>>>list(range(1,10,2)) # só impares
[1, 3, 5, 7, 9]

Fatias são segmentos de sublistas. O segmento é acessado por uma faixa de valores.
Numa lista podemos escrever: lista[início:fim]. Como em range(), do início até o fim,
exclusive o fim. :2 denota, 0:2, então é 0 e o 1. Quando não diz o inico é zero. Quando não
diz o fim é até o último, ex. 1:, é tudo a partir do 1.

>>> lista=[5,10,15]
>>> lista[:2]
[5, 10]
>>> lista[1:]
[10, 15]

>>>lista= ['a','b','c','d','e','f','g']
>>>lista[1:4]
['b','c','d']
>>>lista[-6:-3]
['b','c','d']
© E.L.Favero Algoritmos em Python 55

8.3 Acrescentar e remover elementos


Para modificar uma lista podemos atribuir valores para elementos indexados, podemos
acrescentar elementos no fim e ou podemos remover elementos. A função append()
acrescenta um elemento no final da lista; a função remove() tira um item de uma lista.

append anexe
remove remove

>>> lista=[5,10,15]
>>> lista[2]=11
>>> lista.append(20)
>>> lista
[5, 10, 11, 20]
>>> lista.remove(10)
>>> lista
[5, 11, 20]

8.4 Comando for para percorrer listas

Para i em [2, 4, 88, 100]: escreva(i)

For i in [2, 4, 88, 100]: print(i)

Listas são facilmente percorridas com o comando for. A primeira forma é ver a lista como um
conjunto e com o operador in (pertence) os elementos são acessados: elemento in lista. O
end=' ' dentro do print() diz para colocar um branco depois de cada impressão.

>>>lista = [1, 2, 3]
>>>for i in lista: print(i, end=' ')
1 2 3

A segunda forma de acessar os elementos e a partir de seus índices, extraídos de uma faixa
de valores, range(), que também é como uma lista de indices. Sempre use len(lista) para
definir o fim da lista.

>>>lista = [1, 2, 3]
>>>for i in range(len(lista)): print(lista[i], end=' ')
1 2 3

Estes comandos de linha também podem ser agrupados num programa como ilustrado
abaixo. O print() vazio envia o cursor para a próxima linha.

lista = [1, 2, 3]
for i in lista: print(i, end=',')
print()
for i in range(len(lista)): print(lista[i], end=' ')
>>>
1,2,3,
© E.L.Favero Algoritmos em Python 56

1 2 3

8.5 Tuplas

tupla= ('a', 'b', 'c', 'd', 'e', 'f', 'g')


índice 0 1 2 3 4 5 6
Índice (-) -7 -6 -5 -4 -3 -2 -1

O tipo tupla é similar a uma lista, mas é imutável, não podemos mudar o valor de seus
elementos. Sintaticamente, uma tupla é similar a uma lista de valores separados por
vírgulas, mas a tupla é delimitada por parênteses. Na tupla, o acesso aos elementos e o
fatiamento segue a mesma sintaxe da lista.

>>>tupla= ('a','b','c', 'd','e','f','g')


>>>len(tupla)
7
>>>tupla[1:4]
('b','c','d')
>>>tupla[-6:-3]
('b','c','d')

>>>tupla = [1, 2, 3]
>>>len(tupla)
3

>>> tupla1=(20,40,60)
>>> for t in tupla1: print(t, end=' ')
20 40 60

Também o commando for permite percorrer uma tupla, usando a mesma notação que
apresentamos para listas.

Pensamento computacional dos tipos mutáveis e imutáveis. Vimos 3 tipos compostos:


strings, que são compostos de caracteres; listas e tuplas, que são compostas de elementos
de qualquer tipo. Uma das diferenças entre strings e listas é que os elementos de uma lista
podem ser modificados, mas os caracteres em uma string não; tuplas também não podem
ser modificadas. Em outras palavras, strings e tuplas são imutáveis e listas são mutáveis.

>>> tupla1=(20,40,60)
>>> tupla1[2]=0
TypeError: 'tuple' object does not support item assignment

>>> str='abc'
>>> str[1]='B'
TypeError: 'str' object does not support item assignment

8.5.1 Lista de exercícios (9)


E8.1 Usando range() defina uma lista com os valores de 80 até 100.
>>> list(range(80,100))
© E.L.Favero Algoritmos em Python 57

[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99]
E8.2 Usando range() defina uma lista com os valores de 80 até 100, inclusive os
extremos.
>>> list(range(80,101))
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
95, 96, 97, 98, 99, 100]
E8.3 Usando range() defina uma lista com os valores de 100 até 80, inclusive os
extremos, em ordem decrescente.

E8.4 Usando range() defina uma lista com os valores de 80 até 100, só os valores
pares.

E8.5 Usando range() defina uma lista com os valores de 80 até 100, só os valores
impares.

E8.6 Usando range() defina uma lista com os valores de 80 até 100, só os valores
pares. E usando um comando for imprima a lista gerada por range().

E8.7 Usando range() defina uma lista com os valores de 80 até 100, só os valores
impares. E usando um comando for imprima a lista gerada por range().

E8.8 Ler um número e imprimir todos os pares até o número lido. Use o comando for.
x=int(input('dig X:'))
for i in range(0,x+1,2):
print(i, end=' ')
print()
>>>

E8.9 Ler um número e imprimir todos os impares até o número lido. Use o comando for.

8.5.2 Perguntas conceituais (5)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C9.1 Qual a diferença de lista para tupla?
C9.2 O que é uma range()?
C9.3 Qual a diferença entre uma fatia e uma faixa de valores?
C9.4 O que é um índice positivo?
C9.5 O que é um índice negativo?
© E.L.Favero Algoritmos em Python 58

Capítulo
9 COMANDO DE REPETIÇÃO: FOR

Este capítulo aprofunda o estudo do comando for, que é um comando de repetição.


Este comando foi introduzido no capítulo sobre listas. Este comando está fortemente
associado a função range() e ao caminhamento sobre listas. Novos conceitos:
compreensão de listas; somar e contar com o for; comandos break e o continue.
Vamos aprender a ler uma lista de valores digitados como uma string.

9.1 O comando FOR


Já introduzimos o comando for parcorrer listas e tuplas. Neste item vamos aprofundar o
estudo do comando for. Ele permite percorrer qualquer objeto iterável. Além disso, vamos
ver os comandos break e continue dentro do corpo do comando for.

Fluxograma do comando for

Acima temos a figura de um fluxograma do comando for. O laço de repetição for é


principalmente baseado na notação de faixa de valores, mas na verdade vale para qualquer
tipo iterável, como um objeto que poder retornar sempre o próximo elemento. Ele executa
seu bloco de contexto delimitado pela indentação; abaixo o primeiro print ta dentro do for.

for i in range(0,10):
print ("i=", i, end=' ')
© E.L.Favero Algoritmos em Python 59

print()
>>>
i= 0 i= 1 i= 2 i= 3 i= 4 i= 5 i= 6 i= 7 i= 8 i= 9

No comando for abaixo o laço é interrompido com break: quando o j==7 o break (parar) é
ativado e o comando pára a sua execução. Aqui testamos se o j%2!=0 então o valor é impar.
Note que só os impares são impressos.

for j in range(0,10):
if j % 2!=0: print(j, 'é impar')
if j==7: break
>>>
1 é impar
3 é impar
5 é impar
7 é impar

Idem acima, mas com o novo comando continue. Se j%2==0: continue volta para o início do
laço então não imprime 'é impar'. O break sai totalmente do laço.
for j in range(0,10):
if j>7: break
if j % 2==0:continue
print(j, 'é impar')
>>>
1 é impar
3 é impar
5 é impar
7 é impar

9.2 Somar com FOR


Somar todos os valores de 0 até 20. Vamos usar uma variável soma para armazenar o valor
da soma, e vamos utilizar um range(0,21) pois o intervalo é aberto no final.

soma=0
for i in range(0,21):
soma = soma+i
print(soma)
>>>
210

Para os próximos exercícios vamos aprender a trabalhar com uma string de dígitos. Por
exemplo, vamos aprender a utilizar a função split(). Aqui introduzimos outra notação
chamada de compreensão de lista, que é baseada numa versão do comando for: y=[int(i)
for i in x]. Todos os strings de x são transformados em int() em y.

9.2.1 String como lista de valores


>>> x= "12 17 21 2 47".split()
>>> x
['12', '17', '21', '2', '47']
>>> y=[int(i) for i in x]
>>> y
[12, 17, 21, 2, 47]
© E.L.Favero Algoritmos em Python 60

A lista de string foi convertida numa lista de int. Int pode ser somado algebricamente. O
split() pode também quebrar na vírgula. Quando usamos soma += i leia-se soma = soma+i.
Este comando += evita de repetirmos o nome da variável soma, para acumular algo com o
comando de atribuição.

>>> z="10, 60, 20, 50"


>>> z1=z.split(',')
>>> z1
['10', ' 60', ' 20', ' 50']
>>> z2=[int(i) for i in z1]
>>> z2
[10, 60, 20, 50]
>>>soma=0
>>>for i in z2: soma +=i
>>>soma
140

Ler uma lista de valores int e somar os valores lidos. Neste caso vamos usar uma função
split() para quebrar o string em valores. E cada valor em dígito deve ser convertido para
numérico.

str1=input('digite valores (x,y,z,...):')


lis1=str1.split(',')
print(lis1)
lis2=[int(i) for i in lis1]
print(lis2)
soma=0
for i in lis2: soma +=i
print(soma)
>>>
digite valores (x,y,z,...):3,34,7,24,5
['3', '34', '7', '24', '5']
[3, 34, 7, 24, 5]
73
9.3 Contar com FOR
Contar quantos valores de 0 até 20, são múltiplos de 3. Vamos usar uma variável conta para
armazenar o valor da conta, e vamos utilizar x%3==0 para testar os divisores de três.

conta=0
for x in range(0,21):
if x%3==0:
conta = conta+1
print(conta)
>>>

Ler uma lista de valores int e contar quantos são impares. Mostrar a lista lida e a quantidade
de impares. No exemplo abaixo, o '\n’ denota o carctere quebra de linha.

str1=input('digite valores (x y z ...):')


lis1=str1.split()
print(lis1)
lis2=[int(i) for i in lis1]
conta=0
for i in lis2:
© E.L.Favero Algoritmos em Python 61

if i % 2!=0: conta +=1


print(lis2, '\nNro de impares:', conta)
>>>
digite valores (x y z ...):2 5 5 7 4 4 2 3 23 20
['2', '5', '5', '7', '4', '4', '2', '3', '23', '20']
[2, 5, 5, 7, 4, 4, 2, 3, 23, 20]
Nro de impares: 5

9.3.1 Lista de exercícios (8)


E9.1 Ler dois valores a e b, e simular a multiplicação utilizando somente somas e
subtrações. Por exemplo, 4x3=3+3+3+3 que resulta em 12.

a=int(input('a:'));b=int(input('b:'))
mult=0
print('o resultado de %d * %d=' % (a,b), end=' ' )
for i in list(range(a)):
print('+',b, end=' ')
mult=mult+b
print('é igual:', mult)
>>>
a:4
b:7
o resultado de 4 * 7= + 7 + 7 + 7 + 7 é igual: 28

E9.2 Ler um número e imprimir todos os impares até o número lido. Use o comando for.

x=int(input('dig X:'))
for i in range(1,x+1,2):
print(i, end=' ')
print()
>>>

E9.3 Ler um número e imprimir todos os pares até o número lido. Use o comando for.

E9.4 Imprima a seqüência de 9 até 0. Use o comando for.

for i in range(9,-1,-1):
print(i, end=' ')
>>>
9 8 7 6 5 4 3 2 1 0
E9.5 Imprima a soma dos múltiplos de 7 entre 0 e 1000.

E9.6 Imprima a tabuada de um número n lido. Use o comando for.

n=int(input('tabua do n:'))
x=1
for x in range(0,11):
print("%d x %d = %d" % (n,x, n*x))
>>>
tabua do n:3
3 x 0 = 0
3 x 1 = 3
3 x 2 = 6
© E.L.Favero Algoritmos em Python 62

3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27
3 x 10 = 30

E9.7 Escreva todos valores de 51 até 100 com quebra linha de 10 em 10 valores. Use
for.
for x in range(51,101):
print(x, end=' ')
if x % 10 ==0: print()
>>>
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100

E9.8 Ler uma lista de supermercado com o produto, a quantidade e o tipo "a2, f6, b20,
c2". Onde produtos são letras de a..f e os valores são desta tabela: {a:10, b:60,
c:40, d:70, e:15, f:100}. Imprimir o boleto na seguinte forma (use um comando
while):
"""
Item qty preço subtotal
a 2 10 20
f 6 100 600
b 20 60 1200
c 2 40 80
___________________
Total 1900 """

lis= "a2, f6, b20, c2"


#lis=input('digite valores:')
lis1=lis.split(',')
lis1=[i.strip() for i in lis1]
print(lis1)
itens=[i[0] for i in lis1]
qti =[int(i[1:]) for i in lis1]
print(itens,qti)
def preco(x):
'''{a:10, b:60, c:40, d:70, e:15, f:100}'''
if x=='a': p=10
elif x=='b': p=60
elif x=='c': p=40
elif x=='d': p=70
elif x=='e': p=15
elif x=='f': p=100
else: p=None
return p
total = 0
print('item qti preço subtotal')
© E.L.Favero Algoritmos em Python 63

for i in range(len(itens)):
subtotal = qti[i]*preco(itens[i])
print(itens[i],qti[i],preco(itens[i]),subtotal)
total += subtotal
print('total:', total)
>>>
['a2', 'f6', 'b20', 'c2']
['a', 'f', 'b', 'c'] [2, 6, 20, 2]
item qti preço subtotal
a 2 10 20
f 6 100 600
b 20 60 1200
c 2 40 80
total: 1900

Três apóstrofos ou três aspas neste programa, delimitam comentários que podem
ser de múltiplas linhas.

9.3.2 Perguntas conceituais (2)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C9.1 O que faz o comando break?
C9.2 O que faz o comando continue?
© E.L.Favero Algoritmos em Python 64

Capítulo
10 COMANDO DE REPETIÇÃO: WHILE

Este capítulo apresenta o comando while, que é um comando de repetição. Este


comando é alternativo ao for, mas é até mais geral que ele. Vamos repetir os
algoritmos que foram feitos com for agora com o while. Contar e somar com while.
Percorrer estruturas e listas.

10.1 Comando WHILE


Abaixo temos o fluxograma do comando while: o bloco de comando é executado enquanto a
condição for verdadeira. Quando a condição for falsa a execução do comando termina.

Fluxograma do comando while

Segue abaixo o pseudo código do comando while, aqui chamado de “faça enquanto”.
Diferente do for o programador tem que inicializar a variável de controle do laço (i=0) e
também lembrar de incrementa-la dentro da indentação do laço (i=i+1).
© E.L.Favero Algoritmos em Python 65

Pseudo código do comando “faça enquanto”:


i=0
faça enquanto i<10:
escreva ("i=", i, end=' ')
i=i+1
escreva(‘\n’)
>>>
i= 0 i= 1 i= 2 i= 3 i= 4 i= 5 i= 6 i= 7 i= 8 i= 9
\n

Segue abaixo o while definido no Python. O laço de repetição while tem uma estrutura mais
simples que a do comando for. Seu bloco de contexto é definido pela indentação. O que
diferencia o for do while é que o for automaticamente executa uma inicialização e um
incremento. No while fica para o programador fazer a inicialização (i=0) e o incremento
(i=i+1). Um erro comum é esquecer o incremento e então o algoritmo entra em looping (laço
infinito).

i=0
while i<10:
print ("i=", i, end=' ')
i=i+1
print()
>>>
i= 0 i= 1 i= 2 i= 3 i= 4 i= 5 i= 6 i= 7 i= 8 i= 9

O segundo exemplo de while é um laço com True, isto é, “faça enquanto é verdade”, que
roda sempre, neste caso o break é necessário para a parada do laço.

j=0
while True:
if j % 2!=0: print(j, 'é impar')
if j==7: break
j=j+1
>>>
1 é impar
3 é impar
5 é impar
7 é impar

10.2 Somar com WHILE


Somar todos os valores de 0 até 20. Vamos usar a variável soma para armazenar o valor da
soma.

soma=0;i=0
while i <=20:
soma = soma+i
i=i+1
print(soma)
>>>
© E.L.Favero Algoritmos em Python 66

10.3 Contar com WHILE


Contar quantos valores de 0 até 20 são múltiplos de 3. Vamos usar uma variável conta para
armazenar o valor da conta, e vamos utilizar i%3==0 para testar os divisores de três.

conta=0;i=0
while i<=20:
if i%3==0:
conta = conta+1
i=i+1
print(conta)
>>>
7

Idem mas agora reescrevendo com o comando continue. A estrutura do algoritmo muda um
pouco. Se i%3!=0, for diferente de 0, então não conta. O continue permite executar somente
uma parte dos comandos do bloco.

conta=0;i=0
while i<=20:
i=i+1
if i%3!=0: continue
conta = conta+1
print(conta)
>>>
7

10.3.1 Lista de Exercícios (8)


E10.1 Ler dois valores a e b, e simular a multiplicação utilizando somente somas e
subtrações. Por exemplo, 4x3=3+3+3+3 que resulta em 12.

a=int(input('a:'));b=int(input('b:'))
mult=0
print('o resultado de %d * %d=' % (a,b), end=' ' )
while a>0:
print('+',b, end=' ')
mult=mult+b
a=a-1
print('é igual:', mult)
>>>
a:4
b:7
o resultado de 4 * 7= + 7 + 7 + 7 + 7 é igual: 28

E3.1 Temos dois operadores especiais de divisão // e %, divisão inteira e o resto da


divisão. Como podemos programa-los utilizando soma e subtração. Por exemplo,
14//3 =4 e 14%3=2. Ler dois números inteiros positivos e simular os operadores //
e %.

a=int(input('a:'));b=int(input('b:'))
conta=0
© E.L.Favero Algoritmos em Python 67

print('o resultado de %d // %d' % (a,b) )


while a>=b:
conta = conta + 1
print('-',b, 'conta:', conta);
a=a-b
print(' divisão inteira (//) :', conta)
print(' resto da divisão (%): ', a)
>>>
a:13
b:4
o resultado de 13 // 4
- 4 conta: 1
- 4 conta: 2
- 4 conta: 3
divisão inteira (//) : 3
resto da divisão (%): 1

E3.2 Ler um número e imprimir todos os impares até o número lido. Use o comando
while.

x=int(input('dig X:'))
y=1
while y<=x:
print(y, end=' ')
y=y+2
print('fim')
>>>
dig X:9
1 3 5 7 9
E3.3 Ler um número e imprimir todos os pares até o número lido. Use o comando while.

E3.4 Imprimir a soma dos múltiplos de 7 entre 0 e 1000.

E3.5 Imprima a seqüência de 9 até 0. Use o comando while.

x=9
while x>=0:
print(x, end=' ')
x=x-1
>>>
9 8 7 6 5 4 3 2 1 0

E3.6 Imprima a tabuada de um número n lido. Use o comando while.

n=int(input('tabua do n:'))
x=0
while x<=10:
print("%d x %d = %d" % (n,x, n*x))
x=x+1
>>>
tabua do n:3
3 x 0 = 0
3 x 1 = 3
3 x 2 = 6
© E.L.Favero Algoritmos em Python 68

3 x 3 = 9
3 x 4 = 12
3 x 5 = 15
3 x 6 = 18
3 x 7 = 21
3 x 8 = 24
3 x 9 = 27
3 x 10 = 30

E3.7 Escreva todos valores de 51 até 100 com quebra linha de 10 em 10 valores. Use
while.
x=51
while x<=100:
print(x, end=' ')
if x % 10 ==0: print()
x=x+1
>>>
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100

E3.8 Ler uma lista de supermercado com o produto, a quantidade e o tipo "a2, f6, b20,
c2". Onde produtos são letras de a..f e os valores são desta tabela: {a:10, b:60,
c:40, d:70, e:15, f:100}. Imprimir o boleto na seguinte forma:
"""
Item qty preço subtotal
a 2 10 20
f 6 100 600
b 20 60 1200
c 2 40 80
___________________
Total 1900 """

lis= "a2, f6, b20, c2"


#lis=input('digite valores:')
lis1=lis.split(',')
lis1=[i.strip() for i in lis1]
print(lis1)
itens=[i[0] for i in lis1]
qti =[int(i[1:]) for i in lis1]
print(itens,qti)
def preco(x):
'''{a:10, b:60, c:40, d:70, e:15, f:100}'''
if x=='a': p=10
elif x=='b': p=60
elif x=='c': p=40
elif x=='d': p=70
elif x=='e': p=15
elif x=='f': p=100
else: p=None
return p
total = 0
print('item qti preço subtotal')
© E.L.Favero Algoritmos em Python 69

i=0
while i<len(itens):
subtotal = qti[i]*preco(itens[i])
print(itens[i],qti[i],preco(itens[i]),subtotal)
total += subtotal
i=i+1
print('total:', total)
>>>
['a2', 'f6', 'b20', 'c2']
['a', 'f', 'b', 'c'] [2, 6, 20, 2]
item qti preço subtotal
a 2 10 20
f 6 100 600
b 20 60 1200
c 2 40 80
total: 1900

10.3.2 Perguntas conceituais (1)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C10.1 Qual a diferença entre o comando for e o comando while, tem alguma coisa que só
pode ser feita com for ou só com while ?
© E.L.Favero Algoritmos em Python 70

Capítulo

11 FUNÇÕES
Este capítulo aprofunda o conceito de funções, como objetos computacionais.
Apresentamos funções recursivas.

11.1 Mais sobre funções


Funções recebem opcionalmente parâmetros e devolvem opcionalmente resultados. A
palavra def precede o nome da função. As funções também são consideradas objetos e têm
alguns atributos, dentre os quais __doc__, o qual contém a documentação da função, e
__name__, que contém o nome da função. Funções também podem ser atribuídas a
variáveis. Funções são executáveis quando se coloca () no final, com ou sem parâmetros.
Também é possível utilizar parâmetros opcionais como por exemplo uma função que
calcula a potência, onde poderíamos ou não informar o expoente. Caso não for informado é
assumido o valor default 2.

def potencia(base,exp=2):
''' função potencia com exp int opcional '''
if exp==0: return 1
pot=base
for i in range(1,exp): pot=pot*base
return pot

pot=potencia
print(pot(2)) # 4
print(potencia(2,8)) # 256
print(pot(4,3)) # 4*4*4
print(pot.__doc__)
print(pot.__name__)
>>>
4
256
64
função potencia com exp int opcional
potencia

O poder das funções é abstrair fragmentos de cógigo, numa espécie de caixa preta. É dado
um nome para uma sequência de comandos que executa uma funcionalidade.
© E.L.Favero Algoritmos em Python 71

11.2 Função soma()


Uma lista representa também um vetor. Os índices começam sempre no 0 e terminam com
o comprimento (len) menos 1. Como somar os elementos de uma lista, várias versões.

V=[1,2,7,11,23,6]
# Defina a soma dos elementos do vetor use for, sem usar índices
def soma(v):
soma=0;
for i in v:soma = soma+i
return soma
# Defina a soma dos elementos do vetor use for,
# acessando os elementos com índices
def soma1(v):
soma=0;
for i in range(len(v)):soma = soma+v[i]
return soma

Podemos fazer vários aprimoramentos nos códigos, um deles é usar o operador +=. Assim
soma=soma+v, fica soma +=v. Podemos também somar usando while.

# Defina a função soma dos elementos do vetor use while


def soma2(v):
soma=0;i=0
while i<len(v): soma += v[i];i+=1
return soma
print(' soma:',soma(V))
print(' soma1:',soma1(V))
print(' soma2:',soma2(V))

11.2.1 Função média() e desvio()


Outra função bem usual é a média de uma lista ou de um vetor de valores. Pode ser feita
com a soma, sum(), do vetor dividida pelo seu comprimento. Mas também pode ser feita
sem usar a soma.

#Defina a função média utilizando a função soma


def med(v):return(sum(v)/len(v))
#Defina a função média, med1, sem utilizar a função soma (sum)
def med1(v):
s=0;
for i in range(len(v)): s=s+v[i]
return s/len(v)
print(' med:',med(V))
print(' med1:',med1(V))

Uma função parente da média é o desvio padrão. Seja SS o somatório da diferença de cada
elemento com a média elevada ao quadrado. Assim SS = somatório de (V[i]-med)**2. O
desvio é a raiz(SS/(len(V)).

#Defina a função desvio1 padrão, sem usar a função média


def desvio(v):
m=sum(v)/len(v);
s=0;
for i in v:s+=(i-m)**2
return (s/len(v))**0.5
© E.L.Favero Algoritmos em Python 72

print(' desv:',desvio(V))

11.2.2 Listas x Strings


Podemos inicializar uma lista de letras a partir de uma string. É muito chato ter que digitar
uma lista de letra, cada letra entre dois apóstrofos. É mais fácil transformar uma string numa
lista utilizando o comando list() .

>>>L=list("afghtlmedk")
>>>L
>>> ['a', 'f', 'g', 'h', 't', 'l', 'm', 'e', 'd', 'k']
>>>int('1')
1
>>> str(1)
'1'

Agora vamos devolver dois objetos de uma função, dois vetores. Vamos primeiro mesclar
dois vetores, da forma que se A=list("abcdefg") e B=list("1234567") então
AB=list("a1b2c3d4e5f6g7"). Já a função separa faz o trabalho contrário, neste caso ela
separa as duas listas, o A e o B. Note que o *separa(AB) remove a tupla.

#Faça a função mescla(A,B) que entra A e B e retorna AB


def mescla(A,B):
AB=[]
for i in range(len(A)):
AB.append(A[i])
AB.append(B[i])
return ''.join(AB)

A=list("abcdefg")
B=list("1234567")
AB=list("a1b2c3d4e5f6g7")
print('mescla AB:', mescla(A,B))
print('mescla BA:', mescla(B,A))

#Faça a função separa(AB) que retorna A e B


def separa(AB):
A,B=[],[]
for i in range(0,len(AB),2):
A.append(AB[i])
B.append(AB[i+1])
return ''.join(A),''.join(B)
print('separa AB:', separa(AB))
print('separa AB:', separa(mescla(B,A)))

print('separa AB:', *separa(AB))


print('separa AB:', *separa(mescla(B,A)))

11.2.3 Função reverse() e palíndromo()


A função reverse também tem várias aplicações. Uma delas é no código da função
palíndromo. Uma lista é um palíndromo se ela for igual a sua imagem invertida, assim
list("abcba") é palíndromo, pois list("abcba") =rev(list("abcba") ).
© E.L.Favero Algoritmos em Python 73

Uma forma simples de inverter uma lista é pela manipulação de fatias, assim
reverso(x) = x[::-1]. Mas vamos programar outras formas para exercitar a solução do
problema:
i) rev: iniciar no índice len()-1, até 0, diminuindo de 1; fica range(len(s)-1,-1,-1)
ii) rev1: percorrer a lista com for tirando da cabeça e colocando na cauda
iii)rev2: idem com recursividade, sem o for

def rev(s):
REV=[]
for i in range(len(s)-1,-1,-1):
REV.append(s[i])
return REV
print('rev abcdef:',rev(list('abcdef')))

O append sempre acrescenta um elemento no final da lista. Mas o + é mais flexível podendo
concatenar quaisquer duas listas, assim podemos percorrer a lista do início para o fim e
sempre ir acrescentando na frente. Por fim, vamos fazer uma versão rev2() recursiva.

def rev1(s):
REV=[]
for i in range(len(s)):REV=[s[i]]+REV
return REV

11.2.4 Funções recursivas


Outro recurso de programação são as funções recursivas. Vamos apresentar o conceito
com a função reverse.

def rev2(s):
if s!=[]: return rev2(s[1:])+[s[0]]
else: return []

Uma função é recursiva se ela se chama a si mesma: na linha do def, ela é definda, e
dentro do seu corpo, ela já é chamada.
Abaixo no Python Tutor vemos que primeiro a função vai se chamando e a lista de
entrada diminui até ficar vazia. As funções recursivas vão se empilhando dentro da maquina
abstrata de execução do Python. Depois de chegar no vazio da lista da entrada as funções
vão gerando o retorno, com as listas parciais invertidas.
© E.L.Favero Algoritmos em Python 74

Com mais dois passos next, vemos o retorno da lista parcial [c,d] invertida, agora [d,c].
Continuando com next as funções são removidas da pilha de execução e o resultado vem
sendo motado, até se chegar em [d,c,b,a]. Para animar funções recursivas no Python Tutor
utilize entradas pequenas de no máximo 5 elementos.

Abaixo temos um teste comparando as três versões de reverse, para mostar que elas geram
o mesmo reultado.

print('rev1 abcdef:',rev1(list('abcdef')))
print('rev2 abcdef:',rev2(list('abcdef')))
li=list("123456")
print(rev(li), '\n', rev1(li),'\n', rev2(li) )
© E.L.Favero Algoritmos em Python 75

Agora com várias versões de reverse vamos programar duas versões da função palíndromo,
a primeira mais fácil de ler, x==rev(x) e a segunda um pouco mais abstrata x==x[::-1].

def palindromo(x): return x==rev(x)


def palindromo1(x):return x==x[::-1]

print(palindromo(list('abcdeedcba')))
print(palindromo(list('12321')))
print(palindromo1(list('12321')))
print(palindromo1(list('123X21')))

11.2.5 Problemas recursivos


O que faz uma função recursiva? Porque utilizar funções recursivas? No exemplo de
reverse, a recursividade substitui o comando de repetição. Mas, na matemática é comum o
uso de funções recursivas para tratar de problemas com definições recursivas. Neste caso a
recursividade da linguagem de programação permite uma codificação direta da função
matemática com a função a ser programada.

As folhas da Bromélia são formadas por espirais, cujos raios pertencem a série de
Fibonacci. A Sequência de Fibonacci é uma série numérica descoberta pelo matemático
Fibonacci: 1, 1, 2, 3, 5, 8, 13, 21, 34, ... Ele mostrou a serie com o exemplo do crescimento
acelerado da população de coelhos, com a fórmula recursiva:

Fo= F1 = 1
Fn = Fn - 1 + Fn - 2

def fibo(n):
if n<=1: return n
else: return fibo(n-1)+fibo(n-2)

for i in range(1,10): print(fibo(i),end=' ')


>>>
1 1 2 3 5 8 13 21 34
© E.L.Favero Algoritmos em Python 76

11.3 Exercícios (16)


Ao responder estes exercícios testando cada função com duas entradas para
garantir que a saída está correta.

E11.1 Faça a função potencia para valores inteiros de base e expoente, use um for
E11.2 Defina a soma dos elementos do vetor, use for, sem usar índices
def soma(v):
soma=0;
for i in v:soma = soma+v
return soma

E11.3 Defina a soma dos elementos do vetor use for, acessando os elementos com índices
def soma1(v):
soma=0;
for i in range(len(v)):soma = soma+v[i]
return soma

E11.4 Defina a função soma dos elementos do vetor use while


def soma2(v):
soma=0;i=0
while i<len(v): soma += v[i]
return soma
V=[3,6,9,1,1,3,8]; print(' soma2:',soma2(V))

E11.5 Defina a função soma dos elementos do vetor use while, sem usar índice, usando
pop().
v=[1,5,7]
print(v); print(v.pop()); print(v)
def soma2(v):
soma=0;
while v: soma += v.pop()
return soma
V=[3,6,9,1,1,3,8]; print(' soma2:',soma2(V))

E11.6 Defina a função média utilizando a função soma


def med(v):return(sum(v)/len(v))

E11.7 Defina a função média, med1, sem utilizar a função soma (sum)
def med1(v):
s=0;
for i in range(len(v)): s=s+v[i]
return s/len(v)
V=[3,6,9,1,1,3,8]; print(' med1:',med1(V))

E11.8 Defina a função desvio1 padrão, sem usar a função média


def desvio(v):
m=sum(v)/len(v);
s=0;
for i in v:s+=(i-m)**2
return (s/len(v))**0.5
V=[3,6,9,1,1,3,8]; print(' desv:',desvio(V))

E11.9 Faça a função mescla(A,B) que entra A e B e retorna AB


© E.L.Favero Algoritmos em Python 77

def mescla(A,B):
AB=[]
for i in range(len(A)):
AB.append(A[i])
AB.append(B[i])
return ''.join(AB)

A=list("abcdefg")
B=list("1234567")
print('mescla AB:', mescla(A,B))
print('mescla BA:', mescla(B,A))

E11.10 Faça a função separa(AB) que retorna A e B


AB=list("a1b2c3d4e5f6g7")
def separa(AB):
A,B=[],[]
for i in range(0,len(AB),2):
A.append(AB[i])
B.append(AB[i+1])
return ''.join(A),''.join(B)
print('separa AB:', *separa(AB))

E11.11 Faça a função reverse usando um for e range: iniciar no índice len()-1, até 0,
diminuindo de 1; fica range(len(s)-1,-1,-1)
def rev(s):
REV=[]
for i in range(len(s)-1,-1,-1):
REV.append(s[i])
return REV
print('rev abcdef:',rev(list('abcdef')))

E11.12 Faça a função reverse: percorrer a lista com for tirando da cabeça e colocando na
futura cauda
def rev1(s):
REV=[]
for i in range(len(s)):REV=[s[i]]+REV
return REV
print('rev abcdef:',rev1(list('abcdef')))

E11.13 Faça a função reverse com recursividade: percorrer a lista tirando da cabeça e
colocando na cauda
def rev2(s):
if s!=[]: return rev2(s[1:])+[s[0]]
else: return []
print('rev abcdef:',rev2(list('abcdef')))

E11.14 Faça a função palindromo usando x[::-1] para inverter x


def palindromo1(x):return x==x[::-1]
print(palindromo1(list('12321')))
print(palindromo1(list('123X21')))

E11.15 Faça a função palindromo usando rev()


def palindromo(x): return x==rev(x)
print(palindromo(list('abcdeedcba')))
print(palindromo(list('12321')))
© E.L.Favero Algoritmos em Python 78

E11.16 Faça a função palindromo sem usar uma lista invertida. Comparando sempre os dois
extremos, em direção ao meio.

11.3.1 Perguntas conceituais (2)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C11.1 Quais são os componentes de uma função?
C11.2 O que caracteriza uma função recursiva?
© E.L.Favero Algoritmos em Python 79

Capítulo

12 MÉTODOS DE BUSCA E
ORDENAÇÃO

Mostramos alguns métodos de busca e de ordenação de listas, como uma forma de


exercitar o desenvolvimento de algoritmos e as técnicas de programação.

12.1.1 Função maxi() e imax()


Outras funções muito usuais são de máximo e de mínimo de uma lista. Podemos definir uma
função maxi() para retornar o elemento máximo, max() do Python. Mas também podemos
retornar o índice do máximo. Outra função auxiliar para implementar uma ordenação é
buscar o máximo a partir de um dado índice do vetor, imax1().

#Defina a função que retorna o máximo elemento de um vetor


def maxi(v):
M=v[0];
for i in range(len(v)):
if M<v[i]:M=v[i]
return M

#Defina a função que retorna o índice do máximo elemento de um vetor


def imax(v):
M=0;
for i in range(1,len(v)):
if v[M]<v[i]:M=i
return M
print(' maxi:', maxi(V))
print(' imax:', imax(V))

# idem iniciando a busca em j


def imax1(j,v):
M=j;
for i in range(j,len(v)):
if v[M]<v[i]:M=i
return M
print(' maxi:', maxi(V))
print(' imax:', imax(V))
print(' imax:', imax1(3,V))
© E.L.Favero Algoritmos em Python 80

12.1.2 Função busca(), in1() e index1()


Uma função útil é a busca de um elemento dentro de uma lista. Podemos fazer duas
versões uma que diz se o elemento está na lista e outra que diz a posição do elemento na
lista.
def busca(x,v):
for i in v:
if x==i:return True
return False
def busca1(x,v):
for i in range(len(v)):
if x==v[i]:return i
return None

Estas duas funções existem na linguagem: vi= [4,5,3,7]; 3 in vi; vi.index(3). Mas cuidado que
se perguntamos >>>vi.index(10) resulta em ValueError: 10 is not in list. Vamos reescreve-las
como in1() e index1()

def in1(x,v):
for i in v:
if x==i:return True
return False
def index1(x,v):
for i in range(len(v)):
if x==v[i]:return i
return None

V=[1,3,7,11,23,6]
print('busca 3:',busca(3,V))
print('busca 8:',busca(8,V))
print('busca1 3:',busca1(3,V))
print('in1 3:',in1(3,V))
print('index1 23:',index1(23,V))
>>>
busca 3: True
busca 8: False
busca1 3: 1
in1 3: True
index1 23: 4

12.1.3 Ordenção: método da bolha


Outra função útil é de troca de dois elementos de um vetor. Em Python pode ser feita com
atribuição múltipla, ou com o uso de uma variável temporária temp.

# troca dois elementos de um vetor v, índices a,b


def troca(v,a,b):
v[a],v[b]=v[b],v[a]
return
v1=[1,7,9,12]
troca(v1,1,3)
print(v1)

# troca dois elementos de um vetor v, índices a,b


© E.L.Favero Algoritmos em Python 81

def troca1(v,a,b):
temp=v[a];v[a]=v[b];v[b]=temp
return

Fonte: Python Tutor

Note que na troca() temos um return vazio, pois o efeito da troca ocorre sobre a própria lista.
Poderíamos ter colocado return None. Troca atua sobre um vetor, que é mutável, assim o
efeito fica gravado no vetor.
Em algumas linguagens de programação existe uma diferença entre uma função e
procedimento. A função recebe parâmetros e retorna valores ou objetos. Um procedimento
deixa o seu efeito sobre algumas estruturas de dados como no exemplo da troca, sem
retorno de valores.

Agora compreendendo como se troca dois elementos de um vetor podemos fazer um dos
métodos de ordenação chamado bubble sort ou método da bolha. Este método consiste
em testar dois elemento contíguos de um vetor se V[i]>V[i+1] então troca-se o conteúdo
destas duas posições. Varrendo-se o vetor do início até o fim sempre fazendo estas trocas
aos poucos os valores maiores vão para o final e os menores ficam no início. Quando é
possível percorrer o vetor e não for feita nelhuma troca então parar.

def bolhaOrd(V):
trocaOK=True
while trocaOK:
trocaOK=False
for i in range(len(V)-1):
if V[i]>V[i+1]:
V[i],V[i+1]=V[i+1],V[i];
trocaOK=True
return V
S1='blagla';
V=list(S1)
print(''.join(bolhaOrd(V)))

Rodando o método da bolha sobre a lista “blagla” a primeira troca será das letras “la” por
“al”, como ilustrado abaixo no python tutor, ficando “balgal”; depois “lg” por “gl”, etc.
© E.L.Favero Algoritmos em Python 82

Na primeira passage o l que estava na segunda posição vai sendo levado para a 5 posição.
No total são 88 passos (ver abaixo). No passo 61 a lista tá quase ordenada, só falta uma
troca.

Troca Novo string


1 blagla
2 balgla
3 baglla
4 baglal
© E.L.Favero Algoritmos em Python 83

12.1.4 Ordenação: Seleçao direta


Outro método de ordenação fácil de compreender é a seleção direta. Usando a função
troca() e a função que retorna o índice do elemento máximo do vetor, imax1(), podemos
fazer um algoritmo de ordenação: ordena os elementos de um vetor, trazendo sempre o
máximo para o início, com sucessivas trocas. Note que a troca() e a ordena() destrõem o
vetor original. Portanto, devemos tirar uma cópia do vetor para preservá-lo, com V1=list(V)
ou V1=V[:].

# ordena, usando imax1(j,V) e troca(),


# trazendo sempre o máximo para o início
def ordena(v):
for i in range(len(v)):
m=imax1(i,v)
v[m],v[i]=v[i],v[m]
return(v)
def ordena1(v):
for i in range(len(v)):m=imax1(i,v);troca(v,i,m)
return v
def ordena2(v):
for i in range(len(v)):troca(v,i,imax1(i,v))
return v

print('troca 3 x 4:',troca(V,3,4))
V=[1,3,7,11,23,6]
V1=list(V) # copia da lista V
V2=V[:] # idem, copia a lista V
V3=V[:]
print(' ordena:', ordena(V1))
print('ordena1:', ordena1(V2))
print('ordena2:', ordena2(V3))

Em Python existe a função del V[i] que deleta o elemento i de V. Podemos fazer uma função
ordenad() que pega o imax(), deleta-o, e coloca ele noutra lista aux, que cria a nova lista
ordenada.
© E.L.Favero Algoritmos em Python 84

def imax(v):
M=0;
for i in range(1,len(v)):
if v[M]<v[i]:M=i
return M
def ordenad(v):
aux=[]
while v!=[]:
m=imax(v); aux.append(v[m])
del v[m]
return aux
def ordenad1(v):
aux=[]
while v!=[]:
m=v.index(max(v));aux.append(v[m]); del v[m]
return aux

V=[1,3,7,11,23,6]
V1=V[:];V2=V[:]
print(' ordenad:', ordenad(V1))
print('ordenad1:', ordenad1(V2))

Existe uma pequena diferença entre ordenad() e ordenad1(). Podemos pensar que a
primeira é um pouco mais eficiente, pois quando encontrou o máximo já memorizou o índice
e a segunda depois de encontrar o máximo ainda busca o índice v.index().

Projeto. Crie um vetor aleatório, de randint(), com tamanho 1000 (ver cap 4). Usando os
recursos de tempo, import time, como ilustrado abaixo, compare o tempo das duas funções.
Quanto por cento a primeira é mais rápida?

import time as t
miliseg=t.time
t0 = miliseg() # inicia a contagem do tempo
for i in range(100000):
x=10+10
t1 = miliseg() #fim da contagem de tempo
print(round(t1-t0,4),"milisegundos para fazer 100k somas")

12.2 Exercícios (18)


E12.1 Defina a função que retorna o máximo elemento de um vetor, use for
def maxi(v):
M=v[0];
for i in range(len(v)):
if M<v[i]:M=v[i]
return M
V=[3,6,9,1,1,3,8]; print(' maxi:', maxi(V))

E12.2 Defina a função que retorna o índice do máximo elemento de um vetor


def imax(v):
M=0;
for i in range(1,len(v)):
© E.L.Favero Algoritmos em Python 85

if v[M]<v[i]:M=i
return M
V=[3,6,9,1,1,3,8]; print(' imax:', imax(V))

E12.3 Retorne o indice do máximo do vetor, iniciando a busca em j


def imax1(j,v):
M=j;
for i in range(j,len(v)):
if v[M]<v[i]:M=i
return M
V=[3,6,9,1,1,3,8]; print(' imax:', imax1(3,V))

E12.4 Defina mini() que retorna o mínimo elemento de um vetor

E12.5 Defina imin() que retorna o índice do mínimo elemento de um vetor

E12.6 Defina a função busca, que diz se o elemento está no vetor


def busca(x,v):
for i in v:
if x==i:return True
return False
V=[1,3,7,11,23,6]
print('busca 3:',busca(3,V))
print('busca 8:',busca(8,V))

E12.7 Defina a função busca, que devolve a posição do elemento que está no vetor
def busca1(x,v):
for i in range(len(v)):
if x==v[i]:return i
return None
V=[1,3,7,11,23,6]
print('busca1 3:',busca1(3,V))

E12.8 Defina uma função busca similar ao in, in1(), que diz o elemento está no vetor, use for
def in1(x,v):
for i in v:
if x==i:return True
return False

E12.9 Defina uma função similar ao index() que retorna o índice do elemento no vetor
def index1(x,v):
for i in range(len(v)):
if x==v[i]:return i
return None
V=[1,3,7,11,23,6]
print('index1 23:',index1(23,V))

E12.10 Defina a função in1() usando um while.

E12.11 Defina a função index1() usando um while.

E12.12 Defina a função troca, que troca dois elementos de um vetor v, índices a,b com
atribuição múltipla
def troca(v,a,b):
v[a],v[b]=v[b],v[a]
© E.L.Favero Algoritmos em Python 86

return

E12.13 Defina a função que troca dois elementos de um vetor v, índices a,b usando uma
variável temporária
def troca1(v,a,b):
temp=v[a];v[a]=v[b];v[b]=temp
return

E12.14 Defina o método de ordenação da bolha para um vetor


def bolhaOrd(V):
trocaOK=True
while trocaOK:
trocaOK=False
for i in range(len(V)-1):
if V[i]>V[i+1]: V[i],V[i+1]=V[i+1],V[i];trocaOK=True
return V
S1='aglfdlksjglksajgghfj'; print(S1);
V=list(S1); print(''.join(bolhaOrd(V)))

E12.15 Defina o método de ordenação por seleção direta, usando imax1(j,V) e fazendo troca
com atribuição múltipla; trazendo sempre o máximo para o início da lista sendo
ordenada
def ordena(v):
for i in range(len(v)):
m=imax1(i,v)
v[m],v[i]=v[i],v[m]
return(v)
V=[1,3,7,11,23,6];V1=list(V)
print(' ordena:', ordena(V1))

E12.16 Defina o método de ordenação por seleção direta, usando imax1(j,V) e troca(),
def ordena1(v):
for i in range(len(v)):m=imax1(i,v);troca(v,i,m)
return v
def ordena2(v):
for i in range(len(v)):troca(v,i,imax1(i,v))
return v

V=[1,3,7,11,23,6];V2=V[:];V3=V[:]
print('ordena1:', ordena1(V2))
print('ordena2:', ordena2(V3))

E12.17 Faça a função ordenad() que pega o imax(), deleta-o, e coloca ele noutra lista aux,
que monta a nova lista ordenada.

def imax(v):
M=0;
for i in range(1,len(v)):
if v[M]<v[i]:M=i
return M
def ordenad(v):
aux=[]
while v!=[]:
m=imax(v); aux.append(v[m])
del v[m]
© E.L.Favero Algoritmos em Python 87

return aux

E12.18 Faça a função de seleção direta, de ordenação, ordenad1() usando max() e index()
primitivas do Python
def ordenad1(v):
aux=[]
while v!=[]:
m=v.index(max(v));aux.append(v[m]); del v[m]
return aux
V=[1,3,7,11,23,6];V2=V[:]
print('ordenad1:', ordenad1(V2))

Projeto Nerd (avançado *complexo). Crie um vetor aleatório, de randint(), com tamanho
1000 (ver próximo capítulo sobre matrizes). Usando os recursos de tempo, import time,
como ilustrado abaixo, compare o tempo das funções de ordenação. Qual delas é mais
rápida?

import time as t
miliseg=t.time
t0 = miliseg() # inicia a contagem do tempo
for i in range(100000):
x=10+10
t1 = miliseg() #fim da contagem de tempo
print(round(t1-t0,4),"milisegundos para fazer 100k somas")
© E.L.Favero Algoritmos em Python 88

Capítulo

13 VETORES E MATRIZES
Neste capítulo apresentamos duas estruturas de dados: vetores e matrizes. Estas
estruturas são generalizações da lista e da tupla. Aqui uma lista de dados numéricos é
vista como um vetor. E uma lista de listas como uma matriz.

13.1 Medidas de distância


Aqui introduzimos o conceito de estrutura de dados, como um tipo de dados contruído a
partir da repetição, por exemplo, numa lista de tipos de dados simples. Dizemos que os tipos
de dados int, float, char, string são tipos simples. Uma lista como um vetor é uma estrutura
de dados composta por dados simples. Mas também podemos formar listas de listas, por
exemplo, para representar uma matriz. Vetores e matrizes são objetos da matemática muito
utilizados na computação.

BOX: Bit e Byte x Dado x Informação. Aqui vamos conceituar a palavra


dado. Bit é uma unidade mínima de informação. O bit pode ser 0 ou 1. Oito
bits são um byte. Num byte pode-se representar um caracter. Composições
de bytes formam os tipos de dados simples: int, bool, float, char e string. Tudo
o que representamos nas variáveis dos algoritmos são os dados.
Os dados num contexto de interesse são interpretados como
informações úteis. Por exemplo, num algoritmo de dar aumento de salário, os
valores salário atual, percentual de aumento e novo salário são três variáveis
para o programador. São três dados para o programador. Mas, são três
informações importantes para a pessoa que paga o salário e para a pessoa
que recebe o salário.

A distância Euclidiana é uma medida de uma reta entre dois pontos no espaço. Outra
medida é a distância de Manhattan que consiste em seguir os contornos dos quadrados,
unidades de medida. Assim de (0,0) até (6,6) via distância Eucliadiana temos sqrt( (6-0)**2+(
(6-0)**2)= sqrt(72)= 8.48 unidades; e via distância de Manhattan teremos (6-0)+(6-0)=12
unidades (6 na vertical + 6 na horizontal).
© E.L.Favero Algoritmos em Python 89

Diagrama das ruas de uma cidade: a distancia euclidiana é a reta entre os dois pontos; a
distância de Manhattan segue o contorno dos quadrados

O tabuleiro acima é um espaço plano, de duas dimensões, 2D. Podemos trabalhar em


espaços 3D, ou até multidimensionais. Para trabalhar num espaço multidimensional, com
distâncias e com o coseno do ângulo entre dois vetores, precisamos de uma estrutura de
dados chamada de vetor. Um vetor é uma lista de valores. Um vetor também é chamado de
uma estrutura de dados homogênea, pois seus elementos são todos do mesmo tipo de
dados.

A figura abaixo mostra a equação da distância Euclidiana, do Coseno e da Norma.


O coseno mede o ângulo entre dois vetores, que também pode ser considerada uma
medidade de similaridade entre vetores. Quanto menor for o ângulo mais similares são os
vetores. Na equação do Coseno, X dot Y significa o somatório de x(i)*y(i) para todos os x in
X e y in Y.

Distância Euclidiana: Coseno: Norma:

Coseno versus distância euclidiana Norma do vetor


© E.L.Favero Algoritmos em Python 90

13.2 Distância euclidiana, conseno e norma


def euclD(x,y):return sum((a-b)**2) for a,b in zip(x, y))**0.5
def manhD(x,y):return sum(abs(a-b) for a,b in zip(x,y))
def rootX2( x ):return sum([a*a for a in x])**0.5
def cosiV(x,y):return sum(a*b for a,b in zip(x,y))/(inf+rootX2(x)*rootX2(y))

As equações podem ser facilmente codificadas em Python numa programação bem abstrata
como consta no quadro acima, num estilo funcional de programação. Para facilitar o
entendimento vamos codificá-las da maneira convencional, de maneira procedural, com
comandos “for” percorrendo os vetores.
Se temos dois vetores X e Y e se seus elementos são x(i) e y(i), então euclD(X,Y)
é a raiz quadrada do somatório dos valores (x(i)-y(i))**2. O sqrt(), raiz quadrada, está na
biblioteca math, mas também pode ser escrita como x**0.5.
Uma biblioteca de funções é similar a uma coleção de livros, mas neste caso os
objetos armazenados são de programação, são funções e classes. O comando from math
import *, importa tudo da biblioteca math.

from math import *


def euclD(x,y):
aux=0;
for i in range(len(x)):
aux += (x[i]-y[i])**2
return sqrt(aux)
def manhD(x,y):
aux=0;
for i in range(len(x)):
aux += abs(x[i]-y[i])
return aux

A função rootX2() representa a norma de um vetor, que também é o seu comprimento. Esta
norma é usada no denominador do coseno. Se u=(a,b,c,d), a rootX2(u) =
sqrt(a*a+b*b+c*c+d*d).

inf=float(1E-20)
def rootX2(x):
aux=0;
for i in range(len(x)):
aux += (x[i])**2
return sqrt(aux)
def cosV(x,y):
aux=0;
for i in range(len(x)):
aux += (x[i]*y[i])
return aux/(inf+float(rootX2(x)*rootX2(y)))

O coseno possui um denominador que eventualmente pode ser zero. Porém, na


computação devemos evitar divisões por zero porque geram erros de execução. Para
contornar este problema definimos uma constante infinitezimal (inf) com valor 1E-20=
0.00000000000000000001, são 20 casas depois do ponto, 19 zeros antes do um. Esta
constante é somada com o denominador e assim não dá erro de divisão.

x=[6,1,3,2]
y=[3,1,1,4] # z=2y
z=[6,2,2,8]
© E.L.Favero Algoritmos em Python 91

a=[1,2,1]
b=[3,1,2]
print('coseno a,b:', round(cosV(a,b),2) )
print('coseno x,x:', round(cosV(x,x),2))
print('coseno x,y:', round(cosV(x,y),2))
print('coseno y,z:', round(cosV(y,z),2))
print('euclidiana x,x:', round(euclD(x,x),2))
print('euclidiana y,z:', round(euclD(y,z),2))
>>>
coseno a,b: 0.76
coseno x,x: 1.0
coseno x,y: 0.82
coseno y,z: 1.0
euclidiana x,x: 0.0
euclidiana y,z: 5.2

Pelos resultados podemos ver que coseno(x,x) é sempre 1, não importa quem é o vetor x.
Agora se criamos um vetor z=2*y, coseno(y,z) continua sendo 1. Pois o vetor 2*y tem a
mesma direção de y. Por outro lado, a distância Euclidiana entre x e x é sempre zero,
euclD(x,x) = 0.

13.3 Matriz como Listas


Transpor uma matriz é transformar suas colunas em linhas e vice versa. Por exemplo,
abaixo temos uma matriz B de 3x2, 3 linhas por duas colunas, que transposta fica de 2x3.

Transposta de uma matriz

Em Python um vetor (array) é uma lista. Mas o que são vetores ou matrizes
multidimensionais? São listas de listas.

13.3.1 Trabalhar com números aleatórios: random


Antes de criar a matriz vamos apresentar outra biblioteca, a de números aletórios, random.
Import random as rand, significa que todos os objetos da biblioteca podem ser utilizados,
mas devemos colocar o prefixo rand, as=alias, “nick name”.
Inicialmente vamos utilizar seed() e randint(). Seed cria uma semente para o gerador
de número aletórios. Assim debaixo da semente ele gerará sempre a mesma sequência,
mas quando mudamos a semente muda a sequência. Randint(2,900) gerará um numero
aletório entre o valor 2 e o valor 900. Seguem alguns exemplos, gerando 10 valores. No for
_ in, o _ indica que não importa o valor, pois neste caso queremos que ele apenas conte até
10, a cada conta geramos um valor randômico.
© E.L.Favero Algoritmos em Python 92

import random as rand


rand.seed(1234)
L=[rand.randint(2,900) for _ in range(10)]
print(L)
rand.seed(1234)
L=[rand.randint(2,900) for _ in range(10)]
print(L)
rand.seed(13)
L=[rand.randint(2,900) for _ in range(10)]
print(L)
>>>
[798, 453, 121, 9, 94, 828, 598, 37, 689, 711]
[798, 453, 121, 9, 94, 828, 598, 37, 689, 711]
[267, 299, 703, 702, 823, 871, 192, 669, 238, 684]

Agora que sabemos como gerar uma lista de valores aletórios vamos preencher uma matriz
com valores aletórios. Abaixo criamos uma matriz de 3 linhas por 4 colunas.
Aqui utilizamos outra forma de importação pois vamos utilizar apenas a função
randint. Nesta forma de importação não é necessário o prefixo.

from random import randint


lin=3; col=4
matriz=[]
for i in range(lin):
linha=[ (i,j,randint(1,100) ) for j in range(col)]
matriz.append(linha)
# escreve todas as linhas
for i in range(lin):print(matriz[i])
# escreve a diagonal
for i in range(lin):print(matriz[i][i])
>>>
[(0, 0, 2), (0, 1, 51), (0, 2, 48), (0, 3, 80)]
[(1, 0, 35), (1, 1, 38), (1, 2, 95), (1, 3, 54)]
[(2, 0, 30), (2, 1, 27), (2, 2, 29), (2, 3, 6)]
(0, 0, 2)
(1, 1, 38)
(2, 2, 29)

Para efeito didático, cada célula da matriz armazena uma tripla (linha, coluna, valor
aleatório). O valor aleatório é gerado com randint(1,100). Cada linha compreende 4 valores
aleatórios. Mostra-se toda a matriz com um comando for; com outro comando for, mostra-se
como acessar só a diagonal.

Python tem algumas funções poderosas, por exemplo, com zip(*) podemos transpor a
matriz: as linhas viram colunas e vice versa. O resultado do zip(*) são tuplas, cada linha é
uma tupla; com list(zip(* matriz)) as tuplas são convertidas em listas. Com o comando for, a
forma de manipular listas e tuplas é a mesma.

inv=list(zip(* matriz))
for i in range(col):print(inv[i])
>>>
((0, 0, 15), (1, 0, 72), (2, 0, 37))
((0, 1, 91), (1, 1, 33), (2, 1, 17))
((0, 2, 88), (1, 2, 87), (2, 2, 43))
© E.L.Favero Algoritmos em Python 93

((0, 3, 19), (1, 3, 11), (2, 3, 68))

Vamos ilustrar o funcionamento do zip(), fecha o zíper. Suponha a e b duas listas. zip
emparelha as duas em duplas, fecha o zíper. O unzip, zip(* ) faz o efeito ao contrário, abre o
zíper. O * transforma uma lista em elementos como argumentos.

>>> a=[1,2,3,4]
>>> b=[7,8,9,10]
>>> list(zip(a,b))
[(1, 7), (2, 8), (3, 9), (4, 10)]

>>> cd=list(zip(a,b))
>>> cd
[(1, 7), (2, 8), (3, 9), (4, 10)]
>>> list(zip(* cd))
[(1, 2, 3, 4), (7, 8, 9, 10)]

Zipper de listas

13.3.2 Mais sobre valores aleatórios random


Da biblioteca random temos mais algumas preciosidades. A primeira é escolher uma
amostra aleatória dos elementos de uma lista (sample), e a segunda é embaralhar os
elementos de uma lista (shuffle). Vamos exemplificar estes dois métodos.

import random as rd
rd.seed(15)
L=[x for x in range(12)]
print(L)
>>>
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

Primeiro geramos uma lista L com 12 valores. Agora vamos pegar duas amostra aleatórias
de 3 elementos desta lista L. O zero aleatoriamente foi selecionado nas duas amostras.

>>> rd.sample(L,3)
[3, 0, 8]
>>> rd.sample(L,3)
[11, 0, 2]
© E.L.Favero Algoritmos em Python 94

Agora vamos embaralhar a lista toda. O suffle() destrói a lista original L enquanto que o
sample() não afeta ela. Para mostrar o resultado do shuffle() é necessário mostrar o
conteúdo da lista L. Note que as duas embaralhadas são bem diferentes.

>>> rd.shuffle(L)
>>> L
[7, 6, 4, 11, 8, 9, 1, 5, 2, 10, 0, 3]
>>> rd.shuffle(L)
>>> L
[5, 2, 7, 10, 4, 6, 0, 11, 9, 3, 1, 8]

13.3.3 Perguntas conceituais (12)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C13.1 Qual a diferença entra a distância Euclidiana e distância de Manhattan?
C13.2 O que é a norma de um vetor?
C13.3 O que mede o coseno de dois vetores?
C13.4 O que faz o comando import?
C13.5 O que faz o zip()?
C13.6 O que faz o zip(* ) ?
C13.7 Porque utilizar random.seed() ?
C13.8 O que faz o shuflle()?
C13.9 O que faz o sample() ?

Responda com no mínimo 30 palavras e máximo 50 palavras


C13.10 O que é uma estrutura de dados?
C13.11 O que é um dado?
C13.12 Qual a diferença entre dado e informação?
© E.L.Favero Algoritmos em Python 95

Capítulo

14 DICIONÁRIOS E CONJUNTOS: SET


E DICT

Neste capítulo apresentamos mais dois tipos de dados do Python: set e dict. Set é
para conjuntos e dict é uma estrutura de dados flexível e sofisticada chamada de
dicionário. Um dict pode ser visto como uma espécie de generalização de listas. Um
dict também pode representar estruturas de dados tipo JSON, que são comuns na
troca de informações, por exemplo, na web.

14.1 Dicionários e Conjuntos: Set e Dict


Conjuntos (set) podem ser criados a partir de listas, sendo que neste caso os elementos
repetidos são removidos. Conjuntos aceitam operações de união intercessão e diferença.

>>> L=[1,3,1,2,7,1]
>>> len(L)
6
>>> set(L)
{1, 2, 3, 7}
>>> S=set(L)
>>> len(S)
4
>>> S.add(4)
>>> S
{1, 2, 3, 4, 7}
>>> S.remove(3)
>>> S
{1, 2, 4, 7}

>>> 2 in S
True
>>>
>>> S.union({3,8})
{1, 2, 3, 4, 7, 8}

Dicionários e conjuntos são delimitados por {}, mas este símbolo está reservado para
dicionário vazio. Conjunto vazio é igual set(). Os dicionários são estruturas de dados que
permitem mapear uma chave para um valor. Um mapeamento é uma coleção de
associações entre pares de valores, onde o primeiro elemento do par é chamado de chave e
© E.L.Favero Algoritmos em Python 96

o segundo de valor, como um conteúdo. As chaves keys() do dicionário formam um conjunto


de valores todos distintos. Os valores do dicionário podem ser repetidos.

Diagrama de representação de um dicionário

No dicionário podemos acessar só as chaves FD.keys() ou só os valores FD.values()


ou os pares de itens, FD.items(). De certa forma, a notação de dicionário é similar a de listas
-- uma generalização das listas, onde as chaves são os índices. As chaves de um dicionário
não precisam ser valores inteiros, mas devem ser valores imutáveis.

DI=dict( [('i', 5), ('c', 7), ('d', 1), ('a', 9), ('n', 5)] )

>>> DI.keys(); DI.values()


dict_keys(['i', 'c', 'd', 'a', 'n'])
dict_values([5, 7, 1, 9, 5])

DI.items()
dict_items([('i', 5), ('c', 7), ('d', 1), ('a', 9), ('n', 5)])

>>> sorted(DI.items())
[('a', 9), ('c', 7), ('d', 1), ('i', 5), ('n', 5)]

>>>DI['c']
7

Podemos também imprimir os itens ordenados pelo valor da chave. Dicionários são
acessados como listas, DI['c'], devolve o valor associado a chave 'c'. Vamos nos aprofundar
num exemplo prático, como calcular a moda de uma lista de itens.
© E.L.Favero Algoritmos em Python 97

14.2 Moda da estatística


Na estatística a moda de uma lista de valores é o valor mais frequente (um deles, se tiver
mais que um). A partir de uma string podemos fazer uma lista. A partir da lista podemos
pegar um conjunto, que é remover os elementos repetidos.

D=list('xxaaabbbakjjakjjsjs')
S=set(D)
print('d:',D,'\ns:',S)
>>>
d: ['x', 'x', 'a', 'a', 'a', 'b', 'b', 'b', 'a', 'k', …, 'j', 's']
s: {'j', 'b', 'x', 'k', 's', 'a'}

Agora vamos criar um dicionário chamado frequência de distribuição, FD, a partir de D. FD é


similar a uma lista onde o índice são as letras únicas de D, extraídas com set(). O valor de
FD guarda a frequência de cada chave em D. Vamos acessar o dicionário como uma lista
FD[‘a’]=5, FD[‘k’]=0, FD[‘k’]+=2. Um dicionário não é uma lista, pois suas chaves não são só
valores inteiros, podem ser de outros tipos.

FD= { 5, 3, 2, 2, 2, 5 }
índice ('j', 'b', 'x', 'k', 's', 'a’)

Vamos programar este dicionário de frequências. Primeiro iniciamos um dicionário vazio


FD={}. Depois zeramos todo ele, para todas as chaves. Agora percorrendo todo D vamos
somando e acumulando a contagem das frequências de cada chave.

D=list('xxaaabbbakjjakjjsjs')
S=set(D)
FD={}
for i in S: FD[i]=0
for i in D: FD[i]+=1
print('FD:',FD)
>>>
FD: {'j': 5, 'x': 2, 'k': 2, 's': 2, 'a': 5, 'b': 3}

Esta estrutura resultante FD chama-se dicionário, como uma lista de itens, pares
(chave:valor), (key:value). Neste FD para pegar a moda, o item mais frequente, ou um dos
itens mais frequentes, podemos, por exemplo, ordenar os pares (key:valor) pelo campo
valor. Segue três opções de ordenar um dicionário com sorted(). Na primeira só utilizamos
as chaves; na segunda os itens são ordenados pelo primeiro campo, a chave; na terceira os
itens ordenados pelo campo valor.

>>> sorted(FD)
['a', 'b', 'j', 'k', 's', 'x']
>>>sorted(FD.items())
[('a', 5), ('b', 3), ('j', 5), ('k', 2), ('s', 2), ('x', 2)]
>>>sorted(FD.items(), key=lambda x: x[1])
[('x', 2), ('k', 2), ('s', 2), ('b', 3), ('j', 5), ('a', 5)]

A função lambda x:x[1] pega de cada tupla o valor do índice 1, e.g. em x=('k', 2) x[0]='k' e
x[1]=2.

BOX: Uma função lambda é bem similar a uma função def, mas ela é uma espécie
de mini função, que pode ser definida dentro de uma expressão, dentro de parte de
© E.L.Favero Algoritmos em Python 98

um comando. Uma função def deve ser definida dentro de um bloco de comandos,
numa indentação. Acima exemplificamos a definição de uma função lambda dentro
do argumento de sorted(). Abaixo exemplificamos como podemos definir uma
mesma função, com lambda e com def.

soma=lambda x,y:x+y
mult=lambda x,y:x*y

def soma1(x,y): return x+y


def mult1(x,y): return x*y

print(soma(3,5), mult(7,9))
print(soma1(3,5), mult1(7,9))
>>>
8 63
8 63

A função lambda não tem o return; o retorno dela é a expressão após os dois
pontos. Podemos aplica-la diretamente nos argumentos, usando-se ela entre
parênteses:

print((lambda x,y:x+y)(3,5), (lambda x,y:x*y)(7,9))


8 63

Outra forma de inicializar um dicionário com zeros é utilizar a função fromkeys(),


visando ter um código mais simples:

>>> s = {1,2,4,5,6}
>>> dict.fromkeys(s, 0)
{1: 0, 2: 0, 4: 0, 5: 0, 6: 0}

Agora vamos codificar uma função freq() que calcula a frequência dos elementos de uma
lista. A função moda() faz uso da freq().

def freq(li): # li = lista


FD=dict.fromkeys(set(li),0)
for i in li: FD[i]+=1
return FD.items()
def moda(li):
s=sorted(freq(li),key=lambda x: x[1])
return s[-1][0] #o último, só a chave

>>> D=list('xxaaabbbakjjakjjsjs')
>>> moda(D)
'j'
>>> moda(list("abcccdddkkkkkiijjj"))
'k'

14.3 Pensamento computacional: Dicionários


Um dicionário é uma estrutura de dados poderosa e flexível. Ele permite a codificação de
estruturas de dados heterogêneas, similares ao “record” ou “struct” de outras linguagens. Na
verdade um dicionário codifica uma função com o índice como imagem e os dados como
domínio. É uma função de pode ser incrementalmente atualizada. Pela chave permite
© E.L.Favero Algoritmos em Python 99

acesso direto aos elementos, é eficiente. Como estrutura de dados, o poder de astração
do dicionário foi ilustrado na programação da função moda: usa uma função auxiliar freq(),
com duas linhas de código; na primeira linha, inicializa todos os itens do dicionário com zero
frequência; na segunda linha, com um comando for acumula as frequências; por fim, a
função moda ordena o dicionário das frequências dos termos e pega o último elemento que
contém o valor da moda. Solução simples e elegante.
Um dicionário pode ser salvo num arquivo texto como um objeto JSON-
JavaScript Object Notation. Esta notação é muito usada para intercambio de dados entre
diferentes plataformas de computação. O uso do JSON é exemplificado abaixo.

14.4 “Multiplos ifs” versus “um dicionário”


Mais um modo de refatoração. Já mostramos a solução deste exercício com um comando if,
com while, etc. Ler uma lista de supermercado com o produto, a quantidade e o tipo "a2, f6,
b20, c2". Onde produtos são letras de a..f e os valores são desta tabela: {a:10, b:60, c:40,
d:70, e:15, f:100}. Imprimir o boleto:

"""
Item qty preço subtotal
a 2 10 20
f 6 100 600
b 20 60 1200
c 2 40 80
___________________
Total 1900 """

Vamos tira o if/elif/else e colocar um dicionário. Então a função preço se rescreve com o
dicionário preço.

def preco(x):
'''{a:10, b:60, c:40, d:70, e:15, f:100}'''
if x=='a': p=10
elif x=='b': p=60
elif x=='c': p=40
elif x=='d': p=70
elif x=='e': p=15
elif x=='f': p=100
else: p=None
return p
total = 0

A estrutra de dicionário permite retornar o preço de cada item a partir da chave, do código,
que é a letra do produto. Agora temos que usar assim preco[itens[i]] antes era preco(itens[i]).
A função é com parênteses e o dicionário com colchete.

preco={'a':10, 'b':60, 'c':40, 'd':70, 'e':15, 'f':100}

lis= "a2, f6, b20, c2"


#lis=input('digite valores:')
lis1=lis.split(',')
lis1=[i.strip() for i in lis1]
print(lis1)
itens=[i[0] for i in lis1]
qti =[int(i[1:]) for i in lis1]
© E.L.Favero Algoritmos em Python 100

print(itens,qti)
total = 0
print('item qti preço subtotal')
for i in range(len(itens)):
subtotal = qti[i]*preco[itens[i]]
print(itens[i],qti[i],preco[itens[i]],subtotal)
total += subtotal
print('total:', total)
>>>
['a2', 'f6', 'b20', 'c2']
['a', 'f', 'b', 'c'] [2, 6, 20, 2]
item qti preço subtotal
a 2 10 20
f 6 100 600
b 20 60 1200
c 2 40 80
total: 1900

Três apóstrofos ou três aspas neste programa, delimitam comentários que podem ser de
múltiplas linhas.

14.5 Estruturas de dados complexas


Um dicionário permite também representar estruturas de dados complexas como registos de
dados do tipo JSON - JavaScript Object Notation.

import json

carro = {}
carro['marca'] = 'Global'
carro['modelo'] = 'Fechado'
carro['ano'] = 1978
print(carro)

str_carro=json.dumps(carro)
print(repr(str_carro))

carro1=json.loads(str_carro)
print(carro1)

>>>
{'marca': 'Global', 'modelo': 'Fechado', 'ano': 1978}
'{"marca": "Global", "modelo": "Fechado", "ano": 1978}'
{'marca': 'Global', 'modelo': 'Fechado', 'ano': 1978}

Acima, no primeiro print temos a saída do dict do Python. No segundo print usando
json.dumps() convertemos o carro (dict) num string, por exemplo, para ser gravado num
arquivo ou enviado via web. repr mantém os apóstrofos na escrita. json.loads() transforma o
string num objeto dict. No terceiro print, carro1 foi carregado a partir do string. loads pode
ser usado, por exemplo, quando lemos um json como string de um arquivo para ser
trabalhado como dict.
© E.L.Favero Algoritmos em Python 101

14.5.1 Dados json


Agora vamos ilustrar o exemplo de uso de dados estruturados no formato JSON, que será
representado num dicionário. Abaixo, o exemplo apresenta uma estrutura de dados que
armazena questões sobre expressões aritméticas.

# definindo os campos sem aspas


''' key='key';meta='meta';.. '''
key, meta,que,txt,cap,alter,tipo,tema,grau=tuple(
"key,meta,que,txt,cap,alter,tipo,tema,grau".split(','))

# uma lista de questões com meta dados


QUE1={key:1,
meta:{tipo:'MM',cap:'2',
grau:'F', tema:'expressões aritméticas'},
txt:'O valor da expressão:',
que:
[
{txt:'>>> 2**3', alter: [0,6,8,27, 8]},
{txt:'>>> 2 % 3', alter:[0,1,2,3,1.5, 2]},
{txt:'>>> float(2 % 3)', alter:[0,1.0,2.0,3,1.5, 2.0]},
{txt:'>>> 2 // 3',alter: [0,6,8,27, 0]},
{txt:'>>> float(2 // 3)',alter: [0.0,6.0,8,27, 0.0]},
{txt:'>>> int(2 / 3)',alter: [0,1,2,3,0]},
{txt:'>>> float(2 / 3)',alter: [0.6666,1.0,2,3.3333,0.6666]},
{txt:'>>> 20 % 3', alter:[0,1.0,2, 2.0, 1.5, 2]},
{txt:'>>> 20 // 3', alter:[6,6.0,6.666,3.333,1.5, 6]},
{txt:'>>> int(20 / 3)', alter:[6,6.0,6.666,3.333,1.5, 6]},
{txt:'>>> float(20 / 3)', alter:[6,6.0,6.666,3.333,1.5, 3.333]},
{txt:'>>> 3 - 2 * 4 ', alter:[0,4,-5,4.0,-2, -5]},
{txt:'>>> 3 * 2 ** 2', alter:[0,7,12,36,100, 12]}
]
}

Nesta estrutura existem dois campos txt. O primeiro txt: 'O valor da expressão:' é valido para
todas as questões. O segundo é especifico de cada uma delas, definindo o final do
enunciado, e.g. txt:'>>> 2**3'. O campo alter define as alternativas de respostas para a
múltipla escolha (4 opções), sendo que a última opção é a resposta correta. Os dados de
QUE1 são acessados via chaves QUE1[chave][chave], por exemplo, QUE1[meta][cap]= '2',
seguem alguns testes.

>>>print(QUE1[meta])
{'tipo': 'MM', 'cap': '2', 'grau': 'F', 'tema': 'expressões
aritméticas'}

>>>print(QUE1[meta][cap])
2

>>>print(QUE1[que][4])
{'txt': '>>> float(2 // 3)', 'alter': [0.0, 6.0, 8, 27, 0.0]}

Note que no print todos os nomes de campos são apostrofados. Foi por isso que no início do
código fizemos um mapeamento key='key', meta='meta', etc. visando não precisar escrever
tantos apóstrofos no código da programação.
© E.L.Favero Algoritmos em Python 102

Para facilitar a manipulação dos dados vamos definir duas funções, temaQQ() e renderQQ().
A primeira simplesmente devolve o tema de QUE1; enquanto que a segunda renderiza,
transforma QUE1 numa lista de questões.

def temaQQ(q): return 'Cap '+q[meta][cap]+': '+q[meta][tema]


def renderQQ(q):
if q[meta][tipo]=='MM':
txt1=q[txt];
qx=[]
for i in range(len(q[que])):
(_,tx),(_,ax)=q[que][i].items()
qx +=[(txt1+'\n'+tx, ax)]
return qx
else: return None
q1=QUE1
print('tema das questões:',temaQQ(q1))
print('todas as questões:')
for q in renderQQ(q1): print(q)
>>>
tema das questões: Cap 2: expressões aritméticas
todas as questões:
('O valor da expressão:\n>>> 2**3', [0, 6, 8, 27, 8])
('O valor da expressão:\n>>> 2 % 3', [0, 1, 2, 3, 1.5, 2])
('O valor da expressão:\n>>> float(2 % 3)', [0, 1.0, 2.0, 3, 1.5,
2.0])
('O valor da expressão:\n>>> 2 // 3', [0, 6, 8, 27, 0])
...

Com estas questões renderizadas podemos aplicar diferentes mini provas para diferentes
usuários, tipo 3 questões por prova.

from random import sample


QQ=renderQQ(QUE1)
prova1=sample(QQ,3)
prova2=sample(QQ,3)
print('prova1 aleatoria:\n',prova1)
print('prova2 aleatoria:\n',prova2)
print()
print('prova1 1ra que cabeçalho:\n',prova1[1][0])
print('prova1 1ra que alter :\n',prova1[1][1][:-1])
print('prova1 1ra que correta :\n',prova1[1][1][-1])
>>>
prova1 aleatoria:
[('O valor da expressão:\n>>> 3 * 2 ** 2', [0, 7, 12, 36, 100, 12]),
('O valor da expressão:\n>>> float(20 / 3)', [6, 6.0, 6.666, 3.333, 1.5,
3.333]),
('O valor da expressão:\n>>> 3 - 2 * 4 ', [0, 4, -5, 4.0, -2, -5])]
prova2 aleatoria:
[('O valor da expressão:\n>>> 2**3', [0, 6, 8, 27, 8]),
('O valor da expressão:\n>>> float(2 / 3)', [0.6666, 1.0, 2, 3.3333,
0.6666]),
('O valor da expressão:\n>>> 2 // 3', [0, 6, 8, 27, 0])]

prova1 1ra que cabeçalho:


O valor da expressão:
>>> 3 - 2 * 4
prova1 1ra que alter :
© E.L.Favero Algoritmos em Python 103

[0, 4, -5, 4.0, -2]


prova1 1ra que correta :
-5

Projeto. Faça um programa a partir do código acima que exiba a prova com três questões
aleatórias mostrando as opções; peça para entrar as três respostas, no formato ‘1b 2d 3e’,
quebre a string e cheque o número de respostas corretas, comparando a opção com alter[-
1]. Defina algumas funções auxiliares, como escreveQue(prova1[1]) que escreve uma das
três questões de uma prova; escreveAlter(prova1[1][1][:-1]) para escrever as alternativas de
uma questão, etc. Assim o código ficará limpo e organizado.

Questão 1. Marque a alternativa correta.


O valor da expressão:
>>> 3 * 2 ** 2
b) 0
c) 7
d) 12
e) 36
f) 100
Questão 2. Marque a alternativa correta.
...
Digite as suas escolhas na forma (1b 2d 3e):

14.5.2 Perguntas conceituais (4)


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C14.1 Qual a diferença de uma lista, list(), para um conjunto, set() ?
C14.2 O que é um dicionário ?
C14.3 È possível representar um dicionário numa lista ?
C14.4 É possível representar uma lista num dicionário ?
© E.L.Favero Algoritmos em Python 104

Capítulo

15 PERFORMANCE DE FUNÇÕES
Mostramos várias alternativas de codificação da função fatorial e como escolher a
melhor delas. Com comandos for, while, com recursividade e com reduce.

15.1 Vários fatoriais


Podemos programar o algoritmo do fatorial de várias formas diferentes. Iniciamos com duas
versões mudando o comando de repetição, uma com for e outra com while. Uma terceira
versão só com if+recursividade.

L=[0,1,2,6,8,20]
def fatf(n):
if n==0: return 1
res=1
for i in range(2,n+1):
res=res*i
return res
print('fatorial com for:')
for i in L: print('Fat de %d é %d' % (i,fatf(i)))

def fatw(n):
num = 1
while n >= 1:
num = num * n
n = n - 1
return num
print('fatorial com while:')
for i in L: print('Fat de %d é %d' % (i,fatw(i)))

def fatr(n):
if n==0: return 1
return n*fatr(n-1)
print('fatorial com recursividade:')
for i in L: print('Fat de %d é %d' % (i,fatr(i)))
>>>
fatorial com for:
© E.L.Favero Algoritmos em Python 105

Fat de 0 é 1
Fat de 1 é 1
Fat de 2 é 2
Fat de 6 é 720
Fat de 8 é 40320
Fat de 20 é 2432902008176640000

Temos mais três versões. Estas são para quem gosta do paradigma de programação
funcional, as três usam a função reduce(). Na primeira colocamos uma função mult()
definida com def; na segunda mult() é definida como uma função lambda() e na terceira
mult() vem de uma biblioteca de operadores, codificada em C.

import functools as ft, operator as op


def mult(x,y): return x*y
def fatt(n):
if n == 0: return 1
return ft.reduce(mult,range(1,n+1))
def fatt2(n):
if n == 0: return 1
return ft.reduce(lambda x,y: x*y, range(1,n+1))
def fatt3(n):
if n == 0: return 1
return ft.reduce(op.mul, range(1,n+1))
L=[0,1,2,6,8,20]
for i in L: print('Fat de %d é %d' % (i,fatt(i)))
for i in L: print('Fat de %d é %d' % (i,fatt2(i)))
for i in L: print('Fat de %d é %d' % (i,fatt3(i)))

Para entender como funcionam estas diferentes formas de fazer a multiplicação, vamos
inspecionar o código assembler, código da maquina vitual do Python, byte code. Usa-se a
função dis() (disassembler). Podemos ver que as duas funções def mult() e lambda x,y: x*y,
produzem o mesmo código assember (byte code).

from dis import dis


>>>dis(mult)
3 0 LOAD_FAST 0 (x)
2 LOAD_FAST 1 (y)
4 BINARY_MULTIPLY
6 RETURN_VALUE
>>> dis(lambda x,y: x*y)
1 0 LOAD_FAST 0 (x)
2 LOAD_FAST 1 (y)
4 BINARY_MULTIPLY
6 RETURN_VALUE
>>> dis(op.mul)
TypeError: don't know how to disassemble builtin_function_or_method

15.2 Testando a performance de um algoritmo


Agora vamos testar o tempo de execução das diferentes formas de fazer a solução do
fatorial verificando qual é mais eficiente, mais rápida e que gasta menos tempo na
execução. Encontrar soluções eficientes é um dos objetivos de projetar algoritmos. Note que
no código abaixo colocamos os nomes das funções dentro de uma lista. Listas servem para
© E.L.Favero Algoritmos em Python 106

tudo até para colecionar nomes de funções, que são objetos de trabalho dos
programadores.

import time as t
miliseg=t.time
def testa(f):
t0 = miliseg()
for i in range(100000): f(40)
t1 = miliseg()
print (round(t1-t0,4), "mili seg:", f, f(7))
for f in [fatf,fatw,fatr,fatt, fatt2,fatt3]: testa(f)
>>>>
0.469 mili seg: <function fatf at 0x03E12660> 5040
0.7979 mili seg: <function fatw at 0x0406A078> 5040
1.2064 mili seg: <function fatr at 0x0406A0C0> 5040
0.8138 mili seg: <function fatt at 0x0406A150> 5040
0.8138 mili seg: <function fatt2 at 0x0406A198> 5040
0.4867 mili seg: <function fatt3 at 0x0406A1E0> 5040

A função testa() executa o código 100.000 vezes para dar mais estabilidade no tempo
medido. Pois, se medimos com tempos pequenos a precisão diminui. A versão de pior
desempenho foi a recursiva. As melhores foram a primeira e a última, com for e a funcional
com a multiplicação codificada na biblioteca de operadores.

15.3 Exercícios (4)


E6.1 Faça o fatorial usando for e range()
def fatf(n):
if n==0: return 1
res=1
for i in range(2,n+1):
res=res*i
return res
L=[0,1,2,6,8,20] ; print('fatorial com for:')
for i in L: print('Fat de %d é %d' % (i,fatf(i)))

E6.2 Faça o fatorial usando while


def fatw(n):
num = 1
while n >= 1:
num = num * n
n = n - 1
return num

E6.3 Faça o fatorial usando recursividade


def fatr(n):
if n==0: return 1
return n*fatr(n-1)

E6.4 Faça o fatorial usando reduce()


def fatt2(n):
if n == 0: return 1
return ft.reduce(lambda x,y: x*y, range(1,n+1))
L=[0,1,2,6,8,20] ; print('fatorial com for:')
© E.L.Favero Algoritmos em Python 107

for i in L: print('Fat de %d é %d' % (i,fatt2(i)))

15.3.1 Perguntas conceituais


Responda com no mínimo 30 palavras e máximo 50 palavras
C11.3 Qualalgoritmo é melhor, o mais simples de ler, mais legível ou o mais eficiente, mais
rápido, que usa menos memória?
© E.L.Favero Algoritmos em Python 108

Capítulo

16 APLICAÇÃO DE CÁLCULO
NUMÉRICO

Este capítulo apresenta vários exemplos de aplicações da área de cálculo numérico.


O objetivo é ilustrar diferentes formas e recursos da linguagem Python para a
computação numérica. Mostramos como trabalhar com funções matemáticas e como
trabalhar com vetores de bits utilizando as operações sobre cadeias de bits.

16.1 Cálculo númerico


Apresentaremos alguns exemplos de como podemos codificar séries e métodos de
aproximação de funções em Python.

16.1.1 Número harmônico


Dado um número inteiro n>0, determinar o seu número harmônico h(n) dado pela série
abaixo.

Esta série pode ser escrita como h(n)=sum([1/i for i in range(1,n+1)]); para range(1,n+1),
pois o intervalo final é aberto. Vamos apresentar três versões: com sum() sobre uma lista,
com for e com while.

def h(n): return sum([ 1/i for i in range(1,n+1) ])


def h1(n):
s=0
for i in range(1,n+1): s+=1/i
return s
def h2(n):
s=0; i=1
while i<=n:s+=1/i; i+=1
return s
print('h(10**4)=', h(10**4))
© E.L.Favero Algoritmos em Python 109

print('h1(10**7)=', h1(10**7))
print('h2(10**7)=', h2(10**7))
>>>
h(10**4)= 9.787506036044348
h1(10**7)= 16.69531126585727
h2(10**7)= 16.69531126585727

16.1.2 Método de Newton


Aproximar √3 pelo Método de Newton, com precisão de erro=1e-10. Para encontrar uma
aproximação para √3, fazemos:

Logo:

Seja f = lambda x: x**2-3, e a derivada df=lambda x:2*x. Pode-se generalizar a fórmula


substituindo-se o 3 por um N. Assim f = lambda x,N: x**2-N, para encontar a raiz quadrada
de N.

A equação de aproximação dos termos é dada acima. Ela pode ser codificada como x1=x0-
f(x0)/df(x0). Devemos notar aqui a elegância da definição da função f e de sua derivada df
como duas funções lambda.

erro=1e-10
f =lambda x,y: x**2-y
df=lambda x: 2*x
def raiz2(N):
x0 = N/2
delta=1000
while delta>erro:
x1 = x0-f(x0,N)/df(x0)
delta= abs(x1-x0)
print(x1, delta)
x0=x1
return x1

print('raiz de 3', raiz2(3), 3**0.5)


print('raiz de 30', raiz2(30), 30**0.5)
>>>
'''
1.75 0.25
1.7321428571428572 0.017857142857142794
1.7320508100147276 9.204712812960203e-05
1.7320508075688772 2.445850411092465e-09
1.7320508075688774 2.220446049250313e-16
raiz de 3 1.7320508075688774 1.7320508075688772
8.5 6.5
© E.L.Favero Algoritmos em Python 110

6.014705882352941 2.485294117647059
5.501240471738818 0.5134654106141232
5.477277991889814 0.023962479849004126
5.477225575302472 5.241658734167487e-05
5.477225575051661 2.5081092758227896e-10
5.477225575051661 0.0
raiz de 30 5.477225575051661 5.477225575051661
'''

16.1.3 Método de Herão de Alexandria


O método de Herão de Alexandria é usado para cálculo da raiz quadrada de um número.
Dada a raiz quadrada de um número n, assumindo a0 como uma aproximação inicial. A
equação do primeiro termo é dada abaixo; pode-se iterar fazendo a1=a0.

Esta fórmula pode ser escrita como a1=(ao+N/a0)/2. Vamos assumir que o valor inicial é
N/2. Assim na primeira iteração a0=N/2. Depois a0=a1, prosseguindo até a convergência
com dez casas decimais, um erro=1e-10.

erro=1e-10
def raiz(N):
a0 = N/2
delta=1000
while delta>erro:
a1=(a0+N/a0)/2
delta=abs(a0-a1)
print(a1, delta)
a0=a1
return a1

print('raiz de 1.5', raiz(1.5), 1.5**0.5)


print('raiz de 20', raiz(20), 20**0.5)
>>>
'''
1.375 0.625
1.2329545454545454 0.14204545454545459
1.2247722036028488 0.00818234185169664
1.224744871696564 2.7331906284677743e-05
1.224744871391589 3.0497515624006155e-10
1.224744871391589 0.0
raiz de 1.5 1.224744871391589 1.224744871391589
6.0 4.0
4.666666666666667 1.333333333333333
4.476190476190476 0.1904761904761907
4.472137791286727 0.004052684903749437
4.472135954999956 1.836286770640072e-06
4.47213595499958 3.765876499528531e-13
raiz de 20 4.47213595499958 4.47213595499958
'''
© E.L.Favero Algoritmos em Python 111

16.1.4 Aproximar exp() ou ex


Aproximar o valor de exp(x) ou ex, pela série dada abaixo. Vamos definir uma função fat() e
utilizar a função pow(x,n) para fazer xn . Definimos um erro=1e-10 para dez casas decimais.

def fat(n):
ft=1;
for i in range(2,n+1): ft *= i;
return ft
def e(x):
XYZ=[]
erro=1e-10
e0=1+x;i=2
delta=1000
while delta>erro:
e1= e0 + pow(x,i)/fat(i)
i+=1
delta=abs(e1-e0)
e0=e1
print(e1, delta)
XYZ.append((i,e1,delta))
return e1,XYZ

import math
PI=math.pi
# math.exp(math.pi) : 23.1406926328
print('fat:', fat(2), fat(5), fat(7));
e1,XYZ=e(PI)
print('e(PI):', e1, math.exp(PI))

[X,Y,Z]=list(zip(* XYZ))

from matplotlib import pyplot as plt


from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(X,Y,Z, '.')
ax.legend()
plt.show()

>>>
fat: 2 120 5040
9.076394854134472 4.934802200544679
14.244107634184441 5.167712780049969
18.30281976060121 4.0587121264167685
...
23.140692632767177 7.700862170167966e-11
e(PI): 23.140692632767177 23.140692632779267
© E.L.Favero Algoritmos em Python 112

Abaixo temos o gráfico plotado pelas linhas de código do programa. Salvamos na variável
XYZ, lista de triplas, os valores para gerar o gráfico. Com list(zip(*)) eles foram
desempacotados para os três vetores, um para cada dimensão.
© E.L.Favero Algoritmos em Python 113

Capítulo

17 OPERAÇÕES SOBRE BITS E BYTES


Este capítulo apresenta as expressões lógicas como uma preparação para vermos os
comandos condicionais e de repetição. São apresentadas as tabelas verdade para os
operadores lógicos.

17.1 Operações sobre bits e bytes


As linguagens de programação sempre oferecem vários operadores para se trabalhar com
os bits da representação dos dados, por exemplo, dos valores inteiros.

x&y bit and


x|y bit or
x^y bit xor
x << n x shifted esq n bits
x >> n x shifted dir n bits
~x Inverte os bits

Nesta tabela temos as operações sobre os bits que são ilustradas com o programa a seguir.
Nele vamos definir duas constantes a e b e exemplificar uma operação para cada operador.
Vamos trabalhar com 8 bits ou um byte para ilustrar as operações. 8 bits é um byte. Temos
algumas funções para imprimir os valores utilizando uma formatação que permite a
visualização das duas listas de bits uma sobre a outra. Para um leitor iniciante, as funções
abaixo são complexas, sugerimos apenas uma leitura superficial; a complexidade vem do
comando de formatação format() que serve para alinhar colunas de números, ver web.

a = int('00111100',2)
b = int('00001101',2)
def bi(x):
if x>=0: return '{:>0{}b}'.format(x,8)
else : return '{:>0{}b}'.format( abs(abs(x)-(1<<8)),8)
© E.L.Favero Algoritmos em Python 114

def prt(s,x): print('{:>7}='.format(s), bi(x), x)


def prt_(s,x): print('{:_>7}='.format(s), bi(x), x)

prt('a',a);prt_('b',b);prt('and a&b',a&b);print()
prt('a',a);prt_('b',b);prt('or a|b',a|b);print()
prt('a',a);prt_('b',b);prt('xor a^b',a^b);print()

prt_('a',a);prt('not ~a',~a);print()
prt_('a',a);prt('a << 2',a<<2);print()
prt_('a',a);prt('a >> 2',a>>2);print()

O efeito das operações binárias (& | ^) é fácil de visualizar quando os dois operandos são
mostrados um em cima do outro. O and só é 1 se ambos os bits são 1. O or é 1 se um deles
é 1. O and busca zerar e o or ao contrário tenta fazer tudo 1. O xor é 1 somente onde os bits
são diferentes.

a= 00111100 60
______b= 00001101 13
and a&b= 00001100 12

a= 00111100 60
______b= 00001101 13
or a|b= 00111101 61

a= 00111100 60
______b= 00001101 13
xor a^b= 00110001 49

As operações unarias (~ >> <<) tem um só operando, neste caso estamos exemplificando
com o operando a. O not simplesmente inverte os bits. Como valor inteiro ele troca de sinal.
Nesta situação foi necessário fazer alguns ajustes em bi() para acomodar a impressão de
valores negativos como complemento de 2´s. O deslocamento para esquerda multiplica por
2, se for duas vezes multiplica por 4 e para a esquerda divide por 2, se for duas vezes divide
por 4.

______a= 00111100 60
not ~a= 11000011 -61

______a= 00111100 60
a << 2= 11110000 240

______a= 00111100 60
a >> 2= 00001111 15

BOX: Representação de números negativos em complemento de 2. A idéia é


que o primeiro bit representa o sinal. Se for 1 é um número negativo. Todo
número binário em princípio é positivo. Mas como os inteiros são positivos e
negativos precisamos de um artifício para representar números inteiros
negativos como valores binários. “Complemento de dois” é uma forma de
representar números inteiros negativos. A teoria é simples, para obter a
representação negativa de um número inteiro deve-se inverter todos os bits e
somar 1. Neste caso o primeiro bit representa o sinal. Por exemplo, 1001
representa o -7:
© E.L.Favero Algoritmos em Python 115

1001 invertido fica 0110 +1 fica 0111,


01111= 2**2+2**1+2**0 = 7,
como é negativo fica -7

Agora se queremos passar de -7 para a representação em complemento de


2: primeiro tiramos o sinal: fica 7; depois representamos os bits 111 agora
subtraímos 1 que fica 110, inverte os bits fica 001 e acrescenta o sinal 1001.
Que é a representação de -7 em complemento de 2. É o processo inverso do
que foi mostrado para chegar no -7.

17.2 Crivo de Eratostenes


Para ilustarar uma aplicação usando operadors sobre bits, vamos ver um algoritmo do Crivo
de Eratostenes: Encontrar os primos menores que um valor n. Assume um vetor de n
elementos (usar range n). Inicialmente todos são assumidos primos. Partindo do 2, remove-
se todos os múltiplos de cada um dos primos: coloca-se false nos índices associados aos
múltiplos. No primeiro passo todos os índices múltiplos de 2 são falseados. No próximo
todos os múltiplos de 3 são falseados, etc.

def primo(n):
PRI =[True]*n
PRI[0:2]=[False,False]
for i in range(2,n):
if PRI[i]:
for j in range(i*i,n,i):PRI[j]=False
return [i for i in range(len(PRI)) if PRI[i]==True]

#
>>> primo(100)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, …, 79, 83, 89, 97]

17.3 Escovando os bits


O método acima gasta muita memória para representar a lista de todos os números até n,
uns 4 bytes para cada valor boolean. Mas se pode codificar uma lista primo como um vetor
de bits, assim seria um bit para cada valor primo. Reduziria em muito a memória, mas vai
penalizar o processamento pois vamos ter que setar os bits, fazendo movimentação de bits
(escovando os bits). O tempo de processamento a mais é uma espécie de barulho das
operações de (des)empacotamento (bit x int) e movimentação dos bits.
Agora vamos aprender algo sobre “escovar bits”, termo utilizado para inspecionar
e/ou manipular os bits dos valores da memória do computador.

>>> 23<<1
46
>>> 23*2
46
>>> bin(1)
'0b1'
>>> bin(1<<5)
'0b100000'
>>> 1<<5
32
bin(1<<2)
'0b100'
© E.L.Favero Algoritmos em Python 116

Aqui podemos ver como funcionam as operações sobre bits. O shift left <<1 de uma posição
equivale a multiplicar por 2: 23<<1=46=23*2. O 1<<5 é o mesmo que 2**5, é o mesmo que
ligar o bit na posição 5 (da direita para a esquerda começando por 0). Com este esquema é
fácil ligar somente um bit de uma posição, por exemplo, (1<<32) liga o bit 32. Se fazemos
bin((1<<5)-1) nós ligamos todos os 5 bits – o menos um força todos para 1, na
representação complemento de 2. Se numa lista de uns, fazemos um shift para a esquerda
<< acrescentamos zeros na direita
Aqui estamos trabalhando com inteiros, que são também negativos. Se na
representação binária tem 1 no início são inteiros negativos. Então valem os conceitos
sobre a representação dos valores binários negativos mencionados no capítulo 1, sobre
complemento de 2.

>>> 1<<32
4294967296
>>> bin(1<<32)
'0b100000000000000000000000000000000'
>>> bin((1<<5)-1)
'0b11111'
bin((1<<7)-1)
'0b1111111'
>>> bin(((1<<7)-1)<<3)
'0b1111111000'

O crivo inicialmente assume que todos são primos exceto o 1 e o 2. Podemos inicializar um
vetor de bits, zerando as duas primeiras posições do 1 e do 2. Usando as técnicas
mostradas vamos criar uma lista de uns, com as duas primeiras posições da direita zeradas.

>>> limit=32
>>> bits = ((1 << (limit - 2)) - 1) << 2
>>> bin(bits)
'0b11111111111111111111111111111100'

A função rangeBit() define um padrão como se fosse um for sobre uma cadeia de bits,
ligando só os correspondentes, só os pares, só os múltiplos de 3, 5, 7 etc. O objetivo é
eliminar os múltiplos de um número primo. nZeros indica quantos zeros a direita devem ser
preenchidos.

def rangeBit(nZeros, step, limit):


bits = 1 << nZeros
max = 1 << limit
while bits < max:
bits = bits+(bits << step)
step = step<<1
return bits

print(bin(rangeBit(10,2,40))[-40:])
print(bin(rangeBit(20,2,40))[-40:])
print(bin(rangeBit(10,4,40))[-40:])
>>>
0101010101010101010101010101010000000000
0101010101010101010100000000000000000000
0100010001000100010001000100010000000000
© E.L.Favero Algoritmos em Python 117

for i in [2,3,5,7]:
bi=rangeBit(i,i,32)
print(i, bin(bi)[-32:])
>>>
2 01010101010101010101010101010100
3 01001001001001001001001001001000
5 01000010000100001000010000100000
7 00010000001000000100000010000000

A nova solução primoBit envolve um misto de operações aritméticas com operações sobre
bits. Com rangeBit() pode-se recodificar a função que gera os primos pelo crivo de
Eratostenes. Aqui o vetor de True e False é um vetor de bits simulado sobre um valor inteiro
com precisao “infinita”. O infinita está entre aspas pois na prática sempre será finita, mas em
Python um inteiro pode ser muito longo.
Um bit para cada primo é muito menos espaço. Se um Bool for 4 bytes, 32 bits, a
economia de espaço e de 32 vezes.

import time as t
miliseg=t.time
def testa(fun,I):
t0 = miliseg()
print(list(fun(100000))[-10:]) # escreve os 10 ultimos
#print(max(fun(I))) # escreve o último
t1 = miliseg()
print ('tempo:',round(t1-t0,4),fun)

def primoBit(limit=10000):
PRI=[2]
raiz_limit = int(limit**0.5)
vetBits = ((1 << (limit - 2)) - 1) << 2
# caminha sobre os impares
for i in range(3, limit, 2):
if not (vetBits & (1 << i)):continue
PRI.append(i)
# exclui todos os múltiplos de um primo i
if i <= raiz_limit:
vetBits &= ~rangeBit(i * i, i*2, limit)
return PRI
testa( primoBit, 100000)
testa( primo, 100000)
>>>
[99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, 99989,
99991]
tempo: 0.3005 <function primoBit at 0x03DB52F8>
[99877, 99881, 99901, 99907, 99923, 99929, 99961, 99971, 99989,
99991]
tempo: 0.066 <function primo at 0x03DB5220>

A mais convencional primo foi mais eficiente em termos de tempo, 5x mais rápida.
Mas ganhou em espaço. Neste caso economizamos de colocar todos os primos a
serem gerados numa lista, que também ocuparia muito espaço. Rodando a função
primoBit() para 100000 ela retorna que o max() primo é 99991.
© E.L.Favero Algoritmos em Python 118

17.3.1 Perguntas conceituais


Responda com no mínimo 10 palavras e no máximo 20 palavras:
C5.9 Qual a diferença entre os operadores and e &?
C5.10 Qual a diferença entre os operadores or e I?

Você também pode gostar