Algoritmen

Computers laten pas echt zien wat ze kunnen als de oplossing van een probleem niet goed uitgedrukt kan worden door een formule. Bij programmeren werken we aan het verzinnen en uitschrijven van algoritmes, die precies specificeren hoe een probleem stap-voor-stap opgelost moet worden. Een belangrijk aspect van algoritmen is dat ze werken voor verschillende invoer. In het filmpje hieronder moet het algoritme het juiste antwoord opleveren als er 0, 1, 2, 3, 4, enz. mensen in de kamer zijn.

In het hoofdstuk basiselementen heb je een aantal instructies ( statements) geleerd waar Python mee om kan gaan:

Daarnaast heb je kennis gemaakt met operators die gebruikt worden om expressies samen te stellen. Dit was al genoeg om een werkend programma te schrijven. We gaan het nu interessanter maken door uitzonderingen en herhaling toe te staan.

Voorwaardelijke instructies

In de voorgaande programma’s schreven we scriptjes die regel voor regel van boven naar beneden werden uitgevoerd. Een soort stapsgewijze handleiding. Programma’s worden interessanter als we uitzonderingen willen beschrijven.

Tot nu toe konden we bijvoorbeeld geen programma schrijven dat slechts geld van je bankrekening afschrijft als er ook iets opstaat (stufi-dag). Hiervoor hebben we een conditional nodig. In Python kun je gebruik maken van het if-statement. Dit ziet er in een voorbeeld als volgt uit:

 1  balance = 100
 2  expense = 30
 3  
 4  # pay expenses only if balance allows it 
 5  if balance - expense > 0:
 6      balance = balance - expense
 7  
 8  print "Remaining balance:", balance

Een if-statement in Python kent de volgende structuur:

if conditie:
    code

Een voorwaarde (condition) kent uiteindelijk maar twee mogelijke opties. In Python zijn dit True en False (dit noemen we boolean waardes, naar de bedenker George Boole). In de code hierboven is deze boolean het resultaat de expressie balance - expense > 0. Hier wordt gebruik gemaakt van de vergelijkingsoperator >. Deze operator vergelijkt twee waarden, in dit geval de uitkomst van balance - expense en 0, en produceert een boolean. Afhankelijk van de uitkomst, dat kan dus zijn True of False, wordt de code die bij de if-statement hoort uitgevoerd.

De : op regel 5 hierboven laat zien dat bij de if een codeblok hoort. Dat is dus precies het deel van de code dat slechts wordt uitgevoerd als aan de voorwaarde is voldaan. Zo’n blok bestaat vaak uit meerdere regels code, en om duidelijk te maken welke regels dat zijn, gebruik je indentatie. Dat is een aantal spaties of tabs van de kantlijn af. In de code hierboven hebben we vier spaties gebruikt om aan te geven dat regel 6 bij het if-statement hoort. Omdat regel 8 weer meer naar links staat, is die regel niet meer afhankelijk van de uitkomst van de conditie op regel 5. Die regel wordt dus onvoorwaardelijk uitgevoerd.

Uitzonderingen stapelen

Behalve if, kent Python ook de if-else constructie. Deze ziet er als volgt uit:

balance = 100

if balance >= 0:
    print "balance is positive"
else:
    print "balance is negative"

Hiermee hebben we een manier om één stuk code uit te voeren als de conditie True blijkt, en een ander stuk bij False.

Niet elk probleem is binair. Dan is elif een uitkomst. elif is een samenvoegsel van else en if. Je kan elif als volgt gebruiken:

balance = 100

if balance >= 1000:
    print "I'm rich!"
elif balance >= 0:
    print "At least I'm not broke."
else:
    print "Nope"

Meer operatoren

Mocht je meer nodig hebben dan de vergelijkingsoperatoren hierboven:

Combinaties van voorwaarden

Je kunt verschillende voorwaarden combineren. Als je wilt weten of een getal zich in een bepaald bereik bevindt (bijvoorbeeld tussen de 3 en de 39) dan kun je dat doen met and:

x = 15
x_min = 3
x_max = 39	
if x > x_min and x < x_max:
    print "het getal", x, "bevindt zich tussen", x_min, "en", x_max

