inhoud week 1week 2week 3week 4week 5week 6week 7

261
Inhoud Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7

Upload: martina-lemmens

Post on 13-May-2015

225 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

InhoudWeek 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7

Page 2: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Algoritmen en DatastructurenALGODS Week 1

Page 3: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

3

Inhoud ALGODSOnderwerpen:

Algoritmen en Datastructurenstandaard C++ library (vroeger: STL)

Diverse toepassingen van algoritmen en datastructurenKortste pad en spelletjes

Werkvormen:Theorie (2 uur/week theorie) in week 1 t/m 7Practicum (1 uur/week begeleid en 1 uur/week onbegeleid)Zelfstudie en toetsing (4 uur/week) in week 1 t/m 8Reparatie in week 9 of 10

Page 4: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

4

Leermiddelen Boeken

Thinking in C++ 2nd Edition, Volume 1 + 2, Bruce Eckel Praktisch UML, 5de editie, Warmer en Kleppe

Dictaat (zelf dubbelzijdig afdrukken!) Aanvullingen op theorie Extra voorbeelden

Handouts (in laatste weken) Blackboard en http://bd.eduweb.hhs.nl/algods/

Studiewijzer met uitgebreide planning Dictaat Practicumopdrachten + uitgebreide practicumhandleiding Sourcecode van alle voorbeelden Sheets Links

Page 5: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

5

Voorbeeld Statische datastructuur:

struct deelnemer { int punten; char naam[80];};struct stand { int aantalDeelnemers; deelnemer lijst[100];};stand s;

De nadelen van het gebruik van de ingebouwde datastructuren struct en array zijn: de grootte van de array's lijst en naam moet bij het vertalen van het

programma bekend zijn en kan niet aangepast worden (=statisch). elke deelnemer neemt evenveel ruimte in onafhankelijk van de lengte van

zijn naam (=statisch). het verwijderen van een deelnemer uit de stand

is een heel bewerkelijke operatie.

Do you remember MICPRG?

Page 6: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

6

Voorbeeld Dynamische datastructuur:

class Deelnemer {public: Deelnemer(const string& n, int p); int punten() const; const string& naam() const; void verhoogpunten(int p);private: int pnt; string nm;};class Stand {public: void voegtoe(const Deelnemer& d); void verwijder(const string& n); int punten(const string& n) const; void verhoogpunten(const string& n, int p); vector<deelnemer>::size_type aantalDeelnemers() const;private: vector<Deelnemer> lijst;};Stand s;

Do you remember OGOPRG?

Welke andere dynamische datastructuren zijn er?

Hoe werken dynamische datastructuren eigenlijk?

Page 7: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

7

Recursieve datastructurenLijst

leeg ofelement met pointer naar lijst

Stamboomleeg ofpersoon met pointer naar stamboom (van vader) en pointer

naar stamboom (van moeder)

Page 8: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

8

Algorithms+

Datastructures=

Programs

‘76 boek van Niklaus Wirth:

Page 9: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

9

Klassieke datastructurenKlassieke datastructuren kunnen m.b.v. OOP technieken

als herbruikbare componenten worden geïmplementeerd.

Er zijn diverse component- bibliotheken verkrijgbaar:STL (Standard Template Library) Opgenomen in ISO/ANSI C+

+98 std (sept 1998) Aanwezig in Microsoft Visual C++ 2010 en GCC.

