#include <iostream>
#include <cstring>

using namespace std;

struct OperationCounter
{
    int eqTest, ltTest, gtTest;
    int mul, div, mod, add, inc;
    int assign, deref;
    int memAlloc, memFree;

    OperationCounter() { reset(); }

    void reset() { memset(this, 0, sizeof(*this)); }

    void print()
    {
        cout << "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << endl;
        cout << "    equality tests : " << eqTest   << endl;
        cout << "   less than tests : " << ltTest   << endl;
        cout << "greater than tests : " << gtTest   << endl;
        cout << "   multiplications : " << mul      << endl;
        cout << "         divisions : " << div      << endl;
        cout << "        modulo ops : " << mod      << endl;
        cout << "         additions : " << add      << endl;
        cout << "        increments : " << inc      << endl;
        cout << "       assignments : " << assign   << endl;
        cout << "      dereferences : " << deref    << endl;
        cout << "       allocations : " << memAlloc << endl;
        cout << "     deallocations : " << memFree  << endl;
        cout << "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=" << endl;
    }

} opc1, opc2;

int gcd(int a, int b)
{
    opc1.assign += 2;
    opc1.eqTest++;

    if (b == 0)
        return a;
    else
    {
        opc1.mod++;

        return gcd(b, a % b);
    }
}

int lcm(int a, int b)
{
    opc1.assign += 2;

    opc1.mul++;
    opc1.div++;

    return a * b / gcd(a, b);
}

int lcmOfList1(const int * list, int size)
{
    opc1.assign ++;
    opc1.deref ++;

    int ret = list[0];

    opc1.assign ++;

    for (int i = 1; i < size; ++ i)
    {
        opc1.ltTest ++;
        opc1.inc ++;

        opc1.assign ++;
        opc1.deref ++;

        ret = lcm(ret, list[i]);
    }

    return ret;
}

int lcmOfList2(const int * list, int size)
{
    opc2.memAlloc ++;

    int * newList = new int[size];

    opc2.assign ++;

    for (int i = 0; i < size; ++ i)
    {
        opc2.ltTest ++;
        opc2.inc ++;

        opc2.deref += 2;
        opc2.assign ++;

        newList[i] = list[i];
    }

    int min, max, imin, cur;

    while (true)
    {
        opc2.assign += 3;
        opc2.deref ++;

        min = max = newList[0];
        imin = 0;

        opc2.assign ++;

        for (int i = 1; i < size; ++ i)
        {
            opc2.ltTest ++;
            opc2.inc ++;

            opc2.assign ++;
            opc2.deref ++;

            cur = newList[i];

            opc2.gtTest ++;

            if (min > cur)
            {
                opc2.assign += 2;

                min = cur;
                imin = i;
            }

            opc2.ltTest ++;

            if (max < cur)
            {
                opc2.assign ++;

                max = cur;
            }
        }

        opc2.eqTest ++;

        if (min == max) break;

        opc2.deref +=2 ;
        opc2.add ++;
        opc2.assign ++;

        newList[imin] += list[imin];
    }

    opc2.deref ++;
    opc2.assign ++;

    int ret = newList[0];

    opc2.memFree ++;

    delete[] newList;

    return ret;
}

int main()
{
    enum { size = 5 };

    int nList[size] = { 2, 3, 5, 7, 11 };

    cout << "method 1 result : " << lcmOfList1(nList, size) << endl;
    cout << "method 1 stats  : " << endl;
    opc1.print();

    cout << endl;

    cout << "method 2 result : " << lcmOfList2(nList, size) << endl;
    cout << "method 2 stats  : " << endl;
    opc2.print();
}