Hier zijn de drie operators om voorwaarden te combineren:

Loops

Soms is het handig om van een hele reeks getallen te bepalen of ze aan een bepaalde eis voldoen. Omdat zulk “dom werk” precies is wat een computer zo goed kan, is dat een basiselement in bijna alle programmeertalen. We noemen dit een loop.

Herhaling

Als we tien keer iets willen doen, dan ziet het er bijvoorbeeld zo uit:

for x in range(1, 11):
	print "hallo"

We gebruiken hier het commando range() met een begingetal en eindgetal om aan te geven hoe vaak de loop uitgevoerd zal worden. Daarbij telt Python van het begin tot het einde—dus niet tot en met!

Verder zie je dat we net als bij if weer kunnen inspringen om duidelijk te maken welke regel herhaald moet worden. Er staan hier vier spaties vóór print: dat is dus precies de instructie die meerdere malen uitgevoerd gaat worden.

Tellen

In het voorbeeld hierboven wordt een regel code tien keer herhaald. Dat werkt al heel efficiënt (het zijn maar twee regels code), maar vaak willen we tijdens het herhalen ook iets tellen, zodat we bijvoorbeeld weten hoe ver we zijn. Stel dat we bijvoorbeeld de getallen van 1 tot en met 10 op het scherm willen printen en dan aangeven dat we klaar zijn:

for getal in range(1,11):
	print getal
print "Ik ben klaar" 

Deze loop werkt met een variabele genaamd getal om voor elke stap een nieuwe waarde vast te houden. Als de loop begint zal de variabele getal op 1 gesteld worden en daarna worden de handelingen uitgevoerd die in het programma beschreven staan. Als alle handelingen van de loop uitgevoerd zijn gaat het programma terug naar de beginregel bij for, en zet nu de variabele getal op 2. Vervolgens worden wederom alle handelingen uitgevoerd.

Rekenen

Zoals je hierboven zag, kun je in de loop naar de variabele getal verwijzen om iets uit te printen. Je kunt de variabele ook gebruiken als onderdeel van een herhalende berekening. Als je bijvoorbeeld de som van alle getallen tot en met 20 wil uitrekenen en het resultaat vervolgens op het scherm wilt printen werkt dat als volgt:

som = 0
for getal in range(1,21):
	som = som + getal
print "De som van de getallen van 1 tot en met 20 is %d" % (som) 

Voordat we over de getallen loopen zetten we een variabele som op 0. Die gebruiken we om tijdens de loop het totaal bij te houden.

Dan gaan we for-loop in. We tellen bij elke stap de waarde van getal op bij de variabele som. Zoals gebruikelijk in een for-loop, verandert getal bij elke stap. Nadat we zo alle getallen hebben doorlopen, printen we de uiteindelijke waarde van de variabele som. Let op: die print-opdracht staat niet in de loop, anders wordt deze ook twintig keer uitgevoerd! Maar, probeer gerust uit of dit inderdaad zo werkt.

Een loop met een voorwaarde

Je kunt tijdens een loop de getallen ook verschillend behandelen. Als we bijvoorbeeld de som van de even getallen tussen 1 en 20 willen printen kunnen we een if-statement gebruiken.

som = 0
for getal in range(1,21):
    if getal % 2 == 0:
       som = som + getal
print "De som van de even getallen van 1 tot en met 20 is %d" % (som)

We gebruiken in dit stukje code ook de % (modulo-operator) om te bepalen of een getal een veelvoud is van 2. De modulo-operator is werkt als volgt: y % x geeft je de rest van de deling als je het getal y door x hebt gedeeld. De formule 7 % 2 levert dus 1 op; 35 % 8 geeft 3.. Zo’n bouwsteen als de modulo-operator kan je ook prima inzetten om te kijken of een getal een veelvoud is van een ander getal. Als 679875 % 37 precies gelijk is aan 0 betekent dat dat 679875 een veelvoud is van 37.

In het voorbeeld hierboven testen we voor elk van de getallen of het een even getal is (rest 0 als je door 2 deelt). Als dat zo is tellen we het getal op bij de variabele som. Aan het eind van de loop printen we de waarde weer op het scherm. Alle oneven getallen worden dus helemaal genegeerd.

