Oefenopgaven
Contents
3.6. Oefenopgaven#
3.6.1. Functies#
Een nieuwe wortelfunctie
De functie math.sqrt geeft een foutmelding op het moment dat je als input een negatief getal invoert. Mogelijk ben je dit al eens tegengekomen.
We zouden dit graag op willen lossen door een nieuwe wortelfunctie te schrijven die, wanneer de input negatief is, een complex antwoord teruggeeft. Bij een input 9 geeft deze dus, net als de reguliere wortelfunctie, als output 3, maar bij een input -9 krijgen we nu geen foutmelding maar 3j.
Schrijf een functie genaamt my_sqrt met deze functionaliteit.
Hint - Complexe getallen
Als je een getal complex wilt maken moet je het vermenigvuldigen met 1j. Zonder het getal ervoor wordt j niet als de complexe eenheid herkend.
ABC-formule
Probeer het nu zelf eens door een functie te schrijven die de abc-formule uitvoert. Je kunt daarvoor de volgende stappen zetten.
Open een nieuw venster met een leeg script, sla dit op onder een geschikte naam.
Noem je functie
abc_formuleen geef deze drie input-argumenten:a, benc.Bereken in de functie eerst de discriminant
Dals tussenvariabele,Bereken daarna de twee mogelijke oplossingen:
x1enx2.Geef ten slotte deze twee mogelijke oplossingen terug als output.
Vergeet niet de functie aan te roepen met een losse regel code, bijvoorbeeld:
oplossing_1, oplossing_2 = abc_formule(1, -6, 9).Test als laatste je functie voor andere input-waarden. Test ook of de functie een foutmelding geeft als je bijvoorbeeld
a = 0als invoer geeft.
Hint
Vorige week hebben we ook al een opgave met de ABC-formule gemaakt. Je kan die code als inspiratie gebruiken voor het maken van deze opgave. Test de functie met de waarden a = 1, b = -6, c = 9 om voorlopig problemen met een negatieve discriminant te voorkomen.
3.6.2. Aandachtspunten bij het schrijven van functies#
3.6.3. Functies zonder in- of output#
Een functie zonder in- of output
Probeer dit nu zelf eens uit door de twee functies uit Functies zonder in- of output te combineren in één functie zonder input of output die de huidige tijd print.
Hint
Je code kan ongeveer deze structuur hebben:
import time
def print_tijd_string():
''' Print een string met de huidige tijd.
inputs:
outputs:
'''
# De functie eindigt met het printen van de berekende tijd.
print("...")
# En geeft vervolgens niks terug als output.
return
# Roep 20 minuten lang elke minuut de functie aan
for i in range(20):
# Roep de string aan
print_tijd_string()
# Wacht een minuut
time.sleep(60)
Dobbelstenen
Het getal dat je gooit met een dobbelsteen kan je zien als een functie zonder input maar met een output, namelijk het getal dat je werpt. Om dit in code te doen moeten we een willekeurig getal genereren.
Daarvoor kan je de functie random.randint() gebruiken uit de module random. Om deze te kunnen gebruiken moet je deze eerst importeren met
import random
Hint
Dit is een voorbeeld van code die drie keer een ‘standaard-dobbelsteen’ gooit. We schrijven eerst een algemene functie voor het gooien van een dobbelsteen met n zijden, en daarna een functie voor een dobbelsteen met specifiek 6 zijden. Zo kunnen we later makkelijk functies maken voor anders-zijdige dobbelstenen.
import time
import random
def dobbelsteen_met_n_zijden(n):
''' Simuleer het gooien van een dobbelsteen met n zijden.
inputs:
n (int): het aantal stenen van de dobbelsteen
outputs:
worp (int): een willekeurig getal tussen 1 en n.
'''
worp = random.randint(1, n)
return worp
def d6():
''' Simuleer het gooien van een dobbelsteen met 6 zijden.
inputs:
outputs:
worp (int): een willekeurig getal tussen 1 en 6.
'''
worp_met_6_stenen = dobbelsteen_met_n_zijden(6)
return worp_met_6_stenen
# Rol 10 keer met een dobbelsteen met 6 zijden.
for i in range(10):
deze_worp = d6()
print('We gooien', deze_worp)
# Wacht een seconde
time.sleep(1)
Schrijf twee functies: één voor een 20-zijdige dobbelsteen (
d20) en één voor een 6-zijdige dobbelsteen (d6). Je mag zoals hierboven een hulpfunctie schrijven die eenn-zijdige dobbelsteen simuleert.Schrijf vervolgens een derde functie genaamd
fireball, die voor een bordspelletje uitrekent hoeveel schade een aanval aanbrengt bij een tegenstander. Deze functie heeft de volgende functionaliteit:
Hint
Voor dramatisch effect (maar ook tussendoor om te checken de code die je al geschreven hebt goed werkt) kun je bij elke stap die gezet wordt een print-actie uitvoeren (liefst natuurlijk met een dramatische pauze van x seconden ertussen met behulp van time.sleep( x )). Bijvoorbeeld met het volgende resultaat:
Met de 6-zijdige dobbelsteen gooien we 6. De maximale schade wordt 6.
Met de 6-zijdige dobbelsteen gooien we 2. De maximale schade wordt 8.
Met de 6-zijdige dobbelsteen gooien we 1. De maximale schade wordt 9.
Met de 6-zijdige dobbelsteen gooien we 6. De maximale schade wordt 15.
Met de 6-zijdige dobbelsteen gooien we 2. De maximale schade wordt 17.
Met de 6-zijdige dobbelsteen gooien we 5. De maximale schade wordt 22.
Met de 6-zijdige dobbelsteen gooien we 3. De maximale schade wordt 25.
Met de 6-zijdige dobbelsteen gooien we 2. De maximale schade wordt 27.
Met de 20-zijdige dobbelsteen gooien we 17.
De maximale schade wordt door twee gedeeld. Dat is nu: 13.5.
Definieer een variabele met waarde 0 om de maximaal aangerichte schade in bij te houden;
Rol 8 keer met een 6-zijdige dobbelsteen (er moet dus een
for-loop in je functie komen), de som van deze dobbelstenen is de maximale schade;Dan gooien we met een 20-zijdige dobbelsteen om te kijken of de aanval effectief aankomt, of maar slapjes. De waarde van de worp sla je op in een variabele;
Als (
if?) het resultaat van de 20-zijdige dobbelsteen lager dan 15 is, is het resultaat gelijk aan maximale schade;Anders is het resultaat gelijk aan de helft van de maximale schade.
Geef de aangerichte schade terug als output.
Roep de functie
fireballeen paar keer aan.
Denk ook aan de documentatie van de functies die je schrijft. Denk je dat elke medestudent direct zou begrijpen wat je code doet?
3.6.4. Flow#
Zet in de juiste volgorde
Pas de code hieronder aan zodat het liedje in de juiste volgorde komt te staan. Je mag zelf bepalen of je de for-loop laat staan en een if-statement toevoegt, of dat je de functies los aanroept. We raden het je wel aan om de eerste manier te gebruiken.
def een():
print('1')
def twee():
print('2')
def drie():
print('3')
def vier():
print('4')
def hoedje():
print('hoedje van')
def papier():
print('papier')
def tellen():
een()
twee()
drie()
vier()
for i in range(2):
tellen()
hoedje()
papier()
3.6.5. Scope#
Wat gaat hier mis?
In de onderstaande code is er een fout gemaakt met de scope. Hierdoor voert de code niet goed uit. Lees de code goed door en probeer dit op te lossen.
import math
def discriminant(a, b, c):
''' Bereken de discriminant voor de abc-formule '''
return b ** 2 - 4 * a * c
def resultaat(a, b, c, sgn=1):
''' Bereken het resultaat van de abc-formule
sgn bepaalt het teken (+1 of -1) dat voor de wortel van de discriminant komt
'''
D = discriminant(a, b, c)
return -b + sgn * math.sqrt(D) / (2 * a)
def abc(a, b, c):
''' De abc-formule voor een kwadratische vergelijking
Input:
- a
- b
- c
Output:
- resultaat: een lijst met de mogelijke resultaten.
Kan lengte 0, 1 of 2 hebben
'''
if D > 0:
res1 = resultaat(a, b, c, 1)
res2 = resultaat(a, b, c, -1)
resultaat = [res1, res2]
elif D == 0:
res = resultaat(a, b, c)
resultaat = [res]
else:
resultaat = []
return resultaat
print(abc(5, -2, -3))