Boost (http://www.boost.org/) Zeer uitgebreid. Een aantal boost onderdelen zijn opgenomen in ISO/ANSI C++11 std (aug 2011). Aanwezig in GCC en Microsoft Visual C++ 2012 (niet in Microsoft Visual C++ 2010).

Page 10: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

10

DatastructurenDing om data “gestructureerd” in op te slaan.Een template is erg geschikt voor het implementeren

van een datastructuur.Basisbewerkingen:

insert, remove, findempty, full, size

Een bepaalde datastructuur kan op verschillende manieren geïmplementeerd worden.

Een Abstracte Base Class per datastructuur maakt gebruik onafhankelijk van de implementatie.

Page 11: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

11

DatastructuresStackQueueVectorSorted vectorLinked ListSorted listBinary TreeSearch treeHash TablePriority Queue (Binary Heap)

Page 12: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

12

Big O notationDe big O notatie wordt gebruikt om de executietijd en

het geheugengebruik van algorithmen met elkaar te vergelijken.

De O staat voor “order of magnitude”.f(n)=O(n2) betekent dat functie f(n) “van boven”

asymptotisch begrensd wordt door g(n)=n2.Dit betekent dat f(n) a·n2 voor grote waarden van n. Waarbij

a 0 (je mag a zelf kiezen).

Page 13: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

13

Big O notation voorbeeldWat is de big O notatie voor:

f(n) = 2n3 + 4n + 2 log2 n + 100.f(n) = 4 log2 n.f(n) = log10 n.

Bedenk: log10 n = log2 n / log2 10.f(n) = 1000.f(x) = (10x4 + 4x2) / (5x3 + 12x2 + 7x).

= O(n3)= O(log n)= O(log n)

= O(1)= O(x)

Page 14: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

14

Big O notation voorbeeldWat is de executietijd van het volgende algoritme in big

O notatie:

int max(const vector<int>& v) { vector<int>::size_type n = v.size(); assert(n > 0); int max = v[0]; for (vector<int>::size_type i = 1; i < n; ++i) { if (v[i] > max) { max = v[i]; } } return max;}

T(n) = O(n)

Kan het beter ?

… als de array al gesorteerd is ?… als je v.size() processoren hebt ?

Page 15: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

15

Big O notation voorbeeld C++11int max(const vector<int>& v) { assert(v.size() > 0); auto max = v[0]; for (auto elm: v) { if (elm > max) { max = elm; } } return max;} Range-based for

Niet beschikbaar in VC++ 2010Wel beschikbaar in VC++ 2012

Wel beschikbaar in GCC 4.6 (of hoger)met optie –std=c++0x of –std=c++11

auto-typed variables Wel beschikbaar in VC++ 2010

Wel beschikbaar in GCC 4.4 (of hoger)

Page 16: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

16

Big O notation voorbeeld C++11int max(const vector<int>& v) { assert(v.size() > 0); auto max = v[0]; for (decltype(v.size()) i = 1; i < v.size(); ++i) { if (v[i] > max) { max = v[i]; } } return max;} auto-typed variables en

declared type of an expressionWel beschikbaar in VC++ 2010

Wel beschikbaar in GCC 4.4 (of hoger)

Page 17: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

17

Big O notation voorbeeldWat is de executietijd van het volgende algoritme in big

O notatie:int maxprod(const vector<int>& v) { auto n = v.size(); assert(n > 0); auto maxp = v[0] * v[0]; for (decltype(n) i = 0; i < n; ++i) { for (decltype(n) j = i; j < n; ++j) { if (v[i] * v[j] > maxp) { maxp = v[i] * v[j]; } } } return maxp;}

T(n) = O(n2)

Kan het beter ?

Page 18: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

18

Big O notation voorbeeldWat is de executietijd van het volgende algoritme in big

O notatie:int maxprod(const vector<int>& v) { auto n = v.size(); assert(n > 0); auto max = v[0]; for (decltype(n) i = 0; i < n; ++i) { if (v[i] > max) { max = v[i]; } } return max * max;}

T(n) = O(n)

Maximum van alle mogelijke producten is

max * max

Page 19: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

19

Big O notation

Je ziet dat een O(n2) algoritme niet bruikbaar is voor hele grote hoeveelheden data en dat een O(10n)

algoritme sowieso niet bruikbaar is.

Page 20: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

20

Bekende datastructuren

Page 21: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

21

Bekende datastructuren (1)

Heeft alleen maar nadelen!

Page 22: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

22

Bekende datastructuren (2)

Page 23: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Algoritmen en DatastructurenALGODS Week 2

Page 24: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

24

StackLIFO (Last In First Out) buffer

slechts op 1 plaats toegankelijkMemberfuncties:

void push(const T& t)void pop()const T& top() const

Voorbeeld van gebruik:expressie evaluator

insert O(1)remove O(1)

find O(1)

Page 25: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

25

ADT Stack#ifndef _TISD_Bd_Stack_#define _TISD_Bd_Stack_

template <typename T> class Stack {public: Stack() {} virtual ~Stack() {} virtual void push(const T& t) = 0; virtual void pop() = 0; virtual const T& top() const = 0; virtual bool empty() const = 0; virtual bool full() const = 0;private: // Voorkom toekennen en kopiëren void operator=(const Stack&); Stack(const Stack&);};

#endif

Page 26: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

26

ADT Stack C++11#ifndef _TISD_Bd_Stack_#define _TISD_Bd_Stack_

template <typename T> class Stack {public: Stack() = default; virtual ~Stack() = default; virtual void push(const T& t) = 0; virtual void pop() = 0; virtual const T& top() const = 0; virtual bool empty() const = 0; virtual bool full() const = 0;// Voorkom toekennen en kopiëren void operator=(const Stack&) = delete; Stack(const Stack&) = delete;};

#endif

Page 27: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

27

Toepassingen van stacksBalanced symbol checkerA simple calculator

Een eenvoudige calculator is een goed te (her)gebruiken component. Denk aan

numerieke invoervelden.

Page 28: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

28

Balance (1 van 2)// Contoleer op gebalanceerde haakjes. // Invoer afsluiten met een punt.#include <iostream>#include "stacklist.h" // zie dictaatusing namespace std;

int main() { StackWithList<char> s; char c; cin.get(c); while (c != '.') { if (c == '(' || c == '{' || c == '[') { s.push(c); } else { if (c == ')' || c == '}' || c == ']') { if (s.empty()) { cout << "Fout" << endl; } else {

Page 29: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

29

Balance (2 van 2) char d = s.top(); s.pop(); if (d == '(' && c != ')' || d == '{' && c != '}'

|| d == '[' && c != ']') { cout << "Fout" << endl; } } } } cin.get(c); } if (!s.empty()) { cout << "Fout" << endl; } return 0;}

Page 30: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

30

Postfix Wij zijn gewend infix notatie te gebruiken voor het noteren van

expressies. Er bestaat nog een andere methode: reverse polish notation (RPN) of postfix genoemd. Prefix: operator operand operand Infix: operand operator operand Postfix: operand operand operator

Voordelen postfix t.o.v. infix: Geen prioriteitsregel nodig

Meneer Van Dale Wacht Op Antwoord. (Oud) Hoe Moeten Wij Van De Onvoldoendes Afkomen? (Modern)

Geen haakjes nodig Eenvoudiger te bereken m.b.v. Stack

We zullen eerst een postfix calculator maken en daarna een infix naar postfix convertor.

Page 31: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

31

Postfix calculator (1 van 2)// Evalueer postfix expressie. Invoer afsluiten met =.

#include <iostream>#include <cctype>#include "stacklist.h" // zie dictaatusing namespace std;

int main() { StackWithList<int> s; char c; int i; cin >> c; while (c != '=') { if (isdigit(c)) { cin.putback(c); cin >> i; s.push(i); }

Page 32: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

32

Postfix calculator (1 van 2) else if (c == '+') { int op2 = s.top(); s.pop(); int op1 = s.top(); s.pop(); s.push(op1 + op2); } else if (c == '*') { int op2 = s.top(); s.pop(); int op1 = s.top(); s.pop(); s.push(op1 * op2); } else cout << "Fout" << endl; cin >> c; } cout << "=" << s.top() << endl; s.pop(); if (!s.empty()) cout << "Fout" << endl; cin.get(); cin.get(); return 0;}

Page 33: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

33

Infix Postfix Gebruik een stack met karakters. Lees karakter voor karakter in. Als een ingelezen karakter geen haakje of operator is dan kan dit meteen

worden doorgestuurd naar de uitvoer. Een haakje openen wordt altijd op de stack geplaatst. Als we een operator inlezen dan moeten we net zo lang operatoren van de

stack halen en doorsturen naar de uitvoer totdat we: een operator op de stack tegenkomen met een lagere prioriteit of een haakje openen tegenkomen of totdat de stack leeg is.

Daarna moet de ingelezen operator op de stack worden geplaatst. Als we een haakje sluiten inlezen dan moeten we net zo lang operatoren van

de stack halen en doorsturen naar de uitvoer totdat we een haakje openen op de stack tegenkomen. Dit haakje openen moet wel van de stack verwijderd worden maar wordt niet doorgestuurd naar de uitvoer.

Als we einde van de invoer bereiken moeten we alle operatoren van de stack halen en doorsturen naar de uitvoer.

Page 34: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

34

Stack implementationsEen stack kan op verschillende manieren

geïmplementeerd worden:d.m.v. een array (of vector).d.m.v. een gelinkte lijst.

Page 35: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

35

Stack met array (1 van 4)#ifndef _TISD_Bd_StackWithArray_#define _TISD_Bd_StackWithArray_#include "stack.h" // zie dictaat

template <typename T> class StackWithArray: public Stack<T> {public: explicit StackWithArray(size_t size); virtual ~StackWithArray(); virtual void push(const T& t); virtual void pop(); virtual const T& top() const; virtual bool empty() const; virtual bool full() const;private: T* a; // pointer naar de array size_t s; // size van a (max aantal elementen op de stack) size_t i; // index in a van de eerste lege plaats};

Page 36: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

36

Stack met array (1 van 4) C++11#ifndef _TISD_Bd_StackWithArray_#define _TISD_Bd_StackWithArray_#include "stack.h" // zie dictaat

template <typename T> class StackWithArray: public Stack<T> {public: explicit StackWithArray(size_t size); virtual ~StackWithArray() override; virtual void push(const T& t) override; virtual void pop() override; virtual const T& top() const override; virtual bool empty() const override; virtual bool full() const override;private: T* a; // pointer naar de array size_t s; // size van a (max aantal elementen op de stack) size_t i; // index in a van de eerste lege plaats};

Explicit override voorkomt overload

(per ongeluk door bijvoorbeeld spelfout)

Page 37: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

37

Stack met array (2 van 4)template <typename T> StackWithArray<T>::StackWithArray(size_t size): a(0), s(size), i(0) { if (s <= 0) { std::cerr << "Stack size should be >0" << std::endl; s = 0; } else { a = new T[s]; }}

template <typename T>StackWithArray<T>::~StackWithArray() { delete[] a;}

Page 38: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

38

Stack met array (3 van 4)template <typename T> void StackWithArray<T>::push(const T& t) { if (full()) std::cerr << "Can't push on an full stack" << std::endl; else a[i++] = t;}

template <typename T> void StackWithArray<T>::pop() { if (empty()) std::cerr << "Can't pop an empty stack" << std::endl; else --i;}

template <typename T> const T& StackWithArray<T>::top() const { if (empty()) { std::cerr << "Can't top an empty stack" << std::endl; std::exit(-1); // no valid return } return a[i - 1];}

Page 39: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

39

Stack met array (4 van 4)template <typename T> bool StackWithArray<T>::empty() const { return i == 0;}

template <typename T> bool StackWithArray<T>::full() const { return i == s;}

#endif

Page 40: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

40

Stacktest#include <iostream>#include "stackarray.h"using namespace std;

int main() { StackWithArray<char> s(32); char c; cout <<"Type een tekst, sluit af met ." << endl; cin.get(c); while (c != '.') { s.push(c); cin.get(c); } while (!s.empty()) { cout << s.top(); s.pop(); } cin.get(); cin.get(); return 0;}

Page 41: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

41

Stack met lijst (1 van 3)#include "stack.h"

template <typename T> class StackWithList: public Stack<T> {public: StackWithList(); virtual ~StackWithList(); virtual void push(const T& t); virtual void pop(); virtual const T& top() const; virtual bool empty() const; virtual bool full() const;private: class Node { public: Node(const T& t, Node* n); T data; Node* next; }; Node* p; // pointer naar de top van de stack};

Page 42: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

42

Stack met lijst (2 van 3)template <typename T> StackWithList<T>::StackWithList(): p(0) {}

template <typename T> StackWithList<T>::~StackWithList() { while (!empty()) pop();}

template <typename T> bool StackWithList<T>::empty() const { return p == 0;}

template <typename T> bool StackWithList<T>::full() const { return false;}

template <typename T> StackWithList<T>::Node::Node(const T& t,Node* n):

data(t), next(n) {}

Page 43: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

43

Stack met lijst (3 van 3)template <typename T> void StackWithList<T>::push(const T& t) { p = new Node(t, p);}

template <typename T> void StackWithList<T>::pop() { if (empty()) std::cerr << "Can't pop an empty stack" << endl; else { Node* old = p; p = p->next; delete old; }}

template <typename T> const T& StackWithList<T>::top() const { if (empty()) { std::cerr << "Can't top an empty stack" << std::endl; std::exit(-1); // no valid return } return p->data;}

Page 44: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

44

Array versus gelinkte lijstArray is sneller.Array is statisch.

Niet gebruikte gedeelte is overhead.Lijst is dynamisch.

Heeft overhead van 1 pointer per element

Page 45: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

45

Dynamisch stack kiezen Stack<char>* s = 0; cout << "Welke stack? (l = list, a = array): "; char c; do { cin.get(c); if (c == 'l' || c == 'L') { s = new StackWithList<char>; } else if (c == 'a' || c == 'A') { cout << "Hoeveel elementen?: "; int i; cin >> i; s = new StackWithArray<char>(i); } } while (s == 0);

cout << "Type een tekst, sluit af met ." << endl; cin.get(c); while (c != '.') { s->push(c); cin.get(c); } // ... delete s;

Page 46: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Zelfstudie! (Zie studiewijzer)Advanced C++ (namespace, exception, RTTI).Dictaat OGOPRG hoofdstuk 6.2, 6.8 en 6.9.Zie eventueel voor extra informatie: TICPPV1 H10 en

TICPPV2 H1 en H8.

46

Page 47: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Algoritmen en DatastructurenALGODS Week 3

Page 48: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

48

Standaard C++ LibraryStandaard algoritmen en datastructuren in C++

(voorheen STL = Standard Template Library).Zie http://en.cppreference.com/w/cpp.Zie dictaat hoofdstuk 6.Zie eventueel TICPPV2 hoofdstuk 4 en 5.

Page 49: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

49

STLContainers (datastructuren)Iterators (om door een container te wandelen)Algoritmen (generiek)

Het gebruik van iterators maakt generiek programmeren (generic programming) mogelijk. Een generiek algoritme kan op verschillende datatypes (containers) toegepast worden.

Generic programming is dus niet OOP. Met behulp van iterators kun je een algoritme op de objecten in een container

uitvoeren. De algoritmen zijn zo efficient mogelijk (geen inheritance en virtuele functies

gebruikt). Je kunt eigen algoritmen, containers en iteratoren toevoegen.

Page 50: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

50

STL componentenC = containerA = algoritme

i = iterator

Een algoritme kan ook uit één container lezen en in dezelfde

container schrijven

Page 51: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

51

Iterator voorbeeldMet behulp van een iterator kun je door een string

lopen op dezelfde manier als dat je met een pointer door een char[] kunt lopen.

char naam[] = "Henk";for (const char* p = naam; *p != '\0'; ++p) { cout << *p << " ";}cout << endl;

string naam = "Harry";for (string::const_iterator i = naam.begin();

i != naam.end(); ++i) { cout << *i << " ";}cout << endl;

Page 52: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

52

Iterator voorbeeld C++11Met behulp van een iterator kun je door een string

lopen op dezelfde manier als dat je met een pointer door een char[] kunt lopen.

char naam[] = "Henk";for (const auto* p = naam; *p != '\0'; ++p) { cout << *p << " ";}cout << endl;

string naam = "Harry";for (auto i = naam.cbegin(); i != naam.cend(); ++i) { cout << *i << " ";}cout << endl;

cbegin() geeft een const_iterator terug

Page 53: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

53

ContainersSequentiële containers (linear)

[] string array (sinds C++11) vector forward_list (single linked list, sinds C++11) list (double linked list) deque (double ended queue, eigenlijk een devector) bitset (slaan wij over) adapters (in combinatie met vector, list of deque)

stackqueuepriority_queue

Page 54: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

54

Containers (vervolg)Associatieve containers (elementen op volgorde van

sleutelwaarde opgeslagen)set

Verzameling van sleutels (keys). Sleutel moet orgineel zijn.

multisetVerzameling van sleutels (keys). Sleutel kan meerdere malen voorkomen.

mapVerzameling van paren (sleutel, waarde) (key, value).Sleutel moet orgineel zijn.

multimapVerzameling van paren (sleutel, waarde) (key, value).Sleutel kan meerdere malen voorkomen.

Geïmplementeerd met een binairy search tree

Page 55: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

55

Containers (vervolg) C++11Associatieve containers (elementen in willekeurige

volgorde opgeslagen)unordered_set

Verzameling van sleutels (keys). Sleutel moet orgineel zijn.

unordered_multisetVerzameling van sleutels (keys). Sleutel kan meerdere malen voorkomen.

unordered_mapVerzameling van paren (sleutel, waarde) (key, value).Sleutel moet orgineel zijn.

unordered_multimapVerzameling van paren (sleutel, waarde) (key, value).Sleutel kan meerdere malen voorkomen.

Geïmplementeerd met een hash table

Page 56: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

56

ContainersDe containers regelen hun eigen geheugenbeheer.

De containers maken kopietjes van de elementen die erin gestopt worden. Als je dat niet wilt dan moet je een container met pointers gebruiken.

Alle objecten in een container zijn van hetzelfde type. (Dat kan wel een polymorf pointertype zijn!)

Page 57: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

57

Sequentiële containers

array

vector

deque

forward_list

list

Page 58: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

58

Sequentiële containersvector

random access op indexoperator[], at(…) gooit exception out_of_range

toevoegen of verwijderenpush_back(…) pop_back() O(1)insert(…) erase(…) O(n)

dequerandom access op index

operator[], at(…) gooit exception out_of_rangetoevoegen of verwijderen

push_front(…) pop_front() O(1)push_back(…) pop_back() O(1)insert(…) erase(…) O(n)

Page 59: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

59

Sequentiële containersforward_list

geen random access op indextoevoegen of verwijderen

push_front(…) pop_front() O(1)insert_after(…) erase_after(…) O(1)

listgeen random access op indextoevoegen of verwijderen

push_front(…) pop_front() O(1)push_back(…) pop_back() O(1)insert(…) erase(…) O(1)

Page 60: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

60

vector voorbeeld#include <iostream>#include <vector>using namespace std;

int main() { vector<int> v; void print(const vector<int>& vec); // zelf gedefinieerd int i; cin >> i; while (i != 0) { v.push_back(i); cin >> i; } print(v); if (v.size() >= 4) { for (vector<int>::iterator iter = v.begin() + 2;

iter != v.begin() + 4; ++iter) { *iter *= 2; } } print(v); // ...

Je kunt hier in C++11 ook auto gebruiken!

Page 61: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

61

vector voorbeeld// print met behulp van een index:void print(const vector<int>& vec) { cout << "De inhoud van de vector is:" << endl; for (vector<int>::size_type index = 0; index != vec.size();

++index) { cout << vec[index] << " "; } cout << endl;}

// print met behulp van een iterator:void print(const vector<int>& vec) { cout << "De inhoud van de vector is:" << endl; for (auto iter = vec.cbegin(); iter != vec.cend(); ++iter) { cout << *iter << " "; } cout << endl;}

Is het niet beter om hier vec.at(index) te

gebruiken?

Welke versie is beter?

Page 62: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

62

Generiek voorbeeld// print met behulp van een index:template<typename C> void print(const C& c) { cout << "De inhoud van de container is:" << endl; for (decltype(c.size()) i = 0; i != c.size(); ++i) { cout << c[i] << " "; } cout << endl;}

// print met behulp van een iterator:template<typename C> void print(const C& c) { cout << "De inhoud van de container is:" << endl; for (auto iter = c.cbegin(); iter != c.cend(); ++iter) { cout << *iter << " "; } cout << endl;}

Welke versie is beter?

Kan dat niet eenvoudiger?

Page 63: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

63

Generiek voorbeeld// print met behulp van range based for:template<typename C> void print(const C& c) { cout << "De inhoud van de container is:" << endl; for (const auto& elm: c) { cout << elm << " "; } cout << endl;}

Welke versie is beter?

Hoe kun je een deel van een container printen?

Page 64: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

64

Generiek voorbeeld// print met behulp van twee iteratoren:template <typename Iter> void print(Iter begin, Iter end) { cout << "De inhoud van de container is:" << endl; for (Iter iter = begin; iter != end; ++iter) { cout << *iter << " "; } cout << endl;}

int main() { vector<int> v; list<double> l; for (int i = 1; i <= 10; ++i) { v.push_back(i); l.push_back(1.0 / i); } print(v.cbegin(), v.cend()); // print 1 t/m 10 print(v.cbegin() + 1, v.cend() - 1); // print 2 t/m 9 print(l.cbegin(), l.cend());

Welke versie is beter?

Page 65: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

65

list voorbeeld#include <iostream>#include <list>using namespace std;

class Hond {public: virtual void blaf() const = 0; // ...};

class Tekkel: public Hond { // ...};

class SintBernard: public Hond { // ...};

int main() { list<Hond*> kennel = { new Tekkel, new SintBernard, new Tekkel }; for (const auto hp: kennel) { hp->blaf(); } cin.get(); return 0;}

Page 66: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

66

AdaptersContainer adapters passen de interface van een vector,

deque of list aan.stackqueuepriority_queue

stack<int, vector<int>> s1; // stack implemented with vector stack<int, deque<int>> s2; // stack implemented with deque stack<int, list<int>> s3; // stack implemented with list stack<int> s4; // using deque by defaultJe kunt nu alleen tijdens compile time kiezen

welke stack je wilt en niet tijdens run-time. Zie Week 2.

Page 67: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

67

Adaptersstack

Kan niet met forward_list (stack gebruikt push_back en pop_back)

push(…), pop(), top(), empty() queue

kan niet met vector (queue gebruikt push_back en pop_front)

Kan niet met forward_list (queue gebruikt push_back en pop_front)

push(…), pop(), front(), empty()Let op: push voegt achteraan toe en pop verwijdert vooraan.

priority_queuekan niet met list en forward_list (gebruikt index)

push(…), pop(), top(), empty()Let op: top geeft het grootste element terug en pop verwijdert dit element.

wordt geïmplementeerd als binary heap.

Page 68: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

68

Stacktest#include <iostream>#include <stack>using namespace std;

int main() { stack<char> s(32); char c; cout << "Type een tekst, sluit af met ." << endl; cin.get(c); while (c != '.') { s.push(c); cin.get(c); } while (!s.empty()) { cout << s.top(); s.pop(); } cin.get(); cin.get(); return 0;}

Page 69: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

69

Bekende datastructuren

Page 70: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

70

Associatieve containers set (verzameling) multiset (bag) map (1:N relatie) multimap (M:N relatie)

Mogelijkheden: zoeken op Key doorlopen op volgorde van Key

Implementatie: binary search tree

Bevat elementen van het template type pair<const Key, Value>

Bevat elementen van het type const Key

Page 71: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

71

Associatieve containers unordered_set (verzameling) unordered_multiset (bag) unordered_map (1:N) unordered_multimap (M:N)

Mogelijkheden: zoeken op Key

Implementatie: hash table

Bevat elementen van het template type pair<const Key, Value>

Bevat elementen van het type const Key

Page 72: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

72

Associatieve containers

Page 73: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

73

set (verzameling) Toevoegen met insert

Een element wordt automatisch op de “goede” plaats ingevoegd. Returntype is een pair<iterator, bool>. De bool geeft aan of het

invoegen gelukt is en de iterator geeft de plek aan waar ingevoegd is. Verwijderen met erase

Een te verwijderen element wordt automatisch opgezocht. Je kunt ook een iterator meegeven of een range (2 iteratoren).

Zoeken met find Geeft een iterator terug naar de plaats waar het element staat en geeft end() terug als element niet gevonden is.

Zoeken met count Geeft het aantal keer dat een element voorkomt (0 of 1).

Page 74: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

74

multiset (bag) Toevoegen met insert

Een element wordt automatisch op de “goede” plaats ingevoegd. Returntype is een iterator. Deze iterator geeft de plek aan waar ingevoegd

is. Verwijderen met erase

Een te verwijderen element wordt automatisch opgezocht. Alle gevonden elementen worden verwijderd.

Je kunt ook een iterator meegeven of een range (2 iteratoren). Zoeken met find

Geeft een iterator terug naar de plaats waar het eerste gevonden element staat en geeft end() terug als element niet gevonden is.

Zoeken met count Geeft het aantal keer dat een element voorkomt (0).

Page 75: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

75

set voorbeeld#include <iostream>#include <string>#include <set>using namespace std;

void print(const set<string>& s) { cout << "De set bevat: "; for (const auto& e: s) { cout << e << " "; } cout << endl;}

int main() { set<string> docenten = { "Jesse", "Paul", "Ineke", "Harry"}; docenten.insert("Paul"); print(docenten); // ...

Wat is de uitvoer?

Wat verandert er als we de set vervangen door een

multiset?

Wat verandert er als we de set vervangen door een unordered_set?

Page 76: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

76

set voorbeeld#include <iostream>#include <string>#include <set>using namespace std;

int main() { set<string> docenten; // … // achteraf testen of insert gelukt is. pair<set<string>::iterator, bool> result =

docenten.insert("Harry"); if (!result.second) { cout << "1 Harry is genoeg." << endl; } // vooraf testen of insert mogelijk is. if (docenten.count("Harry")) { cout << "1 Harry is genoeg." << endl; }

Je kunt hier in C++11 ook auto gebruiken!

Page 77: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

77

map (1:N relatie) Elementen zijn:pair<const key, value>

interface gelijk aan set insert erase find count

extra operator[] met operator[] kun je een key als index gebruiken. Als de key al in de map zit wordt een reference naar de bijbehorende value teruggegeven.

Als de key niet aanwezig in de map dan wordt deze key toegevoegd met de default value (default constructor).

Page 78: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

78

multimap (M:N relatie)Elementen zijn:pair<const key, value>

interface gelijk aan setinserterasefindcount

geen operator[]

Page 79: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

79

map voorbeeld#include <iostream>#include <fstream>#include <string>#include <map>using namespace std;

int main() { string w; map<string, int> freq; // word count cout << "Geef filenaam: "; cin >> w; ifstream fin(w); while (fin >> w) { ++freq[w]; } for (const auto& e: freq) { cout << e.first << " " << e.second << endl; }

Page 80: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Algoritmen en DatastructurenALGODS Week 4

Page 81: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

81

Iterators

input iterator (single pass) een voor een lezen * (rvalue) ++

output iterator (single pass) een voor een schrijven * (lvalue) ++

forward iterator voorwaarts * ++ == !=

bidirectional iterator voor-/achterwaarts * ++ -- == !=

random access iterator met sprongen * ++ -- += -= + - == != > >= < <= [] een gewone pointer is een random access iterator

Een iterator is geen class maar een (interface) afspraak. Elke class die aan deze afspraak voldoet is als iterator te gebruiken.

Page 82: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

82

Iterators

Page 83: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

83

IteratorsRelatie met containers

forward iteratorforward_list

bidirectional iteratorlist, set, multiset, map en multimap

random access iteratorvector en deque

Relatie met algoritmesinput iterator bijvoorbeeld findoutput iterator bijvoorbeeld copyforward iterator bijvoorbeeld removebidirectional iterator bijvoorbeeld reverserandom access iterator bijvoorbeeld sort

Page 84: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

84

Speciale iteratorsInsert-iterators (een soort cursor in insert mode).

insert_iteratorback_insert_iteratorfront_insert_iterator

Stream-iterators (koppeling tussen iostream library en STL).istream_iteratorostream_iterator

Dit zijn wel echte classes!

Page 85: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

85

Speciale iterators voorbeeldvector<int> rij;ifstream fin("getallen.txt");istream_iterator<int> iin(fin);istream_iterator<int> einde;copy(iin, einde, back_inserter(rij));sort(rij.begin(), rij.end());ofstream fout("getallen.txt");ostream_iterator<int> iout(fout, " ");copy(rij.begin(), rij.end(), iout);

Waarom werkt sort(iin, einde) niet?

Page 86: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

86

Generieke algoritmenEen generiek algoritme werkt op een range. Een range

wordt aangegeven door twee iteratoren i1 en i2. De range loopt van i1 tot (dus niet t/m) i2. In de wiskunde zouden we dit noteren als [i1, i2).

vector<int> v = {12, 18, 6}; sort(v.begin(), v.end()); for (auto e: v) { cout << e << " "; }

Page 87: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

87

Algoritmen vs memberfunctiesEen generiek algoritme werkt op meerdere container

types. Sommige containers hebben voor bepaalde bewerkingen specifieke memberfuncties.Omdat het generieke algoritme krachtigere iteratoren nodig

heeft dan de container kan leveren.Omdat de specifieke memberfunctie sneller is dan het

generieke algoritme.Kijk dus voordat je een generiek algoritme gebruikt

altijd eerst of er een specifieke memberfunctie is.

Page 88: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

88

Algoritmen vs memberfunctieslist<int> l = {12, 18, 6};sort(l.begin(), l.end()); // O(n log n)

l.sort(); // O(n log n)

heeft random access iteratoren nodig list levert bidirectionele

iteratoren

VS2013 error (16 regels) belangrijkste mededeling: binary '-' : 'std::_List_iterator<std::_List_val<std::_List_simple_types<int>>>' does not define this operator or a conversion to a type acceptable to the predefined operatorGCC error (58 regels) belangrijkste mededeling: In instantiation of 'void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]': error: no match for 'operator-' in '__last - __first'

Page 89: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

89

Algoritmen vs memberfunctiesset<int> s = {12, 6, 18};

auto i1 = find(s.cbegin(), s.cend(), 6); // O(n)if (i1 != s.cend()) { cout << *i1 << " gevonden" << endl;}

auto i2 = s.find(6); // O(log n)if (i2 != s.end()) { cout << *i2 << " gevonden" << endl;}

Page 90: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

90

Algoritmen Zoeken van elementen

find zoek element met bepaalde waarde O(n) find_if zoek element met bepaalde eigenschap find_if_not zoek element zonder bepaalde eigenschap (C++11) find_first_of zoek eerste element uit bepaalde range adjacent_find zoek twee opeenvolgende gelijke elementen search_n zoek naar n opeenvolgende gelijke elementen

Tellen van elementen count tel elementen met bepaalde waarde count_if tel elementen met bepaalde eigenschap

Testen van elementen (C++11) all_of test of alle elementen aan een bepaalde eigenschap voldoen any_of test of een element aan een bepaalde eigenschap voldoet none_of test of geen enkel element aan een bepaalde eigenschap voldoet

Wat is voordeel t.o.v. count_if?

Inconsequente naamgeving

Page 91: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

91

Algoritmen Werken met elementen

for_each voer bewerking uit op elk element Zoeken naar een range

search zoek naar een range find_end zoek naar een range van achter vandaan

Vergelijken van ranges mismatch zoek eerste verschil in twee ranges equal vergelijk twee ranges (returntype is bool)

Inconsequente naamgeving

Page 92: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

92

find#include <iostream>#include <vector>#include <algorithm>using namespace std;

int main() { vector<int> v = {-3, -4, 3, 4}; auto r = find(v.cbegin(), v.cend(), -4); if (r != v.cend()) { cout << "Het eerste element met waarde –4 heeft " << "index: " << r - v.cbegin() << endl; } cin.get(); return 0;}

Page 93: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

93

find_if#include <iostream>#include <list>#include <algorithm>using namespace std;

bool ispos(int i) { return i >= 0;}

int main() { list<int> l = {-3, -4, 3, 4}; auto r = find_if(l.cbegin(), l.cend(), ispos); if (r != l.cend()) { cout << "Het eerste positieve element is: " << *r << endl; }//...

Function ispos is used as predicateWat als we de eerste waarde >= 1 in de

lijst l willen zoeken?

Page 94: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

94

find_if//...class IsPos {public: bool operator()(int i) const { return i >= 0; }};

int main() { list<int> l = {-3, -4, 3, 4}; auto r = find_if(l.cbegin(), l.cend(), IsPos()); if (r != l.cend()) { cout << "Het eerste positieve element is: " << *r << endl; }//...

Functor IsPos() is used as predicateFunctor is een object dat zich gedraagd

als een functie

Page 95: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

95

find_if//...class IsGreaterEqualInt {public: IsGreaterEqualInt(int r): right(r) {} bool operator()(int left) const { return left >= right; }private: int right;};

int main() { list<int> l = {-3, -4, 3, 4}; auto r = find_if(l.cbegin(), l.cend(), IsGreaterEqualInt(0)); if (r != l.cend()) { cout << "Het eerste positieve element is: " << *r << endl; }//...

Functor IsGreaterEqualInt(0) is used as predicate. 0 is nu variabel!

Page 96: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

96

find_if//...template <typename T> class IsGreaterEqual {public: IsGreaterEqual(const T& r): right(r) {} bool operator()(const T& left) const { return left >= right; }private: T right;};

int main() { list<int> l {-3, -4, 3, 4}; auto r = find_if(l.cbegin(), l.cend(), IsGreaterEqual<int>(0)); if (r != l.cend()) { cout << "Het eerste positieve element is: " << *r << endl; }//...

Functor IsGreaterEqual<int>(0) is used as predicate. Type int is nu een template

parameter (compile time variabel) en 0 is nu variabel!

Page 97: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

97

find_if#include <iostream>#include <list>#include <algorithm>#include <functional>using namespace std;using namespace std::placeholders;

int main() { list<int> l = {-3, -4, 3, 4}; auto r = find_if(l.cbegin(), l.cend(),

bind(greater_equal<int>(), _1, 0)); if (r != l.cend()) { cout << "Het eerste positieve element is: " << *r << endl; }//...

Standaard functorbind(greater_equal<int>(), _1,

0) is used as predicate

_1 is a placeholder for the first argument

Page 98: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Lambda functie C++11Een lambda functie is een anonieme functie die

eenmalig gebruikt wordt als een functie object (functor).

De lambda functie wordt gedefinieerd op de plaats waar het functie object nodig is.

Een lambda functie kan dus als predicate gebruikt worden.

Page 99: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

99

find_if#include <iostream>#include <list>#include <algorithm>

int main() { list<int> l = {-3, -4, 3, 4}; auto r = find_if(l.cbegin(), l.cend(), [](int i) { return i >= 0; }); if (r != l.cend()) { cout << "Het eerste positieve element is: " << *r << endl; }//...

Lamda functie [](int i) { return i >= 0;

} is used as predicate

Voordeel?

Nadeel?

“eenvoudige” syntax

geen hergebruik mogelijk

Page 100: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

100

for_each#include <vector>#include <iostream>#include <iterator>#include <algorithm>using namespace std;

void printDubbel(int i) { cout << i << " " << i << " ";}

int main() { vector<int> v = {-3, -4, 3, 4}; ostream_iterator<int> iout(cout, " "); copy(v.cbegin(), v.cend(), iout); cout << endl; for_each(v.cbegin(), v.cend(), printDubbel); cout << endl;//...

Page 101: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

101

for_each met lambda#include <vector>#include <iostream>#include <iterator>#include <algorithm>using namespace std;

int main() { vector<int> v = {-3, -4, 3, 4}; ostream_iterator<int> iout(cout, " "); copy(v.cbegin(), v.cend(), iout); cout << endl; for_each(v.cbegin(), v.cend(), [](int i) { cout << i << " " << i << " "; }); cout << endl;//...

Page 102: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

102

Alternatief voor for_each#include <vector>#include <iostream>#include <iterator>#include <algorithm>using namespace std;

int main() { vector<int> v = {-3, -4, 3, 4}; ostream_iterator<int> iout(cout, " "); copy(v.cbegin(), v.cend(), iout); cout << endl; for (auto i: v) { cout << i << " " << i << " "; }; cout << endl; //...

Dit is toch veel simpeler!Wat is dan het nut van for_each?

Met for_each kun je ook een deel van een container bewerken!

Page 103: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

C++0x closure Een lambda functie kan gebruik maken van identifiers die buiten

de lambda functie gedeclareerd zijn. De verzameling van identifiers wordt een closure genoemd. Nederlands: (in)sluiting. Deze closure wordt tussen [ en ] opgegeven.

[a, &b] a wordt “by value” en b wordt “by reference” ingesloten.

[&] elke gebruikte variabele wordt “by reference” ingesloten. [=] elke gebruikte variabele wordt “by value” ingesloten. [=, &c] c wordt “by reference” ingesloten en alle andere

gebruikte variabelen worden “by value” ingesloten.

103

Page 104: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

C++0x closure

int somEven = 0;for_each(v.cbegin(), v.cend(), [&somEven](int i) { if (i % 2 == 0) { somEven += i; }});

Bepaal de som van alle even getallen in een vector.

[&] werkt ook. Wat is beter?

104

Page 105: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

C++0x lambda return type Een lambda functie kan in veel gevallen zelf zijn return type

bepalen. Bij een lambda functie die die dit niet kan moet het return type

worden opgegeven.

list<double> res = {1.4, 1.5, 4.9, 5.0, 8.9, 9.1, 10.0};vector<int> geheel;// Alle resultaten < 1.5 moeten worden afgerond tot 1// Alle resultaten > 9.9 moeten worden afgerond tot 10 // Alle overige resultaten moeten met 0.5 worden verhoogd en// daarna afgerondtransform(res.cbegin(), res.cend(), back_inserter(geheel), [](double c) -> int { if (c < 1.5) { return 1; } if (c > 9.9) { return 10; } return round(c + 0.5);});

105

1 2 5 6 9 10 10

Page 106: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

106

Algoritmen (vervolg) Kopiëren

copy kopieer elementen copy_if kopieer elementen met een bepaalde eigenschap

Bewerken transform voer een binaire bewerking uit op twee ranges replace vervang elementen met een bepaalde waarde replace_if vervang elementen met een bepaalde eigenschap replace_copy copy gevolgd door replace replace_copy_if copy gevolgd door replace_if rotate roteer de elementen rotate_copy copy gevolgd door rotate random_shuffle schud de elementen (b.v. kaarten)

Verwisselen swap_range verwissel ranges reverse keer de volgorde om reverse_copy copy gevolgd door reverse

Vergeten in C++98toegevoegd in C++11

Page 107: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

107

transform//...#include <functional>#include <algorithm>using namespace std;

int telop(int i, int j) { return i + j; }int main() { vector<int> v = {-3 , -4, 3, 4}, w = {1, 2, 3, 4}; ostream_iterator<int> iout(cout, " "); copy(v.cbegin(), v.cend(), iout); cout << endl; // Bewerking opgeven met een functie. transform(v.cbegin(), v.cend(), w.cbegin(), v.begin(), telop); copy(v.cbegin(), v.cend(), iout); cout << endl; // Bewerking opgeven met std functie-objecten. transform(v.cbegin(), v.cend(), w.cbegin(), v.begin(),

plus<int>()); copy(v.cbegin(), v.cend(), iout); cout << endl;

Page 108: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

108

Algoritmen (vervolg) Verwijderen

remove “verwijder”1 elementen met bepaalde waarde remove_if “verwijder”1 elementen met bepaalde eigenschap remove_copy copy gevolgd door remove remove_copy_if copy gevolgd door remove_if unique “verwijder”1 alle elementen die gelijk zijn aan hun voorganger unique_copy copy gevolgd door unique

Diversen fill maak alle elementen gelijk aan bepaalde waarde fill_n fill alleen de eerste n elementen generate maak alle elementen gelijk aan uitvoer van bepaalde functie generate_n generate alleen de eerste n elementen

1 “verwijder” = verwijdert elementen niet echt (geeft iterator terug om te gebruiken in erase)

Page 109: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

109

remove_if//...int main() { vector<int> v; for (int i = 0; i < 10; ++i) { v.push_back(i * i); } ostream_iterator<int> out(cout, " "); copy(v.cbegin(), v.cend(), out); cout << endl; vector<int>::iterator end = remove_if(v.begin(), v.end(),

bind (not2(modulus<int>()), _1, 2)); copy(v.begin(), end, out); cout << endl; copy(v.cbegin(), v.cend(), out); cout << endl; v.erase(end, v.end()); copy(v.cbegin(), v.cend(), out); cout << endl;//...

0 1 4 9 16 25 36 49 64 811 9 25 49 811 9 25 49 81 25 36 49 64 811 9 25 49 81

Page 110: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

110

Tip: remove within erase//...int main() { vector<int> v; for (int i = 0; i < 10; ++i) { v.push_back(i * i); } ostream_iterator<int> out(cout, " "); copy(v.cbegin(), v.cend(), out); cout << endl; v.erase(remove_if(v.begin(), v.end(),

bind(not2(modulus<int>()), _1, 2)), v.end()); copy(v.cbegin(), v.cend(), out); cout << endl;//...

0 1 4 9 16 25 36 49 64 811 9 25 49 81

Page 111: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

111

Algoritmen (vervolg) Sorteren

sort sorteer elementen O(n•log n) stable_sort sorteer elementen (gelijke elementen worden niet

verwisseld) binary_search zoek in een gesorteerde range O(log n)

Set operations (werkt voor alle gesorteerde ranges) includes range1 range 2 set_union set_intersection set_difference – set_symmetric_difference

Meer ...

Page 112: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

112

mem_fn#include <iostream>#include <list>#include <algorithm>#include <functional>using namespace std;

class Hond {public: virtual void blaf() const = 0;//...};

class Tekkel: public Hond {//... };

class StBernard: public Hond { //...};

int main() { list<Hond*> k = { new Tekkel, new StBernard, new Tekkel}; for_each( k.cbegin(), k.cend(), mem_fn(&Hond::blaf) );//...

blaf()

Page 113: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

113

Alternatief: Lambda functie#include <iostream>#include <list>#include <algorithm>

using namespace std;

class Hond {public: virtual void blaf() const = 0;//...};

class Tekkel: public Hond {//... };

class StBernard: public Hond { //...};

int main() { list<Hond*> k = { new Tekkel, new StBernard, new Tekkel}; for_each( k.cbegin(), k.cend(), [](const Hond* hp) { hp->blaf(); } );//...

blaf()

Page 114: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Algoritmen en DatastructurenALGODS Week 5

Page 115: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

GamesSpel met 2 spelers, die elk afwisselend aan de beurt

zijn.Boter Kaas en Eieren (Tic-Tac-Toe).4 op een rij.ZeeslagDammen, Schaken, Go, …

Hoe vind je de beste zet?Bouw een game tree.Pas het minimax algoritme toe.Gebruik alpha-beta pruning om minimax sneller te maken.

115

Page 116: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Game tree

X

X

X

X

OX

O

X

O

X

O

X

X

O X

X

O

XX

Zie Handouts

116

Page 117: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Game tree

Backtracking algoritme met minimax strategie!

Zie Handouts

117

Page 118: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1184 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

? ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 119: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax0.cpp value()//...

int value(int pos);int chooseComputerMove(int pos);int chooseHumanMove(int pos);

const int UNDECIDED = -1;

int value(int pos) { static const int value[16] = {4, 5, 3, 2, 6, 7, 8, 9, 1, 10, 2,

11, 12, 13, 14, 14}; if (pos >= 15 && pos < 31) return value[pos - 15]; // return known value return UNDECIDED; }

//...119

Page 120: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax0.cpp chooseComputerMove()//...

int chooseComputerMove(int pos) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = 0; for (int i = 1; i < 3; ++i) { int value = chooseHumanMove(2 * pos + i); if (value > bestValue) { bestValue = value; } } } return bestValue;}

//...

120

Page 121: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax0.cpp chooseHumanMove()//...

int chooseHumanMove(int pos) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = 15; for (int i = 1; i < 3; ++i) { int value = chooseComputerMove(2 * pos + i); if (value < bestValue) { bestValue = value; } } } return bestValue;}

//...

121

Page 122: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax0.cpp main()//...

int main() { int value = chooseComputerMove(0); cout << "Minimaal te behalen Maximale waarde = " << value <<

endl; cin.get();}

Minimaal te behalen Maximale waarde = 4

122

Page 123: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1234 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

? ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 124: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1244 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

≤4 ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 125: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1254 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 126: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1264 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 ? ? ? ? ? ? ?

≥4 ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 127: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1274 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 ≤3 ? ? ? ? ? ?

≥4 ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 128: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1284 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 ? ? ? ? ? ?

≥4 ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 129: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1294 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 ? ? ? ? ? ?

4 ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 130: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1304 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 ? ? ? ? ? ?

4 ?? ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 131: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1314 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 ≤6 ? ? ? ? ?

4 ?? ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 132: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1324 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 ? ? ? ? ?

4 ?? ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 133: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1334 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 ? ? ? ? ?

4 ?≥6 ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 134: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1344 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 ≤8 ? ? ? ?

4 ?≥6 ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 135: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1354 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 ? ? ? ?

4 ?≥6 ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 136: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1364 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 ? ? ? ?

4 ?8 ?

≤4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 137: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1374 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 ? ? ? ?

4 ?6 ?

4 ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 138: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1384 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 ? ? ? ?

4 ?6 ?

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 139: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1394 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 ≤1 ? ? ?

4 ?6 ?

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 140: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1404 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 ? ? ?

4 ?8 ?

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 141: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1414 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 ? ? ?

4 ?8 ≥1

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 142: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1424 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 ≤2 ? ?

4 ?8 ≥1

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 143: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1434 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 ? ?

4 ?8 ≥1

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 144: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1444 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 ? ?

4 ?8 2

4 ?

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 145: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1454 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 ? ?

4 ?8 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 146: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1464 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 ≤12 ?

4 ?8 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 147: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1474 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 ?

4 ?8 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 148: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1484 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 ?

4 ≥128 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 149: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1494 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 ≤14

4 ≥128 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 150: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1504 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 ≥128 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 151: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1514 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 148 2

4 ≤2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 152: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1524 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 148 2

4 2

≥4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 153: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1534 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 148 2

4 2

4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 154: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1544 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 148 2

4 2

4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 155: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Niet alleen de beste waarde maar ook de beste keuze moet worden bepaald!

155

Minmax voorbeeld

Page 156: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1564 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 148 2

4 2

4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 157: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax2.cpp chooseComputerMove()//...

int chooseComputerMove(int pos, int& bestNextPos) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = 0; for (int i = 1; i < 3; ++i) { int dummyPos; int value = chooseHumanMove(2 * pos + i, dummyPos); if (value > bestValue) { bestValue = value; bestNextPos = 2 * pos + i; } } } return bestValue;}

//...157

Page 158: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax2.cpp chooseHumanMove()//...

int chooseHumanMove(int pos, int& bestNextPos) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = 15; for (int i = 1; i < 3; ++i) { int dummyPos; int value = chooseComputerMove(2 * pos + i, dummyPos); if (value < bestValue) { bestValue = value; bestNextPos = 2 * pos + i; } } } return bestValue;}

//...

158

Page 159: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax2.cpp main()int main() { int pos = 0, bestNextPos, bestValue; while (pos < 15) { bestValue = chooseComputerMove(pos, bestNextPos); cout << "Minimaal te behalen Maximale waarde = " <<

bestValue << endl; pos = bestNextPos; cout << "Computer kiest positie: " << pos << endl; int posL = 2 * pos + 1, posR = 2 * pos + 2; if (pos < 15) { cout << "Je kunt kiezen voor positie " << posL <<

" of positie " << posR << endl; chooseHumanMove(pos, bestNextPos); cout << "Pssst, " << bestNextPos <<

" is de beste keuze." << endl; do { cout << "Maak je keuze: "; cin >> pos; } while (pos != posL && pos != posR); } } cout << "Behaalde waarde = " << value(pos) << endl;//...

159

Page 160: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

MinMax2.cpp main()Minimaal te behalen Maximale waarde = 4Computer kiest positie: 1Je kunt kiezen voor positie 3 of positie 4Pssst, 3 is de beste keuze.Maak je keuze: 4Minimaal te behalen Maximale waarde = 8Computer kiest positie: 10Je kunt kiezen voor positie 21 of positie 22Pssst, 21 is de beste keuze.Maak je keuze: 22Behaalde waarde = 9

160

Page 161: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1614 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 2 6 8 1 2 12 14

4 148 2

4 2

4

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Minimax voorbeeld

Page 162: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1624 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

? ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Alpha-beta pruning voorbeeld

Page 163: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1634 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

≤4 ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Alpha-beta pruning voorbeeld

Page 164: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1644 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 ? ? ? ? ? ? ?

? ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Alpha-beta pruning voorbeeld

Page 165: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1654 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 ? ? ? ? ? ? ?

≥4 ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Alpha-beta pruning voorbeeld

Page 166: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1664 5 3 2 6 7 8 9 1 10 2 11 12 13 14 14

4 ≤3 ? ? ? ? ? ?

≥4 ?? ?

? ?

?

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Alpha-beta pruning voorbeeld

Page 167: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1674 5 3 6 7 8 9 1 10 2 11 12 13 14 14

4 ≤3 ? ? ? ? ? ?

≥4 ?? ?

? ?

?

15 16 17 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

Alpha-beta pruning voorbeeld

Page 168: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1684 5 3 6 7 8 9 1 10 2 11 12 13 14 14

4 ? ? ? ? ? ?

4 ?? ?

? ?

?

15 16 17 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

≤3

Alpha-beta pruning voorbeeld

Page 169: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1694 5 3 6 7 8 9 1 10 2 11 12 13 14 14

4 ? ? ? ? ? ?

4 ?? ?

≤4 ?

?

15 16 17 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

≤3

Alpha-beta pruning voorbeeld

Page 170: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1704 5 3 6 7 8 9 1 10 2 11 12 13 14 14

4 ≤6 ? ? ? ? ?

4 ?? ?

≤4 ?

?

15 16 17 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

≤3

Alpha-beta pruning voorbeeld

Page 171: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1714 5 3 6 7 8 9 1 10 2 11 12 13 14 14

4 6 ? ? ? ? ?

4 ?? ?

≤4 ?

?

15 16 17 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

≤3

Alpha-beta pruning voorbeeld

Page 172: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1724 5 3 6 7 8 9 1 10 2 11 12 13 14 14

4 6 ? ? ? ? ?

4 ?≥6 ?

≤4 ?

?

15 16 17 19 20 21 22 23 24 25 26 27 28 29 30

7 12 13118 9 10 14

3 54 6

0

1 2

Computer

Mens

≤3

Alpha-beta pruning voorbeeld

Page 173: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1734 5 3 6 7 1 10 2 11 12 13 14 14

4 6 ? ? ? ?

4 ?≥6 ?

≤4 ?

?

15 16 17 19 20 23 24 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

Alpha-beta pruning voorbeeld

Page 174: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1744 5 3 6 7 1 10 2 11 12 13 14 14

4 6 ? ? ? ?

4 ??

4 ?

?

15 16 17 19 20 23 24 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

Alpha-beta pruning voorbeeld

Page 175: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1754 5 3 6 7 1 10 2 11 12 13 14 14

4 6 ? ? ? ?

4 ??

4 ?

≥4

15 16 17 19 20 23 24 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

Alpha-beta pruning voorbeeld

Page 176: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1764 5 3 6 7 1 10 2 11 12 13 14 14

4 6 ? ? ? ?

4 ?≥4

4 ?

≥4

15 16 17 19 20 23 24 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

Alpha-beta pruning voorbeeld

Page 177: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1774 5 3 6 7 1 10 2 11 12 13 14 14

4 6 ≤1 ? ? ?

4 ?≥4

4 ?

≥4

15 16 17 19 20 23 24 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

Alpha-beta pruning voorbeeld

Page 178: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1784 5 3 6 7 1 2 11 12 13 14 14

4 6 ? ? ?

4 ?

4 ?

≥4

15 16 17 19 20 23 25 26 27 28 29 30

7 12 138 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

11

≤1

≥4

Alpha-beta pruning voorbeeld

Page 179: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1794 5 3 6 7 1 2 11 12 13 14 14

4 6 ? ? ?

4 ?

4 ?

≥4

15 16 17 19 20 23 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 180: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1804 5 3 6 7 1 2 11 12 13 14 14

4 6 ≤2 ? ?

4 ?

4 ?

≥4

15 16 17 19 20 23 25 26 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 181: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1814 5 3 6 7 1 2 12 13 14 14

4 6 ≤2 ? ?

4 ?

4 ?

≥4

15 16 17 19 20 23 25 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 182: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1824 5 3 6 7 1 2 12 13 14 14

4 6 ≤2 ? ?

4 ?

4 ?

≥4

15 16 17 19 20 23 25 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 183: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1834 5 3 6 7 1 2 12 13 14 14

4 6 ≤2 ? ?

4 ?

4 ≤4

≥4

15 16 17 19 20 23 25 27 28 29 30

7 12 13118 9 14

3 54 6

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 184: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1844 5 3 6 7 1 2

4 6 ≤2

4

4 ≤4

≥4

15 16 17 19 20 23 25

7 12118 9

3 54

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 185: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1854 5 3 6 7 1 2

4 6 ≤2

4

4 ≤4

4

15 16 17 19 20 23 25

7 12118 9

3 54

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 186: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1864 5 3 6 7 1 2

4 6 ≤2

4

4 ≤4

4

15 16 17 19 20 23 25

7 12118 9

3 54

0

1 2

Computer

Mens

≤3

≥6

≤1

≥4

Alpha-beta pruning voorbeeld

Page 187: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

187

AlphaBeta2.cpp chooseComputerMove()//...int chooseComputerMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = alpha; for (int i = 1; bestValue < beta && i < 3; ++i) { int dummyPos; int value = chooseHumanMove(2 * pos + i, dummyPos,

alpha, beta); if (value > bestValue) { bestValue = value; alpha = bestValue; bestNextPos = 2 * pos + i; } } } return bestValue;}//...

187

Page 188: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

188

AlphaBeta2.cpp chooseComputerMove()//...int chooseComputerMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = alpha; for (int i = 1; alpha < beta && i < 3; ++i) { int dummyPos; int value = chooseHumanMove(2 * pos + i, dummyPos,

alpha, beta); if (value > bestValue) { bestValue = value; alpha = bestValue; bestNextPos = 2 * pos + i; } } } return bestValue;}//...

188

Maakt niet uit voor de werking!

Page 189: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

189

AlphaBeta2.cpp chooseHumanMove()//...int chooseHumanMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = beta; for (int i = 1; bestValue > alpha && i < 3; ++i) { int dummyPos; int value = chooseComputerMove(2 * pos + i, dummyPos,

alpha, beta); if (value < bestValue) { bestValue = value; beta = bestValue; bestNextPos = 2 * pos + i; } } } return bestValue;}//...

189

Page 190: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

190

AlphaBeta2.cpp chooseHumanMove()//...int chooseHumanMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = beta; for (int i = 1; beta > alpha && i < 3; ++i) { int dummyPos; int value = chooseComputerMove(2 * pos + i, dummyPos,

alpha, beta); if (value < bestValue) { bestValue = value; beta = bestValue; bestNextPos = 2 * pos + i; } } } return bestValue;}//...

190

Maakt niet uit voor de werking!

Page 191: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

191

AlphaBeta2.cpp chooseHumanMove()//...int chooseHumanMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { bestValue = beta; for (int i = 1; alpha < beta && i < 3; ++i) { int dummyPos; int value = chooseComputerMove(2 * pos + i, dummyPos,

alpha, beta); if (value < bestValue) { bestValue = value; beta = bestValue; bestNextPos = 2 * pos + i; } } } return bestValue;}//...

191

Maakt niet uit voor de werking!

Voorwaarde voor snoeien is: alpha ≥ beta

Bijhouden bestValue is niet nodig.

Page 192: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

192

AlphaBeta2.cpp chooseComputerMove()//...int chooseComputerMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { for (int i = 1; alpha < beta && i < 3; ++i) { int dummyPos; int value = chooseHumanMove(2 * pos + i, dummyPos,

alpha, beta); if (value > alpha) { alpha = value; bestNextPos = 2 * pos + i; } } bestValue = alpha; } return bestValue;}//...

