Inleiding Programmeren 2 Gertjan van Noord November 28, 2016
Stof week 3 nogmaals Zelle hoofdstuk 8 en recursie Brookshear hoofdstuk 5: Algoritmes Datastructuren: tuples
Een geheel andere manier om te loopen : recursie Een functie is recursief, indien de functie gedefinieerd is in termen van zichzelf def lengte ( instring ) : if ( instring ==""): return 0 else : return 1 + lengte ( instring [1:]) Merk op: elke aanroep van lengte heeft als parameter een kortere string De stop-conditie hier: als de string leeg is, ben je klaar.
recursie Aanroep: x = lengte (" piet ") Eerste frame: lengte (" piet "): return 1 + lengte (" iet ")
recursie Aanroep: x = lengte (" piet ") lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + lengte ("et")
recursie x = lengte (" piet ") lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + lengte ("et") lengte ("et"): return 1 + lengte ("t")
recursie x = lengte (" piet ") lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + lengte ("et") lengte ("et"): return 1 + lengte ("t") lengte ("t"): return 1 + lengte ("")
recursie lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + lengte ("et") lengte ("et"): return 1 + lengte ("t") lengte ("t"): return 1 + lengte ("") lengte (""): return 0
recursie lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + lengte ("et") lengte ("et"): return 1 + lengte ("t") lengte ("t"): return 1 + 0 0 lengte (""): return 0
recursie lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + lengte ("et") lengte ("et"): return 1 + 1 1 lengte ("t"): return 1 + 0 0 lengte (""): return 0
recursie lengte (" piet "): return 1 + lengte (" iet ") lengte (" iet "): return 1 + 2 2 lengte ("et"): return 1 + 1 1 lengte ("t"): return 1 + 0 0 lengte (""): return 0
recursie lengte (" piet "): return 1 + 3 3 lengte (" iet "): return 1 + 2 2 lengte ("et"): return 1 + 1 1 lengte ("t"): return 1 + 0 0 lengte (""): return 0
lengte (" piet "): return 4 recursie
Huiswerkopdracht Syracuse Je begint met positief getal x x/2 als x even 3x + 1 als x oneven voor een gegeven getal, geef de Syracuse sequentie (eindigt altijd op 1) je moet dus een lijst getallen teruggeven
Voorbeeld %./ syracuse.py 17 [17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
Huiswerkopdracht Syracuse Check of getal x even is: de rest operator >>> 43 % 8 3 >>> 32 % 7 4 >>> 100 % 10 0 if x % 2 == 0 :
Huiswerkopdracht Syracuse Nog een operator: delen met integers, de // operator >>> 4 / 2 2.0 >>> 4 // 2 2 >>> 100 // 3 33 n = x //2
Algoritme Aan welke eisen moet een goed algoritme voldoen?
Algoritme correctheid efficientie
Algoritme correctheid efficientie eenvoud, begrijpelijkheid, makkelijk aan te passen,...
Efficientie wordt niet uitgedrukt in milliseconds want is afhankelijk van de grootte van de input, n waarbij we meestal uitgaan van het slechtste geval
Efficientie in termen van n check of een bepaalde waarde voorkomt in een lijst (lengte n) def member (el, lijst ): for i in lijst : if i == el: return True return False Wat is de efficientie van dit algoritme?
Efficientie in termen van n check of een bepaalde waarde voorkomt in een lijst (lengte n) def member (el, lijst ): for i in lijst : if i == el: return True return False In het slechtste geval moeten we de hele lijst door, dus we doorlopen de loop n maal De efficientie is lineair: als de lijst twee keer zo lang is, zal het algoritme twee keer zo veel tijd nodig hebben. Kan het beter?
Efficientie in termen van n Kan het beter? Hoe ga je te werk bij het zoeken van een woord in een woordenboek? Dat kan omdat de woorden in woordenboek geordend is Dit algoritme heet binary search Hoeveel stappen kost dat algoritme?
Binary search def binarysearch ( alist, item ): first = 0 last = len ( alist ) -1 while first <= last : midpoint = ( first + last )//2 print ( alist [ midpoint ]) # only for demo! if alist [ midpoint ] == item : return True else : if item < alist [ midpoint ]: last = midpoint -1 else : first = midpoint +1 return False
Binary search >>> from binsearch import * >>> alist = list ( range (100)) >>> alist [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, >>> binarysearch ( alist,23) 49 24 11 17 20 22 23 True
Efficientie in termen van n Kan het beter? Hoe ga je te werk bij het zoeken van een woord in een woordenboek? Dat kan omdat de woorden in woordenboek geordend zijn Hoeveel stappen kost dat algoritme? 100 50 25 13 7 4 2 1 128 64 32 16 8 4 2 1
Efficientie in termen van n Kan het beter? Hoe ga je te werk bij het zoeken van een woord in een woordenboek? Dat kan omdat de woorden in woordenboek geordend zijn Hoeveel stappen kost dat algoritme? log(n); als de input groter wordt, kost het algoritme nauwelijks meer tijd
Les Als de lijst geordend is, kun je sneller algoritme gebruiken Algemeen patroon: efficientie van algoritme wordt mede bepaald door de gekozen representatie: data-structuren! zoeken naar een gegeven element: n in een gegeven lijst log(n) in een gesorteerde lijst onafhankelijk van n, in een hash (Python: dictionary en set)...
Efficientieklassen onafhankelijk van n; constant log(n) (zoeken in een woordenboek) n lineair n log(n) n n kwadratisch n 3, n 4... polynomiaal 2 n exponentieel...
Voorbeeld Gegeven: een lijst strings Gevraagd: bevat deze lijst een string waarvoor geldt dat de omgekeerde string ook in de lijst voor komt? [ jan, piet, kees ] : nee [ jan, nora, aron, karel ]: ja [ anna, beatrix ]: ja
Voorbeeld Gegeven: een lijst strings Gevraagd: bevat deze lijst een string waarvoor geldt dat de omgekeerde string ook in de lijst voor komt? [ jan, piet, kees ] : nee [ jan, nora, aron, karel ]: ja [ anna, beatrix ]:ja def contains_reverse ( lijst ): for i in lijst : ir = i [:: -1] # ir = reverse (i) for j in lijst : if j == ir: return True return False
Voorbeeld Gegeven: een lijst strings Gevraagd: bevat deze lijst een string waarvoor geldt dat de omgekeerde string ook in de lijst voor komt? def contains_reverse ( lijst ): for i in lijst : ir = i [:: -1] # ir = reverse (i) for j in lijst : if j == ir: return True return False Welke efficientieklasse?
Experiment member: n seconds 10 0.00001 100 0.00003 1000 0.00022 10000 0.00256 100000 0.02200 1000000 0.24419 contains-reverse: n seconds 10 0.00004 100 0.00262 1000 0.24911 10000 24.86578
Data-structuren zijn dus belangrijk voor efficiente algoritmen
Data-structuren: tuples tuples lijken op lijsten, maar zijn immutable we gebruiken ronde haken, geen rechte haken tup1 = () tup2 = (1, 3, 5) tup3 = 1, 3, 5 tup4 = (1,) geentuple = (1) Dus let op, als je een tuple met slechts 1 element definieert, is de komma verplicht (maar zulke tuples zijn ook nergens (?) goed voor)
Data-structuren: tuples Net als bij lijsten: indexing tup[1] iteratie for i in tup: slicing tup[1:] concatenatie tup1 + tup2 repetitie tup1 * 3
Data-structuren: tuples Operaties als lijsten Heel geschikt om paren, triples, etc te representeren paren: bijvoorbeeld coordinaten
Data-structuren: sets Set zoals bij wiskunde: elk element maar 1x Heel efficient is: het bouwen op basis van bijvoorbeeld lijst het zoeken naar een gegeven element het toevoegen/weghalen van een element
Data-structuren: sets Set zoals bij wiskunde: elk element maar 1x Heel efficient is: het bouwen op basis van bijvoorbeeld lijst het zoeken naar een gegeven element het toevoegen/weghalen van een element Meestal beter dan een gesorteerde lijst
Data-structuren: sets Set zoals bij wiskunde: elk element maar 1x Heel efficient is: het bouwen op basis van bijvoorbeeld lijst het zoeken naar een gegeven element het toevoegen/weghalen van een element Meestal beter dan een gesorteerde lijst Beperking: de elementen mogen niet mutable zijn
Data-structuren: sets Set zoals bij wiskunde: elk element maar 1x Efficient in gebruik Meestal beter dan een gesorteerde lijst Beperking: de elementen mogen niet mutable zijn: sets van strings sets van getallen maar niet: sets van lijsten, of sets van sets wel: sets van tuples, bijvoorbeeld een set van coordinaten
Valkuil: Lege Set >>> verz = set () Dit is niet hetzelfde, helaas, als: >>> verz = {}
>>> pair1 = (2,3) >>> pair2 = (2,4) >>> pair3 = (3,5) >>> set ([ pair1, pair2, pair3 ]) {(2, 3), (2, 4), (3, 5)} Sets
verz = {(2, 3), (2, 4), (3, 5)} >>> for p in verz :... print (p [1])... 3 4 5 Iteratie
Check / Verwijder / Voeg-toe verz = {(2, 3), (2, 4), (3, 5)} >>> if (3,5) in verz :... print (" yes ")... yes >>> verz. add ((3,6)) >>> verz {(2, 3), (2, 4), (3, 6), (3, 5)} >>> verz. remove ((2,3)) >>> verz {(2, 4), (3, 6), (3, 5)}
Archery of Longest word?