#include <iostream>
#include <vector>
#include <list>
#include <algorithm>     // for lower_bound and is_sorted
#include <random>        // for random number generation
#include <chrono>        // for timing
using namespace std;

void insertIntoVector(vector<int>& vec, int n)
{
    minstd_rand generator; 
    uniform_int_distribution<int> distribution(1, n);

    for (int i = 0; i < n; ++i)
    {
        int value = distribution(generator);
        auto position = lower_bound(vec.begin(), vec.end(), value);
        vec.insert(position, value);
    }
    if (!is_sorted(vec.begin(), vec.end()))
        cout << "Warning: Vector is not sorted!\n";
}

void insertIntoList(list<int>& lst, int n)
{
    minstd_rand generator;
    uniform_int_distribution<int> distribution(1, n);
    for (int i = 0; i < n; ++i)
    {
        int value = distribution(generator);
        auto position = find_if(lst.begin(), lst.end(),
                                [value](int x){ return x >= value; });
        lst.insert(position, value);
    }
    vector<int> tmp(lst.begin(), lst.end());
    if (!is_sorted(tmp.begin(), tmp.end()))
        cout << "Warning: List is not sorted!\n";
}

double measureVector(int n)
{
    vector<int> vec(n);
    for (int i = 0; i < n; ++i)
        vec[i] = i + 1;

    auto start = chrono::high_resolution_clock::now();
    insertIntoVector(vec, n);
    auto end = chrono::high_resolution_clock::now();
    chrono::duration<double> elapsed = end - start;

    cout << "Vector final size: " << vec.size()
         << ", is_sorted: " << boolalpha
         << is_sorted(vec.begin(), vec.end()) << endl;

    return elapsed.count();
}

double measureList(int n)
{
    list<int> lst;
    for (int i = 1; i <= n; ++i)
        lst.push_back(i);

    auto start = chrono::high_resolution_clock::now();
    insertIntoList(lst, n);
    auto end = chrono::high_resolution_clock::now();
    chrono::duration<double> elapsed = end - start;

    vector<int> tmp(lst.begin(), lst.end());
    cout << "List final size:   " << lst.size()
         << ", is_sorted: " << boolalpha
         << is_sorted(tmp.begin(), tmp.end()) << endl;

    return elapsed.count();
}

int main()
{
    int testSizes[] = {1000, 5000, 10000};

    for (int i = 0; i < 3; ++i)
    {
        int n = testSizes[i];
        cout << "--- n = " << n << " ---" << endl;

        double timeVec = measureVector(n);
        double timeList = measureList(n);

        cout << "Vector time: " << timeVec << " seconds" << endl;
        cout << "List time:   " << timeList << " seconds" << endl;
        cout << endl;
    }
    return 0;
}
