Buscar

Introdução a Algoritmos e Programação com Python Uma abordagem dirigida por testes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 63 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 63 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 63 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 1 
Introdução a Algoritmos e Programação 
com Python 
Uma abordagem dirigida por testes 
Raul Sidnei Wazlawick 
Elsevier, 2017 
 
Respostas aos Exercícios 
Existem virtualmente infinitas formas de escrever programas para resolver cada problema. 
Neste documento apresentamos a forma que nos parece mais simples, mais correta e mais 
adequada ao estilo Python de programar. Aconselhamos, porém, que você só recorra a esta 
lista depois de ter feito cada programa proposto e visto que ele funciona. Então você poderá 
verificar se a estratégia que usou era realmente a mais simples. Caso você tenha feito um 
programa melhor do que as minhas sugestões, entre em contato e me avise! Haverá um 
agradecimento especial na próxima edição do livro. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 2 
2 Alô Mundo 
2.1 
print('Lista de compras:\n\nMamão\nPão\nCafé') 
2.2 
O seguinte programa vai mostrar que o resultado é -6: 
print(2+2-2*2+(2-2*(2+2))) 
Confirma a evolução das operações na tabela abaixo. Primeiramente é executada a expressão 
2+2 dos parênteses mais internos (Passo 1), restando avaliar: 2+2-2*2+(2-2*4). Em seguida, é 
avaliada a multiplicação 2*4 (Passo 2) dentro do que agora se constitui nos parênteses mais 
internos, restando avaliar: 2+2-2*2+(2-8). Em seguida é avaliada a expressão 2-8 dentro dos 
parênteses (Passo 3), restando avaliar depois: 2+2-2*2-6; observe que como o resultado da 
expressão 2-8 é negativo, a soma 2+(2-8) é convertida na subtração 2-6. Agora que não há 
mais parênteses na expressão, avalia-se a única multiplicação que restou, 2*2 (Passo 5), e em 
seguida as somas e subtração da expressão: 2+2-4-6 (Passos 6 a 8). Nesta última expressão, 
todos os operadores têm a mesma precedência e, portanto, são avaliados da esquerda para a 
direita, restando sucessivamente as seguintes expressões: 4-4-6, depois 0-6 e finalmente -6, o 
resultado final da expressão. 
Passo Expressão 
1 2+2-2*2+(2-2*(2+2)) 
2 2+2-2*2+(2-2*4) 
3 2+2-2*2+(2-8) 
4 2+2-2*2-6 
5 2+2-4-6 
6 4-4-6 
7 0-6 
8 -6 
2.3 
Supondo que seu peso seja 83 kg e sua altura 1,79m, o programa a seguir vai informar que seu 
índice de massa corporal (IMC) é igual a 25.90431010268094: 
print(83/(1.79*1.79)) 
Erros comuns que você pode ter cometido: 
1. Esquecer que a divisão e multiplicação têm ambas a mesma precedência e que são 
executadas da esquerda para a direita. Assim, se você esquecer os parênteses e 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 3 
escrever print(83/1.79*1.79) vai obter como resultado 83, ou seja, o peso original, já 
que ele será primeiro dividido pela altura e depois multiplicado pela altura novamente. 
2. Trocar o ponto decimal por vírgula, como em print(83/(1,79*1,79)) ou 
print(83/1,79*1,79). No primeiro caso, o programa dará erro pois as vírgulas estão 
dentro dos parênteses da expressão numérica e não separando argumentos. No 
segundo caso, o resultado seria 83.0 79 79, ou seja, 83/1, 79*1 e 79. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 4 
3 Variáveis 
3.1 
• Elefante – o interpretador aceita como identificador, mas não deve ser usado como 
nome da variável por questão de estilo: variáveis em Python devem iniciar por letra 
minúscula. Assim, o correto seria "elefante". Mais adiante veremos casos em que 
identificadores devem iniciar com letra maiúscula. 
• madeira – identificador válido para variáveis. 
• casaDePedra – o interpretador aceita como identificador, mas não deve ser usado por 
questão de estilo, pois identificadores de variáveis com nomes compostos devem usar 
o estilo snake_case. Assim, o correto seria "casa_de_pedra". 
• tábua_de_passar – identificador válido para variáveis, desde que o sistema permita 
letras acentuadas. 
• linha42 – identificador válido para variáveis. 
• 3a_dimensão – inválido, pois inicia com algarismos numéricos. Opções válidas seriam 
"terceira_dimensão" ou ainda "dimensão3". 
• validação&verificação – inválido pois contém um caractere especial "&". O correto 
seria "validação_e_verificação". 
• 14bis – inválido pois inicia em número. Opções válidas: "quatorze_bis" ou 
"modelo_14_bis". 
• continue – inválido pois é palavra reservada de Python. Confira a lista apresentada um 
pouco antes do enunciado do exercício. 
3.2 
x = 45 # aqui x=45 
y = 14 # aqui x=45 e y=14 
z = x // y # aqui x=45, y=14 e z=3 
print(z) # aqui imprime 'z': 3 
z = y % z # aqui x=45, y=14 e z=2, 'z' mudou 
print(x) # aqui imprime x: 45 
y = 10 # aqui x=45, y=10 e z=2, 'y' mudou 
print(z) # aqui imprime z: 2 
Erros comuns: 
• Achar que no final "z" vale 0 no final porque "y" passou a valer 10 e 10 % 2 é igual a 0. 
Isso não acontece porque os comandos são executados em sequência e quando o 
valor de "z" foi atualizado pela última vez, "y" ainda valia 14. Mesmo que "y" seja 
alterado depois disso, o valor de "z" permanece sendo o que era em sua última 
atribuição. 
• Achar que o programa vai imprimir 3, 2 e 10, que são os últimos valores calculados 
antes do comando "print". Isso não acontece porque o comando "print" imprime a 
variável que é passada como argumento, e não o valor da última variável atualizada no 
programa. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 5 
Com este exemplo podemos introduzir uma importante técnica de verificação de programas 
chamada "trace table" ou "tabela de rastreamento", que por um grosseiro erro de tradução de 
décadas atrás acabou sendo conhecido em português como "teste de mesa" ("table" tanto 
pode ser traduzido como "tabela" quanto como "mesa" e em algum momento nos anos 1970 
algum autor optou pela tradução menos adequada e assim "trace table" acabou virando "teste 
de mesa" para muitos programadores brasileiros). 
Uma tabela de rastreamento terá as variáveis do programa indicadas nas colunas e cada linha 
representará os valores de cada variável após a execução de cada linha do programa. Para não 
ter que escrever todos os comandos dentro da tabela usualmente se trabalha com os números 
das linhas dos comandos executados, como mostrado abaixo: 
1 x = 45 
2 y = 14 
3 z = x // y 
4 print(z) 
5 z = y % z 
6 print(x) 
7 y = 10 
8 print(z) 
Assim, a tabela de rastreamento para o programa deste exercício poderia ser representada da 
seguinte forma: 
Linha x y z 
1 45 - - 
2 45 14 - 
3 45 14 3 
4 45 14 3 
5 45 14 2 
6 45 14 2 
7 45 10 2 
8 45 10 2 
Para simplificar essa tabela podemos representar nela apenas os valores que foram 
modificados em cada linha (valores em negrito na tabela anterior). Dessa forma, o valor de 
uma variável em uma linha será aquele que for encontrado na própria linha ou na linha 
anterior mais próxima da atual e acima dela onde esse valor seja definido: 
Linha x y z 
1 45 - - 
2 14 - 
3 3 
4 
5 2 
6 
7 10 
8 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 6 
 
Assim, observando a tabela, o valor das variáveis na linha 6 por exemplo será 45 para "x", 
porque "x" recebeu esse valor na linha 1 e não mudou mais até a linha 6, 14 para "y" porque 
"y" recebeu esse valor na linha 2 e não mudou mais até a linha 6, e 2 para a variável "z", 
porque "z" recebeu esse valor na linha 5 e não mudou na linha 6. 
3.3 
print('{0} e {1} são {2} e {3}'.format(x, y, a, b)) 
print('Total: {0}'.format(x+y)) 
print('{0} {1} {2} são números inteiros'.format(a, b, c)) 
print('{0} + 0= {0}'.format(z)) 
 
Aqui o exercício era apenas para escrever as expressões. O programa não irá rodar porque os 
valores das variáveis não foram definidos. 
3.4 
print('{0}/{1}/{2}'.format(dia, mês, ano)) 
 
Da mesma forma, aqui o programa não deve ser rodado, apenas a linha escrita para fim de 
resolução do exercício. 
3.5 
print('Este programa calcula a média de três valores') 
a = int(input('Primeiro valor:')) 
b = int(input('Segundo valor:')) 
c = int(input('Terceiro valor:')) 
print('Média:', (a+b+c)/3) 
Erros comuns: 
• Esquecer o "int". Neste caso, o programa dá erro assim que você digitar o primeiro 
número. 
• Usar "//" ao invés de "/". Ninguém falou que era para calcular a média "inteira". 
Observe que os números digitados como entrada precisam ser necessariamente 
inteiros, por causa da função "int". Mas o resultado é apresentado em ponto 
flutuante. 
• Esquecer os parênteses na expressão (a+b+c)/3, o que daria os resultados 
12.333333333333332 36.0 0.0 para os testes, equivalendo à expressão a+b+c/3, na 
qual a divisão c/3é executada antes das somas. 
3.6 
print('Este programa eleva um número ao seu cubo') 
número = int(input('Número: ')) 
print('{0} elevado ao cubo é {1}'.format(número, número**3)) 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 7 
3.7 
print('Este programa calcula a raiz cúbica de um número') 
x = int(input('Número: ')) 
print('A raiz cúbica de {0} é: {1}'.format(x, x**(1/3))) 
 
Erros comuns: 
• Esquecer os parênteses em x**(1/3). Se você usar a expressão x**1/3 terá como 
resultado uma expressão equivalente a (x**1)/3. Isso acontece porque a precedência 
da potenciação (**) é maior do que a da divisão. 
• Ao invés de 1/3 usar o valor simplificado de 0.3 ou 0.33, que incorpora um erro de 
precisão importante ao resultado. 
• Ao entrar com os números negativos, escrever "- 40" em vez de "-40". Não se pode 
usar espaço entre o sinal de negativo e o número em si. Se você fizer isso o programa 
vai dar erro após a entrada de dados. 
3.8 
print('Este programa calcula a raiz n de um número x') 
n = int(input('n: ')) 
x = int(input('x: ')) 
print('A raiz {0} de {1} é {2}.'.format(n, x, x**(1/n))) 
3.9 
print('Este programa calcula áreas e volume de uma sala') 
altura = int(input('Altura: ')) 
comprimento = int(input('Comprimento: ')) 
largura = int(input('Largura: ')) 
print('Área do piso:', largura*comprimento) 
print('Volume da sala:', largura*comprimento*altura) 
print('Área das paredes:', 2*(largura*altura + comprimento*altura)) 
3.10 
print('Quantos segundos se passaram desde a meia-noite!') 
print('Que horas são?') 
horas = int(input('Horas (0-23): ')) 
minutos = int(input('Minutos (0-59): ')) 
segundos = int(input('Segundos (0-59): ')) 
print('Já se passaram {0} segundos desde a meia noite' 
.format(3600*horas + 60*minutos + segundos)) 
 
Obs.: Como a linha final ficou bastante longa, optamos por colocar o envio da mensagem 
"format" na linha abaixo do "print". Existem regras de estilo para quebra de linha deste tipo. 
No caso, o ponto ideal para fazer a quebra de linha é exatamente antes do ponto de envio da 
mensagem e o recuo na linha seguinte deve coincidir com o início da string, conforme 
mostrado acima. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 8 
3.11 
print('Raizes de um polinômio ax**2+bx+c') 
a = int(input('a: ')) 
b = int(input('b: ')) 
c = int(input('c: ')) 
delta = (b**2 - 4*a*c)**(1/2) # delta é o resultado da raiz quadrada 
x1 = (-b+delta)/2*a 
x2 = (-b-delta)/2*a 
print('Primeira raiz:', x1) 
print('Segunda raiz:', x2) 
 
Erros comuns: 
• Escrever "2a" ao invés de "2*a". O interpretador não entende que "2a" deva ser 
uma multiplicação; você deve ser sempre explícito e usar o operador "*" para 
indicar multiplicações. 
• Não usar a variável "delta" para conter o resultado da raiz quadrada não é 
necessariamente um erro, mas o programa resultante terá a expressão (b**2-
4*a*c)**(1/2) repetida duas vezes, se você não armazenar esse valor em uma 
variável intermediária como "delta" ou "discriminante". Embora não cause erro, 
repetir código é considerado uma prática ruim entre programadores. 
3.12 
print('Conversão de segundos em horário') 
segundos_totais = int(input('Qual a quantidade de segundos? ')) 
horas = segundos_totais //3600 
segundos_restantes = (segundos_totais - horas*3600) 
minutos = segundos_restantes//60 
segundos = segundos_restantes % 60 
print('{0}h{1}m{2}s'.format(horas, minutos, segundos)) 
 
Obs.: O maior desafio neste exercício está em perceber que para obter o valor em minutos 
você não pode dividir o total de segundos por 60, o que seria talvez sua primeira tentativa. 
Você deve dividir por 60 aquilo que sobra da quantidade total de segundos, depois que você 
subtrai dela a quantidade de segundos contidos nas horas inteiras que já foram calculadas, ou 
seja, segundos_totais - horas*3600, que, para não repetir duas vezes a expressão, 
armazenamos na variável "segundos_restantes". Daí para encontrar a quantidade de segundos 
é só ver quanto sobrou desse valor dividido por 60. 
3.13 
G = 9.80665 
h = 56 
tempo = (2*h/G)**(1/2) 
print('Tempo para Torre de Pisa:', tempo) 
h = 333 
tempo = (2*h/G)**(1/2) 
print('Tempo para Torre de Tóquio:', tempo) 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 9 
 
Resultados: 
• Tempo para Torre de Pisa: 3.3794706072627405 
• Tempo para Torre de Tóquio: 8.240940467223995 
Aqui neste exemplo não tivemos como evitar de escrever a expressão (2*h/G)**(1/2) duas 
vezes. Mais adiante, com outras estruturas de programação, porém, poderemos evitar esse 
tipo de redundância nos programas. 
3.14 
print('Este programa simula prestações de uma compra') 
valor = float(input('Valor da compra: ')) 
print('A vista:', round(valor*0.9, 2)) 
print('Prestação em 5x:', round(valor/5, 2)) 
print('Prestação em 10x:', round(valor*1.2/10, 2)) 
3.15 
5.13532181e-07 
5.9012210122e10 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 10 
4 Repetição Fixa 
4.1 
print('Canção dos programadores') 
for i in range(99, 251): 
print(i, 'bugs no software, pegue um deles e conserte...') 
 
Erro comum: usar range(99, 250). Neste caso, a canção vai parar em 249. Lembre-se que o 
limite superior de um "range" não pertence à lista de números gerada por ele. 
4.2 
print('Canção dos programadores v.2') 
for i in range(99, 251): 
print(i, 'bugs no software, pegue um deles e conserte...') 
print('Tecle "Ctrl-F5"') 
print('Vamos fazer mais um café!') 
4.3 
for i in range(2004, 2100, 4): 
print(i) 
Observação: o segundo argumento da função "range" poderia ser qualquer número entre 
2097 e 2100 inclusive. 
4.4 
print('Canção dos programadores v.3') 
for i in range(99, 251, 7): 
print(i, 'bugs no software, pegue um deles e conserte...') 
print('Tecle "Ctrl-F5"') 
print('Vamos fazer mais um café!') 
 
O valor de parada (segundo argumento da função "range") deve ser 251 porque ela deve parar 
"em ou antes" de 250. Se o valor fosse 250, a repetição só pararia antes. 
4.5 
Se o usuário digitar "0", vai visualizar apenas "0" e "Fogo!", pois o valor final da repetição é -1. 
Assim, o "0" está incluído na sequência. 
Já para qualquer valor negativo digitado pelo usuário, ele vai visualizar apenas a palavra 
"Fogo!", pois a repetição não será executada nenhuma vez. 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 11 
4.6 
print('Canção dos bons programadores') 
for i in range(99, 0, -11): 
print(i, 'bugs no software, pegue onze deles e conserte...') 
print('Tecle "Ctrl-F5"')print('Sem erros no software! Está estabilizado!') 
4.7 
print('Programa que simula prestações em compras sem juros') 
valor = int(input('Valor da compra:')) 
for i in range(1, 21): 
print('{0}x de R${1}'.format(i, valor//i)) 
 
Erros comuns: 
• Se você iniciar o "range" em 0, vai dar um erro no programa porque ele vai tentar 
dividir o valor por zero. 
• Se você terminar o "range" em 20, ele vai parar no valor 19. Lembre-se que o range 
nunca inclui o valor final. 
• Se você usar "/" em vez de "//" vai obter valores com casas decimais, e o enunciado do 
exercício pedia para mostrar apenas o valor inteiro. 
4.8 
print('Cálculo do somatório dos inteiros entre dois limites') 
inferior = int(input('Entre com o limite inferior:')) 
superior = int(input('Entre com o limite superior:')) 
somatório = 0 
for i in range(inferior, superior+1): 
 somatório += i 
print(somatório) 
4.9 
print('Cálculo do somatório dos quadrados') 
n = int(input('Entre com o limite superior:')) 
somatório = 0 
for i in range(1, n+1): 
 somatório += i**2 
print(somatório) 
4.10 
print('Cálculo do somatório dos termos de um polinômio') 
a = int(input('Entre com o valor de a:')) 
b = int(input('Entre com o valor de b:')) 
n = int(input('Entre com o valor de n:')) 
somatório = 0 
for i in range(1, n+1): 
 somatório += a - b*i + i**2 
print(somatório) 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 12 
4.11 
QUANTIDADE = 10 
print('Somatório e média de {0} números'.format(QUANTIDADE)) 
somatório = 0 
for i in range(QUANTIDADE): 
 número = int(input('Entre com um valor:')) 
 somatório += número 
print('Somatório:', somatório) 
print('Média:', somatório/QUANTIDADE) 
4.12 
print('Média de n números') 
quantidade = int(input('Quantos números?')) 
somatório = 0 
for i in range(quantidade): 
 número = int(input('Entre com um valor:')) 
 somatório += número 
print('Média:', somatório/quantidade) 
4.13 
print('Seu número da sorte') 
data_nascimento = int(input(Data de nascimento no formato ddmmaaaa:')) 
número_da_sorte = 0 
for i in range(8): 
 número_da_sorte += data_nascimento % 10 
data_nascimento //= 10 
print('Seu número da sorte é: ', número_da_sorte) 
4.14 
print('Pagamento pelo jogo de xadrez') 
grãos = 0 
for i in range(64): 
 grãos += 2**i 
print('Grãos de arroz:', grãos) 
quilos = grãos//170000 
print('Quilos:', quilos) 
quilômetros_quadrados = quilos//550000 
print('Quilômetros quadrados:', quilômetros_quadrados) 
brasis = quilômetros_quadrados//8514876 
print('Brasis:', brasis) 
 
Obs.: Os resultados são: 
• Grãos de arroz: 18446744073709551615 
• Quilos: 108510259257115 
• Quilômetros quadrados: 197291380 
• Brasis: 23 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 13 
4.15 
print('Este programa calcula o enésimo número de Fibonacci') 
ordem = int(input('Qual Fibonacci você quer saber? ')) 
atual = 1 
último = 1 
for i in range (2, ordem): 
 penúltimo = último 
 último = atual 
 atual = último+penúltimo 
print('Resposta:', atual) 
 
O segredo aqui está em controlar qual o último e o penúltimo números de Fibonacci para 
calcular o atual. Dentro do "for" atualizamos, nesta estrita ordem, "penúltimo" recebendo o 
valor de "último", "último" recebendo o valor de "atual" e "atual" recebendo a soma de 
"último" e "penúltimo". 
Como no início da repetição "último" e "atual" valem 1, devemos começar o "range" em 2, 
porque já estamos calculando o segundo número de Fibonacci. 
Para ter uma visão mais clara sobre o funcionamento deste programa, sugerimos que utilize a 
tabela de rastreamento, como mostrada no capítulo anterior. Segue exemplo que mostra a 
tabela para o cálculo do quarto número de Fibonacci: 
1 print('Este programa calcula o enésimo número de Fibonacci') 
2 ordem = int(input('Qual Fibonacci você quer saber? ')) 
3 atual = 1 
4 último = 1 
5 for i in range (2, ordem): 
6 penúltimo = último 
7 último = atual 
8 atual = último+penúltimo 
9 print('Resposta:', atual) 
 
Linha ordem atual último i penúltimo 
1 
2 4 
3 1 
4 1 
5 2 
6 1 
7 1 
8 2 
5 3 
6 1 
7 2 
8 3 
5 4 
9 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 14 
4.16 
print('Este programa calcula o enésimo número de Tribonacci') 
ordem = int(input('Qual Tribonacci você quer saber? ')) 
atual = 1 
último = 1 
penúltimo = 0 
for i in range(2, ordem): 
 antepenúltimo = penúltimo 
 penúltimo = último 
 último = atual 
 atual = último+penúltimo+antepenúltimo 
print('Resposta:', atual) 
 
Obs.: O exercício foi resolvido simplesmente adicionando-se uma nova variável para conter o 
antepenúltimo número da sequência o qual é necessário para calcular o Tribonatti. 
4.17 
fatorial = 1 
for i in range(1, n+1): 
 fatorial *= i 
print('{0}!={1}'.format(i, fatorial)) 
 
Obs.: Na versão anterior do programa não havia necessidade de iniciar a repetição com 1, 
porque o resultado era impresso no final. Mas agora, como os resultados são impressos dentro 
do "for" fazemos a repetição ocorrer uma vez, mesmo que para multiplicar 1 por 1, mas 
também para imprimir o resultado na tela que, de outra forma, não seria visto. 
4.18 
print('Calendário de 2017 a 2020') 
for ano in range(2017, 2021): 
for mês in range(1, 13): 
for dia in range(1, 31): 
print('{0}/{1}/{2}'.format(dia, mês, ano)) 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 15 
5 Seleção 
5.1 
for i in range(256): 
print(i, chr(i)) 
Teste depois o programa substituindo 256 por 55296 e veja o resultado. 
5.2 
print('Digite dois números diferentes e direi qual o maior') 
x = int(input('Primeiro número: ')) 
y = int(input('Segundo número: ')) 
if x > y: 
print('O maior é', x) 
else: 
print('O maior é', y) 
5.3 
print('Cálculo da nota geral de um edital') 
qualidade = int(input('Nota da qualidade: ')) 
preço = int(input('Nota do preço: ')) 
prazo = int(input('Nota do prazo: ')) 
if qualidade <7: 
 nota_geral = 0 
else: 
if preço >= 7: 
 nota_geral = (qualidade+preço+prazo)/3 
else: 
 nota_geral = (qualidade+2*preço+prazo)/4 
print('Nota geral:', nota_geral) 
 
Obs.: Não é necessário explicitar a última condição (condição 3 do enunciado) porque caso a 
primeira e a segunda não sejam verdadeiras, a terceira, por eliminação, tem que ser 
verdadeira. Assim, a estrutura do programa pode terminar com um "else" para a terceira 
condição, não sendo necessário escrever if preço < 7. 
5.4 
print('Digite a idade de 10 pessoas e direi quais são maiores') 
maiores = 0 
for i in range(1, 11): 
 idade = int(input('[{0}]:'.format(i))) 
if idade >= 18: 
 maiores += 1 
print(maiores, 'pessoas são maiores de idade') 
Obs.: aqui não é necessário dar tratamento especial ao primeiro elemento como fizemos no 
caso de encontrar o maior elemento de uma sequência de números. Como se trata de contar 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 16 
quantos elementos em uma lista tem determinada propriedade (ser maior de idade), basta 
inicializar a variável que vai conter essa quantidade com zero e acrescentar 1 cada vez que um 
elemento com a propriedade for encontrado. 
5.5 
print('Digite 10 números e eu direi a média dos pares e dos ímpares') 
quantos_pares = 0 
quantos_ímpares = 0 
soma_pares = 0 
soma_ímpares = 0 
for i in range(1,11): 
 número = int(input('[{0}]:'.format(i))) 
if número % 2 == 0: 
 quantos_pares += 1 
soma_pares += número 
else: 
 quantos_ímpares += 1 
soma_ímpares += número 
print('Média dos pares:', soma_pares/quantos_pares) 
print('Média dos ímpares:', soma_ímpares/quantos_ímpares)5.6 
print('Digite 10 números e eu direi a média dos pares e dos ímpares') 
quantos_pares = 0 
quantos_ímpares = 0 
soma_pares = 0 
soma_ímpares = 0 
for i in range(1,11): 
 número = int(input('[{0}]:'.format(i))) 
if número % 2 == 0: 
quantos_pares += 1 
soma_pares += número 
else: 
 quantos_ímpares += 1 
soma_ímpares += número 
if quantos_pares >0: 
print('Média dos pares:', soma_pares/quantos_pares) 
else: 
print('Nenhum número par') 
if quantos_ímpares >0: 
print('Média dos ímpares:', soma_ímpares/quantos_ímpares) 
else: 
print('Nenhum número ímpar') 
 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 17 
5.7 
print('Digite a idade e altura de 5 pessoas') 
quantos_abaixo_de_170 = 0 
quantos_acima_dos_20 = 0 
soma_idade_dos_abaixo_de_170 = 0 
soma_altura_dos_acima_de_20 = 0 
for i in range(1, 6): 
 idade = int(input('Idade[{0}]:'.format(i))) 
 altura = int(input('Altura[{0}]:'.format(i))) 
if altura <170: 
 quantos_abaixo_de_170 += 1 
soma_idade_dos_abaixo_de_170 += idade 
if idade >20: 
 quantos_acima_dos_20 += 1 
soma_altura_dos_acima_de_20 += altura 
if quantos_abaixo_de_170 >0: 
print('Idade média dos abaixo de 170 cm:', 
 soma_idade_dos_abaixo_de_170/quantos_abaixo_de_170) 
else: 
print('Ninguém abaixo de 170 cm') 
if quantos_acima_dos_20 >0: 
print('Altura média dos acima de 20 anos:', 
 soma_altura_dos_acima_de_20/quantos_acima_dos_20) 
else: 
print('Ninguém acima dos 20 anos') 
 
Obs.: como as linhas de dois "print" ficaram muito longas, adicionamos uma quebra logo após 
a vírgula endentando o argumento seguinte da função na mesma coluna do argumento que 
aparece na linha do "print". 
5.8 
número = int(input('Digite um número e direi se é perfeito: ')) 
soma_divisores = 0 
for i in range(1, número//2+1): 
if número % i == 0: 
 soma_divisores += i 
if soma_divisores == número: 
print('O número é PERFEITO!') 
else: 
print('O número não é perfeito...') 
 
Obs.: não é necessário verificar todos os números menores do que n para saber quais são os 
divisores de n. Basta verificar de 1 até n//2, porque nenhum número maior do que n//2 pode 
ser divisor de n. Por exemplo, no caso de 28, nenhum número maior do que 14 pode ser 
divisor de 28. Por isso é que o "range" vai de 1 a número//2+1. 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 18 
5.9 
print('Número perfeitos entre 2 e dez mil:') 
for número in range(2, 10001): 
 soma_divisores = 0 
for i in range(1, número//2+1): 
if número % i == 0: 
 soma_divisores += i 
if soma_divisores == número: 
print(número) 
Obs.: Se o programa estiver correto você vai visualizar a lista: 6, 28, 496 e 8128. 
5.10 
número = int(input('Digite um número e direi se é primo: ')) 
é_primo = True 
for possível_divisor in range(2, número//2+1): 
if número % possível_divisor == 0: 
 é_primo = False 
print('Divisor:', possível_divisor) # linha adicionada 
if é_primo: 
print('é primo') 
else: 
print('não é primo') 
5.11 
número = int(input('Digite um número e direi se é triangular: ')) 
é_triangular = False 
for i in range(1, int(número**(1/3)+1)): 
if número == i*(i+1)*(i+2): 
 é_triangular = True 
primeiro_fator = i 
if é_triangular: 
print('É triangular porque {0}={1}x{2}x{3}' 
.format(número, primeiro_fator, primeiro_fator+1, 
primeiro_fator+2)) 
else: 
print('Não é triangular') 
 
Obs.: uma das decisões que afetam a eficiência deste programa é decidir até quando executar 
o "for". Optamos por simplesmente limitar o "for" à parte inteira da raiz cúbica do número. Se 
você escreveu for i in range(1, número) ou for i in range(1, número//2+1), o programa 
funcionará da mesma forma, mas fará muitas comparações desnecessárias após examinar a 
raiz cúbica do número. Isso ocorre porque se o primeiro dos três números consecutivos for 
maior do que a raiz cúbica do número, o produto deles será sempre maior do que o número 
em questão já que, por definição, se "x" é a raiz cúbica de "y", então "y" é igual a x*x*x. Além 
disso, como os três fatores são consecutivos, basta guardar o primeiro, caso sejam 
encontrados e os outros dois podem ser produzidos somando-se 1 e 2 ao primeiro. 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 19 
5.12 
print('Digite os valores dos lados e direi se é triângulo') 
lado1 = int(input('Lado 1:')) 
lado2 = int(input('Lado 2:')) 
lado3 = int(input('Lado 3:')) 
if lado1 >= lado2+lado3 \ 
or lado2 >= lado1+lado3 \ 
or lado3 >= lado1+lado2: 
print('Não é triângulo') 
else: 
print('É triângulo') 
 
Obs.: você certamente não precisou disso ao escrever seu programa, mas para mostrar o 
programa mais claramente no tamanho de texto adotado neste documento, tivemos que 
dividir a linha do "if" em três partes. O símbolo "\" colocado ao final da linha do "if" e da linha 
seguinte, indica que a condição continua na linha seguinte. Se tivéssemos simplesmente 
escrito as três linhas como abaixo, haveria erro de compilação, porque o interpretador não 
saberia que a segunda linha é continuação da primeira e a terceira continuação da segunda. 
if lado1 >= lado2+lado3 
or lado2 >= lado1+lado3 
or lado3 >= lado1+lado2: 
 
Em Python, o uso da barra invertida não é necessário quando você divide a linha após abrir, 
mas não fechar parênteses. Assim, por exemplo, uma lista de argumentos para uma função, 
que vai entre parênteses, pode ser escrita assim: 
função(arg1, 
 arg2, 
 arg3) 
Mas em outras situações, a barra invertida deve ser usada para indicar que a linha continua 
abaixo. Por exemplo: 
if a > b \ 
and (b > c 
or c > d): 
Observe que, neste exemplo, tivemos que usar a barra ao final da primeira linha, mas não 
usamos ao final da segunda linha, pois na segunda linha havia parênteses aberto. 
5.13 
print('Digite um ano e direi se é bissexto') 
ano = int(input('Ano:')) 
if ano % 4 == 0 and not ano % 100 == 0 or ano % 400 == 0: 
print('é bissexto') 
else: 
print('não é bissexto') 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 20 
Obs.: Pelas regras de precedência não é necessário usar parênteses na condição porque o 
"not" será executado primeiro, depois o "and" e finalmente o "or. 
5.14 
print('Digite um número e direi o mês correspondente') 
mês = int(input('Número do mês:')) 
if mês == 1: 
print('janeiro') 
elif mês == 2: 
print('fevereiro') 
elif mês == 3: 
print('março') 
elif mês == 4: 
print('abril') 
elif mês == 5: 
print('maio') 
elif mês == 6: 
print('junho') 
elif mês == 7: 
print('julho') 
elif mês == 8: 
print('agosto') 
elif mês == 9: 
print('setembro') 
elif mês == 10: 
print('outubro') 
elif mês == 11: 
print('novembro') 
elif mês == 12: 
print('dezembro') 
else: 
print('mês inválido') 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 21 
5.15 
print('Eleições') 
abel = 0 
beatriz = 0 
caio = 0 
dirce = 0 
eustáquio = 0 
brancos = 0 
nulos = 0 
for i in range(1, 11): 
print('Vote 11 Abel / 15 Beatriz / 21 Caio / ' 
 '25 Dirce / 46 Eustáquio') 
voto = int(input('Voto[{0}]: '.format(i))) 
if voto == 11: 
 abel += 1 
elif voto == 15: 
 beatriz += 1 
elif voto == 21: 
 caio += 1 
elif voto == 25: 
 dirce += 1 
elif voto == 46: 
 eustáquio += 1 
elif voto == 0: 
 brancos += 1 
else: 
 nulos += 1 
print('Resultados:') 
print('Abel:', abel) 
print('Beatriz:', beatriz) 
print('Caio:', caio) 
print('Dirce:', dirce) 
print('Eustáquio:', eustáquio) 
print('Brancos:', brancos) 
print('Nulos:', nulos) 
 
Adiante no livro veremos a estrutura de "dicionário", quepermite resolver esse tipo de 
problema de forma bem mais elegante e simples. 
Observe também que no "print" subordinado ao "for" dividimos a literal em duas linhas, 
quando uma linha termina com aspas e a linha seguinte inicia com aspas isso equivale a 
concatenar as literais das duas linhas. Não há necessidade de usar a barra invertida aqui para 
indicar quebra de linha, nem se deve usar vírgula neste caso. Assim, por exemplo, o comando 
seguinte vai imprimir "abc": 
print('a' 
 'b' 
 'c') 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 22 
5.16 
print('Classificação de nadadores') 
idade = int(input('Qual a idade do participante? ')) 
if idade <5: 
print('Classificação inválida') 
elif idade <= 7: 
print('Infantil A') 
elif idade <= 10: 
print('Infantil B') 
elif idade <= 14: 
print('Juvenil A') 
elif idade <= 17: 
print('Juvenil B') 
else: 
print('Adulto') 
 
Obs.: o uso do "elif" nos desobriga de verificar o limite inferior de cada intervalo. Assim, o 
programa testou no primeiro "if" se a idade era menor do que 5; então a condição do "elif" 
seguinte pode ser idade <= 7, porque verificar se ela é maior ou igual 5 seria redundante já que 
o teste anterior que verificava se era menor do que 5 já falhou e, portanto, já sabemos que a 
idade é maior ou igual a 5. 
5.17 
nota = float(input('Entre com a nota: ')) 
if nota <0: 
print('nota inválida') 
elif nota <7: 
print('Conceito E') 
elif nota <8: 
print('Conceito C') 
elif nota <9: 
print('Conceito B') 
elif nota <= 10: 
print('Conceito A') 
else: 
print('nota inválida') 
5.18 
print('Índice de Massa Corporal') 
peso = float(input('Entre com o peso (kg): ')) 
altura = float(input('Entre com a altura (m): ')) 
imc = peso/altura**2 
print('IMC:', imc) 
if imc <18.5: 
print('Adulto com baixo peso') 
elif imc <25: 
print('Adulto com peso adequado') 
elif imc <30: 
print('Adulto com sobrepeso') 
else: 
print('Adulto com obesidade') 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 23 
5.19 
print('Conversão de moedas') 
moeda = input('Qual a moeda? (e, d, m, a, l): ') 
reais = float(input('Quantos reais? ')) 
if reais <0: 
print('Quantidade inválida') 
elif moeda == 'e': 
print(reais*0.31, 'Euros') 
elif moeda == 'd': 
print(reais*0.42, 'Dólares') 
elif moeda == 'm': 
print(reais*5.55, 'Pesos Mexicanos') 
elif moeda == 'm': 
print(reais*2.84, 'Pesos Argentinos') 
elif reais == 'l': 
print(moeda*0,26, 'Libras') 
else: 
print('Moeda inválida') 
5.20 
Para resolver este problema, vamos incrementar o número de dias um por um verificando 
sempre se chegamos a um final de mês, situação na qual o dia retorna a 1 e o mês é 
incrementado, ou a um final de ano, situação na qual o dia e o mês retornam a 1 e o ano é 
incrementado. A primeira versão usa uma estrutura "if-elif-else": 
 
print('Cálculo de data futura') 
dia = int(input('Dia: ')) 
mês = int(input('Mês: ')) 
ano = int(input('Ano: ')) 
avanço = int(input('Quantos dias no futuro? ')) 
for i in range(avanço): 
if dia == 31: 
 fim_do_mês = True 
 elif dia == 30 and (mês == 4 or mês == 6 or mês == 9 or mês == 1): 
 fim_do_mês = True 
 elif dia == 29 and mês == 2 \ 
and (ano % 4 == 0 and not ano % 100 == 0 or ano % 400 == 0): 
 fim_do_mês = True 
 elif dia == 28 and mês == 2: 
 fim_do_mês = True 
 else: 
 fim_do_mês = False 
 if fim_do_mês and mês == 12: 
 fim_do_ano = True 
 else: 
 fim_do_ano = False 
 if fim_do_ano: 
 ano += 1 
mês = 1 
dia = 1 
elif fim_do_mês: 
 mês += 1 
dia = 1 
else: 
 dia += 1 
print('{0}/{1}/{2}'.format(dia, mês, ano)) 
 
A segunda versão atribui a expressão lógica diretamente às variáveis booleanas sem usar "if-
elif-else": 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 24 
print('Cálculo de data futura') 
dia = int(input('Dia: ')) 
mês = int(input('Mês: ')) 
ano = int(input('Ano: ')) 
avanço = int(input('Quantos dias no futuro? ')) 
for i in range(avanço): 
 fim_do_mês = dia == 31 \ 
or (dia == 30 
and (mês == 4 or mês == 6 or mês == 9 or mês == 1)) \ 
or (dia == 29 and mês == 2 
and (ano % 4 == 0 and not ano % 100 == 0 or ano % 400 == 0)) \ 
or (dia == 28 and mês == 2) 
 fim_do_ano = fim_do_mês and mês == 12 
if fim_do_ano: 
 ano += 1 
mês = 1 
dia = 1 
elif fim_do_mês: 
 mês += 1 
dia = 1 
else: 
 dia += 1 
print('{0}/{1}/{2}'.format(dia, mês, ano)) 
 
Obs.: na expressão complexa que atribui valor booleano a "fim_do_mês", foi usada barra 
invertida apenas nos finais de linha onde não havia parêntese aberto. Nos casos em que a 
linha termina com parêntese aberto, mas não fechado, o uso da barra invertida é opcional e 
recomenda-se não usá-la. 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 25 
6 Repetição Condicionada 
6.1 
CARGA_MÁXIMA = 500 
print('Simulador de elevador') 
peso_total = 0 
while peso_total <= CARGA_MÁXIMA: 
 peso_pessoa = int(input('Peso do passageiro: ')) 
 peso_total += peso_pessoa 
print('Peso excedido') 
 
Obs.: 
1. Neste exercício, ao contrário de muitos outros, não é necessário ler o peso do primeiro 
passageiro antes do "while", já que apenas o peso total é usado na condição do 
"while" e esse peso já foi inicializado com 0. Se a primeira pessoa, inclusive, pesasse 
mais de 500 kg, ela seria impedida de entrar no elevador. Por este motivo também a 
condição é testada na própria estrutura "while" e não em um "if" subordinado. 
2. A constante "CARGA_MÁXIMA" foi usada aqui mesmo ela aparecendo uma única vez 
no programa. Considera-se uma boa prática de programação evitar usar aquilo que se 
conhece como "números mágicos" dentro de um programa. Neste caso até podemos 
saber que peso_total<= 500 estaria se referindo à carga máxima do elevador. Mas 
uma pessoa que fosse ler este código, sem ter sido seu programador, poderia ficar em 
dúvida sobre o real significado do valor 500 nesta expressão. Assim, a substituição do 
número mágico 500 pela constante "CARGA_MÁXIMA" deixa o código mais fácil de ler 
e entender. 
6.2 
print('Programa que inverte números') 
número = int(input('Digite um número: ')) 
invertido = 0 
while número != 0: 
 último_dígito = número % 10 
número //= 10 
invertido *= 10 
invertido += último_dígito 
print('Número invertido:', invertido) 
 
Erro comum: 
• Durante o "while" você deve primeiro multiplicar o número invertido por 10 para só 
depois somar o último dígito a ele. Se você inverter a ordem dessas operações não vai 
obter o resultado desejado, mas um número 10 vezes maior do que o esperado. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 26 
6.3 
Primeira versão ainda incorreta: 
TAXA_MORTES = 0.06 
TAXA_NASCIMENTOS = 0.01 
POPULAÇÃO_MÍNIMA = 100000 
print('Evolução da população de dodôs.') 
ano = 1600 
população = 1000000 
while população >= POPULAÇÃO_MÍNIMA: 
 mortos = round(população*TAXA_MORTES) 
 nascidos = round(população*TAXA_NASCIMENTOS) 
print('Ano: {0}. População: {1}. Nascidos: {2}. Mortos: {3}.' 
.format(ano, população, nascidos, mortos)) 
 população += nascidos-mortos 
 ano += 1 
 
Erros comuns: 
• Ao invés de escrever população >= POPULAÇÃO_MÍNIMA ou mesmo população >= 
100000, você poderia ter talvez escrito população >= população*0.1, pensando que 
assim estaria comparando a população atual de dodôs com 10% da população inicial. 
Mas note que você está comparando a variável "população" (o valor atual e não o 
inicial) com 10% dela própria; essa expressão nunca será falsa (qual número é maior 
que 10% dele próprio?) e seuprograma entrará em repetição infinita (sobre isso, veja 
Seção 6.3). Você tem que comparar a população atual, armazenada na variável 
"população" com 10% da população inicial, ou seja, 10% de um milhão, que é cem mil. 
• Dentre os comandos subordinados ao "while", a escolha da posição onde colocar o 
"print" é fundamental para os resultados saírem certos. Se tivesse colocado, por 
exemplo, mais no início da lista de comandos, os valores de "mortos" e "nascidos" 
estariam indefinidos quando o "print" fosse executado pela primeira vez. Assim o 
programa daria erro. Por outro lado, se tivesse colocado o "print" depois da 
atualização do ano e da população, o que seria impresso em cada linha referente a ano 
e população estaria errado, pois já estariam sendo mostrados dados do ano 
subsequente e não do ano atual. 
• O enunciado do problema exigia que se trabalhasse com os números de nascidos e 
mortos como inteiros. Se não houvesse a função "round" antes da atribuição dos 
valores dessas variáveis dentro do "while", o programa geraria resultados ligeiramente 
diferentes por causa de arredondamentos não feitos, mesmo que você usasse o 
"round" na hora de imprimir no final. 
• Finalmente, talvez a maior "pegadinha" do exercício é que o enunciado exige que 
sejam mostrados os resultados até que o tamanho da população seja menor do que 
10% da original. Acontece que a população é atualizada no final da lista de comandos 
subordinados ao "while" e quando o programa retorna à linha do "while" para testar o 
tamanho da população, e ela está menor, a execução para e, dessa forma, não são 
calculados os mortos e nascidos nem impressa a última linha que deveria ser aquela 
com o ano em que a população se tornou menor do que 10% da original. Observe que 
se você fez um programa semelhante a esse, ele parou no ano de 1644 quando a 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 27 
população ainda era superior a 100.000 dodôs. Isso nos leva a uma segunda versão 
deste programa na qual usamos uma estrutura while True com um "break" para parar 
a repetição logo depois de imprimir a população, caso ela tenha se tornado inferior ao 
mínimo estabelecido: 
Segunda versão: 
TAXA_MORTES = 0.06 
TAXA_NASCIMENTOS = 0.01 
POPULAÇÃO_MÍNIMA = 100000 
print('Evolução da população de dodôs.') 
ano = 1600 
população = 1000000 
while True: 
 mortos = round(população*TAXA_MORTES) 
 nascidos = round(população*TAXA_NASCIMENTOS) 
print('Ano: {0}. População: {1}. Nascidos: {2}. Mortos: {3}.' 
.format(ano, população, nascidos, mortos)) 
if população < POPULAÇÃO_MÍNIMA: 
break 
população += nascidos-mortos 
 ano += 1 
Se você fez o exercício corretamente, a última linha que vai visualizar será: "Ano: 1645. 
População: 99441. Nascidos: 994. Mortos: 5966.". 
6.4 
VEL_TARTARUGA = 1 
VEL_LEBRE = 10 
print('A tartaruga e a lebre') 
tartaruga = 500 
lebre = 0 
minuto = 0 
while tartaruga > lebre: 
 tartaruga += VEL_TARTARUGA 
 lebre += VEL_LEBRE 
 minuto += 1 
print('A lebre vai alcançar a tartaruga em {0} minutos' 
.format(minuto)) 
 
Observação: aqui, como em outros casos, abreviamos parte do nome das constantes. Por 
exemplo, usamos "VEL_TARTARUGA" ao invés de 'VELOCIDADE_DA_TARTARUGA". Ocorre que 
quando identificadores ficam muito longos eles começam a prejudicar, e não a ajudar, a 
legibilidade dos programas. Assim, quando o significado de uma sigla for absolutamente claro, 
recomenda-se usar abreviação para evitar que o identificador fique muito longo. Porém, deve-
se evitar abreviações cujo significado não seja tão claro, como por exemplo "VT" e "VL" no 
lugar de "VEL_TARTARUGA" e "VEL_LEBRE". 
Se você fez tudo certo, deve ter visto o resultado "56". 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 28 
6.5 
TAXA_CARRO = 1.004 
TAXA_APLICAÇÃO = 1.007 
print('Compra de um carro') 
aplicação = 10000 
preço_carro = 12000 
meses = 0 
while preço_carro > aplicação: 
 meses += 1 
aplicação *= TAXA_APLICAÇÃO 
 preço_carro *= TAXA_CARRO 
print('Vai levar {0} meses para você poder comprar o carro' 
.format(meses)) 
 
Se fez tudo certo, descobriu que o resultado é "62". 
6.6 
print('Cartão x Salário') 
salário = 2000 
dívida = 100 
mês = 10 
ano = 2016 
while salário > dívida: 
 mês += 1 
if mês == 13: 
 mês = 1 
ano += 1 
elif mês == 3: 
 salário *= 1.05 
dívida *= 1.15 
print('A dívida será superior ao salário em {0}/{1}' 
.format(mês, ano)) 
 
Se você fez tudo certo, deve ter visualizado como resultado o mês de setembro de 2018. 
6.7 
print('A tartaruga e a lebre') 
tartaruga = int(input('Quantos metros de vantagem tem a tartaruga? ')) 
lebre = 0 
velocidade_tartaruga = int(input('Velocidade da tartaruga: ')) 
velocidade_lebre = int(input('Velocidade da lebre: ')) 
minuto = 0 
if velocidade_tartaruga >= velocidade_lebre and tartaruga > lebre: 
print('A lebre nunca vai alcançar a tartaruga') 
else: 
while tartaruga > lebre: 
 tartaruga += velocidade_tartaruga 
 lebre += velocidade_lebre 
 minuto += 1 
print('A lebre vai alcançar a tartaruga em {0} minutos' 
.format(minuto)) 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 29 
 
Erro comum: 
• Se você apenas comparar as velocidades sem verificar se a tartaruga realmente tem 
uma vantagem positiva sobre a lebre, o programa terá um comportamento estranho, 
pois se ambas saírem juntas (vantagem zero), a resposta deveria ser "0 minutos", pois 
elas já estão juntas; mas neste caso, se a velocidade da tartaruga for maior do que a da 
lebre, o programa estranhamente vai dizer que a tartaruga nunca vai alcançar a lebre, 
ou seja, o programa iria falhar no quarto teste proposto. 
6.8 
print('Divisão pelo método das subtrações sucessivas') 
dividendo = int(input('Dividendo: ')) 
divisor = int(input('Divisor: ')) 
contador = 0 
if divisor == 0: 
print('Erro de divisão por zero') 
else: 
while dividendo >= divisor: 
 dividendo -= divisor 
 contador += 1 
print('Divisão: ', contador) 
print('Resto:', dividendo) 
 
Erro comum: 
• Caso você tenha esquecido de testar se o divisor é zero, quando executar o último 
teste proposto seu programa vai entrar em repetição infinita. Como você pode ver, 
esse é o motivo de a divisão por zero ser indefinida. 
6.9 
soma = 0 
quantidade = 0 
while True: 
 entrada = input('Nota: ') 
if entrada == '': 
break 
nota = float(entrada) 
if nota % 0.5 != 0: 
print('Nota inválida! Deve ser múltiplo de .5') 
elif nota <0 or nota >10: 
print('Nota inválida! Deve estar entre 0 e 10') 
else: 
 soma += nota 
 quantidade += 1 
if quantidade == 0: 
print('Nenhuma nota foi digitada') 
else: 
 média = round(2*soma//quantidade)/2 
print('Média:', média) 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 30 
6.10 
x = float(input('Valor de x:')) 
if -1 < x <1: 
 série_anterior = x 
 série_atual = x+x**3 
i = 2 
while série_anterior != série_atual: 
 i += 2 
série_anterior = série_atual 
 termo = x**(2*i+1) 
 série_atual += termo 
print('Somatório:', série_atual) 
else: 
print('Valor inválido. "x" deve estar entre -1 e 1') 
 
6.11 
from math import factorial 
PRECISÃO = 10 
x = float(input('Seno de:')) 
série_anterior = 0 
série_atual = x 
i = 1 
sinal = 1 
while round(série_anterior, PRECISÃO) != round(série_atual, PRECISÃO): 
 i += 2 
sinal *= -1 
série_anterior = série_atual 
 termo = sinal*(x**i / factorial(i)) 
 série_atual += termo 
print('Seno de', x, ':', round(série_atual, PRECISÃO)) 
6.12 
from math import factorial 
x = float(input('Cosseno de:')) 
série_anterior = 1 
série_atual = 1 - x**2/2 
i = 2 
sinal = -1 
while série_anterior != série_atual:i += 2 
sinal *= -1 
série_anterior = série_atual 
 termo = sinal*(x**i / factorial(i)) 
 série_atual += termo 
print('Cosseno de', x, ':', série_atual) 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 31 
7 Funções 
7.1 
from random import randint 
print('Mega sena. Números sorteados:') 
for i in range(6): 
print(randint(1, 50)) 
 
Erros comuns: 
• Esquecer de importar "randint". 
• Confundir randint com randrange. Para gerar os números de 1 a 50, pode-se tanto usar 
randint(1, 50) como randrange(1, 51). 
7.2 
from random import randint 
print('Programa General') 
while True: 
 quantos = int(input('Quantos dados devem ser jogados? ')) 
if quantos == 0: 
break 
 elif 1 <= quantos <= 5: 
for i in range(quantos): 
print(randint(1, 6)) 
else: 
print('Quantidade inválida') 
print('Obrigado por jogar!') 
 
Obs.: Neste caso, se não usássemos a estrutura while True com break teríamos que ler a 
quantidade de dados tanto antes quando dentro do "while". 
7.3 
def fatorial(n): 
 fat = 1 
for i in range(2, n+1): 
 fat *= i 
return fat 
 
print('Cálculo de combinações C(n, p)') 
n = int(input('Quantos elementos no total (n)?')) 
p = int(input('Quantos elementos em cada combinação (p)?')) 
c = fatorial(n)//(fatorial(p)*fatorial(n-p)) 
print('Combinações possíveis:', c) 
 
Erro comum: 
• Esquecer o uso de parênteses após o sinal de divisão na expressão 
fatorial(n)//(fatorial(p)*fatorial(n-p)). Como as multiplicações e divisões são 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 32 
executadas da esquerda para a direita, a divisão seria feita antes da multiplicação e 
assim em vez de calcular 𝑛𝑛!
𝑝𝑝!(𝑛𝑛−𝑝𝑝)
, o programa estaria calculando 𝑛𝑛!
𝑝𝑝!
(𝑛𝑛 − 𝑝𝑝)!, e o 
resultado seria diferente do esperado. 
7.4 
def média_final(p1, p2, p3, p4, rec=-1): 
 média_das_4 = (3*p1+4*p2+5*p3+6*p4)/18 
if rec == -1: 
return round(média_das_4, 1) 
else: 
return round((média_das_4+rec)/2, 1) 
 
 
print(média_final(3, 2, 7, 6, 8)) 
print(média_final(6, 4, 9, 8)) 
print(média_final(8, 2, 1, 2, 7)) 
 
Obs.: O desafio deste exercício está em perceber que a nota da recuperação não tem, de fato, 
um valor default como 0 ou 10, porque isso afetaria o cálculo. Se ela não estiver presente na 
chamada da função, ela não deve ser usada. Assim, definimos como valor padrão da 
recuperação uma nota impossível, como -1. Dessa forma, a função consegue detectar que se o 
valor de "rec" for -1, esse valor não deve ser usado no cálculo da média, caso contrário, isso 
significa que a função foi chamada com um valor definido para "rec" e, portanto, ele deve ser 
usado. Também poderíamos usar o valor "None" no lugar de –1. "None" é um valor especial 
que em Python significa "nenhum" ou "nada": 
def média_final(p1, p2, p3, p4, rec=None): 
 média_das_4 = (3*p1 + 4*p2 + 5*p3 + 6*p4)/18 
if rec == None: 
return round(média_das_4, 1) 
else: 
return round((média_das_4+rec)/2, 1) 
7.5 
def tribonacci(n): 
if n == 1 or n == 2: 
return 1 
elif n ==3: 
return 2 
else: 
return tribonacci(n-1)+tribonacci(n-2)+tribonacci(n-3) 
 
 
def mdc(a, b): 
if b == 0: 
return a 
else: 
return mdc(b, a % b) 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 33 
7.6 
def mdc(x, y): 
if y == 0: 
return x 
else: 
return mdc(y, x % y) 
7.7 
def triangulo_invertido(n): 
if n == 1: 
print('$') 
else: 
print('$'*n) 
 triangulo_invertido(n-1) 
7.8 
def triângulo_rec(n, original): 
if n == 1: 
print('$'*original) 
else: 
print('$'*(original-n+1)) 
 triângulo_rec(n-1, original) 
 
def triângulo(n): 
 triângulo_rec(n, n) 
 
Obs.: Esta função é um pouco mais difícil de conceber porque ela deve guardar tanto o valor 
original da primeira chamada quanto o valor que está sendo diminuído a cada chamada 
recursiva. Assim, uma segunda função, chamada "triângulo_rec" é definida com dois 
parâmetros. A cada chamada recursiva, o primeiro parâmetro é decrementado (subtraído 1) e 
o segundo é passado exatamente como recebido. Assim, se você chamar triângulo(5), vai 
ativar as seguintes chamadas recursivas: triângulo_rec(5, 5), triângulo_rec(4, 
5),triângulo_rec(3, 5),triângulo_rec(2, 5) etriângulo_rec(1, 5). 
7.9 
def fatorial(n): 
 fat = 1 
for i in range(2, n+1): 
 fat *= i 
return fat 
 
def arranjo(n, p): 
 a = 1 
for i in range(n-p+1, n+1): 
 a *= i 
return a 
 
def combinação (n, p): 
return arranjo(n,p) // fatorial(p) 
 
print('Cálculo de combinações C(n, p)') 
n = int(input('Quantos elementos no total (n)?')) 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 34 
p = int(input('Quantos elementos em cada combinação (p)?')) 
print('Combinações possíveis:', combinação(n,p)) 
7.10 
def inverte(n): 
 invertido = 0 
while n != 0: 
 último_dígito = n % 10 
n //= 10 
invertido *= 10 
invertido += último_dígito 
return invertido 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 35 
8 Desenvolvimento Dirigido por Teste 
8.1 
def divisão(x, y): 
try: 
return x/y 
except ZeroDivisionError: 
return None 
 
print(divisão(12, 10)) 
print(divisão(3, 1)) 
print(divisão(14, 0)) 
8.2 
A resposta que já consta na continuação do texto é: 
def mmc(x, y): 
 candidato = x 
while not(candidato % x == 0 and candidato % y == 0): 
 candidato += 1 
return candidato 
 
Existe, porém, um algoritmo mais eficiente para calcular o "mmc". Só que ele usa a função 
"mdc" (máximo divisor comum), que já vimos no capítulo anterior. A ideia é a seguinte, se "y" 
for zero, o "mmc" de "x" e "y" é "x"; senão é x*y/mdc(x, y): 
def mmc(x, y): 
if y == 0: 
return x 
else: 
return x*y/mdc(x, y) 
8.3 
def analisa(idade): 
assert isinstance(idade, int) 
assert 0 <= idade <= 120 
if idade <18: 
return 'menor' 
elif idade <= 64: 
return 'adulto' 
else: 
return 'idoso' 
8.4 
Aqui, a análise de valor limítrofe aplica-se entre a classe dos números negativos, para os quais 
o fatorial não é definido, e dos não negativos. Assim, devemos fazer um teste de falha com -1 e 
um teste válido com 0. Fora isso, podemos testar valores dentro das duas classes como -25 e 5. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 36 
Devemos fazer também testes de falha para números de ponto flutuante e valores não 
numéricos. 
# Valores não inteiros 
try: 
 fatorial(0.35) 
raise Exception 
except AssertionError: pass 
 
try: 
 fatorial('abc') 
raise Exception 
except AssertionError: pass 
 
# Negativos 
try: 
 fatorial(-25) 
raise Exception 
except AssertionError: pass 
 
try: 
 fatorial(-1) # valor limítrofe 
raise Exception 
except AssertionError: pass 
 
# Válidos 
assert(fatorial(0) == 1) #valor limítrofe 
assert(fatorial(5) == 120) 
 
print('Todos os testes finalizados com sucesso') 
 
O programa original vai falhar já no primeiro teste. Para corrigi-lo basta adicionar uma linha 
com o comando "assert" como mostrado abaixo: 
def fatorial(n): 
assert isinstance(n, int) and n >= 0 
fat = 1 
for i in range(2, n+1): 
 fat *= i 
return fat 
8.5 
Neste exemplo, as classes de equivalência não se aplicam diretamente ao valor do argumento, 
mas aos resultados que a função produz. Assim, devemos ver como o programa se comporta 
quando zero notas são informadas – um caso limite – ou quando resultados são produzidos 
com apenas uma nota de alguns tipos ou com notas repetidas. O teste com o valor 186 (uma 
nota de cada valor: 100+50+20+10+5+1) também é importante porque ele exercita todas as 
linhas do programa, já que com estevalor todas as condições do "if-elif-else" são executadas. 
Este teste garante assim a cobertura do código. 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 37 
def quantas_notas(reais): 
assert isinstance(reais, int) and reais >= 0 
print(reais) 
quantidade = 0 
while reais != 0: 
if reais >= 100: 
 reais -= 100 
quantidade += 1 
elif reais >= 50: 
 reais -= 50 
quantidade += 1 
elif reais >= 20: 
 reais -= 20 
quantidade += 1 
elif reais >= 10: 
 reais -= 10 
quantidade += 1 
elif reais >= 5: 
 reais -= 5 
quantidade += 1 
else: 
 reais -= 1 
quantidade += 1 
return quantidade 
 
# Válidos 
assert quantas_notas(0) == 0 # zero notas - valor limítrofe 
assert quantas_notas(100) == 1 # uma nota apenas 
assert quantas_notas(51) == 2 # duas notas não repetidas 
assert quantas_notas(44) == 6 # notas repetidas 
assert quantas_notas(186) == 6 # uma nota de cada 
 
# negativo 
try: 
 quantas_notas(-1) # valor limítrofe 
raise Exception 
except AssertionError: pass 
 
# não inteiro 
try: 
 quantas_notas(1.5) 
raise Exception 
except AssertionError: pass 
 
# não numérico 
try: 
 quantas_notas('abc') 
raise Exception 
except AssertionError: pass 
 
print('Todos os testes finalizados com sucesso') 
 
Interessante observar que eu mesmo desenvolvia solução para este exercício, conforme 
proposto, usando TDD. A primeira versão da função que implementei falhou nos testes porque 
usei ">" em vez de ">=", um erro MUITO comum. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 38 
8.6 
from math import sqrt 
 
def area(a, b, c): 
assert (isinstance(a, int) or isinstance(a, float)) and a >0 
assert (isinstance(b, int) or isinstance(b, float)) and b >0 
assert (isinstance(c, int) or isinstance(c, float)) and c >0 
assert a < b+c and b < a+c and c < a+b 
 p = (a+b+c)/2 
return sqrt(p*(p-a)*(p-b)*(p-c)) 
 
# Válidos 
CASAS_DECIMAIS = 3 
assert round(area(5, 5, 5), CASAS_DECIMAIS) == 10.825 # equilátero 
assert round(area(5, 5, 2), CASAS_DECIMAIS) == 4.899 # isósceles acutângulo 
assert round(area(5, 5, 8.5), CASAS_DECIMAIS) == 11.194 # isósceles obtusângulo 
assert round(area(5, 3, 2.1), CASAS_DECIMAIS) == 1.236 # escaleno acutângulo 
assert round(area(5.1, 3.5, 8), CASAS_DECIMAIS) == 6.184 # escaleno obtusângulo 
assert round(area(3, 4, 5), CASAS_DECIMAIS) == 6 # reto 
 
# valores negativos 
try: 
 area(-1, -3, -4) 
raise Exception 
except AssertionError: pass 
 
# não numérico 
try: 
 area('a', 'b', 'c') 
raise Exception 
except AssertionError: pass 
 
# não forma triângulo - valor limítrofe onde c = a+b 
try: 
 area(1, 2, 3) 
raise Exception 
except AssertionError: pass 
 
# não forma triângulo 
try: 
 area(10, 2, 5) 
raise Exception 
except AssertionError: pass 
 
print('Todos os testes finalizados com sucesso') 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 39 
8.7 
def converte(temperatura, escala): 
assert isinstance(temperatura, int) or isinstance(temperatura, float) 
assert escala == 'C' or escala == 'F' 
if escala == 'C': 
assert temperatura >= -273.15 
return 1.8*temperatura + 32 
if escala == 'F': 
assert temperatura >= -459.67 
return (temperatura-32)/1.8 
 
# Válidos 
CASAS_DECIMAIS = 2 
assert round(converte(-273.15, 'C'), CASAS_DECIMAIS) == -459.67 #valor limítrofe 
assert round(converte(-459.67, 'F'), CASAS_DECIMAIS) == -273.15 #valor limítrofe 
assert round(converte(0, 'C'), CASAS_DECIMAIS) == 32 
assert round(converte(0, 'F'), CASAS_DECIMAIS) == -17.78 
assert round(converte(15, 'C'), CASAS_DECIMAIS) == 59 
assert round(converte(38, 'F'), CASAS_DECIMAIS) == 3.33 
 
# abaixo do zero absoluto - valor limítrofe 
try: 
 converte(-273.16, 'C') 
raise Exception 
except AssertionError: pass 
 
try: 
 converte(-459.68, 'F') 
raise Exception 
except AssertionError: pass 
 
# temperatura não numérica 
try: 
 converte('C', 'F') 
raise Exception 
except AssertionError: pass 
 
# escala inválida 
try: 
 converte(10, 'K') 
raise Exception 
except AssertionError: pass 
 
print('Todos os testes finalizados com sucesso') 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 40 
9 Estruturas de Dados Primitivas 
9.1 
from string import ascii_lowercase 
 
def letras_disponíveis(usadas): 
assert isinstance(usadas, list) 
for elemento in usadas: 
assert type(elemento) == str \ 
and len(elemento) == 1 \ 
and 'a' <= elemento <= 'z' 
restantes = list(ascii_lowercase) 
for letra in usadas: 
 restantes.remove(letra) 
return restantes 
 
 
# classes válidas 
assert letras_disponíveis([]) == list(ascii_lowercase) 
assert letras_disponíveis(list(ascii_lowercase)) == [] 
assert letras_disponíveis(['a', 'g', 'b', 'k', 'y']) == \ 
 ['c', 'd', 'e', 'f', 'h', 'i', 'j', 'l', 'm', 'n', 
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'z'] 
 
# classes inválidas 
try: 
 letras_disponíveis(1) # não é lista 
raise Exception 
except AssertionError: pass 
 
try: 
 letras_disponíveis([1, 2]) # elementos que não são letras 
raise Exception 
except AssertionError: pass 
 
try: 
 letras_disponíveis(['$']) # string que não é letra 
raise Exception 
except AssertionError: pass 
 
try: 
 letras_disponíveis(['asd']) # string com mais de 1 caractere 
raise Exception 
except AssertionError: pass 
 
print('Todos testes concluídos com sucesso!') 
9.2 
Minha primeira versão deste programa falhou no teste em que todas as letras da palavra são 
informadas porque usei um if letra in restantes em vez de while letra in restantes. Neste caso, 
como a palavra tem a letra "a" repetida 3 vezes, o programa só removeu uma ocorrência do 
"a" e assim "restantes" ficou com ['a', 'a']. Quando percebi isso, simplesmente troquei o "if" 
por "while" e o programa funcionou sem erros. 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 41 
def adivinhou_palavra(letras, palavra): 
assert isinstance(letras, list) 
for elemento in letras: 
assert isinstance(elemento, str) \ 
and len(elemento) == 1 \ 
and 'a'<= elemento <= 'z' 
assert isinstance(palavra, str) 
for simbolo in palavra: 
assert 'a'<= simbolo <= 'z' 
restantes = list(palavra) 
for letra in letras: 
while letra in restantes: 
 restantes.remove(letra) 
return len(restantes) == 0 
 
# classes válidas 
assert adivinhou_palavra([], 'palavra') == False # nenhuma letra no palpite 
assert adivinhou_palavra(['a'], 'palavra') == False # uma letra no palpite 
assert adivinhou_palavra(['a', 'p', 'l', 'v', 'r'], 'palavra') == True 
assert adivinhou_palavra(['a', 'f', 'p', 'l', 'v', 'r', 'q'], 'palavra') == True 
 
# classes inválidas 
try: 
 adivinhou_palavra(1, 'palavra') # primeiro argumento não é lista 
raise Exception 
except AssertionError: pass 
 
try: 
 adivinhou_palavra([1, 2], 'palavra') # lista com elementos que não são letras 
raise Exception 
except AssertionError: pass 
 
try: 
 adivinhou_palavra(['$'], 'palavra') # string que não é letra 
raise Exception 
except AssertionError: pass 
 
try: 
 adivinhou_palavra(['asd'], 'palavra') # string com mais de 1 caracter 
raise Exception 
except AssertionError: pass 
 
try: 
 adivinhou_palavra(['a'], 'palavra1') # palavra com símbolo não alfabético 
raise Exception 
except AssertionError: pass 
 
try: 
 adivinhou_palavra(['a'], 5) # palavra não é string 
raise Exception 
except AssertionError: pass 
 
print('Todos testes concluídos com sucesso!') 
9.3 
Aqui, usamos uma abordagem nova para percorrer a lista que produz um algoritmo mais 
simples do que outros que seriam possíveis. Inicializamoso "elemento_anterior", que dentro 
do "for" será comparado com o elemento da iteração com "None", que literalmente significa 
"nenhum". Assim, quando o primeiro "if" subordinado ao "for" verificar se o elemento atual é 
igual ao anterior, a comparação dará "False" e essa é exatamente a intenção, já que naquele 
momento não existe elemento anterior. Se o "elemento_anterior" não tivesse sido inicializado 
dessa forma, teríamos que primeiro tratar a situação especial do primeiro elemento, antes do 
"for", e em seguida fazer o "for" variar a partir do segundo elemento da lista. Isso causaria a 
repetição de código que está dentro do "for" e teria que aparecer também antes dele. Mas 
atenção: o "None" não pode ser comparado a números com os operadores ">", "<", "<=" e 
">=", mas apenas com "==" e "!=". 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 42 
def maior_sequencia(lista): 
assert isinstance(lista, list) 
for elemento in lista: 
assert isinstance(elemento, int) 
 elemento_anterior = None 
contador = 1 
maior_contador = 0 
for elemento in lista: 
if elemento == elemento_anterior: 
contador += 1 
else: 
 contador = 1 
if contador > maior_contador: 
 maior_contador = contador 
 elemento_anterior = elemento 
return maior_contador 
 
# válidos 
assert maior_sequencia([]) == 0 
assert maior_sequencia([5]) == 1 
assert maior_sequencia([5, 6, 7]) == 1 
assert maior_sequencia([5, 5, 6]) == 2 
assert maior_sequencia([5, 6, 5]) == 1 
assert maior_sequencia([3, 4, 1, 1, 1, 1, 1, 3, 3, 3, 3]) == 5 
 
#inválidos 
try: 
 maior_sequencia(5) 
raise Exception 
except AssertionError: pass 
 
try: 
 maior_sequencia([3, 4, 'abc']) 
raise Exception 
except AssertionError: pass 
 
print('Todos os testes concluídos com sucesso!') 
9.4 
Aqui, a técnica usada para saber se uma lista é permutação da outra foi criar uma cópia da 
segunda lista, para evitar efeitos colaterais e fazer o seguinte: para cada elemento da primeira 
lista, se ele estiver na segunda lista, removê-lo da segunda lista; se ele não estiver, retornar 
"False". Se, no final, a segunda lista estiver vazia, retornar "True"; senão, retornar "False". 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 43 
def é_permutação(l1, l2_original): 
assert isinstance(l1, list) and isinstance(l2_original, list) 
 l2 = l2_original.copy() 
for elemento in l1: 
if elemento in l2: 
 l2.remove(elemento) 
else: 
return False 
 return l2 == [] 
 
assert é_permutação([1, 2, 3, 3, 8, 9, 0, 2], [0, 1, 2, 2, 3, 3, 8, 9]) 
assert not é_permutação([0, 1, 2, 2, 3, 3, 3, 8], [0, 1, 2, 2, 3, 3, 8, 9]) 
assert not é_permutação([0, 1, 2, 2, 3, 3, 8, 9], [0, 1, 2, 3, 8, 9]) 
assert not é_permutação([], [0, 1, 2, 3, 8, 9]) 
assert not é_permutação([0, 1, 2, 2, 3, 3, 8, 9], []) 
assert é_permutação([], []) 
 
try: 
 é_permutação(3, [0, 1, 2, 2, 3, 3, 8, 9]) 
raise Exception 
except AssertionError: pass 
 
try: 
 é_permutação([0, 1, 2, 2, 3, 3, 8, 9], 4) 
raise Exception 
except AssertionError: pass 
 
print('Todos testes executados com sucesso') 
9.5 
Este programa é apenas uma variação da Mega-Sena, na qual a quantidade de números e o 
intervalo de geração são alterados. 
from random import randint 
print('Loteria') 
sorteados = [] 
while len(sorteados) <25: 
 sorteado = randint(1, 40) 
for posição in range(len(sorteados)): 
 número = sorteados[posição] 
if número == sorteado: 
break 
 if número > sorteado: 
 sorteados.insert(posição, sorteado) 
break 
 else: 
 sorteados.append(sorteado) 
print(sorteados) 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 44 
9.6 
Os testes a serem executados para testar esta função são mostrados abaixo. Em seguida, duas 
estratégias de resolução do problema são mostradas e discutidas: 
assert união([3,7,1,9,5,6,4], [1,7,5,8,2,0,3]) \ 
 == [0,1,2,3,4,5,6,7,8,9] 
assert união([1, 1, 1, 1, 1], [2, 0, 2]) == [0, 1, 2] 
assert união([1, 2, 3], [4]) == [1, 2, 3, 4] 
assert união([1, 2, 3], []) == [1, 2, 3] 
assert união([1], [1]) == [1] 
assert união([], []) == [] 
 
try: 
 união(1, [1]) # argumento 1 não é lista 
raise Exception 
except AssertionError: pass 
 
try: 
 união([1], 'abc') # argumento 2 não é lista 
raise Exception 
except AssertionError: pass 
 
try: 
 união([1, 'abc'], [1]) # lista com valor não numérico 
raise Exception 
except AssertionError: pass 
 
try: 
 união([1], ['abc', 2]) # lista com valor não numérico 
raise Exception 
except AssertionError: pass 
 
print('Todos testes executados com sucesso') 
A primeira estratégia, a mais óbvia, consiste em usar uma abordagem semelhante à que 
usamos no problema da Mega-Sena. Vamos criar uma nova lista para ser a ordenada. Depois 
percorrer cada lista original e, para cada elemento, procuramos na lista ordenada se ele já está 
lá. Se estiver, ignoramos o elemento e vamos para o próximo; se encontrarmos um elemento 
maior do que ele, nós o inserimos antes deste elemento e vamos para o próximo; senão nós o 
inserimos no final da lista: 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 45 
 
def união(l1, l2): 
assert isinstance(l1, list) 
assert isinstance(l2, list) 
for elemento in l1: 
assert type(elemento) in [float, int] 
for elemento in l2: 
assert type(elemento) in [float, int] 
 nova_lista = [] 
for elemento in l1: 
for posição in range(len(nova_lista)): 
if nova_lista[posição] == elemento: 
break 
 elif nova_lista[posição] > elemento: 
 nova_lista.insert(posição, elemento) 
break 
 else: 
 nova_lista.append(elemento) 
for elemento in l2: 
for posição in range(len(nova_lista)): 
if nova_lista[posição] == elemento: 
break 
 elif nova_lista[posição] > elemento: 
 nova_lista.insert(posição, elemento) 
break 
 else: 
 nova_lista.append(elemento) 
return nova_lista 
 
O problema com este algoritmo é que o código subordinado a for elemento in l1 e for 
elemento in l2 é idêntico, aparecendo assim duas vezes repetido na função. Isso não é uma 
boa prática de programação. Código duplicado é normalmente fonte de dor de cabeça. Assim, 
nossa segunda abordagem consiste em, antes de executar este código uma única vez, produzir 
uma lista que seja a união das duas listas originais, fazendo união = l1+l2. Inclusive, podemos 
fazer isso já durante as precondições (linhas com "assert"), logo depois de nos certificarmos 
que os dois parâmetros são listas, para simplificar o código ali também: 
def união(l1, l2): 
assert isinstance(l1, list) 
assert isinstance(l2, list) 
 união = l1+l2 
for elemento in união: 
assert type(elemento) in [float, int] 
 nova_lista = [] 
for elemento in união: 
for posição in range(len(nova_lista)): 
if nova_lista[posição] == elemento: 
break 
 elif nova_lista[posição] > elemento: 
 nova_lista.insert(posição, elemento) 
break 
 else: 
 nova_lista.append(elemento) 
return nova_lista 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 46 
9.7 
def soma(t, u): 
assert isinstance(t, tuple) and len(t) == 2 
assert isinstance(u, tuple) and len(u) == 2 
assert isinstance(t[0], int) or isinstance(t[0], float) 
assert isinstance(u[0], int) or isinstance(u[0], float) 
assert t[1] == 'C' or t[1] == 'F' 
assert u[1] == 'C' or u[1] == 'F' 
 
if t[1] == u[1]: 
return (t[0]+u[0], t[1]) 
else: 
if t[1] == 'F': 
 t_convertido = (t[0]-32)/1.8 
else: 
 t_convertido = 1.8*t[0]+32 
return(t_convertido+u[0], u[1]) 
 
# válidos 
assert soma((12, 'C'), (20, 'C')) == (32, 'C') 
assert soma((-12, 'F'), (20, 'F')) == (8, 'F') 
assert soma((12, 'C'), (20, 'F')) == (73.6, 'F') 
assert soma((32, 'F'), (-20, 'C')) == (-20, 'C') 
 
# inválidos 
 
try: 
 soma(5, (1, 'F')) 
raise Exception 
except AssertionError: pass 
 
try: 
 soma((1, 'F'), 'C') 
raise Exception 
except AssertionError: pass 
 
try: 
 soma(('C', 'C'), (1, 'F')) 
raise Exception 
except AssertionError: pass 
 
try: 
 soma((5, 'C'), ('1', 'F')) 
raise Exception 
except AssertionError: pass 
 
try: 
 soma((5, 'K'), ('1', 'F')) 
raise Exception 
except AssertionError: pass 
 
try: 
 soma((5, 'C'), ('1', 'K')) 
raise Exception 
except AssertionError: pass 
 
print('Todos os testes executados com sucesso!') 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 47 
9.8 
def menos_provável(partículas): 
assert isinstance(partículas, dict) 
for chave in partículas: 
 valor = partículas[chave] 
assert type(valor) in [int, float] 
assert 1 == sum(list(partículas.values())) 
 chave_menor = [] 
 valor_menor = None 
 for chave, valor in partículas.items(): 
if valor_menor == None: 
 valor_menor = valor 
 chave_menor.append(chave) 
elif valor == valor_menor: 
 chave_menor.append(chave) 
elif valor < valor_menor: 
 chave_menor = [chave] 
 valor_menor = valor 
return chave_menor 
 
# classes válidas 
dic = {'neutron': 0.55, 'proton': 0.21, 
'meson': 0.03, 'muon': 0.07, 'neutrino': 0.14} 
assert menos_provável(dic) == ['meson'] 
 
dic = {'neutron': 0.55, 'proton': 0.21, 
'meson': 0.03, 'muon': 0.03, 'neutrino': 0.18} 
resultado = menos_provável(dic) 
assert resultado == ['meson', 'muon'] \ 
or resultado == ['muon', 'meson'] 
 
dic = {'neutron': 0.55, 'proton': 0.03, 
'meson': 0.21, 'muon': 0.03, 'neutrino': 0.18} 
resultado = menos_provável(dic) 
assert resultado == ['proton', 'muon'] \ 
or resultado == ['muon', 'proton'] 
 
dic = {'neutron': 0.55, 'proton': 0.21, 
'meson': 0.21, 'muon': 0.03, 'neutrino': 0.0} 
resultado = menos_provável(dic) 
assert resultado == ['neutrino'] \ 
or resultado == ['neutrino'] 
 
# classes inválidas 
try: 
 menos_provável([5, 3]) # não é dicionário 
raise Exception 
except AssertionError: pass 
 
try: 
 menos_provável({'meson': 'abc'}) # valor não numérico 
raise Exception 
except AssertionError: pass 
 
try: 
 menos_provável({'meson': 0.5, 'proton': 0.4}) # prob. total < 1 
raise Exception 
except AssertionError: pass 
 
try: 
 menos_provável({'meson': 0.5, 'proton': 0.6}) # prob. total > 1 
raise Exception 
except AssertionError: pass 
 
print('Todos testes executados com sucesso') 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 48 
10 Estruturas de Dados Derivadas 
10.1 
def analisa(expressão): 
assert isinstance(expressão, str) 
 pilha = [] 
 caracteres = list(expressão) 
for símbolo in caracteres: 
if símbolo == '(': 
 pilha.append(símbolo) 
elif símbolo == ')': 
if pilha and pilha[-1] == '(': 
 pilha.pop() 
else: 
return False 
 return pilha == [] 
 
assert analisa('a+b') 
assert not analisa('(a+b') 
assert analisa('(a+(b+c-(a)*e+(a)))') 
assert not analisa('(a+(b+c-a)*e+(a)))') 
assert not analisa(')+a+(') 
 
try: 
 analisa(5) 
raise Exception 
except AssertionError: pass 
 
print('Sucesso!') 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 49 
10.2 
def é_palíndromo(expressão): 
assert isinstance(expressão, str) 
 tamanho = len(expressão) 
assert tamanho >= 1 
pilha = [] 
 caracteres = list(expressão) 
 posição = tamanho//2 
for i in range(posição): 
 pilha.append(caracteres[i]) 
if tamanho % 2 != 0: # se a expressão tem tamanho ímpar 
posição += 1 # despreza o caractere central 
for i in range(posição, tamanho): 
if caracteres[i] != pilha.pop(): 
return False 
 return True 
 
assert é_palíndromo('x') 
assert é_palíndromo('ana') 
assert é_palíndromo('osso') 
assert é_palíndromo('abcdcba') 
assert not é_palíndromo('casa') 
assert not é_palíndromo('quadros') 
 
try: 
 é_palíndromo(5) 
raise Exception 
except AssertionError: pass 
 
try: 
 é_palíndromo('') 
raise Exception 
except AssertionError: pass 
 
print('Sucesso!') 
10.3 
N = 4 
a = [] 
for i in range(N, 0, -1): 
 a.append(i) 
b = [] 
c = [] 
 
print(a, b, c) 
for i in range(1, 2**N): 
if i % 3 == 1: 
 origem = a 
 destino = b 
elif i % 3 == 2: 
 origem = a 
 destino = c 
else: 
 origem = b 
 destino = c 
if not origem or (destino and destino[-1] < origem[-1]): 
 origem, destino = destino, origem 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 50 
 destino.append(origem.pop()) 
print(i, a, b, c) 
10.4 
fila = [] 
prioridades = [] 
while True: 
 comando = input('Digite (c)hegada (a)tender (p)arar: ') 
if comando == 'c': 
 nome = input('Digite o nome do paciente: ') 
if input('Prioridade (s/n)? ') == 's': 
 prioridades.append(nome) 
else: 
 fila.append(nome) 
elif comando == 'a': 
if prioridades: 
 nome = prioridades.pop(0) 
print(nome) 
elif fila: 
 nome = fila.pop(0) 
print(nome) 
else: 
print('Não há ninguém na fila') 
elif comando == 'p': 
if not fila: 
break 
 else: 
print('A fila ainda contém os seguintes nomes:') 
for nome in fila: 
print(nome) 
 opção = input('Parar? (s)im (n)ão: ') 
if opção == 's': 
break 
 else: 
print('Comando desconhecido!') 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 51 
10.5 
from random import random 
TEMPO_SIMULAÇÃO = 1000 
PROBABILIDADE_CARRO = 0.05 
TEMPO_SEMÁFORO = 50 
via1 = [] 
via2 = [] 
carro = 1 
carros_parados = 0 
semáforo = True 
for i in range(1, TEMPO_SIMULAÇÃO+1): 
if random() < PROBABILIDADE_CARRO: 
 via1.append(carro) 
 carro += 1 
if random() < PROBABILIDADE_CARRO: 
 via2.append(carro) 
 carro += 1 
print(i, via1, via2) 
if i % TEMPO_SEMÁFORO == 0: 
 semáforo = not semáforo 
print('Semáforo mudou') 
if semáforo: 
if via1: 
 via1.pop(0) 
else: 
if via2: 
 via2.pop(0) 
 carros_parados += len(via1) + len(via2) 
assert TEMPO_SIMULAÇÃO != 0 
print('Número médio de carros parados:', carros_parados/TEMPO_SIMULAÇÃO) 
 
Ao executar o programa algumas vezes, obtivemos resultados variando entre 0.9 e 1.6. 
Executando novamente com probabilidades de 70%, os resultados variaram entre 190 e 290 
automóveis parados em média, ou seja, um grande congestionamento. 
 
 
 
 
 
 
 
 
 
 
Introdução a Algoritmos e Programação com Python - Raul Sidnei Wazlawick ©Elsevier, 2017 
 
 52 
10.6 
def é_quadrado_mágico(matriz): 
# valor da linha 0 - padrão de comparação 
padrão = sum(matriz[0]) 
# verifica linhas 
for linha in matriz: 
if padrão != sum(linha): 
return False 
# verifica colunas 
for coluna in range(len(matriz)): 
 valor = 0 
for linha in range(len(matriz)): 
 valor += matriz[linha][coluna] 
if valor != padrão: 
return False 
# verifica diagonais 
valor1 = 0 
valor2 = 0 
for linha in range(len(matriz)): 
 valor1 += matriz[linha][linha] # diagonal principal 
valor2 += matriz[linha][len(matriz)-linha-1] # diag. secundária 
if valor1 != padrão or valor2 != padrão: 
return False 
 return True 
 
quadrado_mágico = [[2, 7, 6], [9, 5, 1], [4,

Continue navegando