mirror of
				https://github.com/coolaj86/fizzbuzz.git
				synced 2024-11-16 17:29:04 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			369 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			369 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <string>
 | |
| #include <iostream>
 | |
| #include <set>
 | |
| #include <list>
 | |
| #include <algorithm>
 | |
| #include <vector>
 | |
| #include <time.h>
 | |
| 
 | |
| #include "tut/tut.hpp"
 | |
| #include "BST.h"
 | |
| 
 | |
| #define NULL_NODE (static_cast<BSTNode*>(NULL))
 | |
| 
 | |
| using namespace std;
 | |
| 
 | |
| bool gDoRemove = false;
 | |
| extern std::string gCurrentTest;
 | |
| 
 | |
| string generateKey();
 | |
| void CheckSubTreeOrder(BSTNode * bNode, bool isLeftLess);
 | |
| void CheckBSTOrder(BST & bst);
 | |
| void CompareSubTrees(BSTNode* subTree1, BSTNode* subTree2);
 | |
| void CompareTrees(BST & bst1, BST & bst2);
 | |
| 
 | |
| struct BSTTest
 | |
| {
 | |
| public:
 | |
| 	BSTTest() : BSTTestSize(6379)
 | |
| 	{
 | |
| 	}
 | |
| 
 | |
| 	void initBST(BST& bst)
 | |
| 	{
 | |
| 		for(int i = 0; i < BSTTestSize; ++i)
 | |
| 		{
 | |
| 			string key = generateKey();
 | |
| 			if(chosen.find(key) != chosen.end())
 | |
| 			{
 | |
| 				--i;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				chosen.insert(key);
 | |
| 				BSTNode * curNode = bst.Insert(key);
 | |
| 				tut::ensure("Insert() - Return NULL when the value was not in the tree", curNode != NULL);
 | |
| 				tut::ensure_equals("Insert() - Returned a value which was different from the one entered", curNode->GetValue(), key);
 | |
| 				tut::ensure_equals("Insert() - The size of the BST is not the size of the elements inserted", bst.GetSize(), (int)chosen.size());
 | |
| 
 | |
| 				curNode = bst.Insert(key);
 | |
| 				tut::ensure_equals("Instert() - Did not return NULL when the value was in the tree", curNode, NULL_NODE);
 | |
| 				tut::ensure_equals("Insert() - Size incremented on duplicate insertion", bst.GetSize(), (int)chosen.size());
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	std::string generateKey()
 | |
| 	{
 | |
| 		char key[9];
 | |
| 		int digit = '9'-'0'+1;
 | |
| 		int upCase = 'Z'-'A'+digit+1;
 | |
| 		int top = 'z'-'a'+upCase+1;
 | |
| 		for(int i = 0; i < 9; i++){
 | |
| 			int val = rand()%top;
 | |
| 			if(val < digit){
 | |
| 				key[i] = val + '0';
 | |
| 			}
 | |
| 			else if(val < upCase){
 | |
| 				key[i] = val - digit + 'A';
 | |
| 			}
 | |
| 			else{
 | |
| 				key[i] = val - upCase + 'a';
 | |
| 			}
 | |
| 		}//end for i
 | |
| 		string result(key);
 | |
| 		return result;
 | |
| 	}
 | |
| 
 | |
| 	const int BSTTestSize;
 | |
| 	set<string> chosen;
 | |
| };
 | |
| 
 | |
| 
 | |
| void CheckSubTreeOrder(BSTNode * bNode, bool isLeftLess){
 | |
| 	if(bNode != NULL){
 | |
| 		string val = bNode->GetValue();
 | |
| 		BSTNode * lNode = bNode->GetLeft();
 | |
| 		BSTNode * rNode = bNode->GetRight();
 | |
| 		if(isLeftLess){
 | |
| 			if(lNode != NULL){
 | |
| 				tut::ensure("The left node had a greater value when it should have been less", lNode->GetValue() <= val);
 | |
| 				CheckSubTreeOrder(lNode, isLeftLess);
 | |
| 			}
 | |
| 			if(rNode != NULL){
 | |
| 				tut::ensure("The right node had a lesser value when it should have been less", rNode->GetValue() >= val);
 | |
| 				CheckSubTreeOrder(rNode, isLeftLess);
 | |
| 			}
 | |
| 		}
 | |
| 		else{
 | |
| 			if(lNode != NULL){
 | |
| 				tut::ensure("The left node had a lesser value when it should have been less", lNode->GetValue() >= val);
 | |
| 				CheckSubTreeOrder(lNode, isLeftLess);
 | |
| 			}
 | |
| 			if(rNode != NULL){
 | |
| 				tut::ensure("The right node had a greater value when it should have been less", rNode->GetValue() <= val);
 | |
| 				CheckSubTreeOrder(rNode, isLeftLess);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void CheckBSTOrder(BST & bst){
 | |
| 	BSTNode * bNode = bst.GetRoot();
 | |
| 	if(bNode != NULL){
 | |
| 		bool isLeftLess = true;
 | |
| 		BSTNode * left = bNode->GetLeft();
 | |
| 		if(left != NULL){
 | |
| 			if(left->GetValue() > bNode->GetValue()){
 | |
| 				isLeftLess = false;
 | |
| 			}
 | |
| 		}
 | |
| 		else{
 | |
| 			BSTNode * right = bNode->GetRight();
 | |
| 			if(right != NULL){
 | |
| 				if(right->GetValue() < bNode->GetValue()){
 | |
| 					isLeftLess = false;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 		CheckSubTreeOrder(bNode->GetLeft(), isLeftLess);
 | |
| 		CheckSubTreeOrder(bNode->GetRight(), isLeftLess);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void CompareSubTrees(BSTNode* subTree1, BSTNode* subTree2){
 | |
| 	tut::ensure_not("SubTrees are not equal", (subTree1 && !subTree2) || (subTree2 && !subTree1));
 | |
| 	if(subTree1 != NULL){
 | |
| 		tut::ensure_not("Nodes point to the same memory", subTree1 == subTree2 || subTree1 == subTree2);
 | |
| 		tut::ensure_equals("Node values are not equal", subTree1->GetValue(), subTree2->GetValue());
 | |
| 		CompareSubTrees(subTree1->GetLeft(),subTree2->GetLeft());
 | |
| 		CompareSubTrees(subTree1->GetRight(),subTree2->GetRight());
 | |
| 	}
 | |
| }
 | |
| 
 | |
| void CompareTrees(BST & bst1, BST & bst2){
 | |
| 	tut::ensure_equals("Sizes of the two trees are not equal", bst1.GetSize(), bst2.GetSize());
 | |
| 	CompareSubTrees(bst1.GetRoot(), bst2.GetRoot());
 | |
| }
 | |
| 
 | |
| namespace tut
 | |
| {
 | |
| 	namespace
 | |
| 	{
 | |
| 		typedef tut::test_group<BSTTest> tGroup;
 | |
| 		typedef tGroup::object tObject;
 | |
| 		tGroup group("BST");
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<1> ()
 | |
| 	{
 | |
| 		set_test_name("Default Constructor");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 
 | |
| 		// Root should be NULL
 | |
| 		tut::ensure_equals("Default Constructor - Root is not NULL", bst.GetRoot(), NULL_NODE);
 | |
| 
 | |
| 		// Size should be 0
 | |
| 		tut::ensure_equals("Default Constructor - Size is not 0", bst.GetSize(), 0);
 | |
| 		tut::ensure("Default Constructor - Says it's not empty", bst.IsEmpty());
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<2> ()
 | |
| 	{
 | |
| 		set_test_name("Insert");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 		initBST(bst);
 | |
| 
 | |
| 		CheckBSTOrder(bst);
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<3> ()
 | |
| 	{
 | |
| 		set_test_name("GetSize");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 		initBST(bst);
 | |
| 		tut::ensure_equals("GetSize() - The size of the BST is not the size of the elements inserted", bst.GetSize(), static_cast<int>(chosen.size()));
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<4> ()
 | |
| 	{
 | |
| 		set_test_name("Find");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 		initBST(bst);
 | |
| 
 | |
| 		set<string>::iterator iter;
 | |
| 		for(iter = chosen.begin(); iter != chosen.end(); iter++){
 | |
| 			BSTNode * curNode = bst.Find(*iter);
 | |
| 			tut::ensure("Find() - Node not found when it should have been", curNode != NULL);
 | |
| 			tut::ensure_equals("Find() - Returned a node with the wrong value", curNode->GetValue(), *iter);
 | |
| 		}
 | |
| 
 | |
| 		for(int i = 0; i < BSTTestSize; i++){
 | |
| 			string key = generateKey();
 | |
| 			if(chosen.find(key) == chosen.end()){
 | |
| 				BSTNode * curNode = bst.Find(key);
 | |
| 				tut::ensure("Find() - Returned a node when the value was not in the tree", curNode == NULL);
 | |
| 			}
 | |
| 			else{
 | |
| 				--i;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<5> ()
 | |
| 	{
 | |
| 		set_test_name("Copy Constructor");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 		BST emptyCopyBst(bst);
 | |
| 		initBST(bst);
 | |
| 
 | |
| 		BST fullCopyBst(bst);
 | |
| 		CompareTrees(bst,fullCopyBst);
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<6> ()
 | |
| 	{
 | |
| 		set_test_name("Assignment Operator");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 
 | |
| 		//Assign empty to empty
 | |
| 		BST emptyBst;
 | |
| 		emptyBst = bst;
 | |
| 		CompareTrees(bst,emptyBst);
 | |
| 
 | |
| 		//Return type check
 | |
| 		tut::ensure ("Assignment Operator: Testing return value", &emptyBst == &(emptyBst = bst));
 | |
| 
 | |
| 		//Assign empty to full
 | |
| 		initBST(bst);
 | |
| 		BST fullBst;
 | |
| 		fullBst = bst;
 | |
| 		CompareTrees(bst,fullBst);
 | |
| 
 | |
| 		//Assign to self
 | |
| 		fullBst = fullBst;
 | |
| 
 | |
| 		//Assign full to empty
 | |
| 		BST& nowEmpty = fullBst;
 | |
| 		nowEmpty = emptyBst;
 | |
| 		CompareTrees(emptyBst, nowEmpty);
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<7> ()
 | |
| 	{
 | |
| 		set_test_name("Clear");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 		initBST(bst);
 | |
| 
 | |
| 		BST bst2(bst);
 | |
| 
 | |
| 		BST bst3;
 | |
| 		bst3 = bst;
 | |
| 
 | |
| 		bst.Clear();
 | |
| 		CompareTrees(bst3, bst2);
 | |
| 		bst3.Clear();
 | |
| 
 | |
| 		BSTNode* curNode = bst.GetRoot();
 | |
| 		tut::ensure_equals("GetRoot() - Returned a node after the tree was cleared", curNode, NULL_NODE);
 | |
| 	}
 | |
| 
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<8> ()
 | |
| 	{
 | |
| 		set_test_name ("IsEmpty");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		BST bst;
 | |
| 		initBST(bst);
 | |
| 
 | |
| 		BST bst2(bst);
 | |
| 		bst = bst2;
 | |
| 		BST bst3;
 | |
| 		bst3 = bst;
 | |
| 		bst.Clear();
 | |
| 		bst3.Clear();
 | |
| 
 | |
| 		tut::ensure_not("IsEmpty() - The Tree is not empty", bst2.IsEmpty());
 | |
| 		bst = bst2; //for the remove stage
 | |
| 		bst2.Clear();
 | |
| 		tut::ensure("IsEmpty() - The Tree is Empty", bst2.IsEmpty());
 | |
| 		tut::ensure_equals("GetSize() - The Tree returned a non 0 size after it was cleared", bst2.GetSize(), 0);
 | |
| 	}
 | |
| 
 | |
| #if TEST_BST_REMOVE
 | |
| 	template<>
 | |
| 	template<>
 | |
| 	void tObject::test<9> ()
 | |
| 	{
 | |
| 		set_test_name ("Remove");
 | |
| 		gCurrentTest = get_test_name();
 | |
| 		if(!gDoRemove)
 | |
| 			return;
 | |
| 
 | |
| 		set<string>::iterator iter;
 | |
| 		BSTNode * curNode;
 | |
| 
 | |
| 		BST bst;
 | |
| 		initBST(bst);
 | |
| 
 | |
| 		BST bst2(bst);
 | |
| 		bst = bst2;
 | |
| 		BST bst3;
 | |
| 		bst3 = bst;
 | |
| 		bst.Clear();
 | |
| 		bst3.Clear();
 | |
| 
 | |
| 		bst = bst2;
 | |
| 		bst2.Clear();
 | |
| 
 | |
| 		for(int i = 0; i < BSTTestSize; i++){
 | |
| 			string key = generateKey();
 | |
| 			if(chosen.find(key) == chosen.end()){
 | |
| 				ensure_not("Remove() - Returned true when the value was not in the tree", bst.Remove(key));
 | |
| 			}
 | |
| 			else{
 | |
| 				--i;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		BSTNode * root = bst.GetRoot();
 | |
| 		chosen.erase(root->GetValue());
 | |
| 		bst.Remove(root->GetValue());
 | |
| 		root = NULL;
 | |
| 
 | |
| 		vector<string> randomv(chosen.begin(), chosen.end());
 | |
| 		random_shuffle(randomv.begin(), randomv.end());
 | |
| 
 | |
| 		for(vector<string>::iterator vIter = randomv.begin(); vIter != randomv.end(); vIter++){
 | |
| 			ensure("Remove() - Returned false whe nthe value was in the tree", bst.Remove(*vIter));
 | |
| 			ensure_not("Remove() - Returned true when the value was not in the tree", bst.Remove(*vIter));
 | |
| 
 | |
| 		}
 | |
| 		ensure_equals("Remove() - Size of tree is not 0 after removing all values", bst.GetSize(), 0);
 | |
| 		ensure_equals("GetRoot() - Did not return NULL after removing all values", bst.GetRoot(), NULL_NODE);
 | |
| 	}
 | |
| #endif
 | |
| }
 |