/*
*	Lukasz Trzaska gr 4i1 STL SEARCH_N
*
* 	#include <algorithm>
*   iterator search_n( iterator start, iterator end, size_t num, const TYPE& val );
*   iterator search_n( iterator start, iterator end, size_t num, const TYPE& val, BinPred p );
*        
*	Funkcja search_n() szuka num wystapien w zasiegu kontenera [start,end).
*	Jezeli zostanie znalezione num kopii danego elementu wystapujacych kolejno 
* 	w sekwencji, funkcja zwraca iterator na pierwszy znaleziony element.
*	W przeciwnym wypadku zwraca iterator na end danej sekwencji.
*	Jezeli predykat binarny jest zadany, to zostaje uzyty do specyficznego 
*	porownania elementow.
*/
#include<iostream>
#include<algorithm>	//zawiera funkcje search_n
#include<vector>	//przekladowy kontener
#include<typeinfo>  //dla typeid() uzytego w predykacie porownujacym elementy

using namespace std;

//funkcja pomocnicza do wyswietlania elementow w sekwencji
//wyswietla elementy z zakresu [b, e)
void print(const vector<string>::const_iterator& b, const vector<string>::const_iterator& e) {
	int i = 0;
	if(b == e) {
 		 cout << "brak elementow" << endl;
 		 return;
 	}
	vector<string>::const_iterator it = b;    
	while(it != e) {
       cout << "[" << i++ << "] " << *it << endl;
	   ++it;
	}
}
//deklaracja binarnego predykatu
//zwraca TRUE gdy porownywane stringi maja ostatnia litere ta sama
template<class T>
struct string_equal_last : public binary_function <T, T, bool> {
	bool operator()(const T& x, const T& y) {		
		if(typeid(T) != typeid(std::string)) //zabezpiecz przed uzyciem nie dla stringu
	       return false;
		
		string::const_iterator ix = x.end(); 
		string::const_iterator iy = y.end();
		if(*--ix == *--iy) return true;
		return false; 	        
	}
};

int main() {
    vector<string> vecA;
    vector<string>::iterator itResult;
    
    // Utworzenie przykladowego wektora elementów
    vecA.push_back("Slon");			vecA.push_back("Wielblad");
    vecA.push_back("Zyrafa"); 		vecA.push_back("Kon");
    vecA.push_back("Niedzwiedz"); 	vecA.push_back("Antylopa");
    vecA.push_back("Borsuk");		vecA.push_back("Mysz");
    vecA.push_back("Zebra");		vecA.push_back("Anakonda");		
	vecA.push_back("Anakonda");  	vecA.push_back("Zyrafa");
    vecA.push_back("Wilk");			vecA.push_back("Jaszczurka");
    
	// Wyswietlenie wszystkich elementow wektora
    print(vecA.begin(), vecA.end());
	
	// search_n PODSTAWOWE UZYCIE - wyszukanie w wektorze kolejno 2 wystapien 
	// slowa Zyrafa po sobie (w naszym wektorze nie wystepuje)
    itResult = search_n(vecA.begin(), vecA.end(), 2, "Zyrafa");
    
	cout << endl << "search_n(vecA.begin(), vecA.end(), 2, Zyrafa)" << endl;
    print(itResult, vecA.end());
	
	// search_n PODSTAWOWE UZYCIE - wyszukanie w wektorze kolejno 
	// 2 wystapien slowa Anakonda
    itResult = search_n(vecA.begin(), vecA.end(), 2, "Anakonda");
    
	cout << endl << "search_n(vecA.begin(), vecA.end(), 2, Anakonda)" << endl;
    print(itResult, vecA.end());
	
	// search_n PODSTAWEWE UZYCIE Z PREDYKATEM - wyszukanie w wektorze kolejno 
	// 2 wystapien slowa Anakonda z jawnie wolanym binarnym predykatem porownujacym
    itResult = search_n(vecA.begin(), vecA.end(), 2, "Anakonda", equal_to<string>());
    
	cout << endl << "search_n(vecA.begin(), vecA.end(), 2, Anakonda, equal_to<string>())" << endl;
    print(itResult, vecA.end());
	
	// search_n UZYCIE Z WLASNYM PREDYKATEM - wyszukanie w wektorze kolejno 
	// 4 wystapien slow ktore maja ta sama ostatnia litere co Anakonda
    itResult = search_n(vecA.begin(), vecA.end(), 4, "Anakonda", string_equal_last<string>());
    
	cout << endl << "search_n(vecA.begin(), vecA.end(), 5, Anakonda, string_equal_last<string>())" << endl;
	print(itResult, vecA.end());
        
    getchar();
    return 0;
}
