//  Jakub Rutkowski 5EIK
//	Algorytmy STL: remove_copy oraz remove_copy_if
//-------------------------------------------------------------------------------------------------------------
//                                          Opis Algorytmu
//-------------------------------------------------------------------------------------------------------------
/*
Algorytm remove_copy kopiuje elementy pewnej kolekcji do innej omijajac obiekty, które sa rowne zadanej wartosci.
Algorytm remove_copy_if kopiuje elementy pewnej kolekcji do innej. Element jest kopiowany, jezeli nie zostal
spelniony pewien warunek. W przeciwnym przypadku element zostaje pominięty.
Funkcje te stosowane sa do operacji na kontenerach, aby poprawic czytelnosc kodu oraz zaoszczedzic programiscie
czas.

    Nagłowek:
        #include<algorithm>

    Deklaracje:
	template<class ForwardIterator, class OutputIterator, class Type>
            inline OutputIterator remove_copy(
                ForwardIterator First,
                ForwardIterator Last,
                OutputIterator Result,
                const T& Value
                )

        template<class ForwardIterator, class OutputIterator, class Predicate>
            inline OutputIterator remove_copy_if(
                ForwardIterator First,
                ForwardIterator Last,
                OutputIterator Result,
                Predicate Pred
            )

    Parametry:
	remove_copy:
            First      - Poczatkowy element kolekcji zrodlowej.
            Last       - Koncowy element kolekcji zrodlowej.
            Result     - Iterator na kolekcje, do ktorej kopiowane sa dane.
            Value      - Wartosc, ktora ma byc pomijana podczas kopiowania.

        remove_copy_if:
            Firstt      - Poczatkowy element kolekcji zrodlowej.
            Last        - Koncowy element kolekcji zrodlowej.
            Result      - Iterator na kolekcje, do ktorej kopiowane sa dane.
            Pred        - Warunek okreslajacy czy wartosc ma zostac skopiowana.

    Wartosc zwracana:
		Obie funkcje zwracaja iterator na koniec nowej kolekcji.

    Złożonosc:
        Obie funkcje pracuja w czasie liniowym.

*/
//-------------------------------------------------------------------------------------------------------------
//                                          Przyklad Uzycia
//-------------------------------------------------------------------------------------------------------------
#include <algorithm>
#include <list>
#include <iostream>

bool Predykat(std::string element);

int main()
{
    std::list<std::string> kolekcja_zrodlowa;       //Tworzymy przykladowa kolekcje obiektow
    kolekcja_zrodlowa.push_back("Adam");            //i wypelniamy ja przykladowymi wartosciami
    kolekcja_zrodlowa.push_back("Ewa");
    kolekcja_zrodlowa.push_back("Usun");
    kolekcja_zrodlowa.push_back("Ela");
    kolekcja_zrodlowa.push_back("Usun");
    kolekcja_zrodlowa.push_back("Jola");
    kolekcja_zrodlowa.push_back("Ola");

    //wypisujemy zawartosc na standartowe wyjscie:
    std::cout << "Zawartosc kolekcji zrodlowej:" << std::endl;
    for(std::list<std::string>::iterator i=kolekcja_zrodlowa.begin(); i!=kolekcja_zrodlowa.end(); i++)
        std::cout << *i << std::endl;

    //-----------------------
    //Algorytm remove_copy:
    //-----------------------
    std::list<std::string> kolekcja_docelowa1;      //Tworzymy kolekcje, do ktorej kopiowala bedzie funkcja remove_copy
    std::string warunek="Usun";                     //Tworzymy zmienna przechowujaca napis, ktory ma nie byc kopiowany

    kolekcja_docelowa1.resize(10);

    std::list<std::string>::iterator doc1_iterator; //Funkcja ma skopiowac kolekcja_zrodlowa do kolekcja_docelowa1 pomijajac wartosc "Usun"
    doc1_iterator = remove_copy(kolekcja_zrodlowa.begin(), kolekcja_zrodlowa.end(), kolekcja_docelowa1.begin(), warunek);

    //wypisujemy zawartosc kolekcja_docelowa1 na standartowe wyjscie
    std::cout << std::endl << "Zawartosc kolekcji po skopiowaniu do niej obiektow za pomoca remove_copy:" << std::endl;
    for(std::list<std::string>::iterator i=kolekcja_docelowa1.begin(); i!=doc1_iterator; i++)
        std::cout << *i << std::endl;



    //-----------------------
    //Algorytm remove_copy_if:
    //-----------------------
    std::list<std::string> kolekcja_docelowa2;      //Tworzymy kolekcje, do ktorej kopiowala bedzie funkcja remove_copy_if

    kolekcja_docelowa2.resize(10);

    std::list<std::string>::iterator doc2_iterator; //Funkcja ma skopiowac kolekcja_zrodlowa do kolekcja_docelowa1 pomijajac wartosci
                                                    //dla ktorych Predykat() == true
    doc2_iterator = remove_copy_if(kolekcja_zrodlowa.begin(), kolekcja_zrodlowa.end(), kolekcja_docelowa2.begin(), Predykat);

    //wypisujemy zawartosc kolekcja_docelowa2 na standartowe wyjscie
    std::cout << std::endl << "Zawartosc kolekcji po skopiowaniu do niej obiektow za pomoca remove_copy_if:" << std::endl;
    for(std::list<std::string>::iterator i=kolekcja_docelowa2.begin(); i!=doc2_iterator; i++)
        std::cout << *i << std::endl;

	return 0;
}

bool Predykat(std::string element){                 //Funkcja warunek, ktora zostaje wywolywana przez funkcje remove_copy_if aby sprawdzic,
                                                    //czy dany element nalezy usunac.
    if(element=="Usun" || element[0] == 'E')
        return true;                                //Jezeli element=="Usun" lub pierwszy znak elementu to "E", wtedy nie kopiujemy.
    return false;
}