192

Page 193: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

193

AlphaBeta2.cpp chooseHumanMove()//...int chooseHumanMove(int pos, int& bestNextPos, int alpha,

int beta) { int bestValue = value(pos); if (bestValue == UNDECIDED) { for (int i = 1; alpha < beta && i < 3; ++i) { int dummyPos; int value = chooseComputerMove(2 * pos + i, dummyPos,

alpha, beta); if (value < beta) { beta = value; bestNextPos = 2 * pos + i; } } bestValue = beta; } return bestValue;}//...

193

Page 194: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

1944 5 3 6 7 1 2

4 4 2

4

4 4

4

15 16 17 19 20 23 25

7 12118 9

3 54

0

1 2

Computer

Mens

3

4

1

4

Alpha-beta pruning voorbeeld

0,15

0,15

0,15

0,15 0,4

4,15

4,154,3

alpha,beta

0,4

0,4

0,4 0,4

4,4

4,15

4,15

4,15

4,15 4,1 4,2

4,4

4,15

4,15

Page 195: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Code: zie dictaat.

195

AlphaBeta1Verbose.cpp

snoei node 18snoei node 10snoei node 24snoei node 26snoei node 6Minimaal te behalen Maximale waarde = 4

Page 196: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacToeclass TicTacToe {public: enum Side {EMPTY, HUMAN, COMPUTER}; enum Value {HUMAN_WINS = -1, DRAW, COMPUTER_WINS, UNDECIDED}; TicTacToe() { fill(board.begin(), board.end(), EMPTY); } Value chooseComputerMove(int& bestRow, int& bestColumn); Value chooseHumanMove(int& bestRow, int& bestColumn); Side side(int row, int column) const; bool isUndecided() const; bool playMove(Side s, int row, int column); bool boardIsFull() const; bool isAWin(Side s) const;private: typedef matrix<Side, 3, 3> Board; Board board; Value value() const;};

