#ifndef _hashset_h
#define _hashset_h
#include <iostream>
#include "hashmap.h"
#include "vector.h"
template <typename ValueType>
class HashSet {
public:
HashSet();
virtual ~HashSet();
int size() const;
bool isEmpty() const;
void add(const ValueType & value);
void insert(const ValueType & value);
void remove(const ValueType & value);
bool contains(const ValueType & value) const;
bool isSubsetOf(const HashSet & set2) const;
void clear();
bool operator==(const HashSet & set2) const;
bool operator!=(const HashSet & set2) const;
HashSet operator+(const HashSet & set2) const;
HashSet operator+(const ValueType & element) const;
HashSet operator*(const HashSet & set2) const;
HashSet operator-(const HashSet & set2) const;
HashSet operator-(const ValueType & element) const;
HashSet & operator+=(const HashSet & set2);
HashSet & operator+=(const ValueType & value);
HashSet & operator*=(const HashSet & set2);
HashSet & operator-=(const HashSet & set2);
HashSet & operator-=(const ValueType & value);
ValueType first() const;
std::string toString();
void mapAll(void (*fn)(ValueType)) const;
void mapAll(void (*fn)(const ValueType &)) const;
template <typename FunctorType>
void mapAll(FunctorType fn) const;
private:
HashMap<ValueType,bool> map;
bool removeFlag;
public:
HashSet & operator,(const ValueType & value) {
if (this->removeFlag) {
this->remove(value);
} else {
this->add(value);
}
return *this;
}
class iterator : public std::iterator<std::input_iterator_tag,ValueType> {
private:
typename HashMap<ValueType,bool>::iterator mapit;
public:
iterator() {
}
iterator(typename HashMap<ValueType,bool>::iterator it) : mapit(it) {
}
iterator(const iterator & it) {
mapit = it.mapit;
}
iterator & operator++() {
++mapit;
return *this;
}
iterator operator++(int) {
iterator copy(*this);
operator++();
return copy;
}
bool operator==(const iterator & rhs) {
return mapit == rhs.mapit;
}
bool operator!=(const iterator & rhs) {
return !(*this == rhs);
}
ValueType operator*() {
return *mapit;
}
ValueType *operator->() {
return mapit;
}
};
iterator begin() const {
return iterator(map.begin());
}
iterator end() const {
return iterator(map.end());
}
};
extern void error(std::string msg);
template <typename ValueType>
HashSet<ValueType>::HashSet() {
}
template <typename ValueType>
HashSet<ValueType>::~HashSet() {
}
template <typename ValueType>
int HashSet<ValueType>::size() const {
return map.size();
}
template <typename ValueType>
bool HashSet<ValueType>::isEmpty() const {
return map.isEmpty();
}
template <typename ValueType>
void HashSet<ValueType>::add(const ValueType & value) {
map.put(value, true);
}
template <typename ValueType>
void HashSet<ValueType>::insert(const ValueType & value) {
map.put(value, true);
}
template <typename ValueType>
void HashSet<ValueType>::remove(const ValueType & value) {
map.remove(value);
}
template <typename ValueType>
bool HashSet<ValueType>::contains(const ValueType & value) const {
return map.containsKey(value);
}
template <typename ValueType>
void HashSet<ValueType>::clear() {
map.clear();
}
template <typename ValueType>
bool HashSet<ValueType>::isSubsetOf(const HashSet & set2) const {
iterator it = begin();
iterator end = this->end();
while (it != end) {
if (!set2.map.containsKey(*it)) return false;
++it;
}
return true;
}
template <typename ValueType>
bool HashSet<ValueType>::operator==(const HashSet & set2) const {
return this->isSubsetOf(set2) && set2.isSubsetOf(*this);
}
template <typename ValueType>
bool HashSet<ValueType>::operator!=(const HashSet & set2) const {
return !(*this == set2);
}
template <typename ValueType>
HashSet<ValueType> HashSet<ValueType>::operator+(const HashSet & set2) const {
HashSet<ValueType> set = *this;
foreach (ValueType value in set2) {
set.add(value);
}
return set;
}
template <typename ValueType>
HashSet<ValueType>
HashSet<ValueType>::operator+(const ValueType & element) const {
HashSet<ValueType> set = *this;
set.add(element);
return set;
}
template <typename ValueType>
HashSet<ValueType> HashSet<ValueType>::operator*(const HashSet & set2) const {
HashSet<ValueType> set;
foreach (ValueType value in *this) {
if (set2.map.containsKey(value)) set.add(value);
}
return set;
}
template <typename ValueType>
HashSet<ValueType> HashSet<ValueType>::operator-(const HashSet & set2) const {
HashSet<ValueType> set;
foreach (ValueType value in *this) {
if (!set2.map.containsKey(value)) set.add(value);
}
return set;
}
template <typename ValueType>
HashSet<ValueType>
HashSet<ValueType>::operator-(const ValueType & element) const {
HashSet<ValueType> set = *this;
set.remove(element);
return set;
}
template <typename ValueType>
HashSet<ValueType> & HashSet<ValueType>::operator+=(const HashSet & set2) {
foreach (ValueType value in set2) {
this->add(value);
}
return *this;
}
template <typename ValueType>
HashSet<ValueType> & HashSet<ValueType>::operator+=(const ValueType & value) {
this->add(value);
this->removeFlag = false;
return *this;
}
template <typename ValueType>
HashSet<ValueType> & HashSet<ValueType>::operator*=(const HashSet & set2) {
Vector<ValueType> toRemove;
foreach (ValueType value in *this) {
if (!set2.map.containsKey(value)) toRemove.add(value);
}
foreach (ValueType value in toRemove) {
this->remove(value);
}
return *this;
}
template <typename ValueType>
HashSet<ValueType> & HashSet<ValueType>::operator-=(const HashSet & set2) {
Vector<ValueType> toRemove;
foreach (ValueType value in *this) {
if (set2.map.containsKey(value)) toRemove.add(value);
}
foreach (ValueType value in toRemove) {
this->remove(value);
}
return *this;
}
template <typename ValueType>
HashSet<ValueType> & HashSet<ValueType>::operator-=(const ValueType & value) {
this->remove(value);
this->removeFlag = true;
return *this;
}
template <typename ValueType>
ValueType HashSet<ValueType>::first() const {
if (isEmpty()) error("first: set is empty");
return *begin();
}
template <typename ValueType>
std::string HashSet<ValueType>::toString() {
ostringstream os;
os << *this;
return os.str();
}
template <typename ValueType>
void HashSet<ValueType>::mapAll(void (*fn)(ValueType)) const {
map.mapAll(fn);
}
template <typename ValueType>
void HashSet<ValueType>::mapAll(void (*fn)(const ValueType &)) const {
map.mapAll(fn);
}
template <typename ValueType>
template <typename FunctorType>
void HashSet<ValueType>::mapAll(FunctorType fn) const {
map.mapAll(fn);
}
template <typename ValueType>
std::ostream & operator<<(std::ostream & os, const HashSet<ValueType> & set) {
os << "{";
bool started = false;
foreach (ValueType value in set) {
if (started) os << ", ";
writeGenericValue(os, value, true);
started = true;
}
os << "}";
return os;
}
template <typename ValueType>
std::istream & operator>>(std::istream & is, HashSet<ValueType> & set) {
char ch;
is >> ch;
if (ch != '{') error("operator >>: Missing {");
set.clear();
is >> ch;
if (ch != '}') {
is.unget();
while (true) {
ValueType value;
readGenericValue(is, value);
set += value;
is >> ch;
if (ch == '}') break;
if (ch != ',') {
error(std::string("operator >>: Unexpected character ") + ch);
}
}
}
return is;
}
#endif