#pragma once
#include <iostream>
#include <vector>
#include <algorithm>
using std::copy;
using std::vector;
using std::find;
using std::sort;
class Set {
public:
Set() {}
explicit Set(vector<int64_t> v) {
this->Copy(v);
}
Set& operator=(Set other) {
this->Copy(other.Data());
return *this;
}
vector<int64_t> Data() { return this->list; }
void Add(int64_t value) {
this->list.push_back(value);
}
void Remove(int64_t value) {
vector<int64_t>::iterator idx = this->Index(value);
if (idx == this->list.end()) return;
this->list.erase(idx);
this->list.resize(this->list.size() - 1);
}
bool Contains(int64_t value) {
if (this->Index(value) == this->list.end())
return false;
return true;
}
Set Union(Set other) {
vector<int64_t> res, second = other.Data();
res.reserve(this->list.size() + second.size());
res.insert(res.end(), this->list.begin(), this->list.end() );
res.insert(res.end(), second.begin(), second.end());
return Set(res);
}
Set Intersection(Set other) {
vector<int64_t> res;
for (auto k : other.Data())
if (this->Contains(k))
res.push_back(k);
sort(res.begin(), res.end());
return Set(res);
}
Set Difference(Set other) {
vector<int64_t> res;
for (auto k : this->list)
if (!other.Contains(k))
res.push_back(k);
sort(res.begin(), res.end());
return Set(res);
}
Set SymmetricDifference(Set other) {
vector<int64_t> res;
for (auto k : other.Data())
if (!this->Contains(k))
res.push_back(k);
for (auto k : this->list)
if (!other.Contains(k))
res.push_back(k);
sort(res.begin(), res.end());
return Set(res);
}
private:
vector<int64_t> list;
void Copy(vector<int64_t> v) {
this->list.resize(v.size());
copy(v.begin(), v.end(), this->list.begin());
}
vector<int64_t>::iterator Index(int64_t value) {
auto idx = find(this->list.begin(), this->list.end(), value);
return idx;
}
};