//======================================================
//	Bartosz Zaremba										
//	J1TIZ												
//	algorytm copy_backward								
//======================================================

/*	OPIS ALGORYTMU copy_backward
	
	--Definicja--
	template<class Bi, class Bi2> 
		Bi2 copy_backward(Bi first, Bi last, Bi2 result)
		{
			while (first != last) *--result = *--last;
			return result;
		};
	
	--Parametry--
	first - iterator wskazujacy na pierwszy element
			sekwencji wejsciowej
	last  - iterator wskazujacy na pozycje za ostatnim
			elementem sekwencji wejsciowej
	result- iterator wskazujacy na pozycje za ostatnim
			elementem sekwencji wyjsciowej

	--Opis--
	Algorytm kopiuje sekwencje [first, last) do sekwencji
	konczacej sie na pozycji poprzedzajacej iterator result,
	czyli do zakresu [result - (last - first), result).
	Kopiowanie odbywa sie od tylu, zaczynajac od elementu
	(last - 1) konczas na first. Algorytm copy_backward 
	nie zmienia kolejnosci elementow.
	Niezbedne jest uzycie iteratora dwukierunkowego zarowno
	dla ciagu wejsciowego jak i wyjciowego. Wazne jest, aby 
	w sekwencji wyjsciowej bylo	wystarczajaco duzo miejsca
	do skopiowania calego zakresu wejsciowego.
	
	Kopiowanie opiera sie na dekrementacji iteratorow result
	oraz last i przypisaniu wartosciu z sekwencji wejsciowej
	do wyjsciowej. Dzieje sie tak do momentu, gdy iteratory
	last oraz first nie beda wskazywac na to samo.
	Powyzszy proces wyglada nastepujaco:
	*(result - 1) = *(last - 1)
	*(result - 2) = *(last - 2)
	*(result - 3) = *(last - 3)
	...
	*(result - N) = *(last - N) // ( last - N = first )
 
 */

/*	Przyklad użycia	*/

#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

using std::cout;
using std::endl;
using std::ostream;
using std::ostream_iterator;
using std::string;
using std::vector;

// Funkcja wypisujaca elementy wektora do strumienia
template<class T> ostream& print(ostream& os, const std::vector<T> &v) {
	for(int i = 0; i < v.size(); ++i )
		os << v.at(i) << " ";
	os << endl;
	return os;
}

int main()
{
	vector<int> v1;
	vector<int> v2;
	int i = 0;

	// ustawienie wartosci poczatkowych wektorow v1 i v2
	for(; i < 5; ++i )
	{
		v1.push_back( i );
		v2.push_back( 11*(i + 1) );
	}
	print(cout, v1);
	print(cout, v2);

	// rozszerzenie i skopiowanie wektora na koniec
	// v1 = [ 0, 1, 2, 3, 4 ]
	v1.resize( 2*v1.size() ); // zwiekszenie rozmiaru wektora
	copy_backward( v1.begin(), v1.begin() + v1.size()/2, v1.end() );
	// v1 = [ 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 ]
	print(cout, v1);
	
	// wstawienie 3 wartosci z wektora v1 w srodek wektora v2
	// v2 = [ 11, 22, 33, 44, 55 ]
	copy_backward(v1.begin() + 2, v1.end() - 5, v2.end() - 1 );
	// v2 = [ 11, 2, 3, 4, 55 ]
	print(cout, v2);
	
	//Dzialania na napisach
	vector<string> v3;
	v3.push_back("Nick");
	v3.push_back("uszkodzil");
	v3.push_back("bolid");
	v3.push_back("Roberta");
	print(cout, v3);
	// "Nick uszkodzil bolid Roberta"

	vector<string> v4;
	v3.resize(v3.size() + 2 );
	v4.push_back("swoj");
	v4.push_back("i");
	v4.push_back("Roberta");
	copy_backward( v4.begin(), v4.end(), v3.end() );
	print(cout, v3);
	// "Nick uszkodzil bolid swoj i Roberta"

	// Uwaga! copy_backward wymaga uzycia 
	// iteratora dwukierunkowego dla obu
	// kontenerow - wejsciowego i wyjsciowego
	ostream_iterator<string> output( cout, " " );
	copy(v3.begin(), v3.end(), output); //dobrze
	//copy_backward(v4.begin(), v4.end(), output); //blad!

	//getchar();
	return 0;
}