196

Page 197: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacToe::chooseComputerMoveTicTacToe::Value TicTacToe::chooseComputerMove(int& bestRow,

int& bestColumn) { Value bestValue = value(); if (bestValue == UNDECIDED) { bestValue = HUMAN_WINS; for (int row = 0; row < 3; ++row) { for (int column = 0; column < 3; ++column) { if (board(row, column) == EMPTY) { board(row, column) = COMPUTER; int dummyRow, dummyColumn; Value value = chooseHumanMove(dummyRow, dummyColumn); board(row, column) = EMPTY; if (value > bestValue) { bestValue = value; bestRow = row; bestColumn = column; } } } } } return bestValue;}

197

Page 198: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacToe::chooseHumanMoveTicTacToe::Value TicTacToe::chooseHumanMove(int& bestRow, int& bestColumn) { Value bestValue = value(); if (bestValue == UNDECIDED) { bestValue = COMPUTER_WINS; for (int row = 0; row < 3; ++row) { for (int column = 0; column < 3; ++column) { if (board(row, column) == EMPTY) { board(row, column) = HUMAN; int dummyRow, dummyColumn; Value value = chooseComputerMove(dummyRow, dummyColumn); board(row, column) = EMPTY; if (value < bestValue) { bestValue = value; bestRow = row; bestColumn = column; } } } } } return bestValue;}

