// L-32 MCS 360 Fri 5 Nov 2010 : partition.cpp

/* This program tests the partition of a vector of pairs. */

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;

vector< pair<int,char> > random_vector ( int n );
// returns a vector of n random 2-digit numbers
// associated with lower case letters

void write_vector ( vector< pair<int,char> > v, int lower, int upper );
// writes the vector v, from v[lower] to v[upper], v[upper] included

void partition
 ( vector< pair<int,char> >& v, int lower, int upper, int& pivot );
// precondition: upper - lower > 0
// takes v[lower] as pivot and interchanges elements so that
// v[i].first <= v[pivot].first for all i < pivot, and
// v[i].first > v[pivot].first for all i > pivot,
// where lower <= pivot <= upper

int main()
{
   cout << "give n : ";
   int n; cin >> n;

   srand(time(0));
   vector< pair<int,char> > v = random_vector(n);
   cout << n << " random items : ";
   write_vector(v,0,n-1); cout << endl;

   int lower = 0;
   int upper = n-1;
   int pivot = 0;
   if(n > 1) partition(v,lower,upper,pivot);
   cout << "pivot = " << pivot << endl;

   cout << "the partitioned vector : " << endl;
   cout << "-> first half : ";
   write_vector(v,0,pivot-1); cout << endl;
   cout << "-> the pivot : ";
   write_vector(v,pivot,pivot); cout << endl;
   cout << "-> second half : ";
   write_vector(v,pivot+1,upper); cout << endl;

   return 0;
}

vector< pair<int,char> > random_vector ( int n )
{
   vector< pair<int,char> > v;

   for(int i=0; i<n; i++)
   {
      pair<int,char> p;
      p.first = 10 + (rand() % 90);
      p.second = 'a' + rand() % 26;
      v.push_back(p);
   }

   return v;
}

void write_vector ( vector< pair<int,char> > v, int lower, int upper )
{
   for(int i=lower; i<=upper; i++)
      cout << "(" << v[i].first
           << "," << v[i].second
           << ")";
}

void partition
 ( vector< pair<int,char> >& v, int lower, int upper, int& pivot )
{
   pair<int,char> x = v[lower];

   int up = lower+1; // index will go up 
   int down = upper; // index will go down

   while(up < down)
   {
      while((up < down) && (v[up].first <= x.first)) up++;
      while((up < down) && (v[down].first > x.first)) down--;

      if(up == down) break;

      cout << "swapping " << up << " with " << down << endl;
      pair<int,char> tmp = v[up];
      v[up] = v[down]; v[down] = tmp;
   }
   cout << "up = " << up << "  down = " << down << endl;
   if(v[up].first > x.first) up--;
   cout << "moving pivot to " << up << endl;
   v[lower] = v[up]; v[up] = x;
   pivot = up;
}

