School Commit Init

This commit is contained in:
2024-08-31 12:07:21 +03:00
commit 0b130ee18c
2801 changed files with 4720552 additions and 0 deletions
@@ -0,0 +1,17 @@
#include <iostream>
#include "Matrix.h"
#include "ExtendedTest.h"
#include "ShortTest.h"
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "Test End" << endl;
system("pause");
}
@@ -0,0 +1,166 @@
#include <assert.h>
#include "Matrix.h"
#include "ExtendedTest.h"
#include <iostream>
#include <exception>
using namespace std;
void testCreate() {
cout << "Test create" << endl;
Matrix m(10, 10);
assert(m.nrLines() == 10);
assert(m.nrColumns() == 10);
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
assert(m.element(i, j) == NULL_TELEM);
}
void testModify() {
cout << "Test modify" << endl;
Matrix m(10, 10);
for (int j = 0; j < m.nrColumns(); j++)
m.modify(4, j, 3);
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
if (i == 4)
assert(m.element(i, j) == 3);
else
assert(m.element(i, j) == NULL_TELEM);
}
void testQuantity() {
cout << "Test quantity" << endl;
Matrix m(200, 300);
for (int i = m.nrLines() / 2; i < m.nrLines(); i++) {
for (int j = 0; j <= m.nrColumns() / 2; j++)
{
int v1 = j;
int v2 = m.nrColumns() - v1 - 1;
if (i % 2 == 0 && v1 % 2 == 0)
m.modify(i, v1, i*v1);
else
if (v1 % 3 == 0)
m.modify(i, v1, i + v1);
if (i % 2 == 0 && v2 % 2 == 0)
m.modify(i, v2, i*v2);
else
if (v2 % 3 == 0)
m.modify(i, v2, i + v2);
}
}
for (int i = 0; i <= m.nrLines() / 2; i++) {
for (int j = 0; j <= m.nrColumns() / 2; j++)
{
int v1 = j;
int v2 = m.nrColumns() - v1 - 1;
if (i % 2 == 0 && v1 % 2 == 0)
m.modify(i, v1, i*v1);
else
if (v1 % 3 == 0)
m.modify(i, v1, i + v1);
if (i % 2 == 0 && v2 % 2 == 0)
m.modify(i, v2, i*v2);
else
if (v2 % 3 == 0)
m.modify(i, v2, i + v2);
}
}
for (int i = 0; i < m.nrLines(); i++)
for (int j = 0; j < m.nrColumns(); j++)
if (i % 2 == 0 && j % 2 == 0)
assert(m.element(i, j) == i * j);
else
if (j % 3 == 0)
assert(m.element(i, j) == i + j);
else assert(m.element(i, j) == NULL_TELEM);
}
void testExceptions() {
cout << "Test exceptions" << endl;
Matrix m(10, 10);
try {
m.element(-10, 0);
assert(false);
}
catch (exception&) {
assert(true);
}
try {
m.modify(12, 0, 1);
assert(false);
}
catch (exception&) {
assert(true);
}
try {
assert(m.nrLines());
}
catch (exception&) {
assert(false);
}
}
void testMix() {
cout << "Test mix" << endl;
int size = 2000;
Matrix m(size/2, size);
for (int i = 0; i < size/2; i++) {
for (int j = 0; j < size; j++) {
if (i == j) {
m.modify(i, j, 11);
}
else if (i == 100 * j) {
m.modify(i, j, 111);
}
else if ((i + j) % 1111 == 0) {
m.modify(i, j, 1111);
}
}
}
for (int i = 0; i < size/2; i++) {
for (int j = 0; j < size; j++) {
if (i == j) {
TElem old = m.modify(i, j, NULL_TELEM);
assert(old == 11);
}
else if (i == 100 * j) {
TElem old = m.modify(i, j, -111);
assert(old == 111);
}
else if ((i + j) % 1111 == 3) {
m.modify(i, j, 1);
}
}
}
for (int i = 0; i < size/2; i++) {
for (int j = 0; j < size; j++) {
TElem e = m.element(i, j);
if (i == j) {
assert(e == NULL_TELEM);
}
else if (i == 100 * j) {
assert(e == -111);
}
else if ((i + j) % 1111 == 3) {
assert(e == 1);
}
else if ((i + j) % 1111 == 0) {
assert(e == 1111);
}
else {
assert(e == NULL_TELEM);
}
}
}
}
void testAllExtended() {
testCreate();
testModify();
testQuantity();
testMix();
testExceptions();
}
@@ -0,0 +1,4 @@
#pragma once
#include "ExtendedTest.h"
void testAllExtended();
@@ -0,0 +1,81 @@
#include "Matrix.h"
#include <exception>
using namespace std;
Matrix::Matrix(int nrLines, int nrColumns) {
// Theta(1)
if (nrLines <= 0 || nrColumns <= 0) {
throw exception();
}
this->numberOfLines = nrLines;
this->numberOfColumns = nrColumns;
this->values = new TElem[nrLines * nrColumns];
this->lines = new int[nrLines * nrColumns];
this->columns = new int[nrColumns+1];
for (int i = 0; i < nrColumns+1; i++) {
this->columns[i] = 0;
}
}
int Matrix::nrLines() const {
// Theta(1)
return this->numberOfLines;
}
int Matrix::nrColumns() const {
// Theta(1)
return this->numberOfColumns;
}
TElem Matrix::element(int i, int j) const {
// Best: theta(1) | Worst: theta( nr of non-zero elements in the column) | Total: theta( nr of non-zero elements in the column)
if(i>=this->numberOfLines || j>=this->numberOfColumns || i<0 || j<0)
throw exception();
for(int k=0;k<this->columns[j+1]-this->columns[j];k++){
if(this->lines[k+this->columns[j]]==i)
return this->values[k+this->columns[j]];
}
return NULL_TELEM;
}
TElem Matrix::modify(int i, int j, TElem e) {
// Best: theta(1) | Worst: theta( nr of rows + nr of non zero values + nr of non zero values in the column) | Total: theta( nr of rows + nr of non zero values + nr of non zero values in the column)
if(i>=this->numberOfLines || j>=this->numberOfColumns || i<0 || j<0)
throw exception();
for(int k=0;k<this->columns[j+1]-this->columns[j];k++){
if(this->lines[k+this->columns[j]]==i){
swap(this->values[k+this->columns[j]],e);
return e;
}
}
for(int k=this->columns[this->numberOfColumns];k>this->columns[j];k--){
swap(this->lines[k],this->lines[k-1]);
swap(this->values[k],this->values[k-1]);
}
this->lines[this->columns[j]]=i;
this->values[this->columns[j]]=e;
for(int k=j+1;k<=this->numberOfColumns;k++)
this->columns[k]++;
return NULL_TELEM;
}
void Matrix::setMainDiagonal(TElem e) {
// Theta(min(nr of rows,nr of cols))
int length = this->numberOfLines;
if (this->numberOfColumns < this->numberOfLines) {
length = this->numberOfColumns;
}
for (int i = 0; i < length; i++) {
this->modify(i, i, e);
}
}
@@ -0,0 +1,39 @@
#pragma once
//DO NOT CHANGE THIS PART
typedef int TElem;
#define NULL_TELEM 0
class Matrix {
private:
//TODO - Representation
TElem* values;
int* lines;
int* columns;
int numberOfLines;
int numberOfColumns;
public:
//constructor
Matrix(int nrLines, int nrCols);
//returns the number of lines
int nrLines() const;
//returns the number of columns
int nrColumns() const;
//returns the element from line i and column j (indexing starts from 0)
//throws exception if (i,j) is not a valid position in the Matrix
TElem element(int i, int j) const;
//modifies the value from line i and column j
//returns the previous value from the position
//throws exception if (i,j) is not a valid position in the Matrix
TElem modify(int i, int j, TElem e);
void setMainDiagonal(TElem e);
};
@@ -0,0 +1,15 @@
#include <assert.h>
#include "Matrix.h"
using namespace std;
void testAll() {
Matrix m(4, 4);
assert(m.nrLines() == 4);
assert(m.nrColumns() == 4);
m.modify(1, 1, 5);
assert(m.element(1, 1) == 5);
TElem old = m.modify(1, 1, 6);
assert(m.element(1, 2) == NULL_TELEM);
assert(old == 5);
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,19 @@
#include "ExtendedTest.h"
#include "ShortTest.h"
#include "SortedMap.h"
#include <iostream>
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "That's all!" << endl;
system("pause");
return 0;
}
Binary file not shown.
@@ -0,0 +1,341 @@
#include <exception>
#include <assert.h>
#include <algorithm>
#include <vector>
#include <iostream>
#include "SortedMap.h"
#include "SMIterator.h"
#include "ExtendedTest.h"
using namespace std;
bool increasing(TKey c1, TKey c2) {
if (c1 <= c2) {
return true;
} else {
return false;
}
}
bool decreasing(TKey c1, TKey c2) {
if (c1 >= c2) {
return true;
} else {
return false;
}
}
void testIteratorSteps(SortedMap& m, Relation r) {
SMIterator li = m.iterator();
TElem elem = NULL_TPAIR;
int count = 0;
if (li.valid()) {
elem = li.getCurrent();
count++;
li.next();
}
while (li.valid()) {
TElem elem2 = li.getCurrent();
assert(r(elem.first, elem2.first));
elem = elem2;
count++;
li.next();
}
assert(count == m.size());
}
void testCreate() {
cout << "Test create" << endl;
SortedMap sm(increasing);
assert(sm.size() == 0);
assert(sm.isEmpty());
SMIterator it = sm.iterator();
it.first();
assert(!it.valid());
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
for (int i = 0; i < 10; i++) {
assert(sm.search(i) == NULL_TVALUE);
}
for (int i = -10; i < 10; i++) {
assert(sm.remove(i) == NULL_TVALUE);
}
}
void testSearch(Relation r) {
cout << "Test search" << endl;
SortedMap sm(r);
int cMin = 0;
int cMax = 10;
try {
for (int i = cMin; i <= cMax; i++) {
sm.add(i, i + 1);
}
assert(true);
} catch (exception&) {
assert(false);
}
int intervalDim = 10;
for (int i = cMin; i <= cMax; i++) {
assert(sm.search(i) == i + 1);
}
testIteratorSteps(sm, r);
for (int i = cMin - intervalDim; i < cMin; i++) {
assert(sm.search(i) == NULL_TVALUE);
}
for (int i = cMax + 1; i < cMax + intervalDim; i++) {
assert(sm.search(i) == NULL_TVALUE);
}
}
void testSearch() {
testSearch(increasing);
testSearch(decreasing);
}
vector<int> keysInRandomOrder(int cMin, int cMax) {
vector<int> keys;
for (int c = cMin; c <= cMax; c++) {
keys.push_back(c);
}
int n = keys.size();
for (int i = 0; i < n - 1; i++) {
int j = i + rand() % (n - i);
swap(keys[i], keys[j]);
}
return keys;
}
void populateSMEmpty(SortedMap& sm, int cMin, int cMax) {
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
assert(sm.add(keys[i], keys[i]) == NULL_TVALUE);
}
}
void rePopulateSMShift(SortedMap& sm, int cMin, int cMax, int shift) {
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
assert(sm.add(keys[i], keys[i] - shift) == keys[i]);
}
}
void populateSMShift(SortedMap& sm, int cMin, int cMax, int shift) {
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
sm.add(keys[i], keys[i] - shift);
}
}
void testAddAndSearch(Relation r) {
cout << "Test add and search" << endl;
SortedMap sm(r);
int cMin = 100;
int cMax = 200;
populateSMEmpty(sm, cMin, cMax);
testIteratorSteps(sm, r);
for (int c = cMin; c <= cMax; c++) {
assert(sm.search(c) == c);
}
assert(sm.size() == (cMax - cMin + 1));
rePopulateSMShift(sm, cMin, cMax, 1);
assert(sm.size() == (cMax - cMin + 1));
testIteratorSteps(sm, r);
populateSMShift(sm, 2 * cMax, 3 * cMax, 2 * cMax - cMin);
for (int c = 2 * cMax; c <= 3 * cMax; c++) {
assert(sm.search(c) == c - 2 * cMax + cMin);
}
testIteratorSteps(sm, r);
assert(sm.size() == (cMax - cMin + 1) + (cMax + 1));
SMIterator it = sm.iterator();
it.first();
if (it.valid()) {
TKey cPrec = it.getCurrent().first;
assert(sm.search(cPrec) != NULL_TVALUE);
it.next();
while (it.valid()) {
TKey c = it.getCurrent().first;
assert(r(cPrec, c));
assert(sm.search(c) != NULL_TVALUE);
cPrec = c;
it.next();
}
}
}
void testAdd() {
testAddAndSearch(increasing);
testAddAndSearch(decreasing);
}
void testRemoveAndSearch(Relation r) {
cout << "Test remove and search" << endl;
SortedMap sm(r);
int cMin = 10;
int cMax = 20;
populateSMEmpty(sm, cMin, cMax);
testIteratorSteps(sm, r);
for (int c = cMax + 1; c <= 2 * cMax; c++) {
assert(sm.remove(c) == NULL_TVALUE);
testIteratorSteps(sm, r);
}
int dim = cMax - cMin + 1;
assert(sm.size() == dim);
for (int c = cMin; c <= cMax; c++) {
assert(sm.remove(c) == c);
assert(sm.search(c) == NULL_TVALUE);
SMIterator it = sm.iterator();
it.first();
if (it.valid()) {
TKey cPrec = it.getCurrent().first;
it.next();
while (it.valid()) {
TKey c = it.getCurrent().first;
assert(r(cPrec, c));
cPrec = c;
it.next();
}
}
dim--;
assert(sm.size() == dim);
}
for (int c = cMin; c <= cMax; c++) {
assert(sm.remove(c) == NULL_TVALUE);
}
assert(sm.isEmpty());
assert(sm.size() == 0);
}
void testRemove() {
testRemoveAndSearch(increasing);
testRemoveAndSearch(decreasing);
}
void testIterator(Relation r) {
cout << "Test iterator" << endl;
SortedMap sm(r);
SMIterator it = sm.iterator();
assert(!it.valid());
it.first();
assert(!it.valid());
int cMin = 100;
int cMax = 300;
vector<int> keys = keysInRandomOrder(cMin, cMax);
int n = keys.size();
for (int i = 0; i < n; i++) {
assert(sm.add(keys[i], keys[n - i - 1]) == NULL_TVALUE);
}
SMIterator itSM = sm.iterator();
assert(itSM.valid());
itSM.first();
assert(itSM.valid());
TKey cPrec = itSM.getCurrent().first;
for (int i=1; i<100; i++){
assert(cPrec == itSM.getCurrent().first);
}
itSM.next();
while (itSM.valid()) {
TKey c = itSM.getCurrent().first;
assert(cMin <= c && c <= cMax);
assert(sm.search(c) != NULL_TVALUE);
assert(r(cPrec, c));
cPrec = c;
itSM.next();
}
}
void testQuantity(){
cout << "Test quantity" << endl;
SortedMap sm(increasing);
int cMin = -3000;
int cMax = 3000;
vector<int> keys = keysInRandomOrder(cMin, cMax);
populateSMEmpty(sm, cMin, cMax);
for (int c = cMin; c <= cMax; c++){
assert(sm.search(c) == c);
}
testIteratorSteps(sm, increasing);
assert(sm.size() == cMax - cMin + 1);
SMIterator it = sm.iterator();
assert(it.valid());
it.first();
assert(it.valid());
for (int i = 0; i < sm.size(); i++) {
it.next();
}
assert(!it.valid());
it.first();
while (it.valid()){
TKey c = it.getCurrent().first;
assert(sm.search(c) == c);
TValue v = it.getCurrent().second;
assert(c == v);
it.next();
}
assert(!it.valid());
for (int c = cMin-100; c <= cMax+100; c++){
sm.remove(c);
assert(sm.search(c) == NULL_TVALUE);
testIteratorSteps(sm, increasing);
}
assert(sm.size() == 0);
assert(sm.isEmpty());
}
void testIterator() {
testIterator(increasing);
testIterator(decreasing);
}
void testExtra(){
cout << "Test extra" << endl;
SortedMap sm(increasing);
sm.add(1, 1);
sm.add(2, 2);
sm.add(3, 3);
sm.add(4, 3);
vector<TValue> v = sm.valueBag();
assert(v.size() == 3);
assert(v[0] == 1);
assert(v[1] == 2);
assert(v[2] == 3);
}
void testAllExtended() {
testCreate();
testAdd();
testSearch();
testRemove();
testIterator();
testQuantity();
testExtra();
}
@@ -0,0 +1,4 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,39 @@
#include "SMIterator.h"
#include "SortedMap.h"
#include <exception>
using namespace std;
SMIterator::SMIterator(const SortedMap& m) : map(m){
//Complexity: O(1)
this->current = this->map.head;
}
void SMIterator::first(){
//Complexity: O(1)
this->current = this->map.head;
}
void SMIterator::next(){
//Complexity: O(1)
if (this->current == nullptr)
throw exception();
this->current = this->current->next;
}
bool SMIterator::valid() const{
//Complexity: O(1)
if(this->current == nullptr)
return false;
return true;
}
TElem SMIterator::getCurrent() const{
//Complexity: O(1)
if(this->current==nullptr)
throw exception();
return this->current->element;
}
@@ -0,0 +1,20 @@
#pragma once
#include "SortedMap.h"
//DO NOT CHANGE THIS PART
class SMIterator{
friend class SortedMap;
private:
const SortedMap& map;
SMIterator(const SortedMap& mapionar);
//TODO - Representation
Node* current;
public:
void first();
void next();
bool valid() const;
TElem getCurrent() const;
};
@@ -0,0 +1,39 @@
#include <assert.h>
#include "SortedMap.h"
#include "SMIterator.h"
#include "ShortTest.h"
#include <exception>
using namespace std;
bool relatie1(TKey cheie1, TKey cheie2) {
if (cheie1 <= cheie2) {
return true;
}
else {
return false;
}
}
void testAll(){
SortedMap sm(relatie1);
assert(sm.size() == 0);
assert(sm.isEmpty());
sm.add(1,2);
assert(sm.size() == 1);
assert(!sm.isEmpty());
assert(sm.search(1)!=NULL_TVALUE);
TValue v =sm.add(1,3);
assert(v == 2);
assert(sm.search(1) == 3);
SMIterator it = sm.iterator();
it.first();
while (it.valid()){
TElem e = it.getCurrent();
assert(e.second != NULL_TVALUE);
it.next();
}
assert(sm.remove(1) == 3);
assert(sm.isEmpty());
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,130 @@
#include "SMIterator.h"
#include "SortedMap.h"
#include <exception>
#include <algorithm>
using namespace std;
SortedMap::SortedMap(Relation r) {
//Complexity: O(1)
this->relation = r;
this->head = nullptr;
this->length = 0;
}
TValue SortedMap::add(TKey k, TValue v) {
//Complexity: O(n) - average/worst O(1) - best
if (this->head == nullptr){
this->head = new Node(pair<TKey, TValue>(k, v));
this->length++;
return NULL_TVALUE;
}
if (this->head->element.first == k){
TValue value = this->head->element.second;
this->head->element.second = v;
return value;
}
if(this->relation(k, this->head->element.first)){
Node* new_node = new Node(pair<TKey, TValue>(k, v));
new_node->next = this->head;
this->head = new_node;
this->length++;
return NULL_TVALUE;
}
Node* previous_node = this->head;
Node* current_node = this->head->next;
for(int i = 0; i < this->length-1; i++){
if (current_node->element.first == k){
TValue value = current_node->element.second;
current_node->element.second = v;
return value;
}
if (this->relation(k, current_node->element.first)){
Node* new_node = new Node(pair<TKey, TValue>(k, v));
new_node->next = current_node;
previous_node->next = new_node;
this->length++;
return NULL_TVALUE;
}
previous_node = current_node;
current_node = current_node->next;
}
previous_node->next = new Node(pair<TKey, TValue>(k, v));
this->length++;
return NULL_TVALUE;
}
TValue SortedMap::search(TKey k) const {
//Complexity: O(n) - average/worst O(1) - best
Node* current_node = this->head;
for(int i = 0; i< this->length; i++){
if (current_node->element.first == k)
return current_node->element.second;
current_node = current_node->next;
}
return NULL_TVALUE;
}
TValue SortedMap::remove(TKey k) {
//Complexity: O(n) - average/worst O(1) - best
if(this->head!=nullptr && this->head->element.first == k){
Node* new_head = this->head->next;
TValue value = this->head->element.second;
delete this->head;
this->head = new_head;
this->length--;
return value;
}
Node* current_node = this->head;
for(int i = 1; i< this->length; i++){
if (current_node->next->element.first == k){
Node* removed_node = current_node->next;
TValue value = removed_node->element.second;
current_node->next = current_node->next->next;
delete removed_node;
this->length--;
return value;
}
current_node = current_node->next;
}
return NULL_TVALUE;
}
int SortedMap::size() const {
//Complexity: O(1)
return this->length;
}
bool SortedMap::isEmpty() const {
//Complexity: O(1)
if (this->length == 0)
return true;
return false;
}
SMIterator SortedMap::iterator() const {
//Complexity: O(1)
return SMIterator(*this);
}
SortedMap::~SortedMap() {
//Complexity: O(n)
Node* current_node = this->head;
for(int i = 0; i < this->length; i++){
Node* next_node = current_node->next;
delete current_node;
current_node = next_node;
}
}
std::vector<TValue> SortedMap::valueBag() {
//Complexity: O(n*m) - average/worst O(n) - best
vector<TValue> values;
Node* current_node = this->head;
for(int i = 0; i < this->length; i++){
if (find(values.begin(), values.end(), current_node->element.second) == values.end())
values.push_back(current_node->element.second);
current_node = current_node->next;
}
return values;
}
@@ -0,0 +1,70 @@
#pragma once
//DO NOT INCLUDE SORTEDMAPITERATOR
#include <vector>
//DO NOT CHANGE THIS PART
typedef int TKey;
typedef int TValue;
#include <utility>
typedef std::pair<TKey, TValue> TElem;
#define NULL_TVALUE -111111
#define NULL_TPAIR pair<TKey, TValue>(-111111, -111111);
class SMIterator;
typedef bool(*Relation)(TKey, TKey);
class Node {
public:
TElem element;
Node* next;
Node(TElem e) {
element = e;
next = nullptr;
}
Node(TElem e, Node* n) {
element = e;
next = n;
}
bool operator==(Node* n) {
return this->element.first == n->element.first;
}
};
class SortedMap {
friend class SMIterator;
private:
//TODO - Representation
Node* head;
Relation relation;
int length;
public:
// implicit constructor
SortedMap(Relation r);
// adds a pair (key,value) to the map
//if the key already exists in the map, then the value associated to the key is replaced by the new value and the old value is returned
//if the key SMes not exist, a new pair is added and the value null is returned
TValue add(TKey c, TValue v);
//searches for the key and returns the value associated with the key if the map contains the key or null: NULL_TVALUE otherwise
TValue search(TKey c) const;
//removes a key from the map and returns the value associated with the key if the key existed ot null: NULL_TVALUE otherwise
TValue remove(TKey c);
//returns the number of pairs (key,value) from the map
int size() const;
//checks whether the map is empty or not
bool isEmpty() const;
// return the iterator for the map
// the iterator will return the keys following the order given by the relation
SMIterator iterator() const;
// destructor
~SortedMap();
std::vector<TValue> valueBag();
};
@@ -0,0 +1,11 @@
#include <iostream>
#include "ShortTest.h"
#include "ExtendedTest.h"
int main(){
testAll();
testAllExtended();
std::cout<<"Finished IL Tests!"<<std::endl;
system("pause");
}
@@ -0,0 +1,387 @@
#include "ExtendedTest.h"
#include <assert.h>
#include <exception>
#include <cstdlib>
#include <vector>
#include <iostream>
#include "ListIterator.h"
#include "SortedIndexedList.h"
using namespace std;
//order relation - ascending
bool asc(TComp c1, TComp c2) {
if (c1 <= c2) {
return true;
} else {
return false;
}
}
//order relation - descending
bool desc(TComp c1, TComp c2) {
if (c1 >= c2) {
return true;
} else {
return false;
}
}
void testIteratorSteps(SortedIndexedList& list, Relation r) {
int count = 0;
ListIterator li = list.iterator();
TComp prev = li.getCurrent();
if (li.valid()) {
count++;
li.next();
}
while (li.valid()) {
TComp current = li.getCurrent();
assert(r(prev, current));
count++;
li.next();
prev = current;
}
assert(count == list.size());
}
void testCreate() {
cout << "Test create" << endl;
SortedIndexedList list = SortedIndexedList(asc);
assert(list.size() == 0);
assert(list.isEmpty());
ListIterator it = list.iterator();
assert(!it.valid());
it.first();
for (int i = 0; i < 10; i++) {
assert(!it.valid());
assert(list.search(i) == -1);
try {
assert(list.getElement(i));
assert(false);
} catch (exception&) {
assert(true);
}
try {
assert(list.remove(i));
assert(false);
} catch (exception&) {
assert(true);
}
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
}
}
//generate a vector with values between cMin and cMax so that
//1) no value that is >=cMin and <=cMax which is a multiple of s is not included
//2) values v, v>=cMin and v<=cMax which are a multiple of m (but not of s) are included c/m + 1 times
//3) values >=cMin and <=cMax are in random order
vector<int> random(int cMin, int cMax, int s, int m) {
vector<int> v;
for (int c = cMin; c <= cMax; c++) {
if (c % s != 0) {
v.push_back(c);
if (c % m == 0) {
for (int j = 0; j < c / m; j++) {
v.push_back(c);
}
}
}
}
int n = v.size();
for (int i = 0; i < n - 1; i++) {
int j = i + rand() % (n - i);
swap(v[i], v[j]);
}
return v;
}
//generate a vector containing values >=cMin and <=cMax, each included one time, in random order
vector<int> random(int cMin, int cMax) {
vector<int> v;
for (int c = cMin; c <= cMax; c++) {
v.push_back(c);
}
int n = v.size();
for (int i = 0; i < n - 1; i++) {
int j = i + rand() % (n - i);
swap(v[i], v[j]);
}
return v;
}
//populate the sorted list with values >=cMin and <=cMax a.i.:
//1) no value that is >=cMin and <=cMax which is a multiple of s is not included
//2) values v, v>=cMin and v<=cMax which are a multiple of m (but not of s) are included c/m + 1 times
//3) values >=cMin and <=cMax are in random order
int populate(SortedIndexedList& list, int cMin, int cMax, int s, int m) {
vector<int> v = random(cMin, cMax, s, m);
int n = v.size();
for (int i = 0; i < n; i++) {
list.add(v[i]);
}
return n;
}
//populate the sorted list with values >=cMin and <=cMax, each included one time, in random order
void populate(SortedIndexedList& list, int cMin, int cMax) {
vector<int> v = random(cMin, cMax);
int n = v.size();
for (int i = 0; i < n; i++) {
list.add(v[i]);
}
}
void testAddAndSearch(Relation r) {
cout << "Test add and search" << endl;
SortedIndexedList list = SortedIndexedList(r);
int vMin = 10;
int vMax = 30;
int s = 5;
int m = 3;
int n = populate(list, vMin, vMax, s, m);
assert(!list.isEmpty());
assert(list.size() == n);
//we can't find values outside the interval or on invalid positions
int d = 30;
for (int i = 1; i <= d; i++) {
assert(list.search(vMin - i) == -1);
assert(list.search(vMax + i) == -1);
try{
list.getElement(n-1+i);
list.getElement(-d);
assert(false);
} catch (exception&) {
assert(true);
}
}
//check the relation order
ListIterator it = list.iterator();
it.first();
assert(it.valid());
TComp prev = it.getCurrent();
it.next();
while (it.valid()) {
TComp current = it.getCurrent();
assert(r(prev, current));
prev = current;
it.next();
}
testIteratorSteps(list, r);
//check if added values can be found
for (int v = vMin; v <= vMax; v++) {
int p = list.search(v);
//we can't find values which are a multiple of s
assert((p != -1) == (v % s != 0));
//values which are a multiple of m can be found exactly v/m+1 times
if (p != -1 && v%m == 0){
for (int i=0; i<=v/m; i++){
try{
assert(list.remove(p) == v);
} catch (exception&) {
assert(false);
}
}
assert(list.search(v) == -1);
}
}
}
void testDeleteSearch(Relation r) {
cout << "Test delete and search" << endl;
SortedIndexedList list = SortedIndexedList(r);
int vMin = 0;
int vMax = 100;
populate(list, vMin, vMax);
int d = 30;
for (int i = 1; i <= d; i++) {
try {
list.remove(list.search(vMax + i));
assert(false);
} catch (exception&) {
assert(true);
}
}
assert(!list.isEmpty());
assert(list.size() == vMax - vMin + 1);
ListIterator it1 = list.iterator();
assert(it1.valid());
it1.first();
assert(it1.valid());
TComp deleted = NULL_TCOMP;
testIteratorSteps(list, r);
try {
deleted = list.remove(list.search(it1.getCurrent()));
assert(list.size() == vMax - vMin);
it1.first();
TComp newFirst = it1.getCurrent();
assert(newFirst != deleted);
assert(r(deleted, newFirst));
it1.first();
ListIterator it2 = list.iterator();
assert(it2.valid());
it2.first();
assert(it2.valid());
assert(it1.getCurrent() == newFirst && it2.getCurrent() == newFirst);
} catch (exception&) {
assert(false);
}
//delete values in random order while checking the relation order
vector<int> vs = random(vMin, vMax);
int n = vs.size();
for (int i = 0; i < n; i++) {
testIteratorSteps(list, r);
int v = vs[i];
try {
int it1 = list.search(v);
TComp deletedCurrent = list.remove(it1);
assert(deletedCurrent != deleted);
assert(deletedCurrent == v);
assert(list.search(v) == -1);
if (!list.isEmpty()) {
ListIterator it2 = list.iterator();
it2.first();
assert(it2.valid());
TComp prev = it2.getCurrent();
while (it2.valid()) {
TComp current = list.getElement(list.search(it2.getCurrent()));
assert(r(prev, current));
assert(!r(deletedCurrent, current) || !r(current, deletedCurrent));
prev = current;
it2.next();
}
}
} catch (exception&) {
assert(v == deleted);
}
}
assert(list.isEmpty());
assert(list.size() == 0);
}
void testDeleteSearch() {
testDeleteSearch(asc);
testDeleteSearch(desc);
}
void testAddAndSearch() {
testAddAndSearch(asc);
testAddAndSearch(desc);
}
void testQuantity(){
cout << "Test quantity" << endl;
SortedIndexedList list = SortedIndexedList(asc);
int vMin = 3000;
int vMax = 6000;
vector<int> values = random(vMin, vMax);
int n = values.size();
for (int i = 0; i < n; i++){
list.add(values[i]);
}
assert(list.size() == vMax - vMin + 1);
for (int v = vMin; v <= vMax; v++){
assert(list.search(v)>= 0 && list.search(v) < list.size());
assert(list.getElement(list.search(v)) == v);
}
ListIterator it = list.iterator();
it.first();
assert(it.valid());
TComp firstElement = it.getCurrent();
it.first();
assert(it.valid());
assert(it.getCurrent() == firstElement);
for (int i = 0; i < list.size(); i++) {
it.next();
}
assert(!it.valid());
it.first();
while (it.valid()){
TComp v = it.getCurrent();
assert(vMin <= v && v<=vMax);
it.next();
}
assert(!it.valid());
int d = 100;
//consider the interval [vMin-d, vMax+d]
for (int v = vMin-d; v <= vMax+d; v++){
//check that only values from the interval [vMin, vMax] are included in the list
assert((list.search(v) != -1) == (vMin <= v && v <= vMax));
try{
assert(list.remove(list.search(v)));
assert(vMin <= v && v <= vMax);
} catch (exception&) {
assert(vMin > v || v > vMax);
}
}
assert(list.size() == 0);
assert(list.isEmpty());
}
void testPrevious(){
cout << "Test previous" << endl;
SortedIndexedList list = SortedIndexedList(asc);
list.add(1);
list.add(3);
list.add(7);
list.add(10);
list.add(12);
ListIterator it = list.iterator();
it.last();
assert(it.valid());
assert(it.getCurrent() == 12);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 10);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 7);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 3);
it.previous();
assert(it.valid());
assert(it.getCurrent() == 1);
it.previous();
assert(!it.valid());
}
void testAllExtended() {
testCreate();
testAddAndSearch();
testDeleteSearch();
testQuantity();
testPrevious();
}
@@ -0,0 +1,3 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,49 @@
#include "ListIterator.h"
#include "SortedIndexedList.h"
#include <iostream>
using namespace std;
ListIterator::ListIterator(const SortedIndexedList& list) : list(list) {
// O(1)
this->_current = list._head;
}
void ListIterator::first(){
// O(1)
this->_current = this->list._head;
}
void ListIterator::next(){
// O(1)
if(!this->valid())
throw exception();
this->_current = this->list._next[this->_current];
}
bool ListIterator::valid() const{
// O(1)
if(this->_current != -1)
return true;
return false;
}
TComp ListIterator::getCurrent() const{
// O(1)
if(this->valid())
return this->list._elements[this->_current];
return NULL_TCOMP;
}
void ListIterator::previous(){
// O(1)
if(!this->valid())
throw exception();
this->_current = this->list._prev[this->_current];
}
void ListIterator::last(){
// O(1)
this->_current = this->list._tail;
}
@@ -0,0 +1,24 @@
#pragma once
#include "SortedIndexedList.h"
//DO NOT CHANGE THIS PART
class ListIterator{
friend class SortedIndexedList;
private:
const SortedIndexedList& list;
ListIterator(const SortedIndexedList& list);
//TODO - Representation
int _current;
public:
void first();
void last();
void next();
bool valid() const;
TComp getCurrent() const;
void previous();
};
@@ -0,0 +1,37 @@
#include <assert.h>
#include "ListIterator.h"
#include "SortedIndexedList.h"
using namespace std;
bool relation1(TComp e1, TComp e2) {
if (e1 <= e2) {
return true;
}
else {
return false;
}
}
void testAll(){
SortedIndexedList list = SortedIndexedList(relation1);
assert(list.size() == 0);
assert(list.isEmpty());
list.add(1);
assert(list.size() == 1);
assert(!list.isEmpty());
ListIterator iterator = list.iterator();
assert(iterator.valid());
iterator.first();
assert(iterator.getCurrent() == 1);
iterator.next();
assert(!iterator.valid());
iterator.first();
assert(iterator.valid());
assert(list.search(1) == 0);
assert(list.remove(0) == 1);
assert(list.size() == 0);
assert(list.isEmpty());
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,149 @@
#include "ListIterator.h"
#include "SortedIndexedList.h"
#include <iostream>
using namespace std;
#include <exception>
SortedIndexedList::SortedIndexedList(Relation r) {
// O(1)
this->_relation = r;
this->_capacity = 10;
this->_length = 0;
this->_elements = new TComp[this->_capacity];
this->_next = new int[this->_capacity];
this->_prev = new int[this->_capacity];
for(int i = 0; i < this->_capacity; i++){
this->_elements[i] = NULL_TCOMP;
this->_next[i] = -1;
this->_prev[i] = -1;
}
this->_head = -1;
this->_tail = -1;
this->_firstEmpty = 0;
}
int SortedIndexedList::size() const {
//O(1)
return this->_length;
}
bool SortedIndexedList::isEmpty() const {
//O(1)
return this->_length == 0;
}
TComp SortedIndexedList::getElement(int i) const{
//O(i) - average case | O(i) - worst case | O(i) - best case
if(i < 0 || i >= this->_length)
throw exception();
int current = this->_head;
while(i != 0){
i--;
current = this->_next[current];
}
return this->_elements[current];
}
TComp SortedIndexedList::remove(int i) {
// O(i) - average case | O(i) - worst case | O(i) - best case
if(i < 0 || i >= this->_length)
throw exception();
int current = this->_head;
while(i != 0){
i--;
current = this->_next[current];
}
TComp removed = this->_elements[current];
if(this->_head == current)
this->_head = this->_next[current];
else
this->_next[this->_prev[current]] = this->_next[current];
if(this->_tail == current)
this->_tail = this->_prev[current];
else
this->_prev[this->_next[current]] = this->_prev[current];
this->_elements[current] = NULL_TCOMP;
this->_next[current] = -1;
this->_prev[current] = -1;
this->_length--;
if(this->_firstEmpty > current)
this->_firstEmpty = current;
return removed;
}
int SortedIndexedList::search(TComp e) const {
//O(n) - average case | O(n) - worst case | O(1) - best case
int current = this->_head;
int i = 0;
while(current != -1){
if(this->_elements[current] == e)
return i;
current = this->_next[current];
i++;
}
return -1;
}
void SortedIndexedList::add(TComp e) {
// O(n) - average case | O(n) - worst case | O(1) - best case
if(this->_length == this->_capacity)
this->resize();
int current = this->_head;
int prev = -1;
while(current != -1 && this->_relation(this->_elements[current], e)){
prev = current;
current = this->_next[current];
}
this->_elements[this->_firstEmpty] = e;
this->_next[this->_firstEmpty] = current;
this->_prev[this->_firstEmpty] = prev;
if(prev == -1)
this->_head = this->_firstEmpty;
else
this->_next[prev] = this->_firstEmpty;
if(current == -1)
this->_tail = this->_firstEmpty;
else
this->_prev[current] = this->_firstEmpty;
this->_length++;
while(this->_firstEmpty < this->_capacity && this->_elements[this->_firstEmpty] != NULL_TCOMP)
this->_firstEmpty++;
}
ListIterator SortedIndexedList::iterator(){
//O(1)
return ListIterator(*this);
}
//destructor
SortedIndexedList::~SortedIndexedList() {
//O(1)
delete[] this->_elements;
delete[] this->_next;
delete[] this->_prev;
}
void SortedIndexedList::resize(){
//O(n)
this->_capacity *= 2;
TComp* newElements = new TComp[this->_capacity];
int* newNext = new int[this->_capacity];
int* newPrev = new int[this->_capacity];
for(int i = 0; i < this->_capacity; i++){
newElements[i] = NULL_TCOMP;
newNext[i] = -1;
newPrev[i] = -1;
}
for(int i = 0; i < this->_length; i++){
newElements[i] = this->_elements[i];
newNext[i] = this->_next[i];
newPrev[i] = this->_prev[i];
}
delete[] this->_elements;
delete[] this->_next;
delete[] this->_prev;
this->_elements = newElements;
this->_next = newNext;
this->_prev = newPrev;
}
@@ -0,0 +1,57 @@
#pragma once
//DO NOT INCLUDE LISTITERATOR
//DO NOT CHANGE THIS PART
class ListIterator;
typedef int TComp;
typedef bool (*Relation)(TComp, TComp);
#define NULL_TCOMP -11111
class SortedIndexedList {
private:
friend class ListIterator;
private:
//TODO - Representation
Relation _relation;
int _capacity;
int _length;
TComp* _elements;
int* _next;
int* _prev;
int _head;
int _tail;
int _firstEmpty;
void resize();
public:
// constructor
SortedIndexedList(Relation r);
// returns the size of the list
int size() const;
//checks if the list is empty
bool isEmpty() const;
// returns an element from a position
//throws exception if the position is not valid
TComp getElement(int pos) const;
// adds an element in the sortedList (to the corresponding position)
void add(TComp e);
// removes an element from a given position
//returns the removed element
//throws an exception if the position is not valid
TComp remove(int pos);
// searches for an element and returns the first position where the element appears or -1 if the element is not in the list
int search(TComp e) const;
// returns an iterator set to the first element of the list or invalid if the list is empty
ListIterator iterator();
//destructor
~SortedIndexedList();
};
@@ -0,0 +1,18 @@
#include "ExtendedTest.h"
#include "ShortTest.h"
#include "Map.h"
#include <iostream>
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "That's all!" << endl;
system("pause");
return 0;
}
@@ -0,0 +1,291 @@
#include "ExtendedTest.h"
#include "Map.h"
#include "MapIterator.h"
#include <assert.h>
#include <iostream>
using namespace std;
void testIteratorSteps(Map& m) {
MapIterator mi = m.iterator();
int count = 0;
while (mi.valid()) {
count++;
mi.next();
}
assert(count == m.size());
}
void testCreate() {
cout << "Test create" << endl;
Map m;
assert(m.size() == 0);
assert(m.isEmpty() == true);
for (int i = -10; i < 10; i++) {
assert(m.search(i) == NULL_TVALUE);
}
for (int i = -10; i < 10; i++) {
assert(m.search(i) == NULL_TVALUE);
}
MapIterator it = m.iterator();
assert(it.valid() == false);
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
}
void testAdd() {
cout << "Test add" << endl;
Map m;
for (int i = 0; i < 10; i++) {
assert(m.add(i, i) == NULL_TVALUE);
}
assert(m.isEmpty() == false);
assert(m.size() == 10);
for (int i = -10; i < 0; i++) {
assert(m.add(i, i) == NULL_TVALUE);
}
for (int i = 0; i < 10; i++) {
assert(m.add(i, i) == i);
}
for (int i = 10; i < 20; i++) {
assert(m.add(i, i) == NULL_TVALUE);
}
assert(m.isEmpty() == false);
assert(m.size() == 30);
for (int i = -100; i < 100; i++) {
m.add(i, i);
}
assert(m.isEmpty() == false);
assert(m.size() == 200);
for (int i = -200; i < 200; i++) {
if (i < -100) {
assert(m.search(i) == NULL_TVALUE);
}
else if (i < 0) {
assert(m.search(i) == i);
}
else if (i < 100) {
assert(m.search(i) == i);
}
else {
assert(m.search(i) == NULL_TVALUE);
}
}
for (int i = 10000; i > -10000; i--) {
m.add(i, i);
}
testIteratorSteps(m);
assert(m.size() == 20000);
}
void testRemove() {
cout << "Test remove" << endl;
Map m;
for (int i = -100; i < 100; i++) {
assert(m.remove(i) == NULL_TVALUE);
}
assert(m.size() == 0);
for (int i = -100; i < 100; i = i + 2) {
assert(m.add(i, i) == NULL_TVALUE);
}
for (int i = -100; i < 100; i++) {
if (i % 2 == 0) {
assert(m.remove(i) == i);
}
else {
assert(m.remove(i) == NULL_TVALUE);
}
}
assert(m.size() == 0);
for (int i = -100; i <= 100; i = i + 2) {
assert(m.add(i, i) == NULL_TVALUE);
}
testIteratorSteps(m);
for (int i = 100; i > -100; i--) {
if (i % 2 == 0) {
assert(m.remove(i) == i);
}
else {
assert(m.remove(i) == NULL_TVALUE);
}
testIteratorSteps(m);
}
assert(m.size() == 1);
m.remove(-100);
assert(m.size() == 0);
for (int i = -100; i < 100; i++) {
assert(m.add(i, 0) == NULL_TVALUE);
assert(m.add(i, 1) == 0);
assert(m.add(i, 2) == 1);
assert(m.add(i, 3) == 2);
assert(m.add(i, 4) == 3);
}
assert(m.size() == 200);
for (int i = -200; i < 200; i++) {
if (i < -100 || i >= 100) {
assert(m.remove(i) == NULL_TVALUE);
}
else {
assert(m.remove(i) == 4);
assert(m.remove(i) == NULL_TVALUE);
}
}
assert(m.size() == 0);
}
void testIterator() {
cout << "Test iterator" << endl;
Map m;
MapIterator it = m.iterator();
assert(it.valid() == false);
for (int i = 0; i < 100; i++) {
m.add(33, 33);
}
MapIterator it2 = m.iterator();
assert(it2.valid() == true);
TElem el = it2.getCurrent();
assert(el.first == 33);
assert(el.second == 33);
it2.next();
assert(it2.valid() == false);
try {
it2.next();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it2.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
it2.first();
assert(it2.valid() == true);
Map m2;
for (int i = -100; i < 100; i++) {
assert(m2.add(i, i) == NULL_TVALUE);
assert(m2.add(i, i) == i);
assert(m2.add(i, i) == i);
}
MapIterator it3 = m2.iterator();
assert(it3.valid() == true);
for (int i = 0; i < 200; i++) {
it3.next();
}
assert(it3.valid() == false);
it3.first();
assert(it3.valid() == true);
Map m3;
for (int i = 0; i < 200; i = i + 4) {
m3.add(i, i);
}
MapIterator it4 = m3.iterator();
assert(it4.valid() == true);
int count = 0;
while (it4.valid()) {
TElem e = it4.getCurrent();
assert(e.first % 4 == 0);
it4.next();
count++;
}
assert(count == 50);
}
void testQuantity() {
Map m;
cout << "Test quantity" << endl;
for (int j = 0; j < 30000; j = j + 1) {
assert(m.add(j, j) == NULL_TVALUE);
}
for (int i = 10; i >= 1; i--) {
for (int j = 0; j < 30000; j = j + i) {
assert(m.add(j, j) == j);
}
}
assert(m.size() == 30000);
MapIterator it = m.iterator();
assert(it.valid() == true);
for (int i = 0; i < m.size(); i++) {
it.next();
}
it.first();
while (it.valid()) {
TElem e = it.getCurrent();
assert(m.search(e.first) == e.first);
it.next();
}
assert(it.valid() == false);
for (int j = 30000 - 1; j >= 0; j--) {
assert(m.remove(j) == j);
}
for (int i = 0; i < 10; i++) {
for (int j = 40000; j >= -4000; j--) {
assert(m.remove(j) == NULL_TVALUE);
}
}
assert(m.size() == 0);
}
void testExtra()
{
cout << "Test extra" << endl;
Map m;
assert(m.isEmpty() == true);
assert(m.getKeyRange() == -1);
assert(m.add(1, 2) == NULL_TVALUE);
assert(m.add(1, 3) == 2);
assert(m.add(2, 3) == NULL_TVALUE);
assert(m.getKeyRange() == 1);
assert(m.add(100, 100) == NULL_TVALUE);
assert(m.getKeyRange() == 99);
}
void testAllExtended() {
testCreate();
testAdd();
testRemove();
testIterator();
testQuantity();
testExtra();
}
@@ -0,0 +1,3 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,170 @@
#include "Map.h"
#include "MapIterator.h"
#include <math.h>
#include <iostream>
Map::Map() {
//O(1)
this->_capacity=INITIAL_CAPACITY;
this->_size=0;
this->_elements=new TElem[this->_capacity];
this->_next=new int[this->_capacity];
for(int i=0;i<this->_capacity;i++){
this->_elements[i]=NULL_TELEM;
this->_next[i]=-1;
}
this->_nextFree=INITIAL_CAPACITY-1;
}
Map::~Map() {
//O(1)
delete[] this->_elements;
delete[] this->_next;
}
TValue Map::add(TKey c, TValue v){
// O(1) - amortized
if(this->_size>=this->_capacity*ALPHA)
this->_resize();
int hash=abs(c % this->_capacity);
while(this->_next[hash]!=-1 && this->_elements[hash].first!=c)
hash=this->_next[hash];
if(this->_elements[hash].first==c){
TValue oldValue=this->_elements[hash].second;
this->_elements[hash].second=v;
return oldValue;
}
this->_elements[this->_nextFree]=std::make_pair(c,v);
this->_next[hash]=this->_nextFree;
while(this->_elements[this->_nextFree]!=NULL_TELEM)
this->_nextFree--;
this->_size++;
return NULL_TVALUE;
}
TValue Map::search(TKey c) const{
// O(1) - amortized
int hash = abs(c % this->_capacity);
while (this->_next[hash] != -1 && this->_elements[hash].first != c)
hash = this->_next[hash];
if (this->_elements[hash].first == c)
return this->_elements[hash].second;
return NULL_TVALUE;
}
TValue Map::remove(TKey c){
//O(1) - amortized
int hash = abs(c % this->_capacity);
int prev = -1;
while (this->_next[hash] != -1 && this->_elements[hash].first != c) {
prev = hash;
hash = this->_next[hash];
}
if (this->_elements[hash].first == c) {
TValue oldValue = this->_elements[hash].second;
if (prev == -1) {
if(this->_next[hash]!=-1){
int remove = this->_next[hash];
this->_elements[hash] = this->_elements[this->_next[hash]];
this->_next[hash] = this->_next[this->_next[hash]];
this->_next[remove] = -1;
this->_elements[remove] = NULL_TELEM;
hash = remove;
}
else
this->_elements[hash] = NULL_TELEM;
}
else {
this->_next[prev] = this->_next[hash];
this->_elements[hash] = NULL_TELEM;
this->_next[hash] = -1;
}
if(hash>this->_nextFree)
this->_nextFree = hash;
this->_size--;
return oldValue;
}
return NULL_TVALUE;
}
int Map::size() const {
//O(1)
return this->_size;
}
bool Map::isEmpty() const{
//O(1)
return (this->_size==0);
}
MapIterator Map::iterator() const {
return MapIterator(*this);
}
void Map::_resize() {
//O(n)
int oldCapacity=this->_capacity;
this->_capacity*=2;
while(true){
bool ok=true;
for(int i=2;i<=sqrt(this->_capacity);i++)
if(this->_capacity%i==0){
ok=false;
break;
}
if(ok)
break;
this->_capacity++;
}
TElem* newElements=new TElem[this->_capacity];
int* newNext=new int[this->_capacity];
for(int i=0;i<this->_capacity;i++){
newElements[i]=NULL_TELEM;
newNext[i]=-1;
}
this->_nextFree=this->_capacity-1;
for(int i=0;i<oldCapacity;i++){
if(this->_elements[i]!=NULL_TELEM){
int hash=abs(this->_elements[i].first % this->_capacity);
while(newNext[hash]!=-1)
hash=this->_next[hash];
if(newElements[hash]==NULL_TELEM){
newElements[hash]=this->_elements[i];
newNext[hash]=-1;
}
else{
newElements[this->_nextFree]=this->_elements[i];
newNext[hash]=this->_nextFree;
while(newElements[this->_nextFree]!=NULL_TELEM)
this->_nextFree--;
}
}
}
delete[] this->_elements;
delete[] this->_next;
this->_elements=newElements;
this->_next=newNext;
}
int Map::getKeyRange() const{
//O(n)
MapIterator it = this->iterator();
if (!it.valid())
return -1;
int min = it.getCurrent().first;
int max = it.getCurrent().first;
while (it.valid()) {
if (it.getCurrent().first < min)
min = it.getCurrent().first;
if (it.getCurrent().first > max)
max = it.getCurrent().first;
it.next();
}
return max - min;
}
@@ -0,0 +1,66 @@
#pragma once
#include <utility>
using namespace std;
//DO NOT INCLUDE MAPITERATOR
//DO NOT CHANGE THIS PART
typedef int TKey;
typedef int TValue;
typedef std::pair<TKey, TValue> TElem;
#define NULL_TVALUE -111111
#define NULL_TELEM pair<TKey, TValue>(-111111, -111111)
#define ALPHA 0.75
#define INITIAL_CAPACITY 2300000
class MapIterator;
class Map {
//DO NOT CHANGE THIS PART
friend class MapIterator;
private:
//TODO - Representation
TElem* _elements;
int* _next;
int _size;
int _capacity;
int _nextFree;
void _resize();
public:
// implicit constructor
Map();
// adds a pair (key,value) to the map
//if the key already exists in the map, then the value associated to the key is replaced by the new value and the old value is returned
//if the key does not exist, a new pair is added and the value null is returned
TValue add(TKey c, TValue v);
//searches for the key and returns the value associated with the key if the map contains the key or null: NULL_TVALUE otherwise
TValue search(TKey c) const;
//removes a key from the map and returns the value associated with the key if the key existed ot null: NULL_TVALUE otherwise
TValue remove(TKey c);
//returns the number of pairs (key,value) from the map
int size() const;
//checks whether the map is empty or not
bool isEmpty() const;
//returns an iterator for the map
MapIterator iterator() const;
int getKeyRange() const;
// destructor
~Map();
};
@@ -0,0 +1,55 @@
#include "Map.h"
#include "MapIterator.h"
#include <exception>
using namespace std;
MapIterator::MapIterator(const Map& d) : map(d)
{
//O(1)
this->_current=0;
while (this->_current<this->map._capacity && this->map._elements[this->_current]==NULL_TELEM)
{
this->_current++;
}
this->_first=this->_current;
}
void MapIterator::first() {
//O(1)
this->_current=this->_first;
}
void MapIterator::next() {
//O(1)
if(this->valid()){
this->_current++;
while (this->_current<this->map._capacity && this->map._elements[this->_current]==NULL_TELEM)
{
this->_current++;
}
}
else
throw exception();
}
TElem MapIterator::getCurrent(){
//O(1)
if(this->valid())
return this->map._elements[this->_current];
throw exception();
}
bool MapIterator::valid() const {
//O(1)
if(this->_current<this->map._capacity && this->map._elements[this->_current]!=NULL_TELEM)
return true;
return false;
}
@@ -0,0 +1,21 @@
#pragma once
#include "Map.h"
class MapIterator
{
//DO NOT CHANGE THIS PART
friend class Map;
private:
const Map& map;
//TODO - Representation
int _current;
int _first;
MapIterator(const Map& m);
public:
void first();
void next();
TElem getCurrent();
bool valid() const;
};
@@ -0,0 +1,41 @@
#include "ShortTest.h"
#include <assert.h>
#include "Map.h"
#include "MapIterator.h"
void testAll() { //call each function to see if it is implemented
Map m;
assert(m.isEmpty() == true);
assert(m.size() == 0); //add elements
assert(m.add(5,5)==NULL_TVALUE);
assert(m.add(1,111)==NULL_TVALUE);
assert(m.add(10,110)==NULL_TVALUE);
assert(m.add(7,7)==NULL_TVALUE);
assert(m.add(1,1)==111);
assert(m.add(10,10)==110);
assert(m.add(-3,-3)==NULL_TVALUE);
assert(m.size() == 5);
assert(m.search(10) == 10);
assert(m.search(16) == NULL_TVALUE);
assert(m.remove(1) == 1);
assert(m.remove(6) == NULL_TVALUE);
assert(m.size() == 4);
TElem e;
MapIterator id = m.iterator();
id.first();
int s1 = 0, s2 = 0;
while (id.valid()) {
e = id.getCurrent();
s1 += e.first;
s2 += e.second;
id.next();
}
assert(s1 == 19);
assert(s2 == 19);
}
@@ -0,0 +1,4 @@
#pragma once
void testAll();
@@ -0,0 +1,15 @@
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <iostream>
#include "ShortTest.h"
#include "ExtendedTest.h"
using namespace std;
int main() {
testAll();
testAllExtended();
cout << "Test over" << endl;
system("pause");
}
@@ -0,0 +1,328 @@
#include "ShortTest.h"
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <assert.h>
#include <iostream>
#include <exception>
using namespace std;
bool relation2(TComp r1, TComp r2) {
return r1 <= r2;
}
bool relation3(TComp r1, TComp r2) {
return r1 >= r2;
}
void testCreate() {
cout << "Test create" << endl;
SortedBag sb(relation2);
assert(sb.isEmpty() == true);
assert(sb.size() == 0);
for (int i = -10; i < 30; i++) {
assert(sb.remove(i) == false);
}
for (int i = -10; i < 30; i++) {
assert(sb.search(i) == false);
}
for (int i = -10; i < 30; i++) {
assert(sb.nrOccurrences(i) == 0);
}
SortedBagIterator it = sb.iterator();
assert(it.valid() == false);
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
}
void testIterator(SortedBag& sb, Relation rel) {
SortedBagIterator it = sb.iterator();
TComp e1;
TComp e2;
if (it.valid()) {
e1 = it.getCurrent();
it.next();
}
while (it.valid()) {
e2 = e1;
e1 = it.getCurrent();
it.next();
assert(sb.search(e1) == true);
assert(sb.search(e2) == true);
assert(sb.nrOccurrences(e1) > 0);
assert(sb.nrOccurrences(e2) > 0);
assert(rel(e2, e1));
}
try {
it.getCurrent();
assert(false);
}
catch (exception&) {
assert(true);
}
try {
it.next();
assert(false);
}
catch (exception&) {
assert(true);
}
it.first();
assert(it.valid() == true);
it.first();
int count = 0;
while (it.valid()) {
count++;
it.next();
}
assert(count == sb.size());
}
void testAdd(Relation r) {
cout << "Test add" << endl;
SortedBag sb(r);
for (int i = 0; i < 100; i++) {
sb.add(i);
}
assert(sb.size() == 100);
assert(sb.isEmpty() == false);
testIterator(sb, r);
for (int i = 200; i >= -200; i--) {
sb.add(i);
}
assert(sb.size() == 501);
testIterator(sb, r);
for (int i = -300; i < 300; i++) {
bool exista = sb.search(i);
int nrA = sb.nrOccurrences(i);
if (i < -200 || i > 200) {
assert(exista == false);
assert(nrA == 0);
}
else if (i >= -200 && i < 0) {
assert(exista == true);
assert(nrA == 1);
}
else if (i >= 0 && i < 100) {
assert(exista == true);
assert(nrA == 2);
}
else if (i >= 100 && i <= 200) {
assert(exista == true);
assert(nrA == 1);
}
}
for (int i = 0; i < 100; i++) {
sb.add(0);
}
assert(sb.nrOccurrences(0) == 102);
testIterator(sb, r);
SortedBag sb2(r);
for (int i = 0; i < 300; i = i + 2) {
sb2.add(i);
sb2.add(2 * i);
sb2.add(-2 * i);
}
assert(sb2.size() == 450);
testIterator(sb2, r);
}
void testRemove(Relation r) {
cout << "Test remove" << endl;
SortedBag sb(r);
for (int i = -100; i < 100; i++) {
assert(sb.remove(i) == false);
assert(sb.search(i) == false);
assert(sb.nrOccurrences(i) == 0);
}
assert(sb.isEmpty() == true);
for (int i = -100; i < 100; i++) {
sb.add(i);
}
assert(sb.size() == 200);
for (int i = -100; i < 100; i = i + 2) {
assert(sb.remove(i) == true);
}
assert(sb.size() == 100);
for (int i = -100; i < 100; i++) {
if (i % 2 == 0) {
assert(sb.nrOccurrences(i) == 0);
assert(sb.search(i) == false);
assert(sb.remove(i) == false);
}
else {
assert(sb.nrOccurrences(i) == 1);
assert(sb.search(i) == true);
}
sb.add(i);
sb.add(i);
sb.add(i);
}
assert(sb.size() == 700);
for (int i = -200; i < 200; i++) {
if (i < -100 || i >= 100) {
assert(sb.search(i) == false);
assert(sb.nrOccurrences(i) == 0);
assert(sb.remove(i) == false);
}
else if (i % 2 == 0) {
assert(sb.search(i) == true);
assert(sb.nrOccurrences(i) == 3);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == false);
}
else {
assert(sb.search(i) == true);
assert(sb.nrOccurrences(i) == 4);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == true);
assert(sb.remove(i) == false);
}
}
SortedBag sb2(r);
for (int i = 300; i >= -500; i--) {
sb2.add(i);
sb2.add(i * 2);
sb2.add(-2 * i);
}
for (int i = -100; i < 100; i++) {
for (int j = 0; j < 100; j++) {
sb2.remove(i);
}
}
for (int i = -100; i < 0; i++) {
assert(sb2.nrOccurrences(i) == 0);
assert(sb2.search(i) == false);
}
}
void testQuantity(Relation r) {
cout << "Test quantity" << endl;
SortedBag sb(r);
for (int j = 0; j < 10; j++) {
sb.add(0);
for (int i = 1; i < 300; i++) {
sb.add(i);
sb.add(-i);
}
sb.add(-3000);
}
int count = 6000;
assert(sb.size() == 6000);
for (int i = 0; i < 5000; i++) {
TComp nr = rand() % 8000 - 4000;
if (sb.remove(nr) == true) {
count--;
}
assert(sb.size() == count);
}
assert(sb.size() == count);
}
void testIterator(Relation rel) {
cout << "Test iterator" << endl;
SortedBag sb(rel);
for (int i = 0; i < 500; i++) {
sb.add(i);
sb.add(-2 * i);
sb.add(2 * i);
sb.add(i);
sb.add(-2 * i);
sb.add(2 * i);
}
assert(sb.size() == 3000);
SortedBagIterator sbi = sb.iterator();
int count = 0;
while (sbi.valid()) {
count++;
sbi.next();
}
assert(count == sb.size());
sbi.first();
TElem e = sbi.getCurrent();
sbi.next();
count = 1;
while (sbi.valid()) {
TElem ee = sbi.getCurrent();
assert(rel(e, ee));
TElem ee2 = sbi.getCurrent();
assert(ee == ee2);
TElem ee3 = sbi.getCurrent();
assert(ee == ee3);
e = ee;
sbi.next();
count++;
}
assert(count == sb.size());
}
void testExtra(){
cout << "Test extra" << endl;
SortedBag sb(relation2);
sb.add(2);
sb.add(2);
sb.add(2);
sb.add(1);
sb.add(1);
sb.add(1);
sb.add(1);
sb.add(2);
sb.add(5);
sb.add(3);
sb.add(4);
assert(sb.size() == 11);
assert(sb.nrOccurrences(1) == 4);
assert(sb.nrOccurrences(2) == 4);
assert(sb.nrOccurrences(3) == 1);
assert(sb.nrOccurrences(4) == 1);
assert(sb.nrOccurrences(5) == 1);
assert(sb.elementsWithThisFrequency(1) == 3);
assert(sb.elementsWithThisFrequency(4) == 2);
try {
sb.elementsWithThisFrequency(0);
assert(false);
}
catch (exception&) {
assert(true);
}
}
void testAllExtended() {
testCreate();
testAdd(relation2);
testAdd(relation3);
testRemove(relation2);
testRemove(relation3);
testIterator(relation2);
testIterator(relation3);
testQuantity(relation2);
testQuantity(relation3);
testExtra();
}
@@ -0,0 +1,3 @@
#pragma once
void testAllExtended();
@@ -0,0 +1,39 @@
#include "ShortTest.h"
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <assert.h>
bool relation1(TComp e1, TComp e2) {
return e1 <= e2;
}
void testAll() {
SortedBag sb(relation1);
sb.add(5);
sb.add(6);
sb.add(0);
sb.add(5);
sb.add(10);
sb.add(8);
assert(sb.size() == 6);
assert(sb.nrOccurrences(5) == 2);
assert(sb.remove(5) == true);
assert(sb.size() == 5);
assert(sb.search(6) == true);
assert(sb.isEmpty() == false);
SortedBagIterator it = sb.iterator();
assert(it.valid() == true);
while (it.valid()) {
it.getCurrent();
it.next();
}
assert(it.valid() == false);
it.first();
assert(it.valid() == true);
}
@@ -0,0 +1,3 @@
#pragma once
void testAll();
@@ -0,0 +1,239 @@
#include "SortedBag.h"
#include "SortedBagIterator.h"
#include <exception>
SortedBag::SortedBag(Relation r) {
//TODO - Implementation
this->relation = r;
this->root = nullptr;
this->length = 0;
}
void SortedBag::add(TComp e) {
//Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* newNode = new BSTNode;
newNode->elem = e;
newNode->left = nullptr;
newNode->right = nullptr;
newNode->parent = nullptr;
newNode->count = 1;
if (this->root == nullptr) {
this->root = newNode;
this->length++;
return;
}
BSTNode* current = this->root;
while (current != nullptr) {
if (current->elem == e) {
current->count++;
this->length++;
return;
}
if (this->relation(e, current->elem)) {
if (current->left == nullptr) {
current->left = newNode;
newNode->parent = current;
this->length++;
return;
}
else {
current = current->left;
}
}
else {
if (current->right == nullptr) {
current->right = newNode;
newNode->parent = current;
this->length++;
return;
}
else {
current = current->right;
}
}
}
}
bool SortedBag::remove(TComp e) {
//Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* current = this->root;
while (current != nullptr) {
if(current->elem==e){
if(current->count>1){
current->count--;
this->length--;
return true;
}
else{
if(current->left==nullptr && current->right==nullptr){
if(current->parent==nullptr){
this->root=nullptr;
this->length--;
return true;
}
else{
if(current->parent->left==current){
current->parent->left=nullptr;
this->length--;
return true;
}
else{
current->parent->right=nullptr;
this->length--;
return true;
}
}
}
else{
if(current->left==nullptr){
if(current->parent==nullptr){
this->root=current->right;
this->root->parent=nullptr;
this->length--;
return true;
}
else{
if(current->parent->left==current){
current->parent->left=current->right;
this->length--;
return true;
}
else{
current->parent->right=current->right;
this->length--;
return true;
}
}
}
else{
if(current->right==nullptr){
if(current->parent==nullptr){
this->root=current->left;
this->root->parent=nullptr;
this->length--;
return true;
}
else{
if(current->parent->left==current){
current->parent->left=current->left;
this->length--;
return true;
}
else{
current->parent->right=current->left;
this->length--;
return true;
}
}
}
else{
BSTNode* current2=current->right;
while(current2->left!=nullptr){
current2=current2->left;
}
current->elem=current2->elem;
current->count=current2->count;
if(current2->parent->left==current2){
current2->parent->left=current2->right;
this->length--;
return true;
}
else{
current2->parent->right=current2->right;
this->length--;
return true;
}
}
}
}
}
}
else{
if(this->relation(e,current->elem)){
current=current->left;
}
else{
current=current->right;
}
}
}
return false;
}
bool SortedBag::search(TComp elem) const {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* current = this->root;
while (current != nullptr) {
if (current->elem == elem) {
return true;
}
if (this->relation(elem, current->elem)) {
current = current->left;
}
else {
current = current->right;
}
}
return false;
}
int SortedBag::nrOccurrences(TComp elem) const {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
BSTNode* current = this->root;
while (current != nullptr) {
if (current->elem == elem) {
return current->count;
}
if (this->relation(elem, current->elem)) {
current = current->left;
}
else {
current = current->right;
}
}
return 0;
}
int SortedBag::size() const {
//O(1)
return this->length;
}
bool SortedBag::isEmpty() const {
//O(1)
return (this->length == 0);
}
SortedBagIterator SortedBag::iterator() const {
return SortedBagIterator(*this);
}
SortedBag::~SortedBag() {
//O(n)
delete this->root;
}
int SortedBag::elementsWithThisFrequency(int frequency) const {
// O(n)
if(frequency<=0){
throw std::exception();
}
return reccuriveCount(this->root,frequency);
}
int SortedBag::reccuriveCount(BSTNode* node, int frequency) const {
if(node==nullptr){
return 0;
}
return reccuriveCount(node->left,frequency)+reccuriveCount(node->right, frequency) + (this->nrOccurrences(node->elem)==frequency);
}
@@ -0,0 +1,65 @@
#pragma once
//DO NOT INCLUDE SORTEDBAGITERATOR
//DO NOT CHANGE THIS PART
typedef int TComp;
typedef TComp TElem;
typedef bool(*Relation)(TComp, TComp);
#define NULL_TCOMP -11111;
class BSTNode {
public:
TComp elem;
BSTNode* left;
BSTNode* right;
BSTNode* parent;
~BSTNode() {
delete left;
delete right;
}
int count;
};
class SortedBagIterator;
class SortedBag {
friend class SortedBagIterator;
private:
//TODO - Representation
BSTNode* root;
Relation relation;
int length;
int reccuriveCount(BSTNode* node, int frequency) const;
public:
//constructor
SortedBag(Relation r);
//adds an element to the sorted bag
void add(TComp e);
//removes one occurence of an element from a sorted bag
//returns true if an element was removed, false otherwise (if e was not part of the sorted bag)
bool remove(TComp e);
//checks if an element appearch is the sorted bag
bool search(TComp e) const;
//returns the number of occurrences for an element in the sorted bag
int nrOccurrences(TComp e) const;
//returns the number of elements from the sorted bag
int size() const;
//returns an iterator for this sorted bag
SortedBagIterator iterator() const;
//checks if the sorted bag is empty
bool isEmpty() const;
//destructor
~SortedBag();
int elementsWithThisFrequency(int frequency) const;
};
@@ -0,0 +1,73 @@
#include "SortedBagIterator.h"
#include "SortedBag.h"
#include <exception>
using namespace std;
SortedBagIterator::SortedBagIterator(const SortedBag& b) : bag(b) {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
this->first();
}
TComp SortedBagIterator::getCurrent() {
//O(1)
if(this->valid())
return this->current->elem;
else
throw exception();
}
bool SortedBagIterator::valid() {
//O(1)
if(this->current == nullptr)
return false;
return true;
}
void SortedBagIterator::next() {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
if(this->valid())
{
if(this->currentCount > 1)
this->currentCount--;
else
{
if(this->current->right != nullptr)
{
this->current = this->current->right;
while(this->current->left != nullptr)
this->current = this->current->left;
this->currentCount = this->current->count;
}
else
{
BSTNode* currentParent = this->current->parent;
while(currentParent != nullptr && currentParent->right == this->current)
{
this->current = currentParent;
currentParent = currentParent->parent;
}
this->current = currentParent;
if(this->current != nullptr)
this->currentCount = this->current->count;
else
this->currentCount = 0;
}
}
}
else
throw exception();
}
void SortedBagIterator::first() {
// Best case: O(1) Worst case: O(n) Average case: O(log n)
this->current = this->bag.root;
if(this->current != nullptr){
while(this->current->left != nullptr)
this->current = this->current->left;
this->currentCount = this->current->count;
}
else{
this->currentCount = 0;
}
}
@@ -0,0 +1,24 @@
#pragma once
#include "SortedBag.h"
class SortedBag;
class SortedBagIterator
{
friend class SortedBag;
private:
const SortedBag& bag;
SortedBagIterator(const SortedBag& b);
//TODO - Representation
BSTNode* current;
int currentCount;
public:
TComp getCurrent();
bool valid();
void next();
void first();
};
@@ -0,0 +1,39 @@
class Bag:
def __init__(self):
self.__elements = []
def add(self, e):
self.__elements.append(e)
def remove(self, e):
if e in self.__elements:
self.__elements.remove(e)
return True
return False
def search(self, e):
return e in self.__elements
def size(self):
return len(self.__elements)
def nrOccurrences(self, e):
return self.__elements.count(e)
def destroy(self):
del(self)
def iterator(self):
return BagIterator(self.__elements)
class BagIterator:
def __init__(self, elements):
self.__elements = elements
self.__current = 0
def first(self):
self.__current = 0
def valid(self):
return self.__current < len(self.__elements)
def next(self):
if self.valid():
self.__current += 1
def getCurrent(self):
if self.valid():
return self.__elements[self.__current]
else:
raise ValueError("Invalid iterator position.")
@@ -0,0 +1,46 @@
from Bag import Bag, BagIterator
def createIntBag():
intBag=Bag()
intBag.add(6)
intBag.add(11)
intBag.add(77)
intBag.add(7)
intBag.add(4)
intBag.add(6)
intBag.add(77)
intBag.add(6)
return intBag
def createStringBag():
stringBag=Bag()
stringBag.add("data")
stringBag.add("structures")
stringBag.add("and")
stringBag.add("algorithms")
stringBag.add("data")
stringBag.add("data")
stringBag.add("algorithms")
return stringBag
def printBag(bag):
it = bag.iterator()
while it.valid():
print(it.getCurrent())
it.next()
print("Over. Let's start again.")
it.first()
while it.valid():
print(it.getCurrent())
it.next()
def main():
b1 = createIntBag()
printBag(b1)
print("No occurrences of 77: ", b1.nrOccurrences(77))
b2 = createStringBag()
printBag(b2)
print("No occurrences of 'data': ", b2.nrOccurrences("data"))
if __name__ == "__main__":
main()