Basis¶
Dit zijn de uitwerkingen van beide delen van de basis: De nacht van het nijlpaard en De uitslag van de schoolrun.
De nacht van het nijlpaard¶
Opdracht: De nacht van het nijlpaard
Stap 1: far_enough(a, b, distance)¶
def far_enough(a, b, distance):
"""Geeft True als plaats b minstens distance verder ligt dan plaats a."""
return b - a >= distance
assert far_enough(1, 3, 2) == True
assert far_enough(2, 3, 2) == False
assert far_enough(3, 3, 1) == False
assert far_enough(5, 10, 5) == True
Stap 2: drop_too_close(place, places, distance)¶
Zodra één plaats ver genoeg ligt, stopt de recursie: de plaatsen daarna liggen nog verder weg.
def drop_too_close(place, places, distance):
"""Geeft places zonder de plaatsen aan het begin die te dicht bij place liggen."""
if places == []: # basisgeval
return []
elif far_enough(place, places[0], distance): # basisgeval: ver genoeg
return places
else: # recursief geval: de eerste plaats ligt te dichtbij
return drop_too_close(place, places[1:], distance)
assert drop_too_close(1, [3, 7], 2) == [3, 7]
assert drop_too_close(3, [3, 5, 8], 4) == [8]
assert drop_too_close(1, [3, 5, 10, 12], 4) == [5, 10, 12]
assert drop_too_close(5, [6, 7], 3) == []
assert drop_too_close(5, [], 2) == []
Stap 3: hippo_dinner(distance, places)¶
def hippo_dinner(distance, places):
"""Geeft hoeveel nijlpaarden er hoogstens mee-eten op de plaatsen in places."""
if places == []: # basisgeval
return 0
first = places[0]
rest = places[1:]
use_it = 1 + hippo_dinner(distance, drop_too_close(first, rest, distance))
lose_it = hippo_dinner(distance, rest)
return max(use_it, lose_it)
assert hippo_dinner(1, [2, 3, 3]) == 2
assert hippo_dinner(2, [1, 3, 7]) == 3
assert hippo_dinner(4, [1, 3, 5, 10, 12]) == 3
assert hippo_dinner(3, [4]) == 1
assert hippo_dinner(3, []) == 0
De uitslag van de schoolrun¶
Opdracht: De uitslag van de schoolrun
De gegeven code uit de opgave:
RESULTS = [
["Noor", 17, 754],
["Sem", 19, 698],
["Lotte", 18, 698],
["Yara", 16, 812],
["Finn", 21, 745],
]
Stap 4: fastest(results)¶
def fastest(results):
"""Geeft de naam van de deelnemer met de kleinste tijd; results is niet leeg."""
return min(results, key=lambda r: r[2])[0]
assert fastest(RESULTS) == "Sem"
assert fastest([["Ali", 20, 600]]) == "Ali"
Stap 5: ranking(results)¶
De sleutel [r[2], r[0]] vergelijkt eerst de tijd en bij een gelijke tijd de
naam.
def ranking(results):
"""Geeft de namen van snel naar langzaam; bij gelijke tijd op alfabet."""
return [r[0] for r in sorted(results, key=lambda r: [r[2], r[0]])]
assert ranking(RESULTS) == ["Lotte", "Sem", "Finn", "Noor", "Yara"]
assert ranking([["Bo", 30, 700], ["Ad", 25, 700]]) == ["Ad", "Bo"]
assert ranking([]) == []
Stap 6: select(results, test)¶
def select(results, test):
"""Geeft de deelnemers uit results waarvoor test True teruggeeft."""
return [r for r in results if test(r)]
assert select(RESULTS, lambda r: r[1] < 18) == [["Noor", 17, 754], ["Yara", 16, 812]]
assert select(RESULTS, lambda r: r[2] < 700) == [["Sem", 19, 698], ["Lotte", 18, 698]]
assert select(RESULTS, lambda r: r[1] > 30) == []
Stap 7: winner(results, test)¶
def winner(results, test):
"""Geeft de naam van de snelste deelnemer waarvoor test True teruggeeft."""
return fastest(select(results, test))
assert winner(RESULTS, lambda r: r[1] < 18) == "Noor"
assert winner(RESULTS, lambda r: r[1] >= 18) == "Sem"
assert winner(RESULTS, lambda r: r[0][0] == "Y") == "Yara"
Stap 8: een jeugdpodium¶
Eén mogelijke uitwerking. Deze aanpak gebruikt de bestaande selectie en ranglijst, en neemt daarna de eerste drie namen. De leeftijdsgrens wordt bij de selectie gecontroleerd.
def youth_podium(results, age_limit):
"""Geeft maximaal drie namen onder age_limit, op tijd en daarna op alfabet."""
return ranking(select(results, lambda participant: participant[1] < age_limit))[:3]
assert youth_podium(RESULTS, 18) == ["Noor", "Yara"]
assert youth_podium(RESULTS, 16) == []
assert youth_podium([], 18) == []
assert youth_podium([["Bo", 17, 700]], 18) == ["Bo"]
assert youth_podium([["Bo", 18, 600], ["Ad", 17, 700]], 18) == ["Ad"]
assert youth_podium(
[["Daan", 17, 700], ["Cato", 16, 700], ["Bo", 17, 600], ["Ad", 15, 500]], 18
) == ["Ad", "Bo", "Cato"]
Opdracht 1: dezelfde regel bij gelijke tijden¶
fastestkiest de snelste naam;rankingordent alle namen;selectfiltert deelnemers;winnerkiest de snelste uit de gefilterde deelnemers.winnergeefttestdoor aanselect, dattestper deelnemer aanroept. Daarna roeptwinnerfastestaan.fastestgeeft een lambda aanmin;rankinggeeft een lambda aansorted. Deze functies roepen de lambda aan om de vergelijkingssleutel te krijgen.Verander in
fastestde sleutel vanr[2]naar[r[2], r[0]]. Dat vergelijkt eerst tijd en dan naam.winnergebruiktfastestnaselecten krijgt de nieuwe regel dus zonder eigen wijziging.rankingheeft die sleutel al;selectblijft dezelfde deelnemers in dezelfde volgorde doorgeven.Bij
RESULTSverandertfastestvan Sem naar Lotte, en de volwassen winnaar ook. De jeugdwinnaar blijft Noor. Bij Bo en Ad verandert zowelfastestals de jeugdwinnaar van Bo naar Ad;rankingblijft Ad, Bo en jeugdselectie blijft Bo, Ad. Zonder gelijke tijden verandert niets. Alleen de bestaande assertionsfastest(RESULTS)en de volwassenwinner(RESULTS, ...)moeten Sem door Lotte vervangen. De overige blijven geldig, ook alle assertions voorrankingenselect.
TIED = [["Bo", 16, 700], ["Ad", 17, 700]]
assert fastest(TIED) == "Bo"
assert winner(TIED, lambda r: r[1] < 18) == "Bo"
def fastest(results):
"""Geeft de snelste naam; bij gelijke tijd op alfabet; results is niet leeg."""
return min(results, key=lambda r: [r[2], r[0]])[0]
assert fastest(TIED) == "Ad"
assert winner(TIED, lambda r: r[1] < 18) == "Ad"
assert ranking(TIED) == ["Ad", "Bo"]
assert select(TIED, lambda r: r[1] < 18) == TIED
assert fastest(RESULTS) == "Lotte"
assert winner(RESULTS, lambda r: r[1] >= 18) == "Lotte"
assert winner(RESULTS, lambda r: r[1] < 18) == "Noor"
assert ranking(RESULTS) == ["Lotte", "Sem", "Finn", "Noor", "Yara"]
assert select(RESULTS, lambda r: r[2] < 700) == [["Sem", 19, 698], ["Lotte", 18, 698]]
assert fastest([["Ali", 20, 600], ["Bo", 16, 700]]) == "Ali"