198

Page 199: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Tic-Tac-Toeaantal aanroepen chooseComputerMove bij eerste

zet (computer begint):Maximaal: 1+9+9x8+9x8x7+ ... + 9x8x7x6x5x4x3x2x1 =

986410Stoppen als er een winnaar is =

549946Toepassen alpha-beta pruning =

16811Toepassen (maximale) transposition table =

4272

199

Page 200: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Tic-Tac-Toeaantal aanroepen en execution time chooseComputerMove bij eerste en derde zet (computer begint):

200

Zet 1 Zet 3

Time Moves Time Moves

TicTacSlow.cpp 2,202610 549946 0,034667 8232

TicTacAB.cpp 0,071300 16811 0,002244 450

TicTacMap.cpp 0,183925 4272 0,000028 1

Page 201: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Transpostions

Door zetverwisselig bereik je soms dezelfde positie.Idee: sla berekende posities op en zoek voordat je

rekent.201

Page 202: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacMap.cppclass TicTacToe {//...private: class BoardWrapper { public: BoardWrapper(const Board& b); bool operator<(const BoardWrapper& rhs) const; private: Board board; }; class ValueAndBestMove { public: ValueAndBestMove() = default; ValueAndBestMove(Value v, int r, int c); Value value; int bestRow, bestColumn; }; map<BoardWrapper, ValueAndBestMove> boards;//...};

202

Waarom is dit nodig?

BoardWrapper is een wrapper (inpakker) voor Board.

Page 203: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacMap.cppbool TicTacToe::BoardWrapper::operator<(const BoardWrapper& rhs)

const { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (board(i, j) != rhs.board(i, j)) { return board(i, j) < rhs.board(i, j); } } } return false;}

