/* set.h -- Matt Mahoney, mmahoney@cs.fit.edu set.h defines a Set class. A Set supports the following operations: Set() // Empty set, {} Set(x) // Implicit conversion of x (type T) to {x} a+b // Union (elements in either a or b) a*b // Intersection (elements in both a and b) a-b // Difference (elements in a but not b) a+=b, a-=b, a*=b // Equivalent to a=a+b, a=a-b, a=a*b a==b // Set equality a<=b // true if a is a subset of b ab, a!=b, a>=b // Equivalent to !(b<=a), b containing only x (e.g {x}) in any of the above expressions where a Set is expected. */ #include #include // NO using namespace std; template class Set { private: typedef std::map M; typedef M::const_iterator CI; M m; // The elements are the keys of s (ignoring values) public: Set(): m() {} Set(const T& x): m() {m[x]=true;} Set& operator += (const Set& b); // Union Set& operator -= (const Set& b); // Difference Set& operator *= (const Set& b); // Intersection bool in(const T& x) const {return m.find(x)!=m.end();} // x is element? int size() const {return m.size();} // Number of elements void print(std::ostream& out) const; // Print in format {x,y,...} to out }; // Code for members +, -, * template Set& Set::operator += (const Set& b) { // Union for (CI p=b.m.begin(); p!=b.m.end(); ++p) m[p->first]=true; return *this; } template Set& Set::operator -= (const Set& b) { // Difference M r; for (CI p=m.begin(); p!=m.end(); ++p) if (!b.in(p->first)) r[p->first]=true; m=r; return *this; } template Set& Set::operator *= (const Set& b) { // Intersection M r; for (CI p=m.begin(); p!=m.end(); ++p) if (b.in(p->first)) r[p->first]=true; m=r; return *this; } // Output helper template void Set::print(std::ostream& out) const { out << "{"; for (CI p=m.begin(); p!=m.end(); ++p) { if (p!=m.begin()) out << ","; out << p->first; } out << "}"; } // Nonmember binary set operations template Set operator+(Set a, const Set& b) {return a+=b;} template Set operator-(Set a, const Set& b) {return a-=b;} template Set operator*(Set a, const Set& b) {return a*=b;} template bool operator<=(const Set& a, const Set& b) {return (a-b).size()==0;} template bool operator==(const Set& a, const Set& b) {return a<=b && b<=a;} template bool operator!=(const Set& a, const Set& b) {return !(a==b);} template bool operator>=(const Set& a, const Set& b) {return b<=a;} template bool operator< (const Set& a, const Set& b) {return a<=b && !(b<=a);} template bool operator> (const Set& a, const Set& b) {return b<=a && !(a<=b);} // Output template std::ostream& operator << (std::ostream& out, const Set& st) { st.print(out); return out; } // Define binary operators with implicit conversions on the left or right #define op(r, x) \ template r operator x (const T& a, const Set& b) {return Set(a) x b;} \ template r operator x (const Set& a, const T& b) {return a x Set(b);} op(Set, +) op(Set, -) op(Set, *) op(bool, <) op(bool, <=) op(bool, >) op(bool, >=) op(bool, ==) op(bool, !=) #undef op