Lista 07 · Repetição com while¶
Esta lista é sobre uma única ideia: voltar e fazer de novo. Todo exercício aqui tem um laço, e todo laço tem as mesmas três peças — a variável que existe antes, a condição que decide se continua, e a linha que faz a variável avançar.
Faça a Parte A no papel, antes de abrir o OnlineGDB. Rastrear um laço volta a volta é a habilidade que a prova cobra, e é a única forma de entender um laço que não faz o que você esperava.
Dois avisos antes de rodar qualquer coisa:
- Se o programa não parar, você escreveu um laço infinito. Não é defeito da máquina: falta a linha que muda a variável do teste. Botão Stop vermelho no OnlineGDB, e leia o bloco de novo.
- Se o total sair igual à última parcela, o acumulador está sendo zerado dentro do laço. Esse não trava, não reclama e entrega o número errado — é o erro mais importante da unidade.
Como esta lista funciona
Cada exercício abaixo é um arquivo só. Copie o código inteiro, cole no
OnlineGDB, escreva a sua solução no lugar do # TODO e
aperte ▶ Run.
Nos exercícios que mostram como deve ficar, compare a sua saída com a publicada aqui, linha por linha. Espaço a mais, acento faltando e letra maiúscula contam: o computador não relaxa em nenhum deles.
Parte A · no papel¶
Faça esta parte antes de ligar o computador
Escreva a resposta no caderno, depois rode para conferir. Prever e errar ensina; rodar primeiro e ler a saída, não.
Estes são para fazer no papel, sem computador. Depois rode e confira a sua previsão — se a sua tabela bater com a tela, você entendeu o laço.
A1. Rastreie. Complete a tabela, uma linha por volta, e diga o que o programa imprime.
| Volta | contador no teste |
o teste dá | imprime | contador no fim |
|---|---|---|---|---|
| 1 | ||||
| 2 | ||||
| … |
Quantas voltas o laço deu? Com que valor contador fica ao final?
A2. Rastreie o acumulador. Qual é o valor de total impresso?
| Volta | total no início |
n |
total no fim |
|---|---|---|---|
| 1 | 0 | 1 | |
| 2 | |||
| 3 | |||
| 4 |
A3. O erro que não dá erro. Este programa deveria somar 1 + 2 + 3 + 4 + 5. Ele imprime outro número, e não dá erro nenhum.
- Rastreie e diga o que ele imprime.
- Explique, numa frase, por quê.
- Conserte movendo uma única linha.
A4. Laço infinito. Um destes três nunca termina. Qual, e por quê?
# (a)
x = 10
while x > 0:
print(x)
x = x - 2
# (b)
x = 10
while x > 0:
print(x)
x = x + 2
# (c)
x = 10
while x > 0:
x = x - 1
print(x)
A5. < ou <=? Quantas linhas cada um imprime?
A6. A sentinela. O programa abaixo deveria somar valores até a pessoa
digitar 0. Ele trava para sempre. O que falta?
total = 0
valor = float(input("Valor (0 encerra): "))
while valor != 0:
total = total + valor
print(total)
A7. Ordene o algoritmo. As linhas estão fora de ordem. Reescreva-as na ordem que faz o programa somar os números de 1 a 100.
(Duas delas precisam ficar indentadas. Diga quais.)
Parte B · no computador¶
Exercício 01¶
Escreva um programa que pergunte um número inteiro n e mostre a soma de todos
os inteiros de 1 até n.
Use um while. É o padrão acumulador do capítulo: a variável do total nasce
em zero antes do laço.
Use exatamente estes textos, para a sua sessão bater com a publicada:
A sessão publicada usa 10, que dá dez voltas. Mas o caso que quebra é o
0: não há o que somar, o laço dá zero voltas e a resposta é 0. Se o seu
programa imprimir 1 aí, o acumulador começou no lugar errado — ou o avanço
veio antes da soma.
Teste também estes, à mão, trocando o valor digitado — o 0 em primeiro
lugar:
n digitado |
Soma |
|---|---|
| 0 | 0 |
| 1 | 1 |
| 5 | 15 |
| 10 | 55 |
| 100 | 5050 |
Como deve ficar. Rodando o programa e digitando 10,
a tela tem de ficar assim:
# Exercício 01 — a soma de 1 até n.
# TODO: pergunte o numero (e converta para int).
# TODO: crie o acumulador do total, comecando em 0, ANTES do laco.
# TODO: crie o contador comecando em 1, escreva o while e nao esqueca do avanco.
# TODO: depois do laco, mostre a soma.
Exercício 02¶
Escreva um programa que pergunte um número inteiro maior ou igual a zero e mostre quantos algarismos ele tem.
Use um while e o operador // do capítulo 4: dividir por 10 joga fora o
último algarismo (137 // 10 dá 13). Conte quantas vezes dá para fazer isso
até sobrar zero.
Use exatamente estes textos, para a sua sessão bater com a publicada:
Cuidado com o zero
0 tem um algarismo, mas o laço não daria nenhuma volta com ele — o
programa responderia 0, sem travar e sem reclamar. Trate esse caso à
parte, com um if, antes do laço. É por isso que o 0 é o valor da sessão
publicada.
Teste também estes, à mão, trocando o valor digitado:
| Número digitado | Algarismos |
|---|---|
| 0 | 1 |
| 7 | 1 |
| 42 | 2 |
| 137 | 3 |
| 1000 | 4 |
| 987654321 | 9 |
Como deve ficar. Rodando o programa e digitando 0,
a tela tem de ficar assim:
# Exercício 02 — quantos algarismos tem o número.
# TODO: pergunte o numero (e converta para int).
# TODO: trate o caso do 0 separadamente, com um if — ele tem 1 algarismo.
# TODO: senao, enquanto sobrar numero, jogue fora o ultimo algarismo com // 10
# e conte mais um.
# TODO: mostre a quantidade de algarismos.
Exercício 03¶
Um cliente começou a assistir uma série pelo celular, e a cada dia ele assiste um pouco mais: o consumo de dados cresce sempre a mesma quantidade de um dia para o outro. Escreva um programa que pergunte a franquia, o consumo do primeiro dia e o aumento diário, e mostre quantos dias completos ele consegue usar sem estourar a franquia.
Com 1 GB no primeiro dia e aumento de 0,2 GB, os dias gastam 1,0 — 1,2 — 1,4 — 1,6 … GB. Não há divisão que responda isso: cada dia é diferente do anterior, e é o laço que vai somando um de cada vez.
É o padrão do capítulo: um acumulador para o que já foi gasto e um contador para os dias. Mas aqui a condição tem de perguntar "ainda cabe mais um dia?" — e não "já estourou?" —, ou a resposta conta um dia que o cliente não conseguiu completar.
Use exatamente estes textos, para a sua sessão bater com a publicada:
Quando não dá nem para o primeiro dia
Com franquia de 5 GB e consumo de 10 GB no primeiro dia, a resposta é 0 —
o laço dá zero voltas, e isso está certo. É esse o caso da sessão
publicada. Um programa que responde 1 aí desconta um dia que o cliente
nunca teve.
Teste também estes, à mão, trocando os valores digitados:
| Franquia | Consumo no 1º dia | Aumento/dia | Dias completos |
|---|---|---|---|
| 5 | 10 | 1 | 0 |
| 20 | 1 | 0.2 | 10 |
| 10 | 1 | 1 | 4 |
| 30 | 1 | 0.5 | 9 |
| 20 | 1.4 | 0 | 14 |
| 10 | 2 | 0 | 5 |
Repare nas duas últimas linhas: com aumento 0 o consumo é sempre o mesmo, e aí
uma divisão resolveria (20 // 1.4 dá 14). É o aumento que torna o laço
necessário.
Como deve ficar. Rodando o programa e digitando 5, 10, 1,
a tela tem de ficar assim:
# Exercício 03 — quantos dias a franquia aguenta, com o consumo crescendo.
# TODO: pergunte a franquia, o consumo do primeiro dia e o aumento por dia (float).
# TODO: acumulador do que ja foi usado e contador de dias, ANTES do laco.
# TODO: continue enquanto couber MAIS UM dia dentro da franquia.
# TODO: dentro do laco, depois de contar o dia, aumente o consumo do dia seguinte.
# TODO: depois do laco, mostre os dias completos.
Exercício 04¶
Escreva um programa que pergunte um número inteiro maior ou igual a zero e
mostre a soma dos algarismos dele — para 137, a resposta é 11
(1 + 3 + 7).
Dois operadores do capítulo 4 resolvem isto: % 10 devolve o último algarismo e
// 10 joga o último algarismo fora. Repita até não sobrar nada.
Use exatamente estes textos, para a sua sessão bater com a publicada:
Os zeros no meio do caminho
Em 1000 a resposta é 1: três voltas somam zero e não mudam nada, mas o
laço precisa dar essas voltas até sobrar nada. É esse o valor da sessão
publicada. Se o seu programa parar no primeiro zero, ele responde errado sem
dar erro nenhum.
Teste também estes, à mão, trocando o valor digitado:
| Número digitado | Soma dos algarismos |
|---|---|
| 1000 | 1 |
| 0 | 0 |
| 7 | 7 |
| 137 | 11 |
| 4321 | 10 |
| 999999 | 54 |
Como deve ficar. Rodando o programa e digitando 1000,
a tela tem de ficar assim:
# Exercício 04 — a soma dos algarismos.
# TODO: pergunte o numero (e converta para int).
# TODO: acumulador em 0, ANTES do laco.
# TODO: enquanto sobrar numero: pegue o ultimo algarismo com % 10, some,
# e descarte-o com // 10.
# TODO: depois do laco, mostre a soma dos algarismos.
Exercício 05¶
Você está juntando dinheiro para trocar de celular, numa conta que rende um tanto por cento ao mês. Escreva um programa que pergunte o saldo que você já tem, quanto consegue guardar por mês, o rendimento mensal e a meta, e mostre quantos meses faltam para o saldo alcançar ou passar a meta.
A cada mês, nesta ordem: o saldo rende e depois recebe o depósito.
Use exatamente estes textos, para a sua sessão bater com a publicada:
A sessão publicada começa do zero, guarda 100 por mês com rendimento de 2%
e mira 1200: são 11 meses. Sem o rendimento seriam 12, e aí uma divisão
(1200 / 100) resolveria. Com o rendimento, cada mês soma um valor diferente do
anterior, porque o saldo que rende é cada vez maior — e só o laço dá conta
disso.
Mas o caso que quebra é o da meta já alcançada: com saldo 500 e meta 500
a resposta é 0, porque a condição já é falsa de saída e o laço dá zero
voltas. Isso está certo, e é o primeiro que você tem de testar à mão.
Teste também estes, à mão, trocando os valores digitados:
| Saldo | Depósito/mês | Rendimento (%) | Meta | Meses |
|---|---|---|---|---|
| 500 | 100 | 1 | 500 | 0 |
| 0 | 100 | 2 | 1200 | 11 |
| 0 | 100 | 0 | 1200 | 12 |
| 0 | 200 | 5 | 3000 | 12 |
| 0 | 200 | 0 | 3000 | 15 |
| 1000 | 0 | 1 | 1100 | 10 |
| 200 | 100 | 0 | 500 | 3 |
A linha com depósito 0 termina porque o rendimento sozinho já faz o saldo
crescer.
Saldo zero e depósito zero não termina nunca
Se o saldo começar em 0 e o depósito for 0, não há nada para render nem
para somar: o saldo fica parado abaixo da meta e o laço não para. Botão
Stop vermelho no OnlineGDB.
Como deve ficar. Rodando o programa e digitando 0, 100, 2, 1200,
a tela tem de ficar assim:
# Exercício 05 — meses até alcançar a meta, com o dinheiro rendendo.
# TODO: pergunte o saldo atual, o deposito mensal, o rendimento (%) e a meta (float).
# TODO: um contador de meses, ANTES do laco.
# TODO: enquanto o saldo for MENOR que a meta: o saldo rende, recebe o deposito,
# e conta-se um mes.
# TODO: depois do laco, mostre quantos meses foram.
Exercício 06¶
Escreva um programa que pergunte, um de cada vez, quanto o cliente consumiu de
dados em cada dia, em GB. Quando ele digitar 0, o programa para de perguntar e
mostra:
- quantos dias foram informados;
- o consumo total, com uma casa decimal;
- a média por dia, com duas casas decimais.
O 0 é a sentinela: ele encerra o laço e não entra na conta.
Use exatamente estes textos, para a sua sessão bater com a publicada:
Os dois input()
Um antes do while, para a condição ter o que testar na primeira volta, e
outro no fim do bloco, para a próxima volta ter um valor novo. Faltando
o segundo, o programa nunca termina.
Pode supor que o cliente informa pelo menos um dia antes de digitar 0.
Como deve ficar. Rodando o programa e digitando 1.4, 2.0, 0.6, 3.0, 0,
a tela tem de ficar assim:
Consumo do dia em GB (0 encerra): 1.4
Consumo do dia em GB (0 encerra): 2.0
Consumo do dia em GB (0 encerra): 0.6
Consumo do dia em GB (0 encerra): 3.0
Consumo do dia em GB (0 encerra): 0
Dias informados: 4
Consumo total: 7.0 GB
Media por dia: 1.75 GB