203

Voldoet deze implementatie aan de regels die moeten gelden voor een < operatie? a < a false a < b !(b < a) a < b && b < c a < c

Page 204: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacMap.cppTicTacToe::Value TicTacToe::chooseComputerMove(int& bestRow,

int& bestColumn, Value alpha, Value beta) { auto itr = boards.find(BoardWrapper(board)); if (itr != boards.end()) { bestRow = itr->second.bestRow; bestColumn = itr->second.bestColumn; return itr->second.value; } Value bestValue = value(); if (bestValue == UNDECIDED) { for (int row = 0; alpha < beta && row < 3; ++row) { //... } bestValue = alpha; } boards[BoardWrapper(board)] = ValueAndBestMove(bestValue,

bestRow, bestColumn); return bestValue;} 204

Page 205: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacMapRestrictedDepth.cppTicTacToe::Value TicTacToe::chooseComputerMove(int& bestRow,

int& bestColumn, Value alpha, Value beta, int depth) { if (depth >= 3 && depth <= MAX_DEPTH) { auto itr = boards.find(BoardWrapper(board)); if (itr != boards.end()) { bestRow = itr->second.bestRow; bestColumn = itr->second.bestColumn; return itr->second.value; } }//... Value value = chooseHumanMove(dummyRow,

dummyColumn, alpha, beta, depth + 1);//... if (depth >= 3 && depth <= MAX_DEPTH) { boards[BoardWrapper(board)] = ValueAndBestMove(

bestValue, bestRow, bestColumn); } return bestValue;}

205

Verklaar?

Page 206: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacDetermineMaxTableDepth.cpp

206

2 3 4 5 6 7 8 90

2000400060008000

1000012000140001600018000

0

0.05

0.1

0.15

0.2

0.25

0.3

TicTacDetermineMaxTableDepth

Map sizeMoves consideredAvarage execution time (10 runs)

MAX_DEPTH

Aant

al

Exec

ution

tim

e (s

)

Debug mode

Page 207: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacDetermineMaxTableDepth.cpp

207

Release mode

2 3 4 5 6 7 8 90

2000400060008000

1000012000140001600018000

0

0.01

0.02

0.03

0.04

0.05

0.06

0.07

