See More

// // Created by alex on 7/31/17. // #include "cpp_solutions/chapter_01_arrays_and_strings/chapter_01_includes.h" #include "cpp_solutions/chapter_02_linked_lists/chapter_02_includes.h" #include "cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h" #include "cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h" #include "cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h" #include "cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h" #include "cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h" #include "cpp_solutions/chapter_12_cpp/chapter_12_includes.h" #include "cpp_solutions/misc_exercises/misc_includes.h" #define CATCH_CONFIG_MAIN #include "cpp_solutions/third_party/Catch/include/catch.hpp" #include #include #include TEST_CASE("Chapter 01 - Problem 01 - isUnique()", "test"){ REQUIRE(chapter_01::isUnique("alex")); REQUIRE(!chapter_01::isUnique("aalex")); } TEST_CASE("Chapter 01 - Problem 02 - isPermutation()", "test"){ REQUIRE(!chapter_01::isPermutation("alex", "aalex")); REQUIRE(chapter_01::isPermutation("alex", "xela")); REQUIRE(!chapter_01::isPermutation("aabb", "aaaa")); REQUIRE(!chapter_01::isPermutation("aaaa", "aabb")); REQUIRE(!chapter_01::isPermutation("aaaa", "aa")); REQUIRE(chapter_01::isPermutation("", "")); } TEST_CASE("Chapter 01 - Problem 03 - URLify()", "test") { // expect 'Mr. John Smith' -> 'Mr.%20John%20Smith' std::string input1 = "Mr. John Smith "; std::string output1 = "Mr.%20John%20Smith%20"; chapter_01::URLify(input1); REQUIRE(input1 == output1); std::string input2 = ""; std::string output2 = ""; chapter_01::URLify(input2); REQUIRE(input2 == output2); std::string input3 = " "; std::string output3 = "%20"; chapter_01::URLify(input3); REQUIRE(input3 == output3); std::string input4 = "Alex"; std::string output4 = "Alex"; chapter_01::URLify(input4); REQUIRE(input4 == output4); } TEST_CASE("Chapter 01 - Problem 04 - palindromePermutation()", "test") { REQUIRE(chapter_01::palindromePermutation("tact coa")); REQUIRE(!chapter_01::palindromePermutation("Tact Coa")); REQUIRE(!chapter_01::palindromePermutation("xyz")); REQUIRE(chapter_01::palindromePermutation("AA B AA")); REQUIRE(!chapter_01::palindromePermutation("aA B AA")); } TEST_CASE("Chapter 01 - Problem 05 - oneAway()", "test"){ REQUIRE(chapter_01::oneAway("pale", "ple")); REQUIRE(chapter_01::oneAway("pale", "pale")); REQUIRE(chapter_01::oneAway("pale", "bale")); REQUIRE(!chapter_01::oneAway("pale", "bae")); REQUIRE(!chapter_01::oneAway("alex", "al")); REQUIRE(!chapter_01::oneAway("alex", "all")); REQUIRE(!chapter_01::oneAway("alex", "alll")); REQUIRE(chapter_01::oneAway("apple", "aple")); REQUIRE(chapter_01::oneAway("bale", "pale")); REQUIRE(chapter_01::oneAway("", "")); } TEST_CASE("Chapter 01 - Problem 06 - stringCompression()", "test"){ REQUIRE("a2b1c5a3" == chapter_01::stringCompression("aabcccccaaa")); REQUIRE("alex" == chapter_01::stringCompression("alex")); REQUIRE("" == chapter_01::stringCompression("")); REQUIRE("a10" == chapter_01::stringCompression("aaaaaaaaaa")); } TEST_CASE("Chapter 01 - Problem 07 - rotateMatrix()", "test"){ Eigen::MatrixXi input4x4(4,4); input4x4 << 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4; Eigen::MatrixXi input5x5(5,5); input5x5 << 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5; Eigen::MatrixXi output4x4(4,4); output4x4 << 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4; Eigen::MatrixXi output5x5(5,5); output5x5 << 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5; chapter_01::rotate(input4x4); chapter_01::rotate(input5x5); REQUIRE(input4x4.isApprox(output4x4)); REQUIRE(input5x5.isApprox(output5x5)); } TEST_CASE("Chapter 01 - Problem 08 - setZero()", "test"){ // assume rotations are clockwise Eigen::MatrixXi input4x4(4,4); input4x4 << 1, 2, 3, 4, 1, 2, 0, 4, 1, 2, 3, 4, 0, 2, 3, 4; Eigen::MatrixXi input5x5(5,5); input5x5 << 0, 2, 3, 4, 5, 1, 2, 0, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5; Eigen::MatrixXi output4x4(4,4); output4x4 << 0, 2, 0, 4, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0; Eigen::MatrixXi output5x5(5,5); output5x5 << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0; chapter_01::setZero(input4x4); chapter_01::setZero(input5x5); REQUIRE(input4x4.isApprox(output4x4)); REQUIRE(input5x5.isApprox(output5x5)); } TEST_CASE("Chapter 01 - Problem 09 - stringRotation()", "test"){ REQUIRE(chapter_01::stringRotation("waterbottle", "erbottlewat")); REQUIRE(!chapter_01::stringRotation("waterbottle", "erbottlewatx")); REQUIRE(chapter_01::stringRotation("", "")); } TEST_CASE("Chapter 02 - Basic LinkedList Functionality", "test"){ std::vector testVector = {1,2,3,4,5,6,7}; REQUIRE(testVector == chapter_02::listToVector(chapter_02::vectorToList(testVector))); } TEST_CASE("Chapter 02 - Problem 01 - removeDups()", "test"){ std::vector noDups = {1,7,3,6,5,4,2}; std::vector dups = {2,2,1,5,6,2,5,2,7,7}; std::vector fixedDups = {2,1,5,6,7}; std::vector emptyVec; // check that remove dups function doesn't affect lists with no dups chapter_02::SinglyLinkedNode* noDupsHead = chapter_02::vectorToList(noDups); chapter_02::removeDups(noDupsHead); REQUIRE(noDups == chapter_02::listToVector(noDupsHead)); // check case with duplicates chapter_02::SinglyLinkedNode* dupsHead = chapter_02::vectorToList(dups); chapter_02::removeDups(dupsHead); REQUIRE(fixedDups == chapter_02::listToVector(dupsHead)); // check case with empty list chapter_02::SinglyLinkedNode* emptyHead = chapter_02::vectorToList(emptyVec); chapter_02::removeDups(emptyHead); REQUIRE(emptyVec == chapter_02::listToVector(emptyHead)); } TEST_CASE("Chapter 02 - Problem 02 - returnKthToLast()", "test"){ std::vector testVec1 = {1,7,3,6,5,4,2}; std::vector testVec2 = {2,2,1,5,6,2,5,2,7,7}; std::vector testVec3; chapter_02::SinglyLinkedNode* testVec1Head = chapter_02::vectorToList(testVec1); chapter_02::SinglyLinkedNode* testVec2Head = chapter_02::vectorToList(testVec2); chapter_02::SinglyLinkedNode* testVec3Head = chapter_02::vectorToList(testVec3); REQUIRE(5 == chapter_02::returnKthToLast(testVec1Head, 3)->getValue()); REQUIRE(2 == chapter_02::returnKthToLast(testVec1Head, 1)->getValue()); REQUIRE(1 == chapter_02::returnKthToLast(testVec1Head, testVec1.size())->getValue()); REQUIRE(2 == chapter_02::returnKthToLast(testVec2Head, 3)->getValue()); REQUIRE(7 == chapter_02::returnKthToLast(testVec2Head, 1)->getValue()); REQUIRE(2 == chapter_02::returnKthToLast(testVec2Head, testVec2.size())->getValue()); REQUIRE(nullptr == chapter_02::returnKthToLast(testVec2Head, 0)); REQUIRE(nullptr == chapter_02::returnKthToLast(testVec1Head, 10)); REQUIRE(nullptr == chapter_02::returnKthToLast(testVec3Head, 10)); } TEST_CASE("Chapter 02 - Problem 03 - deleteMiddleNode()", "test"){ // create test dataset std::vector<:string> testVec = {"a", "b", "c", "d", "e", "f"}; std::vector<:string> expectedVec = {"a", "b", "d", "e", "f"}; chapter_02::SinglyLinkedNode<:string>* testVecHead = chapter_02::vectorToList(testVec); chapter_02::SinglyLinkedNode<:string>* expectedVecHead = chapter_02::vectorToList(expectedVec); // traverse input to find node with content "c" chapter_02::SinglyLinkedNode<:string>* head = testVecHead; while (head != nullptr && head->getValue() != "c"){ head = head->getNext(); } // head is not at location "c". call delete function chapter_02::deleteMiddleNode(head); // check that vec 1 and vec 2 are the same while (testVecHead != nullptr && expectedVecHead != nullptr){ REQUIRE(testVecHead->getValue() == expectedVecHead->getValue()); testVecHead = testVecHead->getNext(); expectedVecHead = expectedVecHead->getNext(); } } TEST_CASE("Chapter 02 - Problem 04 - partition()", "test"){ // create test dataset std::vector inputVec = {3, 5, 8, 5, 10, 2, 1}; std::vector expectedVec = {1, 2, 3, 5, 8, 5, 10}; chapter_02::SinglyLinkedNode* inputVecHead = chapter_02::vectorToList(inputVec); chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); // perform partition inputVecHead = chapter_02::partition(inputVecHead, 5); // check that vec 1 and vec 2 are the same while (inputVecHead != nullptr && expectedVecHead != nullptr){ REQUIRE(inputVecHead->getValue() == expectedVecHead->getValue()); inputVecHead = inputVecHead->getNext(); expectedVecHead = expectedVecHead->getNext(); } } TEST_CASE("Chapter 02 - Problem 05 - sumLists()", "test"){ // create test dataset // 9423 + 951 = 10374 std::vector n1Vec = {3, 2, 4, 9}; std::vector n2Vec = {1, 5, 9}; std::vector sumVecExpected = {4, 7, 3, 0, 1}; chapter_02::SinglyLinkedNode* n1Head = chapter_02::vectorToList(n1Vec); chapter_02::SinglyLinkedNode* n2Head = chapter_02::vectorToList(n2Vec); std::vector sumVecActual = chapter_02::listToVector(chapter_02::sumLists(n1Head, n2Head)); REQUIRE(sumVecExpected == sumVecActual); }; TEST_CASE("Chapter 02 - Problem 06 - palindrome()", "test"){ // create test dataset std::vector list1 = {0, 4, 7, 0, 0, 7, 4, 0}; std::vector list2 = {3, 5, 2, 5, 3}; std::vector list3 = {0, 1, 0, 1, 0, 1}; std::vector<:string> list4 = {"a", "l", "e", "x"}; std::vector<:string> list5 = {"A", "B", "B", "A"}; chapter_02::SinglyLinkedNode* head1 = chapter_02::vectorToList(list1); chapter_02::SinglyLinkedNode* head2 = chapter_02::vectorToList(list2); chapter_02::SinglyLinkedNode* head3 = chapter_02::vectorToList(list3); chapter_02::SinglyLinkedNode<:string>* head4 = chapter_02::vectorToList(list4); chapter_02::SinglyLinkedNode<:string>* head5 = chapter_02::vectorToList(list5); REQUIRE(chapter_02::palindrome(head1)); REQUIRE(chapter_02::palindrome(head2)); REQUIRE(!chapter_02::palindrome(head3)); REQUIRE(!chapter_02::palindrome(head4)); REQUIRE(chapter_02::palindrome(head5)); }; TEST_CASE("Chapter 02 - Problem 07 - intersection()", "test") { // list 1 chapter_02::SinglyLinkedNode* node1_6 = new chapter_02::SinglyLinkedNode(1, nullptr); chapter_02::SinglyLinkedNode* node1_5 = new chapter_02::SinglyLinkedNode(2, node1_6); chapter_02::SinglyLinkedNode* node1_4 = new chapter_02::SinglyLinkedNode(7, node1_5); chapter_02::SinglyLinkedNode* node1_3 = new chapter_02::SinglyLinkedNode(9, node1_4); chapter_02::SinglyLinkedNode* node1_2 = new chapter_02::SinglyLinkedNode(5, node1_3); chapter_02::SinglyLinkedNode* node1_1 = new chapter_02::SinglyLinkedNode(1, node1_2); chapter_02::SinglyLinkedNode* node1_0 = new chapter_02::SinglyLinkedNode(3, node1_1); // list 2 chapter_02::SinglyLinkedNode* node2_1 = new chapter_02::SinglyLinkedNode(6, node1_4); // intersection point chapter_02::SinglyLinkedNode* node2_0 = new chapter_02::SinglyLinkedNode(4, node2_1); // list 3 chapter_02::SinglyLinkedNode* node3_1 = new chapter_02::SinglyLinkedNode(6, nullptr); chapter_02::SinglyLinkedNode* node3_0 = new chapter_02::SinglyLinkedNode(4, node3_1); REQUIRE(node1_4 == chapter_02::intersection(node1_0, node2_0)); REQUIRE(nullptr == chapter_02::intersection(node1_0, node3_0)); REQUIRE(nullptr == chapter_02::intersection(static_cast<:singlylinkednode>*>(nullptr), static_cast<:singlylinkednode>*>(nullptr))); } TEST_CASE("Chapter 02 - Problem 08 - findLoop()", "test") { // see problem_2_8_explanation.pdf // example 1 chapter_02::SinglyLinkedNode* node1_7 = new chapter_02::SinglyLinkedNode(7, nullptr); chapter_02::SinglyLinkedNode* node1_6 = new chapter_02::SinglyLinkedNode(6, node1_7); chapter_02::SinglyLinkedNode* node1_5 = new chapter_02::SinglyLinkedNode(5, node1_6); chapter_02::SinglyLinkedNode* node1_4 = new chapter_02::SinglyLinkedNode(4, node1_5); chapter_02::SinglyLinkedNode* node1_3 = new chapter_02::SinglyLinkedNode(3, node1_4); chapter_02::SinglyLinkedNode* node1_2 = new chapter_02::SinglyLinkedNode(2, node1_3); chapter_02::SinglyLinkedNode* node1_1 = new chapter_02::SinglyLinkedNode(1, node1_2); chapter_02::SinglyLinkedNode* node1_0 = new chapter_02::SinglyLinkedNode(0, node1_1); node1_7->setNext(node1_5); REQUIRE(node1_5 == chapter_02::findLoop(node1_0)); // example 2 chapter_02::SinglyLinkedNode* node2_10 = new chapter_02::SinglyLinkedNode(10, nullptr); chapter_02::SinglyLinkedNode* node2_9 = new chapter_02::SinglyLinkedNode(9, node2_10); chapter_02::SinglyLinkedNode* node2_8 = new chapter_02::SinglyLinkedNode(8, node2_9); chapter_02::SinglyLinkedNode* node2_7 = new chapter_02::SinglyLinkedNode(7, node2_8); chapter_02::SinglyLinkedNode* node2_6 = new chapter_02::SinglyLinkedNode(6, node2_7); chapter_02::SinglyLinkedNode* node2_5 = new chapter_02::SinglyLinkedNode(5, node2_6); chapter_02::SinglyLinkedNode* node2_4 = new chapter_02::SinglyLinkedNode(4, node2_5); chapter_02::SinglyLinkedNode* node2_3 = new chapter_02::SinglyLinkedNode(3, node2_4); chapter_02::SinglyLinkedNode* node2_2 = new chapter_02::SinglyLinkedNode(2, node2_3); chapter_02::SinglyLinkedNode* node2_1 = new chapter_02::SinglyLinkedNode(1, node2_2); chapter_02::SinglyLinkedNode* node2_0 = new chapter_02::SinglyLinkedNode(0, node2_1); node2_10->setNext(node2_3); REQUIRE(node2_3 == chapter_02::findLoop(node2_0)); // example 3 REQUIRE(static_cast<:singlylinkednode>*>(nullptr) == chapter_02::findLoop(static_cast<:singlylinkednode>*>(nullptr))); } TEST_CASE("Chapter 03 - Stack", "test"){ chapter_03::Stack myStack; for (int i = 1; i <= 4; i++){ myStack.push(i); } std::vector tooShort = {3,2,1}; std::vector incorrect = {5,3,2,1}; std::vector justRight = {4,3,2,1}; std::vector tooLong = {4,3,2,1,1}; std::vector empty = {}; REQUIRE(myStack!=tooShort); REQUIRE(myStack!=tooLong); REQUIRE(myStack!=incorrect); REQUIRE(myStack==justRight); REQUIRE(myStack.peek()==4); REQUIRE(!myStack.isEmpty()); while (!myStack.isEmpty()){ empty.push_back(myStack.pop()); } REQUIRE(empty==justRight); REQUIRE(myStack.isEmpty()); REQUIRE(myStack.pop()==0); REQUIRE(myStack.peek()==0); } TEST_CASE("Chapter 03 - Problem 02 - StackMin()", "test"){ chapter_03::StackMin myStack; myStack.push(-8); myStack.push(-5); myStack.push(1); myStack.push(-6); REQUIRE(myStack.seeMin() == -8); myStack.push(-9); REQUIRE(myStack.seeMin() == -9); myStack.push(-15); myStack.push(-30); myStack.pop(); myStack.pop(); REQUIRE(myStack.seeMin() == -9); } TEST_CASE("Chapter 03 - Problem 04 - QueueViaStacks()", "test"){ chapter_03::QueueViaStacks myQueue; for (int i = 0; i < 10; i++) myQueue.enqueue(i); for (int i = 0; i < 5; i++) REQUIRE(myQueue.dequeue() == i); for (int i = 0; i < 5; i++) myQueue.enqueue(i); for (int i = 5; i < 10; i++) REQUIRE(myQueue.dequeue() == i); for (int i = 0; i < 5; i++) REQUIRE(myQueue.dequeue() == i); } TEST_CASE("Chapter 03 - Problem 05 - sortStack()", "test") { chapter_03::Stack stack; std::vector vector = {7, 6, 3, 5, 1, 2, 4}; for (int x : vector) { stack.push(x); } chapter_03::sortStack(stack); for (int x = 1; x <= 7; x++) { REQUIRE(stack.pop() == x); } } TEST_CASE("Chapter 03 - Problem 06 - AnimalShelter", "test") { chapter_03::AnimalShelter shelter; auto catA = chapter_03::Cat("a"); auto dogB = chapter_03::Dog("b"); auto dogC = chapter_03::Dog("c"); auto catD = chapter_03::Cat("d"); auto dogE = chapter_03::Dog("e"); auto catF = chapter_03::Cat("f"); shelter.enqueue(&catA); shelter.enqueue(&dogB); shelter.enqueue(&dogC); shelter.enqueue(&catD); shelter.enqueue(&dogE); shelter.enqueue(&catF); REQUIRE("a" == shelter.dequeueAny()->getName()); REQUIRE("b" == shelter.dequeueAny()->getName()); REQUIRE("c" == shelter.dequeueDog()->getName()); REQUIRE("d" == shelter.dequeueCat()->getName()); REQUIRE("e" == shelter.dequeueAny()->getName()); REQUIRE("f" == shelter.dequeueAny()->getName()); REQUIRE(nullptr == shelter.dequeueAny()); } TEST_CASE("Chapter 04 - Basic Graph Functionality", "test"){ chapter_02::TetraGraphNode node(1); chapter_02::TetraGraphNode* child0 = new chapter_02::TetraGraphNode(0); chapter_02::TetraGraphNode* child1 = new chapter_02::TetraGraphNode(1); chapter_02::TetraGraphNode* child2 = new chapter_02::TetraGraphNode(2); chapter_02::TetraGraphNode* child3 = new chapter_02::TetraGraphNode(3); node.addChild(child0, 0); node.addChild(child1, 1); node.addChild(child2, 2); node.addChild(child3, 3); std::vector<:tetragraphnode>*> children; node.getChildren(children); REQUIRE(children[0] == child0); REQUIRE(children[1] == child1); REQUIRE(children[2] == child2); REQUIRE(children[3] == child3); node.removeChild(0); node.removeChild(1); node.removeChild(2); node.removeChild(3); std::vector<:tetragraphnode>*> deletedChildren; node.getChildren(deletedChildren); REQUIRE(deletedChildren.size() == 0); // no need to delete children, because removeChildren does that for us. } TEST_CASE("Chapter 04 - Problem 01 - Route Between Nodes", "test"){ /* Implements this directed graph: 1 -> 2 -> 3 | v 4 -> 5 -> 6 | ^ v | 7 -> 8 */ chapter_02::TetraGraphNode* node1 = new chapter_02::TetraGraphNode(1); chapter_02::TetraGraphNode* node2 = new chapter_02::TetraGraphNode(2); chapter_02::TetraGraphNode* node3 = new chapter_02::TetraGraphNode(3); chapter_02::TetraGraphNode* node4 = new chapter_02::TetraGraphNode(4); chapter_02::TetraGraphNode* node5 = new chapter_02::TetraGraphNode(5); chapter_02::TetraGraphNode* node6 = new chapter_02::TetraGraphNode(6); chapter_02::TetraGraphNode* node7 = new chapter_02::TetraGraphNode(7); chapter_02::TetraGraphNode* node8 = new chapter_02::TetraGraphNode(8); node1->addChild(node2, 0); node2->addChild(node3, 0); node2->addChild(node4, 1); node4->addChild(node5, 0); node4->addChild(node7, 1); node5->addChild(node6, 0); node7->addChild(node8, 0); node8->addChild(node5, 0); REQUIRE(chapter_04::pathExistsDFS(node1, node6)); REQUIRE(chapter_04::pathExistsDFS(node7, node5)); REQUIRE(!chapter_04::pathExistsDFS(node3, node8)); REQUIRE(chapter_04::pathExistsDFS(node1, node8)); REQUIRE(!chapter_04::pathExistsDFS(static_cast<:tetragraphnode>*>(nullptr), static_cast<:tetragraphnode>*>(nullptr))); REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast<:tetragraphnode>*>(nullptr))); delete node1; delete node2; delete node3; delete node4; delete node5; delete node6; delete node7; delete node8; } TEST_CASE("Chapter 04 - Problem 02 - minimalTree()", "test"){ // test 1 std::vector sortedArray1 = {8, 9, 10, 11, 12, 13, 14}; chapter_02::BinaryNode* head1 = chapter_04::minimalTree(sortedArray1); std::vector expectedPostOrderTraversal1 = {8, 10, 9, 12, 14, 13, 11}; std::vector actualPostOrderTraversal1; chapter_02::bstToVector(actualPostOrderTraversal1, head1); REQUIRE(expectedPostOrderTraversal1.size() == actualPostOrderTraversal1.size()); for (int i = 0; i < actualPostOrderTraversal1.size(); i++) { REQUIRE(actualPostOrderTraversal1[i] == expectedPostOrderTraversal1[i]); } // test 2 std::vector sortedArray2 = {9, 10, 11, 12, 13, 14}; chapter_02::BinaryNode* head2 = chapter_04::minimalTree(sortedArray2); std::vector expectedPostOrderTraversal2 = {10, 9, 12, 14, 13, 11}; std::vector actualPostOrderTraversal2; chapter_02::bstToVector(actualPostOrderTraversal2, head2); REQUIRE(expectedPostOrderTraversal2.size() == actualPostOrderTraversal2.size()); for (int i = 0; i < actualPostOrderTraversal2.size(); i++) { REQUIRE(actualPostOrderTraversal2[i] == expectedPostOrderTraversal2[i]); } } TEST_CASE("Chapter 04 - Problem 03 - makeLL()", "test"){ /* * Construct a binary tree of the form * 0 * 12 * 3456 */ chapter_02::BinaryNode* head = new chapter_02::BinaryNode(0); chapter_02::BinaryNode* child1 = new chapter_02::BinaryNode(1); chapter_02::BinaryNode* child2 = new chapter_02::BinaryNode(2); chapter_02::BinaryNode* child3 = new chapter_02::BinaryNode(3); chapter_02::BinaryNode* child4 = new chapter_02::BinaryNode(4); chapter_02::BinaryNode* child5 = new chapter_02::BinaryNode(5); chapter_02::BinaryNode* child6 = new chapter_02::BinaryNode(6); head->setLeft(child1); head->setRight(child2); child1->setLeft(child3); child1->setRight(child4); child2->setLeft(child5); child2->setRight(child6); // execute conversion to linked list std::vector<:singlylinkednode>*> vectorOfHeads; std::vector<:singlylinkednode>*> vectorOfTails; std::vector expected = {0, 1, 2, 3, 4, 5, 6}; chapter_04::makeLL(vectorOfHeads, vectorOfTails, head); std::vector actual = chapter_04::vectorFromVectorOfLLs(vectorOfHeads); // test for (int i = 0; i < expected.size(); i++) { REQUIRE(expected[i] == actual[i]); } } TEST_CASE("Chapter 04 - Problem 04 - checkBalanced()", "test") { /* balanced tree: node111, node121,node122, node131,node132,nullptr,nullptr, nullptr,nullptr,nullptr,nullptr, */ chapter_02::BinaryNode node132(132, nullptr, nullptr); chapter_02::BinaryNode node131(131, nullptr, nullptr); chapter_02::BinaryNode node122(122, nullptr, nullptr); chapter_02::BinaryNode node121(121, &node131, &node132); chapter_02::BinaryNode node111(111, &node121, &node122); chapter_04::NodeStatus status1 = chapter_04::checkBalanced(&node111); REQUIRE(status1.balanced); REQUIRE(status1.subtreeSize == 3); /* unbalanced tree: node211, node221,node222, node231,node232,nullptr,nullptr, node241,nullptr,nullptr,nullptr, nullptr,nullptr, */ chapter_02::BinaryNode node241(241, nullptr, nullptr); chapter_02::BinaryNode node232(232, nullptr, nullptr); chapter_02::BinaryNode node231(231, &node241, nullptr); chapter_02::BinaryNode node222(222, nullptr, nullptr); chapter_02::BinaryNode node221(221, &node231, &node232); chapter_02::BinaryNode node211(211, &node221, &node222); chapter_04::NodeStatus status2 = chapter_04::checkBalanced(&node211); REQUIRE(!status2.balanced); REQUIRE(status2.subtreeSize == 4); } TEST_CASE("Chpater 04 - Problem 05 - validateBST()", "test") { // construct a binary tree chapter_02::BinaryNode node1(1); chapter_02::BinaryNode node2(2); chapter_02::BinaryNode node3(3); chapter_02::BinaryNode node4(4); chapter_02::BinaryNode node5(5); chapter_02::BinaryNode node6(6); chapter_02::BinaryNode node8(8); chapter_02::BinaryNode node10(10); /* 8 4, 10 2, 6, 1, 3, 5, */ node8.setLeft(&node4); node8.setRight(&node10); node4.setLeft(&node2); node4.setRight(&node6); node2.setLeft(&node1); node2.setRight(&node3); node6.setLeft(&node5); REQUIRE(chapter_04::validateBST(&node8)); // add node that breaks BST rule chapter_02::BinaryNode node9(9); node6.setRight(&node9); REQUIRE(!chapter_04::validateBST(&node8)); } TEST_CASE("Chapter 04 - Problem 06 - successor()", "test"){ // construct a binary tree chapter_02::BinaryNode* node0 = new chapter_02::BinaryNode(0); chapter_02::BinaryNode* node1 = new chapter_02::BinaryNode(1); chapter_02::BinaryNode* node2 = new chapter_02::BinaryNode(2); chapter_02::BinaryNode* node3 = new chapter_02::BinaryNode(3); chapter_02::BinaryNode* node4 = new chapter_02::BinaryNode(4); chapter_02::BinaryNode* node5 = new chapter_02::BinaryNode(5); chapter_02::BinaryNode* node6 = new chapter_02::BinaryNode(6); chapter_02::BinaryNode* node7 = new chapter_02::BinaryNode(7); chapter_02::BinaryNode* node8 = new chapter_02::BinaryNode(8); chapter_02::BinaryNode* node9 = new chapter_02::BinaryNode(9); chapter_02::BinaryNode* node10 = new chapter_02::BinaryNode(10); /* 8 4 10 2 6 1 3 5 0 9 In-order traversal: 1, 2, 0, 3, 9, 4, 5, 6, 8, 10 */ node0->setParent(node3); node1->setParent(node2); node3->setParent(node2); node2->setParent(node4); node5->setParent(node6); node6->setParent(node4); node4->setParent(node8); node9->setParent(node3); node10->setParent(node8); node8->setLeft(node4); node8->setRight(node10); node4->setLeft(node2); node4->setRight(node6); node2->setLeft(node1); node2->setRight(node3); node6->setLeft(node5); node3->setLeft(node0); node3->setRight(node9); REQUIRE(node8 == chapter_04::successor(node6)); REQUIRE(node5 == chapter_04::successor(node4)); REQUIRE(node0 == chapter_04::successor(node2)); REQUIRE(node3 == chapter_04::successor(node0)); REQUIRE(node4 == chapter_04::successor(node9)); REQUIRE(nullptr == chapter_04::successor(node10)); } TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { // no circular dependencies std::vector projects1 = {'a', 'b', 'c', 'd', 'e', 'f'}; std::vector<:pair char>> dependencies1 = { std::pair('a', 'd'), std::pair('f', 'b'), std::pair('b', 'd'), std::pair('f', 'a'), std::pair('d', 'c')}; std::vector projects2 = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; std::vector<:pair char>> dependencies2 = { std::pair('f', 'c'), std::pair('f', 'b'), std::pair('f', 'a'), std::pair('c', 'a'), std::pair('b', 'a'), std::pair('a', 'e'), std::pair('b', 'e'), std::pair('d', 'g')}; // add circular dependency std::vector<:pair char>> dependencies3 = { std::pair('a', 'd'), std::pair('f', 'b'), std::pair('b', 'd'), std::pair('f', 'a'), std::pair('d', 'c'), std::pair('c', 'a')}; // verify output std::vector actualBuildOrder1 = {}; std::vector actualBuildOrder2 = {}; std::vector actualBuildOrder3 = {}; std::vector expectedBuildOrder1 = {'e', 'f', 'b', 'a', 'd', 'c'}; std::vector expectedBuildOrder2 = {'d', 'f', 'g', 'c', 'b', 'a', 'e'}; chapter_04::buildOrder(projects1, dependencies1, actualBuildOrder1); chapter_04::buildOrder(projects2, dependencies2, actualBuildOrder2); chapter_04::buildOrder(projects1, dependencies3, actualBuildOrder3); for (int i = 0; i < actualBuildOrder1.size(); i++) { REQUIRE(actualBuildOrder1[i] == expectedBuildOrder1[i]); } for (int i = 0; i < actualBuildOrder2.size(); i++) { REQUIRE(actualBuildOrder2[i] == expectedBuildOrder2[i]); } REQUIRE(actualBuildOrder3.empty()); } TEST_CASE("Chapter 04 - Problem 08 - firstCommonAncestor()", "test") { /* construct binary tree 7 4 3 10 5 6 15 21 17 25 */ chapter_02::BinaryNode n21(21); chapter_02::BinaryNode n17(17); chapter_02::BinaryNode n15(15, &n21, &n17); chapter_02::BinaryNode n6(6); chapter_02::BinaryNode n3(3, &n6, &n15); chapter_02::BinaryNode n10(10); chapter_02::BinaryNode n5(5); chapter_02::BinaryNode n4(4, &n10, &n5); chapter_02::BinaryNode n7(7, &n4, &n3); chapter_02::BinaryNode n25(25); REQUIRE(&n3 == chapter_04::firstCommonAncestor(&n7, &n6, &n21)); REQUIRE(&n7 == chapter_04::firstCommonAncestor(&n7, &n10, &n21)); REQUIRE(nullptr == chapter_04::firstCommonAncestor(&n7, &n15, &n25)); REQUIRE(nullptr == chapter_04::firstCommonAncestor(&n7, &n7, &n7)); // a node is not its own ancestor REQUIRE(&n7 == chapter_04::firstCommonAncestor(&n7, &n3, &n4)); } TEST_CASE("Chapter 04 - Problem 10 - checkSubtree()", "test") { /* construct binary tree 7 4 3 10 5 6 15 21 17 25 */ chapter_02::BinaryNode n21(21); chapter_02::BinaryNode