Let op dit detail: we gebruiken == om te kijken of twee getallen aan elkaar gelijk zijn. Het antwoord daarop is ‘waar’ of ‘niet waar’. Een veelvoorkomende fout is dat hier een enkele = gebruikt wordt. Bestudeer dus goed het verschil tussen die twee operatoren.

Variabelen nuttig gebruiken

Dit stukje code rekent heel specifiek de som van de even getallen van 1 tot en met 20 uit.

som = 0
for getal in range(1, 21):
    if getal % 2 == 0:
       print "Yes! %d is een even getal" % getal
       som = som + getal
print "de som van de even getallen van 1 tot en met 20 is %d" % (som)

Stel dat we het programma nu gaan aanpassen om de even getallen van 1 tot en met 88 op te tellen, dan moeten we het programma op twee plekken aanpassen. Kopieer bovenstaande code maar eens en pas deze aan zodat deze tot 88 telt en zinvolle uitvoer geeft. Bij een klein stukje code gaat zo’n aanpassing nog wel, maar bij een groter probleem merk je dat bepaalde informatie vaak in de code voorkomt en zorgvuldig aangepast moet worden. Grote kans op fouten!

Zorg daarom dat je, nadat je het specifieke probleem hebt opgelost, je code zo universeel mogelijk maakt. Het onderstaande stukje code rekent de som uit van de even getallen van 1 tot en met max_getal. Die variabele hoef je dus alleen in het begin van je code een waarde te geven (20, 138613 of in dit geval 88) en verder zie je dat getal nergens terug komen. De informatie wordt via de variabele max_getal doorgegeven naar alle plekken waar deze nodig is.

som = 0
max_getal = 88
for getal in range(1, max_getal+1):
    if getal % 2 == 0:
       print "Yes! %d is een even getal" % getal
       som = som + getal
print "de som van de even getallen van 1 tot en met %d is %d" % (max_getal, som)

Stapgrootte van een loop

Je kunt met range ook de stapgrootte opgeven. for telt dan zoals voorheen van begin tot einde, en neemt niet stappen van 1, maar van de grootte die jij hebt ingesteld. Dit ziet er zo uit:

for getal in range(1, 100, 10):
   ...

Elke stap in de for-loop zal dan steeds 10 verder zijn dan de vorige. Denk even na welke stappen gemaakt zouden worden bij de loop hierboven; of neem de code over en zet er een print in om het gedrag te bestuderen.

Nog een loop

In de vorige hoofdstukken hebben we gewerkt met for-loops. Die zijn heel handig als je weet hoe veel stappen er genomen moeten worden.

Maar wat nou als we niet weten waar het verhaal eindigt? Hieronder zie je een voorbeeld waarbij we de loop af willen breken zodra de som van de getallen tot dan toe groter is dan 50. Probeer onderstaande code te runnen zodat je ziet wat er precies gebeurt.

som = 0
getal = 0
while som <= 50:
    getal = getal + 1
    som = som + getal
    print "%d  som = %d" % (getal, som)
print "Ik stopte omdat de som meer dan 50 is"

De opdracht met while kun je hier lezen als “zolang som kleiner is of gelijk aan 50”. Elke keer dat we weer bovenaan de loop zijn aangekomen, wordt die voorwaarde gecontroleerd, en als daar niet meer aan wordt voldaan, dan stopt de loop.

Een loop afbreken

Zoals gezegd weet je soms bij een while-loop niet wanneer deze precies moet eindigen. In bovenstaande voorbeeld kunnen we in ieder geval zeggen dat we stoppen als som groter dan 50 wordt. Maar er kunnen nog andere situaties optreden waardoor we meteen kunnen stoppen met een loop. In dat geval kun je een break gebruiken: dit commando stopt de binnenste (dichtstbijzijnde) loop per direct. Kijk maar eens naar dit voorbeeld, waarin de wortel van 16 wordt berekend:

getal = 16
for n in range(1, getal):
    if n*n == getal:
        print n
        break

Bestudeer goed hoe dit programma werkt, en probeer het ook uit. Haal de break eens weg. Dan werkt het programma nog steeds. Het voordeel is dat het programma direct stopt als de wortel is gevonden. Dat is dus ietsje efficiënter.