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

//Print function for vector, passes by reference so a copy
//is not made slowly.
void printV(vector<int> &v){
    for(int element: v){
        cout << element << " ";
    }
    cout << "\n";
}

int main(){

    //default constructor manually
    vector<int> vec1 = {1,2,3};
    printV(vec1);

    //initialize a vector of size 10, (int default value is 0)
    vector<int> vec2(10);
    printV(vec2);

    //initialize the vector of size 10, (default value is now 7)
    vector<int> vec3(10,7);
    printV(vec3);

    cout << "------------------\n";
    //initialize a vector, print it, increment a value in the vector
    vector<int> vec4(5,1);
    printV(vec4);
    vec4[3]++;
    printV(vec4);

    //swap works on indices of a vector
    vector<int> vec5 = {1,2,3,4};
    swap(vec5[0],vec5[2]);
    printV(vec5);

    //set a vector of [0,1,2,3,4,5,6,7,8,9]
    vector<int> vec6(10);
    for(int i = 0; i < vec6.size(); i++){
        vec6[i] = i;
    }

    printV(vec6);

    //reverse manually, we will reverse vec6
    for(int i = 0; i < vec6.size()/2; i++){
        int index1 = i;
        int index2 = vec6.size()-i-1;
        swap(vec6[index1],vec6[index2]);
    }
    printV(vec6);
    //reverse it back using the built in c++ reverse function
    reverse(vec6.begin(),vec6.end());

    printV(vec6);

    vector<int> vec7 = {1,5,7,3,2,6,7,8,3,2,5,4};
    //sort is built in to c++
    sort(vec7.begin(),vec7.end());
    printV(vec7);


    //make an empty vector of ints
    vector<int> vec8;
    vec8.push_back(7);
    vec8.push_back(5);
    vec8.push_back(123);
    printV(vec8);

    vec8.pop_back();
    printV(vec8);
    //lets empty the vec5, you can also use .clear() which will do the same thing
    vector<int> vec5copy = vec5;
    while(vec5.size()){
        vec5.pop_back();
    }

    //just to show its being printed but is empty
    cout << "[";
    printV(vec5);
    cout << "]\n";

    //erase given index erases that value, realy slow
    while(vec5copy.size()){
        vec5copy.erase(vec5copy.begin());
    }

    printV(vec5copy);



    //VECTORS OF PAIRS;
    vector<pair<int,int>> supercoolvector;
    //initalize a bunch of pairs manually
    pair<int,int> mypair(10,15);
    pair<int,int> otherpair(7,5);
    pair<int,int> thirdpair(7,3);

    //push them to the back manually
    supercoolvector.push_back(mypair);
    supercoolvector.push_back(otherpair);
    supercoolvector.push_back(thirdpair);

    //you can also push back a pair created by make pair
    supercoolvector.push_back(make_pair(9,3));

    //the "best" way to do it
    //emplace back will call the constructor for a pair and then push it to the back.
    supercoolvector.emplace_back(1,2);
    supercoolvector.emplace_back(3,4);
    for(pair<int,int> p: supercoolvector){
        cout << p.first << " " << p.second << "\n";
    }

    cout << "------------------------\n";
    //even more complicated use of .emplace_back(), we can make a vector of vectors
    //sometimes called a 2D vector
    vector<vector<int>> vecofvecs;
    vecofvecs.emplace_back(5,2);
    vecofvecs.emplace_back(7,3);
    vecofvecs.emplace_back(3,7);
    for(int i = 0; i < vecofvecs.size(); i++){
        //the vector at the index i of vecofvecs can be passed into our printV function.
        printV(vecofvecs[i]);
    }

    return 0;
}
