/****************************************/
/*	Autor: Kacper Świętkowski			*/
/*	k.swietkowski@stud.elka.pw.edu.pl	*/			
/*	Temat: biblioteka stl,				*/
/*	algorytmy	replace, replace_if		*/
/****************************************/

/*
Algorytmy replace, replace_if()
umożliwiają przeglądanie ciągu (kolekcji)
i zamianę wartości na inne, zgodnie ze
specyfikacją.
Dwa pierwsze argumenty funkcji replace i replace_if
stanowią kolejno : początek i koniec przeglądanego ciągu,
w algorytmie replace trzeci argument to wartość do której
porównywane są elementy ciągu(operator==()), jeżeli 
elementy są takie same, to element ciągu zamieniany
jest na 4 argument

w algorytmie replace_if trzecim argumentem jest predykat,
przyjmujący jako argument typ elementów trzymanych w kolekcji
jeżeli predykat dla danego elementu zwróci wartość true
element ten zamieniany jest na argument 4
*/


#include <list>
#include <string>
#include <algorithm>
#include <iostream>

/* definicja predykatu (funkcji zwracającej wartość bool)		*/
/*	predykat ten wykorzystywany jest wraz z  algorytmem replace_if	
	do zmiany napisu w liscie napisow							*/
	bool is_gdansk(const std::string & miast);

int main()
{
	/* inicjalizacja zmiennych służących demonstracji	*/
	typedef std::list<std::string> Miasta;
	typedef bool (*Pred)(const std::string&);
	Miasta miasta;
	miasta.push_back("Warszawa");
	miasta.push_back("Krakow");
	miasta.push_back("Poznan");
	miasta.push_back("Ostrow Mazowiecka");
	miasta.push_back("Warszawa");

	/********************************/
	/*	Uzycie algorytmu replace	*/
	/********************************/

	replace(	miasta.begin(), // początek przeglądanego ciagu
				miasta.end(),	// ostatni przeglądane element (koniec ciagu)
				std::string("Warszawa"), // wzorzec elementu do zamiany
				std::string("Gdansk"));	// wartosc na ktora zostanie zamieniony 

	// drukujemy liste po zamianie za pomoca replace
	// zamiast napisu "Warszawa" zostanie wydrukowany napis "Gdansk"
	std::cout <<std::endl << "Miasta po zamianie" << std::endl;
	for(	Miasta::iterator i = miasta.begin();	i != miasta.end(); ++i)
		std::cout<< *i << std::endl;


	/********************************/
	/* Uzycie algorytmu replace_if	*/
	/********************************/

	/* dwa pierwsze argumenty bez zmian,
	trzecim argumentem jest predykat, algorytm zamieni wartosc dla ktorej predykat
	zwraca wartosc TRUE na wartosc z czwartego argumentu */

	replace_if(	miasta.begin(),	 // początek przeglądanego ciagu
				miasta.end(),	// ostatni przeglądane element (koniec ciagu)	
				(Pred)is_gdansk,// predykat
				std::string("Wroclaw"));// wartosc na ktora zostanie zamieniony element
										// spelniajacy predykat

	// drukujemy liste po zamianie za pomocą replace_if
	std::cout <<std::endl<< "Miasta po zamianie" << std::endl;
	for(	Miasta::iterator i = miasta.begin();	i != miasta.end(); ++i)
		std::cout<< *i << std::endl;


	system("PAUSE");
}


/* Prosty predykat, zwracajacy wartosc 1
gdy napis ma wartosc "Gdansk"				*/
bool is_gdansk(const std::string& miasto)
{
	return (miasto == "Gdansk");
}

/*	Implementacja algorytmu replace  
template<class For, class T>
void replace(For first, For last, const T& val, const T& new_val)
{
	while (first != last)
	{
		if(*first == val) 
			*first = new_val;
		++first;
	}
}

	Implementacja algorytmu replace_if  
template<class For, class T>
void replace_if(For first, For last, Pred p, const T& new_val)
{
	while (first != last)
	{
		if(p(*first)
			*first = new_val;
		++first;
	}
}

*/