#include <set>
#include <iostream>
template <typename ObType, typename BinaryFunction>
bool isGroup(const std::set<ObType> & S, BinaryFunction & op)
{
/*
isGroup returns true or false depending on whether the set S
along with the operator op is a group in the Algebraic sense.
That is, S is a group if and only if all the 4 following
conditions are true:
(1) If a, b in S, then a op b in S
(2) If a, b, c in S, then (a + b) + c = a + (b + c)
(3) There is an element 0 in S such that a + 0 = 0 + a for all a in S
(4) If a in S, then there is a b in S such that a + b = b + a = 0
*/
typename std::set<ObType>::const_iterator beg(S.cbegin()), offend(S.cend());
bool noProblemsYet(true), foundIdentity(false);
ObType iden;
for (typename std::set<ObType>::const_iterator ia = beg; ia != offend && noProblemsYet; ++ia)
{
bool isIdentity = true;
for (typename std::set<ObType>::const_iterator ib = beg; ib != offend && noProblemsYet; ++ib)
{
// ---------- (1) --------------
if (S.count(op(*ia, *ib)) == 0)
noProblemsYet = false;
// ---------- (3) --------------
if (op(*ia, *ib) != op(*ib, *ia))
isIdentity = false;
// -----------------------------
for (typename std::set<ObType>::const_iterator ic = beg; ic != offend && noProblemsYet; ++ic)
{
// ---------- (2) -------------
if (op(op(*ia, *ib), *ic) != op(*ia, op(*ib, *ic)))
noProblemsYet = false;
// ----------------------------
}
}
if (isIdentity)
{
foundIdentity = true;
iden = *ia;
}
}
if (noProblemsYet)
{
if (!foundIdentity)
noProblemsYet = false;
for (typename std::set<ObType>::const_iterator ia = beg; ia != offend && noProblemsYet; ++ia)
{
bool foundInverse = false;
for (typename std::set<ObType>::const_iterator ib = beg; ib != offend && noProblemsYet; ++ib)
{
if (op(*ia, *ib) == op(*ib, *ia) && op(*ia, *ib) == iden)
{
foundInverse = true;
break;
}
}
// ---------- (4) -------------
if (!foundInverse)
noProblemsYet = false;
// ----------------------------
}
}
return noProblemsYet;
}
/* ----------------------------- Functors --------------------------------------*/
template <typename T>
class Adder
{
private:
static const char symbol = '+';
public:
T operator() (const T & x, const T & y) { return x + y; };
char getSymbol(void) { return symbol; };
};
template <typename T>
class Subtracter
{
private:
static const char symbol = '-';
public:
T operator() (const T & x, const T & y) { return x - y; };
char getSymbol(void) { return symbol; };
};
template <typename T>
class Multiplier
{
private:
static const char symbol = '*';
public:
T operator() (const T & x, const T & y) { return x * y; };
char getSymbol(void) { return symbol; };
};
template <typename T>
class Divider
{
private:
static const char symbol = '/';
public:
T operator() (const T & x, const T & y) { return x / y; };
char getSymbol(void) { return symbol; };
};
template <typename T>
class Modder
{
private:
static const char symbol = '%';
public:
T operator() (const T & x, const T & y) { return x % y; };
char getSymbol(void) { return symbol; };
};
/* ------------------------------------------------------------------------------*/
int main()
{
std::set<int> S1 = { 0, 1, -1 };
std::set<int> S2 = { 0 };
class Adder<int> p;
std::cout << isGroup(S1, p);
return 0;
}