/*
 * Marc Groenewegen, 2023
 */

#include <iostream>
#include <algorithm> // for using sort()
#include <vector>
#include <iterator>



int main()
{
std::vector<long> v;
std::vector<long>::iterator pos;

  std::cout << "Vector contains " << v.size() << " elements" << std::endl;

  std::cout << "Vector capacity " << v.capacity() << std::endl;

  v.push_back(110);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(105);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(100);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(101);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(106);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(106);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(102);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(108);
  std::cout << "Vector capacity " << v.capacity() << std::endl;
  v.push_back(103);
  std::cout << "Vector capacity " << v.capacity() << std::endl;

  std::cout << "Look closely at how the capacity grows. Can you explain?" << std::endl;

  std::cout << "Vector contains " << v.size() << " elements" << std::endl;
  std::cout << "First element: " << v.front() << std::endl;
  std::cout << "Last element: " << v.back() << std::endl;

  std::cout << "Element 3: " << v[3] << std::endl;

  std::cout << "Last element " << v.back() <<
               " is popped off the vector." << std::endl;
  v.pop_back();

  /* vector::end() returns an iterator referring to the past-the-end element
     which is the theoretical element that would follow the last element
     in the vector.
     It does not point to any element, and thus shall not be dereferenced.
  */
  std::cout << "Vector contents:\n";
  pos=v.begin();
  while(pos != v.end()){
    std::cout << *pos << " ";
    pos++;
  } // while

  std::cout << std::endl;

  /* Sort vector
   *
   * Incremental sorting of standard types like int, float, string etc. can
   * be done without specifying a compare function, because '<' is available
   * for these types.
   *
   * For reverse sorting of standard types, std::greater() can be used
   * while std::less() is the same as incremental sort and does not have to
   * be specified.
   *
   * If you want to sort other than the standard types you need to provide
   * a compare function or provide '<' operator for the class (see operator
   * overloading and an example in event_set.cpp).
   */
  sort(v.begin(),v.end());

  // Show it again
  std::cout << "Vector after sorting with the function sort():\n";
  pos=v.begin();
  while(pos != v.end()){
    std::cout << *pos << " ";
    pos++;
  } // while

  std::cout << std::endl;

  // Sort vector backwards
  sort(v.begin(),v.end(),std::greater<long>());

  // Show it again
  std::cout << "Vector after reverse sorting:\n";
  pos=v.begin();
  while(pos != v.end()){
    std::cout << *pos << " ";
    pos++;
  } // while

  std::cout << std::endl;

  std::cout << "Jump to position 3 by adding a number to the iterator\n";
  pos=v.begin() + 3;
  while(pos != v.end()){
    std::cout << *pos << " ";
    pos++;
  } // while

  std::cout << std::endl;

  // make vector empty
  if(v.empty()){
    std::cout << "Vector is empty before clearing\n";
  }
  v.clear();
  if(v.empty()){
    std::cout << "Vector is empty after clearing\n";
  }
  std::cout << "Vector capacity " << v.capacity() << std::endl;

  std::cout << std::endl;

  return 0;
} // main()
