# aprenentatge de bucles

Bucles en Python

while i for: com repeteix un programa instruccions, com es controla amb break, continue i pass, i com llegir-ne l'execució pas a pas.

Per què repetim instruccions?

Un bucle executa un bloc de codi repetidament mentre es compleixi (o per a cada element d'una seqüència) una condició. Evita haver d'escriure la mateixa instrucció moltes vegades i permet recórrer llistes, comptar, o esperar un esdeveniment.

while mentre la condició sigui certa

Comprova la condició abans de cada volta. Si és falsa des del principi, el cos no s'executa mai. En Python, el cos es marca amb indentació (espais), no amb claus.

Sintaxi

while condició:
    # cos: s'executa mentre condició sigui certa

Exemple

i = 1
while i <= 5:
    print(i)
    i += 1

S'imprimeixen els nombres 1 a 5. Cada volta: es comprova i <= 5, s'executa el cos, i s'incrementa i manualment — si oblidéssim l'i += 1, el bucle no acabaria mai.

for recorrent una seqüència

Un for en Python recorre els elements d'una seqüència. Amb range(inici, final, pas) es genera una seqüència de nombres sense incloure el valor final.

Sintaxi

for variable in seqüència:
    # cos

Exemple

for i in range(1, 6):
    print(i)

range(1, 6) genera 1, 2, 3, 4, 5 — el 6 no s'inclou mai. A cada volta, i pren el següent valor del rang; quan s'exhaureix, el bucle acaba tot sol, sense necessitat d'incrementar res a mà.

Control del flux dins un bucle

De vegades cal sortir abans d'hora, saltar-nos una volta concreta, o simplement no fer res.

break

Talla el bucle immediatament: no es torna a comprovar la condició ni el rang, s'ix directament del bucle.

for i in range(1, 11):
    if i == 4:
        break
    print(i)
# imprimeix: 1 2 3

continue

Salta directament a la següent volta, sense executar la resta del cos d'aquesta volta.

for i in range(1, 6):
    if i == 3:
        continue
    print(i)
# imprimeix: 1 2 4 5  (el 3 no s'arriba a imprimir)

pass

No fa absolutament res. És un marcador de lloc buit: s'utilitza quan la sintaxi exigeix un bloc (per exemple dins un if) però encara no hi vols posar cap instrucció. A diferència de continue, pass no salta res: l'execució simplement continua a la línia següent com si aquell bloc no hi fos.

for i in range(1, 6):
    if i == 3:
        pass
    print(i)
# imprimeix: 1 2 3 4 5  (el 3 SÍ s'imprimeix: pass no salta res)

Mira el bucle executar-se pas a pas

Tria una variant i avança pas a pas (o deixa-ho en reproducció automàtica) per veure com evolucionen les variables i la sortida per terminal.

Codi

Variables

NomValor

Terminal

Pas 1 / 1

Problemes per resoldre

Sense solució ni comprovació automàtica: escriu el programa, executa'l (python3 programa.py) i prova'l amb els exemples. Amb variables, condicionals i bucles en tens prou. Les pistes són plegades perquè les obris només si les necessites.

1. Suma d'una progressió aritmètica for

Una progressió aritmètica té com a terme general a(n) = a·n + b. Demana a i b (nombres decimals) i n (enter), i calcula la suma dels n primers termes sumant-los un a un. Després comprova el resultat calculant-lo també amb la fórmula (a1 + an) · n / 2, on a1 és el primer terme i an l'últim.

a: 2
b: 1
n: 5
Suma dels 5 primers termes: 35.00
Amb la fórmula: 35.00
Pistes

Els termes són 3, 5, 7, 9 i 11, i sumen 35. Necessites un acumulador suma que comenci a 0 i un for ct in range(1, n + 1): (recorda que range no inclou el final); a cada volta hi afegeixes a*ct + b.

Llegeix a i b amb float(input(...)) i n amb int(input(...)). El primer terme és a*1 + b i l'últim a*n + b. Amb una f-string com f"{suma:.2f}" obtens els dos decimals.

2. Una dada vàlida while True + break

Demana una nota entre 0 i 10 (tots dos inclosos). Si l'usuari escriu un valor fora d'aquest rang, mostra un missatge d'error i torna a demanar-la, tantes vegades com calgui. Quan la nota sigui correcta, mostra-la.

Nota (0-10): 12
Valor fora de rang.
Nota (0-10): -3
Valor fora de rang.
Nota (0-10): 7
Nota acceptada: 7
Pistes

Python no té do-while: la nota s'ha de demanar almenys un cop, i això es fa amb while True: i un break quan el valor és correcte.

Comprova el rang amb la comparació encadenada 0 <= nota <= 10. El missatge d'error només s'ha de mostrar quan el valor és incorrecte.

3. Multiplicació russa while True + break

L'algorisme rus per multiplicar escriu a i b en dues columnes. A cada fila, a es divideix entre 2 (divisió entera) i b es multiplica per 2, fins que a arriba a 0. La suma dels valors de b de les files on a és senar és el producte a·b. Escriu un programa que ho calculi així, sense fer a*b.

Introdueix a i b: 46 43
46 x 43 = 1978
Pistes

Per a 46 i 43 les files són:

  a     b
 46    43
 23    86   ← a és senar: se suma 86
 11   172   ← senar: se suma
  5   344   ← senar: se suma
  2   688
  1  1376   ← senar: se suma

I 86 + 172 + 344 + 1376 = 1978.

Com que no hi ha do-while, fes servir while True: i surt amb break quan a arribi a 0 (al final de cada volta). Treballa amb còpies x i y si vols escriure a i b originals. Divisió entera: //. Pots fer x, y = x // 2, y * 2 en una sola línia. Per llegir dos valors, demana'ls amb dos input() separats.

4. Decimal a binari while

Demana un nombre natural més petit que 256 i escriu-ne la representació en binari fent divisions successives per 2 i quedant-te amb les restes. Si el nombre no és vàlid, torna a demanar-lo.

Nombre (0-255): 100
100 en binari és 1100100
Pistes

Les restes surten de dreta a esquerra: 100%2 = 0, 50%2 = 0, 25%2 = 1, 12%2 = 0... La primera que surt és el bit menys significatiu.

En Python pots construir el resultat com una cadena: comença amb bin = "" i a cada volta posa la resta al davant, bin = str(resta) + bin.

Comprova que el 0 també funciona: el bucle no s'executa cap cop i la cadena queda buida, així que caldrà tractar-lo a part. Per demanar el nombre fins que sigui vàlid, reutilitza la idea de l'exercici 2.

5. Nombre primer while

Demana un enter n i digues si és primer. Un nombre és primer si només és divisible entre 1 i entre ell mateix; el 0 i l'1 no ho són.

Nombre: 17
17 és primer

Nombre: 91
91 no és primer

Nombre: 1
1 no és primer
Pistes

Prova els divisors 2, 3, 4... i para en trobar el primer que divideixi n (n % divisor == 0): no cal mirar-los tots.

N'hi ha prou de provar-los mentre divisor*divisor <= n (si n té un divisor més gran que la seva arrel, en té també un de més petit). Així no cal cap arrel quadrada ni import math.

Una variable booleana primer que passa a False quan trobes un divisor et deixa sortir amb la condició del while. Comença-la a False si n < 2.

6. MCD de tres nombres while

L'algorisme d'Euclides calcula el màxim comú divisor de m i n: mentre n no sigui 0, es substitueix (m, n) per (n, resta de m entre n); quan n és 0, el MCD és m. Escriu un programa que llegeixi tres enters positius i en calculi el MCD, sabent que MCD(a, b, c) = MCD(MCD(a, b), c).

a: 120
b: 140
c: 210
MCD(120, 140, 210) = 10
Pistes

Els passos són MCD(120, 140) = 20 i després MCD(20, 210) = 10.

El cos del bucle es pot escriure en una sola línia amb assignació múltiple: m, n = n, m % n. Calcula primer el MCD d'a i b i guarda'l; després aplica el mateix bucle amb aquest resultat i c. Treballa amb còpies si vols escriure a, b i c al final.

7. L'algorisme 3n+1 while

Parteix d'un enter n ≥ 1 i repeteix: escriu n; si n val 1, acaba; si n és senar, substitueix-lo per 3n+1; si és parell, per n/2. Escriu tots els valors (el «cicle» de n) en una sola línia i, al final, la longitud del cicle (quants valors has escrit, comptant el primer i l'1).