TicTacDetermineMaxTableDepth

Map sizeMoves consideredAvarage execution time (10 runs)

MAX_DEPTH

Aant

al

Exec

ution

tim

e (s

)

Page 208: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Alternatief voor map

208

Volgorde van stellingen is niet belangrijk. Gebruik van unordered_map ligt dus meer voor de hand.

Ook een perfect hash met behulp van een array is mogelijk (en véél sneller). Idee van Remco Boom.

Page 209: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Doorrekenen van de hele boom duurt te lang: reken tot een bepaalde diepte en “schat” daar de waarde van de stelling.

Dilemma:schatten kost veel tijd geen tijd om diep te rekenen.schatten kost minder tijd tijd om dieper te rekenen.

Transpositiematrix weggooien na berekenen van een computerzet. Waarom?

Algoritme kan verliezen: algoritme zoals tot nu besproken bevat een BUG! Kan niet tegen zijn verlies ;-)(gevonden en hersteld door Marc Cornet)

Ingewikkelder spel

209

Page 210: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacABLoser.cpp // place computer in losing situation t.playMove(TicTacToe::HUMAN, 0, 0); t.playMove(TicTacToe::COMPUTER, 0, 1); t.playMove(TicTacToe::HUMAN, 1, 1); printBoard(); doComputerMove();

210

---xo x

---Calculation time: 0.00114894 secMoves considered: 238Computer plays: ROW = -858993460 COLUMN = -858993460

Page 211: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Oplossing:Initialiseer bestRow en bestColumn met een geldige zet

voordat chooseComputerMove wordt aangeroepenAls de waarde van een stelling gelijk is aan de huidige beste

waarde kies dan die stelling

TicTacABLoser.cpp

211

Beide oplossingen zijn niet ideaal omdat computer geen tegenspel meer geeft maar “opgeeft” zodra hij verloren staat.

Page 212: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

TicTacABLoser.cpp

212

---xo x

---Calculation time: 0.00518334 secMoves considered: 238Computer plays: ROW = 0 COLUMN = 2

---xoo x

---

Page 213: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Algoritmen en DatastructurenALGODS Week 6

Page 214: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

214

Bekende datastructuren

Page 215: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Grafen: definities

Graph bestaat uitverzameling vertices [vur-tuh-seez] (nodes) en verzameling edges (arcs).

Edge verbind twee vertices.In een directed graph (digraph) hebben de edges een

richting.Vertex v is adjacent to w als er een edge is van v naar w.Edge heeft mogelijk cost (of weight). 215

V1

V2V3

V4

V5

4

5

117

11

6

Page 216: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Grafen: definities

Path is een rijtje vertices verbonden door edges.

Path length = aantal edges in path.Weighted path length = som van de costs van de edges

in path.Cycle = path van vertix naar zichzelf met lengte > 0.DAG = directed acyclic graph = directed graph zonder

cycles. 216

V1

V2V3

V4

V5

4

5

117

11

6

Page 217: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Grafen: toepassingenComputernetwerk (Internet)Openbaar vervoerTelefoonnetwerk

217

Voor de meeste praktischetoepassingen geldt dat het aantal

edges veel kleiner is dan allemogelijke verbindingen

= sparce graph.

Belangrijk algoritme: bepalen shortest path.

Page 218: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Grafen: datastructuurMatrix |V| x |V|

Elk element m[v][w] bevat de cost van de edge van v naar w. Cost = oneindig als edge niet bestaat.

Benodigde geheugen O(|V|2).Niet geschikt voor sparce graphs.

Adjacency listMaak voor elke vertex een lijstje met uitgaande edges

(adjacent vertice met de bijbehorende costs).struct Edge { Vertex* destination; int costs; };

Elke Vertex bevat een list<Edge> adjacent.Benodigde geheugen O(|E|).

218

Page 219: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Grafen: datastructuren

219

