/*
 *  transform.cpp
 *  
 *
 *  Created by GLevi on 04/12/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

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

template <class T>
void print  (T  i) {
	cout << " " << i;
}


int op_increase (int i) { return ++i; }
int op_sum (int i, int j) { return i+j; }

bool myfn(int i, int j)  { return i>j; }

template <class T>
struct      mystruct : binary_function<T ,T ,bool> {
	bool operator() (T  i,T  j) const { return i<j; }
};

template <class T>
class generatore 
{
public:
	generatore (T  start = 0, T  stp = 1) : current(start), step(stp)
	{ }
	T  operator() () { return current+=step; }
private:
	T  current;
	T  step;
};





int main () {
	vector<int> first(10); // 
	vector<int> second;
	vector<int>::iterator it;
	generatore<int> pippo(10,10) ;
	mystruct<int> ordina;
	generate(first.begin(), first.end(), pippo );
	first.resize(first.size()*2);
	generate(first.begin()+first.size()/2, first.end(), generatore<int>(1,17) );
	
	// Spiegatemi questo:
	int i = 0;
	i = ++i + 1;
	std::cout << i << std::endl;
	
	
		
	cout << "\nfirst contiene:";
	
	for_each (first.begin(), first.end(), print<int>);

	
	second.resize(first.size());     // alloca spazio.
	
	transform (first.begin(), first.end(), second.begin(), op_increase);
	cout << "\nsecond contiene:";
	for_each (second.begin(), second.end(), print<int>);
	
	

	
	transform (first.begin(), first.end(), second.begin(), first.begin(), op_sum);

	cout << "\n Dopo la somma con second first contiene:";
	for_each (first.begin(), first.end(), print<int>);
	
	sort(first.begin(),first.end(),mystruct<int>());
	cout << "\nOrdinamento normale:";
	for (it=first.begin(); it!=first.end(); ++it)
		cout << " " << *it;
	
	cout <<"\nRovesciando l'ordinamento :"<< endl;
	
	sort(first.begin(),first.end(),not2(ordina ));
	for_each (first.begin(), first.end(), print<int>);

	

	cout << "\nL'elemento più piccolo è : " << *min_element(first.begin(), first.end()) << endl;
	cout << "Il più grande è :  " << *max_element(first.begin(), first.end()) << endl;
	
	
	
	
	cout << "Usando myfn l'elemento più piccolo è : " << *min_element(first.begin(), first.end(),myfn) << endl;
	cout << "Usando myfn il più grande è :  " << *max_element(first.begin(), first.end(),myfn) << endl;
	
	
	
	cout << "Usando mystruct l'elemento più piccolo è : " << *min_element(first.begin(), first.end(),mystruct<int>() ) << endl;
	cout << "Usando mystruct e not2 l'elemento più piccolo è  :  " << *max_element(first.begin(), first.end(),not2(mystruct<int>())) << endl;
	
	
	
	
	return 0;
}