#include <iostream>
#include <iomanip>
#include <list>

using namespace std;

/**
 * Fill a sorted list with size values using the factor.
 * @parm lst the list to fill.
 * @parm factor the factor.
 * @parm size the size.
 */
void fill(list<int>& lst, int factor, int size);

/**
 * Insert a value into a sorted list.
 * @parm lst the sorted list.
 * @parm value the value to insert.
 */
void insert_value(list<int>& lst, const int& value);

/**
 * Print a list.
 * @parm lst the list to print.
 */
void print(list<int>& lst);

/**
 * Print a list in reverse.
 * @parm lst the list to print.
 */
void print_reverse(list<int>& lst);

/**
 * Delete value from a sorted list.
 * @parm lst the list.
 * @parm value the value to delete.
 */
void delete_value(list<int>& lst, const int& value);

int main()
{
    list<int> list1, list2;

    cout << "Print list1 forwards and backwards:" << endl;
    fill(list1, 5, 10);
    print(list1);
    print_reverse(list1);

    cout << endl << "Insert into list1 12, -5, and 47:" << endl;
    insert_value(list1, 12);
    insert_value(list1, -5);
    insert_value(list1, 47);
    print(list1);

    cout << endl << "Delete from list1 20, -5, 33, and 47:" << endl;
    delete_value(list1, 20);
    delete_value(list1, -5);
    delete_value(list1, 47);
    print(list1);

    cout << endl << "Print list2:" << endl;
    fill(list2, 10, 10);
    print(list2);

    cout << endl << "Merge list2 into list1:" << endl;
    list1.merge(list2);
    cout << "list1:"; print(list1);
    cout << "list2:"; print(list2);

    cout << endl << "Remove all 10s from list1:" << endl;
    list1.remove(10);
    print(list1);

    cout << endl << "Remove duplicate values:" << endl;
    list1.unique();
    print(list1);

    return 0;
}

void fill(list<int>& lst, int factor, int size)
{
    for (int i = 0; i < size; i++) lst.push_back(i*factor);
}

void insert_value(list<int>& lst, const int& value)
{
    // Look for the insertion point.
    list<int>::iterator it = lst.begin();
    while ((it != lst.end()) && (value > *it)) it++;

    // Insert before the iterator's position.
    lst.insert(it, value);
}

void print(list<int>& lst)
{
    for (auto it = lst.begin(); it != lst.end(); it++) cout << setw(3) << *it;
    cout << endl;
}

void print_reverse(list<int>& lst)
{
    for (auto it = lst.rbegin(); it != lst.rend(); it++) cout << setw(3) << *it;
    cout << endl;
}

void delete_value(list<int>& lst, const int& value)
{
    // Look for the value.
    list<int>::iterator it = lst.begin();
    while ((it != lst.end()) && (value != *it)) it++;

    // Delete the value if it was found.
    if (it != lst.end()) lst.erase(it);
}