class Graph {public: // ...private: struct Vertex { // Vertex kan alleen gebruikt worden door // memberfuncties van Graph Vertex(const string& name); string name; struct Edge { // Edge kan alleen gebruikt worden door // memberfuncties van Graph Vertex* destination; int costs; }; list<Edge> adjacent; // ... }; map<string, Vertex*> vertexes; // vertex op naam opgeslagen static const int INF = INT_MAX; // ...};

Page 220: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Vertexstruct Vertex { Vertex(const string& name); void addEdge(Vertex* v, int costs); string name; struct Edge { Edge(Vertex* v, int costs); Vertex* destination; int costs; }; list<Edge> adjacent; // used for shortest-path algorithms void reset(); void printPath() const; Vertex* previous; int costs; bool isProcessed; // used for dijkstra algorithm unsigned int timesQueued; // used for negative algorithm bool isOnQueue; // used for negative algorithm unsigned int indegree; // used for acyclic algorithm};

220

Page 221: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

VertexGraph::Vertex::Edge::Edge(Vertex* v, int costs):

destination(v), costs(costs) {}Graph::Vertex::Vertex(const string& name): name(name) { reset();}void Graph::Vertex::addEdge(Vertex* v, int costs) { adjacent.push_back(Graph::Vertex::Edge(v, costs));}void Graph::Vertex::reset() { costs = INF; previous = 0; isProcessed = isOnQueue = false; timesQueued = indegree = 0;}void Graph::Vertex::printPath() const { if (previous) { previous->printPath(); cout << " to "; } cout << name;}

221

Page 222: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Graphclass Graph {public: ~Graph(); void addEdge(const string& sourceName, const string& destName,

int cost); void printPath(const string& destName) const; void unweighted(const string& startName); void dijkstra(const string& startName); void negative(const string& startName); void acyclic(const string& startName);private: struct Vertex { /* … */ };// getVertex creates a Vertex when it does not exists Vertex* getVertex(const string& vertexName);// find Vertex throws an exception when the Vertex does not exists Vertex* findVertex(const string& vertexName); const Vertex* findVertex(const string& vertexName) const; void reset();

222

Page 223: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

GraphGraph::~Graph() { for (auto& p : vertices) { delete p.second; }}void Graph::reset() { for (auto& p : vertices) { p.second->reset(); }}Graph::Vertex* Graph::getVertex(const string& vertexName) { Vertex* v = vertices[vertexName]; if (v == 0) { v = new Vertex(vertexName); vertices[vertexName] = v; } return v;}Graph::Vertex* Graph::findVertex(const string& vertexName) { auto itr = vertices.find(vertexName); if (itr == vertices.end()) throw runtime_error(vertexName + " not found"); return itr->second;}

223

Page 224: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Graphvoid Graph::addEdge(const string& sourceName,

const string& destName, int cost) { Vertex* v = getVertex(sourceName); Vertex* w = getVertex(destName); v->addEdge(w, cost);}void Graph::printPath(const string& destinationName) const { const Vertex* destination = findVertex(destinationName); if (destination->costs == INF) cout << destinationName << " is unreachable"; else { cout << "(Costs are: " << destination->costs << ") "; destination->printPath(); } cout << endl;}

224

Page 225: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Unweighted shortest path Voor elke vertex:

costs = INF Voor start vertex:

costs = 0 Voor alle vertices met costs == 0:

Voor alle adjacent vertices:if costs == INF costs = 1

Voor alle vertices met costs == 1:Voor alle adjacent vertices:

if costs == INF costs = 2 Enz...

225

Single source algoritme Uitgaande van een

start vertex wordt het kortste pad naar alle andere vertices berekend.

(Geldt voor alle SP algoritmen)

Page 226: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

USP (Breadth-first search)

226

V2

V5

V0

V6

V3

V1

V4

Page 227: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

USP (Breadth-first search)

227

V2

V5

V0

V6

V3

V1

V4

costs costs

costscosts

costscosts

costs

∞ ∞

∞ ∞

∞0

1

31

2

3

2

Page 228: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Unweighted shortest pathEerste keer dat costs een waarde != INF krijgt is dit

meteen de kortste afstand. Je kunt dan meteen de previous pointer goed zetten.

Volgorde van de te bezoeken vertices kan als volgt bepaald worden:Zet start vertex in een queue.Zolang queue niet leeg:

Haal vertex v uit queue.Voor alle adjacent vertices w:

Als costsw == INF.costsw = costsv + 1.Zet vertex w in de queue. 228

Page 229: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Unweighted shortest pathvoid Graph::unweighted(const string& startName){ reset(); Vertex* start = findVertex(startName); start->costs = 0; queue<Vertex*> q; q.push(start); while (!q.empty()) { Vertex* v = q.front(); q.pop(); for (auto& e : v->adjacent) { Vertex* w = e.destination; if (w->costs == INF) { w->costs = v->costs + 1; w->previous = v; q.push(w); } } }} 229

Page 230: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

USP O(|E|)Orde USP

Elke Vertex wordt 1x in de queue gezet en dus ook 1x uit de queue gehaald. Inzetten en uithalen is O(1).

Elke Vertex wordt dus 1x bezocht .Bij een bezoek worden alle adjacent Edges bekeken.Voor het hele algoritme geldt dus dat elke Edge 1x wordt

bekeken O(|E|)

230

Page 231: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Positive-weighted shortest pathDijkstra’s algoritmeAls vertex w adjacent to vertex v is:

costsw = costsv + costsv,w als deze waarde kleiner is dan de huidige waarde van costsw

Het is nu niet meer mogelijk om de costs van elke vertex maar 1x aan te passen.

231

Page 232: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Positive-weighted shortest pathVolgorde van de te bezoeken vertices kan als volgt

bepaald worden:Zet start vertex in een priority_queue die laagste costs

vooraan zet.Zolang priority_queue niet leeg:

Haal vertex v uit priority_queue.Voor alle adjacent vertices w:

Als costsw > costsv + costsv,w costsw = costsv + costsv,w Zet vertex w in de priority_queue.

232

Page 233: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Positive-weighted shortest pathvoid Graph::dijkstra(const string& startName) { reset(); Vertex* start = findVertex(startName); start->costs = 0; auto ptrVectorGreater = [](Vertex* p, Vertex* q) { return p->costs > q->costs; }; priority_queue<Vertex*, vector<Vertex*>,

decltype(ptrVectorGreater)> pq(ptrVectorGreater); pq.push(start);

// see next page

233

Page 234: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Positive-weighted shortest path while (!pq.empty()) { Vertex* v = pq.top(); pq.pop(); for (auto& e: v->adjacent) { Vertex* w = e.destination; int cvw = e.costs; if (cvw < 0) { throw runtime_error("Graph has negative edges"); } if (w->costs > v->costs + cvw) { w->costs = v->costs + cvw; w->previous = v; pq.push(w); } } }}

234

Page 235: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Dijkstra’s algoritme

235

V2

V5

V0

V6

V3

V1

V4

6

2

5

103

2

68

4

2

4

1

Page 236: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Dijkstra’s algoritme

236

V2

V5

V0

V6

V3

V1

V4

costs costs

costscosts

costscosts

costs

∞ ∞

∞ ∞

∞7

0

7

13

6

12

2

6

2

5

103

2

68

4

2

4

1

5

91210

previous

Page 237: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Dijkstra’s algoritmeOptimalisatie:

Een Vertex* kan meerdere keren in de priority_queue worden geplaatst (steeds met lagere costs).

Een vertex hoeft maar 1x te worden “afgehandeld”. De eerste keer dat een Vertex* uit de priority_queue wordt gehaald worden alle adjacent vertices onderzocht.

De variabele isProcessed wordt gebruikt om aan te geven of de vertex al is afgehandeld (isProcessed == true).maak isProcessed true als Vertex* (voor het eerst) uit

de priority_queue wordt gehaald.Als isProcessed == true als Vertex* uit de priority_queue wordt gehaald, hoef je niets meer te doen.

237Vraag: Waarom moet Vertex opnieuw in de priority_queue worden geplaatst als de costs aangepast (verlaagd) zijn?

Page 238: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Optimalisatie while (!pq.empty()) { Vertex* v = pq.top(); pq.pop(); if (!v->isProcessed) { v->isProcessed = true; for (auto& e: v->adjacent) { Vertex* w = e.destination; int cvw = e.costs; if (cvw < 0) { throw runtime_error("Graph has negative edges"); } if (w->costs > v->costs + cvw) { w->costs = v->costs + cvw; w->previous = v; pq.push(w); } } } }}

238

Page 239: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Dijkstra O(|E|•log|V|)Orde (van geoptimaliseerde code):

Elke vertex wordt 1x bezocht .Daarbij worden alle adjacent vertexes bekeken en (mogelijk)

wordt de destination in de priority_queue geplaatst. Voor het hele algoritme geldt dus (worst-case) O(|E|•log|E|)

|V| < |E| < |V|2

↔ log|V| < log|E| < log|V|2

↔ log|V| < log|E| < 2•log|V|O(log|V|) < O(log|E|) < O(log|V|)↔ O(log|E|) = O(log|V|)O(|E|•log|E|)↔ O(|E|•log|V|)

239

Page 240: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Negative-weighted shortest pathBellman-Ford algoritmeHet is nu niet meer mogelijk om elke vertex maar 1x te

“bezoeken”.Een negative-cost cycle moet herkend worden.Telkens als costs van een vertex wordt aangepast moet

deze vertex opnieuw “bezocht” worden.Als een vertex |V| keer bezocht is, is er negative-cost

cycle aanwezig.Bellman-Ford: O(|E|•|V|)

240

Page 241: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Negative-weighted shortest pathZet start vertex in een queue.Zolang queue niet leeg:

Haal vertex v uit queue.Als v |V| keer in de queue heeft gestaan

rapporteer negative-cost cycle en stopVoor alle adjacent vertices w:

Als costsw > costsv + costsv,w

costsw = costsv + costsv,w

Als w niet in de queue staat:Zet vertex w in de queue.

241

Page 242: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Negative-weighted shortest pathHulpvariabelen in Vertex:

unsigned int timesQueuednumber of time that this Vertex is placed on the queue

bool isOnQueuethis Vertex is currently present on the queue

242

Page 243: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Bellman-Fordvoid Graph::negative(const string& startName) { reset(); Vertex* start = findVertex(startName); start->costs = 0; queue<Vertex*> q; q.push(start); start->isOnQueue = true; start->timesQueued += 1;

// see next page

243

Page 244: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Bellman-Ford while (!q.empty()) { Vertex* v = q.front(); q.pop(); v->isOnQueue = false; if (v->timesQueued > vertices.size()) { throw runtime_error("Negative cycle detected"); } for (auto& e: v->adjacent) { Vertex* w = e.destination; int cvw = e.costs; if (w->costs > v->costs + cvw) { w->costs = v->costs + cvw; w->previous = v; w->timesQueued += 1; if (!w->isOnQueue) { w->isOnQueue = true; q.push(w); } } } }}

244

Page 245: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Bellman-Ford

245

V2

V0

V3

V1

V4

4

6

4-3

2

4

-2

Page 246: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Bellman-Ford

246

V2

V0

V3

V1

V4

costs costs

costs costs

∞ ∞

∞∞5

0 5

1

6

4

6

4-3

2

4

-2

previous

costs∞43

Helder staat in de queueVaag staat niet meer in de queue

Enz: V3 = 2, V4 = 0, V1 = 4V3 = 1, V4 = -1, V1 = 3…

Page 247: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Acyclic shortest pathGebruik topological sort.

Ev,w V < Wbereken de indegree van elke vertex (# binnenkomende edges)Herhaal tot alle vertices in de queue staan:

Zoek vertex v met indegree == 0 en plaats v in de queueVoor alle adjacent vertices w: indegree w = indegree w + 1

De vertices in de queue zijn nu topological sorted.Bij het zoeken naar het kortste pad worden vertices in

topological order “bezocht”:Elke vertex hoeft maar 1x bezocht te worden.

Acyclic shortest path: O(|E|)247

Page 248: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Acyclic shortest pathvoid Graph::acyclic(const string& startName) { reset(); Vertex* start = findVertex(startName); start->costs = 0; queue<Vertex*> q; // calculate all indegrees for (auto& p : vertices) { for (auto& e : p.second->adjacent) { e.destination->indegree += 1; } } // start with vertices with indegree 0 for (auto& p : vertices) { Vertex* v = p.second; if (v->indegree == 0) { q.push(v); } }

// see next page248

Page 249: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Acyclic shortest path // for all vertices in queue decltype (vertices.size()) iterations; for (iterations = 0; !q.empty(); ++iterations) { Vertex* v = q.front(); q.pop(); for (auto& e: v->adjacent) { Vertex* w = e.destination; int cvw = e.costs; w->indegree -= 1; if (w->indegree == 0) { q.push(w); } if (v->costs != INF && w->costs > v->costs + cvw) { w->costs = v->costs + cvw; w->previous = v; } } } if (iterations != vertices.size()) { throw runtime_error("Graph has a cycle!"); }}

249

Page 250: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Acyclic shortest path

250

V2

V5

V0

V6

V3

V1

V4

6 2

5

10

68

4

2

1

2

Page 251: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Acyclic shortest path

251

V2

V5

V0

V6

V3

V1

V4

costs costs

costscosts

costscosts

costs

∞ ∞

∞ ∞

∞012

6

6 2

5

10

68

4

2

1

10

65

previous

24

3

1

02

1

ind

ind

indind

ind ind

ind1 20

00

1

10

0

210

ind = indegree

Page 252: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Shortest path algoritmenBreath-first

UnweightedO(|E|)

AcyclicWeighted, no cyclesO(|E|)

DijkstraWeighted, no negative edgesO(|E|•log|V|)

Bellman-FordWeightedO(|E|•|V|) 252

Page 253: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

253

Galgje met find//...int main() { string w = "galgje"; set<string::size_type> v; do { for (string::size_type i = 0; i < w.size(); ++i) cout << (count(v.begin(), v.end(), i) ? w[i] : '.'); cout << endl << "Geef een letter: "; char c; cin >> c; auto r = w.begin(); while ((r = find(r, w.end(), c)) != w.end()) { v.insert(r - w.begin()); ++r; } } while (v.size() != w.size()); cout << w << " is geraden!" << endl; //...

Page 254: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

254

Galgje met sets (versie 1)//...int main() { string w = "galgje"; set<char> geraden, letters; copy(w.begin(), w.end(), inserter(letters, letters.begin())); do { for (auto c: w) cout << (geraden.count(c) ? c : '.'); cout << endl << "Raad een letter: "; char c; cin >> c; geraden.insert(c); } while (!includes(geraden.begin(), geraden.end(),

letters.begin(), letters.end())); cout << w << " is geraden!" << endl; //...

Page 255: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

255

Galgje met sets (versie 2)//...int main() { string w = "galgje"; set<char> goedGeraden, letters; copy(w.begin(), w.end(), inserter(letters, letters.begin())); do { for (auto c: w) cout << (geraden.count(c) ? c : '.'); cout << endl << "Raad een letter: "; char c; cin >> c; if (letters.count(c)) goedGeraden.insert(c); } while (goedGeraden != letters); cout << w << " is geraden!" << endl; //...

Page 256: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

256

Galgje met strings//...int main() { string w = "galgje"; string geraden(w.length(), '.'); do { cout << geraden << endl << "Raad een letter: "; char c; cin >> c; for (string::size_type i = 0; i < w.length(); ++i) if (w[i] == c) geraden[i] = c; } while (geraden != w); cout << w << " is geraden!" << endl; //...

Page 257: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

257

Galgje met strings en transform//...int main() { string w = "galgje"; string geraden(w.length(), '.'); do { cout << geraden << endl << "Raad een letter: "; char c; cin >> c; transform(w.begin(), w.end(), geraden.begin(),

geraden.begin(), [c](char wc, char gc) { return c == wc ? wc : gc; }); } while (geraden != w); cout << w << " is geraden!" << endl; //...

Page 258: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Practicum opdracht 4Wie opdracht 4b nog niet heeft

ingeleverd moet de zaal verlaten!

258

Page 259: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Opdracht 4 met STLstruct Freq: public map<string, int> { void init(string s) { (*this)[s] = 0; } void inc(string s) { if (count(s)) ++(*this)[s]; } void dec(string s) { if (count(s)) --(*this)[s]; }};bool second_is_not_0(Freq::value_type p) { return p.second != 0; }bool second_abs_is_gt_1(Freq::value_type p) { return abs(p.second) > 1; }int main() { Freq f; ifstream f0("keywords.txt"), f1("in1.cpp"), f2("in2.cpp"); istream_iterator<string> if0(f0), if1(f1), if2(f2), iend; for_each(if0, iend, bind(mem_fn(&Freq::init), &f, _1)); for_each(if1, iend, bind(mem_fn(&Freq::inc), &f, _1)); for_each(if2, iend, bind(mem_fn(&Freq::dec), &f, _1)); cout << any_of(f.begin(), f.end(), second_abs_is_gt_1) << endl; cout << count_if(f.begin(), f.end(), second_is_not_0) << endl; cin.get(); return 0;}

259

Page 260: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Opdracht 4 met lamdaint main() { map<string, int> f; ifstream f0("keywords.txt"), f1("in1.cpp"), f2("in2.cpp"); istream_iterator<string> if0(f0), if1(f1), if2(f2), iend; transform(if0, iend, inserter(f, f.end()), [](string s) { return make_pair(s, 0); }); for_each(if1, iend, [&](string w) { if (f.count(w)) ++f[w]; }); for_each(if2, iend, [&](string w) { if (f.count(w)) --f[w]; }); cout << any_of(f.cbegin(), f.cend(), [](const pair<const string, int>& p) { return abs(p.second) > 1; }) << endl; cout << count_if(f.cbegin(), f.cend(), [](const pair<const string, int>& p) { return p.second != 0; }) << endl; cin.get(); return 0;} 260

Page 261: Inhoud Week 1Week 2Week 3Week 4Week 5Week 6Week 7

Opdracht 4 met lamdaint main() { map<string, int> f; ifstream f0("keywords.txt"), f1("in1.cpp"), f2("in2.cpp"); istream_iterator<string> if0(f0), if1(f1), if2(f2), iend; for_each(if0, iend, [&](string w) { f[w] = 0; }); for_each(if1, iend, [&](string w) { if (f.count(w)) ++f[w]; }); for_each(if2, iend, [&](string w) { if (f.count(w)) --f[w]; }); cout << any_of(f.cbegin(), f.cend(), [](const pair<const string, int>& p) { return abs(p.second) > 1; }) << endl; cout << count_if(f.cbegin(), f.cend(), [](const pair<const string, int>& p) { return p.second != 0; }) << endl; cin.get(); return 0;}

261