Nombre: 22
22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
Longitud del cicle: 16

Nombre: 8
8 4 2 1
Longitud del cicle: 4
Pistes

No saps quantes voltes farà el bucle, per això un while (que s'acaba quan n val 1) hi encaixa millor que un for.

Per escriure en una sola línia fes servir print(n, end=" "), i un print() buit al final per saltar de línia. Divisió entera per 2: n // 2. Un comptador que comenci a 1 et dona la longitud. Prova nombres de la forma 2n (64, 1024...): tenen cicles molt curts.

8. Nombres «XX» bucles encaixats

Diem que un enter és «XX» si tots els seus divisors, excepte ell mateix i l'1, són nombres primers. Demana un enter positiu N i escriu tots els nombres «XX» entre 0 i N (tots dos exclosos), separats per espais.

N: 21
1 2 3 4 5 6 7 9 10 11 13 14 15 17 19
Pistes

El 8 no és «XX» perquè és divisible entre 4, que no és primer. El 6 sí que ho és: els seus divisors 2 i 3 són primers. L'1 no té cap divisor per comprovar, així que hi entra.

Tres bucles encaixats: el de fora recorre els candidats i d'1 a N-1 (range(1, N)); el del mig recorre els possibles divisors d de 2 a i-1 i mira si i % d == 0; el de dins comprova si aquest divisor és primer (com a l'exercici 5).

Una variable booleana xx que comença a True i passa a False quan trobes un divisor que no és primer. Escrius i només si, en acabar, xx segueix a True.

Exercicis d'autoavaluació

Cada exercici es genera amb valors nous a l'atzar. Llegeix el codi, pensa quina serà la sortida per terminal i comprova-ho.

—

Quina serà la sortida per terminal d'aquest programa?