From 5e1fbe49efac0577601aa714a6982959b0489845 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 21 Jan 2019 16:38:06 -0800 Subject: [PATCH 001/176] make skeleton for 4.4 cpp --- CMakeLists.txt | 2 +- README.md | 4 +-- .../chapter_04_includes.h | 1 + .../problem_04_03_make_ll.py | 2 +- .../problem_04_04_check_balanced.py | 30 +++++++++++++++++++ .../problem_04_04_is_balanced.py | 14 --------- tests.cpp | 4 +++ tests.py | 8 ++--- 8 files changed, 43 insertions(+), 22 deletions(-) create mode 100644 python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py delete mode 100644 python_solutions/chapter_04_trees_and_graphs/problem_04_04_is_balanced.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 57f1f89..d37034e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,6 @@ set(SOURCE_FILES cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp - ) + cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/README.md b/README.md index 054775a..991a98a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `3 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `4 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `34 / 151` +Total: `35 / 151` ### Build Process #### Mac: diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index 394a031..f7208bc 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -6,3 +6,4 @@ #include "problem_04_01_pathExists.h" #include "problem_04_02_minimalTree.h" #include "problem_04_03_makeLL.h" +#include "problem_04_04_checkBalanced.h" diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_03_make_ll.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_03_make_ll.py index 81a5f1c..632d7de 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_03_make_ll.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_03_make_ll.py @@ -1,5 +1,5 @@ """ -Chapter 04 - Problem 02 - Minimal Tree +Chapter 04 - Problem 03 - List of Depths Problem Statement: Given a binary tree, design an algorithm which creates a linked list diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py new file mode 100644 index 0000000..e7a42ba --- /dev/null +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py @@ -0,0 +1,30 @@ +""" +Chapter 04 - Problem 04 - Check Balanced + +Problem Statement: +Implement a function to check if a binary tree is balanced. +For the purposes of this question, a balanced tree is defined to be a tree +such that the heights of the two subtrees of any node never differ by more than one. + + +Solution: +Implement a recursion-based solution in which a recursive checkBalanced() is called on +every node. At each recursive call, the function returns (1) the number of child nodes beneath +it and (2) boolean if the numbers returned by its left and right children differ by more than 1. The recursive +terminating condition is a node which does not have any children: in this case the node returns 0 and true. + +Time complexity: O(N) +Space complexity: O(N) +""" + + +def check_height(root): + if root is None: + return [True, 0] + [left_balanced, left_height] = check_height(root.left) + [right_balanced, right_height] = check_height(root.right) + return [left_balanced and right_balanced and abs(left_height - right_height) <= 1, 1 + max(left_height, right_height)] + + +def check_balanced(root): + return check_height(root)[0] diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_04_is_balanced.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_04_is_balanced.py deleted file mode 100644 index 6f61b9f..0000000 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_04_is_balanced.py +++ /dev/null @@ -1,14 +0,0 @@ -def check_height(root): - if root is None: - return [True, 0] - [left_balanced, left_height] = check_height(root.left) - [right_balanced, right_height] = check_height(root.right) - return [left_balanced and right_balanced and abs(left_height - right_height) <= 1, 1 + max(left_height, right_height)] - - -def is_balanced(root): - """ - For the purposes of this question, a balanced tree is defined to be a tree - such that the heights of the two subtrees of any node never differ by more than one. - """ - return check_height(root)[0] diff --git a/tests.cpp b/tests.cpp index aea0658..1e1a169 100644 --- a/tests.cpp +++ b/tests.cpp @@ -489,6 +489,10 @@ TEST_CASE("Chapter 04 - Problem 03 - makeLL()", "test"){ } } +TEST_CASE("Chapter 04 - Problem 04 - checkBalanced()", "test") { + +} + TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } diff --git a/tests.py b/tests.py index c95e126..0bd663b 100644 --- a/tests.py +++ b/tests.py @@ -31,7 +31,7 @@ from python_solutions.chapter_04_trees_and_graphs import problem_04_01_path_exists as p_4_1 from python_solutions.chapter_04_trees_and_graphs import problem_04_02_make_bst as p_4_2 from python_solutions.chapter_04_trees_and_graphs import problem_04_03_make_ll as p_4_3 -from python_solutions.chapter_04_trees_and_graphs import problem_04_04_is_balanced as p_4_4 +from python_solutions.chapter_04_trees_and_graphs import problem_04_04_check_balanced as p_4_4 from python_solutions.chapter_04_trees_and_graphs import problem_04_05_validate_BST as p_4_5 from python_solutions.chapter_04_trees_and_graphs import problem_04_06_successor as p_4_6 from python_solutions.chapter_04_trees_and_graphs import problem_04_07_build_order as p_4_7 @@ -588,7 +588,7 @@ def test_problem_4_4(self): node121 = tb.BinaryNode("node", node131, node132) node122 = tb.BinaryNode("leaf", None, None) root1 = tb.BinaryNode("root", node121, node122) - self.assertTrue(p_4_4.is_balanced(root1)) + self.assertTrue(p_4_4.check_balanced(root1)) """ unbalanced tree: root, @@ -603,10 +603,10 @@ def test_problem_4_4(self): node221 = tb.BinaryNode("node", node231, node232) node222 = tb.BinaryNode("leaf", None, None) root2 = tb.BinaryNode("root", node221, node222) - self.assertFalse(p_4_4.is_balanced(root2)) + self.assertFalse(p_4_4.check_balanced(root2)) def test_problem_4_5(self): - # contstruct a binary tree + # construct a binary tree node1 = tb.BinaryNode(1) node2 = tb.BinaryNode(2) node3 = tb.BinaryNode(3) From 4a94f51bd0dcb4ae5006d98384f64a427dd4e26f Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 21 Jan 2019 16:38:40 -0800 Subject: [PATCH 002/176] implement interface for 4.4 cpp --- .../problem_04_04_checkBalanced.h | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h new file mode 100644 index 0000000..f18c0e2 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h @@ -0,0 +1,30 @@ +/* +Chapter 04 - Problem 04 - Check Balanced + +Problem Statement: +Implement a function to check if a binary tree is balanced. +For the purposes of this question, a balanced tree is defined to be a tree +such that the heights of the two subtrees of any node never differ by more than one. + +Solution: +Implement a solution in which a recursive checkBalanced() function is called on +every node. At each recursive call, the function returns (1) the number of child nodes beneath +it and (2) boolean if the numbers returned by its left and right children differ by more than 1. The recursive +terminating condition is a node which does not have any children: in this case the node returns 0 and true. + +Time complexity: O(N) +Space complexity: O(N) +*/ +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + struct NodeStatus { + bool balanced; + int children; + }; + + template + void checkBalanced(chapter_02::BinaryNode* head, NodeStatus& status) { + + } +} // namespace chapter_04 From e4b0154249ea10208688f21b53efc1c86abf213e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 21 Jan 2019 17:04:46 -0800 Subject: [PATCH 003/176] WIP implement test for 4.4 cpp. macbook is dying. --- cpp_solutions/chapter_02_linked_lists/Node.h | 4 ++ .../problem_04_04_checkBalanced.h | 6 ++- tests.cpp | 39 +++++++++++++++++++ tests.py | 8 ++-- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 8c5e9be..89e6234 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -76,6 +76,10 @@ namespace chapter_02{ _left = nullptr; _right = nullptr; } + BinaryNode(T value, BinaryNode* left, BinaryNode* right) : Node(value){ + _left = left; + _right = right; + } void setLeft(BinaryNode* left) { _left = left; } diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h index f18c0e2..22fc920 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h @@ -24,7 +24,9 @@ namespace chapter_04 { }; template - void checkBalanced(chapter_02::BinaryNode* head, NodeStatus& status) { - + NodeStatus checkBalanced(chapter_02::BinaryNode* head) { + NodeStatus status; + status.balanced = false; + status.children = 0; } } // namespace chapter_04 diff --git a/tests.cpp b/tests.cpp index 1e1a169..43844b9 100644 --- a/tests.cpp +++ b/tests.cpp @@ -490,6 +490,45 @@ TEST_CASE("Chapter 04 - Problem 03 - makeLL()", "test"){ } TEST_CASE("Chapter 04 - Problem 04 - checkBalanced()", "test") { +/* +balanced tree: + +root, +node,leaf, +leaf,leaf,_,_, +_,_,_,_, +*/ + +chapter_02::BinaryNode node131(131, nullptr, nullptr); +chapter_02::BinaryNode node132(132, nullptr, nullptr); +chapter_02::BinaryNode node121(121, &node131, &node132); +chapter_02::BinaryNode node122(122, nullptr, nullptr); +chapter_02::BinaryNode node111(111, &node121, &node122); +chapter_04::NodeStatus status1 = chapter_04::checkBalanced(&node111); +REQUIRE(status1.balanced == true); +REQUIRE(status1.children == 4); + +/* +unbalanced tree: +root, +node,leaf, +node,leaf,_,_, +leaf,_,_,_, +_,_, +*/ + + +/* +node241 = tb.BinaryNode("leaf", None, None) +node231 = tb.BinaryNode("node", node241, None) +node232 = tb.BinaryNode("leaf", None, None) +node221 = tb.BinaryNode("node", node231, node232) +node222 = tb.BinaryNode("leaf", None, None) +root2 = tb.BinaryNode("root", node221, node222) +self.assertFalse(p_4_4.check_balanced(root2)) +*/ + + } diff --git a/tests.py b/tests.py index 0bd663b..45773ef 100644 --- a/tests.py +++ b/tests.py @@ -587,8 +587,8 @@ def test_problem_4_4(self): node132 = tb.BinaryNode("leaf", None, None) node121 = tb.BinaryNode("node", node131, node132) node122 = tb.BinaryNode("leaf", None, None) - root1 = tb.BinaryNode("root", node121, node122) - self.assertTrue(p_4_4.check_balanced(root1)) + node111 = tb.BinaryNode("root", node121, node122) + self.assertTrue(p_4_4.check_balanced(node111)) """ unbalanced tree: root, @@ -602,8 +602,8 @@ def test_problem_4_4(self): node232 = tb.BinaryNode("leaf", None, None) node221 = tb.BinaryNode("node", node231, node232) node222 = tb.BinaryNode("leaf", None, None) - root2 = tb.BinaryNode("root", node221, node222) - self.assertFalse(p_4_4.check_balanced(root2)) + root211 = tb.BinaryNode("root", node221, node222) + self.assertFalse(p_4_4.check_balanced(root211)) def test_problem_4_5(self): # construct a binary tree From ee26191240be1f736bf48a210c180d25686a0573 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 21 Jan 2019 21:46:12 -0800 Subject: [PATCH 004/176] implement tests for 4.4 cpp --- .../problem_04_04_checkBalanced.h | 1 + tests.cpp | 28 ++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h index 22fc920..8abe171 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h @@ -28,5 +28,6 @@ namespace chapter_04 { NodeStatus status; status.balanced = false; status.children = 0; + return status; } } // namespace chapter_04 diff --git a/tests.cpp b/tests.cpp index 43844b9..291453c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -493,10 +493,10 @@ TEST_CASE("Chapter 04 - Problem 04 - checkBalanced()", "test") { /* balanced tree: -root, -node,leaf, -leaf,leaf,_,_, -_,_,_,_, +node111, +node121,node122, +node131,node132,nullptr,nullptr, +nullptr,nullptr,nullptr,nullptr, */ chapter_02::BinaryNode node131(131, nullptr, nullptr); @@ -510,14 +510,22 @@ REQUIRE(status1.children == 4); /* unbalanced tree: -root, -node,leaf, -node,leaf,_,_, -leaf,_,_,_, -_,_, +node211, +node221,node222, +node231,node232,nullptr,nullptr, +node241,nullptr,nullptr,nullptr, +nullptr,nullptr, */ - +chapter_02::BinaryNode node241(241, nullptr, nullptr); +chapter_02::BinaryNode node231(231, &node241, nullptr); +chapter_02::BinaryNode node232(232, nullptr, nullptr); +chapter_02::BinaryNode node221(221, &node231, &node232); +chapter_02::BinaryNode node222(222, nullptr, nullptr); +chapter_02::BinaryNode node211(211, &node221, &node222); +chapter_04::NodeStatus status2 = chapter_04::checkBalanced(&node211); +REQUIRE(status1.balanced == false); +REQUIRE(status1.children == 5); /* node241 = tb.BinaryNode("leaf", None, None) node231 = tb.BinaryNode("node", node241, None) From 39b73dbde0e98341c72ecba92ac97d9c5d2e94b0 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 21 Jan 2019 22:58:39 -0800 Subject: [PATCH 005/176] implement 4.4 cpp --- .../problem_04_04_checkBalanced.h | 25 ++++++++++++++--- tests.cpp | 27 ++++++------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h index 8abe171..b9bd3c7 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h @@ -20,14 +20,33 @@ Space complexity: O(N) namespace chapter_04 { struct NodeStatus { bool balanced; - int children; + int subtreeSize; }; template NodeStatus checkBalanced(chapter_02::BinaryNode* head) { NodeStatus status; - status.balanced = false; - status.children = 0; + // terminating condition + if (head == nullptr) { + status.balanced = true; + status.subtreeSize = 0; + return status; + } + + // recursive calls + NodeStatus leftStatus = checkBalanced(head->getLeft()); + NodeStatus rightStatus = checkBalanced(head->getRight()); + + // check for imbalance in left and right children + if (std::abs(leftStatus.subtreeSize - rightStatus.subtreeSize) > 1) { + status.balanced = false; + } else { + status.balanced = true; + } + + // check for imbalance in subtrees + status.balanced = status.balanced && leftStatus.balanced && rightStatus.balanced; + status.subtreeSize = std::max(leftStatus.subtreeSize, rightStatus.subtreeSize) + 1; return status; } } // namespace chapter_04 diff --git a/tests.cpp b/tests.cpp index 291453c..9f2ad60 100644 --- a/tests.cpp +++ b/tests.cpp @@ -499,17 +499,18 @@ node131,node132,nullptr,nullptr, nullptr,nullptr,nullptr,nullptr, */ -chapter_02::BinaryNode node131(131, nullptr, nullptr); chapter_02::BinaryNode node132(132, nullptr, nullptr); -chapter_02::BinaryNode node121(121, &node131, &node132); +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 == true); -REQUIRE(status1.children == 4); +REQUIRE(status1.subtreeSize == 3); /* unbalanced tree: + node211, node221,node222, node231,node232,nullptr,nullptr, @@ -518,26 +519,14 @@ nullptr,nullptr, */ chapter_02::BinaryNode node241(241, nullptr, nullptr); -chapter_02::BinaryNode node231(231, &node241, nullptr); chapter_02::BinaryNode node232(232, nullptr, nullptr); -chapter_02::BinaryNode node221(221, &node231, &node232); +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(status1.balanced == false); -REQUIRE(status1.children == 5); -/* -node241 = tb.BinaryNode("leaf", None, None) -node231 = tb.BinaryNode("node", node241, None) -node232 = tb.BinaryNode("leaf", None, None) -node221 = tb.BinaryNode("node", node231, node232) -node222 = tb.BinaryNode("leaf", None, None) -root2 = tb.BinaryNode("root", node221, node222) -self.assertFalse(p_4_4.check_balanced(root2)) -*/ - - - +REQUIRE(status2.balanced == false); +REQUIRE(status2.subtreeSize == 4); } TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ From 21f64f19ac9889f02d1abf674a4ee1545477e4f3 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 21 Jan 2019 23:46:30 -0800 Subject: [PATCH 006/176] reorganize readme for clarity --- README.md | 83 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 991a98a..bfb3ff1 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Total: `56 / 145` Total: `35 / 151` -### Build Process +### Building: #### Mac: Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: @@ -76,7 +76,56 @@ Mac usage requires the package managers Homebrew and Pip which is done for you i make configure-ubuntu #### Windows: -The project can be developed on Windows using Visual Studio 2017. First get the code: +For Windows users, I recommend developing this project using the [Windows Subsystem +for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) feature +of Windows 10 and then following the Ubuntu build and testing instructions inside WSL. +This recommendation is due to the use of Ubuntu, CMake, and makefile based build and execution +systems on the servers that automatically test changes to the code. For more on Windows +development, see the `Appendix` section at the end of this page. + +### Testing: +Testing is the most important part of this project: *only* +the unit tests define the problem being solved. In the root +directory, execute the following to run all tests in Python and C++: + + make test + +`make test` is the command I use most while developing this project. My workflow follows: + +1. I read a problem and encode the problem definition by implementing its unit tests. +2. I execute `make test` to see where the project fails to satisfy the unit tests. +3. I add to the implementation of the problem solution until `make test` succeeds. + +### Optional: Generating a Test Coverage % Report Locally (Python support only): +This will show exactly which lines are not covered by tests in each Python source file: + + pip install coverage + make test_coverage + +### Contributing +The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. +I definitely need help! PRs are of course very welcome. The work has become quite time consuming because each solution is *living* +code that actually gets executed. Thus, each solution needs its own small dataset and infrastructure in order to be tested. +Just writing the test for a problem is often harder than solving the problem itself. Here are some ways you can help: + +1. Fixing bugs :bug:. +2. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). +3. Adding more unit tests to increase the test coverage %. +4. Implementing automated C++ test coverage measurement using [gcov](http://gcc.gnu.org/onlinedocs/gcc/Gcov.html). +5. Integrating automated test coverage % reporting for both Python and C++ via [Coveralls](Coveralls.io). +6. Adding prose solution descriptions for problems that don't have them. + +If you have any contributions, please make a PR to the `master` branch. Feel free to message me for clarification on any of +the above items. + +### Appendix: Windows Development +On my own Windows machine, I develop using [CLion](https://www.jetbrains.com/clion/) running +natively in Windows and test the code using `make test` in a WSL terminal window. +For users who do not want to use WSL, I have developed the build and test methodology below: + +#### Building +The project can be developed purely on Windows without WSL by using Visual Studio 2017. +First clone the code: git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git cd ctci @@ -94,13 +143,7 @@ to tell Visual Studio to download PDBs it needs. Additionally, [this article](ht describes Visual Studio CMake support in more detail if you're interested. A CMakeSettings.json file in the root project directory sets the location of the Visual Studio build folder to be inside the root folder of the project. -### Running Tests: -#### Mac & Ubuntu: -In the root directory, execute the following to run all tests in Python and C++: - - make test - -#### Windows: +#### Testing Running the tests and seeing their output is best done from a PowerShell window since VisualStudio in CMake mode does *not* allow the console output of the `tests.exe` and `tests.py` files to remain visible even when pressing CTRL + F5 as described [in this post](https://stackoverflow.com/a/1775870) which applies to @@ -114,25 +157,3 @@ In the meantime, from the project root directory, you can run the Python tests u ... and you can run the C++ tests using ... .\build\x64-Debug\tests.exe - -### Optional: Generating a Test Coverage % Report Locally (Python support only): -This will show exactly which lines are not covered by tests in each Python source file: - - pip install coverage - make test_coverage - -### Contributing -The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. -I definitely need help! PRs are of course very welcome. The work has become quite time consuming because each solution is *living* -code that actually gets executed. Thus, each solution needs its own small dataset and infrastructure in order to be tested. -Just writing the test for a problem is often harder than solving the problem itself. Here are some ways you can help: - -0. Fixing bugs :bug:. -1. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). -2. Adding more unit tests to increase the test coverage %. -3. Implementing automated C++ test coverage measurement using [gcov](http://gcc.gnu.org/onlinedocs/gcc/Gcov.html). -4. Integrating automated test coverage % reporting for both Python and C++ via [Coveralls](Coveralls.io). -5. Adding prose solution descriptions for problems that don't have them. - -If you have any contributions, please make a PR to the `master` branch. Feel free to message me for clarification on any of -the above items. From 3c2bc037b232938a2b60d5da3de047a8ee637378 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 22 Jan 2019 12:48:41 -0800 Subject: [PATCH 007/176] implement 4.5 C++ --- CMakeLists.txt | 3 +- .../chapter_04_includes.h | 1 + .../problem_04_05_validateBST.h | 34 ++++++++++++++ .../problem_04_05_validate_BST.py | 25 ++++++++++ tests.cpp | 47 +++++++++++++++---- 5 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d37034e..be4f23e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,6 @@ set(SOURCE_FILES # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file - cpp_solutions/misc_exercises/integralImage.cpp - cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h) + cpp_solutions/misc_exercises/integralImage.cpp) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index f7208bc..d653fc0 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -7,3 +7,4 @@ #include "problem_04_02_minimalTree.h" #include "problem_04_03_makeLL.h" #include "problem_04_04_checkBalanced.h" +#include "problem_04_05_validateBST.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h new file mode 100644 index 0000000..fc04d38 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h @@ -0,0 +1,34 @@ +/* +Chapter 04 - Problem 05 - Validate BST + +Problem Statement: +Implement a function to check if a binary tree is a binary search tree (BST). + +Solution: +A BST is defined as a binary tree in which every node is less than all nodes to +its right and greater than all nodes to its left. It is not enough to just check that each +node is greater or less than its parent. If the node is a right child, it must be greater than its +parent but also less than all nodes to the right of its parent. If the node is a left child, it must be less +than its parent, but also greater than all nodes to the left of its parent. + +To validate a BST according to these rules, we recursively traverse the tree and check if each node's value +is between min and max values. The min and max values are initialized to +Inf and -Inf and we update the +min and max values as we traverse down the tree. For example, at the head of the tree, min=-Inf and max=+Inf thus +any head value will pass the test. For the left child of the head, min=-Inf and max=head_value while for the +right child of the head, min=head_value and max=+Inf. We repeat this pattern for all nodes and return false +if a node is not in bounds. + +Time complexity: O(N) +Space complexity: O(N) +*/ + +#include + +namespace chapter_04 { + template + bool validateBST(chapter_02::BinaryNode* head, T min = std::numeric_limits::min(), T max = std::numeric_limits::max()) { + if (head == nullptr) return true; // lack of a node is considered valid + if (head->getValue() > max || head->getValue() < min) return false; + return validateBST(head->getLeft(), min, head->getValue()) && validateBST(head->getRight(), head->getValue(), max); + } +} // namespace chapter_04 diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py index bb57822..ee7fb68 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py @@ -1,3 +1,28 @@ +""" +Chapter 04 - Problem 05 - Validate BST + +Problem Statement: +Implement a function to check if a binary tree is a binary search tree (BST). + +Solution: +A BST is defined as a binary tree in which every node is less than all nodes to +its right and greater than all nodes to its left. It is not enough to just check that each +node is greater or less than its parent. If the node is a right child, it must be greater than its +parent but also less than all nodes to the right of its parent. If the node is a left child, it must be less +than its parent, but also greater than all nodes to the left of its parent. + +To validate a BST according to these rules, we recursively traverse the tree and check if each node's value +is between min and max values. The min and max values are initialized to +Inf and -Inf and we update the +min and max values as we traverse down the tree. For example, at the head of the tree, min=-Inf and max=+Inf thus +any head value will pass the test. For the left child of the head, min=-Inf and max=head_value while for the +right child of the head, min=head_value and max=+Inf. We repeat this pattern for all nodes and return false +if a node is not in bounds. + +Time complexity: O(N) +Space complexity: O(N) +""" + + def validate_BST_helper(node, min, max): if node is None: return True diff --git a/tests.cpp b/tests.cpp index 9f2ad60..2a20859 100644 --- a/tests.cpp +++ b/tests.cpp @@ -417,12 +417,12 @@ TEST_CASE("Chapter 04 - Problem 01 - Route Between Nodes", "test"){ node5->addChild(node6, 0); node7->addChild(node8, 0); node8->addChild(node5, 0); - REQUIRE(chapter_04::pathExistsDFS(node1, node6) == true); - REQUIRE(chapter_04::pathExistsDFS(node7, node5) == true); - REQUIRE(chapter_04::pathExistsDFS(node3, node8) == false); - REQUIRE(chapter_04::pathExistsDFS(node1, node8) == true); - REQUIRE(chapter_04::pathExistsDFS(static_cast*>(nullptr), static_cast*>(nullptr)) == false); - REQUIRE(chapter_04::pathExistsDFS(node1, static_cast*>(nullptr)) == false); + 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*>(nullptr), static_cast*>(nullptr))); + REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(nullptr))); delete node1; delete node2; delete node3; @@ -505,7 +505,7 @@ 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 == true); +REQUIRE(status1.balanced); REQUIRE(status1.subtreeSize == 3); /* @@ -525,10 +525,41 @@ 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 == false); +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 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } From 242bf285ccd1e6ac41262e8d3b7b96bcf5c7dd98 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 23 Jan 2019 10:37:39 -0800 Subject: [PATCH 008/176] update completion in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bfb3ff1..0084f6a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `4 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `5 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `35 / 151` +Total: `36 / 151` ### Building: #### Mac: From 24b43fc3abc25f4a9d6cae92a83e753c925ccf71 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 23 Jan 2019 20:31:13 -0800 Subject: [PATCH 009/176] update completion in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bfb3ff1..0084f6a 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `4 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `5 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `35 / 151` +Total: `36 / 151` ### Building: #### Mac: From 5da0552ef47876cfa903e0d8812495c33c082ef6 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 27 Jan 2019 22:29:41 -0800 Subject: [PATCH 010/176] (1) simplify 4.6 python, (2) add more tests for 4.6 python, (3) make interface for 4.6 C++, (4) implement parent link for BinaryNode --- cpp_solutions/chapter_02_linked_lists/Node.h | 21 +++++++++----- .../chapter_04_includes.h | 1 + .../problem_04_04_checkBalanced.h | 2 ++ .../problem_04_05_validateBST.h | 1 + .../problem_04_06_successor.h | 23 +++++++++++++++ .../problem_04_06_successor.py | 25 ++++++++++++++-- tests.py | 29 ++++++++++++++++--- 7 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 89e6234..3251e5c 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -69,16 +69,14 @@ namespace chapter_02{ template class BinaryNode : public Node { private: - BinaryNode* _left; - BinaryNode* _right; + BinaryNode* _left; + BinaryNode* _right; + BinaryNode* _parent; public: - BinaryNode(T value) : Node(value){ - _left = nullptr; - _right = nullptr; - } - BinaryNode(T value, BinaryNode* left, BinaryNode* right) : Node(value){ + BinaryNode(T value, BinaryNode* left = nullptr, BinaryNode* right = nullptr, BinaryNode* parent = nullptr) : Node(value){ _left = left; _right = right; + _parent = parent; } void setLeft(BinaryNode* left) { _left = left; @@ -86,18 +84,27 @@ namespace chapter_02{ void setRight(BinaryNode* right) { _right = right; } + void setParent(BinaryNode* parent) { + _right = parent; + } BinaryNode* getLeft() const { return _left; } BinaryNode* getRight() const { return _right; } + BinaryNode* getParent() const { + return _parent; + } void removeLeft(){ _left = nullptr; } void removeRight(){ _left = nullptr; } + void removeParent(){ + _left = nullptr; + } }; // utility function that converts contents of std::vector to linked list diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index d653fc0..b2b5e4b 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -8,3 +8,4 @@ #include "problem_04_03_makeLL.h" #include "problem_04_04_checkBalanced.h" #include "problem_04_05_validateBST.h" +#include "problem_04_06_successor.h" \ No newline at end of file diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h index b9bd3c7..f710370 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h @@ -15,6 +15,8 @@ terminating condition is a node which does not have any children: in this case t Time complexity: O(N) Space complexity: O(N) */ + +#pragma once #include "../chapter_02_linked_lists/Node.h" namespace chapter_04 { diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h index fc04d38..eab841b 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h @@ -22,6 +22,7 @@ Time complexity: O(N) Space complexity: O(N) */ +#pragma once #include namespace chapter_04 { diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h new file mode 100644 index 0000000..e59fa3b --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h @@ -0,0 +1,23 @@ +/* +Chapter 04 - Problem 06 - Successor + +Problem Statement: +Write an algorithm to find the "next" node (i.e., in-order successor) of a given node in a binary search tree. +You may assume that each node has a link to its parent. + +Solution: +Based on the definition of in order traversal, the successor of a node is determined as follows: + +1. If the target node has a right child, then its successor is the leftmost member of its right subtree. +2. If the target node does not have a right child, then its successor its first ancestor to its right. +3. If nodes described in cases 1 and 2 do not exist, then the node has no successor. + +To check case 1, we check if there is a right subtree then traverse only through the left connection until we reach +the leftmost node and return it. To check case 2, we traverse from the target node up the tree only through +parent connections until we find a the first right ancestor and return it. + +Time complexity: O(N) +Space complexity: O(N) +*/ + +#pragma once diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py index c0da708..9dd70c6 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py @@ -1,3 +1,26 @@ +""" +Chapter 04 - Problem 06 - Successor + +Problem Statement: +Write an algorithm to find the "next" node (i.e., in-order successor) of a given node in a binary search tree. +You may assume that each node has a link to its parent. + +Solution: +Based on the definition of in order traversal, the successor of a node is determined as follows: + +1. If the target node has a right child, then its successor is the leftmost member of its right subtree. +2. If the target node does not have a right child, then its successor its first ancestor to its right. +3. If nodes described in cases 1 and 2 do not exist, then the node has no successor. + +To check case 1, we check if there is a right subtree then traverse only through the left connection until we reach +the leftmost node and return it. To check case 2, we traverse from the target node up the tree only through +parent connections until we find a the first right ancestor and return it. + +Time complexity: O(N) +Space complexity: O(N) +""" + + def get_leftmost(node): while node.left is not None: node = node.left @@ -7,8 +30,6 @@ def get_leftmost(node): def successor(node): if node.right is not None: return get_leftmost(node.right) - if node.parent is None: - return None while node != node.parent.left: node = node.parent if node.parent is None: diff --git a/tests.py b/tests.py index 45773ef..2c20d89 100644 --- a/tests.py +++ b/tests.py @@ -540,7 +540,6 @@ def test_problem_4_1(self): p_4_1.reset(my_graph) self.assertEqual(p_4_1.path_exists_BFS(my_graph, my_graph.get_node(1), None), False) - def test_problem_4_2(self): # test 1 my_list_1 = [8, 9, 10, 11, 12, 13, 14] @@ -615,7 +614,12 @@ def test_problem_4_5(self): node6 = tb.BinaryNode(6) node8 = tb.BinaryNode(8) node10 = tb.BinaryNode(10) - + """ + 8 + 4, 10 + 2, 6, + 1, 3, 5, + """ node8.left = node4 node8.right = node10 node4.left = node2 @@ -630,6 +634,8 @@ def test_problem_4_5(self): self.assertFalse(p_4_5.validate_BST(node8)) def test_problem_4_6(self): + # construct a binary tree + node0 = tb.BinaryNodeLP(0) node1 = tb.BinaryNodeLP(1) node2 = tb.BinaryNodeLP(2) node3 = tb.BinaryNodeLP(3) @@ -637,14 +643,25 @@ def test_problem_4_6(self): node5 = tb.BinaryNodeLP(5) node6 = tb.BinaryNodeLP(6) node8 = tb.BinaryNodeLP(8) + node9 = tb.BinaryNodeLP(9) node10 = tb.BinaryNodeLP(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.parent = node3 node1.parent = node2 node3.parent = node2 node2.parent = node4 node5.parent = node6 node6.parent = node4 node4.parent = node8 + node9.parent = node3 node10.parent = node8 node8.left = node4 @@ -654,10 +671,14 @@ def test_problem_4_6(self): node2.left = node1 node2.right = node3 node6.left = node5 + node3.left = node0 + node3.right = node9 self.assertEqual(node8, p_4_6.successor(node6)) self.assertEqual(node5, p_4_6.successor(node4)) - self.assertEqual(node3, p_4_6.successor(node2)) + self.assertEqual(node0, p_4_6.successor(node2)) + self.assertEqual(node3, p_4_6.successor(node0)) + self.assertEqual(node4, p_4_6.successor(node9)) self.assertEqual(None, p_4_6.successor(node10)) def test_problem_4_7(self): From 9a2a4efa2cc81d678a36fd4ea6f6b934a9421e0d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 27 Jan 2019 22:57:32 -0800 Subject: [PATCH 011/176] implement tests for 4.6 C++ --- .../problem_04_06_successor.h | 7 +++ tests.cpp | 50 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h index e59fa3b..8f05664 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h @@ -21,3 +21,10 @@ Space complexity: O(N) */ #pragma once +#include "../chapter_02_linked_lists/Node.h" +namespace chapter_04{ + template + chapter_02::BinaryNode* successor(chapter_02::BinaryNode* target) { + return nullptr; + } +} // namespace chapter_04 \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index 2a20859..cc18419 100644 --- a/tests.cpp +++ b/tests.cpp @@ -560,6 +560,56 @@ TEST_CASE("Chpater 04 - Problem 05 - validateBST()", "test") { 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 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } From 5b101e61614671657f9bf6308001b3682adaf20a Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 27 Jan 2019 23:56:30 -0800 Subject: [PATCH 012/176] (1) implement 4.6 C++, (2) refactor 4.6 python, (3) update completion in readme --- README.md | 4 +-- cpp_solutions/chapter_02_linked_lists/Node.h | 6 ++--- .../problem_04_06_successor.h | 22 +++++++++++++++- .../problem_04_06_successor.py | 25 ++++++++++++------- 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 0084f6a..b49f989 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `5 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `6 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `36 / 151` +Total: `37 / 151` ### Building: #### Mac: diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 3251e5c..085c928 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -85,7 +85,7 @@ namespace chapter_02{ _right = right; } void setParent(BinaryNode* parent) { - _right = parent; + _parent = parent; } BinaryNode* getLeft() const { return _left; @@ -100,10 +100,10 @@ namespace chapter_02{ _left = nullptr; } void removeRight(){ - _left = nullptr; + _right = nullptr; } void removeParent(){ - _left = nullptr; + _parent = nullptr; } }; diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h index 8f05664..e9172fb 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h @@ -23,8 +23,28 @@ Space complexity: O(N) #pragma once #include "../chapter_02_linked_lists/Node.h" namespace chapter_04{ + template + chapter_02::BinaryNode* getLeftmostDescendant(chapter_02::BinaryNode* node) { + while(node != nullptr) { + if (node->getLeft() == nullptr) { return node; } + node = node->getLeft(); + } + return node; + } + + template + chapter_02::BinaryNode* getFirstRightAncestor(chapter_02::BinaryNode* node) { + while(node != nullptr) { + if (node->getParent() == nullptr) { return nullptr;} + if (node->getParent()->getLeft() == node) { return node->getParent(); } // a right ancestor is the one whose left child is the current node + node = node->getParent(); + } + return node; + } + template chapter_02::BinaryNode* successor(chapter_02::BinaryNode* target) { - return nullptr; + chapter_02::BinaryNode* returnPointer = getLeftmostDescendant(target->getRight()); + return returnPointer != nullptr ? returnPointer : getFirstRightAncestor(target); } } // namespace chapter_04 \ No newline at end of file diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py index 9dd70c6..19b9e47 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py @@ -21,19 +21,26 @@ """ -def get_leftmost(node): - while node.left is not None: +def get_leftmost_descendant(node): + while node is not None: + if node.left is None: + return node node = node.left return node -def successor(node): - if node.right is not None: - return get_leftmost(node.right) - while node != node.parent.left: - node = node.parent +def get_first_right_ancestor(node): + while node is not None: if node.parent is None: return None - if node.parent.left == node: + if node.parent.left == node: # a right ancestor is the one whose left child is the current node return node.parent - return node.parent + node = node.parent + return node + + +def successor(node): + return_node = get_leftmost_descendant(node.right) + if return_node is None: + return get_first_right_ancestor(node) + return return_node From cc59f07edbc4e06f8d2da0a7369bfb5d22a32615 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 28 Jan 2019 17:04:27 -0800 Subject: [PATCH 013/176] implement general graph node that maintains linked list of connected children --- cpp_solutions/chapter_02_linked_lists/Node.h | 51 ++++++++++++++++--- .../problem_04_01_pathExists.h | 6 +-- .../problem_04_01_path_exists.py | 18 +++---- tests.cpp | 34 ++++++------- 4 files changed, 74 insertions(+), 35 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 085c928..f05cced 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -35,19 +35,58 @@ namespace chapter_02{ void setNext(SinglyLinkedNode* next) {_next = next;} }; // class SinglyLinkedNode - // specialized node for 4-connected graphs + // general graph node. supports infinite number of children by maintaining pointer to head of linked list of child pointers template - class GraphNode : public Node{ + class GraphNode : public Node { private: - GraphNode* _children[4]; + SinglyLinkedNode*>* _head; + SinglyLinkedNode*>* _tail; public: GraphNode(T value) : Node(value) { + _head = nullptr; + } + void push(GraphNode* node) { + if (_head == nullptr) { + _head = new SinglyLinkedNode*>(node); + _tail = _head; + } else { + _tail->setNext(new SinglyLinkedNode*>(node)); + _tail = _tail->getNext(); + } + } + GraphNode* pop() { + if (_head == nullptr) { + return nullptr; + } + GraphNode* tempGN = _head->getValue(); + if (_tail == _head) { + delete _head; + delete _tail; + _head = nullptr; + _tail = nullptr; + return tempGN; + } else { + SinglyLinkedNode*>* tempHead = _head; + _head = _head->getNext(); + delete tempHead; + } + return tempGN; + } + }; + + // specialized node for 4-connected graphs; a specific child node can be retrieved in constant time + template + class TetraGraphNode : public Node{ + private: + TetraGraphNode* _children[4]; + public: + TetraGraphNode(T value) : Node(value) { _children[0] = nullptr; _children[1] = nullptr; _children[2] = nullptr; _children[3] = nullptr; } - void addChild(GraphNode* child, int index) { + void addChild(TetraGraphNode* child, int index) { if (index > 3 || index < 0) return; _children[index] = child; } @@ -56,14 +95,14 @@ namespace chapter_02{ delete _children[index]; _children[index] = nullptr; } - void getChildren(std::vector& children) const { + void getChildren(std::vector& children) const { for (int i = 0; i < 4; i++){ if (_children[i] != nullptr){ children.push_back(_children[i]); } } } - }; // class GraphNode + }; // class TetraGraphNode // specialized node for binary trees template diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_01_pathExists.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_01_pathExists.h index 4cb5866..a181384 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_01_pathExists.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_01_pathExists.h @@ -19,13 +19,13 @@ Space complexity: O(N) namespace chapter_04{ template - bool pathExistsDFS(const chapter_02::GraphNode* start, const chapter_02::GraphNode* end){ + bool pathExistsDFS(const chapter_02::TetraGraphNode* start, const chapter_02::TetraGraphNode* end){ if (start == nullptr || end == nullptr) return false; if (start == end) return true; - std::vector*> nextChildren; + std::vector*> nextChildren; start->getChildren(nextChildren); bool returnValue = false; - for (chapter_02::GraphNode* child : nextChildren){ + for (chapter_02::TetraGraphNode* child : nextChildren){ returnValue = returnValue || pathExistsDFS(child, end); } return returnValue; diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_01_path_exists.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_01_path_exists.py index b05c051..fa4173a 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_01_path_exists.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_01_path_exists.py @@ -15,7 +15,7 @@ """ -class GraphNode: +class TetraGraphNode: def __init__(self, value, frontier=False, explored=False): self.value = value self.frontier = frontier @@ -46,14 +46,14 @@ def reset(graph): 7 -> 8 """ graph.nodes_list = [] - n1 = GraphNode(1, False, False) - n2 = GraphNode(2, False, False) - n3 = GraphNode(3, False, False) - n4 = GraphNode(4, False, False) - n5 = GraphNode(5, False, False) - n6 = GraphNode(6, False, False) - n7 = GraphNode(7, False, False) - n8 = GraphNode(8, False, False) + n1 = TetraGraphNode(1, False, False) + n2 = TetraGraphNode(2, False, False) + n3 = TetraGraphNode(3, False, False) + n4 = TetraGraphNode(4, False, False) + n5 = TetraGraphNode(5, False, False) + n6 = TetraGraphNode(6, False, False) + n7 = TetraGraphNode(7, False, False) + n8 = TetraGraphNode(8, False, False) graph.nodes_list += [[n1, n2]] # adj to n1 graph.nodes_list += [[n2, n3, n4]] # adj to n2 graph.nodes_list += [[n3]] # adj to n3 diff --git a/tests.cpp b/tests.cpp index cc18419..16554bc 100644 --- a/tests.cpp +++ b/tests.cpp @@ -365,16 +365,16 @@ TEST_CASE("Chapter 03 - Problem 04 - QueueViStacks()", "test"){ } TEST_CASE("Chapter 04 - Basic Graph Functionality", "test"){ - chapter_02::GraphNode node(1); - chapter_02::GraphNode* child0 = new chapter_02::GraphNode(0); - chapter_02::GraphNode* child1 = new chapter_02::GraphNode(1); - chapter_02::GraphNode* child2 = new chapter_02::GraphNode(2); - chapter_02::GraphNode* child3 = new chapter_02::GraphNode(3); + 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*> children; + std::vector*> children; node.getChildren(children); REQUIRE(children[0] == child0); REQUIRE(children[1] == child1); @@ -384,7 +384,7 @@ TEST_CASE("Chapter 04 - Basic Graph Functionality", "test"){ node.removeChild(1); node.removeChild(2); node.removeChild(3); - std::vector*> deletedChildren; + std::vector*> deletedChildren; node.getChildren(deletedChildren); REQUIRE(deletedChildren.size() == 0); // no need to delete children, because removeChildren does that for us. @@ -401,14 +401,14 @@ TEST_CASE("Chapter 04 - Problem 01 - Route Between Nodes", "test"){ v | 7 -> 8 */ - chapter_02::GraphNode* node1 = new chapter_02::GraphNode(1); - chapter_02::GraphNode* node2 = new chapter_02::GraphNode(2); - chapter_02::GraphNode* node3 = new chapter_02::GraphNode(3); - chapter_02::GraphNode* node4 = new chapter_02::GraphNode(4); - chapter_02::GraphNode* node5 = new chapter_02::GraphNode(5); - chapter_02::GraphNode* node6 = new chapter_02::GraphNode(6); - chapter_02::GraphNode* node7 = new chapter_02::GraphNode(7); - chapter_02::GraphNode* node8 = new chapter_02::GraphNode(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); @@ -421,8 +421,8 @@ TEST_CASE("Chapter 04 - Problem 01 - Route Between Nodes", "test"){ REQUIRE(chapter_04::pathExistsDFS(node7, node5)); REQUIRE(!chapter_04::pathExistsDFS(node3, node8)); REQUIRE(chapter_04::pathExistsDFS(node1, node8)); - REQUIRE(!chapter_04::pathExistsDFS(static_cast*>(nullptr), static_cast*>(nullptr))); - REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(nullptr))); + REQUIRE(!chapter_04::pathExistsDFS(static_cast*>(nullptr), static_cast*>(nullptr))); + REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(nullptr))); delete node1; delete node2; delete node3; From ab8b6037dee9d4dc44bde44328de28af03ef7015 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 29 Jan 2019 09:05:35 -0800 Subject: [PATCH 014/176] WIP implementing 4.7 C++ --- CMakeLists.txt | 3 +- README.md | 4 +- cpp_solutions/chapter_02_linked_lists/Node.h | 12 +++- .../chapter_04_includes.h | 3 +- .../problem_04_07_buildOrder.cpp | 61 +++++++++++++++++++ .../problem_04_07_buildOrder.h | 11 ++++ .../problem_04_07_build_order.py | 18 ++++++ tests.cpp | 33 ++++++++++ 8 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h diff --git a/CMakeLists.txt b/CMakeLists.txt index be4f23e..ce5e737 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCE_FILES # chapter 2 .cpp files not included because they are template functions implemented in .h files # chapter 3 .cpp files not included because they are template functions implemented in .h files # chapter 4 .cpp files not included because they are template functions implemented in .h files + cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp @@ -34,6 +35,6 @@ set(SOURCE_FILES # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file - cpp_solutions/misc_exercises/integralImage.cpp) + cpp_solutions/misc_exercises/integralImage.cpp cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/README.md b/README.md index b49f989..ea44111 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `6 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `7 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `37 / 151` +Total: `38 / 151` ### Building: #### Mac: diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index f05cced..00dc3a7 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -41,9 +41,11 @@ namespace chapter_02{ private: SinglyLinkedNode*>* _head; SinglyLinkedNode*>* _tail; + int _numAncestors; public: GraphNode(T value) : Node(value) { _head = nullptr; + _tail = nullptr; } void push(GraphNode* node) { if (_head == nullptr) { @@ -64,7 +66,6 @@ namespace chapter_02{ delete _tail; _head = nullptr; _tail = nullptr; - return tempGN; } else { SinglyLinkedNode*>* tempHead = _head; _head = _head->getNext(); @@ -72,6 +73,15 @@ namespace chapter_02{ } return tempGN; } + void incAncestors() { + _numAncestors ++; + } + void decAncestors() { + _numAncestors --; + } + int getNumAncestors() { + return _numAncestors; + } }; // specialized node for 4-connected graphs; a specific child node can be retrieved in constant time diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index b2b5e4b..91ec8cd 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -8,4 +8,5 @@ #include "problem_04_03_makeLL.h" #include "problem_04_04_checkBalanced.h" #include "problem_04_05_validateBST.h" -#include "problem_04_06_successor.h" \ No newline at end of file +#include "problem_04_06_successor.h" +#include "problem_04_07_buildOrder.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp new file mode 100644 index 0000000..a7ddc41 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp @@ -0,0 +1,61 @@ +/* +Chapter 04 - Problem 07 - Build Order + +Problem Statement: +You are given a list of projects and a list of dependencies (which is a list of pairs of projects, +where the second project is dependent on the first project). All of a project's dependencies must +be built before the project is. Find a build order that will allow the projects to be built. +If there is no valid build order, return an error. + +Solution: +We first represent the projects and build dependencies as vertices and edges in a directed acyclic graph. +We then implement a depth first search based algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms + +L ← Empty list that will contain the sorted nodes +while there are unmarked nodes do: + select an unmarked node n + visit(n) + +function visit(node n) + if n has a permanent mark: // n has already been visited + return + if n has a temporary mark: // (not a DAG) + stop + mark n temporarily + for each node m with an edge from n to m: + visit(m) + mark n permanently + add n to head of L + +Time complexity: O(V + E) where V is the number of vertices in the graph and E is the number of edges. +V can be interpreted as the number of projects and E can be interpreted as the number of dependencies. +Space complexity: O(V) +*/ + +#include "problem_04_07_buildOrder.h" +#include + +namespace chapter_04 { + void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder) { + // convert list of project identifiers to graph nodes + std::vector*> projectsGN = {}; // store pointers to GraphNodes used in topological sort + std::unordered_map charToIndexMap; // map project identifier char to index for fast lookup based on project identifier + for (int i = 0; i < projects.size(); i++) { + auto iterator = charToIndexMap.find(projects[i]); // check for project uniqueness + if (iterator != charToIndexMap.end()) return; // the same project exists twice in the project manifest + projectsGN.push_back(new chapter_02::GraphNode(projects[i])); + charToIndexMap[projects[i]] = i; + } + // convert list of project dependencies to graph edges + for (int i = 0; i < dependencies.size(); i++) { + // the first node in a pair must be build before the second. + chapter_02::GraphNode* first = projectsGN[charToIndexMap[dependencies[i].first]]; + chapter_02::GraphNode* second = projectsGN[charToIndexMap[dependencies[i].second]]; + // add edge from the first node to the second node + first->push(second); + second->incAncestors(); + } + + + } +} // namespace chapter_04 \ No newline at end of file diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h new file mode 100644 index 0000000..b06c0f3 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h @@ -0,0 +1,11 @@ +/* +Chapter 04 - Problem 07 - Build Order + +See problem_04_07_buildOrder.cpp for problem description. +*/ +#include +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder); +} // namespace chapter_04 diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py index a33dbdd..60aade0 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py @@ -1,3 +1,21 @@ +""" +Chapter 04 - Problem 07 - Build Order + +Problem Statement: +You are given a list of projects and a list of dependencies (which is a list of pairs of projects, +where the second project is dependent on the first project). All of a project's dependencies must +be built before the project is. Find a build order that will allow the projects to be built. +If there is no valid build order, return an error. + +Solution: +We first represent the projects and build dependencies as vertices and edges in a directed acyclic graph. +We then implement Kahn's algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms + +Time complexity: O(V + E) where V is the number of vertices in the graph and E is the number of edges. +V can be interpreted as the number of projects and E can be interpreted as the number of dependencies. +Space complexity: O(V) +""" + from queue import Queue diff --git a/tests.cpp b/tests.cpp index 16554bc..67011b7 100644 --- a/tests.cpp +++ b/tests.cpp @@ -610,6 +610,39 @@ TEST_CASE("Chapter 04 - Problem 06 - successor()", "test"){ REQUIRE(nullptr == chapter_04::successor(node10)); } +TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { + std::vector project1 = {'a', 'b', 'c', 'd', 'e', 'f'}; + std::vector> dependencies1 = { + std::pair('a', 'd'), + std::pair('f', 'b'), + std::pair('b', 'd'), + std::pair('f', 'a'), + std::pair('d', 'c')}; + std::vector project2 = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; + std::vector> 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')}; + std::vector actualBuildOrder1 = {}; + std::vector actualBuildOrder2 = {}; + std::vector expectedBuildOrder1 = {'e', 'f', 'b', 'a', 'd', 'c'}; + std::vector expectedBuildOrder2 = {'d', 'f', 'g', 'c', 'b', 'a', 'e'}; + chapter_04::buildOrder(project1, dependencies1, actualBuildOrder1); + chapter_04::buildOrder(project2, dependencies2, actualBuildOrder2); + + 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]); + } +} + TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } From eb2743e1709c90d4c6239eac9352f1d32824c9a4 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 29 Jan 2019 12:57:48 -0800 Subject: [PATCH 015/176] WIP 4.7 implemented, but needs test of circular dependency case --- cpp_solutions/chapter_02_linked_lists/Node.h | 3 + .../problem_04_07_buildOrder.cpp | 62 +++++++++++++------ .../problem_04_07_build_order.py | 6 +- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 00dc3a7..30eb8fe 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -82,6 +82,9 @@ namespace chapter_02{ int getNumAncestors() { return _numAncestors; } + SinglyLinkedNode*>* getHeadOfDescendants() { + return _head; + } }; // specialized node for 4-connected graphs; a specific child node can be retrieved in constant time diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp index a7ddc41..150f3b7 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp @@ -9,23 +9,21 @@ If there is no valid build order, return an error. Solution: We first represent the projects and build dependencies as vertices and edges in a directed acyclic graph. -We then implement a depth first search based algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms +We then implement Kahn's algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms -L ← Empty list that will contain the sorted nodes -while there are unmarked nodes do: - select an unmarked node n - visit(n) - -function visit(node n) - if n has a permanent mark: // n has already been visited - return - if n has a temporary mark: // (not a DAG) - stop - mark n temporarily - for each node m with an edge from n to m: - visit(m) - mark n permanently - add n to head of L +L ← Empty list that will contain the sorted elements +S ← Set of all nodes with no incoming edge +while S is non-empty do + remove a node n from S + add n to tail of L + for each node m with an edge e from n to m do + remove edge e from the graph + if m has no other incoming edges then + insert m into S +if graph has edges then + return error (graph has at least one cycle) +else + return L (a topologically sorted order) Time complexity: O(V + E) where V is the number of vertices in the graph and E is the number of edges. V can be interpreted as the number of projects and E can be interpreted as the number of dependencies. @@ -34,6 +32,7 @@ Space complexity: O(V) #include "problem_04_07_buildOrder.h" #include +#include namespace chapter_04 { void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder) { @@ -47,15 +46,38 @@ namespace chapter_04 { charToIndexMap[projects[i]] = i; } // convert list of project dependencies to graph edges - for (int i = 0; i < dependencies.size(); i++) { + for (auto dependency : dependencies) { // the first node in a pair must be build before the second. - chapter_02::GraphNode* first = projectsGN[charToIndexMap[dependencies[i].first]]; - chapter_02::GraphNode* second = projectsGN[charToIndexMap[dependencies[i].second]]; + chapter_02::GraphNode* first = projectsGN[charToIndexMap[dependency.first]]; + chapter_02::GraphNode* second = projectsGN[charToIndexMap[dependency.second]]; // add edge from the first node to the second node first->push(second); second->incAncestors(); } - + // create queue containing all nodes with no dependencies + std::queue*> Q; + for (auto node : projectsGN) { + if (node->getNumAncestors() == 0) Q.push(node); + } + // traverse graph in depth first order starting from nodes without dependencies + while (!Q.empty()) { + chapter_02::GraphNode* node = Q.front(); + Q.pop(); + buildOrder.push_back(node->getValue()); + chapter_02::SinglyLinkedNode*>* child = node->getHeadOfDescendants(); + while (child != nullptr) { + child->getValue()->decAncestors(); + if (child->getValue()->getNumAncestors() == 0) { + Q.push(child->getValue()); + } else if (child->getValue()->getNumAncestors() < 0) { // circular dependency detected + buildOrder.clear(); + return; + } + child = child->getNext(); + } + } + // check for circular dependencies - they manifest as a build list with length different than project list + // free memory consumed by graph nodes } } // namespace chapter_04 \ No newline at end of file diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py index 60aade0..fb0c491 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py @@ -52,8 +52,10 @@ def build_order(project_list, deps_list): if child_node.in_degree == 0: # check if in_degree is 0 build_list.append(child_node.name) q.put(child_node) + if child_node.in_degree < 0: + return None - if len(build_list) != len(project_list): - return None + #if len(build_list) != len(project_list): # result of circular dependencies + # return None return build_list From b248bdb37be050fe15ed0ad35a1339b2454292ff Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 29 Jan 2019 13:43:25 -0800 Subject: [PATCH 016/176] complete implementation and testing of 4.7 python and C++. add testing for circular dependencies. --- .../problem_04_07_buildOrder.cpp | 20 +++++++++------- .../problem_04_07_build_order.py | 24 +++++++++++++++---- tests.cpp | 22 +++++++++++++---- tests.py | 12 ++++++---- 4 files changed, 56 insertions(+), 22 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp index 150f3b7..9d7915b 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp @@ -46,6 +46,7 @@ namespace chapter_04 { charToIndexMap[projects[i]] = i; } // convert list of project dependencies to graph edges + int totalEdges = 0; for (auto dependency : dependencies) { // the first node in a pair must be build before the second. chapter_02::GraphNode* first = projectsGN[charToIndexMap[dependency.first]]; @@ -53,6 +54,7 @@ namespace chapter_04 { // add edge from the first node to the second node first->push(second); second->incAncestors(); + totalEdges ++; } // create queue containing all nodes with no dependencies std::queue*> Q; @@ -67,17 +69,19 @@ namespace chapter_04 { chapter_02::SinglyLinkedNode*>* child = node->getHeadOfDescendants(); while (child != nullptr) { child->getValue()->decAncestors(); - if (child->getValue()->getNumAncestors() == 0) { - Q.push(child->getValue()); - } else if (child->getValue()->getNumAncestors() < 0) { // circular dependency detected - buildOrder.clear(); - return; - } + totalEdges --; // keep track of total edges in graph as we remove them + if (child->getValue()->getNumAncestors() == 0) Q.push(child->getValue()); child = child->getNext(); + node->pop(); } } - // check for circular dependencies - they manifest as a build list with length different than project list + // if edges remain in the graph, at least one circular dependency exists + if (totalEdges != 0) { + buildOrder.clear(); + } // free memory consumed by graph nodes - + for (auto node : projectsGN) { + delete node; + } } } // namespace chapter_04 \ No newline at end of file diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py index fb0c491..6603187 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_07_build_order.py @@ -11,6 +11,20 @@ We first represent the projects and build dependencies as vertices and edges in a directed acyclic graph. We then implement Kahn's algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms +L ← Empty list that will contain the sorted elements +S ← Set of all nodes with no incoming edge +while S is non-empty do + remove a node n from S + add n to tail of L + for each node m with an edge e from n to m do + remove edge e from the graph + if m has no other incoming edges then + insert m into S +if graph has edges then + return error (graph has at least one cycle) +else + return L (a topologically sorted order) + Time complexity: O(V + E) where V is the number of vertices in the graph and E is the number of edges. V can be interpreted as the number of projects and E can be interpreted as the number of dependencies. Space complexity: O(V) @@ -34,10 +48,12 @@ def build_order(project_list, deps_list): for project_name in project_list: nodes_dict[project_name] = Node(project_name) # convert string representation of dependencies to edges between nodes + total_edges = 0 for dep in deps_list: nodes_dict[dep[0]].children.append(nodes_dict[dep[1]]) # parent -> child nodes_dict[dep[1]].parents.append(nodes_dict[dep[0]]) # child <- parent nodes_dict[dep[1]].in_degree += 1 + total_edges += 1 # Kahn's algorithm for topological sorting q = Queue() for name in project_list: # place every node with 0 in_degree in queue @@ -49,13 +65,11 @@ def build_order(project_list, deps_list): current = q.get() for child_node in current.children: child_node.in_degree -= 1 # reduce in degree once parent is removed from queue + total_edges -= 1 if child_node.in_degree == 0: # check if in_degree is 0 build_list.append(child_node.name) q.put(child_node) - if child_node.in_degree < 0: - return None - #if len(build_list) != len(project_list): # result of circular dependencies - # return None + if total_edges != 0: # result of circular dependencies - edges remain in graph after algorithm executes + return None return build_list - diff --git a/tests.cpp b/tests.cpp index 67011b7..37bf1a1 100644 --- a/tests.cpp +++ b/tests.cpp @@ -611,14 +611,15 @@ TEST_CASE("Chapter 04 - Problem 06 - successor()", "test"){ } TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { - std::vector project1 = {'a', 'b', 'c', 'd', 'e', 'f'}; + // no circular dependencies + std::vector projects1 = {'a', 'b', 'c', 'd', 'e', 'f'}; std::vector> dependencies1 = { std::pair('a', 'd'), std::pair('f', 'b'), std::pair('b', 'd'), std::pair('f', 'a'), std::pair('d', 'c')}; - std::vector project2 = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; + std::vector projects2 = {'a', 'b', 'c', 'd', 'e', 'f', 'g'}; std::vector> dependencies2 = { std::pair('f', 'c'), std::pair('f', 'b'), @@ -628,19 +629,30 @@ TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { std::pair('a', 'e'), std::pair('b', 'e'), std::pair('d', 'g')}; + // add circular dependency + std::vector> 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(project1, dependencies1, actualBuildOrder1); - chapter_04::buildOrder(project2, dependencies2, actualBuildOrder2); - + 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 05 - Problem 01 - insertion()", "test"){ diff --git a/tests.py b/tests.py index 2c20d89..2dbe73a 100644 --- a/tests.py +++ b/tests.py @@ -682,12 +682,16 @@ def test_problem_4_6(self): self.assertEqual(None, p_4_6.successor(node10)) def test_problem_4_7(self): - project1 = ['a', 'b', 'c', 'd', 'e', 'f'] + # no circular dependencies + projects1 = ['a', 'b', 'c', 'd', 'e', 'f'] dependencies1 = [('a', 'd'), ('f', 'b'), ('b', 'd'), ('f', 'a'), ('d', 'c')] - project2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] + projects2 = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] dependencies2 = [('f', 'c'), ('f', 'b'), ('f', 'a'), ('c', 'a'), ('b', 'a'), ('a', 'e'), ('b', 'e'), ('d', 'g')] - self.assertEqual(['e', 'f', 'b', 'a', 'd', 'c'], p_4_7.build_order(project1, dependencies1)) - self.assertEqual(['d', 'f', 'g', 'c', 'b', 'a', 'e'], p_4_7.build_order(project2, dependencies2)) + # add circular dependency + dependencies3 = [('a', 'd'), ('f', 'b'), ('b', 'd'), ('f', 'a'), ('d', 'c'), ('c', 'a')] + self.assertEqual(['e', 'f', 'b', 'a', 'd', 'c'], p_4_7.build_order(projects1, dependencies1)) + self.assertEqual(['d', 'f', 'g', 'c', 'b', 'a', 'e'], p_4_7.build_order(projects2, dependencies2)) + self.assertEqual(None, p_4_7.build_order(projects1, dependencies3)) def test_problem_4_8(self): n7 = tb.BinaryNodeLP(7) From 980aec882253641bba1babdf830072811356ee63 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 2 Feb 2019 13:18:04 -0800 Subject: [PATCH 017/176] refactor 4.8 python according to stricter problem statement. reduce length of solution. --- .../problem_04_08_first_common_ancestor.py | 73 +++++++++++-------- tests.cpp | 5 ++ tests.py | 46 ++++++------ 3 files changed, 70 insertions(+), 54 deletions(-) diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py index 3aa4bf0..76752ee 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py @@ -1,31 +1,42 @@ -def fca(node1, node2): - count1 = 0 - count2 = 0 - runner1 = node1 - runner2 = node2 - # compute distance from the top for each node - while runner1 is not None: - runner1 = runner1.parent - count1 += 1 - while runner2 is not None: - runner2 = runner2.parent - count2 += 1 - # determine which node is deeper based on difference in distances from top - if count1 > count2: - deep_node = node1 - shallow_node = node2 - else: - deep_node = node2 - shallow_node = node1 - difference = abs(count1 - count2) - # advance deeper node pointer upward by the number of levels eq to the distance - while difference != 0: - deep_node = deep_node.parent - difference -= 1 - # advance both pointers (now at equal depths) upward simultaneously until they point to the same node - while deep_node is not None and shallow_node is not None: - if deep_node is shallow_node: - return deep_node # if both pointers point to same node, return it - deep_node = deep_node.parent - shallow_node = shallow_node.parent - return None # if we advance both pointers to the top and they are never equal, the nodes aren't in the same tree +""" +Chapter 04 - Problem 08 - First Common Ancestor + +Problem Statement: +Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. +Avoid storing additional nodes in a data structure. Assume that this tree is not necessarily a binary search tree. +Assume that nodes in the tree do not have links to their parents. + +Solution: +Traverse the tree recursively using a function whose return value indicates the presence of nodes 1 and 2 +in the current node's left or right subtrees. The function also passes a reference to a Null node that is changed +to the identity of the first common ancestor if such a node exists. At each recursive call, the function returns one of +the following: "1" if the current node is an ancestor of node1, "2" if the current node is an ancestor of node2, +"3" if the current node is an ancestor of both nodes 1 and 2 or "0" in case the current node is an ancestor +of neither nodes 1 or 2. The function recurses until nodes1 and 2 are found and their presence is "bubbled" +up the tree in the form of the return values. If case "3" is encountered and the reference is still Null, the reference is assigned the first +common ancestor. The terminating condition of the function is (a) finding node1, node2, or Null. + +Time complexity: O(N) +Space complexity: O(N) +""" + + +def first_common_ancestor_helper(currentNode, node1, node2, fca_reference): + if currentNode is None: + return 0 + elif currentNode is node1: + return 1 + elif currentNode is node2: + return 2 + return_left = first_common_ancestor_helper(currentNode.left, node1, node2, fca_reference) + return_light = first_common_ancestor_helper(currentNode.right, node1, node2, fca_reference) + sum = return_left + return_light + if sum == 3 and fca_reference[0] is None: + fca_reference[0] = currentNode + return sum + + +def first_common_ancestor(head, node1, node2): + fca_reference = [None] # rely on mutable list to pass a reference + first_common_ancestor_helper(head, node1, node2, fca_reference) + return fca_reference[0] diff --git a/tests.cpp b/tests.cpp index 37bf1a1..5094dd9 100644 --- a/tests.cpp +++ b/tests.cpp @@ -655,6 +655,11 @@ TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { REQUIRE(actualBuildOrder3.empty()); } +/* +TEST_CASE("Chapter 04 - Problem 08 - firstCommonAncestor()", "test") { + // +} +*/ TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } diff --git a/tests.py b/tests.py index 2dbe73a..f6be4e4 100644 --- a/tests.py +++ b/tests.py @@ -694,29 +694,29 @@ def test_problem_4_7(self): self.assertEqual(None, p_4_7.build_order(projects1, dependencies3)) def test_problem_4_8(self): - n7 = tb.BinaryNodeLP(7) - n4 = tb.BinaryNodeLP(4, parent=n7) - n3 = tb.BinaryNodeLP(3, parent=n7) - n7.left = n4 - n7.right = n3 - n10 = tb.BinaryNodeLP(10, parent=n4) - n5 = tb.BinaryNodeLP(5, parent=n4) - n4.left = n10 - n4.right = n5 - n6 = tb.BinaryNodeLP(6, parent=n3) - n15 = tb.BinaryNodeLP(15, parent=n3) - n3.left = n6 - n3.right = n15 - n21 = tb.BinaryNodeLP(21, parent=n15) - n17 = tb.BinaryNodeLP(17, parent=n15) - n15.left = n21 - n15.right = n17 - n25 = tb.BinaryNodeLP(25) - self.assertEqual(n3, p_4_8.fca(n6, n21)) - self.assertEqual(n7, p_4_8.fca(n10, n21)) - self.assertEqual(None, p_4_8.fca(n15, n25)) - self.assertEqual(n7, p_4_8.fca(n7, n7)) - self.assertEqual(n7, p_4_8.fca(n3, n4)) + """ + construct binary tree + 7 + 4 3 + 10 5 6 15 + 21 17 + """ + n21 = tb.BinaryNode(21) + n17 = tb.BinaryNode(17) + n15 = tb.BinaryNode(15, n21, n17) + n6 = tb.BinaryNode(6) + n3 = tb.BinaryNode(3, n6, n15) + n10 = tb.BinaryNode(10) + n5 = tb.BinaryNode(5) + n4 = tb.BinaryNode(4, n10, n5) + n7 = tb.BinaryNode(7, n4, n3) + n25 = tb.BinaryNode(25) # unconnected node + + self.assertEqual(n3, p_4_8.first_common_ancestor(n7, n6, n21)) + self.assertEqual(n7, p_4_8.first_common_ancestor(n7, n10, n21)) + self.assertEqual(None, p_4_8.first_common_ancestor(n7, n15, n25)) + self.assertEqual(None, p_4_8.first_common_ancestor(n7, n7, n7)) # a node is not its own ancestor + self.assertEqual(n7, p_4_8.first_common_ancestor(n7, n3, n4)) def test_problem_4_9(self): n25 = tb.BinaryNode(25) From 6185f9138a5b516fe95dea8a54ea648020045656 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 15:15:26 -0500 Subject: [PATCH 018/176] implement 4.8 C++. fix memory deallocation bug in Node.h --- CMakeLists.txt | 2 +- cpp_solutions/chapter_02_linked_lists/Node.h | 6 +--- .../problem_02_03_deleteMiddleNode.h | 2 +- .../chapter_04_includes.h | 1 + .../problem_04_08_firstCommonAncestor.h | 32 +++++++++++++++++++ tests.cpp | 28 ++++++++++++++-- 6 files changed, 61 insertions(+), 10 deletions(-) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ce5e737..2e2ab0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,6 @@ set(SOURCE_FILES # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file - cpp_solutions/misc_exercises/integralImage.cpp cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h) + cpp_solutions/misc_exercises/integralImage.cpp) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 30eb8fe..f483cc2 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -28,9 +28,7 @@ namespace chapter_02{ public: SinglyLinkedNode(T value, SinglyLinkedNode* next = nullptr) : Node(value), _next(next) {} // constructor SinglyLinkedNode(const SinglyLinkedNode& other) : Node::_value(other.getValue()), _next(other.getNext()){} // copy constructor - ~SinglyLinkedNode(){ // destructor - _next = nullptr; - } + ~SinglyLinkedNode(){} SinglyLinkedNode* getNext() const {return _next;} void setNext(SinglyLinkedNode* next) {_next = next;} }; // class SinglyLinkedNode @@ -62,8 +60,6 @@ namespace chapter_02{ } GraphNode* tempGN = _head->getValue(); if (_tail == _head) { - delete _head; - delete _tail; _head = nullptr; _tail = nullptr; } else { diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h b/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h index 8c3135e..4d548f1 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h @@ -31,7 +31,7 @@ namespace chapter_02{ if (middle == nullptr || middle->getNext() == nullptr){ return; // given node is not in the middle. do nothing. } - SinglyLinkedNode* next = middle -> getNext(); + SinglyLinkedNode* next = middle->getNext(); middle->setValue(next->getValue()); middle->setNext(next->getNext()); delete next; diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index 91ec8cd..782516b 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -10,3 +10,4 @@ #include "problem_04_05_validateBST.h" #include "problem_04_06_successor.h" #include "problem_04_07_buildOrder.h" +#include "problem_04_08_firstCommonAncestor.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h new file mode 100644 index 0000000..a558163 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h @@ -0,0 +1,32 @@ +// +// Created by Alex Hagiopol on 2019-02-02. +// + +#pragma once +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + template + int firstCommonAncestorHelper(chapter_02::BinaryNode* currentNode, + chapter_02::BinaryNode* node1, + chapter_02::BinaryNode* node2, + chapter_02::BinaryNode*& fca) { + if (currentNode == nullptr) return 0; + if (currentNode == node1) return 1; + if (currentNode == node2) return 2; + int returnLeft = firstCommonAncestorHelper(currentNode->getLeft(), node1, node2, fca); + int returnRight = firstCommonAncestorHelper(currentNode->getRight(), node1, node2, fca); + int sum = returnLeft + returnRight; + if (sum == 3 && fca == nullptr) fca = currentNode; + return sum; + } + + template + chapter_02::BinaryNode* firstCommonAncestor(chapter_02::BinaryNode* head, + chapter_02::BinaryNode* node1, + chapter_02::BinaryNode* node2) { + chapter_02::BinaryNode* fca = nullptr; + firstCommonAncestorHelper(head, node1, node2, fca); + return fca; + } +} // chapter_04 \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index 5094dd9..6fda8d4 100644 --- a/tests.cpp +++ b/tests.cpp @@ -655,11 +655,33 @@ TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { REQUIRE(actualBuildOrder3.empty()); } -/* TEST_CASE("Chapter 04 - Problem 08 - firstCommonAncestor()", "test") { - // -} +/* +construct binary tree + 7 + 4 3 + 10 5 6 15 + 21 17 */ + + 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 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } From fd7b128052941c299a43bcc37f71cc4c546f71f2 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 15:22:56 -0500 Subject: [PATCH 019/176] write essay for 4.8 C++. fix essay for 4.8 python. update completion in readme --- README.md | 4 +-- .../problem_04_08_firstCommonAncestor.h | 25 ++++++++++++++++--- .../problem_04_08_first_common_ancestor.py | 7 +++--- .../problem_04_10_check_subtree.py | 2 +- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ea44111..ba40755 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `7 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `8 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `38 / 151` +Total: `39 / 151` ### Building: #### Mac: diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h index a558163..f153e7d 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h @@ -1,6 +1,25 @@ -// -// Created by Alex Hagiopol on 2019-02-02. -// +/* +Chapter 04 - Problem 08 - First Common Ancestor + +Problem Statement: +Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. +Avoid storing additional nodes in a data structure. Assume that this tree is not necessarily a binary search tree. +Assume that nodes in the tree do not have links to their parents. + +Solution: +Traverse the tree recursively using a function whose return value indicates the presence of nodes 1 and 2 +in the current node's left or right subtrees. The function also passes a reference to a Null node that is changed +to the identity of the first common ancestor if such a node exists. At each recursive call, the function returns one of +the following: "1" if the current node is an ancestor of node1, "2" if the current node is an ancestor of node2, +"3" if the current node is an ancestor of both nodes 1 and 2 or "0" in case the current node is an ancestor +of neither nodes 1 or 2. The function recurses until nodes1 and 2 are found and their presence is "bubbled up" +the tree in the form of the return values. If case "3" is encountered and the reference is still Null, the +reference is assigned the current node which by definition is the first common ancestor. +The terminating condition of the function is finding node1, node2, or Null. + +Time complexity: O(N) +Space complexity: O(N) +*/ #pragma once #include "../chapter_02_linked_lists/Node.h" diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py index 76752ee..0a436e8 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py @@ -12,9 +12,10 @@ to the identity of the first common ancestor if such a node exists. At each recursive call, the function returns one of the following: "1" if the current node is an ancestor of node1, "2" if the current node is an ancestor of node2, "3" if the current node is an ancestor of both nodes 1 and 2 or "0" in case the current node is an ancestor -of neither nodes 1 or 2. The function recurses until nodes1 and 2 are found and their presence is "bubbled" -up the tree in the form of the return values. If case "3" is encountered and the reference is still Null, the reference is assigned the first -common ancestor. The terminating condition of the function is (a) finding node1, node2, or Null. +of neither nodes 1 or 2. The function recurses until nodes1 and 2 are found and their presence is "bubbled up" +the tree in the form of the return values. If case "3" is encountered and the reference is still Null, the reference +is assigned the current node which by definition is the first common ancestor. +The terminating condition of the function is finding node1, node2, or Null. Time complexity: O(N) Space complexity: O(N) diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py index 7208d08..9d029e9 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py @@ -14,4 +14,4 @@ def subtree_equality(t2, t1): return False if t2.val == t1.val: return subtree_equality(t2.left, t1.left) and subtree_equality(t2.right, t1.right) - return False \ No newline at end of file + return False From 746b3103186e1004595361d1d5be0bc47e69607f Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 17:17:06 -0500 Subject: [PATCH 020/176] fix essays with incorrect memory bounds --- .../chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h | 2 +- .../chapter_04_trees_and_graphs/problem_04_05_validateBST.h | 2 +- .../chapter_04_trees_and_graphs/problem_04_06_successor.h | 2 +- .../problem_04_08_firstCommonAncestor.h | 2 +- .../chapter_04_trees_and_graphs/problem_04_04_check_balanced.py | 2 +- .../chapter_04_trees_and_graphs/problem_04_05_validate_BST.py | 2 +- .../chapter_04_trees_and_graphs/problem_04_06_successor.py | 2 +- .../problem_04_08_first_common_ancestor.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h index f710370..83edbd1 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_04_checkBalanced.h @@ -13,7 +13,7 @@ it and (2) boolean if the numbers returned by its left and right children differ terminating condition is a node which does not have any children: in this case the node returns 0 and true. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(H) where H is the height of the tree */ #pragma once diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h index eab841b..2da0c4a 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_05_validateBST.h @@ -19,7 +19,7 @@ right child of the head, min=head_value and max=+Inf. We repeat this pattern for if a node is not in bounds. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(log(N)) assuming tree is balanced */ #pragma once diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h index e9172fb..794e52b 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h @@ -17,7 +17,7 @@ the leftmost node and return it. To check case 2, we traverse from the target no parent connections until we find a the first right ancestor and return it. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(log(N)) assuming tree is balanced */ #pragma once diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h index f153e7d..34d3835 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_08_firstCommonAncestor.h @@ -18,7 +18,7 @@ reference is assigned the current node which by definition is the first common a The terminating condition of the function is finding node1, node2, or Null. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(log(N)) if tree is balanced */ #pragma once diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py index e7a42ba..419abaf 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_04_check_balanced.py @@ -14,7 +14,7 @@ terminating condition is a node which does not have any children: in this case the node returns 0 and true. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(H) where H is the height of the tree """ diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py index ee7fb68..8be5eab 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_05_validate_BST.py @@ -19,7 +19,7 @@ if a node is not in bounds. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(log(N)) assuming tree is balanced """ diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py index 19b9e47..d8fe9df 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.py @@ -17,7 +17,7 @@ parent connections until we find a the first right ancestor and return it. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(log(N)) assuming tree is balanced """ diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py index 0a436e8..b18279a 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_08_first_common_ancestor.py @@ -18,7 +18,7 @@ The terminating condition of the function is finding node1, node2, or Null. Time complexity: O(N) -Space complexity: O(N) +Space complexity: O(log(N)) if tree is balanced """ From c0759e2ec2c173074145ceaf1d49e3afa211dc8a Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 17:20:07 -0500 Subject: [PATCH 021/176] refactor tests for 4.10 python. add essay 4.10 python and C++. add skeleton for 4.10 C++ --- .../chapter_04_includes.h | 1 + .../problem_04_10_checkSubtree.h | 29 +++++++ .../problem_04_10_check_subtree.py | 31 +++++-- tests.cpp | 4 + tests.py | 82 ++++++++++--------- 5 files changed, 103 insertions(+), 44 deletions(-) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index 782516b..a52a5bc 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -11,3 +11,4 @@ #include "problem_04_06_successor.h" #include "problem_04_07_buildOrder.h" #include "problem_04_08_firstCommonAncestor.h" +#include "problem_04_10_checkSubtree.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h new file mode 100644 index 0000000..e011565 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h @@ -0,0 +1,29 @@ +/* +Chapter 04 - Problem 10 - Check Subtree + +Problem Statement: +T1 and T2 are two very large binary trees, with T1 much bigger than T2. +Create an algorithm to determine if T2 is a subtree of T1. A tree T2 is a subtree of T1 +if there exists a node n in T1 such that the subtree of n is identical to T2. That is, +if you cut off the tree at node n, the two trees would be identical. + +Solution: +Traverse T1 recursively in the main function. If during the recursive traversal a node with the same +value as the head of T2 is found in T1, use a helper function to traverse T2 from its head and T1 from +simultaneously to check that every node in each subtree has the same value. If this helper function +returns True, the main function will return True. If the main function reaches the end of T1 without +the helper function having returned True, the main function will return false. + +Time complexity: O(N + KM) where K is the number of times the head of T2 appears in T1. +Space complexity: O(log(N) + log(M)) assuming trees are balanced +*/ + +#pragma once +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + template + bool checkSubtree(chapter_02::BinaryNode T1_head, chapter_02::BinaryNode T2_head) { + return false; + } +} // chapter_04 \ No newline at end of file diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py index 9d029e9..6767dd3 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py @@ -1,17 +1,38 @@ -def check_subtree(t2, t1): +""" +Chapter 04 - Problem 10 - Check Subtree + +Problem Statement: +T1 and T2 are two very large binary trees, with T1 much bigger than T2. +Create an algorithm to determine if T2 is a subtree of T1. A tree T2 is a subtree of T1 +if there exists a node n in T1 such that the subtree of n is identical to T2. That is, +if you cut off the tree at node n, the two trees would be identical. + +Solution: +Traverse T1 recursively in the main function. If during the recursive traversal a node with the same +value as the head of T2 is found in T1, use a helper function to traverse T2 from its head and T1 from +simultaneously to check that every node in each subtree has the same value. If this helper function +returns True, the main function will return True. If the main function reaches the end of T1 without +the helper function having returned True, the main function will return false. + +Time complexity: O(N + KM) where K is the number of times the head of T2 appears in T1. +Space complexity: O(log(N) + log(M)) assuming trees are balanced +""" + + +def check_subtree(t1, t2): if t1 is None or t2 is None: return False if t1.val == t2.val: # potential subtree - if subtree_equality(t2, t1): + if subtree_equality(t1, t2): return True - return check_subtree(t2, t1.left) or check_subtree(t2, t1.right) + return check_subtree(t1.left, t2) or check_subtree(t1.right, t2) -def subtree_equality(t2, t1): +def subtree_equality(t1, t2): if t2 is None and t1 is None: return True if t1 is None or t2 is None: return False if t2.val == t1.val: - return subtree_equality(t2.left, t1.left) and subtree_equality(t2.right, t1.right) + return subtree_equality(t1.left, t2.left) and subtree_equality(t1.right, t2.right) return False diff --git a/tests.cpp b/tests.cpp index 6fda8d4..65cb82c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -682,6 +682,10 @@ construct binary tree REQUIRE(&n7 == chapter_04::firstCommonAncestor(&n7, &n3, &n4)); } +TEST_CASE("Chapter 04 - Problem 10 - checkSubtree()", "test") { + +} + TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } diff --git a/tests.py b/tests.py index f6be4e4..e29c129 100644 --- a/tests.py +++ b/tests.py @@ -700,6 +700,9 @@ def test_problem_4_8(self): 4 3 10 5 6 15 21 17 + + + 25 """ n21 = tb.BinaryNode(21) n17 = tb.BinaryNode(17) @@ -718,46 +721,47 @@ def test_problem_4_8(self): self.assertEqual(None, p_4_8.first_common_ancestor(n7, n7, n7)) # a node is not its own ancestor self.assertEqual(n7, p_4_8.first_common_ancestor(n7, n3, n4)) - def test_problem_4_9(self): - n25 = tb.BinaryNode(25) - n70 = tb.BinaryNode(70) - n20 = tb.BinaryNode(20, right=n25) - n60 = tb.BinaryNode(60, right=n70) - n50 = tb.BinaryNode(50, left=n20, right=n60) - pass - def test_problem_4_10(self): - # tree 1 - n1_1 = tb.BinaryNode(1) - n2_1 = tb.BinaryNode(2) - n7_1 = tb.BinaryNode(7) - n9_1 = tb.BinaryNode(9) - n3_1 = tb.BinaryNode(3, n1_1, n2_1) - n8_1 = tb.BinaryNode(8, n7_1, n9_1) - n5_1 = tb.BinaryNode(5, n3_1, n8_1) - t1_head = n5_1 - # tree 2 - t2_head = n8_1 - # tree 3 - n12_3 = tb.BinaryNode(12) - n13_3 = tb.BinaryNode(13) - n11_3 = tb.BinaryNode(11, n12_3, n13_3) - t3_head = n11_3 - # tree 4 - n7_4 = tb.BinaryNode(7) - n9_4 = tb.BinaryNode(9) - n8_4 = tb.BinaryNode(8, n7_4, n9_4) - t4_head = n8_4 - # tree 5 - n6_5 = tb.BinaryNode(6) - n9_5 = tb.BinaryNode(9) - n8_5 = tb.BinaryNode(8, n6_5, n9_5) - t5_head = n8_5 - self.assertEqual(p_4_10.check_subtree(t1_head, t1_head), True) - self.assertEqual(p_4_10.check_subtree(t2_head, t1_head), True) - self.assertEqual(p_4_10.check_subtree(t3_head, t1_head), False) - self.assertEqual(p_4_10.check_subtree(t4_head, t1_head), True) - self.assertEqual(p_4_10.check_subtree(t5_head, t1_head), False) + """ + construct binary tree + 7 + 4 3 + 10 5 6 15 + 21 17 + + + 25 + """ + n21 = tb.BinaryNode(21) + n17 = tb.BinaryNode(17) + n15 = tb.BinaryNode(15, n21, n17) + n6 = tb.BinaryNode(6) + n3 = tb.BinaryNode(3, n6, n15) + n10 = tb.BinaryNode(10) + n5 = tb.BinaryNode(5) + n4 = tb.BinaryNode(4, n10, n5) + n7 = tb.BinaryNode(7, n4, n3) + n25 = tb.BinaryNode(25) # unconnected node + + """ + construct disconnected binary tree + 30 + 31 32 + """ + n31 = tb.BinaryNode(31) + n32 = tb.BinaryNode(32) + n30 = tb.BinaryNode(30, n31, n32) + + self.assertEqual(True, p_4_10.check_subtree(n7, n15)) + self.assertEqual(True, p_4_10.check_subtree(n7, n7)) + self.assertEqual(True, p_4_10.check_subtree(n7, n21)) + self.assertEqual(True, p_4_10.check_subtree(n7, n4)) + self.assertEqual(False, p_4_10.check_subtree(n7, None)) + self.assertEqual(False, p_4_10.check_subtree(n7, n30)) + self.assertEqual(False, p_4_10.check_subtree(n4, n31)) + self.assertEqual(False, p_4_10.check_subtree(n25, n31)) + self.assertEqual(True, p_4_10.check_subtree(n30, n31)) + self.assertEqual(False, p_4_10.check_subtree(None, None)) def test_problem_4_11(self): random.seed(0) From 4554361dcc153f549b11fa7af81be24b1c03abb4 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 20:15:25 -0500 Subject: [PATCH 022/176] WIP implementing 4.8 C++ --- .../problem_04_10_checkSubtree.h | 10 +++- .../problem_04_10_check_subtree.py | 18 +++---- tests.cpp | 54 ++++++++++++++++--- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h index e011565..b5a7106 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h @@ -22,8 +22,14 @@ Space complexity: O(log(N) + log(M)) assuming trees are balanced #include "../chapter_02_linked_lists/Node.h" namespace chapter_04 { + + template - bool checkSubtree(chapter_02::BinaryNode T1_head, chapter_02::BinaryNode T2_head) { - return false; + bool checkSubtree(const chapter_02::BinaryNode* T1_head, const chapter_02::BinaryNode* T2_head) { + if (T1_head == nullptr || T2_head == nullptr) return false; + if (T1_head->getValue() == T2_head->getValue()) { + if () + } + } } // chapter_04 \ No newline at end of file diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py index 6767dd3..c027ed4 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_10_check_subtree.py @@ -19,15 +19,6 @@ """ -def check_subtree(t1, t2): - if t1 is None or t2 is None: - return False - if t1.val == t2.val: # potential subtree - if subtree_equality(t1, t2): - return True - return check_subtree(t1.left, t2) or check_subtree(t1.right, t2) - - def subtree_equality(t1, t2): if t2 is None and t1 is None: return True @@ -36,3 +27,12 @@ def subtree_equality(t1, t2): if t2.val == t1.val: return subtree_equality(t1.left, t2.left) and subtree_equality(t1.right, t2.right) return False + + +def check_subtree(t1, t2): + if t1 is None or t2 is None: + return False + if t1.val == t2.val: # potential subtree + if subtree_equality(t1, t2): + return True + return check_subtree(t1.left, t2) or check_subtree(t1.right, t2) diff --git a/tests.cpp b/tests.cpp index 65cb82c..ce3c5f2 100644 --- a/tests.cpp +++ b/tests.cpp @@ -656,14 +656,16 @@ TEST_CASE("Chapter 04 - Problem 07 - buildOrder()", "test") { } TEST_CASE("Chapter 04 - Problem 08 - firstCommonAncestor()", "test") { -/* -construct binary tree - 7 - 4 3 - 10 5 6 15 - 21 17 -*/ + /* + 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); @@ -683,7 +685,45 @@ construct binary tree } 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 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); + /* + construct disconnected binary tree + 30 + 31 32 + */ + chapter_02::BinaryNode n31(31); + chapter_02::BinaryNode n32(32); + chapter_02::BinaryNode n30(30, &n31, &n32); + + REQUIRE(chapter_04::checkSubtree(&n7, &n15)); + REQUIRE(chapter_04::checkSubtree(&n7, &n7)); + REQUIRE(chapter_04::checkSubtree(&n7, &n21)); + REQUIRE(chapter_04::checkSubtree(&n7, &n4)); + REQUIRE(!chapter_04::checkSubtree(&n7, nullptr)); + REQUIRE(!chapter_04::checkSubtree(&n7, &n30)); + REQUIRE(!chapter_04::checkSubtree(&n7, &n31)); + REQUIRE(!chapter_04::checkSubtree(&n25, &n31)); + REQUIRE(chapter_04::checkSubtree(&n30, &n31)); + REQUIRE(!chapter_04::checkSubtree(nullptr, nullptr)); } TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ From 7cbd7e1045fb682ad10d6dcf4cc2837cc72a3ef9 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 19:00:15 -0800 Subject: [PATCH 023/176] implement 4.8 C++. increase make test to use 6 cores --- Makefile | 4 ++-- .../problem_04_10_checkSubtree.h | 21 ++++++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 9f31ec4..a406eee 100644 --- a/Makefile +++ b/Makefile @@ -12,13 +12,13 @@ clean: test: @echo TESTING C++ SOLUTIONS - cd build && make -j4 && ./tests + cd build && make -j6 && ./tests @echo TESTING PYTHON SOLUTIONS python3 tests.py test_coverage: @echo TESTING C++ SOLUTIONS - cd build && make -j4 && ./tests + cd build && make -j6 && ./tests @echo TESTING PYTHON SOLUTIONS coverage run --source=python_solutions tests.py coverage report -m diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h index b5a7106..4f1c07c 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_10_checkSubtree.h @@ -22,14 +22,25 @@ Space complexity: O(log(N) + log(M)) assuming trees are balanced #include "../chapter_02_linked_lists/Node.h" namespace chapter_04 { - + template + bool subtreeEquality(const chapter_02::BinaryNode* T1_head, const chapter_02::BinaryNode* T2_head) { + if (T1_head == nullptr && T2_head == nullptr) { + return true; + } else if (T1_head == nullptr || T2_head == nullptr) { + return false; + } else if (T1_head->getValue() != T2_head->getValue()) { + return false; + } + return subtreeEquality(T1_head->getLeft(), T2_head->getLeft()) && subtreeEquality(T1_head->getRight(), T2_head->getRight()); + } template bool checkSubtree(const chapter_02::BinaryNode* T1_head, const chapter_02::BinaryNode* T2_head) { - if (T1_head == nullptr || T2_head == nullptr) return false; - if (T1_head->getValue() == T2_head->getValue()) { - if () + if (T1_head == nullptr || T2_head == nullptr) { + return false; + } else if (T1_head->getValue() == T2_head->getValue()) { + if (subtreeEquality(T1_head, T2_head)) return true; } - + return checkSubtree(T1_head->getLeft(), T2_head) || checkSubtree(T1_head->getRight(), T2_head); } } // chapter_04 \ No newline at end of file From 4e24ad4266d8eaac0e20c0edfc262a6fc2c82294 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 9 Feb 2019 19:01:11 -0800 Subject: [PATCH 024/176] update completion in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ba40755..a0e36c9 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `8 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `9 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `39 / 151` +Total: `40 / 151` ### Building: #### Mac: From c812724b75a2f48045a0f0c14334936300775131 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 11 Feb 2019 18:33:32 -0800 Subject: [PATCH 025/176] WIP 4.11 --- cpp_solutions/chapter_02_linked_lists/Node.h | 24 +++++++++++++++++++ .../chapter_04_includes.h | 1 + .../problem_04_11_randomBST.h | 8 +++++++ ...om_node.py => problem_04_11_random_BST.py} | 0 tests.py | 2 +- 5 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h rename python_solutions/chapter_04_trees_and_graphs/{problem_04_11_random_node.py => problem_04_11_random_BST.py} (100%) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index f483cc2..4009121 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -155,6 +155,30 @@ namespace chapter_02{ } }; + // specialized node for binary trees that allow random node access + template + class RandBinaryNode : BinaryNode { + private: + int _leftChildren; + int _rightChildren; + public: + RandBinaryNode( + T value, + RandBinaryNode* left = nullptr, + RandBinaryNode* right = nullptr, + RandBinaryNode* parent = nullptr) : + BinaryNode(left, right, parent) { + _leftChildren = 0; + _rightChildren = 0; + } + int getLeftChildren() const { return _leftChildren;} + int getrightChildren() const { return _rightChildren;} + void incrementLeftChildren () {_leftChildren ++;} + void incrementRightChildren () {_rightChildren ++;} + void decrementLeftChildren () {_leftChildren --;} + void decrementRightChildren () {_rightChildren --;} + }; + // utility function that converts contents of std::vector to linked list template SinglyLinkedNode* vectorToList(const std::vector numbers){ diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index a52a5bc..618a984 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -12,3 +12,4 @@ #include "problem_04_07_buildOrder.h" #include "problem_04_08_firstCommonAncestor.h" #include "problem_04_10_checkSubtree.h" +#include "problem_04_11_randomBST.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h new file mode 100644 index 0000000..4ebb716 --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h @@ -0,0 +1,8 @@ +#pragma once +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + template + class randomBST { + }; +} // namespace chapter_04 diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_node.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py similarity index 100% rename from python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_node.py rename to python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py diff --git a/tests.py b/tests.py index e29c129..f877224 100644 --- a/tests.py +++ b/tests.py @@ -37,7 +37,7 @@ from python_solutions.chapter_04_trees_and_graphs import problem_04_07_build_order as p_4_7 from python_solutions.chapter_04_trees_and_graphs import problem_04_08_first_common_ancestor as p_4_8 from python_solutions.chapter_04_trees_and_graphs import problem_04_10_check_subtree as p_4_10 -from python_solutions.chapter_04_trees_and_graphs import problem_04_11_random_node as p_4_11 +from python_solutions.chapter_04_trees_and_graphs import problem_04_11_random_BST as p_4_11 from python_solutions.chapter_04_trees_and_graphs import problem_04_12_paths_with_sum as p_4_12 from python_solutions.chapter_05_bit_manipulation import problem_05_00_convert_binary as p_5_0 from python_solutions.chapter_05_bit_manipulation import problem_05_01_insertion as p_5_1 From 8a945515ce4c9f452466fc60ce9ecfa4aaa09a1d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 17 Feb 2019 18:12:09 -0800 Subject: [PATCH 026/176] add way more meaningful tests by comparing the random occurrence of node values with the known quantities of values in the binary tree --- tests.py | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests.py b/tests.py index f877224..eee5a7f 100644 --- a/tests.py +++ b/tests.py @@ -765,15 +765,30 @@ def test_problem_4_10(self): def test_problem_4_11(self): random.seed(0) - rnd_bst = p_4_11.RandBST() - values_list = [10, 13, 14, 11, 7, 5, 8, 6, 4, 10] + rnd_bst_head = p_4_11.RandBinNode() + values_list = [10, 13, 14, 11, 7, 7, 8, 7, 4, 10] for i in values_list: - rnd_bst.insert(i) - self.assertEqual(rnd_bst.get_random(), 11) - self.assertEqual(rnd_bst.get_random(), 8) - self.assertEqual(rnd_bst.get_random(), 11) - self.assertEqual(rnd_bst.get_random(), 8) - self.assertEqual(rnd_bst.get_random(), 13) + rnd_bst_head.insert(i) + occurrence_sum_4 = 0 + occurrence_sum_7 = 0 + occurrence_sum_10 = 0 + occurrence_sum_13 = 0 + # using 10,000 random samples, assert that occurence of values in random samples approximately + # the same as the occurence of the values in the tree + for i in range(10000): + rand_value = rnd_bst_head.get_random() + if rand_value == 4: + occurrence_sum_4 += 1 + elif rand_value == 7: + occurrence_sum_7 += 1 + elif rand_value == 10: + occurrence_sum_10 += 1 + elif rand_value == 13: + occurrence_sum_13 += 1 + self.assertAlmostEqual(occurrence_sum_4, 1000, delta=50) + self.assertAlmostEqual(occurrence_sum_7, 3000, delta=50) # 7 occurs 3 times more than 4 + self.assertAlmostEqual(occurrence_sum_10, 2000, delta=50) # 10 occurs 2 times more than 4 + self.assertAlmostEqual(occurrence_sum_13, 1000, delta=50) def test_problem_4_12(self): # create tree. Same tree as in textbook. From 3488d686657dd47e1dd93710a8a74721af0d17d9 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 17 Feb 2019 18:13:43 -0800 Subject: [PATCH 027/176] (1) fix bug where probability of value occurrence did not empirically match expectations (2) refactor random binary tree to only need one class --- .../problem_04_11_random_BST.py | 63 ++++++++----------- 1 file changed, 25 insertions(+), 38 deletions(-) diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py index 44370c5..9a61402 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py @@ -3,7 +3,7 @@ class RandBinNode: - def __init__(self, value, left=None, right=None, children=0): + def __init__(self, value=None, left=None, right=None, children=0): self.value = value self.left = left self.right = right @@ -21,48 +21,35 @@ def right_children(self): else: return 1 + self.right.children - -class RandBST: - def __init__(self, root=None): - self.root = root - def insert(self, value): - if self.root is None: - self.root = RandBinNode(value) + if value is None: # like good silicon valley people, we disallow adding no value + return + if self.value is None: # create children only if the current node has no value + self.value = value return - runner = self.root - while 1: - if value > runner.value: - runner.children += 1 - if runner.right is not None: - runner = runner.right - else: - runner.right = RandBinNode(value) - return - elif value < runner.value: - runner.children += 1 - if runner.left is not None: - runner = runner.left - else: - runner.left = RandBinNode(value) - return + self.children += 1 + if value > self.value: + if self.right is not None: + self.right.insert(value) + else: + self.right = RandBinNode(value) + else: + if self.left is not None: + self.left.insert(value) else: - return # don't allow non-unique values in tree + self.left = RandBinNode(value) + return def get_random(self): - if self.root is None: - return None - runner = self.root - while 1: - assert(runner.children == runner.left_children() + runner.right_children()) # - sum_of_nodes = 1 + runner.children - rand_int = random.randint(1, sum_of_nodes) - if rand_int == 1: - return runner.value - elif 1 < rand_int <= 1 + runner.left_children(): - runner = runner.left - elif 1 + runner.left_children() < rand_int: - runner = runner.right + assert(self.children == self.left_children() + self.right_children()) + num_nodes = 1 + self.children + rand_int = random.randint(1, num_nodes) + if rand_int == 1: + return self.value + elif 1 < rand_int <= 1 + self.left_children(): + return self.left.get_random() + elif 1 + self.left_children() < rand_int: + return self.right.get_random() def find(self): pass From 9cd956e7c6270b80908428f591666e015ffc658c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 17 Feb 2019 21:26:19 -0800 Subject: [PATCH 028/176] add essay for 4.11 python --- .../problem_04_11_random_BST.py | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py index 9a61402..e1efd6c 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py @@ -1,3 +1,35 @@ +""" +Chapter 04 - Problem 11 - Random Node + +Problem Statement: +You are implementing a binary search tree class from scratch, which, in addition to insert, find, and delete, +has a method getRandomNode() which returns a random node from the tree. All nodes should be equally likely to +be chosen. Design and implement an algorithm for getRandomNode(), and explain how you would implement the rest +of the methods. + +Solution: +The obvious - but not necessarily optimal - solution is to create and maintain an array of pointers to each node in the +tree. When a random node is desired, a random number between zero and the maximum index of the array is generated and +the pointer at the random index is returned. This solution has a time complexity of O(1) for getRandomNode() calls and space +complexity of O(N) due to the space required for the array of pointers. If nodes were never removed from the tree, this +solution would be fine. However, if nodes are removed from the tree, modifying and resizing pointer array requires O(N) time. + +A solution that is more optimal in the case of possible node removal is to randomly traverse the tree and +return the node reached after random traversal. In this case, adding nodes to the tree requires O(log(N)) time, removing +nodes from the tree requires O(log(N)) time, and getting a random node requires O(log(N)) time. The random traversal is +enabled by incrementing and decrementing each node's number of children during operations that insert or delete a node from +the tree. At each instance of a recursive traversal, the value of a random number is used to decide whether to +traverse left, traverse right, or return the current node. The probabilities of the choices will be proportional to the +number of nodes that each choice represents i.e. if a node has 4 left children and 3 right children, the probability to +return itself is 1/8, the probability to traverse left is 4/8, and the probability to traverse right is 3/8. Since random +number generator calls can be expensive, we employ an optimization in which we only generate a random number at the head +of the tree, then propagate the random value to the recursive traversals after accounting for the reduction in node children +at every level. This solution also uses O(N) space because each node must store its total number of children. + +Time complexity: O(log(N)) for a balanced tree. O(D) for an unbalanced tree where D is the depth of the tree. +Space complexity: O(N) because the number of children must be stored for each node. +""" + import random @@ -22,7 +54,7 @@ def right_children(self): return 1 + self.right.children def insert(self, value): - if value is None: # like good silicon valley people, we disallow adding no value + if value is None: # disallow adding no value return if self.value is None: # create children only if the current node has no value self.value = value @@ -40,16 +72,15 @@ def insert(self, value): self.left = RandBinNode(value) return - def get_random(self): - assert(self.children == self.left_children() + self.right_children()) - num_nodes = 1 + self.children - rand_int = random.randint(1, num_nodes) - if rand_int == 1: + def get_random(self, rand_int=None): + if rand_int is None: + rand_int = random.randint(1, 1 + self.children) + if rand_int <= 1: return self.value elif 1 < rand_int <= 1 + self.left_children(): - return self.left.get_random() + return self.left.get_random(rand_int - 1) # no need to compute new random number elif 1 + self.left_children() < rand_int: - return self.right.get_random() + return self.right.get_random(rand_int - self.left_children() - 1) # if we traverse right, make rand_int stay in range of # of children def find(self): pass From eb281f40454096065d5c741a47787b5bf94fcfcb Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 17 Feb 2019 21:27:46 -0800 Subject: [PATCH 029/176] (1) implement tests for 4.11 C++. (2) implement interface for 4.11 C++ --- cpp_solutions/chapter_02_linked_lists/Node.h | 24 --------- .../problem_04_11_randomBST.h | 50 ++++++++++++++++++- tests.cpp | 31 ++++++++++++ 3 files changed, 80 insertions(+), 25 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 4009121..f483cc2 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -155,30 +155,6 @@ namespace chapter_02{ } }; - // specialized node for binary trees that allow random node access - template - class RandBinaryNode : BinaryNode { - private: - int _leftChildren; - int _rightChildren; - public: - RandBinaryNode( - T value, - RandBinaryNode* left = nullptr, - RandBinaryNode* right = nullptr, - RandBinaryNode* parent = nullptr) : - BinaryNode(left, right, parent) { - _leftChildren = 0; - _rightChildren = 0; - } - int getLeftChildren() const { return _leftChildren;} - int getrightChildren() const { return _rightChildren;} - void incrementLeftChildren () {_leftChildren ++;} - void incrementRightChildren () {_rightChildren ++;} - void decrementLeftChildren () {_leftChildren --;} - void decrementRightChildren () {_rightChildren --;} - }; - // utility function that converts contents of std::vector to linked list template SinglyLinkedNode* vectorToList(const std::vector numbers){ diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h index 4ebb716..21f5d07 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h @@ -1,8 +1,56 @@ +/* +Chapter 04 - Problem 11 - Random Node + +Problem Statement: +You are implementing a binary search tree class from scratch, which, in addition to insert, find, and delete, +has a method getRandomNode() which returns a random node from the tree. All nodes should be equally likely to +be chosen. Design and implement an algorithm for getRandomNode(), and explain how you would implement the rest +of the methods. + +Solution: +The obvious - but not necessarily optimal - solution is to create and maintain an array of pointers to each node in the +tree. When a random node is desired, a random number between zero and the maximum index of the array is generated and +the pointer at the random index is returned. This solution has a time complexity of O(1) for getRandomNode() calls and space +complexity of O(N) due to the space required for the array of pointers. If nodes were never removed from the tree, this +solution would be fine. However, if nodes are removed from the tree, modifying and resizing pointer array requires O(N) time. + +A solution that is more optimal in the case of possible node removal is to randomly traverse the tree and +return the node reached after random traversal. In this case, adding nodes to the tree requires O(log(N)) time, removing +nodes from the tree requires O(log(N)) time, and getting a random node requires O(log(N)) time. The random traversal is +enabled by incrementing and decrementing each node's number of children during operations that insert or delete a node from +the tree. At each instance of a recursive traversal, the value of a random number is used to decide whether to +traverse left, traverse right, or return the current node. The probabilities of the choices will be proportional to the +number of nodes that each choice represents i.e. if a node has 4 left children and 3 right children, the probability to +return itself is 1/8, the probability to traverse left is 4/8, and the probability to traverse right is 3/8. Since random +number generator calls can be expensive, we employ an optimization in which we only generate a random number at the head +of the tree, then propagate the random value to the recursive traversals after accounting for the reduction in node children +at every level. This solution also uses O(N) space because each node must store its total number of children. + +Time complexity: O(log(N)) for a balanced tree. O(D) for an unbalanced tree where D is the depth of the tree. +Space complexity: O(N) because the number of children must be stored for each node. +*/ + #pragma once #include "../chapter_02_linked_lists/Node.h" namespace chapter_04 { + // specialized node for binary trees that allow random node access template - class randomBST { + class RandBinaryNode : public chapter_02::BinaryNode { + private: + int _children; + public: + RandBinaryNode( + T value, + RandBinaryNode* left = nullptr, + RandBinaryNode* right = nullptr, + RandBinaryNode* parent = nullptr) : chapter_02::BinaryNode(value, left, right, parent) { + _children = 0; + } + void insert(const T& value) {} + RandBinaryNode* getRandomNode() const {return nullptr;} + int getChildren() const { return _children;} + void incrementChildren() {_children ++;} + void decrementChildren() {_children --;} }; } // namespace chapter_04 diff --git a/tests.cpp b/tests.cpp index ce3c5f2..a5f58ea 100644 --- a/tests.cpp +++ b/tests.cpp @@ -15,6 +15,7 @@ #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")); @@ -726,6 +727,36 @@ TEST_CASE("Chapter 04 - Problem 10 - checkSubtree()", "test") { REQUIRE(!chapter_04::checkSubtree(nullptr, nullptr)); } +TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ + // std::random_device rd; // will be used to obtain a seed for the random number engine + std::mt19937 gen(0); // standard mersenne_twister_engine seeded with rd() + std::uniform_int_distribution<> dis(1, 6); + std::vector valuesList = {10, 13, 14, 11, 7, 7, 8, 7, 4, 10}; + chapter_04::RandBinaryNode head(valuesList[0]); + for (int i = 1; i < valuesList.size(); i++) { + head.insert(valuesList[i]); + } + int occurrenceSum4 = 0; + int occurrenceSum7 = 0; + int occurrenceSum10 = 0; + int occurrenceSum13 = 0; + // using 10,000 random samples, assert that occurence of values in random samples approximately + // the same as the occurence of the values in the tree + for (int i = 0; i < 10000; i++) { + int randValue = head.getRandomNode()->getValue(); + switch (randValue){ + case 4 : occurrenceSum4 ++; break; + case 7 : occurrenceSum7 ++; break; + case 10 : occurrenceSum10 ++; break; + case 13 : occurrenceSum13 ++; break; + } + } + REQUIRE(((950 <= occurrenceSum4) && (occurrenceSum4 <= 1050))); + REQUIRE(((2950 <= occurrenceSum7) && (occurrenceSum7 <= 3050))); + REQUIRE(((1950 <= occurrenceSum10) && (occurrenceSum10 <= 2050))); + REQUIRE(((950 <= occurrenceSum13) && (occurrenceSum13 <= 1050))); +} + TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } From 181ed2e30ab33f8e04cf30be0f84535bcdbec195 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 18 Feb 2019 01:58:47 -0800 Subject: [PATCH 030/176] implement 4.11 C++ --- .../problem_04_11_randomBST.h | 54 +++++++++++++++++-- .../problem_04_11_random_BST.py | 3 +- tests.cpp | 6 +-- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h index 21f5d07..862fd11 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_11_randomBST.h @@ -32,6 +32,7 @@ Space complexity: O(N) because the number of children must be stored for each no #pragma once #include "../chapter_02_linked_lists/Node.h" +#include namespace chapter_04 { // specialized node for binary trees that allow random node access @@ -47,9 +48,56 @@ namespace chapter_04 { RandBinaryNode* parent = nullptr) : chapter_02::BinaryNode(value, left, right, parent) { _children = 0; } - void insert(const T& value) {} - RandBinaryNode* getRandomNode() const {return nullptr;} - int getChildren() const { return _children;} + + void insert(const T& value) { + incrementChildren(); + if (value > this->getValue()) { + if (this->getRight() != nullptr) { + static_cast*>(this->getRight())->insert(value); + } else { + this->setRight(new RandBinaryNode(value)); + } + } else { + if (this->getLeft() != nullptr) { + static_cast*>(this->getLeft())->insert(value); + } else { + this->setLeft(new RandBinaryNode(value)); + } + } + } + + RandBinaryNode* getRandomNode(int randInt = -1, std::mt19937* gen = nullptr) { + if (gen != nullptr) { + std::uniform_int_distribution<> dis(1, 1 + getChildren()); + randInt = dis(*gen); + } + if (randInt <= 1) { + return this; + } else if (1 < randInt && randInt <= 1 + getLeftChildren()) { + return static_cast*>(this->getLeft())->getRandomNode(randInt - 1, nullptr); + } else { + return static_cast*>(this->getRight())->getRandomNode(randInt - 1 - getLeftChildren(), nullptr); + } + } + + int getChildren() const { return _children; } + + int getLeftChildren() const { + if (static_cast*>(this->getLeft()) == nullptr) { + return 0; + } else { + return 1 + static_cast*>(this->getLeft())->getChildren(); + } + } + + int getRightChildren() const { + if (static_cast*>(this->getRight()) == nullptr) { + return 0; + } else { + return 1 + static_cast*>(this->getRight())->getChildren(); + } + } + void incrementChildren() {_children ++;} void decrementChildren() {_children --;} }; diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py index e1efd6c..6586a76 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_11_random_BST.py @@ -70,7 +70,6 @@ def insert(self, value): self.left.insert(value) else: self.left = RandBinNode(value) - return def get_random(self, rand_int=None): if rand_int is None: @@ -79,7 +78,7 @@ def get_random(self, rand_int=None): return self.value elif 1 < rand_int <= 1 + self.left_children(): return self.left.get_random(rand_int - 1) # no need to compute new random number - elif 1 + self.left_children() < rand_int: + else: return self.right.get_random(rand_int - self.left_children() - 1) # if we traverse right, make rand_int stay in range of # of children def find(self): diff --git a/tests.cpp b/tests.cpp index a5f58ea..22dc09e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -728,9 +728,6 @@ TEST_CASE("Chapter 04 - Problem 10 - checkSubtree()", "test") { } TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ - // std::random_device rd; // will be used to obtain a seed for the random number engine - std::mt19937 gen(0); // standard mersenne_twister_engine seeded with rd() - std::uniform_int_distribution<> dis(1, 6); std::vector valuesList = {10, 13, 14, 11, 7, 7, 8, 7, 4, 10}; chapter_04::RandBinaryNode head(valuesList[0]); for (int i = 1; i < valuesList.size(); i++) { @@ -742,8 +739,9 @@ TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ int occurrenceSum13 = 0; // using 10,000 random samples, assert that occurence of values in random samples approximately // the same as the occurence of the values in the tree + std::mt19937 gen(0); // standard mersenne_twister_engine seeded with zero for (int i = 0; i < 10000; i++) { - int randValue = head.getRandomNode()->getValue(); + int randValue = head.getRandomNode(-1, &gen)->getValue(); switch (randValue){ case 4 : occurrenceSum4 ++; break; case 7 : occurrenceSum7 ++; break; From 5ebb6fbaa7e7d77dd3b8179f9ea5a70ca8e4f246 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 18 Feb 2019 02:01:05 -0800 Subject: [PATCH 031/176] update completion in readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a0e36c9..75d75e1 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ Total: `56 / 145` 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `9 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `10 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -59,7 +59,7 @@ Total: `56 / 145` 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `40 / 151` +Total: `41 / 151` ### Building: #### Mac: From e3b615d4b71b1e6c040884f2f7cf4028126731d1 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 18 Feb 2019 02:17:34 -0800 Subject: [PATCH 032/176] re-order table of contents --- README.md | 56 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 75d75e1..4758f08 100644 --- a/README.md +++ b/README.md @@ -7,38 +7,18 @@ * :white_check_mark: Multiplatform Support: Mac, Linux, and Windows ### Introduction -This repo contains Python and C++ solutions for Gayle Laakmann McDowell's [*Cracking the Coding Interview 6th Edition*](http://a.co/baneyGe). +This repo contains C++ and Python solutions for Gayle Laakmann McDowell's [*Cracking the Coding Interview 6th Edition*](http://a.co/baneyGe). Admittedly, there are other GitHub repositories with solutions for this book. *But how do you know that their code is actually correct?* If it's untested, then you don't! -In this project, every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html) -and every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch). We enforce -the tests automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is -the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can reference and contribute solutions with confidence. +In this project, every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch), +and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html) +We enforce test correctness automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) +ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is +the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can +reference and contribute solutions with confidence. ### Table of Contents -#### [Python Solutions](python_solutions): -0. [Python Unit tests](tests.py) -1. [Chapter 1 - Arrays and Strings](python_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. -2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. -4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. -7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. -11. Chapter 11 - Testing: N/A -12. Chapter 12 - C and C++: N/A -13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. -17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. - -Total: `56 / 145` - #### [C++ Solutions](cpp_solutions): 0. [C++ Unit Tests](tests.cpp) 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. @@ -61,6 +41,28 @@ Total: `56 / 145` Total: `41 / 151` +#### [Python Solutions](python_solutions): +0. [Python Unit tests](tests.py) +1. [Chapter 1 - Arrays and Strings](python_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. +2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. +3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. +4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. +5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. +7. Chapter 7 - Object Oriented Design: `0 / 12` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. +9. Chapter 9 - System Design and Scalability: N/A +10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +11. Chapter 11 - Testing: N/A +12. Chapter 12 - C and C++: N/A +13. Chapter 13 - Java: N/A +14. Chapter 14 - Databases: N/A +15. Chapter 15 - Threads and Locks: `0 / 4` complete. +16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. +17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. + +Total: `56 / 145` + ### Building: #### Mac: Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: From f9f297a5298c0ced9cdd96ef62e1df4b67dece74 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 24 Feb 2019 15:48:16 -0800 Subject: [PATCH 033/176] update completion after 4.12 C++ --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4758f08..07493e5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Admittedly, there are other GitHub repositories with solutions for this book. *B how do you know that their code is actually correct?* If it's untested, then you don't! In this project, every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch), -and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html) +and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html). We enforce test correctness automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can @@ -24,7 +24,7 @@ reference and contribute solutions with confidence. 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `10 / 12` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `41 / 151` +Total: `42 / 151` #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) From e649f3a52991d7d40f8e353549fd526df859e2f2 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 24 Feb 2019 15:51:31 -0800 Subject: [PATCH 034/176] make test contain tree identical to 4.12 textbook example --- tests.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/tests.py b/tests.py index eee5a7f..c59d5e8 100644 --- a/tests.py +++ b/tests.py @@ -791,16 +791,27 @@ def test_problem_4_11(self): self.assertAlmostEqual(occurrence_sum_13, 1000, delta=50) def test_problem_4_12(self): - # create tree. Same tree as in textbook. - n_11 = tb.BinaryNode(11) - n_minus_8 = tb.BinaryNode(-8) + """ + construct binary tree like in textbook example + 10 + 5 -3 + 3 1 __ 11 + 3 -2 __ 2 + """ + # leaf nodes at depth = 3 + n_3_leaf = tb.BinaryNode(3) n_minus_2 = tb.BinaryNode(-2) n_2 = tb.BinaryNode(2) + # nodes at depth = 2 + n_3 = tb.BinaryNode(3, n_3_leaf, n_minus_2) n_1 = tb.BinaryNode(1, None, n_2) - n_3 = tb.BinaryNode(3, n_minus_8, n_minus_2) - n_minus_3 = tb.BinaryNode(-3, None, n_11) + n_11 = tb.BinaryNode(11) + # nodes at depth = 1 n_5 = tb.BinaryNode(5, n_3, n_1) + n_minus_3 = tb.BinaryNode(-3, None, n_11) + # root node at depth = 0 n_10 = tb.BinaryNode(10, n_5, n_minus_3) + # count paths that sum to 8 self.assertEqual(p_4_12.paths_with_sum(n_10, 8), 3) def test_problem_5_0(self): From 09b5ccca9d4a53a82ca638741d81ca6fa68f3c8b Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 24 Feb 2019 15:53:34 -0800 Subject: [PATCH 035/176] write essay for 4.12 --- .../problem_04_12_paths_with_sum.py | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_12_paths_with_sum.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_12_paths_with_sum.py index c03da1b..9be30f1 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_12_paths_with_sum.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_12_paths_with_sum.py @@ -1,3 +1,43 @@ +""" +Chapter 04 - Problem 12 - Paths with Sum + +Problem Statement: +You are given a binary tree in which each node contains an integer value (which might be positive or negative). +Design an algorithm to count the number of paths that sum to a given value. The path does not need to start or +end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). + +Solution: +The brute force solution to this problem is to (1) DFS traverse the tree starting from the root and (2) +initiate a new DFS traversal at each node. For each of the type (2) traversals, we keep a running sum of the node values +that have been traversed. When the running sum equals the target sum, we increment a global total. To calculate the +total runtime, we observe that that a node at depth d has d ancestors. Because of the recursive nature of the +algorithm, those ancestors will each cause function (2) to be called on a given node. From the definitions of +binary trees, the depth of a tree with N nodes is equal to log(N). Thus the runtime is thus O(N*log(N)) for a balanced +tree. For an unbalanced tree (in the worst case, every node of the tree is on the same side), the depth of a tree +with N nodes is N. Thus, the worst case runtime of this algorithm is O(N^2). Because a running sum must be stored for +each node (along with the data associated with the node itself) space complexity is O(N). + +A more efficient solution is to only traverse the tree once using depth first search and use a hash table to +keep track of running sums. In the hash table, the keys are running sums and the values are the numbers of times +the keys have been encountered. By definition, a path leads to the target sum if the difference between the current +running sum and *any previously encountered running sum* is equal to the target sum. At each node encountered during the +traversal, we add that node's running sum to a hash table; if that running sum is already in the hash table, then +we increment its value. Also at each node, we compute the difference between the node's running sum and the target +sum: if that difference is equal to *any* previously observed running sum, then we've discovered a path that yields +the target sum. Furthermore, if there exist multiple of the same running sum, then we've discovered multiple paths that +yield the target sum. Thus, when the difference is equal to the target sum, we increment a global path total by the +current running sum's hash table value thus computing the number of paths that lead to the target sum. One final bit +of complexity in this solution is that hashed sums from traversing one path will not apply to a totally different +path in the tree. We resolve this issue in the recursive implementation of depth first search: once a given node's +left and right recursive calls are completed, we *decrement* that node's running sum in the hash table. In this way, +we do a constant number of hash table lookups at each node in the tree yielding a O(N) worst case runtime and O(N) +space required due to the max hash table size and the sunning sums stored for each node. + +Time complexity: O(N) +Space complexity: O(N) +""" + + def paths_with_sum(root, target_sum): hash_table = {} return count_paths(root, target_sum, 0, hash_table) From ba398dee173a6f6bcc1bbcfc456f7bc1ba34b94d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 24 Feb 2019 16:39:49 -0800 Subject: [PATCH 036/176] tests and skeleton for 4.12 C++ --- .../chapter_04_includes.h | 1 + .../problem_04_12_pathsWithSum.h | 47 +++++++++++++++++++ tests.cpp | 25 ++++++++++ 3 files changed, 73 insertions(+) create mode 100644 cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index 618a984..5b5e9d9 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -13,3 +13,4 @@ #include "problem_04_08_firstCommonAncestor.h" #include "problem_04_10_checkSubtree.h" #include "problem_04_11_randomBST.h" +#include "problem_04_12_pathsWithSum.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h new file mode 100644 index 0000000..966d1fa --- /dev/null +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h @@ -0,0 +1,47 @@ +/* +Chapter 04 - Problem 12 - Paths with Sum + +Problem Statement: +You are given a binary tree in which each node contains an integer value (which might be positive or negative). +Design an algorithm to count the number of paths that sum to a given value. The path does not need to start or +end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). + +Solution: +The brute force solution to this problem is to (1) DFS traverse the tree starting from the root and (2) +initiate a new DFS traversal at each node. For each of the type (2) traversals, we keep a running sum of the node values +that have been traversed. When the running sum equals the target sum, we increment a global total. To calculate the +total runtime, we observe that that a node at depth d has d ancestors. Because of the recursive nature of the +algorithm, those ancestors will each cause function (2) to be called on a given node. From the definitions of +binary trees, the depth of a tree with N nodes is equal to log(N). Thus the runtime is thus O(N*log(N)) for a balanced +tree. For an unbalanced tree (in the worst case, every node of the tree is on the same side), the depth of a tree +with N nodes is N. Thus, the worst case runtime of this algorithm is O(N^2). Because a running sum must be stored for +each node (along with the data associated with the node itself) space complexity is O(N). + +A more efficient solution is to only traverse the tree once using depth first search and use a hash table to +keep track of running sums. In the hash table, the keys are running sums and the values are the numbers of times +the keys have been encountered. By definition, a path leads to the target sum if the difference between the current +running sum and *any previously encountered running sum* is equal to the target sum. At each node encountered during the +traversal, we add that node's running sum to a hash table; if that running sum is already in the hash table, then +we increment its value. Also at each node, we compute the difference between the node's running sum and the target +sum: if that difference is equal to *any* previously observed running sum, then we've discovered a path that yields +the target sum. Furthermore, if there exist multiple of the same running sum, then we've discovered multiple paths that +yield the target sum. Thus, when the difference is equal to the target sum, we increment a global path total by the +current running sum's hash table value thus computing the number of paths that lead to the target sum. One final bit +of complexity in this solution is that hashed sums from traversing one path will not apply to a totally different +path in the tree. We resolve this issue in the recursive implementation of depth first search: once a given node's +left and right recursive calls are completed, we *decrement* that node's running sum in the hash table. In this way, +we do a constant number of hash table lookups at each node in the tree yielding a O(N) worst case runtime and O(N) +space required due to the max hash table size and the sunning sums stored for each node. + +Time complexity: O(N) +Space complexity: O(N) +*/ + +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + template + int pathsWithSum(const chapter_02::BinaryNode* head) { + return 0; + } +} // chapter_04 diff --git a/tests.cpp b/tests.cpp index 22dc09e..bbf68c9 100644 --- a/tests.cpp +++ b/tests.cpp @@ -755,6 +755,31 @@ TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ REQUIRE(((950 <= occurrenceSum13) && (occurrenceSum13 <= 1050))); } +TEST_CASE("Chapter 04 - Problem 12 - pathsWithSum()", "test"){ + /* + construct binary tree like in textbook example + 10 + 5 -3 + 3 1 __ 11 + 3 -2 __ 2 + */ + // leaf nodes at depth = 3 + chapter_02::BinaryNode n3_leaf(3); + chapter_02::BinaryNode n_minus2(-2); + chapter_02::BinaryNode n2(2); + // nodes at depth = 2 + chapter_02::BinaryNode n3(3, &n3_leaf, &n_minus2); + chapter_02::BinaryNode n1(1, nullptr, &n2); + chapter_02::BinaryNode n11(11); + // nodes at depth = 1 + chapter_02::BinaryNode n5(5, &n3, &n1); + chapter_02::BinaryNode n_minus3(-3, nullptr, &n11); + // root node at depth = 0 + chapter_02::BinaryNode n10(10, &n5, &n_minus3); + // count paths that sum to 8 + REQUIRE(8 == chapter_04::pathsWithSum(&n10)); +} + TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); } From 964bf98c96c3f04650669c0b8ee98ea68ba6fc7a Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 24 Feb 2019 21:18:00 -0800 Subject: [PATCH 037/176] implement 4.12 C++ --- .../problem_04_12_pathsWithSum.h | 33 +++++++++++++++++-- tests.cpp | 2 +- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h index 966d1fa..4dbda3e 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h @@ -38,10 +38,39 @@ Space complexity: O(N) */ #include "../chapter_02_linked_lists/Node.h" +#include namespace chapter_04 { template - int pathsWithSum(const chapter_02::BinaryNode* head) { - return 0; + void pathsWithSumHelper( + const T& targetSum, + const chapter_02::BinaryNode* head, + T runningSum, + T& globalSum, + std::unordered_map& hashTable) { + if (head == nullptr) return; // terminating condition + runningSum += head->getValue(); // update running sum for this node + if (hashTable.find(runningSum) == hashTable.end()) { // if running sum is not found, add it. + hashTable[runningSum] = 1; + } else { + hashTable[runningSum] ++; // else increment + } + T difference = runningSum - targetSum; + if (hashTable.find(difference) != hashTable.end()) { // if difference is found increment global sum + globalSum += hashTable[difference]; + } + pathsWithSumHelper(targetSum, head->getLeft(), runningSum, globalSum, hashTable); // recurse + pathsWithSumHelper(targetSum, head->getRight(), runningSum, globalSum, hashTable); // recurse + hashTable[runningSum] --; // decrement to not affect unrelated paths + } + + template + int pathsWithSum(const T& targetSum, const chapter_02::BinaryNode* head) { + std::unordered_map hashTable; + hashTable[static_cast(0)] = 1; // if runningSum - globalSum == 0, then by definition we have found a valid path to the targetSum + T globalSum = 0; + T runningSum = 0; + pathsWithSumHelper(targetSum, head, runningSum, globalSum, hashTable); + return globalSum; } } // chapter_04 diff --git a/tests.cpp b/tests.cpp index bbf68c9..2bd8621 100644 --- a/tests.cpp +++ b/tests.cpp @@ -777,7 +777,7 @@ TEST_CASE("Chapter 04 - Problem 12 - pathsWithSum()", "test"){ // root node at depth = 0 chapter_02::BinaryNode n10(10, &n5, &n_minus3); // count paths that sum to 8 - REQUIRE(8 == chapter_04::pathsWithSum(&n10)); + REQUIRE(3 == chapter_04::pathsWithSum(8, &n10)); } TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ From 452cf364c3f2a8cdf3dc0d33b804ece2d96504ea Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 28 Feb 2019 23:04:51 -0800 Subject: [PATCH 038/176] implement 3.5 C++ --- README.md | 4 +- .../chapter_03_stacks_and_queues/Stack.h | 10 +++- .../chapter_03_includes.h | 3 +- .../problem_03_05_sortStack.h | 49 +++++++++++++++++++ .../problem_03_05_sort_stack.py | 25 +++++++++- tests.cpp | 20 ++++++-- 6 files changed, 102 insertions(+), 9 deletions(-) create mode 100644 cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h diff --git a/README.md b/README.md index 07493e5..bbd8d3a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ reference and contribute solutions with confidence. 0. [C++ Unit Tests](tests.cpp) 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `2 / 6` complete. +3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `3 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `42 / 151` +Total: `43 / 151` #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) diff --git a/cpp_solutions/chapter_03_stacks_and_queues/Stack.h b/cpp_solutions/chapter_03_stacks_and_queues/Stack.h index d3b6d94..412a8b4 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/Stack.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/Stack.h @@ -9,14 +9,19 @@ namespace chapter_03{ class Stack{ protected: chapter_02::SinglyLinkedNode* _head; + int _stackSize; public: - Stack(){_head = nullptr;} + Stack(){ + _head = nullptr; + _stackSize = 0; + } // check if stack is empty bool isEmpty() {return _head == nullptr;} // add item to top of stack virtual void push(const T& data) { chapter_02::SinglyLinkedNode* node = new chapter_02::SinglyLinkedNode(data, _head); _head = node; + _stackSize ++; } // remove item from top of stack virtual T pop(){ @@ -25,6 +30,7 @@ namespace chapter_03{ T tempValue = temp->getValue(); _head = _head->getNext(); delete temp; + _stackSize --; return tempValue; } else { return static_cast(0); // nothing to return if stack is empty; @@ -39,6 +45,7 @@ namespace chapter_03{ return static_cast(0); // nothing to return if stack is empty; } } + int stackSize() const {return _stackSize;} // destructor ~Stack(){ while (_head != nullptr){ @@ -47,6 +54,7 @@ namespace chapter_03{ delete temp; } } + // compare values in stack top-to-bottom to values in vector front-to-back for easy unit testing bool operator==(const std::vector& vector){ chapter_02::SinglyLinkedNode* temp = _head; diff --git a/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h b/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h index 7e557f1..b2b2e7e 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h @@ -4,4 +4,5 @@ #pragma once #include "problem_03_02_StackMin.h" -#include "problem_03_04_QueueViaStacks.h" \ No newline at end of file +#include "problem_03_04_QueueViaStacks.h" +#include "problem_03_05_sortStack.h" \ No newline at end of file diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h new file mode 100644 index 0000000..1a159ee --- /dev/null +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h @@ -0,0 +1,49 @@ +/* +Chapter 03 - Problem 05 - Sort Stack + +Problem Statement: +Write a program to sort a stack such that the smallest items are on the top. You can use an +additional temporary stack, but you may not copy the elements into any other data structure +(such as an array). The stack supports the following operations: push(), pop(), peek(), and isEmpty(). + +Solution: +We sort a stack with N items by using an additional stack of up to size N and a single +temporary variable of size 1. We start with a full "left" stack and an empty "right" +stack. We first (1) pop every item off of the left stack and push each item onto the right +stack. During step (1), we fill the temporary variable with the smallest item seen so far. +In step (2), we pop every item off of the right stack back onto the left stack. However, when we encounter +the smallest item, we do *not* pop it back onto the left stack and instead just keep track of it with +the temporary variable. Once the right stack is empty, we pop the smallest item into the right stack +thus establishing the "first" item of the new, sorted stack. We then (3) repeat steps (1) and (2) while ignoring +the already sorted items in the right stack. + +Time complexity: O(N) +Space complexity: O(N) +*/ + +namespace chapter_03 { + template + void sortStack(chapter_03::Stack& stack) { + chapter_03::Stack rightStack; + T temp = static_cast(std::numeric_limits::max()); + int stackSize = stack.stackSize(); + for (int i = 0; i < stackSize; i++) { + // transfer from left to right + while (!stack.isEmpty()) { + T currentItemLeft = stack.pop(); + if (currentItemLeft <= temp) temp = currentItemLeft; + rightStack.push(currentItemLeft); + } + // transfer from right to left + for (int j = 0; j < stackSize - i; j ++) { // ignore sorted items + T currentItemRight = rightStack.pop(); + if (currentItemRight != temp) stack.push(currentItemRight); + } + rightStack.push(temp); // place sorted item + temp = static_cast(std::numeric_limits::max()); + } + while(!rightStack.isEmpty()){ + stack.push(rightStack.pop()); // copy sorted items to input stack + } + } +} diff --git a/python_solutions/chapter_03_stacks_queues/problem_03_05_sort_stack.py b/python_solutions/chapter_03_stacks_queues/problem_03_05_sort_stack.py index 497f473..6274577 100644 --- a/python_solutions/chapter_03_stacks_queues/problem_03_05_sort_stack.py +++ b/python_solutions/chapter_03_stacks_queues/problem_03_05_sort_stack.py @@ -1,3 +1,26 @@ +""" +Chapter 03 - Problem 05 - Sort Stack + +Problem Statement: +Write a program to sort a stack such that the smallest items are on the top. You can use an +additional temporary stack, but you may not copy the elements into any other data structure +(such as an array). The stack supports the following operations: push(), pop(), peek(), and isEmpty(). + +Solution: +We sort a stack with N items by using an additional stack of up to size N and a single +temporary variable of size 1. We start with a full "left" stack and an empty "right" +stack. We first (1) pop every item off of the left stack and push each item onto the right +stack. During step (1), we fill the temporary variable with the smallest item seen so far. +In step (2), we pop every item off of the right stack back onto the left stack. However, when we encounter +the smallest item, we do *not* pop it back onto the left stack and instead just keep track of it with +the temporary variable. Once the right stack is empty, we pop the smallest item into the right stack +thus establishing the "first" item of the new, sorted stack. We then (3) repeat steps (1) and (2) while ignoring +the already sorted items in the right stack. + +Time complexity: O(N) +Space complexity: O(N) +""" + from . import Stack as s @@ -6,7 +29,7 @@ def sort_stack(stack): smallest = None stack_size = stack.size for i in range(stack_size): - for j in range(stack_size - i, 0, -1): # + for j in range(stack_size - i, 0, -1): current = stack.pop() if smallest is None: smallest = current diff --git a/tests.cpp b/tests.cpp index 1f3f3c2..6625579 100644 --- a/tests.cpp +++ b/tests.cpp @@ -315,7 +315,7 @@ TEST_CASE("Chapter 02 - Problem 08 - findLoop()", "test") { } TEST_CASE("Chapter 03 - Stack", "test"){ - chapter_03::Stack myStack = chapter_03::Stack(); + chapter_03::Stack myStack; for (int i = 1; i <= 4; i++){ myStack.push(i); } @@ -340,7 +340,7 @@ TEST_CASE("Chapter 03 - Stack", "test"){ } TEST_CASE("Chapter 03 - Problem 02 - StackMin()", "test"){ - chapter_03::StackMin myStack = chapter_03::StackMin(); + chapter_03::StackMin myStack; myStack.push(-8); myStack.push(-5); myStack.push(1); @@ -355,8 +355,8 @@ TEST_CASE("Chapter 03 - Problem 02 - StackMin()", "test"){ REQUIRE(myStack.seeMin() == -9); } -TEST_CASE("Chapter 03 - Problem 04 - QueueViStacks()", "test"){ - chapter_03::QueueViaStacks myQueue = chapter_03::QueueViaStacks(); +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); @@ -364,6 +364,18 @@ TEST_CASE("Chapter 03 - Problem 04 - QueueViStacks()", "test"){ 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 04 - Basic Graph Functionality", "test"){ chapter_02::TetraGraphNode node(1); chapter_02::TetraGraphNode* child0 = new chapter_02::TetraGraphNode(0); From 3b580e416538158627ea5236a39ab61c56c925c5 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 1 Mar 2019 17:06:21 -0800 Subject: [PATCH 039/176] WIP stuck on inheritance problem --- README.md | 6 +- .../chapter_03_stacks_and_queues/Queue.h | 48 +++++++++++ .../chapter_03_stacks_and_queues/Stack.h | 2 +- .../chapter_03_includes.h | 3 +- .../problem_03_06_animalShelter.h | 85 +++++++++++++++++++ .../problem_03_06_animal_shelter.py | 25 +++++- tests.cpp | 14 +++ tests.py | 5 +- 8 files changed, 182 insertions(+), 6 deletions(-) create mode 100644 cpp_solutions/chapter_03_stacks_and_queues/Queue.h create mode 100644 cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h diff --git a/README.md b/README.md index bbd8d3a..07491f8 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -Total: `43 / 151` +C++ Total: `43` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -61,7 +61,9 @@ Total: `43 / 151` 16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. 17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. -Total: `56 / 145` +Python Total: `56` solutions. + +#####Grand Total: `99` unique solutions. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_03_stacks_and_queues/Queue.h b/cpp_solutions/chapter_03_stacks_and_queues/Queue.h new file mode 100644 index 0000000..862787d --- /dev/null +++ b/cpp_solutions/chapter_03_stacks_and_queues/Queue.h @@ -0,0 +1,48 @@ +#pragma once +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_03 { + template + class Queue { + private: + chapter_02::SinglyLinkedNode* _first; + chapter_02::SinglyLinkedNode* _last; + public: + Queue() { + _first = nullptr; // first element is the place where we *add* elements + _last = nullptr; // last element is the place from which we *remove* elements + // first <- C <- B <- A <- last + // nodes are linked "backwards" from last to first + } + + bool isEmpty() const {return _last == nullptr;} + + void push(const T& data) { + chapter_02::SinglyLinkedNode* node = new chapter_02::SinglyLinkedNode(data, nullptr); + if (_first == nullptr || _last == nullptr) { // if queue contains nothing, first and last element are the same + _first = node; + _last = node; + } else { // if queue contains something, connect new node to existing first node. + _first->setNext(node); + _first = node; + } + } + + T pop(){ + if (_last == nullptr) return static_cast(0); + T tempValue = _last->getValue(); + chapter_02::SinglyLinkedNode* tempNode = _last; + _last = _last->getNext(); + delete tempNode; + return tempValue; + } + + ~Queue(){ + while (_last != nullptr){ + chapter_02::SinglyLinkedNode* tempNode = _last; + _last = _last->getNext(); + delete tempNode; + } + } + }; +} diff --git a/cpp_solutions/chapter_03_stacks_and_queues/Stack.h b/cpp_solutions/chapter_03_stacks_and_queues/Stack.h index 412a8b4..5a0426e 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/Stack.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/Stack.h @@ -16,7 +16,7 @@ namespace chapter_03{ _stackSize = 0; } // check if stack is empty - bool isEmpty() {return _head == nullptr;} + bool isEmpty() const {return _head == nullptr;} // add item to top of stack virtual void push(const T& data) { chapter_02::SinglyLinkedNode* node = new chapter_02::SinglyLinkedNode(data, _head); diff --git a/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h b/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h index b2b2e7e..3350e62 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h @@ -5,4 +5,5 @@ #pragma once #include "problem_03_02_StackMin.h" #include "problem_03_04_QueueViaStacks.h" -#include "problem_03_05_sortStack.h" \ No newline at end of file +#include "problem_03_05_sortStack.h" +#include "problem_03_06_animalShelter.h" diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h new file mode 100644 index 0000000..2530062 --- /dev/null +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h @@ -0,0 +1,85 @@ +/* +Chapter 03 - Problem 6 - Animal Shelter + +Problem Statement: +An animal shelter, which holds only dogs and cats, operates on a strictly "first in, +first out" basis. People must adopt either the "oldest"(based on arrival time) of all animals at the +shelter, or they can select whether they would prefer a dog or a cat (and will receive the oldest +animal of that type). They cannot select which specific animal they would like. Create the data structures +to maintain this system and implement operations such as enqueue, dequeueAny, dequeueDog, and dequeueCat. +You may use the built-in LinkedList data structure. + +Solution: +We can maintain 2 queues: one for cats and one for dogs. Popping off of the end of each queue will fulfill the +requirements for dequeueDog() and dequeueCat() because queues are first in first out data structures. To fulfill +the requirements for dequeueAny(), we can also maintain a single integer variable that keeps track of the ID +of each animal. This ID is incremented with each animal that is added. When dequeueAny() is called, we check the +end of the cats queue and the end of the dogs queue and we pop the animal with the lowest ID number. + +Time complexity: O(N) for building queues of N animals. O(1) for dequeueing an animal. +Space complexity: O(N) for storing queues of N animals. +*/ + +#pragma once +#include "../chapter_02_linked_lists/Node.h" +#include "Queue.h" +#include + +namespace chapter_03 { + enum Species {none, dog, cat}; + + class Animal { + private: + std::string _name; + int _ID; + Species _species; + + public: + Animal(const std::string& name, int ID=0) { + _name = name; + _ID = ID; + _species = Species::none; + } + int getID() const {return _ID;} + void setID(int ID) {_ID = ID;} + std::string getName() const {return _name;} + Species getSpecies() const {return _species;} + }; + + class Dog : public Animal { + private: + Species _species; + public: + Dog(const std::string& name, int ID=0) : Animal(name, ID) { + _species = Species::dog; + } + }; + + class Cat : public Animal { + private: + Species _species; + public: + Cat(const std::string& name, int ID=0) : Animal(name, ID){ + _species = Species::cat; + } + }; + + class AnimalShelter { + private: + Queue _dogs; + Queue _cats; + public: + AnimalShelter() { + _dogs = Queue(); + _cats = Queue(); + } + void enqueue(Animal animal) { + if (animal.getSpecies() == Species::cat) { + _cats.push(static_cast(animal)); + } + } + Cat dequeueCat(); + Dog dequeueDog(); + Animal dequeueAny(); + }; +} diff --git a/python_solutions/chapter_03_stacks_queues/problem_03_06_animal_shelter.py b/python_solutions/chapter_03_stacks_queues/problem_03_06_animal_shelter.py index a7fe958..75da8d7 100644 --- a/python_solutions/chapter_03_stacks_queues/problem_03_06_animal_shelter.py +++ b/python_solutions/chapter_03_stacks_queues/problem_03_06_animal_shelter.py @@ -1,3 +1,26 @@ +""" +Chapter 03 - Problem 6 - Animal Shelter + +Problem Statement: +An animal shelter, which holds only dogs and cats, operates on a strictly "first in, +first out" basis. People must adopt either the "oldest"(based on arrival time) of all animals at the +shelter, or they can select whether they would prefer a dog or a cat (and will receive the oldest +animal of that type). They cannot select which specific animal they would like. Create the data structures +to maintain this system and implement operations such as enqueue, dequeueAny, dequeueDog, and dequeueCat. +You may use the built-in LinkedList data structure. + +Solution: +We can maintain 2 queues: one for cats and one for dogs. Popping off of the end of each queue will fulfill the +requirements for dequeueDog() and dequeueCat() because queues are first in first out data structures. To fulfill +the requirements for dequeueAny(), we can also maintain a single integer variable that keeps track of the ID +of each animal. This ID is incremented with each animal that is added. When dequeueAny() is called, we check the +end of the cats queue and the end of the dogs queue and we pop the animal with the lowest ID number. + +Time complexity: O(N) for building queues of N animals. O(1) for dequeueing an animal. +Space complexity: O(N) for storing queues of N animals. +""" + + class LinkedList: def __init__(self, head=None): # initialize with a node self.head = head @@ -63,4 +86,4 @@ def dequeue_any(self): elif self.cats.peek_head() is not None: return self.cats.remove_head() else: - return None \ No newline at end of file + return None diff --git a/tests.cpp b/tests.cpp index 6625579..95caa9d 100644 --- a/tests.cpp +++ b/tests.cpp @@ -376,6 +376,20 @@ TEST_CASE("Chapter 03 - Problem 05 - sortStack()", "test") { } } +TEST_CASE("Chapter 03 - Problem 06 - AnimalShelter", "test") { + chapter_03::AnimalShelter shelter; + shelter.enqueue(chapter_03::Cat("a")); + shelter.enqueue(chapter_03::Dog("b")); + shelter.enqueue(chapter_03::Dog("c")); + shelter.enqueue(chapter_03::Cat("d")); + shelter.enqueue(chapter_03::Dog("e")); + shelter.enqueue(chapter_03::Cat("f")); + REQUIRE("a" == shelter.dequeueAny().getName()); + REQUIRE("b" == shelter.dequeueAny().getName()); + REQUIRE("c" == shelter.dequeueDog().getName()); + REQUIRE("d" == shelter.dequeueCat().getName()); +} + TEST_CASE("Chapter 04 - Basic Graph Functionality", "test"){ chapter_02::TetraGraphNode node(1); chapter_02::TetraGraphNode* child0 = new chapter_02::TetraGraphNode(0); diff --git a/tests.py b/tests.py index 23a32c6..320f9d2 100644 --- a/tests.py +++ b/tests.py @@ -459,15 +459,18 @@ def test_problem_3_5(self): def test_problem_3_6(self): shelter = p_3_6.AnimalShelter() + self.assertEqual(None, shelter.dequeue_cat()) shelter.enqueue("cat", "a") shelter.enqueue("dog", "b") shelter.enqueue("dog", "c") shelter.enqueue("cat", "d") + shelter.enqueue("dog", "e") + shelter.enqueue("cat", "f") self.assertEqual("a", shelter.dequeue_any().name) self.assertEqual("b", shelter.dequeue_any().name) self.assertEqual("c", shelter.dequeue_dog().name) self.assertEqual("d", shelter.dequeue_cat().name) - self.assertEqual(None, shelter.dequeue_cat()) + def test_tree_binary_tree_traversals(self): """ From da9001cc5c1f8a1d2d9120c3e58b947e43ca8233 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 2 Mar 2019 15:05:02 -0800 Subject: [PATCH 040/176] implement 3.6 C++ --- README.md | 6 +- .../chapter_03_stacks_and_queues/Queue.h | 5 ++ .../problem_03_06_animalShelter.h | 67 ++++++++++++++----- .../problem_03_03_stack_of_plates.py | 2 +- tests.cpp | 29 +++++--- tests.py | 4 +- 6 files changed, 83 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 07491f8..b49368e 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ reference and contribute solutions with confidence. 0. [C++ Unit Tests](tests.cpp) 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `3 / 6` complete. +3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `43` solutions. +C++ Total: `44` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `43` solutions. Python Total: `56` solutions. -#####Grand Total: `99` unique solutions. +#####Grand Total: `100` unique solutions. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_03_stacks_and_queues/Queue.h b/cpp_solutions/chapter_03_stacks_and_queues/Queue.h index 862787d..52bd154 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/Queue.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/Queue.h @@ -37,6 +37,11 @@ namespace chapter_03 { return tempValue; } + T peek() { + if (_last == nullptr) return static_cast(0); + return _last->getValue(); + } + ~Queue(){ while (_last != nullptr){ chapter_02::SinglyLinkedNode* tempNode = _last; diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h index 2530062..74f573d 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h @@ -28,8 +28,10 @@ Space complexity: O(N) for storing queues of N animals. namespace chapter_03 { enum Species {none, dog, cat}; + // superclass for Animal that allows animals of any kind to be passed to the same function ot + // added to the same data structure class Animal { - private: + protected: std::string _name; int _ID; Species _species; @@ -46,40 +48,75 @@ namespace chapter_03 { Species getSpecies() const {return _species;} }; + // dog subsclass class Dog : public Animal { - private: - Species _species; public: Dog(const std::string& name, int ID=0) : Animal(name, ID) { _species = Species::dog; } }; + // cat subclass class Cat : public Animal { - private: - Species _species; public: Cat(const std::string& name, int ID=0) : Animal(name, ID){ _species = Species::cat; } }; + // animal shelter that is a wrapper around two queues containing dogs and cats class AnimalShelter { private: - Queue _dogs; - Queue _cats; + Queue _dogs; + Queue _cats; + int _timestamp; public: AnimalShelter() { - _dogs = Queue(); - _cats = Queue(); + _dogs = Queue(); + _cats = Queue(); + _timestamp = 0; + } + void enqueue(Animal* animal) { + if (animal == nullptr) return; + animal->setID(_timestamp); + _timestamp ++; + if (animal->getSpecies() == Species::cat) { + _cats.push(static_cast(animal)); + } else if (animal->getSpecies() == Species::dog) { + _dogs.push(static_cast(animal)); + } + } + Cat* dequeueCat() { + if (_cats.isEmpty()) { + return nullptr; + } else { + return _cats.pop(); + } } - void enqueue(Animal animal) { - if (animal.getSpecies() == Species::cat) { - _cats.push(static_cast(animal)); + Dog* dequeueDog() { + if (_dogs.isEmpty()) { + return nullptr; + } else { + return _dogs.pop(); + } + } + Animal* dequeueAny() { + // if either of the queues is empty, we need to handle + if (_dogs.isEmpty() && _cats.isEmpty()) { + return nullptr; + } else if (_dogs.isEmpty()) { + return dequeueCat(); + } else if (_cats.isEmpty()) { + return dequeueDog(); + } + // return the animal with lowest ID + int dogID = _dogs.peek()->getID(); + int catID = _cats.peek()->getID(); + if (dogID <= catID) { + return dequeueDog(); + } else { + return dequeueCat(); } } - Cat dequeueCat(); - Dog dequeueDog(); - Animal dequeueAny(); }; } diff --git a/python_solutions/chapter_03_stacks_queues/problem_03_03_stack_of_plates.py b/python_solutions/chapter_03_stacks_queues/problem_03_03_stack_of_plates.py index 4de440c..8cffb5b 100644 --- a/python_solutions/chapter_03_stacks_queues/problem_03_03_stack_of_plates.py +++ b/python_solutions/chapter_03_stacks_queues/problem_03_03_stack_of_plates.py @@ -28,4 +28,4 @@ def pop_at(self, index): self.stacks.pop(index) self.i -= 1 index -= 1 - return self.stacks[index].pop() \ No newline at end of file + return self.stacks[index].pop() diff --git a/tests.cpp b/tests.cpp index 95caa9d..62cc8da 100644 --- a/tests.cpp +++ b/tests.cpp @@ -378,16 +378,25 @@ TEST_CASE("Chapter 03 - Problem 05 - sortStack()", "test") { TEST_CASE("Chapter 03 - Problem 06 - AnimalShelter", "test") { chapter_03::AnimalShelter shelter; - shelter.enqueue(chapter_03::Cat("a")); - shelter.enqueue(chapter_03::Dog("b")); - shelter.enqueue(chapter_03::Dog("c")); - shelter.enqueue(chapter_03::Cat("d")); - shelter.enqueue(chapter_03::Dog("e")); - shelter.enqueue(chapter_03::Cat("f")); - REQUIRE("a" == shelter.dequeueAny().getName()); - REQUIRE("b" == shelter.dequeueAny().getName()); - REQUIRE("c" == shelter.dequeueDog().getName()); - REQUIRE("d" == shelter.dequeueCat().getName()); + 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"){ diff --git a/tests.py b/tests.py index 320f9d2..273312d 100644 --- a/tests.py +++ b/tests.py @@ -470,7 +470,9 @@ def test_problem_3_6(self): self.assertEqual("b", shelter.dequeue_any().name) self.assertEqual("c", shelter.dequeue_dog().name) self.assertEqual("d", shelter.dequeue_cat().name) - + self.assertEqual("e", shelter.dequeue_any().name) + self.assertEqual("f", shelter.dequeue_any().name) + self.assertEqual(None, shelter.dequeue_any()) def test_tree_binary_tree_traversals(self): """ From 041dcb0f4a40ebb024ea75d5a56147c0c6391f78 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 2 Mar 2019 15:27:05 -0800 Subject: [PATCH 041/176] separate implementation and declaration --- CMakeLists.txt | 1 + .../chapter_03_stacks_and_queues/Queue.h | 2 +- .../problem_03_06_animalShelter.cpp | 70 +++++++++++++++++++ .../problem_03_06_animalShelter.h | 68 +++--------------- 4 files changed, 81 insertions(+), 60 deletions(-) create mode 100644 cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f1d808..4dd60e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(SOURCE_FILES cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp # chapter 2 .cpp files not included because they are template functions implemented in .h files # chapter 3 .cpp files not included because they are template functions implemented in .h files + cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp # chapter 4 .cpp files not included because they are template functions implemented in .h files cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp diff --git a/cpp_solutions/chapter_03_stacks_and_queues/Queue.h b/cpp_solutions/chapter_03_stacks_and_queues/Queue.h index 52bd154..dc62916 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/Queue.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/Queue.h @@ -37,7 +37,7 @@ namespace chapter_03 { return tempValue; } - T peek() { + T peek() const { if (_last == nullptr) return static_cast(0); return _last->getValue(); } diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp new file mode 100644 index 0000000..4ceb4db --- /dev/null +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp @@ -0,0 +1,70 @@ +#include "problem_03_06_animalShelter.h" + +namespace chapter_03 { + Animal::Animal(const std::string& name, int ID) { + _name = name; + _ID = ID; + _species = Species::none; + } + + Dog::Dog(const std::string& name, int ID) : Animal(name, ID) { + _species = Species::dog; + } + + Cat::Cat(const std::string& name, int ID) : Animal(name, ID) { + _species = Species::cat; + } + + AnimalShelter::AnimalShelter() { + _dogs = Queue(); + _cats = Queue(); + _timestamp = 0; + } + + void AnimalShelter::enqueue(Animal* animal) { + if (animal == nullptr) return; + animal->setID(_timestamp); + _timestamp ++; + if (animal->getSpecies() == Species::cat) { + _cats.push(static_cast(animal)); + } else if (animal->getSpecies() == Species::dog) { + _dogs.push(static_cast(animal)); + } + } + + Cat* AnimalShelter::dequeueCat() { + if (_cats.isEmpty()) { + return nullptr; + } else { + return _cats.pop(); + } + } + + Dog* AnimalShelter::dequeueDog() { + if (_dogs.isEmpty()) { + return nullptr; + } else { + return _dogs.pop(); + } + } + + Animal* AnimalShelter::dequeueAny() { + // if either of the queues is empty, we need to handle + if (_dogs.isEmpty() && _cats.isEmpty()) { + return nullptr; + } else if (_dogs.isEmpty()) { + return dequeueCat(); + } else if (_cats.isEmpty()) { + return dequeueDog(); + } + // return the animal with lowest ID + int dogID = _dogs.peek()->getID(); + int catID = _cats.peek()->getID(); + if (dogID <= catID) { + return dequeueDog(); + } else { + return dequeueCat(); + } + } +} + diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h index 74f573d..25f86c7 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.h @@ -37,31 +37,23 @@ namespace chapter_03 { Species _species; public: - Animal(const std::string& name, int ID=0) { - _name = name; - _ID = ID; - _species = Species::none; - } + Animal (const std::string& name, int ID=0); int getID() const {return _ID;} void setID(int ID) {_ID = ID;} std::string getName() const {return _name;} Species getSpecies() const {return _species;} }; - // dog subsclass + // dog subclass class Dog : public Animal { public: - Dog(const std::string& name, int ID=0) : Animal(name, ID) { - _species = Species::dog; - } + Dog(const std::string& name, int ID=0); }; // cat subclass class Cat : public Animal { public: - Cat(const std::string& name, int ID=0) : Animal(name, ID){ - _species = Species::cat; - } + Cat(const std::string& name, int ID=0); }; // animal shelter that is a wrapper around two queues containing dogs and cats @@ -71,52 +63,10 @@ namespace chapter_03 { Queue _cats; int _timestamp; public: - AnimalShelter() { - _dogs = Queue(); - _cats = Queue(); - _timestamp = 0; - } - void enqueue(Animal* animal) { - if (animal == nullptr) return; - animal->setID(_timestamp); - _timestamp ++; - if (animal->getSpecies() == Species::cat) { - _cats.push(static_cast(animal)); - } else if (animal->getSpecies() == Species::dog) { - _dogs.push(static_cast(animal)); - } - } - Cat* dequeueCat() { - if (_cats.isEmpty()) { - return nullptr; - } else { - return _cats.pop(); - } - } - Dog* dequeueDog() { - if (_dogs.isEmpty()) { - return nullptr; - } else { - return _dogs.pop(); - } - } - Animal* dequeueAny() { - // if either of the queues is empty, we need to handle - if (_dogs.isEmpty() && _cats.isEmpty()) { - return nullptr; - } else if (_dogs.isEmpty()) { - return dequeueCat(); - } else if (_cats.isEmpty()) { - return dequeueDog(); - } - // return the animal with lowest ID - int dogID = _dogs.peek()->getID(); - int catID = _cats.peek()->getID(); - if (dogID <= catID) { - return dequeueDog(); - } else { - return dequeueCat(); - } - } + AnimalShelter(); + void enqueue(Animal* animal); + Cat* dequeueCat(); + Dog* dequeueDog(); + Animal* dequeueAny(); }; } From 27524499ac1b51925aab8c3310d41e8dd584091f Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 2 Mar 2019 15:30:46 -0800 Subject: [PATCH 042/176] fix markdown error in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b49368e..07b5d2a 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ C++ Total: `44` solutions. Python Total: `56` solutions. -#####Grand Total: `100` unique solutions. +##### Grand Total: `100` unique solutions. ### Building: #### Mac: From b06aaeaf7e625fe6a0c99539a41b9e59983dacf9 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 5 Apr 2019 17:51:02 -0700 Subject: [PATCH 043/176] write essay for 8.7 python. refactor 8.7 python --- .../problem_08_07_permutations_no_dups.py | 74 +++++++++++++++---- tests.py | 3 +- 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py b/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py index 3844f14..1a15cfa 100644 --- a/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py +++ b/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py @@ -1,18 +1,60 @@ +""" +Chapter 08 - Problem 07 - Permutations Without Duplicates + +Problem Statement: +Write a method to compute all permutations of a string of unique characters. + +Solution: +First, we show the definition of permutations by example: +'a' -> 'a' # 1! = 1 +'al' -> 'al' , 'la' # 2! = 2 +'ale' -> 'ale', 'ael', 'lae', 'lea', 'eal', 'ela' # 3! = 6 + +Next, we show a recursive pattern for permutation generation: +permutations('a') = 'a' # terminating condition +permutations('al') = 'al', 'la' # terminating condition +permutations('ale') -> return combine('a', permutations('le')) + = return combine('a', ['le', 'el']) + = return ['ale', 'lae', 'lea', 'ael', 'eal', 'ela'] + +Our recursive solution implementation has 2 components: + +I. A function permutations(string) that takes as input a string. This function terminates when the length of the string is +2 or less. This function recurses when the length of the string is 3 or more. +II. A function combine(char, [string1, string2 ... stringN]) that takes as input a single character and a list of strings. +This function returns a list of strings that are formed by inserting the single character at every possible position in +every member of the list of strings. + +When called on a string of length greater than 2, the function permutations(string) returns combine(string[0], +permutations(string[1:end])). Thus, a string of length N will cause N-2 calls of the permutations() function. At each +call of permutations(string_length_X), the combine() function will produce a list of strings that is X! long. To create +each member of the list of strings produced by combine(), O(X) work is required where X is O(N). Thus, Gayle loosely +approximates an upper bound on the total number of operations as O(N! * N^2). A more accurate expression of the runtime +would be the sum ... + +O(N!*N + (N-1)!*(N-1) + (N-2)!*(N-2) ...) +The space complexity of the problem is O(N! * N) because N! of strings of length N must be stored. + +Time complexity: O(N!*N^2) +Space complexity: O(N!*N) +""" + + def permutations_no_dups(string): if len(string) <= 0: - return None - if len(string) == 1: - return [string[0]] - subproblem_permutations = permutations_no_dups(string[1:]) - new_permutations = [] - for subproblem_permutation in subproblem_permutations: - new_permutations.extend(create_permutations(subproblem_permutation, string[0])) - return new_permutations - - -def create_permutations(string, inserted_character): - permutations = [] - for index in range(0, len(string)): - permutations.append(string[0:index] + inserted_character + string[index:]) - permutations.append(string + inserted_character) - return permutations + return [""] + elif len(string) == 1: + return [string] + elif len(string) == 2: + return [string, string[::-1]] + else: + return combine(string[0], permutations_no_dups(string[1:])) + + +def combine(char, string_list): + output_string_list = [] + for string in string_list: + for i in range(len(string) + 1): + output_string_list += [string[0:i] + char + string[i:]] + print(output_string_list) + return output_string_list diff --git a/tests.py b/tests.py index 273312d..2aff5cc 100644 --- a/tests.py +++ b/tests.py @@ -1026,7 +1026,6 @@ def test_problem_8_13(self): def test_problem_8_14(self): pass - def test_problem_10_01(self): A = [5, 5, 10, 10, 15, 0, 0, 0, 0, 0] B = [3, 6, 9, 12, 15] @@ -1043,7 +1042,6 @@ def test_problem_10_01(self): p_10_1.sorted_merge(D, lastD, E, lastE) self.assertEqual(D, C) - def test_problem_16_03(self): segment1 = p_16_03.LineSegment(p_16_03.Point2(5, 5), p_16_03.Point2(0, 0)) segment2 = p_16_03.LineSegment(p_16_03.Point2(0, 3), p_16_03.Point2(3, 0)) @@ -1089,5 +1087,6 @@ def test_problem_17_21(self): def tearDown(self): pass + if __name__ == '__main__': unittest.main() From 57c3577f986ec8d274a19d1b2197abe0c6e9ef61 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 6 Apr 2019 12:28:31 -0700 Subject: [PATCH 044/176] add file for 8.7 c++ --- .../problem_08_07_permutations_no_dups.h | 1 + 1 file changed, 1 insertion(+) create mode 100644 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h @@ -0,0 +1 @@ +#pragma once From 99db4f17e569b291f931f50acba7cdef3901b0f1 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 7 Apr 2019 21:23:14 -0800 Subject: [PATCH 045/176] write test and skeleton for 8.7 C++ --- CMakeLists.txt | 1 + .../chapter_08_includes.h | 1 + .../problem_08_07_permutationsNoDups.cpp | 48 +++++++++++++++++++ .../problem_08_07_permutationsNoDups.h | 12 +++++ .../problem_08_07_permutations_no_dups.h | 1 - .../problem_08_07_permutations_no_dups.py | 1 - tests.cpp | 24 ++++++++++ 7 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp create mode 100644 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h delete mode 100644 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dd60e9..a3dbce0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(SOURCE_FILES cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h index c008d74..5995477 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h @@ -8,4 +8,5 @@ #include "problem_08_03_magicIndex.h" #include "problem_08_04_powerSet.h" #include "problem_08_05_recursiveMultiply.h" +#include "problem_08_07_permutationsNoDups.h" #include "problem_08_10_paintFill.h" diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp new file mode 100644 index 0000000..7defa54 --- /dev/null +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp @@ -0,0 +1,48 @@ +/* +Chapter 08 - Problem 07 - Permutations Without Duplicates + +Problem Statement: +Write a method to compute all permutations of a string of unique characters. + +Solution: +First, we show the definition of permutations by example: +'a' -> 'a' # 1! = 1 +'al' -> 'al' , 'la' # 2! = 2 +'ale' -> 'ale', 'ael', 'lae', 'lea', 'eal', 'ela' # 3! = 6 + +Next, we show a recursive pattern for permutation generation: +permutations('a') = 'a' # terminating condition +permutations('al') = 'al', 'la' # terminating condition +permutations('ale') -> return combine('a', permutations('le')) + = return combine('a', ['le', 'el']) + = return ['ale', 'lae', 'lea', 'ael', 'eal', 'ela'] + +Our recursive solution implementation has 2 components: + +I. A function permutations(string) that takes as input a string. This function terminates when the length of the string is +2 or less. This function recurses when the length of the string is 3 or more. +II. A function combine(char, [string1, string2 ... stringN]) that takes as input a single character and a list of strings. +This function returns a list of strings that are formed by inserting the single character at every possible position in +every member of the list of strings. + +When called on a string of length greater than 2, the function permutations(string) returns combine(string[0], +permutations(string[1:end])). Thus, a string of length N will cause N-2 calls of the permutations() function. At each +call of permutations(string_length_X), the combine() function will produce a list of strings that is X! long. To create +each member of the list of strings produced by combine(), O(X) work is required where X is O(N). Thus, Gayle loosely +approximates an upper bound on the total number of operations as O(N! * N^2). A more accurate expression of the runtime +would be the sum ... + +O(N!*N + (N-1)!*(N-1) + (N-2)!*(N-2) ...) +The space complexity of the problem is O(N! * N) because N! of strings of length N must be stored. + +Time complexity: O(N!*N^2) +Space complexity: O(N!*N) +*/ + +#include "problem_08_07_permutationsNoDups.h" + +namespace chapter_08 { + void permutationsNoDups(const std::string& string, std::set& test) { + + } +} diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h new file mode 100644 index 0000000..21859ac --- /dev/null +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h @@ -0,0 +1,12 @@ +/* +Chapter 08 - Problem 07 - Permutations Without Duplicates + +See problem_08_07_permutationsNoDups.cpp for problem description. +*/ +#pragma once +#include +#include + +namespace chapter_08 { + void permutationsNoDups(const std::string& string, std::set& test); +} diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h deleted file mode 100644 index 6f70f09..0000000 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py b/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py index 1a15cfa..c8881f2 100644 --- a/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py +++ b/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutations_no_dups.py @@ -56,5 +56,4 @@ def combine(char, string_list): for string in string_list: for i in range(len(string) + 1): output_string_list += [string[0:i] + char + string[i:]] - print(output_string_list) return output_string_list diff --git a/tests.cpp b/tests.cpp index 62cc8da..9bd03db 100644 --- a/tests.cpp +++ b/tests.cpp @@ -915,6 +915,30 @@ TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ REQUIRE(chapter_08::recursiveMultiply(12, 12) == 144); } +TEST_CASE("Chapter 08 - Problem 07 - permutationsWithoutDups()", "test") { + std::set actual1 = {}; + std::set actual2 = {}; + std::set actual3 = {}; + std::set actual4 = {}; + std::set expected1 = {"a"}; + std::set expected2 = {"al", "la"}; + std::set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; + std::set expected4 = {"xela", "exla", "elxa", "elax", + "xlea", "lxea", "lexa", "leax", + "xlae", "lxae", "laxe", "laex", + "xeal", "exal", "eaxl", "ealx", + "xael", "axel", "aexl", "aelx", + "xale", "axle", "alxe", "alex"}; + chapter_08::permutationsNoDups("a", actual1); + chapter_08::permutationsNoDups("al", actual2); + chapter_08::permutationsNoDups("ale", actual3); + chapter_08::permutationsNoDups("alex", actual4); + REQUIRE(actual1 == expected1); + REQUIRE(actual2 == expected2); + REQUIRE(actual3 == expected3); + REQUIRE(actual4 == expected4); +} + TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ Eigen::MatrixXi image(6, 6); image << 0, 1, 1, 0, 0, 3, From ce762fd69f2df02fb32846b46a97eff01552056c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 8 Apr 2019 07:31:08 -0800 Subject: [PATCH 046/176] WIP implementing 8.7 C++ --- .../problem_08_07_permutationsNoDups.cpp | 15 +++++++++++++-- .../problem_08_07_permutationsNoDups.h | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp index 7defa54..e534443 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp @@ -42,7 +42,18 @@ Space complexity: O(N!*N) #include "problem_08_07_permutationsNoDups.h" namespace chapter_08 { - void permutationsNoDups(const std::string& string, std::set& test) { - + void permutationsNoDups(const std::string& string, std::set& permutations) { + if (string.length() <= 0) { + return; + } else if (string.length() == 1) { + permutations.insert(string); + } else if (string.length() == 2) { + permutations.insert(string); + permutations.insert(std::reverse(string)); + } else { + + } } + + } diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h index 21859ac..4f07e47 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h @@ -8,5 +8,5 @@ See problem_08_07_permutationsNoDups.cpp for problem description. #include namespace chapter_08 { - void permutationsNoDups(const std::string& string, std::set& test); + void permutationsNoDups(const std::string& string, std::set& permutations); } From 2606ff18bf8d7317e34fc111ea6a71d96e950b81 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 8 Apr 2019 12:55:17 -0700 Subject: [PATCH 047/176] finish implementing 8.7 C++. correct completion count mistake in readme --- README.md | 11 +++--- .../problem_08_07_permutationsNoDups.cpp | 37 ++++++++++++++----- .../problem_08_07_permutationsNoDups.h | 6 ++- tests.cpp | 18 ++++----- 4 files changed, 45 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 07b5d2a..2cd1c76 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ reference and contribute solutions with confidence. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `5 / 14` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `7 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. 11. Chapter 11 - Testing: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `44` solutions. +C++ Total: `46` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `44` solutions. Python Total: `56` solutions. -##### Grand Total: `100` unique solutions. +##### Grand Total: `102` unique solutions. ### Building: #### Mac: @@ -108,9 +108,8 @@ This will show exactly which lines are not covered by tests in each Python sourc ### Contributing The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. -I definitely need help! PRs are of course very welcome. The work has become quite time consuming because each solution is *living* -code that actually gets executed. Thus, each solution needs its own small dataset and infrastructure in order to be tested. -Just writing the test for a problem is often harder than solving the problem itself. Here are some ways you can help: +I definitely need help, so PRs are welcome. There is much to do because each solution needs its own +small dataset and infrastructure in order to be tested. Here are some ways you can help: 1. Fixing bugs :bug:. 2. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp index e534443..572d260 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp @@ -40,20 +40,37 @@ Space complexity: O(N!*N) */ #include "problem_08_07_permutationsNoDups.h" +#include namespace chapter_08 { - void permutationsNoDups(const std::string& string, std::set& permutations) { - if (string.length() <= 0) { - return; - } else if (string.length() == 1) { + void combine(const std::string& toInsert, const std::unordered_set& oldPermutations, std::unordered_set& newPermutations) { + for (const std::string& oldPermutation : oldPermutations) { + for (int i = 0; i < oldPermutation.length() + 1; i++) { + std::string newPermutation = + oldPermutation.substr(0, static_cast(i)) + + toInsert + + oldPermutation.substr(static_cast(i), std::string::npos); + newPermutations.insert(newPermutation); + } + } + } + + void permutationsNoDups(const std::string& string, std::unordered_set& permutations) { + if (string.length() == 1) { permutations.insert(string); } else if (string.length() == 2) { permutations.insert(string); - permutations.insert(std::reverse(string)); - } else { - - } + std::string copy(string); + std::reverse(copy.begin(), copy.end()); + permutations.insert(copy); + } else if (string.length() > 2) { + std::unordered_set oldPermutations = {}; + std::unordered_set newPermutations = {}; + permutationsNoDups(string.substr(1, std::string::npos), oldPermutations); + combine(string.substr(0, 1), oldPermutations, newPermutations); + for (const std::string& permutation : newPermutations ) { + permutations.insert(permutation); + } + } // if string.length() <= 0 do nothing } - - } diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h index 4f07e47..b38c07b 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.h @@ -4,9 +4,11 @@ Chapter 08 - Problem 07 - Permutations Without Duplicates See problem_08_07_permutationsNoDups.cpp for problem description. */ #pragma once -#include +#include #include +#include +#include namespace chapter_08 { - void permutationsNoDups(const std::string& string, std::set& permutations); + void permutationsNoDups(const std::string& string, std::unordered_set& permutations); } diff --git a/tests.cpp b/tests.cpp index 9bd03db..bc7b7ac 100644 --- a/tests.cpp +++ b/tests.cpp @@ -915,15 +915,15 @@ TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ REQUIRE(chapter_08::recursiveMultiply(12, 12) == 144); } -TEST_CASE("Chapter 08 - Problem 07 - permutationsWithoutDups()", "test") { - std::set actual1 = {}; - std::set actual2 = {}; - std::set actual3 = {}; - std::set actual4 = {}; - std::set expected1 = {"a"}; - std::set expected2 = {"al", "la"}; - std::set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; - std::set expected4 = {"xela", "exla", "elxa", "elax", +TEST_CASE("Chapter 08 - Problem 07 - permutationsNoDups()", "test") { + std::unordered_set actual1 = {}; + std::unordered_set actual2 = {}; + std::unordered_set actual3 = {}; + std::unordered_set actual4 = {}; + std::unordered_set expected1 = {"a"}; + std::unordered_set expected2 = {"al", "la"}; + std::unordered_set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; + std::unordered_set expected4 = {"xela", "exla", "elxa", "elax", "xlea", "lxea", "lexa", "leax", "xlae", "lxae", "laxe", "laex", "xeal", "exal", "eaxl", "ealx", From 7fd478f34e9abfe108c578e0097478894485c942 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 9 Apr 2019 21:05:08 -0700 Subject: [PATCH 048/176] implement 8.8 C++ --- CMakeLists.txt | 1 + README.md | 6 +- .../chapter_08_includes.h | 1 + .../problem_08_08_permutationsWithDups.cpp | 65 +++++++++++++++++++ .../problem_08_08_permutationsWithDups.h | 12 ++++ tests.cpp | 20 ++++++ 6 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp create mode 100644 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a3dbce0..2afea9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ set(SOURCE_FILES cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp diff --git a/README.md b/README.md index 2cd1c76..8328c90 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ reference and contribute solutions with confidence. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `7 / 14` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. 11. Chapter 11 - Testing: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `46` solutions. +C++ Total: `47` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `46` solutions. Python Total: `56` solutions. -##### Grand Total: `102` unique solutions. +##### Grand Total: `103` unique solutions. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h index 5995477..6c0d75d 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h @@ -9,4 +9,5 @@ #include "problem_08_04_powerSet.h" #include "problem_08_05_recursiveMultiply.h" #include "problem_08_07_permutationsNoDups.h" +#include "problem_08_08_permutationsWithDups.h" #include "problem_08_10_paintFill.h" diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp new file mode 100644 index 0000000..71fd135 --- /dev/null +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp @@ -0,0 +1,65 @@ +/* +Chapter 08 - Problem 08 - Permutations With Duplicates + +Problem Statement: +Write a method to compute all permutations of a string whose characters are not necessarily unique. +The list of permutations should not have duplicates. + + +Solution: +See the solution for 8.7 first. +Instead of recursively passing the problem state represented as a string, represent the problem state as a +hash table that maps string characters to their counts in the string. When creating new recursive calls, +create one recursive call for each unique character in the hash table, then decrement that character's count in the table +before passing it on. In this way, each recursive call is spawned with a unique character thus creating only unique permutations +The space and time complexities do not change because in the worst case the recursion tree is still O(N) nodes deep with +O(N!) leaf nodes and O(N) operations required at each node. One such operation is the creation of different copies of the hash +table to be passed down different recursion paths in the tree, each with O(N) entries. Another such operation is the +creation of new strings representing the permutations each with O(N) characters. The additional storage required by the +hash table is O(N) so it does not affect the existing big O analysis of the worst case storage requirement. + +Time complexity: O(N!*N^2) +Space complexity: O(N!*N) +*/ + +#include "problem_08_08_permutationsWithDups.h" +#include +#include + +namespace chapter_08 { + void permutationsWithDupsHelper(const std::string& prefix, std::unordered_set& permutations, const std::unordered_map& hashTable) { + bool found = false; + for (auto pair : hashTable) { + if (pair.second > 0) { + std::unordered_map hashTableCopy = hashTable; // each recursive call is passed a different hash table copy + hashTableCopy[pair.first] --; + std::string prefixCopy = prefix; // each recursive call is passed a different prefix copy + prefixCopy += pair.first; + found = true; + permutationsWithDupsHelper(prefixCopy, permutations, hashTableCopy); + } + } + if (!found) { // when the hash table has been depleted, add prefix to the permutations set + permutations.insert(prefix); + } + } + + void permutationsWithDups(const std::string& string, std::unordered_set& permutations) { + if (string.length() == 1) { + permutations.insert(string); + } else if (string.length() >= 2) { + // map the characters we've seen so far to their counts in a hash table + std::unordered_map hashTable; + for (const char& singleChar : string) { + if (hashTable.count(singleChar)) { + hashTable[singleChar] ++; + } else { + hashTable[singleChar] = 1; + } + } + // pass hash table representation to recursive function that computes permutations + permutationsWithDupsHelper("", permutations, hashTable); + } + // if string.length() <= 0 do nothing + } +} \ No newline at end of file diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.h new file mode 100644 index 0000000..882e345 --- /dev/null +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.h @@ -0,0 +1,12 @@ +/* +Chapter 08 - Problem 07 - Permutations Without Duplicates + +See problem_08_07_permutationsNoDups.cpp for problem description. +*/ +#pragma once +#include +#include + +namespace chapter_08 { + void permutationsWithDups(const std::string& string, std::unordered_set& permutations); +} \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index bc7b7ac..fd5c7c9 100644 --- a/tests.cpp +++ b/tests.cpp @@ -939,6 +939,26 @@ TEST_CASE("Chapter 08 - Problem 07 - permutationsNoDups()", "test") { REQUIRE(actual4 == expected4); } +TEST_CASE("Chapter 08 - Problem 08 - permutationsWithDups()", "test") { + std::unordered_set actual1 = {}; + std::unordered_set actual2 = {}; + std::unordered_set actual3 = {}; + std::unordered_set expected1 = {"ala", "laa", "aal"}; + std::unordered_set expected2 = {"aala", "alaa", "alaa", "laaa", "aala", "aaal"}; + std::unordered_set expected3 = {"xela", "exla", "elxa", "elax", + "xlea", "lxea", "lexa", "leax", + "xlae", "lxae", "laxe", "laex", + "xeal", "exal", "eaxl", "ealx", + "xael", "axel", "aexl", "aelx", + "xale", "axle", "alxe", "alex"}; + chapter_08::permutationsWithDups("ala", actual1); + //chapter_08::permutationsWithDups("alaa", actual2); + //chapter_08::permutationsWithDups("alex", actual3); + REQUIRE(actual1 == expected1); + //REQUIRE(actual2 == expected2); + //REQUIRE(actual3 == expected3); +} + TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ Eigen::MatrixXi image(6, 6); image << 0, 1, 1, 0, 0, 3, From a3b7b86c1d84c95397789e862581d0974186c704 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 16 May 2019 06:30:42 -0800 Subject: [PATCH 049/176] interface for 5.3 C++ --- .../chapter_05_flipBitToWin.cpp | 24 +++++++++++++++++++ .../chapter_05_includes.h | 1 + .../problem_05_03_flipBitToWin.h | 8 +++++++ 3 files changed, 33 insertions(+) create mode 100644 cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp create mode 100644 cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h diff --git a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp new file mode 100644 index 0000000..42d2995 --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp @@ -0,0 +1,24 @@ +// +// Created by alex on 5/15/2019. +// +#include "chapter_05_flipBitToWin.h" + +namespace chapter_05 { + int flipBitToWin(int input) { + /* + * PROBLEM + * given an integer, determine which bit to flip to make it contain the longest possible + * sequence of 1s. + * + * TEST CASE + * + * ALGORITHM + * + * SPACE & TIME + * + * CODE + * + * + */ + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h index 4991d49..4789731 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h +++ b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h @@ -6,5 +6,6 @@ #include "problem_05_01_insertion.h" #include "problem_05_02_binaryToString.h" +#include "problem_05_03_flipBitToWin.h" #include "problem_05_06_conversion.h" #include "problem_05_07_pairwiseSwap.h" diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h new file mode 100644 index 0000000..d2c4f3a --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h @@ -0,0 +1,8 @@ +// +// Created by alex on 5/15/2019. +// + +#pragma once +namespace chapter_05 { + int flipBitToWin(int input); +} From 00dcae1d3a075596bb7270a5da44569767019dac Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 16 May 2019 08:56:41 -0700 Subject: [PATCH 050/176] uncomment tests --- tests.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests.cpp b/tests.cpp index fd5c7c9..148dde7 100644 --- a/tests.cpp +++ b/tests.cpp @@ -952,11 +952,11 @@ TEST_CASE("Chapter 08 - Problem 08 - permutationsWithDups()", "test") { "xael", "axel", "aexl", "aelx", "xale", "axle", "alxe", "alex"}; chapter_08::permutationsWithDups("ala", actual1); - //chapter_08::permutationsWithDups("alaa", actual2); - //chapter_08::permutationsWithDups("alex", actual3); + chapter_08::permutationsWithDups("alaa", actual2); + chapter_08::permutationsWithDups("alex", actual3); REQUIRE(actual1 == expected1); - //REQUIRE(actual2 == expected2); - //REQUIRE(actual3 == expected3); + REQUIRE(actual2 == expected2); + REQUIRE(actual3 == expected3); } TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ From ac81ea3ec6d585101fd96891fa9e0d265d09685a Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 16 May 2019 10:10:53 -0700 Subject: [PATCH 051/176] implement 5.3 C++ --- .gitignore | 1 + CMakeLists.txt | 1 + .../chapter_05_flipBitToWin.cpp | 24 -------- .../problem_05_03_flipBitToWin.cpp | 56 +++++++++++++++++++ tests.cpp | 10 ++++ 5 files changed, 68 insertions(+), 24 deletions(-) delete mode 100644 cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp create mode 100644 cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp diff --git a/.gitignore b/.gitignore index b6515aa..a6c00e5 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ build cmake-build-debug CppProperties.json .vs +**/.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 2afea9b..1e66a53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,6 +25,7 @@ set(SOURCE_FILES cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp diff --git a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp deleted file mode 100644 index 42d2995..0000000 --- a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_flipBitToWin.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Created by alex on 5/15/2019. -// -#include "chapter_05_flipBitToWin.h" - -namespace chapter_05 { - int flipBitToWin(int input) { - /* - * PROBLEM - * given an integer, determine which bit to flip to make it contain the longest possible - * sequence of 1s. - * - * TEST CASE - * - * ALGORITHM - * - * SPACE & TIME - * - * CODE - * - * - */ - } -} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp new file mode 100644 index 0000000..5a5f2d9 --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp @@ -0,0 +1,56 @@ +// +// Created by alex on 5/15/2019. +// +#include "problem_05_03_flipBitToWin.h" + +namespace chapter_05 { + int flipBitToWin(int input) { + /* + * PROBLEM: + * Given an integer, determine which bit to flip to make it contain the longest possible + * sequence of 1s. + * + * TEST CASE: + * 0b000 -> 1 + * 0b100 -> 1 + * 0b1011011 -> 5 + * + * ALGORITHM: + * 1. Iterate through binary representation by using logical right shift on copy of int + * 2. Keep 3 tallys: prev tally, current tally, max tally. + * 3. Loop over binary representation: + * a. Count the number of 1s seen so far in current tally. + * b. If a zero is seen: + * i. add 1 to current tally + * ii. set max tally to sum of pre and post tally if the sum is > max tally + * iii. prev tally = current tally + * c. logical shift the input to the right with >>> + * 4. In case where binary representation ends in 1, we have to do the check in b.ii. again. + * 5. return max tally + * + * SPACE & TIME: + * Space: O(1): extra space we use does not scale with length of int + * Time: O(b) because we have to iterate thru each bit + * + * CODE: + */ + int prevTally = 0; + int currentTally = 0; + int maxTally = 0; + if (input == 0) return 1; // edge case where we do not need to run the algorithm + while (input != 0) { + if ((input & 0b1) == 1) { + currentTally ++; + } else { + int sum = prevTally + currentTally + 1; + if (sum > maxTally) maxTally = sum; + prevTally = currentTally; + currentTally = 0; + } + input = input >> 1; + } + int sum = prevTally + currentTally + 1; + if (sum > maxTally) maxTally = sum; + return maxTally; + } +} diff --git a/tests.cpp b/tests.cpp index 148dde7..2d39d69 100644 --- a/tests.cpp +++ b/tests.cpp @@ -833,6 +833,16 @@ TEST_CASE("Chapter 05 - Problem 02 - binaryToString()", "test") { REQUIRE(binary_string_4 == "0.10111000110101001111110111110011"); // needs double precision to work } +TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { + REQUIRE(chapter_05::flipBitToWin(1775) == 8); + REQUIRE(chapter_05::flipBitToWin(0b0000) == 1); + REQUIRE(chapter_05::flipBitToWin(0b1011) == 4); + REQUIRE(chapter_05::flipBitToWin(0b1010111) == 5); + REQUIRE(chapter_05::flipBitToWin(0b1110101) == 5); + REQUIRE(chapter_05::flipBitToWin(0b00) == 1); + REQUIRE(chapter_05::flipBitToWin(0b10) == 2); +} + TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ REQUIRE(chapter_05::conversion(0b11001100, 0b11110000) == 4); REQUIRE(chapter_05::conversion(29, 15) == 2); From 553a4b70385f0bcf08002f17a42ac4187451bf36 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 16 May 2019 10:12:32 -0700 Subject: [PATCH 052/176] update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8328c90..c39f123 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ reference and contribute solutions with confidence. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `4 / 7` complete. +5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `5 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `47` solutions. +C++ Total: `48` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `47` solutions. Python Total: `56` solutions. -##### Grand Total: `103` unique solutions. +##### Grand Total: `104` unique solutions. ### Building: #### Mac: From 2eb6eb2046b29cac1b6b000dc71149238600018e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 17 May 2019 17:18:51 -0700 Subject: [PATCH 053/176] skeleton for 5.4 C++ --- CMakeLists.txt | 1 + .../problem_05_03_flipBitToWin.cpp | 4 +- .../problem_05_04_nextNumber.cpp | 42 +++++++++++++++++++ .../problem_05_04_nextNumber.h | 6 +++ 4 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp create mode 100644 cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e66a53..0a3a94f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(SOURCE_FILES cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp index 5a5f2d9..1862aa5 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp @@ -7,8 +7,8 @@ namespace chapter_05 { int flipBitToWin(int input) { /* * PROBLEM: - * Given an integer, determine which bit to flip to make it contain the longest possible - * sequence of 1s. + * Flip Bit to Win: You have an integer and you can flip exactly one bit from a 13 to a 1.Write code to + * find the length of the longest sequence of ls you could create. * * TEST CASE: * 0b000 -> 1 diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp new file mode 100644 index 0000000..d920c32 --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -0,0 +1,42 @@ +// +// Created by Alex Hagiopol on 2019-05-17. +// +#include "problem_05_04_nextNumber.h" + +namespace chapter_05 { + std::pair nextNumber(int positiveInteger) { + /* + * PROBLEM: + * Given a positive integer, return the next smallest and next largest + * numbers that have the same number of 1s in their binary representations. + * + * TEST CASE: + * positiveInteger -> (nextSmallest, nextLargest) + * 0b0000 -> (0, 0) + * 0b1000 -> (0b0100, ?) + * 0b0001 -> (?, 0b0010) + * 0b0101 -> (0b0011, 0b0110) + * + * ALGORITHM: + * 1. To make a smaller number, shift least significant 1 that has space to move right + * a. Iterate through binary representation to find the rightmost 1 that has a 0 to its right + * b. & the input integer with 111...1110111 then | with 000...0000100 + * c. when we've found the rightmost 1, note its index, then create masks by left shifting a 1 to that index + * 2. To make a bigger number, shift least significant 1 that has space to move left + * ...same as above + * 3. Edge cases? + * a. 0b00...1 -> return (the number itself, its left shift) + * b. 0b10...0 -> return (its left shift, the number itself) + * c. 0b0 -> return (0,0) + * + * SPACE & TIME: + * Space: O(b) - we need to allocate masks the same size as the input + * Time: O(b) - we need to iterate through the binary representation bit by bit + * + * CODE: + */ + std::pair smallerAndLarger(positiveInteger, positiveInteger); + + return smallerAndLarger; + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h new file mode 100644 index 0000000..5eefcad --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h @@ -0,0 +1,6 @@ +#pragma once +#include + +namespace chapter_05 { + std::pair nextNumber(int positiveInteger); +} From 728e0da23a1eee901c95a2e588758beafb5adfd5 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 19 May 2019 19:00:53 -0800 Subject: [PATCH 054/176] make 5.4 python unit tests conform to textbook implementation --- .gitignore | 18 +- CMakeLists.txt | 90 +- README.md | 324 +-- .../chapter_05_includes.h | 1 + .../problem_05_03_flipBitToWin.cpp | 112 +- .../problem_05_03_flipBitToWin.h | 16 +- .../problem_05_04_nextNumber.cpp | 87 +- .../problem_05_04_nextNumber.h | 13 +- .../problem_05_04_next_number.py | 24 +- tests.cpp | 2199 +++++++++-------- tests.py | 7 +- 11 files changed, 1456 insertions(+), 1435 deletions(-) diff --git a/.gitignore b/.gitignore index a6c00e5..777c102 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ -.idea/ -*pycache* -*.pyc -.coverage -build -cmake-build-debug -CppProperties.json -.vs -**/.DS_Store +.idea/ +*pycache* +*.pyc +.coverage +build +cmake-build-debug +CppProperties.json +.vs +**/.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a3a94f..0c2623e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,45 +1,45 @@ -cmake_minimum_required(VERSION 3.2) -project(ctci) -set(CMAKE_CXX_STANDARD 11) -# include source folder -include_directories(cpp_solutions) -# include Eigen -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_solutions/third_party/eigen) - -# set source files -set(SOURCE_FILES - tests.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_04_palindromePermutation.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp - # chapter 2 .cpp files not included because they are template functions implemented in .h files - # chapter 3 .cpp files not included because they are template functions implemented in .h files - cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp - # chapter 4 .cpp files not included because they are template functions implemented in .h files - cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp - # problem 10.01 not included because it is a template function implemented in .h file - cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp - # problem 12.08 not included because it is a template function implemented in .h file - cpp_solutions/misc_exercises/integralImage.cpp) -# create executable -add_executable(tests ${SOURCE_FILES}) +cmake_minimum_required(VERSION 3.2) +project(ctci) +set(CMAKE_CXX_STANDARD 11) +# include source folder +include_directories(cpp_solutions) +# include Eigen +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_solutions/third_party/eigen) + +# set source files +set(SOURCE_FILES + tests.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_04_palindromePermutation.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp + # chapter 2 .cpp files not included because they are template functions implemented in .h files + # chapter 3 .cpp files not included because they are template functions implemented in .h files + cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp + # chapter 4 .cpp files not included because they are template functions implemented in .h files + cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp + # problem 10.01 not included because it is a template function implemented in .h file + cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp + # problem 12.08 not included because it is a template function implemented in .h file + cpp_solutions/misc_exercises/integralImage.cpp) +# create executable +add_executable(tests ${SOURCE_FILES}) diff --git a/README.md b/README.md index c39f123..4f5e460 100644 --- a/README.md +++ b/README.md @@ -1,162 +1,162 @@ - ## Cracking The Coding Interview Solutions with Automated Unit Tests - - * :white_check_mark: C++ Solutions - * :white_check_mark: Python Solutions - * :white_check_mark: Automated Unit Tests - * :white_check_mark: Active Development - * :white_check_mark: Multiplatform Support: Mac, Linux, and Windows - -### Introduction -This repo contains C++ and Python solutions for Gayle Laakmann McDowell's [*Cracking the Coding Interview 6th Edition*](http://a.co/baneyGe). -Admittedly, there are other GitHub repositories with solutions for this book. *But -how do you know that their code is actually correct?* If it's untested, then you don't! - -In this project, every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch), -and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html). -We enforce test correctness automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) -ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is -the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can -reference and contribute solutions with confidence. - -### Table of Contents -#### [C++ Solutions](cpp_solutions): -0. [C++ Unit Tests](tests.cpp) -1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. -2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `5 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. -7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. -11. Chapter 11 - Testing: N/A -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` -13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` -16. Chapter 16 - Moderate: `0 / 26` complete. -17. Chapter 17 - Hard: `0 / 26` complete. - -C++ Total: `48` solutions. - -#### [Python Solutions](python_solutions): -0. [Python Unit tests](tests.py) -1. [Chapter 1 - Arrays and Strings](python_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. -2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. -4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. -7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. -11. Chapter 11 - Testing: N/A -12. Chapter 12 - C and C++: N/A -13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. -17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. - -Python Total: `56` solutions. - -##### Grand Total: `104` unique solutions. - -### Building: -#### Mac: -Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: - - git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git ctci - cd ctci - make configure-mac - -#### Ubuntu: - - git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git - cd ctci - make configure-ubuntu - -#### Windows: -For Windows users, I recommend developing this project using the [Windows Subsystem -for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) feature -of Windows 10 and then following the Ubuntu build and testing instructions inside WSL. -This recommendation is due to the use of Ubuntu, CMake, and makefile based build and execution -systems on the servers that automatically test changes to the code. For more on Windows -development, see the `Appendix` section at the end of this page. - -### Testing: -Testing is the most important part of this project: *only* -the unit tests define the problem being solved. In the root -directory, execute the following to run all tests in Python and C++: - - make test - -`make test` is the command I use most while developing this project. My workflow follows: - -1. I read a problem and encode the problem definition by implementing its unit tests. -2. I execute `make test` to see where the project fails to satisfy the unit tests. -3. I add to the implementation of the problem solution until `make test` succeeds. - -### Optional: Generating a Test Coverage % Report Locally (Python support only): -This will show exactly which lines are not covered by tests in each Python source file: - - pip install coverage - make test_coverage - -### Contributing -The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. -I definitely need help, so PRs are welcome. There is much to do because each solution needs its own -small dataset and infrastructure in order to be tested. Here are some ways you can help: - -1. Fixing bugs :bug:. -2. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). -3. Adding more unit tests to increase the test coverage %. -4. Implementing automated C++ test coverage measurement using [gcov](http://gcc.gnu.org/onlinedocs/gcc/Gcov.html). -5. Integrating automated test coverage % reporting for both Python and C++ via [Coveralls](Coveralls.io). -6. Adding prose solution descriptions for problems that don't have them. - -If you have any contributions, please make a PR to the `master` branch. Feel free to message me for clarification on any of -the above items. - -### Appendix: Windows Development -On my own Windows machine, I develop using [CLion](https://www.jetbrains.com/clion/) running -natively in Windows and test the code using `make test` in a WSL terminal window. -For users who do not want to use WSL, I have developed the build and test methodology below: - -#### Building -The project can be developed purely on Windows without WSL by using Visual Studio 2017. -First clone the code: - - git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git - cd ctci - git submodule update --init - -Then, install Python3 and numpy using your method of choice. I prefer installing Python3 and pip3 from -the [official website](https://www.python.org/downloads/) then installing numpy via pip: - - pip install numpy - -Then, open the project in Visual Studio 2017 which has CMake support. -I've found that best the workflow is to use Visual Studio to edit code and use debugging functionality. Before -building the code, you must follow [these instructions](https://stackoverflow.com/a/12954908) -to tell Visual Studio to download PDBs it needs. Additionally, [this article](https://blogs.msdn.microsoft.com/vcblog/2016/10/05/cmake-support-in-visual-studio/) -describes Visual Studio CMake support in more detail if you're interested. A CMakeSettings.json file in the root project -directory sets the location of the Visual Studio build folder to be inside the root folder of the project. - -#### Testing -Running the tests and seeing their output is best done from a PowerShell window since VisualStudio in CMake mode -does *not* allow the console output of the `tests.exe` and `tests.py` files to remain visible even when pressing -CTRL + F5 as described [in this post](https://stackoverflow.com/a/1775870) which applies to -"normal" Visual Studio use. I am monitoring the situation re: Visual Studio, and when I find better solutions -I will implement them or post them. If you know of something better, please contact me. - -In the meantime, from the project root directory, you can run the Python tests using ... - - python tests.py - -... and you can run the C++ tests using ... - - .\build\x64-Debug\tests.exe + ## Cracking The Coding Interview Solutions with Automated Unit Tests + + * :white_check_mark: C++ Solutions + * :white_check_mark: Python Solutions + * :white_check_mark: Automated Unit Tests + * :white_check_mark: Active Development + * :white_check_mark: Multiplatform Support: Mac, Linux, and Windows + +### Introduction +This repo contains C++ and Python solutions for Gayle Laakmann McDowell's [*Cracking the Coding Interview 6th Edition*](http://a.co/baneyGe). +Admittedly, there are other GitHub repositories with solutions for this book. *But +how do you know that their code is actually correct?* If it's untested, then you don't! + +In this project, every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch), +and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html). +We enforce test correctness automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) +ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is +the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can +reference and contribute solutions with confidence. + +### Table of Contents +#### [C++ Solutions](cpp_solutions): +0. [C++ Unit Tests](tests.cpp) +1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. +2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. +3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. +5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `5 / 7` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. +7. Chapter 7 - Object Oriented Design: `0 / 12` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. +9. Chapter 9 - System Design and Scalability: N/A +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +11. Chapter 11 - Testing: N/A +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` +13. Chapter 13 - Java: N/A +14. Chapter 14 - Databases: N/A +15. Chapter 15 - Threads and Locks: `0 / 4` +16. Chapter 16 - Moderate: `0 / 26` complete. +17. Chapter 17 - Hard: `0 / 26` complete. + +C++ Total: `48` solutions. + +#### [Python Solutions](python_solutions): +0. [Python Unit tests](tests.py) +1. [Chapter 1 - Arrays and Strings](python_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. +2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. +3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. +4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. +5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. +7. Chapter 7 - Object Oriented Design: `0 / 12` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. +9. Chapter 9 - System Design and Scalability: N/A +10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +11. Chapter 11 - Testing: N/A +12. Chapter 12 - C and C++: N/A +13. Chapter 13 - Java: N/A +14. Chapter 14 - Databases: N/A +15. Chapter 15 - Threads and Locks: `0 / 4` complete. +16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. +17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. + +Python Total: `56` solutions. + +##### Grand Total: `104` unique solutions. + +### Building: +#### Mac: +Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: + + git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git ctci + cd ctci + make configure-mac + +#### Ubuntu: + + git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git + cd ctci + make configure-ubuntu + +#### Windows: +For Windows users, I recommend developing this project using the [Windows Subsystem +for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) feature +of Windows 10 and then following the Ubuntu build and testing instructions inside WSL. +This recommendation is due to the use of Ubuntu, CMake, and makefile based build and execution +systems on the servers that automatically test changes to the code. For more on Windows +development, see the `Appendix` section at the end of this page. + +### Testing: +Testing is the most important part of this project: *only* +the unit tests define the problem being solved. In the root +directory, execute the following to run all tests in Python and C++: + + make test + +`make test` is the command I use most while developing this project. My workflow follows: + +1. I read a problem and encode the problem definition by implementing its unit tests. +2. I execute `make test` to see where the project fails to satisfy the unit tests. +3. I add to the implementation of the problem solution until `make test` succeeds. + +### Optional: Generating a Test Coverage % Report Locally (Python support only): +This will show exactly which lines are not covered by tests in each Python source file: + + pip install coverage + make test_coverage + +### Contributing +The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. +I definitely need help, so PRs are welcome. There is much to do because each solution needs its own +small dataset and infrastructure in order to be tested. Here are some ways you can help: + +1. Fixing bugs :bug:. +2. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). +3. Adding more unit tests to increase the test coverage %. +4. Implementing automated C++ test coverage measurement using [gcov](http://gcc.gnu.org/onlinedocs/gcc/Gcov.html). +5. Integrating automated test coverage % reporting for both Python and C++ via [Coveralls](Coveralls.io). +6. Adding prose solution descriptions for problems that don't have them. + +If you have any contributions, please make a PR to the `master` branch. Feel free to message me for clarification on any of +the above items. + +### Appendix: Windows Development +On my own Windows machine, I develop using [CLion](https://www.jetbrains.com/clion/) running +natively in Windows and test the code using `make test` in a WSL terminal window. +For users who do not want to use WSL, I have developed the build and test methodology below: + +#### Building +The project can be developed purely on Windows without WSL by using Visual Studio 2017. +First clone the code: + + git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git + cd ctci + git submodule update --init + +Then, install Python3 and numpy using your method of choice. I prefer installing Python3 and pip3 from +the [official website](https://www.python.org/downloads/) then installing numpy via pip: + + pip install numpy + +Then, open the project in Visual Studio 2017 which has CMake support. +I've found that best the workflow is to use Visual Studio to edit code and use debugging functionality. Before +building the code, you must follow [these instructions](https://stackoverflow.com/a/12954908) +to tell Visual Studio to download PDBs it needs. Additionally, [this article](https://blogs.msdn.microsoft.com/vcblog/2016/10/05/cmake-support-in-visual-studio/) +describes Visual Studio CMake support in more detail if you're interested. A CMakeSettings.json file in the root project +directory sets the location of the Visual Studio build folder to be inside the root folder of the project. + +#### Testing +Running the tests and seeing their output is best done from a PowerShell window since VisualStudio in CMake mode +does *not* allow the console output of the `tests.exe` and `tests.py` files to remain visible even when pressing +CTRL + F5 as described [in this post](https://stackoverflow.com/a/1775870) which applies to +"normal" Visual Studio use. I am monitoring the situation re: Visual Studio, and when I find better solutions +I will implement them or post them. If you know of something better, please contact me. + +In the meantime, from the project root directory, you can run the Python tests using ... + + python tests.py + +... and you can run the C++ tests using ... + + .\build\x64-Debug\tests.exe diff --git a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h index 4789731..8ab824c 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h +++ b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h @@ -7,5 +7,6 @@ #include "problem_05_01_insertion.h" #include "problem_05_02_binaryToString.h" #include "problem_05_03_flipBitToWin.h" +#include "problem_05_04_nextNumber.h" #include "problem_05_06_conversion.h" #include "problem_05_07_pairwiseSwap.h" diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp index 1862aa5..46b53e3 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp @@ -1,56 +1,56 @@ -// -// Created by alex on 5/15/2019. -// -#include "problem_05_03_flipBitToWin.h" - -namespace chapter_05 { - int flipBitToWin(int input) { - /* - * PROBLEM: - * Flip Bit to Win: You have an integer and you can flip exactly one bit from a 13 to a 1.Write code to - * find the length of the longest sequence of ls you could create. - * - * TEST CASE: - * 0b000 -> 1 - * 0b100 -> 1 - * 0b1011011 -> 5 - * - * ALGORITHM: - * 1. Iterate through binary representation by using logical right shift on copy of int - * 2. Keep 3 tallys: prev tally, current tally, max tally. - * 3. Loop over binary representation: - * a. Count the number of 1s seen so far in current tally. - * b. If a zero is seen: - * i. add 1 to current tally - * ii. set max tally to sum of pre and post tally if the sum is > max tally - * iii. prev tally = current tally - * c. logical shift the input to the right with >>> - * 4. In case where binary representation ends in 1, we have to do the check in b.ii. again. - * 5. return max tally - * - * SPACE & TIME: - * Space: O(1): extra space we use does not scale with length of int - * Time: O(b) because we have to iterate thru each bit - * - * CODE: - */ - int prevTally = 0; - int currentTally = 0; - int maxTally = 0; - if (input == 0) return 1; // edge case where we do not need to run the algorithm - while (input != 0) { - if ((input & 0b1) == 1) { - currentTally ++; - } else { - int sum = prevTally + currentTally + 1; - if (sum > maxTally) maxTally = sum; - prevTally = currentTally; - currentTally = 0; - } - input = input >> 1; - } - int sum = prevTally + currentTally + 1; - if (sum > maxTally) maxTally = sum; - return maxTally; - } -} +// +// Created by alex on 5/15/2019. +// +#include "problem_05_03_flipBitToWin.h" + +namespace chapter_05 { + int flipBitToWin(int input) { + /* + * PROBLEM: + * Flip Bit to Win: You have an integer and you can flip exactly one bit from a 13 to a 1.Write code to + * find the length of the longest sequence of ls you could create. + * + * TEST CASE: + * 0b000 -> 1 + * 0b100 -> 1 + * 0b1011011 -> 5 + * + * ALGORITHM: + * 1. Iterate through binary representation by using logical right shift on copy of int + * 2. Keep 3 tallys: prev tally, current tally, max tally. + * 3. Loop over binary representation: + * a. Count the number of 1s seen so far in current tally. + * b. If a zero is seen: + * i. add 1 to current tally + * ii. set max tally to sum of pre and post tally if the sum is > max tally + * iii. prev tally = current tally + * c. logical shift the input to the right with >>> + * 4. In case where binary representation ends in 1, we have to do the check in b.ii. again. + * 5. return max tally + * + * SPACE & TIME: + * Space: O(1): extra space we use does not scale with length of int + * Time: O(b) because we have to iterate thru each bit + * + * CODE: + */ + int prevTally = 0; + int currentTally = 0; + int maxTally = 0; + if (input == 0) return 1; // edge case where we do not need to run the algorithm + while (input != 0) { + if ((input & 0b1) == 1) { + currentTally ++; + } else { + int sum = prevTally + currentTally + 1; + if (sum > maxTally) maxTally = sum; + prevTally = currentTally; + currentTally = 0; + } + input = input >> 1; + } + int sum = prevTally + currentTally + 1; + if (sum > maxTally) maxTally = sum; + return maxTally; + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h index d2c4f3a..28f8dad 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h @@ -1,8 +1,8 @@ -// -// Created by alex on 5/15/2019. -// - -#pragma once -namespace chapter_05 { - int flipBitToWin(int input); -} +// +// Created by alex on 5/15/2019. +// + +#pragma once +namespace chapter_05 { + int flipBitToWin(int input); +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index d920c32..d53fb76 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -1,42 +1,45 @@ -// -// Created by Alex Hagiopol on 2019-05-17. -// -#include "problem_05_04_nextNumber.h" - -namespace chapter_05 { - std::pair nextNumber(int positiveInteger) { - /* - * PROBLEM: - * Given a positive integer, return the next smallest and next largest - * numbers that have the same number of 1s in their binary representations. - * - * TEST CASE: - * positiveInteger -> (nextSmallest, nextLargest) - * 0b0000 -> (0, 0) - * 0b1000 -> (0b0100, ?) - * 0b0001 -> (?, 0b0010) - * 0b0101 -> (0b0011, 0b0110) - * - * ALGORITHM: - * 1. To make a smaller number, shift least significant 1 that has space to move right - * a. Iterate through binary representation to find the rightmost 1 that has a 0 to its right - * b. & the input integer with 111...1110111 then | with 000...0000100 - * c. when we've found the rightmost 1, note its index, then create masks by left shifting a 1 to that index - * 2. To make a bigger number, shift least significant 1 that has space to move left - * ...same as above - * 3. Edge cases? - * a. 0b00...1 -> return (the number itself, its left shift) - * b. 0b10...0 -> return (its left shift, the number itself) - * c. 0b0 -> return (0,0) - * - * SPACE & TIME: - * Space: O(b) - we need to allocate masks the same size as the input - * Time: O(b) - we need to iterate through the binary representation bit by bit - * - * CODE: - */ - std::pair smallerAndLarger(positiveInteger, positiveInteger); - - return smallerAndLarger; - } -} +// +// Created by Alex Hagiopol on 2019-05-17. +// +#include "problem_05_04_nextNumber.h" + +namespace chapter_05 { + /* + * PROBLEM: + * Given a positive integer, return the next smallest and next largest + * numbers that have the same number of 1s in their binary representations. + * + * TEST CASE: + * positiveInteger -> (nextSmallest, nextLargest) + * 0b0000 -> (0, 0) + * 0b1000 -> (0b0100, ?) + * 0b0001 -> (?, 0b0010) + * 0b0101 -> (0b0011, 0b0110) + * + * ALGORITHM: + * 1. To make a smaller number, shift least significant 1 that has space to move right + * a. Iterate through binary representation to find the rightmost 1 that has a 0 to its right + * b. & the input integer with 111...1110111 then | with 000...0000100 + * c. when we've found the rightmost 1, note its index, then create masks by left shifting a 1 to that index + * 2. To make a bigger number, shift least significant 1 that has space to move left + * ...same as above + * 3. Edge cases? + * a. 0b00...1 -> return (the number itself, its left shift) + * b. 0b10...0 -> return (its left shift, the number itself) + * c. 0b0 -> return (0,0) + * + * SPACE & TIME: + * Space: O(b) - we need to allocate masks the same size as the input + * Time: O(b) - we need to iterate through the binary representation bit by bit + * + * CODE: + */ + int getNext(int positiveInteger) { + + return positiveInteger; + } + int getPrev(int positiveInteger) { + + return positiveInteger; + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h index 5eefcad..6d7f067 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h @@ -1,6 +1,7 @@ -#pragma once -#include - -namespace chapter_05 { - std::pair nextNumber(int positiveInteger); -} +#pragma once +#include + +namespace chapter_05 { + int getNext(int positiveInteger); + int getPrev(int positiveInteger); +} diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py index 2f71339..5be67f1 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py @@ -19,17 +19,17 @@ def get_prev(binary_list): 3. Flip the 0 to a 1. """ if all(x == binary_list[0] for x in binary_list): # step 0 - return None + return -1 - zero_index = None - one_index = None + zero_index = -1 + one_index = -1 for index in range(len(binary_list) - 1, 0, -1): # step 1. traverse list starting with least significant bit if binary_list[index] == '0' and binary_list[index - 1] == '1': one_index = index - 1 zero_index = index break - if one_index is None: - return None + if one_index == -1: + return -1 binary_list[one_index] = '0' # step 2 binary_list[zero_index] = '1' # step 4 return binary_list @@ -47,23 +47,23 @@ def get_next(binary_list): if all(x == '1' for x in binary_list): # step 0 return ['1', '0'] + binary_list[1:] - zero_index = None + zero_index = -1 for index in range(len(binary_list) - 1, 0, -1): # step 1. traverse list starting with least significant bit if binary_list[index] == '1' and binary_list[index - 1] == '0': zero_index = index - 1 break - if zero_index is None: - return None + if zero_index == -1: + return -1 - one_index = None + one_index = -1 for index in range(len(binary_list) - 1, 0, -1): # step 3. if binary_list[index] == '1': one_index = index break - if one_index is None: - return None + if one_index == -1: + return -1 if one_index <= zero_index: - return None + return -1 binary_list[zero_index] = '1' # step 2 binary_list[one_index] = '0' # step 4 diff --git a/tests.cpp b/tests.cpp index 2d39d69..65a71ce 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1,1092 +1,1107 @@ -// -// 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 testVec = {"a", "b", "c", "d", "e", "f"}; - std::vector expectedVec = {"a", "b", "d", "e", "f"}; - chapter_02::SinglyLinkedNode* testVecHead = chapter_02::vectorToList(testVec); - chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); - // traverse input to find node with content "c" - chapter_02::SinglyLinkedNode* 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 list4 = {"a", "l", "e", "x"}; - std::vector 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* head4 = chapter_02::vectorToList(list4); - chapter_02::SinglyLinkedNode* 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*>(nullptr), static_cast*>(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*>(nullptr) == chapter_02::findLoop(static_cast*>(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*> 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*> 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*>(nullptr), static_cast*>(nullptr))); - REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(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*> vectorOfHeads; - std::vector*> 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> 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> 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> 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 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); - /* - construct disconnected binary tree - 30 - 31 32 - */ - chapter_02::BinaryNode n31(31); - chapter_02::BinaryNode n32(32); - chapter_02::BinaryNode n30(30, &n31, &n32); - - REQUIRE(chapter_04::checkSubtree(&n7, &n15)); - REQUIRE(chapter_04::checkSubtree(&n7, &n7)); - REQUIRE(chapter_04::checkSubtree(&n7, &n21)); - REQUIRE(chapter_04::checkSubtree(&n7, &n4)); - REQUIRE(!chapter_04::checkSubtree(&n7, nullptr)); - REQUIRE(!chapter_04::checkSubtree(&n7, &n30)); - REQUIRE(!chapter_04::checkSubtree(&n7, &n31)); - REQUIRE(!chapter_04::checkSubtree(&n25, &n31)); - REQUIRE(chapter_04::checkSubtree(&n30, &n31)); - REQUIRE(!chapter_04::checkSubtree(nullptr, nullptr)); -} - -TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ - std::vector valuesList = {10, 13, 14, 11, 7, 7, 8, 7, 4, 10}; - chapter_04::RandBinaryNode head(valuesList[0]); - for (int i = 1; i < valuesList.size(); i++) { - head.insert(valuesList[i]); - } - int occurrenceSum4 = 0; - int occurrenceSum7 = 0; - int occurrenceSum10 = 0; - int occurrenceSum13 = 0; - // using 10,000 random samples, assert that occurence of values in random samples approximately - // the same as the occurence of the values in the tree - std::mt19937 gen(0); // standard mersenne_twister_engine seeded with zero - for (int i = 0; i < 10000; i++) { - int randValue = head.getRandomNode(-1, &gen)->getValue(); - switch (randValue){ - case 4 : occurrenceSum4 ++; break; - case 7 : occurrenceSum7 ++; break; - case 10 : occurrenceSum10 ++; break; - case 13 : occurrenceSum13 ++; break; - } - } - REQUIRE(((950 <= occurrenceSum4) && (occurrenceSum4 <= 1050))); - REQUIRE(((2950 <= occurrenceSum7) && (occurrenceSum7 <= 3050))); - REQUIRE(((1950 <= occurrenceSum10) && (occurrenceSum10 <= 2050))); - REQUIRE(((950 <= occurrenceSum13) && (occurrenceSum13 <= 1050))); -} - -TEST_CASE("Chapter 04 - Problem 12 - pathsWithSum()", "test"){ - /* - construct binary tree like in textbook example - 10 - 5 -3 - 3 1 __ 11 - 3 -2 __ 2 - */ - // leaf nodes at depth = 3 - chapter_02::BinaryNode n3_leaf(3); - chapter_02::BinaryNode n_minus2(-2); - chapter_02::BinaryNode n2(2); - // nodes at depth = 2 - chapter_02::BinaryNode n3(3, &n3_leaf, &n_minus2); - chapter_02::BinaryNode n1(1, nullptr, &n2); - chapter_02::BinaryNode n11(11); - // nodes at depth = 1 - chapter_02::BinaryNode n5(5, &n3, &n1); - chapter_02::BinaryNode n_minus3(-3, nullptr, &n11); - // root node at depth = 0 - chapter_02::BinaryNode n10(10, &n5, &n_minus3); - // count paths that sum to 8 - REQUIRE(3 == chapter_04::pathsWithSum(8, &n10)); -} - -TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ - REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); -} - -TEST_CASE("Chapter 05 - Problem 02 - binaryToString()", "test") { - std::string binary_string_1 = ""; - std::string binary_string_2 = ""; - std::string binary_string_3 = ""; - std::string binary_string_4 = ""; - REQUIRE(chapter_05::binaryToString(0.5, binary_string_1) == 0); - REQUIRE(chapter_05::binaryToString(0.25, binary_string_2) == 0); - REQUIRE(chapter_05::binaryToString(1.5, binary_string_3) == -1); - REQUIRE(chapter_05::binaryToString(0.722, binary_string_4) == 0); - REQUIRE(binary_string_1 == "0.1"); - REQUIRE(binary_string_2 == "0.01"); - REQUIRE(binary_string_3 == ""); - REQUIRE(binary_string_4 == "0.10111000110101001111110111110011"); // needs double precision to work -} - -TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { - REQUIRE(chapter_05::flipBitToWin(1775) == 8); - REQUIRE(chapter_05::flipBitToWin(0b0000) == 1); - REQUIRE(chapter_05::flipBitToWin(0b1011) == 4); - REQUIRE(chapter_05::flipBitToWin(0b1010111) == 5); - REQUIRE(chapter_05::flipBitToWin(0b1110101) == 5); - REQUIRE(chapter_05::flipBitToWin(0b00) == 1); - REQUIRE(chapter_05::flipBitToWin(0b10) == 2); -} - -TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ - REQUIRE(chapter_05::conversion(0b11001100, 0b11110000) == 4); - REQUIRE(chapter_05::conversion(29, 15) == 2); -} - -TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ - REQUIRE(chapter_05::pairwiseSwap(0b10101010) == 0b01010101); - REQUIRE(chapter_05::pairwiseSwap(0b11110000) == 0b11110000); - REQUIRE(chapter_05::pairwiseSwap(0b110) == 0b1001); -} - -TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ - REQUIRE(chapter_08::tripleStep(3) == 4); - REQUIRE(chapter_08::tripleStep(4) == 7); - REQUIRE(chapter_08::tripleStep(5) == 13); -} - -TEST_CASE("Chapter 08 - Problem 02 - robotGrid()", "test"){ - - Eigen::MatrixXd maze(5, 5); - maze << 1, 1, 1, 0, 1, - 0, 0, 1, 1, 1, - 0, 1, 1, 0, 0, - 0, 1, 1, 0, 1, - 1, 1, 1, 1, 1; - std::vector expectedPath = {Eigen::Vector2d(0,0), - Eigen::Vector2d(0,1), - Eigen::Vector2d(0,2), - Eigen::Vector2d(1,2), - Eigen::Vector2d(2,2), - Eigen::Vector2d(3,2), - Eigen::Vector2d(4,2), - Eigen::Vector2d(4,3), - Eigen::Vector2d(4,4)}; - std::vector path; - REQUIRE(chapter_08::robotGrid(maze, path)); - REQUIRE(path == expectedPath); -} - -TEST_CASE("Chapter 08 - Problem 03 - magicIndex()", "test"){ - std::vector noMagicIndex = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector magicIndex5 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector magicIndex7 = {-40, -20, -1, 1, 2, 3, 5, 7, 9, 12, 13}; - REQUIRE(chapter_08::magicIndex(noMagicIndex) == -1); - REQUIRE(chapter_08::magicIndex(magicIndex5) == 5); - REQUIRE(chapter_08::magicIndex(magicIndex7) == 7); -} - -TEST_CASE("Chapter 08 - Problem 04 - powerSet()", "test"){ - std::vector set123 = {1, 2, 3}; - std::vector set12 = {1, 2}; - std::vector set13 = {1, 3}; - std::vector set23 = {2, 3}; - std::vector set1 = {1}; - std::vector set2 = {2}; - std::vector set3 = {3}; - std::vector emptySet = {}; - - std::vector> powerSet123 = {emptySet, set1, set2, set12, set3, set13, set23, set123}; - std::vector> powerSet12 = {emptySet, set1, set2, set12}; - std::vector> powerSet1 = {emptySet, set1}; - - std::vector> testPowerSet = {}; - chapter_08::createPowerSet(set123, testPowerSet); - REQUIRE(testPowerSet == powerSet123); - testPowerSet = {}; - chapter_08::createPowerSet(set12, testPowerSet); - REQUIRE(testPowerSet == powerSet12); - testPowerSet = {}; - chapter_08::createPowerSet(set1, testPowerSet); - REQUIRE(testPowerSet == powerSet1); -}; - -TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ - REQUIRE(chapter_08::recursiveMultiply(1, 1) == 1); - REQUIRE(chapter_08::recursiveMultiply(1, 2) == 2); - REQUIRE(chapter_08::recursiveMultiply(0, 1) == 0); - REQUIRE(chapter_08::recursiveMultiply(9, 10) == 90); - REQUIRE(chapter_08::recursiveMultiply(9, 11) == 99); - REQUIRE(chapter_08::recursiveMultiply(12, 12) == 144); -} - -TEST_CASE("Chapter 08 - Problem 07 - permutationsNoDups()", "test") { - std::unordered_set actual1 = {}; - std::unordered_set actual2 = {}; - std::unordered_set actual3 = {}; - std::unordered_set actual4 = {}; - std::unordered_set expected1 = {"a"}; - std::unordered_set expected2 = {"al", "la"}; - std::unordered_set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; - std::unordered_set expected4 = {"xela", "exla", "elxa", "elax", - "xlea", "lxea", "lexa", "leax", - "xlae", "lxae", "laxe", "laex", - "xeal", "exal", "eaxl", "ealx", - "xael", "axel", "aexl", "aelx", - "xale", "axle", "alxe", "alex"}; - chapter_08::permutationsNoDups("a", actual1); - chapter_08::permutationsNoDups("al", actual2); - chapter_08::permutationsNoDups("ale", actual3); - chapter_08::permutationsNoDups("alex", actual4); - REQUIRE(actual1 == expected1); - REQUIRE(actual2 == expected2); - REQUIRE(actual3 == expected3); - REQUIRE(actual4 == expected4); -} - -TEST_CASE("Chapter 08 - Problem 08 - permutationsWithDups()", "test") { - std::unordered_set actual1 = {}; - std::unordered_set actual2 = {}; - std::unordered_set actual3 = {}; - std::unordered_set expected1 = {"ala", "laa", "aal"}; - std::unordered_set expected2 = {"aala", "alaa", "alaa", "laaa", "aala", "aaal"}; - std::unordered_set expected3 = {"xela", "exla", "elxa", "elax", - "xlea", "lxea", "lexa", "leax", - "xlae", "lxae", "laxe", "laex", - "xeal", "exal", "eaxl", "ealx", - "xael", "axel", "aexl", "aelx", - "xale", "axle", "alxe", "alex"}; - chapter_08::permutationsWithDups("ala", actual1); - chapter_08::permutationsWithDups("alaa", actual2); - chapter_08::permutationsWithDups("alex", actual3); - REQUIRE(actual1 == expected1); - REQUIRE(actual2 == expected2); - REQUIRE(actual3 == expected3); -} - -TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ - Eigen::MatrixXi image(6, 6); - image << 0, 1, 1, 0, 0, 3, - 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 0, 2, - 0, 0, 0, 0, 2, 2, - 0, 2, 2, 2, 2, 2, - 0, 0, 0, 2, 2, 2; - Eigen::MatrixXi zerosFilled(6, 6); - zerosFilled << 0, 1, 1, 5, 5, 3, - 1, 1, 1, 1, 5, 5, - 5, 1, 1, 5, 5, 2, - 5, 5, 5, 5, 2, 2, - 5, 2, 2, 2, 2, 2, - 5, 5, 5, 2, 2, 2; - Eigen::MatrixXi onesFilled(6, 6); - onesFilled << 0, 5, 5, 0, 0, 3, - 5, 5, 5, 5, 0, 0, - 0, 5, 5, 0, 0, 2, - 0, 0, 0, 0, 2, 2, - 0, 2, 2, 2, 2, 2, - 0, 0, 0, 2, 2, 2; - Eigen::MatrixXi twosFilled(6, 6); - twosFilled << 0, 1, 1, 0, 0, 3, - 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 0, 5, - 0, 0, 0, 0, 5, 5, - 0, 5, 5, 5, 5, 5, - 0, 0, 0, 5, 5, 5; - Eigen::MatrixXi threeFilled(6, 6); - threeFilled << 0, 1, 1, 0, 0, 5, - 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 0, 2, - 0, 0, 0, 0, 2, 2, - 0, 2, 2, 2, 2, 2, - 0, 0, 0, 2, 2, 2; - Eigen::MatrixXi expectedZerosFilled = image; - Eigen::MatrixXi expectedOnesFilled = image; - Eigen::MatrixXi expectedTwosFilled = image; - Eigen::MatrixXi expectedThreeFilled = image; - chapter_08::paintFill(expectedZerosFilled, Eigen::Vector2i(2, 0), 5); - chapter_08::paintFill(expectedOnesFilled, Eigen::Vector2i(1, 2), 5); - chapter_08::paintFill(expectedTwosFilled, Eigen::Vector2i(4, 3), 5); - chapter_08::paintFill(expectedThreeFilled, Eigen::Vector2i(0, 5), 5); - REQUIRE(zerosFilled.isApprox(expectedZerosFilled)); - REQUIRE(onesFilled.isApprox(expectedOnesFilled)); - REQUIRE(twosFilled.isApprox(expectedTwosFilled)); - REQUIRE(threeFilled.isApprox(expectedThreeFilled)); -} - -TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ - int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly - int B[5] = {3, 6, 9, 12, 15}; - int lastA = 4; // index of last item placed in A - int lastB = 4; // index of last item placed in B - int C[10] = {3, 5, 5, 6, 9, 10, 10, 12, 15, 15}; - chapter_10::sortedMerge(&A[0], lastA, &B[0], lastB); - for (int i = 0; i < 10; i++){ - REQUIRE(A[i] == C[i]); - } - - - int D[10] = {5, 5, 10, 10}; // remainder of uninitialized values set to zero implicitly - int E[6] = {3, 6, 9, 12, 15, 15}; - int lastD = 3; // index of last item placed in D - int lastE = 5; // index of last item placed in E - chapter_10::sortedMerge(&D[0], lastD, &E[0], lastE); - for (int i = 0; i < 10; i++){ - REQUIRE(D[i] == C[i]); - } -} - -TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ - char s1[] = "Alex"; - char s1Rev[] = "xelA"; - char s2[] = "a"; - char s2Rev[] = "a"; - chapter_12::reverse(&s1[0]); - chapter_12::reverse(&s2[0]); - // strcmp returns 0 if the 2 strings are equal. - REQUIRE(strcmp(&s1[0], &s1Rev[0]) == 0); - REQUIRE(strcmp(&s2[0], &s2Rev[0]) == 0); -} - -TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ - std::vector targetVector = {1,2,3,4,5,6,7}; - chapter_02::SinglyLinkedNode* head = chapter_02::vectorToList(targetVector); - chapter_02::SinglyLinkedNode* copy = chapter_12::copyNode(head); - REQUIRE(targetVector == chapter_02::listToVector(copy)); // check that the values contained in nodes are identical - // Check that the pointers in the head linked list are *not* the same as the pointers in the copy likned list - // This is to verify a copy was actually made. - while (head != nullptr && copy != nullptr){ - REQUIRE(head != copy); - head = head->getNext(); - copy = copy->getNext(); - } -} - -TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ - Eigen::MatrixXd input1(4, 4); - input1 << 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1; - Eigen::MatrixXd output1(4, 4); - output1 << 1, 2, 3, 4, - 2, 4, 6, 8, - 3, 6, 9, 12, - 4, 8, 12, 16; - REQUIRE(output1.isApprox(misc::makeIntegralImage(input1))); - Eigen::MatrixXd output2(4, 4); - output2 << 1, 3, 6, 10, - 3, 9, 18, 30, - 6, 18, 36, 60, - 10, 30, 60, 100; - REQUIRE(output2.isApprox(misc::makeIntegralImage(output1))); -} - -TEST_CASE("Misc Exercises - boxFilter()", "test"){ - -} +// +// 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 testVec = {"a", "b", "c", "d", "e", "f"}; + std::vector expectedVec = {"a", "b", "d", "e", "f"}; + chapter_02::SinglyLinkedNode* testVecHead = chapter_02::vectorToList(testVec); + chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); + // traverse input to find node with content "c" + chapter_02::SinglyLinkedNode* 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 list4 = {"a", "l", "e", "x"}; + std::vector 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* head4 = chapter_02::vectorToList(list4); + chapter_02::SinglyLinkedNode* 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*>(nullptr), static_cast*>(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*>(nullptr) == chapter_02::findLoop(static_cast*>(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*> 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*> 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*>(nullptr), static_cast*>(nullptr))); + REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(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*> vectorOfHeads; + std::vector*> 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> 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> 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> 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 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); + /* + construct disconnected binary tree + 30 + 31 32 + */ + chapter_02::BinaryNode n31(31); + chapter_02::BinaryNode n32(32); + chapter_02::BinaryNode n30(30, &n31, &n32); + + REQUIRE(chapter_04::checkSubtree(&n7, &n15)); + REQUIRE(chapter_04::checkSubtree(&n7, &n7)); + REQUIRE(chapter_04::checkSubtree(&n7, &n21)); + REQUIRE(chapter_04::checkSubtree(&n7, &n4)); + REQUIRE(!chapter_04::checkSubtree(&n7, nullptr)); + REQUIRE(!chapter_04::checkSubtree(&n7, &n30)); + REQUIRE(!chapter_04::checkSubtree(&n7, &n31)); + REQUIRE(!chapter_04::checkSubtree(&n25, &n31)); + REQUIRE(chapter_04::checkSubtree(&n30, &n31)); + REQUIRE(!chapter_04::checkSubtree(nullptr, nullptr)); +} + +TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ + std::vector valuesList = {10, 13, 14, 11, 7, 7, 8, 7, 4, 10}; + chapter_04::RandBinaryNode head(valuesList[0]); + for (int i = 1; i < valuesList.size(); i++) { + head.insert(valuesList[i]); + } + int occurrenceSum4 = 0; + int occurrenceSum7 = 0; + int occurrenceSum10 = 0; + int occurrenceSum13 = 0; + // using 10,000 random samples, assert that occurence of values in random samples approximately + // the same as the occurence of the values in the tree + std::mt19937 gen(0); // standard mersenne_twister_engine seeded with zero + for (int i = 0; i < 10000; i++) { + int randValue = head.getRandomNode(-1, &gen)->getValue(); + switch (randValue){ + case 4 : occurrenceSum4 ++; break; + case 7 : occurrenceSum7 ++; break; + case 10 : occurrenceSum10 ++; break; + case 13 : occurrenceSum13 ++; break; + } + } + REQUIRE(((950 <= occurrenceSum4) && (occurrenceSum4 <= 1050))); + REQUIRE(((2950 <= occurrenceSum7) && (occurrenceSum7 <= 3050))); + REQUIRE(((1950 <= occurrenceSum10) && (occurrenceSum10 <= 2050))); + REQUIRE(((950 <= occurrenceSum13) && (occurrenceSum13 <= 1050))); +} + +TEST_CASE("Chapter 04 - Problem 12 - pathsWithSum()", "test"){ + /* + construct binary tree like in textbook example + 10 + 5 -3 + 3 1 __ 11 + 3 -2 __ 2 + */ + // leaf nodes at depth = 3 + chapter_02::BinaryNode n3_leaf(3); + chapter_02::BinaryNode n_minus2(-2); + chapter_02::BinaryNode n2(2); + // nodes at depth = 2 + chapter_02::BinaryNode n3(3, &n3_leaf, &n_minus2); + chapter_02::BinaryNode n1(1, nullptr, &n2); + chapter_02::BinaryNode n11(11); + // nodes at depth = 1 + chapter_02::BinaryNode n5(5, &n3, &n1); + chapter_02::BinaryNode n_minus3(-3, nullptr, &n11); + // root node at depth = 0 + chapter_02::BinaryNode n10(10, &n5, &n_minus3); + // count paths that sum to 8 + REQUIRE(3 == chapter_04::pathsWithSum(8, &n10)); +} + +TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ + REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); +} + +TEST_CASE("Chapter 05 - Problem 02 - binaryToString()", "test") { + std::string binary_string_1 = ""; + std::string binary_string_2 = ""; + std::string binary_string_3 = ""; + std::string binary_string_4 = ""; + REQUIRE(chapter_05::binaryToString(0.5, binary_string_1) == 0); + REQUIRE(chapter_05::binaryToString(0.25, binary_string_2) == 0); + REQUIRE(chapter_05::binaryToString(1.5, binary_string_3) == -1); + REQUIRE(chapter_05::binaryToString(0.722, binary_string_4) == 0); + REQUIRE(binary_string_1 == "0.1"); + REQUIRE(binary_string_2 == "0.01"); + REQUIRE(binary_string_3 == ""); + REQUIRE(binary_string_4 == "0.10111000110101001111110111110011"); // needs double precision to work +} + +TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { + REQUIRE(chapter_05::flipBitToWin(1775) == 8); + REQUIRE(chapter_05::flipBitToWin(0b0000) == 1); + REQUIRE(chapter_05::flipBitToWin(0b1011) == 4); + REQUIRE(chapter_05::flipBitToWin(0b1010111) == 5); + REQUIRE(chapter_05::flipBitToWin(0b1110101) == 5); + REQUIRE(chapter_05::flipBitToWin(0b00) == 1); + REQUIRE(chapter_05::flipBitToWin(0b10) == 2); +} + +TEST_CASE("Chapter 05 - Problem 04 - nextNumber()", "test"){ + /* + //REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); + REQUIRE(chapter_05::getNext(0b0100) == 0b1000); + //REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); + REQUIRE(chapter_05::getNext(0b0101) == 0b0110); + //REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(0b1111) == 0b10111); // add an extra digit + //REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible + //REQUIRE(chapter_05::getPrev(0b1001) == 0b0101); + REQUIRE(chapter_05::getNext(0b1001) == 0b1010); + */ +} + +TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ + REQUIRE(chapter_05::conversion(0b11001100, 0b11110000) == 4); + REQUIRE(chapter_05::conversion(29, 15) == 2); +} + +TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ + REQUIRE(chapter_05::pairwiseSwap(0b10101010) == 0b01010101); + REQUIRE(chapter_05::pairwiseSwap(0b11110000) == 0b11110000); + REQUIRE(chapter_05::pairwiseSwap(0b110) == 0b1001); +} + +TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ + REQUIRE(chapter_08::tripleStep(3) == 4); + REQUIRE(chapter_08::tripleStep(4) == 7); + REQUIRE(chapter_08::tripleStep(5) == 13); +} + +TEST_CASE("Chapter 08 - Problem 02 - robotGrid()", "test"){ + + Eigen::MatrixXd maze(5, 5); + maze << 1, 1, 1, 0, 1, + 0, 0, 1, 1, 1, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1; + std::vector expectedPath = {Eigen::Vector2d(0,0), + Eigen::Vector2d(0,1), + Eigen::Vector2d(0,2), + Eigen::Vector2d(1,2), + Eigen::Vector2d(2,2), + Eigen::Vector2d(3,2), + Eigen::Vector2d(4,2), + Eigen::Vector2d(4,3), + Eigen::Vector2d(4,4)}; + std::vector path; + REQUIRE(chapter_08::robotGrid(maze, path)); + REQUIRE(path == expectedPath); +} + +TEST_CASE("Chapter 08 - Problem 03 - magicIndex()", "test"){ + std::vector noMagicIndex = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::vector magicIndex5 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::vector magicIndex7 = {-40, -20, -1, 1, 2, 3, 5, 7, 9, 12, 13}; + REQUIRE(chapter_08::magicIndex(noMagicIndex) == -1); + REQUIRE(chapter_08::magicIndex(magicIndex5) == 5); + REQUIRE(chapter_08::magicIndex(magicIndex7) == 7); +} + +TEST_CASE("Chapter 08 - Problem 04 - powerSet()", "test"){ + std::vector set123 = {1, 2, 3}; + std::vector set12 = {1, 2}; + std::vector set13 = {1, 3}; + std::vector set23 = {2, 3}; + std::vector set1 = {1}; + std::vector set2 = {2}; + std::vector set3 = {3}; + std::vector emptySet = {}; + + std::vector> powerSet123 = {emptySet, set1, set2, set12, set3, set13, set23, set123}; + std::vector> powerSet12 = {emptySet, set1, set2, set12}; + std::vector> powerSet1 = {emptySet, set1}; + + std::vector> testPowerSet = {}; + chapter_08::createPowerSet(set123, testPowerSet); + REQUIRE(testPowerSet == powerSet123); + testPowerSet = {}; + chapter_08::createPowerSet(set12, testPowerSet); + REQUIRE(testPowerSet == powerSet12); + testPowerSet = {}; + chapter_08::createPowerSet(set1, testPowerSet); + REQUIRE(testPowerSet == powerSet1); +}; + +TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ + REQUIRE(chapter_08::recursiveMultiply(1, 1) == 1); + REQUIRE(chapter_08::recursiveMultiply(1, 2) == 2); + REQUIRE(chapter_08::recursiveMultiply(0, 1) == 0); + REQUIRE(chapter_08::recursiveMultiply(9, 10) == 90); + REQUIRE(chapter_08::recursiveMultiply(9, 11) == 99); + REQUIRE(chapter_08::recursiveMultiply(12, 12) == 144); +} + +TEST_CASE("Chapter 08 - Problem 07 - permutationsNoDups()", "test") { + std::unordered_set actual1 = {}; + std::unordered_set actual2 = {}; + std::unordered_set actual3 = {}; + std::unordered_set actual4 = {}; + std::unordered_set expected1 = {"a"}; + std::unordered_set expected2 = {"al", "la"}; + std::unordered_set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; + std::unordered_set expected4 = {"xela", "exla", "elxa", "elax", + "xlea", "lxea", "lexa", "leax", + "xlae", "lxae", "laxe", "laex", + "xeal", "exal", "eaxl", "ealx", + "xael", "axel", "aexl", "aelx", + "xale", "axle", "alxe", "alex"}; + chapter_08::permutationsNoDups("a", actual1); + chapter_08::permutationsNoDups("al", actual2); + chapter_08::permutationsNoDups("ale", actual3); + chapter_08::permutationsNoDups("alex", actual4); + REQUIRE(actual1 == expected1); + REQUIRE(actual2 == expected2); + REQUIRE(actual3 == expected3); + REQUIRE(actual4 == expected4); +} + +TEST_CASE("Chapter 08 - Problem 08 - permutationsWithDups()", "test") { + std::unordered_set actual1 = {}; + std::unordered_set actual2 = {}; + std::unordered_set actual3 = {}; + std::unordered_set expected1 = {"ala", "laa", "aal"}; + std::unordered_set expected2 = {"aala", "alaa", "alaa", "laaa", "aala", "aaal"}; + std::unordered_set expected3 = {"xela", "exla", "elxa", "elax", + "xlea", "lxea", "lexa", "leax", + "xlae", "lxae", "laxe", "laex", + "xeal", "exal", "eaxl", "ealx", + "xael", "axel", "aexl", "aelx", + "xale", "axle", "alxe", "alex"}; + chapter_08::permutationsWithDups("ala", actual1); + chapter_08::permutationsWithDups("alaa", actual2); + chapter_08::permutationsWithDups("alex", actual3); + REQUIRE(actual1 == expected1); + REQUIRE(actual2 == expected2); + REQUIRE(actual3 == expected3); +} + +TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ + Eigen::MatrixXi image(6, 6); + image << 0, 1, 1, 0, 0, 3, + 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 2, + 0, 0, 0, 0, 2, 2, + 0, 2, 2, 2, 2, 2, + 0, 0, 0, 2, 2, 2; + Eigen::MatrixXi zerosFilled(6, 6); + zerosFilled << 0, 1, 1, 5, 5, 3, + 1, 1, 1, 1, 5, 5, + 5, 1, 1, 5, 5, 2, + 5, 5, 5, 5, 2, 2, + 5, 2, 2, 2, 2, 2, + 5, 5, 5, 2, 2, 2; + Eigen::MatrixXi onesFilled(6, 6); + onesFilled << 0, 5, 5, 0, 0, 3, + 5, 5, 5, 5, 0, 0, + 0, 5, 5, 0, 0, 2, + 0, 0, 0, 0, 2, 2, + 0, 2, 2, 2, 2, 2, + 0, 0, 0, 2, 2, 2; + Eigen::MatrixXi twosFilled(6, 6); + twosFilled << 0, 1, 1, 0, 0, 3, + 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 5, + 0, 0, 0, 0, 5, 5, + 0, 5, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 5; + Eigen::MatrixXi threeFilled(6, 6); + threeFilled << 0, 1, 1, 0, 0, 5, + 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 2, + 0, 0, 0, 0, 2, 2, + 0, 2, 2, 2, 2, 2, + 0, 0, 0, 2, 2, 2; + Eigen::MatrixXi expectedZerosFilled = image; + Eigen::MatrixXi expectedOnesFilled = image; + Eigen::MatrixXi expectedTwosFilled = image; + Eigen::MatrixXi expectedThreeFilled = image; + chapter_08::paintFill(expectedZerosFilled, Eigen::Vector2i(2, 0), 5); + chapter_08::paintFill(expectedOnesFilled, Eigen::Vector2i(1, 2), 5); + chapter_08::paintFill(expectedTwosFilled, Eigen::Vector2i(4, 3), 5); + chapter_08::paintFill(expectedThreeFilled, Eigen::Vector2i(0, 5), 5); + REQUIRE(zerosFilled.isApprox(expectedZerosFilled)); + REQUIRE(onesFilled.isApprox(expectedOnesFilled)); + REQUIRE(twosFilled.isApprox(expectedTwosFilled)); + REQUIRE(threeFilled.isApprox(expectedThreeFilled)); +} + +TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ + int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly + int B[5] = {3, 6, 9, 12, 15}; + int lastA = 4; // index of last item placed in A + int lastB = 4; // index of last item placed in B + int C[10] = {3, 5, 5, 6, 9, 10, 10, 12, 15, 15}; + chapter_10::sortedMerge(&A[0], lastA, &B[0], lastB); + for (int i = 0; i < 10; i++){ + REQUIRE(A[i] == C[i]); + } + + + int D[10] = {5, 5, 10, 10}; // remainder of uninitialized values set to zero implicitly + int E[6] = {3, 6, 9, 12, 15, 15}; + int lastD = 3; // index of last item placed in D + int lastE = 5; // index of last item placed in E + chapter_10::sortedMerge(&D[0], lastD, &E[0], lastE); + for (int i = 0; i < 10; i++){ + REQUIRE(D[i] == C[i]); + } +} + +TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ + char s1[] = "Alex"; + char s1Rev[] = "xelA"; + char s2[] = "a"; + char s2Rev[] = "a"; + chapter_12::reverse(&s1[0]); + chapter_12::reverse(&s2[0]); + // strcmp returns 0 if the 2 strings are equal. + REQUIRE(strcmp(&s1[0], &s1Rev[0]) == 0); + REQUIRE(strcmp(&s2[0], &s2Rev[0]) == 0); +} + +TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ + std::vector targetVector = {1,2,3,4,5,6,7}; + chapter_02::SinglyLinkedNode* head = chapter_02::vectorToList(targetVector); + chapter_02::SinglyLinkedNode* copy = chapter_12::copyNode(head); + REQUIRE(targetVector == chapter_02::listToVector(copy)); // check that the values contained in nodes are identical + // Check that the pointers in the head linked list are *not* the same as the pointers in the copy likned list + // This is to verify a copy was actually made. + while (head != nullptr && copy != nullptr){ + REQUIRE(head != copy); + head = head->getNext(); + copy = copy->getNext(); + } +} + +TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ + Eigen::MatrixXd input1(4, 4); + input1 << 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1; + Eigen::MatrixXd output1(4, 4); + output1 << 1, 2, 3, 4, + 2, 4, 6, 8, + 3, 6, 9, 12, + 4, 8, 12, 16; + REQUIRE(output1.isApprox(misc::makeIntegralImage(input1))); + Eigen::MatrixXd output2(4, 4); + output2 << 1, 3, 6, 10, + 3, 9, 18, 30, + 6, 18, 36, 60, + 10, 30, 60, 100; + REQUIRE(output2.isApprox(misc::makeIntegralImage(output1))); +} + +TEST_CASE("Misc Exercises - boxFilter()", "test"){ + +} diff --git a/tests.py b/tests.py index 2aff5cc..aaba73d 100644 --- a/tests.py +++ b/tests.py @@ -849,11 +849,12 @@ def test_problem_5_4(self): self.assertEqual(p_5_4.get_next(['0', '1', '0', '0']), ['1', '0', '0', '0']) self.assertEqual(p_5_4.get_prev(['0', '1', '0', '1']), ['0', '0', '1', '1']) self.assertEqual(p_5_4.get_next(['0', '1', '0', '1']), ['0', '1', '1', '0']) - self.assertEqual(p_5_4.get_prev(['1', '1', '1', '1']), None) + self.assertEqual(p_5_4.get_prev(['1', '1', '1', '1']), -1) self.assertEqual(p_5_4.get_next(['1', '1', '1', '1']), ['1', '0', '1', '1', '1']) - self.assertEqual(p_5_4.get_prev(['0', '0', '0', '0']), None) - self.assertEqual(p_5_4.get_next(['0', '0', '0', '0']), None) + self.assertEqual(p_5_4.get_prev(['0', '0', '0', '0']), -1) + self.assertEqual(p_5_4.get_next(['0', '0', '0', '0']), -1) self.assertEqual(p_5_4.get_prev(['1', '0', '0', '1']), ['0', '1', '0', '1']) + self.assertEqual(p_5_4.get_next(['1', '0', '0', '1']), ['1', '0', '1', '0']) def test_problem_5_6(self): self.assertEqual(p_5_6.conversion(0b11001100, 0b11110000), 4) From 86da66f14e19ea1685c5ba1ce0aa68faefd89d40 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 19 May 2019 19:10:25 -0800 Subject: [PATCH 055/176] use only unix and mac line endings --- .gitignore | 18 +- CMakeLists.txt | 90 +- README.md | 324 +-- .../problem_03_05_sortStack.h | 98 +- .../problem_03_06_animalShelter.cpp | 140 +- .../problem_04_06_successor.h | 98 +- .../problem_04_07_buildOrder.cpp | 172 +- .../problem_04_07_buildOrder.h | 22 +- .../problem_04_12_pathsWithSum.h | 152 +- .../problem_05_03_flipBitToWin.cpp | 112 +- .../problem_05_03_flipBitToWin.h | 16 +- .../problem_05_04_nextNumber.cpp | 90 +- .../problem_05_04_nextNumber.h | 14 +- .../problem_08_07_permutationsNoDups.cpp | 152 +- tests.cpp | 2214 ++++++++--------- 15 files changed, 1856 insertions(+), 1856 deletions(-) diff --git a/.gitignore b/.gitignore index 777c102..a6c00e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ -.idea/ -*pycache* -*.pyc -.coverage -build -cmake-build-debug -CppProperties.json -.vs -**/.DS_Store +.idea/ +*pycache* +*.pyc +.coverage +build +cmake-build-debug +CppProperties.json +.vs +**/.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c2623e..0a3a94f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,45 +1,45 @@ -cmake_minimum_required(VERSION 3.2) -project(ctci) -set(CMAKE_CXX_STANDARD 11) -# include source folder -include_directories(cpp_solutions) -# include Eigen -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_solutions/third_party/eigen) - -# set source files -set(SOURCE_FILES - tests.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_04_palindromePermutation.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp - cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp - # chapter 2 .cpp files not included because they are template functions implemented in .h files - # chapter 3 .cpp files not included because they are template functions implemented in .h files - cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp - # chapter 4 .cpp files not included because they are template functions implemented in .h files - cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp - cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp - cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp - # problem 10.01 not included because it is a template function implemented in .h file - cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp - # problem 12.08 not included because it is a template function implemented in .h file - cpp_solutions/misc_exercises/integralImage.cpp) -# create executable -add_executable(tests ${SOURCE_FILES}) +cmake_minimum_required(VERSION 3.2) +project(ctci) +set(CMAKE_CXX_STANDARD 11) +# include source folder +include_directories(cpp_solutions) +# include Eigen +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_solutions/third_party/eigen) + +# set source files +set(SOURCE_FILES + tests.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_04_palindromePermutation.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp + cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp + # chapter 2 .cpp files not included because they are template functions implemented in .h files + # chapter 3 .cpp files not included because they are template functions implemented in .h files + cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp + # chapter 4 .cpp files not included because they are template functions implemented in .h files + cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp + cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp + # problem 10.01 not included because it is a template function implemented in .h file + cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp + # problem 12.08 not included because it is a template function implemented in .h file + cpp_solutions/misc_exercises/integralImage.cpp) +# create executable +add_executable(tests ${SOURCE_FILES}) diff --git a/README.md b/README.md index 4f5e460..c39f123 100644 --- a/README.md +++ b/README.md @@ -1,162 +1,162 @@ - ## Cracking The Coding Interview Solutions with Automated Unit Tests - - * :white_check_mark: C++ Solutions - * :white_check_mark: Python Solutions - * :white_check_mark: Automated Unit Tests - * :white_check_mark: Active Development - * :white_check_mark: Multiplatform Support: Mac, Linux, and Windows - -### Introduction -This repo contains C++ and Python solutions for Gayle Laakmann McDowell's [*Cracking the Coding Interview 6th Edition*](http://a.co/baneyGe). -Admittedly, there are other GitHub repositories with solutions for this book. *But -how do you know that their code is actually correct?* If it's untested, then you don't! - -In this project, every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch), -and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html). -We enforce test correctness automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) -ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is -the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can -reference and contribute solutions with confidence. - -### Table of Contents -#### [C++ Solutions](cpp_solutions): -0. [C++ Unit Tests](tests.cpp) -1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. -2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. -4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `5 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. -7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. -11. Chapter 11 - Testing: N/A -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` -13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` -16. Chapter 16 - Moderate: `0 / 26` complete. -17. Chapter 17 - Hard: `0 / 26` complete. - -C++ Total: `48` solutions. - -#### [Python Solutions](python_solutions): -0. [Python Unit tests](tests.py) -1. [Chapter 1 - Arrays and Strings](python_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. -2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. -3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. -4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. -7. Chapter 7 - Object Oriented Design: `0 / 12` complete. -8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. -11. Chapter 11 - Testing: N/A -12. Chapter 12 - C and C++: N/A -13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. -17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. - -Python Total: `56` solutions. - -##### Grand Total: `104` unique solutions. - -### Building: -#### Mac: -Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: - - git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git ctci - cd ctci - make configure-mac - -#### Ubuntu: - - git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git - cd ctci - make configure-ubuntu - -#### Windows: -For Windows users, I recommend developing this project using the [Windows Subsystem -for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) feature -of Windows 10 and then following the Ubuntu build and testing instructions inside WSL. -This recommendation is due to the use of Ubuntu, CMake, and makefile based build and execution -systems on the servers that automatically test changes to the code. For more on Windows -development, see the `Appendix` section at the end of this page. - -### Testing: -Testing is the most important part of this project: *only* -the unit tests define the problem being solved. In the root -directory, execute the following to run all tests in Python and C++: - - make test - -`make test` is the command I use most while developing this project. My workflow follows: - -1. I read a problem and encode the problem definition by implementing its unit tests. -2. I execute `make test` to see where the project fails to satisfy the unit tests. -3. I add to the implementation of the problem solution until `make test` succeeds. - -### Optional: Generating a Test Coverage % Report Locally (Python support only): -This will show exactly which lines are not covered by tests in each Python source file: - - pip install coverage - make test_coverage - -### Contributing -The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. -I definitely need help, so PRs are welcome. There is much to do because each solution needs its own -small dataset and infrastructure in order to be tested. Here are some ways you can help: - -1. Fixing bugs :bug:. -2. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). -3. Adding more unit tests to increase the test coverage %. -4. Implementing automated C++ test coverage measurement using [gcov](http://gcc.gnu.org/onlinedocs/gcc/Gcov.html). -5. Integrating automated test coverage % reporting for both Python and C++ via [Coveralls](Coveralls.io). -6. Adding prose solution descriptions for problems that don't have them. - -If you have any contributions, please make a PR to the `master` branch. Feel free to message me for clarification on any of -the above items. - -### Appendix: Windows Development -On my own Windows machine, I develop using [CLion](https://www.jetbrains.com/clion/) running -natively in Windows and test the code using `make test` in a WSL terminal window. -For users who do not want to use WSL, I have developed the build and test methodology below: - -#### Building -The project can be developed purely on Windows without WSL by using Visual Studio 2017. -First clone the code: - - git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git - cd ctci - git submodule update --init - -Then, install Python3 and numpy using your method of choice. I prefer installing Python3 and pip3 from -the [official website](https://www.python.org/downloads/) then installing numpy via pip: - - pip install numpy - -Then, open the project in Visual Studio 2017 which has CMake support. -I've found that best the workflow is to use Visual Studio to edit code and use debugging functionality. Before -building the code, you must follow [these instructions](https://stackoverflow.com/a/12954908) -to tell Visual Studio to download PDBs it needs. Additionally, [this article](https://blogs.msdn.microsoft.com/vcblog/2016/10/05/cmake-support-in-visual-studio/) -describes Visual Studio CMake support in more detail if you're interested. A CMakeSettings.json file in the root project -directory sets the location of the Visual Studio build folder to be inside the root folder of the project. - -#### Testing -Running the tests and seeing their output is best done from a PowerShell window since VisualStudio in CMake mode -does *not* allow the console output of the `tests.exe` and `tests.py` files to remain visible even when pressing -CTRL + F5 as described [in this post](https://stackoverflow.com/a/1775870) which applies to -"normal" Visual Studio use. I am monitoring the situation re: Visual Studio, and when I find better solutions -I will implement them or post them. If you know of something better, please contact me. - -In the meantime, from the project root directory, you can run the Python tests using ... - - python tests.py - -... and you can run the C++ tests using ... - - .\build\x64-Debug\tests.exe + ## Cracking The Coding Interview Solutions with Automated Unit Tests + + * :white_check_mark: C++ Solutions + * :white_check_mark: Python Solutions + * :white_check_mark: Automated Unit Tests + * :white_check_mark: Active Development + * :white_check_mark: Multiplatform Support: Mac, Linux, and Windows + +### Introduction +This repo contains C++ and Python solutions for Gayle Laakmann McDowell's [*Cracking the Coding Interview 6th Edition*](http://a.co/baneyGe). +Admittedly, there are other GitHub repositories with solutions for this book. *But +how do you know that their code is actually correct?* If it's untested, then you don't! + +In this project, every C++ solution has unit tests using the [C++ Catch framework](https://github.com/philsquared/Catch), +and every Python solution has unit tests using the [Python unittest framework](https://docs.python.org/3.6/library/unittest.html). +We enforce test correctness automatically using [continuous integration servers](https://travis-ci.org/alexhagiopol/cracking-the-coding-interview) +ensuring that the solutions are made of *living* code that gets executed and tested on every single commit. To my knowledge, this is +the Internet's only solutions repository with this level of testing rigor: >90% automated test coverage means you can +reference and contribute solutions with confidence. + +### Table of Contents +#### [C++ Solutions](cpp_solutions): +0. [C++ Unit Tests](tests.cpp) +1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. +2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. +3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. +4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. +5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `5 / 7` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. +7. Chapter 7 - Object Oriented Design: `0 / 12` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. +9. Chapter 9 - System Design and Scalability: N/A +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +11. Chapter 11 - Testing: N/A +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` +13. Chapter 13 - Java: N/A +14. Chapter 14 - Databases: N/A +15. Chapter 15 - Threads and Locks: `0 / 4` +16. Chapter 16 - Moderate: `0 / 26` complete. +17. Chapter 17 - Hard: `0 / 26` complete. + +C++ Total: `48` solutions. + +#### [Python Solutions](python_solutions): +0. [Python Unit tests](tests.py) +1. [Chapter 1 - Arrays and Strings](python_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. +2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. +3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. +4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. +5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. +7. Chapter 7 - Object Oriented Design: `0 / 12` complete. +8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. +9. Chapter 9 - System Design and Scalability: N/A +10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +11. Chapter 11 - Testing: N/A +12. Chapter 12 - C and C++: N/A +13. Chapter 13 - Java: N/A +14. Chapter 14 - Databases: N/A +15. Chapter 15 - Threads and Locks: `0 / 4` complete. +16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. +17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. + +Python Total: `56` solutions. + +##### Grand Total: `104` unique solutions. + +### Building: +#### Mac: +Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: + + git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git ctci + cd ctci + make configure-mac + +#### Ubuntu: + + git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git + cd ctci + make configure-ubuntu + +#### Windows: +For Windows users, I recommend developing this project using the [Windows Subsystem +for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/install-win10) feature +of Windows 10 and then following the Ubuntu build and testing instructions inside WSL. +This recommendation is due to the use of Ubuntu, CMake, and makefile based build and execution +systems on the servers that automatically test changes to the code. For more on Windows +development, see the `Appendix` section at the end of this page. + +### Testing: +Testing is the most important part of this project: *only* +the unit tests define the problem being solved. In the root +directory, execute the following to run all tests in Python and C++: + + make test + +`make test` is the command I use most while developing this project. My workflow follows: + +1. I read a problem and encode the problem definition by implementing its unit tests. +2. I execute `make test` to see where the project fails to satisfy the unit tests. +3. I add to the implementation of the problem solution until `make test` succeeds. + +### Optional: Generating a Test Coverage % Report Locally (Python support only): +This will show exactly which lines are not covered by tests in each Python source file: + + pip install coverage + make test_coverage + +### Contributing +The goal of this project is to write a tested Python and C++ solution for every problem in the 6th edition of the textbook. +I definitely need help, so PRs are welcome. There is much to do because each solution needs its own +small dataset and infrastructure in order to be tested. Here are some ways you can help: + +1. Fixing bugs :bug:. +2. Solving or improving solutions to problems in either language (see the completion progress in the table of contents). +3. Adding more unit tests to increase the test coverage %. +4. Implementing automated C++ test coverage measurement using [gcov](http://gcc.gnu.org/onlinedocs/gcc/Gcov.html). +5. Integrating automated test coverage % reporting for both Python and C++ via [Coveralls](Coveralls.io). +6. Adding prose solution descriptions for problems that don't have them. + +If you have any contributions, please make a PR to the `master` branch. Feel free to message me for clarification on any of +the above items. + +### Appendix: Windows Development +On my own Windows machine, I develop using [CLion](https://www.jetbrains.com/clion/) running +natively in Windows and test the code using `make test` in a WSL terminal window. +For users who do not want to use WSL, I have developed the build and test methodology below: + +#### Building +The project can be developed purely on Windows without WSL by using Visual Studio 2017. +First clone the code: + + git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git + cd ctci + git submodule update --init + +Then, install Python3 and numpy using your method of choice. I prefer installing Python3 and pip3 from +the [official website](https://www.python.org/downloads/) then installing numpy via pip: + + pip install numpy + +Then, open the project in Visual Studio 2017 which has CMake support. +I've found that best the workflow is to use Visual Studio to edit code and use debugging functionality. Before +building the code, you must follow [these instructions](https://stackoverflow.com/a/12954908) +to tell Visual Studio to download PDBs it needs. Additionally, [this article](https://blogs.msdn.microsoft.com/vcblog/2016/10/05/cmake-support-in-visual-studio/) +describes Visual Studio CMake support in more detail if you're interested. A CMakeSettings.json file in the root project +directory sets the location of the Visual Studio build folder to be inside the root folder of the project. + +#### Testing +Running the tests and seeing their output is best done from a PowerShell window since VisualStudio in CMake mode +does *not* allow the console output of the `tests.exe` and `tests.py` files to remain visible even when pressing +CTRL + F5 as described [in this post](https://stackoverflow.com/a/1775870) which applies to +"normal" Visual Studio use. I am monitoring the situation re: Visual Studio, and when I find better solutions +I will implement them or post them. If you know of something better, please contact me. + +In the meantime, from the project root directory, you can run the Python tests using ... + + python tests.py + +... and you can run the C++ tests using ... + + .\build\x64-Debug\tests.exe diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h index 1a159ee..37be33e 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_05_sortStack.h @@ -1,49 +1,49 @@ -/* -Chapter 03 - Problem 05 - Sort Stack - -Problem Statement: -Write a program to sort a stack such that the smallest items are on the top. You can use an -additional temporary stack, but you may not copy the elements into any other data structure -(such as an array). The stack supports the following operations: push(), pop(), peek(), and isEmpty(). - -Solution: -We sort a stack with N items by using an additional stack of up to size N and a single -temporary variable of size 1. We start with a full "left" stack and an empty "right" -stack. We first (1) pop every item off of the left stack and push each item onto the right -stack. During step (1), we fill the temporary variable with the smallest item seen so far. -In step (2), we pop every item off of the right stack back onto the left stack. However, when we encounter -the smallest item, we do *not* pop it back onto the left stack and instead just keep track of it with -the temporary variable. Once the right stack is empty, we pop the smallest item into the right stack -thus establishing the "first" item of the new, sorted stack. We then (3) repeat steps (1) and (2) while ignoring -the already sorted items in the right stack. - -Time complexity: O(N) -Space complexity: O(N) -*/ - -namespace chapter_03 { - template - void sortStack(chapter_03::Stack& stack) { - chapter_03::Stack rightStack; - T temp = static_cast(std::numeric_limits::max()); - int stackSize = stack.stackSize(); - for (int i = 0; i < stackSize; i++) { - // transfer from left to right - while (!stack.isEmpty()) { - T currentItemLeft = stack.pop(); - if (currentItemLeft <= temp) temp = currentItemLeft; - rightStack.push(currentItemLeft); - } - // transfer from right to left - for (int j = 0; j < stackSize - i; j ++) { // ignore sorted items - T currentItemRight = rightStack.pop(); - if (currentItemRight != temp) stack.push(currentItemRight); - } - rightStack.push(temp); // place sorted item - temp = static_cast(std::numeric_limits::max()); - } - while(!rightStack.isEmpty()){ - stack.push(rightStack.pop()); // copy sorted items to input stack - } - } -} +/* +Chapter 03 - Problem 05 - Sort Stack + +Problem Statement: +Write a program to sort a stack such that the smallest items are on the top. You can use an +additional temporary stack, but you may not copy the elements into any other data structure +(such as an array). The stack supports the following operations: push(), pop(), peek(), and isEmpty(). + +Solution: +We sort a stack with N items by using an additional stack of up to size N and a single +temporary variable of size 1. We start with a full "left" stack and an empty "right" +stack. We first (1) pop every item off of the left stack and push each item onto the right +stack. During step (1), we fill the temporary variable with the smallest item seen so far. +In step (2), we pop every item off of the right stack back onto the left stack. However, when we encounter +the smallest item, we do *not* pop it back onto the left stack and instead just keep track of it with +the temporary variable. Once the right stack is empty, we pop the smallest item into the right stack +thus establishing the "first" item of the new, sorted stack. We then (3) repeat steps (1) and (2) while ignoring +the already sorted items in the right stack. + +Time complexity: O(N) +Space complexity: O(N) +*/ + +namespace chapter_03 { + template + void sortStack(chapter_03::Stack& stack) { + chapter_03::Stack rightStack; + T temp = static_cast(std::numeric_limits::max()); + int stackSize = stack.stackSize(); + for (int i = 0; i < stackSize; i++) { + // transfer from left to right + while (!stack.isEmpty()) { + T currentItemLeft = stack.pop(); + if (currentItemLeft <= temp) temp = currentItemLeft; + rightStack.push(currentItemLeft); + } + // transfer from right to left + for (int j = 0; j < stackSize - i; j ++) { // ignore sorted items + T currentItemRight = rightStack.pop(); + if (currentItemRight != temp) stack.push(currentItemRight); + } + rightStack.push(temp); // place sorted item + temp = static_cast(std::numeric_limits::max()); + } + while(!rightStack.isEmpty()){ + stack.push(rightStack.pop()); // copy sorted items to input stack + } + } +} diff --git a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp index 4ceb4db..ec8a231 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp +++ b/cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp @@ -1,70 +1,70 @@ -#include "problem_03_06_animalShelter.h" - -namespace chapter_03 { - Animal::Animal(const std::string& name, int ID) { - _name = name; - _ID = ID; - _species = Species::none; - } - - Dog::Dog(const std::string& name, int ID) : Animal(name, ID) { - _species = Species::dog; - } - - Cat::Cat(const std::string& name, int ID) : Animal(name, ID) { - _species = Species::cat; - } - - AnimalShelter::AnimalShelter() { - _dogs = Queue(); - _cats = Queue(); - _timestamp = 0; - } - - void AnimalShelter::enqueue(Animal* animal) { - if (animal == nullptr) return; - animal->setID(_timestamp); - _timestamp ++; - if (animal->getSpecies() == Species::cat) { - _cats.push(static_cast(animal)); - } else if (animal->getSpecies() == Species::dog) { - _dogs.push(static_cast(animal)); - } - } - - Cat* AnimalShelter::dequeueCat() { - if (_cats.isEmpty()) { - return nullptr; - } else { - return _cats.pop(); - } - } - - Dog* AnimalShelter::dequeueDog() { - if (_dogs.isEmpty()) { - return nullptr; - } else { - return _dogs.pop(); - } - } - - Animal* AnimalShelter::dequeueAny() { - // if either of the queues is empty, we need to handle - if (_dogs.isEmpty() && _cats.isEmpty()) { - return nullptr; - } else if (_dogs.isEmpty()) { - return dequeueCat(); - } else if (_cats.isEmpty()) { - return dequeueDog(); - } - // return the animal with lowest ID - int dogID = _dogs.peek()->getID(); - int catID = _cats.peek()->getID(); - if (dogID <= catID) { - return dequeueDog(); - } else { - return dequeueCat(); - } - } -} - +#include "problem_03_06_animalShelter.h" + +namespace chapter_03 { + Animal::Animal(const std::string& name, int ID) { + _name = name; + _ID = ID; + _species = Species::none; + } + + Dog::Dog(const std::string& name, int ID) : Animal(name, ID) { + _species = Species::dog; + } + + Cat::Cat(const std::string& name, int ID) : Animal(name, ID) { + _species = Species::cat; + } + + AnimalShelter::AnimalShelter() { + _dogs = Queue(); + _cats = Queue(); + _timestamp = 0; + } + + void AnimalShelter::enqueue(Animal* animal) { + if (animal == nullptr) return; + animal->setID(_timestamp); + _timestamp ++; + if (animal->getSpecies() == Species::cat) { + _cats.push(static_cast(animal)); + } else if (animal->getSpecies() == Species::dog) { + _dogs.push(static_cast(animal)); + } + } + + Cat* AnimalShelter::dequeueCat() { + if (_cats.isEmpty()) { + return nullptr; + } else { + return _cats.pop(); + } + } + + Dog* AnimalShelter::dequeueDog() { + if (_dogs.isEmpty()) { + return nullptr; + } else { + return _dogs.pop(); + } + } + + Animal* AnimalShelter::dequeueAny() { + // if either of the queues is empty, we need to handle + if (_dogs.isEmpty() && _cats.isEmpty()) { + return nullptr; + } else if (_dogs.isEmpty()) { + return dequeueCat(); + } else if (_cats.isEmpty()) { + return dequeueDog(); + } + // return the animal with lowest ID + int dogID = _dogs.peek()->getID(); + int catID = _cats.peek()->getID(); + if (dogID <= catID) { + return dequeueDog(); + } else { + return dequeueCat(); + } + } +} + diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h index 794e52b..4808b01 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_06_successor.h @@ -1,50 +1,50 @@ -/* -Chapter 04 - Problem 06 - Successor - -Problem Statement: -Write an algorithm to find the "next" node (i.e., in-order successor) of a given node in a binary search tree. -You may assume that each node has a link to its parent. - -Solution: -Based on the definition of in order traversal, the successor of a node is determined as follows: - -1. If the target node has a right child, then its successor is the leftmost member of its right subtree. -2. If the target node does not have a right child, then its successor its first ancestor to its right. -3. If nodes described in cases 1 and 2 do not exist, then the node has no successor. - -To check case 1, we check if there is a right subtree then traverse only through the left connection until we reach -the leftmost node and return it. To check case 2, we traverse from the target node up the tree only through -parent connections until we find a the first right ancestor and return it. - -Time complexity: O(N) -Space complexity: O(log(N)) assuming tree is balanced -*/ - -#pragma once -#include "../chapter_02_linked_lists/Node.h" -namespace chapter_04{ - template - chapter_02::BinaryNode* getLeftmostDescendant(chapter_02::BinaryNode* node) { - while(node != nullptr) { - if (node->getLeft() == nullptr) { return node; } - node = node->getLeft(); - } - return node; - } - - template - chapter_02::BinaryNode* getFirstRightAncestor(chapter_02::BinaryNode* node) { - while(node != nullptr) { - if (node->getParent() == nullptr) { return nullptr;} - if (node->getParent()->getLeft() == node) { return node->getParent(); } // a right ancestor is the one whose left child is the current node - node = node->getParent(); - } - return node; - } - - template - chapter_02::BinaryNode* successor(chapter_02::BinaryNode* target) { - chapter_02::BinaryNode* returnPointer = getLeftmostDescendant(target->getRight()); - return returnPointer != nullptr ? returnPointer : getFirstRightAncestor(target); - } +/* +Chapter 04 - Problem 06 - Successor + +Problem Statement: +Write an algorithm to find the "next" node (i.e., in-order successor) of a given node in a binary search tree. +You may assume that each node has a link to its parent. + +Solution: +Based on the definition of in order traversal, the successor of a node is determined as follows: + +1. If the target node has a right child, then its successor is the leftmost member of its right subtree. +2. If the target node does not have a right child, then its successor its first ancestor to its right. +3. If nodes described in cases 1 and 2 do not exist, then the node has no successor. + +To check case 1, we check if there is a right subtree then traverse only through the left connection until we reach +the leftmost node and return it. To check case 2, we traverse from the target node up the tree only through +parent connections until we find a the first right ancestor and return it. + +Time complexity: O(N) +Space complexity: O(log(N)) assuming tree is balanced +*/ + +#pragma once +#include "../chapter_02_linked_lists/Node.h" +namespace chapter_04{ + template + chapter_02::BinaryNode* getLeftmostDescendant(chapter_02::BinaryNode* node) { + while(node != nullptr) { + if (node->getLeft() == nullptr) { return node; } + node = node->getLeft(); + } + return node; + } + + template + chapter_02::BinaryNode* getFirstRightAncestor(chapter_02::BinaryNode* node) { + while(node != nullptr) { + if (node->getParent() == nullptr) { return nullptr;} + if (node->getParent()->getLeft() == node) { return node->getParent(); } // a right ancestor is the one whose left child is the current node + node = node->getParent(); + } + return node; + } + + template + chapter_02::BinaryNode* successor(chapter_02::BinaryNode* target) { + chapter_02::BinaryNode* returnPointer = getLeftmostDescendant(target->getRight()); + return returnPointer != nullptr ? returnPointer : getFirstRightAncestor(target); + } } // namespace chapter_04 \ No newline at end of file diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp index 9d7915b..bdafadc 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp @@ -1,87 +1,87 @@ -/* -Chapter 04 - Problem 07 - Build Order - -Problem Statement: -You are given a list of projects and a list of dependencies (which is a list of pairs of projects, -where the second project is dependent on the first project). All of a project's dependencies must -be built before the project is. Find a build order that will allow the projects to be built. -If there is no valid build order, return an error. - -Solution: -We first represent the projects and build dependencies as vertices and edges in a directed acyclic graph. -We then implement Kahn's algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms - -L ← Empty list that will contain the sorted elements -S ← Set of all nodes with no incoming edge -while S is non-empty do - remove a node n from S - add n to tail of L - for each node m with an edge e from n to m do - remove edge e from the graph - if m has no other incoming edges then - insert m into S -if graph has edges then - return error (graph has at least one cycle) -else - return L (a topologically sorted order) - -Time complexity: O(V + E) where V is the number of vertices in the graph and E is the number of edges. -V can be interpreted as the number of projects and E can be interpreted as the number of dependencies. -Space complexity: O(V) -*/ - -#include "problem_04_07_buildOrder.h" -#include -#include - -namespace chapter_04 { - void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder) { - // convert list of project identifiers to graph nodes - std::vector*> projectsGN = {}; // store pointers to GraphNodes used in topological sort - std::unordered_map charToIndexMap; // map project identifier char to index for fast lookup based on project identifier - for (int i = 0; i < projects.size(); i++) { - auto iterator = charToIndexMap.find(projects[i]); // check for project uniqueness - if (iterator != charToIndexMap.end()) return; // the same project exists twice in the project manifest - projectsGN.push_back(new chapter_02::GraphNode(projects[i])); - charToIndexMap[projects[i]] = i; - } - // convert list of project dependencies to graph edges - int totalEdges = 0; - for (auto dependency : dependencies) { - // the first node in a pair must be build before the second. - chapter_02::GraphNode* first = projectsGN[charToIndexMap[dependency.first]]; - chapter_02::GraphNode* second = projectsGN[charToIndexMap[dependency.second]]; - // add edge from the first node to the second node - first->push(second); - second->incAncestors(); - totalEdges ++; - } - // create queue containing all nodes with no dependencies - std::queue*> Q; - for (auto node : projectsGN) { - if (node->getNumAncestors() == 0) Q.push(node); - } - // traverse graph in depth first order starting from nodes without dependencies - while (!Q.empty()) { - chapter_02::GraphNode* node = Q.front(); - Q.pop(); - buildOrder.push_back(node->getValue()); - chapter_02::SinglyLinkedNode*>* child = node->getHeadOfDescendants(); - while (child != nullptr) { - child->getValue()->decAncestors(); - totalEdges --; // keep track of total edges in graph as we remove them - if (child->getValue()->getNumAncestors() == 0) Q.push(child->getValue()); - child = child->getNext(); - node->pop(); - } - } - // if edges remain in the graph, at least one circular dependency exists - if (totalEdges != 0) { - buildOrder.clear(); - } - // free memory consumed by graph nodes - for (auto node : projectsGN) { - delete node; - } - } +/* +Chapter 04 - Problem 07 - Build Order + +Problem Statement: +You are given a list of projects and a list of dependencies (which is a list of pairs of projects, +where the second project is dependent on the first project). All of a project's dependencies must +be built before the project is. Find a build order that will allow the projects to be built. +If there is no valid build order, return an error. + +Solution: +We first represent the projects and build dependencies as vertices and edges in a directed acyclic graph. +We then implement Kahn's algorithm for topological sorting: https://en.wikipedia.org/wiki/Topological_sorting#Algorithms + +L ← Empty list that will contain the sorted elements +S ← Set of all nodes with no incoming edge +while S is non-empty do + remove a node n from S + add n to tail of L + for each node m with an edge e from n to m do + remove edge e from the graph + if m has no other incoming edges then + insert m into S +if graph has edges then + return error (graph has at least one cycle) +else + return L (a topologically sorted order) + +Time complexity: O(V + E) where V is the number of vertices in the graph and E is the number of edges. +V can be interpreted as the number of projects and E can be interpreted as the number of dependencies. +Space complexity: O(V) +*/ + +#include "problem_04_07_buildOrder.h" +#include +#include + +namespace chapter_04 { + void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder) { + // convert list of project identifiers to graph nodes + std::vector*> projectsGN = {}; // store pointers to GraphNodes used in topological sort + std::unordered_map charToIndexMap; // map project identifier char to index for fast lookup based on project identifier + for (int i = 0; i < projects.size(); i++) { + auto iterator = charToIndexMap.find(projects[i]); // check for project uniqueness + if (iterator != charToIndexMap.end()) return; // the same project exists twice in the project manifest + projectsGN.push_back(new chapter_02::GraphNode(projects[i])); + charToIndexMap[projects[i]] = i; + } + // convert list of project dependencies to graph edges + int totalEdges = 0; + for (auto dependency : dependencies) { + // the first node in a pair must be build before the second. + chapter_02::GraphNode* first = projectsGN[charToIndexMap[dependency.first]]; + chapter_02::GraphNode* second = projectsGN[charToIndexMap[dependency.second]]; + // add edge from the first node to the second node + first->push(second); + second->incAncestors(); + totalEdges ++; + } + // create queue containing all nodes with no dependencies + std::queue*> Q; + for (auto node : projectsGN) { + if (node->getNumAncestors() == 0) Q.push(node); + } + // traverse graph in depth first order starting from nodes without dependencies + while (!Q.empty()) { + chapter_02::GraphNode* node = Q.front(); + Q.pop(); + buildOrder.push_back(node->getValue()); + chapter_02::SinglyLinkedNode*>* child = node->getHeadOfDescendants(); + while (child != nullptr) { + child->getValue()->decAncestors(); + totalEdges --; // keep track of total edges in graph as we remove them + if (child->getValue()->getNumAncestors() == 0) Q.push(child->getValue()); + child = child->getNext(); + node->pop(); + } + } + // if edges remain in the graph, at least one circular dependency exists + if (totalEdges != 0) { + buildOrder.clear(); + } + // free memory consumed by graph nodes + for (auto node : projectsGN) { + delete node; + } + } } // namespace chapter_04 \ No newline at end of file diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h index b06c0f3..2337997 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.h @@ -1,11 +1,11 @@ -/* -Chapter 04 - Problem 07 - Build Order - -See problem_04_07_buildOrder.cpp for problem description. -*/ -#include -#include "../chapter_02_linked_lists/Node.h" - -namespace chapter_04 { - void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder); -} // namespace chapter_04 +/* +Chapter 04 - Problem 07 - Build Order + +See problem_04_07_buildOrder.cpp for problem description. +*/ +#include +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_04 { + void buildOrder(std::vector& projects, std::vector>& dependencies, std::vector& buildOrder); +} // namespace chapter_04 diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h index 4dbda3e..3bd8ac5 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_12_pathsWithSum.h @@ -1,76 +1,76 @@ -/* -Chapter 04 - Problem 12 - Paths with Sum - -Problem Statement: -You are given a binary tree in which each node contains an integer value (which might be positive or negative). -Design an algorithm to count the number of paths that sum to a given value. The path does not need to start or -end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). - -Solution: -The brute force solution to this problem is to (1) DFS traverse the tree starting from the root and (2) -initiate a new DFS traversal at each node. For each of the type (2) traversals, we keep a running sum of the node values -that have been traversed. When the running sum equals the target sum, we increment a global total. To calculate the -total runtime, we observe that that a node at depth d has d ancestors. Because of the recursive nature of the -algorithm, those ancestors will each cause function (2) to be called on a given node. From the definitions of -binary trees, the depth of a tree with N nodes is equal to log(N). Thus the runtime is thus O(N*log(N)) for a balanced -tree. For an unbalanced tree (in the worst case, every node of the tree is on the same side), the depth of a tree -with N nodes is N. Thus, the worst case runtime of this algorithm is O(N^2). Because a running sum must be stored for -each node (along with the data associated with the node itself) space complexity is O(N). - -A more efficient solution is to only traverse the tree once using depth first search and use a hash table to -keep track of running sums. In the hash table, the keys are running sums and the values are the numbers of times -the keys have been encountered. By definition, a path leads to the target sum if the difference between the current -running sum and *any previously encountered running sum* is equal to the target sum. At each node encountered during the -traversal, we add that node's running sum to a hash table; if that running sum is already in the hash table, then -we increment its value. Also at each node, we compute the difference between the node's running sum and the target -sum: if that difference is equal to *any* previously observed running sum, then we've discovered a path that yields -the target sum. Furthermore, if there exist multiple of the same running sum, then we've discovered multiple paths that -yield the target sum. Thus, when the difference is equal to the target sum, we increment a global path total by the -current running sum's hash table value thus computing the number of paths that lead to the target sum. One final bit -of complexity in this solution is that hashed sums from traversing one path will not apply to a totally different -path in the tree. We resolve this issue in the recursive implementation of depth first search: once a given node's -left and right recursive calls are completed, we *decrement* that node's running sum in the hash table. In this way, -we do a constant number of hash table lookups at each node in the tree yielding a O(N) worst case runtime and O(N) -space required due to the max hash table size and the sunning sums stored for each node. - -Time complexity: O(N) -Space complexity: O(N) -*/ - -#include "../chapter_02_linked_lists/Node.h" -#include - -namespace chapter_04 { - template - void pathsWithSumHelper( - const T& targetSum, - const chapter_02::BinaryNode* head, - T runningSum, - T& globalSum, - std::unordered_map& hashTable) { - if (head == nullptr) return; // terminating condition - runningSum += head->getValue(); // update running sum for this node - if (hashTable.find(runningSum) == hashTable.end()) { // if running sum is not found, add it. - hashTable[runningSum] = 1; - } else { - hashTable[runningSum] ++; // else increment - } - T difference = runningSum - targetSum; - if (hashTable.find(difference) != hashTable.end()) { // if difference is found increment global sum - globalSum += hashTable[difference]; - } - pathsWithSumHelper(targetSum, head->getLeft(), runningSum, globalSum, hashTable); // recurse - pathsWithSumHelper(targetSum, head->getRight(), runningSum, globalSum, hashTable); // recurse - hashTable[runningSum] --; // decrement to not affect unrelated paths - } - - template - int pathsWithSum(const T& targetSum, const chapter_02::BinaryNode* head) { - std::unordered_map hashTable; - hashTable[static_cast(0)] = 1; // if runningSum - globalSum == 0, then by definition we have found a valid path to the targetSum - T globalSum = 0; - T runningSum = 0; - pathsWithSumHelper(targetSum, head, runningSum, globalSum, hashTable); - return globalSum; - } -} // chapter_04 +/* +Chapter 04 - Problem 12 - Paths with Sum + +Problem Statement: +You are given a binary tree in which each node contains an integer value (which might be positive or negative). +Design an algorithm to count the number of paths that sum to a given value. The path does not need to start or +end at the root or a leaf, but it must go downwards (traveling only from parent nodes to child nodes). + +Solution: +The brute force solution to this problem is to (1) DFS traverse the tree starting from the root and (2) +initiate a new DFS traversal at each node. For each of the type (2) traversals, we keep a running sum of the node values +that have been traversed. When the running sum equals the target sum, we increment a global total. To calculate the +total runtime, we observe that that a node at depth d has d ancestors. Because of the recursive nature of the +algorithm, those ancestors will each cause function (2) to be called on a given node. From the definitions of +binary trees, the depth of a tree with N nodes is equal to log(N). Thus the runtime is thus O(N*log(N)) for a balanced +tree. For an unbalanced tree (in the worst case, every node of the tree is on the same side), the depth of a tree +with N nodes is N. Thus, the worst case runtime of this algorithm is O(N^2). Because a running sum must be stored for +each node (along with the data associated with the node itself) space complexity is O(N). + +A more efficient solution is to only traverse the tree once using depth first search and use a hash table to +keep track of running sums. In the hash table, the keys are running sums and the values are the numbers of times +the keys have been encountered. By definition, a path leads to the target sum if the difference between the current +running sum and *any previously encountered running sum* is equal to the target sum. At each node encountered during the +traversal, we add that node's running sum to a hash table; if that running sum is already in the hash table, then +we increment its value. Also at each node, we compute the difference between the node's running sum and the target +sum: if that difference is equal to *any* previously observed running sum, then we've discovered a path that yields +the target sum. Furthermore, if there exist multiple of the same running sum, then we've discovered multiple paths that +yield the target sum. Thus, when the difference is equal to the target sum, we increment a global path total by the +current running sum's hash table value thus computing the number of paths that lead to the target sum. One final bit +of complexity in this solution is that hashed sums from traversing one path will not apply to a totally different +path in the tree. We resolve this issue in the recursive implementation of depth first search: once a given node's +left and right recursive calls are completed, we *decrement* that node's running sum in the hash table. In this way, +we do a constant number of hash table lookups at each node in the tree yielding a O(N) worst case runtime and O(N) +space required due to the max hash table size and the sunning sums stored for each node. + +Time complexity: O(N) +Space complexity: O(N) +*/ + +#include "../chapter_02_linked_lists/Node.h" +#include + +namespace chapter_04 { + template + void pathsWithSumHelper( + const T& targetSum, + const chapter_02::BinaryNode* head, + T runningSum, + T& globalSum, + std::unordered_map& hashTable) { + if (head == nullptr) return; // terminating condition + runningSum += head->getValue(); // update running sum for this node + if (hashTable.find(runningSum) == hashTable.end()) { // if running sum is not found, add it. + hashTable[runningSum] = 1; + } else { + hashTable[runningSum] ++; // else increment + } + T difference = runningSum - targetSum; + if (hashTable.find(difference) != hashTable.end()) { // if difference is found increment global sum + globalSum += hashTable[difference]; + } + pathsWithSumHelper(targetSum, head->getLeft(), runningSum, globalSum, hashTable); // recurse + pathsWithSumHelper(targetSum, head->getRight(), runningSum, globalSum, hashTable); // recurse + hashTable[runningSum] --; // decrement to not affect unrelated paths + } + + template + int pathsWithSum(const T& targetSum, const chapter_02::BinaryNode* head) { + std::unordered_map hashTable; + hashTable[static_cast(0)] = 1; // if runningSum - globalSum == 0, then by definition we have found a valid path to the targetSum + T globalSum = 0; + T runningSum = 0; + pathsWithSumHelper(targetSum, head, runningSum, globalSum, hashTable); + return globalSum; + } +} // chapter_04 diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp index 46b53e3..1862aa5 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp @@ -1,56 +1,56 @@ -// -// Created by alex on 5/15/2019. -// -#include "problem_05_03_flipBitToWin.h" - -namespace chapter_05 { - int flipBitToWin(int input) { - /* - * PROBLEM: - * Flip Bit to Win: You have an integer and you can flip exactly one bit from a 13 to a 1.Write code to - * find the length of the longest sequence of ls you could create. - * - * TEST CASE: - * 0b000 -> 1 - * 0b100 -> 1 - * 0b1011011 -> 5 - * - * ALGORITHM: - * 1. Iterate through binary representation by using logical right shift on copy of int - * 2. Keep 3 tallys: prev tally, current tally, max tally. - * 3. Loop over binary representation: - * a. Count the number of 1s seen so far in current tally. - * b. If a zero is seen: - * i. add 1 to current tally - * ii. set max tally to sum of pre and post tally if the sum is > max tally - * iii. prev tally = current tally - * c. logical shift the input to the right with >>> - * 4. In case where binary representation ends in 1, we have to do the check in b.ii. again. - * 5. return max tally - * - * SPACE & TIME: - * Space: O(1): extra space we use does not scale with length of int - * Time: O(b) because we have to iterate thru each bit - * - * CODE: - */ - int prevTally = 0; - int currentTally = 0; - int maxTally = 0; - if (input == 0) return 1; // edge case where we do not need to run the algorithm - while (input != 0) { - if ((input & 0b1) == 1) { - currentTally ++; - } else { - int sum = prevTally + currentTally + 1; - if (sum > maxTally) maxTally = sum; - prevTally = currentTally; - currentTally = 0; - } - input = input >> 1; - } - int sum = prevTally + currentTally + 1; - if (sum > maxTally) maxTally = sum; - return maxTally; - } -} +// +// Created by alex on 5/15/2019. +// +#include "problem_05_03_flipBitToWin.h" + +namespace chapter_05 { + int flipBitToWin(int input) { + /* + * PROBLEM: + * Flip Bit to Win: You have an integer and you can flip exactly one bit from a 13 to a 1.Write code to + * find the length of the longest sequence of ls you could create. + * + * TEST CASE: + * 0b000 -> 1 + * 0b100 -> 1 + * 0b1011011 -> 5 + * + * ALGORITHM: + * 1. Iterate through binary representation by using logical right shift on copy of int + * 2. Keep 3 tallys: prev tally, current tally, max tally. + * 3. Loop over binary representation: + * a. Count the number of 1s seen so far in current tally. + * b. If a zero is seen: + * i. add 1 to current tally + * ii. set max tally to sum of pre and post tally if the sum is > max tally + * iii. prev tally = current tally + * c. logical shift the input to the right with >>> + * 4. In case where binary representation ends in 1, we have to do the check in b.ii. again. + * 5. return max tally + * + * SPACE & TIME: + * Space: O(1): extra space we use does not scale with length of int + * Time: O(b) because we have to iterate thru each bit + * + * CODE: + */ + int prevTally = 0; + int currentTally = 0; + int maxTally = 0; + if (input == 0) return 1; // edge case where we do not need to run the algorithm + while (input != 0) { + if ((input & 0b1) == 1) { + currentTally ++; + } else { + int sum = prevTally + currentTally + 1; + if (sum > maxTally) maxTally = sum; + prevTally = currentTally; + currentTally = 0; + } + input = input >> 1; + } + int sum = prevTally + currentTally + 1; + if (sum > maxTally) maxTally = sum; + return maxTally; + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h index 28f8dad..d2c4f3a 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h @@ -1,8 +1,8 @@ -// -// Created by alex on 5/15/2019. -// - -#pragma once -namespace chapter_05 { - int flipBitToWin(int input); -} +// +// Created by alex on 5/15/2019. +// + +#pragma once +namespace chapter_05 { + int flipBitToWin(int input); +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index d53fb76..c3da45c 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -1,45 +1,45 @@ -// -// Created by Alex Hagiopol on 2019-05-17. -// -#include "problem_05_04_nextNumber.h" - -namespace chapter_05 { - /* - * PROBLEM: - * Given a positive integer, return the next smallest and next largest - * numbers that have the same number of 1s in their binary representations. - * - * TEST CASE: - * positiveInteger -> (nextSmallest, nextLargest) - * 0b0000 -> (0, 0) - * 0b1000 -> (0b0100, ?) - * 0b0001 -> (?, 0b0010) - * 0b0101 -> (0b0011, 0b0110) - * - * ALGORITHM: - * 1. To make a smaller number, shift least significant 1 that has space to move right - * a. Iterate through binary representation to find the rightmost 1 that has a 0 to its right - * b. & the input integer with 111...1110111 then | with 000...0000100 - * c. when we've found the rightmost 1, note its index, then create masks by left shifting a 1 to that index - * 2. To make a bigger number, shift least significant 1 that has space to move left - * ...same as above - * 3. Edge cases? - * a. 0b00...1 -> return (the number itself, its left shift) - * b. 0b10...0 -> return (its left shift, the number itself) - * c. 0b0 -> return (0,0) - * - * SPACE & TIME: - * Space: O(b) - we need to allocate masks the same size as the input - * Time: O(b) - we need to iterate through the binary representation bit by bit - * - * CODE: - */ - int getNext(int positiveInteger) { - - return positiveInteger; - } - int getPrev(int positiveInteger) { - - return positiveInteger; - } -} +// +// Created by Alex Hagiopol on 2019-05-17. +// +#include "problem_05_04_nextNumber.h" + +namespace chapter_05 { + /* + * PROBLEM: + * Given a positive integer, return the next smallest and next largest + * numbers that have the same number of 1s in their binary representations. + * + * TEST CASE: + * positiveInteger -> (nextSmallest, nextLargest) + * 0b0000 -> (0, 0) + * 0b1000 -> (0b0100, ?) + * 0b0001 -> (?, 0b0010) + * 0b0101 -> (0b0011, 0b0110) + * + * ALGORITHM: + * 1. To make a smaller number, shift least significant 1 that has space to move right + * a. Iterate through binary representation to find the rightmost 1 that has a 0 to its right + * b. & the input integer with 111...1110111 then | with 000...0000100 + * c. when we've found the rightmost 1, note its index, then create masks by left shifting a 1 to that index + * 2. To make a bigger number, shift least significant 1 that has space to move left + * ...same as above + * 3. Edge cases? + * a. 0b00...1 -> return (the number itself, its left shift) + * b. 0b10...0 -> return (its left shift, the number itself) + * c. 0b0 -> return (0,0) + * + * SPACE & TIME: + * Space: O(b) - we need to allocate masks the same size as the input + * Time: O(b) - we need to iterate through the binary representation bit by bit + * + * CODE: + */ + int getNext(int positiveInteger) { + + return positiveInteger; + } + int getPrev(int positiveInteger) { + + return positiveInteger; + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h index 6d7f067..267506b 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h @@ -1,7 +1,7 @@ -#pragma once -#include - -namespace chapter_05 { - int getNext(int positiveInteger); - int getPrev(int positiveInteger); -} +#pragma once +#include + +namespace chapter_05 { + int getNext(int positiveInteger); + int getPrev(int positiveInteger); +} diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp index 572d260..97296b8 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp @@ -1,76 +1,76 @@ -/* -Chapter 08 - Problem 07 - Permutations Without Duplicates - -Problem Statement: -Write a method to compute all permutations of a string of unique characters. - -Solution: -First, we show the definition of permutations by example: -'a' -> 'a' # 1! = 1 -'al' -> 'al' , 'la' # 2! = 2 -'ale' -> 'ale', 'ael', 'lae', 'lea', 'eal', 'ela' # 3! = 6 - -Next, we show a recursive pattern for permutation generation: -permutations('a') = 'a' # terminating condition -permutations('al') = 'al', 'la' # terminating condition -permutations('ale') -> return combine('a', permutations('le')) - = return combine('a', ['le', 'el']) - = return ['ale', 'lae', 'lea', 'ael', 'eal', 'ela'] - -Our recursive solution implementation has 2 components: - -I. A function permutations(string) that takes as input a string. This function terminates when the length of the string is -2 or less. This function recurses when the length of the string is 3 or more. -II. A function combine(char, [string1, string2 ... stringN]) that takes as input a single character and a list of strings. -This function returns a list of strings that are formed by inserting the single character at every possible position in -every member of the list of strings. - -When called on a string of length greater than 2, the function permutations(string) returns combine(string[0], -permutations(string[1:end])). Thus, a string of length N will cause N-2 calls of the permutations() function. At each -call of permutations(string_length_X), the combine() function will produce a list of strings that is X! long. To create -each member of the list of strings produced by combine(), O(X) work is required where X is O(N). Thus, Gayle loosely -approximates an upper bound on the total number of operations as O(N! * N^2). A more accurate expression of the runtime -would be the sum ... - -O(N!*N + (N-1)!*(N-1) + (N-2)!*(N-2) ...) -The space complexity of the problem is O(N! * N) because N! of strings of length N must be stored. - -Time complexity: O(N!*N^2) -Space complexity: O(N!*N) -*/ - -#include "problem_08_07_permutationsNoDups.h" -#include - -namespace chapter_08 { - void combine(const std::string& toInsert, const std::unordered_set& oldPermutations, std::unordered_set& newPermutations) { - for (const std::string& oldPermutation : oldPermutations) { - for (int i = 0; i < oldPermutation.length() + 1; i++) { - std::string newPermutation = - oldPermutation.substr(0, static_cast(i)) + - toInsert + - oldPermutation.substr(static_cast(i), std::string::npos); - newPermutations.insert(newPermutation); - } - } - } - - void permutationsNoDups(const std::string& string, std::unordered_set& permutations) { - if (string.length() == 1) { - permutations.insert(string); - } else if (string.length() == 2) { - permutations.insert(string); - std::string copy(string); - std::reverse(copy.begin(), copy.end()); - permutations.insert(copy); - } else if (string.length() > 2) { - std::unordered_set oldPermutations = {}; - std::unordered_set newPermutations = {}; - permutationsNoDups(string.substr(1, std::string::npos), oldPermutations); - combine(string.substr(0, 1), oldPermutations, newPermutations); - for (const std::string& permutation : newPermutations ) { - permutations.insert(permutation); - } - } // if string.length() <= 0 do nothing - } -} +/* +Chapter 08 - Problem 07 - Permutations Without Duplicates + +Problem Statement: +Write a method to compute all permutations of a string of unique characters. + +Solution: +First, we show the definition of permutations by example: +'a' -> 'a' # 1! = 1 +'al' -> 'al' , 'la' # 2! = 2 +'ale' -> 'ale', 'ael', 'lae', 'lea', 'eal', 'ela' # 3! = 6 + +Next, we show a recursive pattern for permutation generation: +permutations('a') = 'a' # terminating condition +permutations('al') = 'al', 'la' # terminating condition +permutations('ale') -> return combine('a', permutations('le')) + = return combine('a', ['le', 'el']) + = return ['ale', 'lae', 'lea', 'ael', 'eal', 'ela'] + +Our recursive solution implementation has 2 components: + +I. A function permutations(string) that takes as input a string. This function terminates when the length of the string is +2 or less. This function recurses when the length of the string is 3 or more. +II. A function combine(char, [string1, string2 ... stringN]) that takes as input a single character and a list of strings. +This function returns a list of strings that are formed by inserting the single character at every possible position in +every member of the list of strings. + +When called on a string of length greater than 2, the function permutations(string) returns combine(string[0], +permutations(string[1:end])). Thus, a string of length N will cause N-2 calls of the permutations() function. At each +call of permutations(string_length_X), the combine() function will produce a list of strings that is X! long. To create +each member of the list of strings produced by combine(), O(X) work is required where X is O(N). Thus, Gayle loosely +approximates an upper bound on the total number of operations as O(N! * N^2). A more accurate expression of the runtime +would be the sum ... + +O(N!*N + (N-1)!*(N-1) + (N-2)!*(N-2) ...) +The space complexity of the problem is O(N! * N) because N! of strings of length N must be stored. + +Time complexity: O(N!*N^2) +Space complexity: O(N!*N) +*/ + +#include "problem_08_07_permutationsNoDups.h" +#include + +namespace chapter_08 { + void combine(const std::string& toInsert, const std::unordered_set& oldPermutations, std::unordered_set& newPermutations) { + for (const std::string& oldPermutation : oldPermutations) { + for (int i = 0; i < oldPermutation.length() + 1; i++) { + std::string newPermutation = + oldPermutation.substr(0, static_cast(i)) + + toInsert + + oldPermutation.substr(static_cast(i), std::string::npos); + newPermutations.insert(newPermutation); + } + } + } + + void permutationsNoDups(const std::string& string, std::unordered_set& permutations) { + if (string.length() == 1) { + permutations.insert(string); + } else if (string.length() == 2) { + permutations.insert(string); + std::string copy(string); + std::reverse(copy.begin(), copy.end()); + permutations.insert(copy); + } else if (string.length() > 2) { + std::unordered_set oldPermutations = {}; + std::unordered_set newPermutations = {}; + permutationsNoDups(string.substr(1, std::string::npos), oldPermutations); + combine(string.substr(0, 1), oldPermutations, newPermutations); + for (const std::string& permutation : newPermutations ) { + permutations.insert(permutation); + } + } // if string.length() <= 0 do nothing + } +} diff --git a/tests.cpp b/tests.cpp index 65a71ce..461f4a3 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1,1107 +1,1107 @@ -// -// 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 testVec = {"a", "b", "c", "d", "e", "f"}; - std::vector expectedVec = {"a", "b", "d", "e", "f"}; - chapter_02::SinglyLinkedNode* testVecHead = chapter_02::vectorToList(testVec); - chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); - // traverse input to find node with content "c" - chapter_02::SinglyLinkedNode* 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 list4 = {"a", "l", "e", "x"}; - std::vector 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* head4 = chapter_02::vectorToList(list4); - chapter_02::SinglyLinkedNode* 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*>(nullptr), static_cast*>(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*>(nullptr) == chapter_02::findLoop(static_cast*>(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*> 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*> 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*>(nullptr), static_cast*>(nullptr))); - REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(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*> vectorOfHeads; - std::vector*> 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> 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> 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> 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 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); - /* - construct disconnected binary tree - 30 - 31 32 - */ - chapter_02::BinaryNode n31(31); - chapter_02::BinaryNode n32(32); - chapter_02::BinaryNode n30(30, &n31, &n32); - - REQUIRE(chapter_04::checkSubtree(&n7, &n15)); - REQUIRE(chapter_04::checkSubtree(&n7, &n7)); - REQUIRE(chapter_04::checkSubtree(&n7, &n21)); - REQUIRE(chapter_04::checkSubtree(&n7, &n4)); - REQUIRE(!chapter_04::checkSubtree(&n7, nullptr)); - REQUIRE(!chapter_04::checkSubtree(&n7, &n30)); - REQUIRE(!chapter_04::checkSubtree(&n7, &n31)); - REQUIRE(!chapter_04::checkSubtree(&n25, &n31)); - REQUIRE(chapter_04::checkSubtree(&n30, &n31)); - REQUIRE(!chapter_04::checkSubtree(nullptr, nullptr)); -} - -TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ - std::vector valuesList = {10, 13, 14, 11, 7, 7, 8, 7, 4, 10}; - chapter_04::RandBinaryNode head(valuesList[0]); - for (int i = 1; i < valuesList.size(); i++) { - head.insert(valuesList[i]); - } - int occurrenceSum4 = 0; - int occurrenceSum7 = 0; - int occurrenceSum10 = 0; - int occurrenceSum13 = 0; - // using 10,000 random samples, assert that occurence of values in random samples approximately - // the same as the occurence of the values in the tree - std::mt19937 gen(0); // standard mersenne_twister_engine seeded with zero - for (int i = 0; i < 10000; i++) { - int randValue = head.getRandomNode(-1, &gen)->getValue(); - switch (randValue){ - case 4 : occurrenceSum4 ++; break; - case 7 : occurrenceSum7 ++; break; - case 10 : occurrenceSum10 ++; break; - case 13 : occurrenceSum13 ++; break; - } - } - REQUIRE(((950 <= occurrenceSum4) && (occurrenceSum4 <= 1050))); - REQUIRE(((2950 <= occurrenceSum7) && (occurrenceSum7 <= 3050))); - REQUIRE(((1950 <= occurrenceSum10) && (occurrenceSum10 <= 2050))); - REQUIRE(((950 <= occurrenceSum13) && (occurrenceSum13 <= 1050))); -} - -TEST_CASE("Chapter 04 - Problem 12 - pathsWithSum()", "test"){ - /* - construct binary tree like in textbook example - 10 - 5 -3 - 3 1 __ 11 - 3 -2 __ 2 - */ - // leaf nodes at depth = 3 - chapter_02::BinaryNode n3_leaf(3); - chapter_02::BinaryNode n_minus2(-2); - chapter_02::BinaryNode n2(2); - // nodes at depth = 2 - chapter_02::BinaryNode n3(3, &n3_leaf, &n_minus2); - chapter_02::BinaryNode n1(1, nullptr, &n2); - chapter_02::BinaryNode n11(11); - // nodes at depth = 1 - chapter_02::BinaryNode n5(5, &n3, &n1); - chapter_02::BinaryNode n_minus3(-3, nullptr, &n11); - // root node at depth = 0 - chapter_02::BinaryNode n10(10, &n5, &n_minus3); - // count paths that sum to 8 - REQUIRE(3 == chapter_04::pathsWithSum(8, &n10)); -} - -TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ - REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); -} - -TEST_CASE("Chapter 05 - Problem 02 - binaryToString()", "test") { - std::string binary_string_1 = ""; - std::string binary_string_2 = ""; - std::string binary_string_3 = ""; - std::string binary_string_4 = ""; - REQUIRE(chapter_05::binaryToString(0.5, binary_string_1) == 0); - REQUIRE(chapter_05::binaryToString(0.25, binary_string_2) == 0); - REQUIRE(chapter_05::binaryToString(1.5, binary_string_3) == -1); - REQUIRE(chapter_05::binaryToString(0.722, binary_string_4) == 0); - REQUIRE(binary_string_1 == "0.1"); - REQUIRE(binary_string_2 == "0.01"); - REQUIRE(binary_string_3 == ""); - REQUIRE(binary_string_4 == "0.10111000110101001111110111110011"); // needs double precision to work -} - -TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { - REQUIRE(chapter_05::flipBitToWin(1775) == 8); - REQUIRE(chapter_05::flipBitToWin(0b0000) == 1); - REQUIRE(chapter_05::flipBitToWin(0b1011) == 4); - REQUIRE(chapter_05::flipBitToWin(0b1010111) == 5); - REQUIRE(chapter_05::flipBitToWin(0b1110101) == 5); - REQUIRE(chapter_05::flipBitToWin(0b00) == 1); - REQUIRE(chapter_05::flipBitToWin(0b10) == 2); -} - -TEST_CASE("Chapter 05 - Problem 04 - nextNumber()", "test"){ - /* - //REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); - REQUIRE(chapter_05::getNext(0b0100) == 0b1000); - //REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); - REQUIRE(chapter_05::getNext(0b0101) == 0b0110); - //REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible - REQUIRE(chapter_05::getNext(0b1111) == 0b10111); // add an extra digit - //REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible - REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible - //REQUIRE(chapter_05::getPrev(0b1001) == 0b0101); - REQUIRE(chapter_05::getNext(0b1001) == 0b1010); - */ -} - -TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ - REQUIRE(chapter_05::conversion(0b11001100, 0b11110000) == 4); - REQUIRE(chapter_05::conversion(29, 15) == 2); -} - -TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ - REQUIRE(chapter_05::pairwiseSwap(0b10101010) == 0b01010101); - REQUIRE(chapter_05::pairwiseSwap(0b11110000) == 0b11110000); - REQUIRE(chapter_05::pairwiseSwap(0b110) == 0b1001); -} - -TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ - REQUIRE(chapter_08::tripleStep(3) == 4); - REQUIRE(chapter_08::tripleStep(4) == 7); - REQUIRE(chapter_08::tripleStep(5) == 13); -} - -TEST_CASE("Chapter 08 - Problem 02 - robotGrid()", "test"){ - - Eigen::MatrixXd maze(5, 5); - maze << 1, 1, 1, 0, 1, - 0, 0, 1, 1, 1, - 0, 1, 1, 0, 0, - 0, 1, 1, 0, 1, - 1, 1, 1, 1, 1; - std::vector expectedPath = {Eigen::Vector2d(0,0), - Eigen::Vector2d(0,1), - Eigen::Vector2d(0,2), - Eigen::Vector2d(1,2), - Eigen::Vector2d(2,2), - Eigen::Vector2d(3,2), - Eigen::Vector2d(4,2), - Eigen::Vector2d(4,3), - Eigen::Vector2d(4,4)}; - std::vector path; - REQUIRE(chapter_08::robotGrid(maze, path)); - REQUIRE(path == expectedPath); -} - -TEST_CASE("Chapter 08 - Problem 03 - magicIndex()", "test"){ - std::vector noMagicIndex = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector magicIndex5 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; - std::vector magicIndex7 = {-40, -20, -1, 1, 2, 3, 5, 7, 9, 12, 13}; - REQUIRE(chapter_08::magicIndex(noMagicIndex) == -1); - REQUIRE(chapter_08::magicIndex(magicIndex5) == 5); - REQUIRE(chapter_08::magicIndex(magicIndex7) == 7); -} - -TEST_CASE("Chapter 08 - Problem 04 - powerSet()", "test"){ - std::vector set123 = {1, 2, 3}; - std::vector set12 = {1, 2}; - std::vector set13 = {1, 3}; - std::vector set23 = {2, 3}; - std::vector set1 = {1}; - std::vector set2 = {2}; - std::vector set3 = {3}; - std::vector emptySet = {}; - - std::vector> powerSet123 = {emptySet, set1, set2, set12, set3, set13, set23, set123}; - std::vector> powerSet12 = {emptySet, set1, set2, set12}; - std::vector> powerSet1 = {emptySet, set1}; - - std::vector> testPowerSet = {}; - chapter_08::createPowerSet(set123, testPowerSet); - REQUIRE(testPowerSet == powerSet123); - testPowerSet = {}; - chapter_08::createPowerSet(set12, testPowerSet); - REQUIRE(testPowerSet == powerSet12); - testPowerSet = {}; - chapter_08::createPowerSet(set1, testPowerSet); - REQUIRE(testPowerSet == powerSet1); -}; - -TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ - REQUIRE(chapter_08::recursiveMultiply(1, 1) == 1); - REQUIRE(chapter_08::recursiveMultiply(1, 2) == 2); - REQUIRE(chapter_08::recursiveMultiply(0, 1) == 0); - REQUIRE(chapter_08::recursiveMultiply(9, 10) == 90); - REQUIRE(chapter_08::recursiveMultiply(9, 11) == 99); - REQUIRE(chapter_08::recursiveMultiply(12, 12) == 144); -} - -TEST_CASE("Chapter 08 - Problem 07 - permutationsNoDups()", "test") { - std::unordered_set actual1 = {}; - std::unordered_set actual2 = {}; - std::unordered_set actual3 = {}; - std::unordered_set actual4 = {}; - std::unordered_set expected1 = {"a"}; - std::unordered_set expected2 = {"al", "la"}; - std::unordered_set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; - std::unordered_set expected4 = {"xela", "exla", "elxa", "elax", - "xlea", "lxea", "lexa", "leax", - "xlae", "lxae", "laxe", "laex", - "xeal", "exal", "eaxl", "ealx", - "xael", "axel", "aexl", "aelx", - "xale", "axle", "alxe", "alex"}; - chapter_08::permutationsNoDups("a", actual1); - chapter_08::permutationsNoDups("al", actual2); - chapter_08::permutationsNoDups("ale", actual3); - chapter_08::permutationsNoDups("alex", actual4); - REQUIRE(actual1 == expected1); - REQUIRE(actual2 == expected2); - REQUIRE(actual3 == expected3); - REQUIRE(actual4 == expected4); -} - -TEST_CASE("Chapter 08 - Problem 08 - permutationsWithDups()", "test") { - std::unordered_set actual1 = {}; - std::unordered_set actual2 = {}; - std::unordered_set actual3 = {}; - std::unordered_set expected1 = {"ala", "laa", "aal"}; - std::unordered_set expected2 = {"aala", "alaa", "alaa", "laaa", "aala", "aaal"}; - std::unordered_set expected3 = {"xela", "exla", "elxa", "elax", - "xlea", "lxea", "lexa", "leax", - "xlae", "lxae", "laxe", "laex", - "xeal", "exal", "eaxl", "ealx", - "xael", "axel", "aexl", "aelx", - "xale", "axle", "alxe", "alex"}; - chapter_08::permutationsWithDups("ala", actual1); - chapter_08::permutationsWithDups("alaa", actual2); - chapter_08::permutationsWithDups("alex", actual3); - REQUIRE(actual1 == expected1); - REQUIRE(actual2 == expected2); - REQUIRE(actual3 == expected3); -} - -TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ - Eigen::MatrixXi image(6, 6); - image << 0, 1, 1, 0, 0, 3, - 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 0, 2, - 0, 0, 0, 0, 2, 2, - 0, 2, 2, 2, 2, 2, - 0, 0, 0, 2, 2, 2; - Eigen::MatrixXi zerosFilled(6, 6); - zerosFilled << 0, 1, 1, 5, 5, 3, - 1, 1, 1, 1, 5, 5, - 5, 1, 1, 5, 5, 2, - 5, 5, 5, 5, 2, 2, - 5, 2, 2, 2, 2, 2, - 5, 5, 5, 2, 2, 2; - Eigen::MatrixXi onesFilled(6, 6); - onesFilled << 0, 5, 5, 0, 0, 3, - 5, 5, 5, 5, 0, 0, - 0, 5, 5, 0, 0, 2, - 0, 0, 0, 0, 2, 2, - 0, 2, 2, 2, 2, 2, - 0, 0, 0, 2, 2, 2; - Eigen::MatrixXi twosFilled(6, 6); - twosFilled << 0, 1, 1, 0, 0, 3, - 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 0, 5, - 0, 0, 0, 0, 5, 5, - 0, 5, 5, 5, 5, 5, - 0, 0, 0, 5, 5, 5; - Eigen::MatrixXi threeFilled(6, 6); - threeFilled << 0, 1, 1, 0, 0, 5, - 1, 1, 1, 1, 0, 0, - 0, 1, 1, 0, 0, 2, - 0, 0, 0, 0, 2, 2, - 0, 2, 2, 2, 2, 2, - 0, 0, 0, 2, 2, 2; - Eigen::MatrixXi expectedZerosFilled = image; - Eigen::MatrixXi expectedOnesFilled = image; - Eigen::MatrixXi expectedTwosFilled = image; - Eigen::MatrixXi expectedThreeFilled = image; - chapter_08::paintFill(expectedZerosFilled, Eigen::Vector2i(2, 0), 5); - chapter_08::paintFill(expectedOnesFilled, Eigen::Vector2i(1, 2), 5); - chapter_08::paintFill(expectedTwosFilled, Eigen::Vector2i(4, 3), 5); - chapter_08::paintFill(expectedThreeFilled, Eigen::Vector2i(0, 5), 5); - REQUIRE(zerosFilled.isApprox(expectedZerosFilled)); - REQUIRE(onesFilled.isApprox(expectedOnesFilled)); - REQUIRE(twosFilled.isApprox(expectedTwosFilled)); - REQUIRE(threeFilled.isApprox(expectedThreeFilled)); -} - -TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ - int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly - int B[5] = {3, 6, 9, 12, 15}; - int lastA = 4; // index of last item placed in A - int lastB = 4; // index of last item placed in B - int C[10] = {3, 5, 5, 6, 9, 10, 10, 12, 15, 15}; - chapter_10::sortedMerge(&A[0], lastA, &B[0], lastB); - for (int i = 0; i < 10; i++){ - REQUIRE(A[i] == C[i]); - } - - - int D[10] = {5, 5, 10, 10}; // remainder of uninitialized values set to zero implicitly - int E[6] = {3, 6, 9, 12, 15, 15}; - int lastD = 3; // index of last item placed in D - int lastE = 5; // index of last item placed in E - chapter_10::sortedMerge(&D[0], lastD, &E[0], lastE); - for (int i = 0; i < 10; i++){ - REQUIRE(D[i] == C[i]); - } -} - -TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ - char s1[] = "Alex"; - char s1Rev[] = "xelA"; - char s2[] = "a"; - char s2Rev[] = "a"; - chapter_12::reverse(&s1[0]); - chapter_12::reverse(&s2[0]); - // strcmp returns 0 if the 2 strings are equal. - REQUIRE(strcmp(&s1[0], &s1Rev[0]) == 0); - REQUIRE(strcmp(&s2[0], &s2Rev[0]) == 0); -} - -TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ - std::vector targetVector = {1,2,3,4,5,6,7}; - chapter_02::SinglyLinkedNode* head = chapter_02::vectorToList(targetVector); - chapter_02::SinglyLinkedNode* copy = chapter_12::copyNode(head); - REQUIRE(targetVector == chapter_02::listToVector(copy)); // check that the values contained in nodes are identical - // Check that the pointers in the head linked list are *not* the same as the pointers in the copy likned list - // This is to verify a copy was actually made. - while (head != nullptr && copy != nullptr){ - REQUIRE(head != copy); - head = head->getNext(); - copy = copy->getNext(); - } -} - -TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ - Eigen::MatrixXd input1(4, 4); - input1 << 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1; - Eigen::MatrixXd output1(4, 4); - output1 << 1, 2, 3, 4, - 2, 4, 6, 8, - 3, 6, 9, 12, - 4, 8, 12, 16; - REQUIRE(output1.isApprox(misc::makeIntegralImage(input1))); - Eigen::MatrixXd output2(4, 4); - output2 << 1, 3, 6, 10, - 3, 9, 18, 30, - 6, 18, 36, 60, - 10, 30, 60, 100; - REQUIRE(output2.isApprox(misc::makeIntegralImage(output1))); -} - -TEST_CASE("Misc Exercises - boxFilter()", "test"){ - -} +// +// 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 testVec = {"a", "b", "c", "d", "e", "f"}; + std::vector expectedVec = {"a", "b", "d", "e", "f"}; + chapter_02::SinglyLinkedNode* testVecHead = chapter_02::vectorToList(testVec); + chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); + // traverse input to find node with content "c" + chapter_02::SinglyLinkedNode* 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 list4 = {"a", "l", "e", "x"}; + std::vector 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* head4 = chapter_02::vectorToList(list4); + chapter_02::SinglyLinkedNode* 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*>(nullptr), static_cast*>(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*>(nullptr) == chapter_02::findLoop(static_cast*>(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*> 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*> 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*>(nullptr), static_cast*>(nullptr))); + REQUIRE(!chapter_04::pathExistsDFS(node1, static_cast*>(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*> vectorOfHeads; + std::vector*> 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> 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> 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> 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 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); + /* + construct disconnected binary tree + 30 + 31 32 + */ + chapter_02::BinaryNode n31(31); + chapter_02::BinaryNode n32(32); + chapter_02::BinaryNode n30(30, &n31, &n32); + + REQUIRE(chapter_04::checkSubtree(&n7, &n15)); + REQUIRE(chapter_04::checkSubtree(&n7, &n7)); + REQUIRE(chapter_04::checkSubtree(&n7, &n21)); + REQUIRE(chapter_04::checkSubtree(&n7, &n4)); + REQUIRE(!chapter_04::checkSubtree(&n7, nullptr)); + REQUIRE(!chapter_04::checkSubtree(&n7, &n30)); + REQUIRE(!chapter_04::checkSubtree(&n7, &n31)); + REQUIRE(!chapter_04::checkSubtree(&n25, &n31)); + REQUIRE(chapter_04::checkSubtree(&n30, &n31)); + REQUIRE(!chapter_04::checkSubtree(nullptr, nullptr)); +} + +TEST_CASE("Chapter 04 - Problem 11 - randomBST()", "test"){ + std::vector valuesList = {10, 13, 14, 11, 7, 7, 8, 7, 4, 10}; + chapter_04::RandBinaryNode head(valuesList[0]); + for (int i = 1; i < valuesList.size(); i++) { + head.insert(valuesList[i]); + } + int occurrenceSum4 = 0; + int occurrenceSum7 = 0; + int occurrenceSum10 = 0; + int occurrenceSum13 = 0; + // using 10,000 random samples, assert that occurence of values in random samples approximately + // the same as the occurence of the values in the tree + std::mt19937 gen(0); // standard mersenne_twister_engine seeded with zero + for (int i = 0; i < 10000; i++) { + int randValue = head.getRandomNode(-1, &gen)->getValue(); + switch (randValue){ + case 4 : occurrenceSum4 ++; break; + case 7 : occurrenceSum7 ++; break; + case 10 : occurrenceSum10 ++; break; + case 13 : occurrenceSum13 ++; break; + } + } + REQUIRE(((950 <= occurrenceSum4) && (occurrenceSum4 <= 1050))); + REQUIRE(((2950 <= occurrenceSum7) && (occurrenceSum7 <= 3050))); + REQUIRE(((1950 <= occurrenceSum10) && (occurrenceSum10 <= 2050))); + REQUIRE(((950 <= occurrenceSum13) && (occurrenceSum13 <= 1050))); +} + +TEST_CASE("Chapter 04 - Problem 12 - pathsWithSum()", "test"){ + /* + construct binary tree like in textbook example + 10 + 5 -3 + 3 1 __ 11 + 3 -2 __ 2 + */ + // leaf nodes at depth = 3 + chapter_02::BinaryNode n3_leaf(3); + chapter_02::BinaryNode n_minus2(-2); + chapter_02::BinaryNode n2(2); + // nodes at depth = 2 + chapter_02::BinaryNode n3(3, &n3_leaf, &n_minus2); + chapter_02::BinaryNode n1(1, nullptr, &n2); + chapter_02::BinaryNode n11(11); + // nodes at depth = 1 + chapter_02::BinaryNode n5(5, &n3, &n1); + chapter_02::BinaryNode n_minus3(-3, nullptr, &n11); + // root node at depth = 0 + chapter_02::BinaryNode n10(10, &n5, &n_minus3); + // count paths that sum to 8 + REQUIRE(3 == chapter_04::pathsWithSum(8, &n10)); +} + +TEST_CASE("Chapter 05 - Problem 01 - insertion()", "test"){ + REQUIRE(chapter_05::insertion(0b10000000000, 0b10011, 2, 6) == 0b10001001100); +} + +TEST_CASE("Chapter 05 - Problem 02 - binaryToString()", "test") { + std::string binary_string_1 = ""; + std::string binary_string_2 = ""; + std::string binary_string_3 = ""; + std::string binary_string_4 = ""; + REQUIRE(chapter_05::binaryToString(0.5, binary_string_1) == 0); + REQUIRE(chapter_05::binaryToString(0.25, binary_string_2) == 0); + REQUIRE(chapter_05::binaryToString(1.5, binary_string_3) == -1); + REQUIRE(chapter_05::binaryToString(0.722, binary_string_4) == 0); + REQUIRE(binary_string_1 == "0.1"); + REQUIRE(binary_string_2 == "0.01"); + REQUIRE(binary_string_3 == ""); + REQUIRE(binary_string_4 == "0.10111000110101001111110111110011"); // needs double precision to work +} + +TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { + REQUIRE(chapter_05::flipBitToWin(1775) == 8); + REQUIRE(chapter_05::flipBitToWin(0b0000) == 1); + REQUIRE(chapter_05::flipBitToWin(0b1011) == 4); + REQUIRE(chapter_05::flipBitToWin(0b1010111) == 5); + REQUIRE(chapter_05::flipBitToWin(0b1110101) == 5); + REQUIRE(chapter_05::flipBitToWin(0b00) == 1); + REQUIRE(chapter_05::flipBitToWin(0b10) == 2); +} + +TEST_CASE("Chapter 05 - Problem 04 - nextNumber()", "test"){ + /* + //REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); + REQUIRE(chapter_05::getNext(0b0100) == 0b1000); + //REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); + REQUIRE(chapter_05::getNext(0b0101) == 0b0110); + //REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(0b1111) == 0b10111); // add an extra digit + //REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible + //REQUIRE(chapter_05::getPrev(0b1001) == 0b0101); + REQUIRE(chapter_05::getNext(0b1001) == 0b1010); + */ +} + +TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ + REQUIRE(chapter_05::conversion(0b11001100, 0b11110000) == 4); + REQUIRE(chapter_05::conversion(29, 15) == 2); +} + +TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ + REQUIRE(chapter_05::pairwiseSwap(0b10101010) == 0b01010101); + REQUIRE(chapter_05::pairwiseSwap(0b11110000) == 0b11110000); + REQUIRE(chapter_05::pairwiseSwap(0b110) == 0b1001); +} + +TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ + REQUIRE(chapter_08::tripleStep(3) == 4); + REQUIRE(chapter_08::tripleStep(4) == 7); + REQUIRE(chapter_08::tripleStep(5) == 13); +} + +TEST_CASE("Chapter 08 - Problem 02 - robotGrid()", "test"){ + + Eigen::MatrixXd maze(5, 5); + maze << 1, 1, 1, 0, 1, + 0, 0, 1, 1, 1, + 0, 1, 1, 0, 0, + 0, 1, 1, 0, 1, + 1, 1, 1, 1, 1; + std::vector expectedPath = {Eigen::Vector2d(0,0), + Eigen::Vector2d(0,1), + Eigen::Vector2d(0,2), + Eigen::Vector2d(1,2), + Eigen::Vector2d(2,2), + Eigen::Vector2d(3,2), + Eigen::Vector2d(4,2), + Eigen::Vector2d(4,3), + Eigen::Vector2d(4,4)}; + std::vector path; + REQUIRE(chapter_08::robotGrid(maze, path)); + REQUIRE(path == expectedPath); +} + +TEST_CASE("Chapter 08 - Problem 03 - magicIndex()", "test"){ + std::vector noMagicIndex = {-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::vector magicIndex5 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + std::vector magicIndex7 = {-40, -20, -1, 1, 2, 3, 5, 7, 9, 12, 13}; + REQUIRE(chapter_08::magicIndex(noMagicIndex) == -1); + REQUIRE(chapter_08::magicIndex(magicIndex5) == 5); + REQUIRE(chapter_08::magicIndex(magicIndex7) == 7); +} + +TEST_CASE("Chapter 08 - Problem 04 - powerSet()", "test"){ + std::vector set123 = {1, 2, 3}; + std::vector set12 = {1, 2}; + std::vector set13 = {1, 3}; + std::vector set23 = {2, 3}; + std::vector set1 = {1}; + std::vector set2 = {2}; + std::vector set3 = {3}; + std::vector emptySet = {}; + + std::vector> powerSet123 = {emptySet, set1, set2, set12, set3, set13, set23, set123}; + std::vector> powerSet12 = {emptySet, set1, set2, set12}; + std::vector> powerSet1 = {emptySet, set1}; + + std::vector> testPowerSet = {}; + chapter_08::createPowerSet(set123, testPowerSet); + REQUIRE(testPowerSet == powerSet123); + testPowerSet = {}; + chapter_08::createPowerSet(set12, testPowerSet); + REQUIRE(testPowerSet == powerSet12); + testPowerSet = {}; + chapter_08::createPowerSet(set1, testPowerSet); + REQUIRE(testPowerSet == powerSet1); +}; + +TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ + REQUIRE(chapter_08::recursiveMultiply(1, 1) == 1); + REQUIRE(chapter_08::recursiveMultiply(1, 2) == 2); + REQUIRE(chapter_08::recursiveMultiply(0, 1) == 0); + REQUIRE(chapter_08::recursiveMultiply(9, 10) == 90); + REQUIRE(chapter_08::recursiveMultiply(9, 11) == 99); + REQUIRE(chapter_08::recursiveMultiply(12, 12) == 144); +} + +TEST_CASE("Chapter 08 - Problem 07 - permutationsNoDups()", "test") { + std::unordered_set actual1 = {}; + std::unordered_set actual2 = {}; + std::unordered_set actual3 = {}; + std::unordered_set actual4 = {}; + std::unordered_set expected1 = {"a"}; + std::unordered_set expected2 = {"al", "la"}; + std::unordered_set expected3 = {"ela", "lea", "lae", "eal", "ael", "ale"}; + std::unordered_set expected4 = {"xela", "exla", "elxa", "elax", + "xlea", "lxea", "lexa", "leax", + "xlae", "lxae", "laxe", "laex", + "xeal", "exal", "eaxl", "ealx", + "xael", "axel", "aexl", "aelx", + "xale", "axle", "alxe", "alex"}; + chapter_08::permutationsNoDups("a", actual1); + chapter_08::permutationsNoDups("al", actual2); + chapter_08::permutationsNoDups("ale", actual3); + chapter_08::permutationsNoDups("alex", actual4); + REQUIRE(actual1 == expected1); + REQUIRE(actual2 == expected2); + REQUIRE(actual3 == expected3); + REQUIRE(actual4 == expected4); +} + +TEST_CASE("Chapter 08 - Problem 08 - permutationsWithDups()", "test") { + std::unordered_set actual1 = {}; + std::unordered_set actual2 = {}; + std::unordered_set actual3 = {}; + std::unordered_set expected1 = {"ala", "laa", "aal"}; + std::unordered_set expected2 = {"aala", "alaa", "alaa", "laaa", "aala", "aaal"}; + std::unordered_set expected3 = {"xela", "exla", "elxa", "elax", + "xlea", "lxea", "lexa", "leax", + "xlae", "lxae", "laxe", "laex", + "xeal", "exal", "eaxl", "ealx", + "xael", "axel", "aexl", "aelx", + "xale", "axle", "alxe", "alex"}; + chapter_08::permutationsWithDups("ala", actual1); + chapter_08::permutationsWithDups("alaa", actual2); + chapter_08::permutationsWithDups("alex", actual3); + REQUIRE(actual1 == expected1); + REQUIRE(actual2 == expected2); + REQUIRE(actual3 == expected3); +} + +TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ + Eigen::MatrixXi image(6, 6); + image << 0, 1, 1, 0, 0, 3, + 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 2, + 0, 0, 0, 0, 2, 2, + 0, 2, 2, 2, 2, 2, + 0, 0, 0, 2, 2, 2; + Eigen::MatrixXi zerosFilled(6, 6); + zerosFilled << 0, 1, 1, 5, 5, 3, + 1, 1, 1, 1, 5, 5, + 5, 1, 1, 5, 5, 2, + 5, 5, 5, 5, 2, 2, + 5, 2, 2, 2, 2, 2, + 5, 5, 5, 2, 2, 2; + Eigen::MatrixXi onesFilled(6, 6); + onesFilled << 0, 5, 5, 0, 0, 3, + 5, 5, 5, 5, 0, 0, + 0, 5, 5, 0, 0, 2, + 0, 0, 0, 0, 2, 2, + 0, 2, 2, 2, 2, 2, + 0, 0, 0, 2, 2, 2; + Eigen::MatrixXi twosFilled(6, 6); + twosFilled << 0, 1, 1, 0, 0, 3, + 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 5, + 0, 0, 0, 0, 5, 5, + 0, 5, 5, 5, 5, 5, + 0, 0, 0, 5, 5, 5; + Eigen::MatrixXi threeFilled(6, 6); + threeFilled << 0, 1, 1, 0, 0, 5, + 1, 1, 1, 1, 0, 0, + 0, 1, 1, 0, 0, 2, + 0, 0, 0, 0, 2, 2, + 0, 2, 2, 2, 2, 2, + 0, 0, 0, 2, 2, 2; + Eigen::MatrixXi expectedZerosFilled = image; + Eigen::MatrixXi expectedOnesFilled = image; + Eigen::MatrixXi expectedTwosFilled = image; + Eigen::MatrixXi expectedThreeFilled = image; + chapter_08::paintFill(expectedZerosFilled, Eigen::Vector2i(2, 0), 5); + chapter_08::paintFill(expectedOnesFilled, Eigen::Vector2i(1, 2), 5); + chapter_08::paintFill(expectedTwosFilled, Eigen::Vector2i(4, 3), 5); + chapter_08::paintFill(expectedThreeFilled, Eigen::Vector2i(0, 5), 5); + REQUIRE(zerosFilled.isApprox(expectedZerosFilled)); + REQUIRE(onesFilled.isApprox(expectedOnesFilled)); + REQUIRE(twosFilled.isApprox(expectedTwosFilled)); + REQUIRE(threeFilled.isApprox(expectedThreeFilled)); +} + +TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ + int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly + int B[5] = {3, 6, 9, 12, 15}; + int lastA = 4; // index of last item placed in A + int lastB = 4; // index of last item placed in B + int C[10] = {3, 5, 5, 6, 9, 10, 10, 12, 15, 15}; + chapter_10::sortedMerge(&A[0], lastA, &B[0], lastB); + for (int i = 0; i < 10; i++){ + REQUIRE(A[i] == C[i]); + } + + + int D[10] = {5, 5, 10, 10}; // remainder of uninitialized values set to zero implicitly + int E[6] = {3, 6, 9, 12, 15, 15}; + int lastD = 3; // index of last item placed in D + int lastE = 5; // index of last item placed in E + chapter_10::sortedMerge(&D[0], lastD, &E[0], lastE); + for (int i = 0; i < 10; i++){ + REQUIRE(D[i] == C[i]); + } +} + +TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ + char s1[] = "Alex"; + char s1Rev[] = "xelA"; + char s2[] = "a"; + char s2Rev[] = "a"; + chapter_12::reverse(&s1[0]); + chapter_12::reverse(&s2[0]); + // strcmp returns 0 if the 2 strings are equal. + REQUIRE(strcmp(&s1[0], &s1Rev[0]) == 0); + REQUIRE(strcmp(&s2[0], &s2Rev[0]) == 0); +} + +TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ + std::vector targetVector = {1,2,3,4,5,6,7}; + chapter_02::SinglyLinkedNode* head = chapter_02::vectorToList(targetVector); + chapter_02::SinglyLinkedNode* copy = chapter_12::copyNode(head); + REQUIRE(targetVector == chapter_02::listToVector(copy)); // check that the values contained in nodes are identical + // Check that the pointers in the head linked list are *not* the same as the pointers in the copy likned list + // This is to verify a copy was actually made. + while (head != nullptr && copy != nullptr){ + REQUIRE(head != copy); + head = head->getNext(); + copy = copy->getNext(); + } +} + +TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ + Eigen::MatrixXd input1(4, 4); + input1 << 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1; + Eigen::MatrixXd output1(4, 4); + output1 << 1, 2, 3, 4, + 2, 4, 6, 8, + 3, 6, 9, 12, + 4, 8, 12, 16; + REQUIRE(output1.isApprox(misc::makeIntegralImage(input1))); + Eigen::MatrixXd output2(4, 4); + output2 << 1, 3, 6, 10, + 3, 9, 18, 30, + 6, 18, 36, 60, + 10, 30, 60, 100; + REQUIRE(output2.isApprox(misc::makeIntegralImage(output1))); +} + +TEST_CASE("Misc Exercises - boxFilter()", "test"){ + +} From 9652fe626968c85253a6a4776e9ad748101ff469 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 20 May 2019 08:35:32 -0800 Subject: [PATCH 056/176] WIP discovered python solution to 5.4 is completely wrong. implement correct getNext in C++. add new unit tests --- .../problem_05_04_nextNumber.cpp | 39 ++++++++++++++++++- .../problem_05_04_nextNumber.h | 5 ++- .../problem_05_04_next_number.py | 2 +- tests.cpp | 10 +++-- tests.py | 4 ++ 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index c3da45c..860e6a7 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -2,6 +2,7 @@ // Created by Alex Hagiopol on 2019-05-17. // #include "problem_05_04_nextNumber.h" +#include namespace chapter_05 { /* @@ -34,11 +35,45 @@ namespace chapter_05 { * * CODE: */ - int getNext(int positiveInteger) { + uint32_t getNext(uint32_t positiveInteger) { + uint32_t oneIndex = 0; // index of the rightmost 1 + uint32_t zeroIndex = 0; // index of the rightmost 0 that has 1s to the right of it + + if (positiveInteger == 0 || positiveInteger == UINT32_MAX) return -1; + + // find rightmost (i.e. least significant) "1" in bit sequence + uint32_t positiveIntegerCopy = positiveInteger; + while (positiveIntegerCopy != 0 && (positiveIntegerCopy & 1) != 1) { + oneIndex ++; + positiveIntegerCopy >>= 1; + } + + // find rightmost non-trailing "0" in bit sequence that is more significant than "1" position + positiveIntegerCopy = positiveInteger >> oneIndex + 1; // for zero to be non-trailing, we need to right shift before checking + zeroIndex += oneIndex + 1; + while (positiveIntegerCopy != 0 && (positiveIntegerCopy & 1) != 0) { + zeroIndex ++; + positiveIntegerCopy >>= 1; + } + + std::cout << "zeroIndex=" << zeroIndex << " \noneIndex=" << oneIndex << std::endl; + std::cout << "positiveInteger before flips" << positiveInteger << std::endl; + + // flip the zeroIndex bit to 1 + positiveInteger = positiveInteger | (1 << zeroIndex); + + // clear all bits to the right of zeroIndex + positiveInteger = positiveInteger & (UINT32_MAX << zeroIndex); + + // add in zeroIndex - oneIndex - 1 number of 1s to the end of the number (this accounts for examples like + // 0b11011001111100 where zeroIndex and oneIndex are separated by ones that need to be added in least significant + // places. + positiveInteger = positiveInteger | ((1 << (zeroIndex - oneIndex - 1)) - 1); return positiveInteger; } - int getPrev(int positiveInteger) { + + uint32_t getPrev(uint32_t positiveInteger) { return positiveInteger; } diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h index 267506b..1c8f758 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.h @@ -1,7 +1,8 @@ #pragma once +#include #include namespace chapter_05 { - int getNext(int positiveInteger); - int getPrev(int positiveInteger); + uint32_t getNext(uint32_t positiveInteger); + uint32_t getPrev(uint32_t positiveInteger); } diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py index 5be67f1..8c72503 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py @@ -39,7 +39,7 @@ def get_next(binary_list): """ strategy: 0. If the number is all ones e.g. [1111] insert a zero in the second most significant place e.g. [10111] - 1. find least significant "01". Note the position of the 0. + 1. Find least significant "1". Note the position of the 0. 2. Flip the 0 to a 1. 3. Find the least significant 1 whose position is *less significant* than the 0 we flipped. 4. Flip that 1 to a 0. diff --git a/tests.cpp b/tests.cpp index 461f4a3..9327400 100644 --- a/tests.cpp +++ b/tests.cpp @@ -844,18 +844,22 @@ TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { } TEST_CASE("Chapter 05 - Problem 04 - nextNumber()", "test"){ - /* //REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); REQUIRE(chapter_05::getNext(0b0100) == 0b1000); //REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); REQUIRE(chapter_05::getNext(0b0101) == 0b0110); //REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible - REQUIRE(chapter_05::getNext(0b1111) == 0b10111); // add an extra digit + REQUIRE(chapter_05::getNext(0b1111) == 0b10111); //REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible + //REQUIRE(chapter_05::getPrev(UINT32_MAX) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(UINT32_MAX) == -1); // there is no next number possible //REQUIRE(chapter_05::getPrev(0b1001) == 0b0101); REQUIRE(chapter_05::getNext(0b1001) == 0b1010); - */ + //REQUIRE(chapter_05::getPrev(0b0110) == 0b0101); + REQUIRE(chapter_05::getNext(0b0110) == 0b1001); + REQUIRE(chapter_05::getNext(0b11011001111100) == 0b11011010001111); + } TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ diff --git a/tests.py b/tests.py index aaba73d..acdf024 100644 --- a/tests.py +++ b/tests.py @@ -844,6 +844,7 @@ def test_problem_5_3(self): self.assertEqual(p_5_3.flip_bit_to_win(0b10), 2) def test_problem_5_4(self): + ''' # See the note in the problem implementation for the reasoning behind using lists of string characters. self.assertEqual(p_5_4.get_prev(['0', '1', '0', '0']), ['0', '0', '1', '0']) self.assertEqual(p_5_4.get_next(['0', '1', '0', '0']), ['1', '0', '0', '0']) @@ -855,6 +856,9 @@ def test_problem_5_4(self): self.assertEqual(p_5_4.get_next(['0', '0', '0', '0']), -1) self.assertEqual(p_5_4.get_prev(['1', '0', '0', '1']), ['0', '1', '0', '1']) self.assertEqual(p_5_4.get_next(['1', '0', '0', '1']), ['1', '0', '1', '0']) + self.assertEqual(p_5_4.get_prev(['0', '1', '1', '0']), ['0', '1', '0', '1']) + self.assertEqual(p_5_4.get_next(['0', '1', '1', '0']), ['1', '0', '1', '0']) + ''' def test_problem_5_6(self): self.assertEqual(p_5_6.conversion(0b11001100, 0b11110000), 4) From 27ebf7edc996251527602c3ebe7f2b7b43457141 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 20 May 2019 08:39:20 -0800 Subject: [PATCH 057/176] clarify algorithm description --- .../problem_05_04_nextNumber.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index 860e6a7..e538abb 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -18,16 +18,12 @@ namespace chapter_05 { * 0b0101 -> (0b0011, 0b0110) * * ALGORITHM: - * 1. To make a smaller number, shift least significant 1 that has space to move right - * a. Iterate through binary representation to find the rightmost 1 that has a 0 to its right - * b. & the input integer with 111...1110111 then | with 000...0000100 - * c. when we've found the rightmost 1, note its index, then create masks by left shifting a 1 to that index - * 2. To make a bigger number, shift least significant 1 that has space to move left - * ...same as above - * 3. Edge cases? - * a. 0b00...1 -> return (the number itself, its left shift) - * b. 0b10...0 -> return (its left shift, the number itself) - * c. 0b0 -> return (0,0) + * getNext(): + * 1. Use bit shifting to find the least significant 1. + * 2. Use bit shifting to find the least significant 0 *to the left of* the least significant 1 + * 3. Flip the zero position to 1. + * 4. Clear all ones to the right of the flipped bit. + * 5. Add in zeroIndex - oneIndex - 1 ones in the least significant positions that have been cleared out * * SPACE & TIME: * Space: O(b) - we need to allocate masks the same size as the input From 44a4db6536a074176c4df47a5b94f8a29e517ac1 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 21 May 2019 14:23:10 -0700 Subject: [PATCH 058/176] implement 5.4 C++ --- .../problem_05_04_nextNumber.cpp | 67 ++++++++++++++----- tests.cpp | 27 +++++--- 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index e538abb..af0742c 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -10,20 +10,30 @@ namespace chapter_05 { * Given a positive integer, return the next smallest and next largest * numbers that have the same number of 1s in their binary representations. * - * TEST CASE: - * positiveInteger -> (nextSmallest, nextLargest) - * 0b0000 -> (0, 0) - * 0b1000 -> (0b0100, ?) - * 0b0001 -> (?, 0b0010) - * 0b0101 -> (0b0011, 0b0110) + * TEST CASES: + * getPrev(0b0000) -> -1 + * getNext(0b0000) -> -1 + * getPrev(0b1000) -> 0b0100 + * getNext(0b1000) -> 0b10000 + * getPrev(0b0001) -> -1 + * getNext(0b0001) -> 0b0010 + * getPrev(0b0101) -> 0b0011 + * getNext(0b0101) -> 0b0110 * * ALGORITHM: * getNext(): * 1. Use bit shifting to find the least significant 1. * 2. Use bit shifting to find the least significant 0 *to the left of* the least significant 1 - * 3. Flip the zero position to 1. - * 4. Clear all ones to the right of the flipped bit. - * 5. Add in zeroIndex - oneIndex - 1 ones in the least significant positions that have been cleared out + * 3. Flip the 0 position to 1. + * 4. Clear all 1s to the right of the flipped bit. + * 5. Add in zeroIndex - oneIndex - 1 ones in the *least significant* positions that have been cleared out + * + * getPrev(): + * 1. Use bit shifting to find least significant 0. + * 2. Use bit shifting to find least significant 1 *to the left of* the least significant 0. + * 3. Flip the 1 position to 0. + * 4. Clear all 1s to the right of the flipped bit. + * 5. Add in zeroIndex + 1 ones in the *most significant* positions that have been cleared out. * * SPACE & TIME: * Space: O(b) - we need to allocate masks the same size as the input @@ -36,7 +46,7 @@ namespace chapter_05 { uint32_t oneIndex = 0; // index of the rightmost 1 uint32_t zeroIndex = 0; // index of the rightmost 0 that has 1s to the right of it - if (positiveInteger == 0 || positiveInteger == UINT32_MAX) return -1; + if (positiveInteger == 0 || positiveInteger == UINT32_MAX) return static_cast(-1); // find rightmost (i.e. least significant) "1" in bit sequence uint32_t positiveIntegerCopy = positiveInteger; @@ -46,16 +56,13 @@ namespace chapter_05 { } // find rightmost non-trailing "0" in bit sequence that is more significant than "1" position - positiveIntegerCopy = positiveInteger >> oneIndex + 1; // for zero to be non-trailing, we need to right shift before checking - zeroIndex += oneIndex + 1; + positiveIntegerCopy = positiveInteger >> (oneIndex + 1); // for zero to be non-trailing, we need to right shift before checking + zeroIndex = oneIndex + 1; while (positiveIntegerCopy != 0 && (positiveIntegerCopy & 1) != 0) { zeroIndex ++; positiveIntegerCopy >>= 1; } - std::cout << "zeroIndex=" << zeroIndex << " \noneIndex=" << oneIndex << std::endl; - std::cout << "positiveInteger before flips" << positiveInteger << std::endl; - // flip the zeroIndex bit to 1 positiveInteger = positiveInteger | (1 << zeroIndex); @@ -70,7 +77,37 @@ namespace chapter_05 { } uint32_t getPrev(uint32_t positiveInteger) { + uint32_t oneIndex = 0; // index of the rightmost 1 + uint32_t zeroIndex = 0; // index of the rightmost 0 that has 1s to the right of it + + if (positiveInteger == 0 || positiveInteger == UINT32_MAX) return static_cast(-1); + + // find the least significant zero + uint32_t positiveIntegerCopy = positiveInteger; + while (positiveIntegerCopy != 0 && (positiveIntegerCopy & 1) != 0) { + zeroIndex ++; + positiveIntegerCopy >>= 1; + } + + // find the least significant 1 *to the left of* the least significant zero + positiveIntegerCopy = positiveInteger >> (zeroIndex + 1); + if (positiveIntegerCopy == 0) return static_cast(-1); // check for 0b0...001111 edge case + oneIndex += zeroIndex + 1; // account for the right shift before computing one index + while (positiveIntegerCopy != 0 && (positiveIntegerCopy & 1) != 1) { + oneIndex ++; + positiveIntegerCopy >>= 1; + } + + // flip the oneIndex bit to 0 + positiveInteger = positiveInteger & (~(1 << oneIndex)); + + // clear all the bits to the right of oneIndex + positiveInteger = positiveInteger & (UINT32_MAX << oneIndex); + // add in zeroIndex + 1 number of ones in most significant positions to the right of oneIndex + uint32_t ones = (1 << (zeroIndex + 1)) - 1; + ones <<= (oneIndex - zeroIndex - 1); + positiveInteger |= ones; return positiveInteger; } } diff --git a/tests.cpp b/tests.cpp index 9327400..ebe210e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -844,22 +844,27 @@ TEST_CASE("Chapter 05 - Problem 03 - flipBitToWin()", "test") { } TEST_CASE("Chapter 05 - Problem 04 - nextNumber()", "test"){ - //REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); + REQUIRE(chapter_05::getPrev(0b0001) == -1); + REQUIRE(chapter_05::getNext(0b0001) == 0b0010); + REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); REQUIRE(chapter_05::getNext(0b0100) == 0b1000); - //REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); + REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); REQUIRE(chapter_05::getNext(0b0101) == 0b0110); - //REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible + REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible REQUIRE(chapter_05::getNext(0b1111) == 0b10111); - //REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible - REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible - //REQUIRE(chapter_05::getPrev(UINT32_MAX) == -1); // there is no previous number possible - REQUIRE(chapter_05::getNext(UINT32_MAX) == -1); // there is no next number possible - //REQUIRE(chapter_05::getPrev(0b1001) == 0b0101); + REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible + REQUIRE(chapter_05::getPrev(UINT32_MAX) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(UINT32_MAX) == -1); // there is no next number possible + REQUIRE(chapter_05::getPrev(0b1001) == 0b0110); + // 0b1001 = 1*2^0 + 0*2^1 + 0*2^2 + 1*2^3 = 9 + // 0b0101 = 1*2^0 + 0*2^1 + 1*2^2 + 0*2^3 = 5 + // 0b0110 = 0*2^0 + 1*2^1 + 1*2^2 + 0*2^3 = 6 <- this is the true getPrev(0b1001) result, not 5!! REQUIRE(chapter_05::getNext(0b1001) == 0b1010); - //REQUIRE(chapter_05::getPrev(0b0110) == 0b0101); + REQUIRE(chapter_05::getPrev(0b0110) == 0b0101); REQUIRE(chapter_05::getNext(0b0110) == 0b1001); - REQUIRE(chapter_05::getNext(0b11011001111100) == 0b11011010001111); - + REQUIRE(chapter_05::getPrev(0b10011110000011) == 0b10011101110000); // example from textbook + REQUIRE(chapter_05::getNext(0b11011001111100) == 0b11011010001111); // example from textbook } TEST_CASE("Chapter 05 - Problem 06 - conversion()", "test"){ From afa680632aff6269551bca6ef314aee5026c82d7 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 21 May 2019 14:27:26 -0700 Subject: [PATCH 059/176] update readme count --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c39f123..66ea714 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ reference and contribute solutions with confidence. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `5 / 7` complete. +5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `6 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `48` solutions. +C++ Total: `49` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `48` solutions. Python Total: `56` solutions. -##### Grand Total: `104` unique solutions. +##### Grand Total: `105` unique solutions. ### Building: #### Mac: From 668ad257aa9238c973af6ce047868dfcecfd5bc9 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 23 May 2019 12:44:55 -0700 Subject: [PATCH 060/176] WIP: fix get_prev() in 5.4 python. --- .../problem_05_04_nextNumber.cpp | 2 +- .../problem_05_04_next_number.py | 93 +++++++++++++------ tests.py | 38 ++++++++ 3 files changed, 104 insertions(+), 29 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index af0742c..4c2677f 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -80,7 +80,7 @@ namespace chapter_05 { uint32_t oneIndex = 0; // index of the rightmost 1 uint32_t zeroIndex = 0; // index of the rightmost 0 that has 1s to the right of it - if (positiveInteger == 0 || positiveInteger == UINT32_MAX) return static_cast(-1); + if (positiveInteger == 0 || positiveInteger >= UINT32_MAX) return static_cast(-1); // find the least significant zero uint32_t positiveIntegerCopy = positiveInteger; diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py index 8c72503..6222e0d 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py @@ -1,38 +1,75 @@ """ -For this problem, I use lists of single character strings to represent binary numbers because -Python has issues manipulating bits in the ways needed to solve this problem. -For example, Python automatically removes "redundant" leading zeros from a binary number. This makes it -difficult to flip all zeros in a binary number to get a desired number of ones. The workarounds -required to solve this problem using "native" binary numbers are - in my view - as ugly or uglier than using -lists of single character strings. - -If you have a beautiful Python solution for this problem, please PR it. - Alex +PROBLEM: +Given a positive integer, return the next smallest and next largest +numbers that have the same number of 1s in their binary representations. + +TEST CASES: +getPrev(0b0000) -> -1 +getNext(0b0000) -> -1 +getPrev(0b1000) -> 0b0100 +getNext(0b1000) -> 0b10000 +getPrev(0b0001) -> -1 +getNext(0b0001) -> 0b0010 +getPrev(0b0101) -> 0b0011 +getNext(0b0101) -> 0b0110 + +ALGORITHM: +getNext(): +1. Use bit shifting to find the least significant 1. +2. Use bit shifting to find the least significant 0 *to the left of* the least significant 1 +3. Flip the 0 position to 1. +4. Clear all 1s to the right of the flipped bit. +5. Add in zeroIndex - oneIndex - 1 ones in the *least significant* positions that have been cleared out + +getPrev(): +1. Use bit shifting to find least significant 0. +2. Use bit shifting to find least significant 1 *to the left of* the least significant 0. +3. Flip the 1 position to 0. +4. Clear all 1s to the right of the flipped bit. +5. Add in zeroIndex + 1 ones in the *most significant* positions that have been cleared out. + +SPACE & TIME: +Space: O(b) - we need to allocate masks the same size as the input +Time: O(b) - we need to iterate through the binary representation bit by bit + +CODE: """ +import numpy as np -def get_prev(binary_list): - """ - strategy: - 0. if all zeros or all ones, return none. - 1. find least significant "10". Note the position of the 1. - 2. Flip the 1 to a 0. - 3. Flip the 0 to a 1. - """ - if all(x == binary_list[0] for x in binary_list): # step 0 +def get_prev(positive_integer): + one_index = 0 + zero_index = 0 + + if positive_integer == 0 or positive_integer >= np.uint32(0xffffffff): return -1 - zero_index = -1 - one_index = -1 - for index in range(len(binary_list) - 1, 0, -1): # step 1. traverse list starting with least significant bit - if binary_list[index] == '0' and binary_list[index - 1] == '1': - one_index = index - 1 - zero_index = index - break - if one_index == -1: + positive_integer_copy = positive_integer + # find the least significant zero + while positive_integer_copy != 0 and (positive_integer_copy & 1) != 0: + zero_index = zero_index + 1 + positive_integer_copy = positive_integer_copy >> 1 + + # find the least significant one that is to the left of the least significant zero + positive_integer_copy = positive_integer >> (zero_index + 1) + if positive_integer_copy == 0: # check for 0b0...001111 edge case return -1 - binary_list[one_index] = '0' # step 2 - binary_list[zero_index] = '1' # step 4 - return binary_list + one_index = zero_index + 1 # account for the right shift before computing one index + while positive_integer_copy != 0 and (positive_integer_copy & 1) != 1: + one_index = one_index + 1 + positive_integer_copy = positive_integer_copy >> 1 + + # flip the 1 to a 0 + positive_integer = positive_integer & (~(1 << one_index)) + + # clear all 1s to the right of one_index + positive_integer = positive_integer & (np.uint32(0xffffffff) << one_index) + + # add in zero_index + 1 number of ones in most significant positions to the right of one_index + ones = (1 << (zero_index + 1)) - 1 + ones = ones << (one_index - zero_index - 1) + positive_integer = positive_integer | ones + return positive_integer def get_next(binary_list): diff --git a/tests.py b/tests.py index acdf024..802fe31 100644 --- a/tests.py +++ b/tests.py @@ -860,6 +860,44 @@ def test_problem_5_4(self): self.assertEqual(p_5_4.get_next(['0', '1', '1', '0']), ['1', '0', '1', '0']) ''' + ''' + REQUIRE(chapter_05::getPrev(0b0001) == -1); + REQUIRE(chapter_05::getNext(0b0001) == 0b0010); + REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); + REQUIRE(chapter_05::getNext(0b0100) == 0b1000); + REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); + REQUIRE(chapter_05::getNext(0b0101) == 0b0110); + REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible + REQUIRE(chapter_05::getNext(0b1111) == 0b10111); + REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible + + REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible + REQUIRE(chapter_05::getPrev(UINT32_MAX) == -1); // there is no previous number possible + + REQUIRE(chapter_05::getNext(UINT32_MAX) == -1); // there is no next number possible + REQUIRE(chapter_05::getPrev(0b1001) == 0b0110); + + // 0b1001 = 1*2^0 + 0*2^1 + 0*2^2 + 1*2^3 = 9 + // 0b0101 = 1*2^0 + 0*2^1 + 1*2^2 + 0*2^3 = 5 + // 0b0110 = 0*2^0 + 1*2^1 + 1*2^2 + 0*2^3 = 6 <- this is the true getPrev(0b1001) result, not 5!! + REQUIRE(chapter_05::getNext(0b1001) == 0b1010); + REQUIRE(chapter_05::getPrev(0b0110) == 0b0101); + REQUIRE(chapter_05::getNext(0b0110) == 0b1001); + REQUIRE(chapter_05::getPrev(0b10011110000011) == 0b10011101110000); // example from textbook + REQUIRE(chapter_05::getNext(0b11011001111100) == 0b11011010001111); // example from textbook + ''' + self.assertEqual(p_5_4.get_prev(0b0001), -1) + self.assertEqual(p_5_4.get_prev(0b0100), 0b0010) + self.assertEqual(p_5_4.get_prev(0b0101), 0b0011) + self.assertEqual(p_5_4.get_prev(0b1111), -1) + self.assertEqual(p_5_4.get_prev(0b0000), -1) + self.assertEqual(p_5_4.get_prev(np.uint32(0xffffffff)), -1) + self.assertEqual(p_5_4.get_prev(0b1001), 0b0110) + self.assertEqual(p_5_4.get_prev(0b0110), 0b0101) + self.assertEqual(p_5_4.get_prev(0b10011110000011), 0b10011101110000) + + + def test_problem_5_6(self): self.assertEqual(p_5_6.conversion(0b11001100, 0b11110000), 4) self.assertEqual(p_5_6.conversion(29, 15), 2) From b136c0d5c844b1f2db486bf0d04f9ff57a298d15 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 23 May 2019 14:03:39 -0700 Subject: [PATCH 061/176] fix 5.4 python --- .../problem_05_04_next_number.py | 57 +++++++++---------- tests.cpp | 2 +- tests.py | 53 +++-------------- 3 files changed, 37 insertions(+), 75 deletions(-) diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py index 6222e0d..c0f88dc 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_04_next_number.py @@ -72,36 +72,33 @@ def get_prev(positive_integer): return positive_integer -def get_next(binary_list): - """ - strategy: - 0. If the number is all ones e.g. [1111] insert a zero in the second most significant place e.g. [10111] - 1. Find least significant "1". Note the position of the 0. - 2. Flip the 0 to a 1. - 3. Find the least significant 1 whose position is *less significant* than the 0 we flipped. - 4. Flip that 1 to a 0. - """ - if all(x == '1' for x in binary_list): # step 0 - return ['1', '0'] + binary_list[1:] - - zero_index = -1 - for index in range(len(binary_list) - 1, 0, -1): # step 1. traverse list starting with least significant bit - if binary_list[index] == '1' and binary_list[index - 1] == '0': - zero_index = index - 1 - break - if zero_index == -1: - return -1 +def get_next(positive_integer): + one_index = 0 + zero_index = 0 - one_index = -1 - for index in range(len(binary_list) - 1, 0, -1): # step 3. - if binary_list[index] == '1': - one_index = index - break - if one_index == -1: - return -1 - if one_index <= zero_index: + if positive_integer == 0 or positive_integer == np.uint32(0xffffffff): return -1 - binary_list[zero_index] = '1' # step 2 - binary_list[one_index] = '0' # step 4 - return binary_list + # find least significant 1 + positive_integer_copy = positive_integer + while positive_integer_copy != 0 and (positive_integer_copy & 1) != 1: + one_index = one_index + 1 + positive_integer_copy = positive_integer_copy >> 1 + + # find least significant 0 that is to the left of the least significant 1 + positive_integer_copy = positive_integer >> (one_index + 1) + zero_index = zero_index + one_index + 1 + while positive_integer_copy != 0 and (positive_integer_copy & 1) != 0: + zero_index = zero_index + 1 + positive_integer_copy = positive_integer_copy >> 1 + + # flip the 0 to a 1 + positive_integer = positive_integer | (1 << zero_index) + + # clear all 1s to the right of zero_index + positive_integer = positive_integer & (np.uint32(0xffffffff) << zero_index) + + # add in zero_index - one_index - 1 number of 1s in the least significant positions + ones = (1 << (zero_index - one_index - 1)) - 1 + positive_integer = positive_integer | ones + return positive_integer diff --git a/tests.cpp b/tests.cpp index ebe210e..7be4277 100644 --- a/tests.cpp +++ b/tests.cpp @@ -859,7 +859,7 @@ TEST_CASE("Chapter 05 - Problem 04 - nextNumber()", "test"){ REQUIRE(chapter_05::getPrev(0b1001) == 0b0110); // 0b1001 = 1*2^0 + 0*2^1 + 0*2^2 + 1*2^3 = 9 // 0b0101 = 1*2^0 + 0*2^1 + 1*2^2 + 0*2^3 = 5 - // 0b0110 = 0*2^0 + 1*2^1 + 1*2^2 + 0*2^3 = 6 <- this is the true getPrev(0b1001) result, not 5!! + // 0b0110 = 0*2^0 + 1*2^1 + 1*2^2 + 0*2^3 = 6 <- N.B. this is the true getPrev(0b1001) result, not 5 REQUIRE(chapter_05::getNext(0b1001) == 0b1010); REQUIRE(chapter_05::getPrev(0b0110) == 0b0101); REQUIRE(chapter_05::getNext(0b0110) == 0b1001); diff --git a/tests.py b/tests.py index 802fe31..37506ab 100644 --- a/tests.py +++ b/tests.py @@ -844,59 +844,24 @@ def test_problem_5_3(self): self.assertEqual(p_5_3.flip_bit_to_win(0b10), 2) def test_problem_5_4(self): - ''' - # See the note in the problem implementation for the reasoning behind using lists of string characters. - self.assertEqual(p_5_4.get_prev(['0', '1', '0', '0']), ['0', '0', '1', '0']) - self.assertEqual(p_5_4.get_next(['0', '1', '0', '0']), ['1', '0', '0', '0']) - self.assertEqual(p_5_4.get_prev(['0', '1', '0', '1']), ['0', '0', '1', '1']) - self.assertEqual(p_5_4.get_next(['0', '1', '0', '1']), ['0', '1', '1', '0']) - self.assertEqual(p_5_4.get_prev(['1', '1', '1', '1']), -1) - self.assertEqual(p_5_4.get_next(['1', '1', '1', '1']), ['1', '0', '1', '1', '1']) - self.assertEqual(p_5_4.get_prev(['0', '0', '0', '0']), -1) - self.assertEqual(p_5_4.get_next(['0', '0', '0', '0']), -1) - self.assertEqual(p_5_4.get_prev(['1', '0', '0', '1']), ['0', '1', '0', '1']) - self.assertEqual(p_5_4.get_next(['1', '0', '0', '1']), ['1', '0', '1', '0']) - self.assertEqual(p_5_4.get_prev(['0', '1', '1', '0']), ['0', '1', '0', '1']) - self.assertEqual(p_5_4.get_next(['0', '1', '1', '0']), ['1', '0', '1', '0']) - ''' - - ''' - REQUIRE(chapter_05::getPrev(0b0001) == -1); - REQUIRE(chapter_05::getNext(0b0001) == 0b0010); - REQUIRE(chapter_05::getPrev(0b0100) == 0b0010); - REQUIRE(chapter_05::getNext(0b0100) == 0b1000); - REQUIRE(chapter_05::getPrev(0b0101) == 0b0011); - REQUIRE(chapter_05::getNext(0b0101) == 0b0110); - REQUIRE(chapter_05::getPrev(0b1111) == -1); // there is no previous number possible - REQUIRE(chapter_05::getNext(0b1111) == 0b10111); - REQUIRE(chapter_05::getPrev(0b0000) == -1); // there is no previous number possible - - REQUIRE(chapter_05::getNext(0b0000) == -1); // there is no next number possible - REQUIRE(chapter_05::getPrev(UINT32_MAX) == -1); // there is no previous number possible - - REQUIRE(chapter_05::getNext(UINT32_MAX) == -1); // there is no next number possible - REQUIRE(chapter_05::getPrev(0b1001) == 0b0110); - - // 0b1001 = 1*2^0 + 0*2^1 + 0*2^2 + 1*2^3 = 9 - // 0b0101 = 1*2^0 + 0*2^1 + 1*2^2 + 0*2^3 = 5 - // 0b0110 = 0*2^0 + 1*2^1 + 1*2^2 + 0*2^3 = 6 <- this is the true getPrev(0b1001) result, not 5!! - REQUIRE(chapter_05::getNext(0b1001) == 0b1010); - REQUIRE(chapter_05::getPrev(0b0110) == 0b0101); - REQUIRE(chapter_05::getNext(0b0110) == 0b1001); - REQUIRE(chapter_05::getPrev(0b10011110000011) == 0b10011101110000); // example from textbook - REQUIRE(chapter_05::getNext(0b11011001111100) == 0b11011010001111); // example from textbook - ''' self.assertEqual(p_5_4.get_prev(0b0001), -1) + self.assertEqual(p_5_4.get_next(0b0001), 0b0010) self.assertEqual(p_5_4.get_prev(0b0100), 0b0010) + self.assertEqual(p_5_4.get_next(0b0100), 0b1000) self.assertEqual(p_5_4.get_prev(0b0101), 0b0011) + self.assertEqual(p_5_4.get_next(0b0101), 0b0110) self.assertEqual(p_5_4.get_prev(0b1111), -1) + self.assertEqual(p_5_4.get_next(0b1111), 0b10111) self.assertEqual(p_5_4.get_prev(0b0000), -1) + self.assertEqual(p_5_4.get_next(0b0000), -1) self.assertEqual(p_5_4.get_prev(np.uint32(0xffffffff)), -1) + self.assertEqual(p_5_4.get_next(np.uint32(0xffffffff)), -1) self.assertEqual(p_5_4.get_prev(0b1001), 0b0110) + self.assertEqual(p_5_4.get_next(0b1001), 0b1010) self.assertEqual(p_5_4.get_prev(0b0110), 0b0101) + self.assertEqual(p_5_4.get_next(0b0110), 0b1001) self.assertEqual(p_5_4.get_prev(0b10011110000011), 0b10011101110000) - - + self.assertEqual(p_5_4.get_next(0b11011001111100), 0b11011010001111) def test_problem_5_6(self): self.assertEqual(p_5_6.conversion(0b11001100, 0b11110000), 4) From d9a6ee90443231a9999533d8b1d54662c3b66c63 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 23 May 2019 14:19:44 -0700 Subject: [PATCH 062/176] make test messaging more clear --- Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Makefile b/Makefile index a406eee..79d158e 100644 --- a/Makefile +++ b/Makefile @@ -11,14 +11,22 @@ clean: rm -rf build && mkdir build && cd build && cmake .. test: + @echo --------------------- @echo TESTING C++ SOLUTIONS + @echo --------------------- cd build && make -j6 && ./tests + @echo ------------------------ @echo TESTING PYTHON SOLUTIONS + @echo ------------------------ python3 tests.py test_coverage: + @echo --------------------- @echo TESTING C++ SOLUTIONS + @echo --------------------- cd build && make -j6 && ./tests + @echo ------------------------ @echo TESTING PYTHON SOLUTIONS + @echo ------------------------ coverage run --source=python_solutions tests.py coverage report -m From e6eecf1b18f3b6023a43fe37076005e0654b0b52 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 23 May 2019 14:28:09 -0700 Subject: [PATCH 063/176] fix typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 66ea714..674bf44 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Python Total: `56` solutions. ### Building: #### Mac: -Mac usage requires the package managers Homebrew and Pip which is done for you in the Makefile: +Mac usage requires installing the package managers Homebrew and Pip which is done for you in the Makefile: git clone https://github.com/alexhagiopol/cracking-the-coding-interview.git ctci cd ctci From 655fb4cd875b9734403047abfaa394cb187cc50a Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 3 Jun 2019 23:32:16 -0800 Subject: [PATCH 064/176] 5.8 C++ WIP. Implemented stringifyScreen(). --- CMakeLists.txt | 6 ++- .../chapter_05_includes.h | 1 + .../problem_05_08_drawLine.cpp | 32 ++++++++++++++ .../problem_05_08_drawLine.h | 7 ++++ .../problem_05_08_draw_line.py | 42 ++++++++++++++++++- tests.cpp | 38 +++++++++++++++++ tests.py | 2 +- 7 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp create mode 100644 cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a3a94f..4dc84b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_solutions/third_party/eigen) # set source files set(SOURCE_FILES tests.cpp + # chapter 1 cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp @@ -18,17 +19,20 @@ set(SOURCE_FILES cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp - # chapter 2 .cpp files not included because they are template functions implemented in .h files + # chapter 2 .cpp files not included because they are template functions implemented in .h files # chapter 3 .cpp files not included because they are template functions implemented in .h files cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp # chapter 4 .cpp files not included because they are template functions implemented in .h files cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp + # chapter 5 cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp + cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp + # chapter 8 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp diff --git a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h index 8ab824c..98fb47e 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h +++ b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h @@ -10,3 +10,4 @@ #include "problem_05_04_nextNumber.h" #include "problem_05_06_conversion.h" #include "problem_05_07_pairwiseSwap.h" +#include "problem_05_08_drawLine.h" diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp new file mode 100644 index 0000000..f1100d7 --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp @@ -0,0 +1,32 @@ +// +// Created by alex on 6/3/2019. +// +#include "problem_05_08_drawLine.h" +#include +#include + +namespace chapter_05 { + std::string stringifyScreen(const uint8_t* screen, uint32_t bitWidth, uint32_t bitLength) { + assert((bitWidth % 8) == 0); + assert((bitLength % 8) == 0); + int byteWidth = bitWidth / 8; + int byteLength = bitLength / 8; + assert((byteLength % byteWidth) == 0); + int height = byteLength / byteWidth; + // we use one character for each pixel plus byteWidth * height extra characters for spaces and newline characters + std::string stringScreen(byteLength * 8 + byteWidth * height, ' '); + int i = 0; + for (int r = 0; r < height; r++) { + for (int c = 0; c < byteWidth; c++) { + uint8_t currentByte = screen[r * byteWidth + c]; + for (int b = 0; b < 8; b++) { + stringScreen[i] = static_cast(((currentByte >> b) & 1) + 48); // ASCII table: 48 = 0; 49 = 1 + i++; + } + stringScreen[i] = '\n'; + i++; + } + } + return stringScreen; + } +} diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h new file mode 100644 index 0000000..1af3cf6 --- /dev/null +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h @@ -0,0 +1,7 @@ +#pragma once +#include + +namespace chapter_05 { + std::string stringifyScreen(const uint8_t* screen, uint32_t bitWidth, uint32_t bitLength); + void drawLine(uint8_t* screen, uint32_t bitWidth, uint32_t bitLength); +} diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py b/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py index cd1c843..67f8775 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py @@ -1,11 +1,51 @@ +""" +PROBLEM: +A monochrome screen is stored as a single array of bytes, allowing eight consecutive pixels to be stored in one byte. +The screen has width W which is a multiple of 8. So, a screen with dimensions 2x16 will require 2x2 8-bit +integers to represent it. The goal is to write a program to draw a horizontal line given coordinates (x1, y) and (x2, y). + +TEST CASES: +x1 = 1 +x2 = 14 +y = 1 + +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 --> 01111111 11111111 11111111 11111110 +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 + +x1 = 1 +x2 = 7 +y = 1 + +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 --> 01111111 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 + +ALGORITHM: +Determine in which bytes x1 and x2 reside. Handle the following cases: +1. x1 < 0 || x1 > W || x2 < 0 || x2 > W || x2 > x1 || y < 0 || y > height + Do nothing. Invalid input. +2. x1 and x2 in the same byte: + Add (x2 - x1 + 1) 1s and left shift them by 8 - x2. +3. x1 and x2 are one whole byte apart or more + Set all in-between bytes to 0xFF. Assign the appropriate number of 1s to the x1 and x2 bytes by left shifting a 1 and then subtracting 1. + +SPACE & TIME: +Time: O(W): the number of operations required to do this procedure scale linearly with W. +Space: O(1): the amount of extra memory required to do this procedure does not scale with the input size + +CODE: +""" + + def stringify_screen(screen, width): assert (width % 8 == 0) string = '' height = len(screen) * 8 // width for h in range(0, height): - string += '\n' for w in range(0, width // 8): string += format(screen[h * width // 8 + w], '#010b')[2:] + string += '\n' return string diff --git a/tests.cpp b/tests.cpp index 7be4277..905d0f8 100644 --- a/tests.cpp +++ b/tests.cpp @@ -878,6 +878,44 @@ TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ REQUIRE(chapter_05::pairwiseSwap(0b110) == 0b1001); } +TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ + /* + screen_1 = [0] * 8 + width_1 = 8 + x1_1 = 3 + x2_1 = 7 + y_1 = 5 + processed_screen_1 = [0] * 5 + [0b00011111] + [0] * 2 + self.assertEqual(p_5_8.stringify_screen(screen_1, width_1), + '\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000') + p_5_8.draw_line(screen_1, width_1, x1_1, x2_1, y_1) + self.assertEqual(screen_1, processed_screen_1) + + screen_2 = [0] * 8 + width_2 = 32 + x1_2 = 0 + x2_2 = 13 + y_2 = 1 + processed_screen_2 = [0] * 4 + [255] + [0b11111100] + [0] * 2 + p_5_8.draw_line(screen_2, width_2, x1_2, x2_2, y_2) + self.assertEqual(screen_2, processed_screen_2) + + screen_3 = [0] * 32 + width_3 = 64 + x1_3 = 5 + x2_3 = 24 + y_3 = 1 + processed_screen_3 = [0] * 8 + [0b00000111] + [255] + [255] + [0b10000000] + [0] * 20 + p_5_8.draw_line(screen_3, width_3, x1_3, x2_3, y_3) + self.assertEqual(screen_3, processed_screen_3) + */ + uint8_t screen1[8] = {0,0,0,0,0,0,0,0}; + uint32_t bitWidth1 = 8; + uint32_t bitLength1 = 64; + std::string expectedScreen1 = "00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n"; + REQUIRE(expectedScreen1 == chapter_05::stringifyScreen(&screen1[0], bitWidth1, bitLength1)); +} + TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ REQUIRE(chapter_08::tripleStep(3) == 4); REQUIRE(chapter_08::tripleStep(4) == 7); diff --git a/tests.py b/tests.py index 37506ab..e5ac974 100644 --- a/tests.py +++ b/tests.py @@ -880,7 +880,7 @@ def test_problem_5_8(self): y_1 = 5 processed_screen_1 = [0] * 5 + [0b00011111] + [0] * 2 self.assertEqual(p_5_8.stringify_screen(screen_1, width_1), - '\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000') + '00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n') p_5_8.draw_line(screen_1, width_1, x1_1, x2_1, y_1) self.assertEqual(screen_1, processed_screen_1) From dcb7c9d103776fc1046d7a5e26974ba19b2d659e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 4 Jun 2019 21:17:21 -0800 Subject: [PATCH 065/176] fix bug in stringifyScreen(). add unit tests for stringifyScreen() in python and C++ --- .../problem_05_08_drawLine.cpp | 50 ++++++++++++++++--- tests.cpp | 22 ++++++-- tests.py | 7 +++ 3 files changed, 70 insertions(+), 9 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp index f1100d7..9db051a 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp @@ -1,6 +1,42 @@ -// -// Created by alex on 6/3/2019. -// +/* +PROBLEM: +A monochrome screen is stored as a single array of bytes, allowing eight consecutive pixels to be stored in one byte. +The screen has width W which is a multiple of 8. So, a screen with dimensions 2x16 will require 2x2 8-bit +integers to represent it. The goal is to write a program to draw a horizontal line given coordinates (x1, y) and (x2, y). + +TEST CASES: +x1 = 1 +x2 = 14 +y = 1 + +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 --> 01111111 11111111 11111111 11111110 +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 + +x1 = 1 +x2 = 7 +y = 1 + +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 --> 01111111 00000000 00000000 00000000 +00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 + +ALGORITHM: +Determine in which bytes x1 and x2 reside. Handle the following cases: +1. x1 < 0 || x1 > W || x2 < 0 || x2 > W || x2 > x1 || y < 0 || y > height + Do nothing. Invalid input. +2. x1 and x2 in the same byte: + Add (x2 - x1 + 1) 1s and left shift them by 8 - x2. +3. x1 and x2 are one whole byte apart or more + Set all in-between bytes to 0xFF. Assign the appropriate number of 1s to the x1 and x2 bytes by left shifting a 1 and then subtracting 1. + +SPACE & TIME: +Time: O(W): the number of operations required to do this procedure scale linearly with W. +Space: O(1): the amount of extra memory required to do this procedure does not scale with the input size + +CODE: +*/ + #include "problem_05_08_drawLine.h" #include #include @@ -14,7 +50,7 @@ namespace chapter_05 { assert((byteLength % byteWidth) == 0); int height = byteLength / byteWidth; // we use one character for each pixel plus byteWidth * height extra characters for spaces and newline characters - std::string stringScreen(byteLength * 8 + byteWidth * height, ' '); + std::string stringScreen(bitLength + height, ' '); int i = 0; for (int r = 0; r < height; r++) { for (int c = 0; c < byteWidth; c++) { @@ -23,8 +59,10 @@ namespace chapter_05 { stringScreen[i] = static_cast(((currentByte >> b) & 1) + 48); // ASCII table: 48 = 0; 49 = 1 i++; } - stringScreen[i] = '\n'; - i++; + if (c == (byteWidth - 1)) { + stringScreen[i] = '\n'; + i++; + } } } return stringScreen; diff --git a/tests.cpp b/tests.cpp index 905d0f8..f120320 100644 --- a/tests.cpp +++ b/tests.cpp @@ -909,12 +909,28 @@ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ p_5_8.draw_line(screen_3, width_3, x1_3, x2_3, y_3) self.assertEqual(screen_3, processed_screen_3) */ - uint8_t screen1[8] = {0,0,0,0,0,0,0,0}; + uint32_t bitWidth1 = 8; uint32_t bitLength1 = 64; + uint8_t screen1[bitLength1 / 8] = {0}; std::string expectedScreen1 = "00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n"; - REQUIRE(expectedScreen1 == chapter_05::stringifyScreen(&screen1[0], bitWidth1, bitLength1)); -} + REQUIRE(expectedScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); + + uint32_t bitWidth2 = 32; + uint32_t bitLength2 = 64; + uint8_t screen2[bitLength2 / 8] = {0}; + std::string expectedScreen2 = "00000000000000000000000000000000\n00000000000000000000000000000000\n"; + REQUIRE(expectedScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); + + uint32_t bitWidth3 = 64; + uint32_t bitLength3 = 256; + uint8_t screen3[bitLength3 / 8] = {0}; + std::string expectedScreen3 = "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n"; + REQUIRE(expectedScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); +}; TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ REQUIRE(chapter_08::tripleStep(3) == 4); diff --git a/tests.py b/tests.py index e5ac974..f307aec 100644 --- a/tests.py +++ b/tests.py @@ -890,6 +890,8 @@ def test_problem_5_8(self): x2_2 = 13 y_2 = 1 processed_screen_2 = [0] * 4 + [255] + [0b11111100] + [0] * 2 + self.assertEqual(p_5_8.stringify_screen(screen_2, width_2), + '00000000000000000000000000000000\n00000000000000000000000000000000\n') p_5_8.draw_line(screen_2, width_2, x1_2, x2_2, y_2) self.assertEqual(screen_2, processed_screen_2) @@ -899,6 +901,11 @@ def test_problem_5_8(self): x2_3 = 24 y_3 = 1 processed_screen_3 = [0] * 8 + [0b00000111] + [255] + [255] + [0b10000000] + [0] * 20 + self.assertEqual(p_5_8.stringify_screen(screen_3, width_3), + '0000000000000000000000000000000000000000000000000000000000000000\n' + '0000000000000000000000000000000000000000000000000000000000000000\n' + '0000000000000000000000000000000000000000000000000000000000000000\n' + '0000000000000000000000000000000000000000000000000000000000000000\n') p_5_8.draw_line(screen_3, width_3, x1_3, x2_3, y_3) self.assertEqual(screen_3, processed_screen_3) From ef6b33c0134fc37ebe853ba592761e6e5cfed50a Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 4 Jun 2019 21:47:17 -0800 Subject: [PATCH 066/176] upgrade compiler to fix compilation error with array initialization --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 79d158e..306f8f6 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ configure-mac: git submodule update --init && ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" && brew install python && easy_install pip && pip install numpy && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. configure-ubuntu: - git submodule update --init && sudo apt-get install -y build-essential cmake python3 python3-numpy && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. + git submodule update --init && sudo apt-get install -y build-essential cmake python3 python3-numpy gcc-7 && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. clean: rm -rf build && mkdir build && cd build && cmake .. From ca48da3f8d7193d0fc1b796a1e143d3bbc7473ac Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 4 Jun 2019 21:54:37 -0800 Subject: [PATCH 067/176] attempt to install gcc-7 on test server --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 306f8f6..2440020 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ configure: - git submodule update --init && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. + git submodule update --init && sudo apt-get install -y gcc-7 && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. configure-mac: git submodule update --init && ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" && brew install python && easy_install pip && pip install numpy && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. From eaea54c013a358a6c29e8b3dbea91b5bdfa2265e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 4 Jun 2019 21:59:43 -0800 Subject: [PATCH 068/176] WIP fix GCC version in cloud --- .travis.yml | 2 ++ Makefile | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4dc6382..5ed5a41 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ +before_install: + - sudo apt-get install -y gcc-7 language: python sudo: required python: diff --git a/Makefile b/Makefile index 2440020..306f8f6 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ configure: - git submodule update --init && sudo apt-get install -y gcc-7 && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. + git submodule update --init && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. configure-mac: git submodule update --init && ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" && brew install python && easy_install pip && pip install numpy && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. From 1bc22a62755860f72a17f570e911c4226fa152ad Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 4 Jun 2019 22:04:56 -0800 Subject: [PATCH 069/176] another attempt to update GCC version on cloud machine --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5ed5a41..bdada50 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,7 @@ before_install: - - sudo apt-get install -y gcc-7 + - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test + - sudo apt-get update -y + - sudo apt-get install -y gcc-7 g++-7 language: python sudo: required python: From ab1b0eb65dac6a7d2d25cebf5e3d99cafa50ee24 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 4 Jun 2019 22:12:52 -0800 Subject: [PATCH 070/176] give up on compiler upgrade due to massive build time increase. conform to old rules for array initialization --- .travis.yml | 4 ---- Makefile | 2 +- tests.cpp | 6 +++--- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index bdada50..4dc6382 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,3 @@ -before_install: - - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test - - sudo apt-get update -y - - sudo apt-get install -y gcc-7 g++-7 language: python sudo: required python: diff --git a/Makefile b/Makefile index 306f8f6..79d158e 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ configure-mac: git submodule update --init && ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)" && brew install python && easy_install pip && pip install numpy && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. configure-ubuntu: - git submodule update --init && sudo apt-get install -y build-essential cmake python3 python3-numpy gcc-7 && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. + git submodule update --init && sudo apt-get install -y build-essential cmake python3 python3-numpy && cd cpp_solutions/third_party/eigen && rm -rf build && mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && sudo make install && cd ../../../.. && rm -rf build && mkdir build && cd build && cmake .. clean: rm -rf build && mkdir build && cd build && cmake .. diff --git a/tests.cpp b/tests.cpp index f120320..e5be0f4 100644 --- a/tests.cpp +++ b/tests.cpp @@ -912,19 +912,19 @@ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ uint32_t bitWidth1 = 8; uint32_t bitLength1 = 64; - uint8_t screen1[bitLength1 / 8] = {0}; + uint8_t screen1[64 / 8] = {0}; std::string expectedScreen1 = "00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n"; REQUIRE(expectedScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); uint32_t bitWidth2 = 32; uint32_t bitLength2 = 64; - uint8_t screen2[bitLength2 / 8] = {0}; + uint8_t screen2[64 / 8] = {0}; std::string expectedScreen2 = "00000000000000000000000000000000\n00000000000000000000000000000000\n"; REQUIRE(expectedScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); uint32_t bitWidth3 = 64; uint32_t bitLength3 = 256; - uint8_t screen3[bitLength3 / 8] = {0}; + uint8_t screen3[256 / 8] = {0}; std::string expectedScreen3 = "0000000000000000000000000000000000000000000000000000000000000000\n" "0000000000000000000000000000000000000000000000000000000000000000\n" "0000000000000000000000000000000000000000000000000000000000000000\n" From 81d35ff0521edc90cef7df6ec584ff7f6d87c221 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 5 Jun 2019 13:45:31 -0700 Subject: [PATCH 071/176] refactor 5.8 unit tests for clarity and additional coverage --- .../problem_05_08_drawLine.cpp | 10 ++ .../problem_05_08_drawLine.h | 2 +- .../problem_05_08_draw_line.py | 2 +- tests.cpp | 110 +++++++++++------- tests.py | 69 ++++++++--- 5 files changed, 136 insertions(+), 57 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp index 9db051a..d9133dd 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp @@ -67,4 +67,14 @@ namespace chapter_05 { } return stringScreen; } + + void drawLine( + uint8_t* screen, + uint32_t bitWidth, + uint32_t bitLength, + uint32_t x1, + uint32_t x2, + uint32_t y) { + + } } diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h index 1af3cf6..b706c3e 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.h @@ -3,5 +3,5 @@ namespace chapter_05 { std::string stringifyScreen(const uint8_t* screen, uint32_t bitWidth, uint32_t bitLength); - void drawLine(uint8_t* screen, uint32_t bitWidth, uint32_t bitLength); + void drawLine(uint8_t* screen, uint32_t bitWidth, uint32_t bitLength, uint32_t x1, uint32_t x2, uint32_t y); } diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py b/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py index 67f8775..24c6e16 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py @@ -63,7 +63,7 @@ def single_byte_line(x1, x2): def draw_line(screen, width, x1, x2, y): assert(width % 8 == 0) - assert(0 <= x1 < x2 <= width) + assert(0 <= x1 <= x2 <= width) assert(0 <= y <= len(screen) * 8 / width - 1) x1_byte_index = y * width // 8 + x1 // 8 diff --git a/tests.cpp b/tests.cpp index e5be0f4..a36b94e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -880,57 +880,87 @@ TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ /* - screen_1 = [0] * 8 - width_1 = 8 - x1_1 = 3 - x2_1 = 7 - y_1 = 5 - processed_screen_1 = [0] * 5 + [0b00011111] + [0] * 2 - self.assertEqual(p_5_8.stringify_screen(screen_1, width_1), - '\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000') - p_5_8.draw_line(screen_1, width_1, x1_1, x2_1, y_1) - self.assertEqual(screen_1, processed_screen_1) - - screen_2 = [0] * 8 - width_2 = 32 - x1_2 = 0 - x2_2 = 13 - y_2 = 1 - processed_screen_2 = [0] * 4 + [255] + [0b11111100] + [0] * 2 - p_5_8.draw_line(screen_2, width_2, x1_2, x2_2, y_2) - self.assertEqual(screen_2, processed_screen_2) - - screen_3 = [0] * 32 - width_3 = 64 - x1_3 = 5 - x2_3 = 24 - y_3 = 1 - processed_screen_3 = [0] * 8 + [0b00000111] + [255] + [255] + [0b10000000] + [0] * 20 - p_5_8.draw_line(screen_3, width_3, x1_3, x2_3, y_3) - self.assertEqual(screen_3, processed_screen_3) - */ - + * Screen #1: Line goes middle to end. Line spans less than 8 bits. + */ uint32_t bitWidth1 = 8; uint32_t bitLength1 = 64; uint8_t screen1[64 / 8] = {0}; - std::string expectedScreen1 = "00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n"; - REQUIRE(expectedScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); + uint32_t x1_1 = 3; + uint32_t x2_1 = 7; + uint32_t y_1 = 5; + std::string expectedInitialScreen1 = "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n"; + std::string expectedFinalScreen1 = "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n" + "00000000\n" + "00011111\n" + "00000000\n" + "00000000\n"; + REQUIRE(expectedInitialScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); + chapter_05::drawLine(screen1, bitWidth1, bitLength1, x1_1, x2_1, y_1); + // REQUIRE(expectedFinalScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); + /* + * Screen #2: Line spans more than 8 bits. + */ uint32_t bitWidth2 = 32; uint32_t bitLength2 = 64; uint8_t screen2[64 / 8] = {0}; - std::string expectedScreen2 = "00000000000000000000000000000000\n00000000000000000000000000000000\n"; - REQUIRE(expectedScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); + uint32_t x1_2 = 0; + uint32_t x2_2 = 13; + uint32_t y_2 = 1; + std::string expectedInitialScreen2 = "00000000000000000000000000000000\n" + "00000000000000000000000000000000\n"; + std::string expectedFinalScreen2 = "00000000000000000000000000000000\n" + "11111111111111000000000000000000\n"; + REQUIRE(expectedInitialScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); + chapter_05::drawLine(screen2, bitWidth2, bitLength2, x1_2, x2_2, y_2); + // REQUIRE(expectedFinalScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); + /* + * Screen #3: Line spans more than 8 bits. + */ uint32_t bitWidth3 = 64; uint32_t bitLength3 = 256; uint8_t screen3[256 / 8] = {0}; - std::string expectedScreen3 = "0000000000000000000000000000000000000000000000000000000000000000\n" - "0000000000000000000000000000000000000000000000000000000000000000\n" - "0000000000000000000000000000000000000000000000000000000000000000\n" - "0000000000000000000000000000000000000000000000000000000000000000\n"; - REQUIRE(expectedScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); -}; + uint32_t x1_3 = 5; + uint32_t x2_3 = 24; + uint32_t y_3 = 1; + std::string expectedInitialScreen3 = "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n"; + std::string expectedFinalScreen3 = "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000011111111111111111111000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n" + "0000000000000000000000000000000000000000000000000000000000000000\n"; + REQUIRE(expectedInitialScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); + chapter_05::drawLine(screen3, bitWidth3, bitLength3, x1_3, x2_3, y_3); + // REQUIRE(expectedFinalScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); + + /* + * Screen #4: Line spans a single bit. + */ + uint32_t bitWidth4 = 8; + uint32_t bitLength4 = 8; + uint8_t screen4[1] = {0}; + uint32_t x1_4 = 3; + uint32_t x2_4 = 3; + uint32_t y_4 = 0; + std::string expectedInitialScreen4 = "00000000\n"; + std::string expectedFinalScreen4 = "00010000\n"; + REQUIRE(expectedInitialScreen4 == chapter_05::stringifyScreen(screen4, bitWidth4, bitLength4)); + chapter_05::drawLine(screen4, bitWidth4, bitLength4, x1_4, x2_4, y_4); + // REQUIRE(expectedFinalScreen1 == chapter_05::stringifyScreen(screen4, bitWidth4, bitLength4)); +} TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ REQUIRE(chapter_08::tripleStep(3) == 4); diff --git a/tests.py b/tests.py index f307aec..481cff2 100644 --- a/tests.py +++ b/tests.py @@ -873,41 +873,80 @@ def test_problem_5_7(self): self.assertEqual(p_5_7.pairwise_swap(0b110), 0b1001) def test_problem_5_8(self): + # Screen #1: Line spans less than 8 bits. screen_1 = [0] * 8 width_1 = 8 x1_1 = 3 x2_1 = 7 y_1 = 5 - processed_screen_1 = [0] * 5 + [0b00011111] + [0] * 2 - self.assertEqual(p_5_8.stringify_screen(screen_1, width_1), - '00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n00000000\n') + # processed_screen_1 = [0] * 5 + [0b00011111] + [0] * 2 + expected_initial_screen_1 = '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n' + expected_final_screen_1 = '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00000000\n'\ + '00011111\n'\ + '00000000\n'\ + '00000000\n' + self.assertEqual(expected_initial_screen_1, p_5_8.stringify_screen(screen_1, width_1)) p_5_8.draw_line(screen_1, width_1, x1_1, x2_1, y_1) - self.assertEqual(screen_1, processed_screen_1) + self.assertEqual(expected_final_screen_1, p_5_8.stringify_screen(screen_1, width_1)) + # Screen #2: Line spans more than 8 bits. screen_2 = [0] * 8 width_2 = 32 x1_2 = 0 x2_2 = 13 y_2 = 1 - processed_screen_2 = [0] * 4 + [255] + [0b11111100] + [0] * 2 - self.assertEqual(p_5_8.stringify_screen(screen_2, width_2), - '00000000000000000000000000000000\n00000000000000000000000000000000\n') + # processed_screen_2 = [0] * 4 + [255] + [0b11111100] + [0] * 2 + expected_initial_screen_2 = '00000000000000000000000000000000\n'\ + '00000000000000000000000000000000\n' + expected_final_screen_2 = '00000000000000000000000000000000\n'\ + '11111111111111000000000000000000\n' + + self.assertEqual(expected_initial_screen_2, p_5_8.stringify_screen(screen_2, width_2)) p_5_8.draw_line(screen_2, width_2, x1_2, x2_2, y_2) - self.assertEqual(screen_2, processed_screen_2) + self.assertEqual(expected_final_screen_2, p_5_8.stringify_screen(screen_2, width_2)) + # Screen #3: Line spans more than 8 bits. screen_3 = [0] * 32 width_3 = 64 x1_3 = 5 x2_3 = 24 y_3 = 1 - processed_screen_3 = [0] * 8 + [0b00000111] + [255] + [255] + [0b10000000] + [0] * 20 - self.assertEqual(p_5_8.stringify_screen(screen_3, width_3), - '0000000000000000000000000000000000000000000000000000000000000000\n' - '0000000000000000000000000000000000000000000000000000000000000000\n' - '0000000000000000000000000000000000000000000000000000000000000000\n' - '0000000000000000000000000000000000000000000000000000000000000000\n') + # processed_screen_3 = [0] * 8 + [0b00000111] + [255] + [255] + [0b10000000] + [0] * 20 + expected_initial_screen_3 = '0000000000000000000000000000000000000000000000000000000000000000\n'\ + '0000000000000000000000000000000000000000000000000000000000000000\n'\ + '0000000000000000000000000000000000000000000000000000000000000000\n'\ + '0000000000000000000000000000000000000000000000000000000000000000\n' + expected_final_screen_3 = '0000000000000000000000000000000000000000000000000000000000000000\n'\ + '0000011111111111111111111000000000000000000000000000000000000000\n'\ + '0000000000000000000000000000000000000000000000000000000000000000\n'\ + '0000000000000000000000000000000000000000000000000000000000000000\n' + + self.assertEqual(expected_initial_screen_3, p_5_8.stringify_screen(screen_3, width_3)) p_5_8.draw_line(screen_3, width_3, x1_3, x2_3, y_3) - self.assertEqual(screen_3, processed_screen_3) + self.assertEqual(expected_final_screen_3, p_5_8.stringify_screen(screen_3, width_3)) + + # Screen #4: Line spans a single bit. + screen_4 = [0] + width_4 = 8 + x1_4 = 3 + x2_4 = 3 + y_4 = 0 + expected_initial_screen_4 = '00000000\n' + expected_final_screen_4 = '00010000\n' + self.assertEqual(expected_initial_screen_4, p_5_8.stringify_screen(screen_4, width_4)) + p_5_8.draw_line(screen_4, width_4, x1_4, x2_4, y_4) + self.assertEqual(expected_final_screen_4, p_5_8.stringify_screen(screen_4, width_4)) def test_problem_8_1(self): self.assertEqual(p_8_1.triple_step(3), 4) From 6bbafe1d1fd57a5b0be0875c558364ba179b7d48 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 5 Jun 2019 15:26:58 -0700 Subject: [PATCH 072/176] implement 5.8 C++ --- .../problem_05_08_drawLine.cpp | 48 ++++++++++++++++--- .../problem_05_08_draw_line.py | 6 +-- tests.cpp | 25 ++++------ 3 files changed, 53 insertions(+), 26 deletions(-) diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp index d9133dd..3df395d 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp @@ -50,14 +50,17 @@ namespace chapter_05 { assert((byteLength % byteWidth) == 0); int height = byteLength / byteWidth; // we use one character for each pixel plus byteWidth * height extra characters for spaces and newline characters - std::string stringScreen(bitLength + height, ' '); + std::string stringScreen(bitLength + height, 'X'); int i = 0; - for (int r = 0; r < height; r++) { - for (int c = 0; c < byteWidth; c++) { + for (uint32_t r = 0; r < height; r++) { + for (uint32_t c = 0; c < byteWidth; c++) { uint8_t currentByte = screen[r * byteWidth + c]; - for (int b = 0; b < 8; b++) { - stringScreen[i] = static_cast(((currentByte >> b) & 1) + 48); // ASCII table: 48 = 0; 49 = 1 + for (int b = 7; b >= 0; b--) { // use int b because we must allow neg values for zero comparison. reverse traversal order for bits to match little endian format + uint8_t mask = static_cast(1) << b; + bool maskMatchesCurrentByte = (currentByte & mask) != 0; + stringScreen[i] = static_cast(static_cast(maskMatchesCurrentByte) + 48); // ASCII table: 48 = 0; 49 = 1 i++; + } if (c == (byteWidth - 1)) { stringScreen[i] = '\n'; @@ -68,13 +71,44 @@ namespace chapter_05 { return stringScreen; } + uint8_t singleByteLine(uint8_t x1, uint8_t x2) { + assert((x1 >= 0) && (x1 < 8) && (x2 >= 0) && (x2 < 8) && (x2 >= x1)); + uint8_t numOnes = x2 - x1 + 1; + uint8_t byte = (static_cast(1) << numOnes) - 1; + byte <<= static_cast(8 - x2 - 1); + return byte; + } + void drawLine( uint8_t* screen, uint32_t bitWidth, uint32_t bitLength, - uint32_t x1, - uint32_t x2, + uint32_t x1BitIndex, + uint32_t x2BitIndex, uint32_t y) { + assert((x1BitIndex >=0) && + (x1BitIndex < bitWidth) && + (x2BitIndex > 0) && + (x2BitIndex < bitWidth) && + (x2BitIndex >= x1BitIndex) && + (y*bitWidth + x1BitIndex <= bitLength) && + (y*bitWidth + x2BitIndex <= bitLength)); + + uint32_t x1ByteIndex = y * bitWidth / 8 + x1BitIndex / 8; + uint32_t x2ByteIndex = y * bitWidth / 8 + x2BitIndex / 8; + if (x1ByteIndex == x2ByteIndex) { + screen[x1ByteIndex] = singleByteLine(x1BitIndex % 8, x2BitIndex % 8); + } + else { + // draw 1s from x1 to end of its byte + screen[x1ByteIndex] = singleByteLine(x1BitIndex % 8, 7); + // draw 1s from 0 to x2 in its byte + screen[x2ByteIndex] = singleByteLine(0, x2BitIndex % 8); + // fill in in-between bytes with all 1s + for (int i = x1ByteIndex + 1; i < x2ByteIndex; i++) { + screen[i] = 255; + } + } } } diff --git a/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py b/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py index 24c6e16..c05bf8b 100644 --- a/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py +++ b/python_solutions/chapter_05_bit_manipulation/problem_05_08_draw_line.py @@ -75,6 +75,6 @@ def draw_line(screen, width, x1, x2, y): screen[x1_byte_index] = single_byte_line(x1 % 8, 7) # draw 1s from 0 to x2 in its byte screen[x2_byte_index] = single_byte_line(0, x2 % 8) - - for index in range(x1_byte_index + 1, x2_byte_index): - screen[index] = 255 + # fill in in-between bytes with all 1s + for index in range(x1_byte_index + 1, x2_byte_index): + screen[index] = 255 diff --git a/tests.cpp b/tests.cpp index a36b94e..c7588f4 100644 --- a/tests.cpp +++ b/tests.cpp @@ -879,9 +879,7 @@ TEST_CASE("Chapter 05 - Problem 07 - pairwiseSwap()", "test"){ } TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ - /* - * Screen #1: Line goes middle to end. Line spans less than 8 bits. - */ + // Screen #1: Line goes middle to end. Line spans less than 8 bits. uint32_t bitWidth1 = 8; uint32_t bitLength1 = 64; uint8_t screen1[64 / 8] = {0}; @@ -906,11 +904,10 @@ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ "00000000\n"; REQUIRE(expectedInitialScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); chapter_05::drawLine(screen1, bitWidth1, bitLength1, x1_1, x2_1, y_1); - // REQUIRE(expectedFinalScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); + REQUIRE(expectedFinalScreen1 == chapter_05::stringifyScreen(screen1, bitWidth1, bitLength1)); - /* - * Screen #2: Line spans more than 8 bits. - */ + + // Screen #2: Line spans more than 8 bits. uint32_t bitWidth2 = 32; uint32_t bitLength2 = 64; uint8_t screen2[64 / 8] = {0}; @@ -923,11 +920,9 @@ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ "11111111111111000000000000000000\n"; REQUIRE(expectedInitialScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); chapter_05::drawLine(screen2, bitWidth2, bitLength2, x1_2, x2_2, y_2); - // REQUIRE(expectedFinalScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); + REQUIRE(expectedFinalScreen2 == chapter_05::stringifyScreen(screen2, bitWidth2, bitLength2)); - /* - * Screen #3: Line spans more than 8 bits. - */ + // Screen #3: Line spans more than 8 bits. uint32_t bitWidth3 = 64; uint32_t bitLength3 = 256; uint8_t screen3[256 / 8] = {0}; @@ -944,11 +939,9 @@ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ "0000000000000000000000000000000000000000000000000000000000000000\n"; REQUIRE(expectedInitialScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); chapter_05::drawLine(screen3, bitWidth3, bitLength3, x1_3, x2_3, y_3); - // REQUIRE(expectedFinalScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); + REQUIRE(expectedFinalScreen3 == chapter_05::stringifyScreen(screen3, bitWidth3, bitLength3)); - /* - * Screen #4: Line spans a single bit. - */ + // Screen #4: Line spans a single bit. uint32_t bitWidth4 = 8; uint32_t bitLength4 = 8; uint8_t screen4[1] = {0}; @@ -959,7 +952,7 @@ TEST_CASE("Chapter 05 - Problem 08 - drawLine()", "test"){ std::string expectedFinalScreen4 = "00010000\n"; REQUIRE(expectedInitialScreen4 == chapter_05::stringifyScreen(screen4, bitWidth4, bitLength4)); chapter_05::drawLine(screen4, bitWidth4, bitLength4, x1_4, x2_4, y_4); - // REQUIRE(expectedFinalScreen1 == chapter_05::stringifyScreen(screen4, bitWidth4, bitLength4)); + REQUIRE(expectedFinalScreen4 == chapter_05::stringifyScreen(screen4, bitWidth4, bitLength4)); } TEST_CASE("Chapter 08 - Problem 01 - tripleStep()", "test"){ From 94e90d4c1a79eaca4b93857a1df9b86ccf632468 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 5 Jun 2019 15:29:44 -0700 Subject: [PATCH 073/176] update completion in readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 674bf44..5679b05 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ reference and contribute solutions with confidence. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `6 / 7` complete. +5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `7 / 7` complete. 6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `49` solutions. +C++ Total: `50` solutions. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `49` solutions. Python Total: `56` solutions. -##### Grand Total: `105` unique solutions. +##### Grand Total: `106` unique solutions. ### Building: #### Mac: From 41c92cf93b2888b5008da6c594e9c71a7cdc6723 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 6 Jun 2019 16:32:34 -0800 Subject: [PATCH 074/176] remove non-active test. add completion targets in readme. --- README.md | 12 ++++++------ tests.cpp | 10 +++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 5679b05..6ba79b3 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ reference and contribute solutions with confidence. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. 5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. +6. Chapter 6 - Math and Logic: N/A 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `50` solutions. +C++ Total: `50` of `141` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -48,7 +48,7 @@ C++ Total: `50` solutions. 3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. 4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. 5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: `0 / 10` complete. +6. Chapter 6 - Math and Logic: N/A 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A @@ -57,13 +57,13 @@ C++ Total: `50` solutions. 12. Chapter 12 - C and C++: N/A 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` complete. +15. Chapter 15 - Threads and Locks: N/A 16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. 17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. -Python Total: `56` solutions. +Python Total: `56` of `131` solutions complete. -##### Grand Total: `106` unique solutions. +##### Grand Total: `106` unique solutions complete. ### Building: #### Mac: diff --git a/tests.cpp b/tests.cpp index c7588f4..22d2fe4 100644 --- a/tests.cpp +++ b/tests.cpp @@ -240,7 +240,7 @@ TEST_CASE("Chapter 02 - Problem 05 - sumLists()", "test"){ 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 @@ -259,7 +259,7 @@ TEST_CASE("Chapter 02 - Problem 06 - palindrome()", "test"){ 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 @@ -1015,7 +1015,7 @@ TEST_CASE("Chapter 08 - Problem 04 - powerSet()", "test"){ testPowerSet = {}; chapter_08::createPowerSet(set1, testPowerSet); REQUIRE(testPowerSet == powerSet1); -}; +} TEST_CASE("Chapter 08 - Problem 05 - recursiveMultiply()", "test"){ REQUIRE(chapter_08::recursiveMultiply(1, 1) == 1); @@ -1187,7 +1187,3 @@ TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ 10, 30, 60, 100; REQUIRE(output2.isApprox(misc::makeIntegralImage(output1))); } - -TEST_CASE("Misc Exercises - boxFilter()", "test"){ - -} From 124f38bf01fb88e34a6af9c89c064d4e42bf0556 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 9 Jun 2019 15:26:36 -0700 Subject: [PATCH 075/176] remove autoadded docstrings --- .../chapter_01_arrays_and_strings/chapter_01_includes.h | 4 ---- .../problem_01_01_isUnique.cpp | 4 ---- .../chapter_01_arrays_and_strings/problem_01_01_isUnique.h | 4 ---- .../problem_01_02_arePermutations.cpp | 4 ---- .../problem_01_02_arePermutations.h | 3 --- .../chapter_01_arrays_and_strings/problem_01_03_URLify.cpp | 4 ---- .../chapter_01_arrays_and_strings/problem_01_03_URLify.h | 4 ---- .../chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp | 4 ---- .../chapter_01_arrays_and_strings/problem_01_05_oneAway.h | 4 ---- .../problem_01_06_stringCompression.cpp | 3 --- .../problem_01_06_stringCompression.h | 3 --- .../problem_01_07_rotateMatrix.cpp | 3 --- .../problem_01_07_rotateMatrix.h | 3 --- .../chapter_01_arrays_and_strings/problem_01_08_setZero.cpp | 3 --- .../chapter_01_arrays_and_strings/problem_01_08_setZero.h | 3 --- .../problem_01_09_stringRotation.cpp | 4 ---- .../problem_01_09_stringRotation.h | 4 ---- cpp_solutions/chapter_02_linked_lists/Node.h | 4 ---- cpp_solutions/chapter_02_linked_lists/chapter_02_includes.h | 4 ---- .../chapter_02_linked_lists/problem_02_01_removeDups.h | 4 ---- .../chapter_02_linked_lists/problem_02_02_returnKthToLast.h | 4 ---- .../problem_02_03_deleteMiddleNode.h | 5 ----- .../chapter_02_linked_lists/problem_02_04_partition.h | 3 --- .../chapter_02_linked_lists/problem_02_05_sumLists.h | 3 --- .../chapter_02_linked_lists/problem_02_06_palindrome.h | 3 --- cpp_solutions/chapter_03_stacks_and_queues/Stack.h | 3 --- .../chapter_03_stacks_and_queues/chapter_03_includes.h | 4 ---- .../chapter_04_trees_and_graphs/chapter_04_includes.h | 4 ---- .../chapter_04_trees_and_graphs/problem_04_03_makeLL.h | 3 --- .../chapter_05_bit_manipulation/chapter_05_includes.h | 4 ---- .../chapter_05_bit_manipulation/problem_05_01_insertion.cpp | 3 --- .../chapter_05_bit_manipulation/problem_05_01_insertion.h | 3 --- .../problem_05_02_binaryToString.cpp | 3 --- .../problem_05_02_binaryToString.h | 4 ---- .../problem_05_03_flipBitToWin.cpp | 3 --- .../problem_05_03_flipBitToWin.h | 4 ---- .../problem_05_04_nextNumber.cpp | 3 --- .../problem_05_06_conversion.cpp | 4 ---- .../chapter_05_bit_manipulation/problem_05_06_conversion.h | 4 ---- .../problem_05_07_pairwiseSwap.cpp | 4 ---- .../problem_05_07_pairwiseSwap.h | 4 ---- .../chapter_08_includes.h | 4 ---- .../problem_08_01_tripleStep.cpp | 6 +----- .../problem_08_01_tripleStep.h | 4 ---- .../problem_08_02_robotGrid.h | 4 ---- .../problem_08_03_magicIndex.h | 4 ---- .../problem_08_04_powerSet.h | 4 ---- .../problem_08_05_recursiveMultiply.h | 4 ---- .../problem_08_10_paintFill.h | 4 ---- .../chapter_10_sorting_and_searching/chapter_10_includes.h | 4 ---- .../problem_10_01_sortedMerge.h | 3 --- cpp_solutions/chapter_12_cpp/chapter_12_includes.h | 4 ---- cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp | 4 ---- cpp_solutions/chapter_12_cpp/problem_12_02_reverse.h | 4 ---- cpp_solutions/chapter_12_cpp/problem_12_08_copyNode.h | 4 ---- .../chapter_01_arrays_and_strings/problem_01_03_URLify.py | 2 +- .../chapter_04_trees_and_graphs/problem_04_02_make_bst.py | 5 +++-- .../problem_08_01_triple_step.py | 2 +- 58 files changed, 6 insertions(+), 208 deletions(-) diff --git a/cpp_solutions/chapter_01_arrays_and_strings/chapter_01_includes.h b/cpp_solutions/chapter_01_arrays_and_strings/chapter_01_includes.h index 4f02ecc..e77ad41 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/chapter_01_includes.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/chapter_01_includes.h @@ -1,7 +1,3 @@ -// -// Created by alex on 7/31/17. -// - #pragma once #include "problem_01_01_isUnique.h" #include "problem_01_02_arePermutations.h" diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp index f0fa577..d9bf5b4 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp @@ -1,7 +1,3 @@ -// -// Created by alex on 7/31/17. -// - /* Chapter 01 - Problem 01 - Is Unique - CTCI 6th Edition page 90 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.h index b505694..f1c0941 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp index 049801b..9f697e3 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/21/17. -// - /* Chapter 01 - Problem 02 - Check Permutation - CTCI 6th Edition page 90 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.h index fd30865..4d5a3f3 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp index ad7d4fc..d8aba22 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp @@ -1,7 +1,3 @@ -// -// Created by alex on 1/10/18. -// - /* Chapter 01 - Problem 03 - URLify - CTCI 6th Edition page 90 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.h index 3b031d3..855ab81 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.h @@ -1,7 +1,3 @@ -// -// Created by alex on 1/10/18. -// - #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp index 7beb968..14a5763 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.cpp @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 1/13/18. -// - /* Chapter 01 - Problem 05 - One Away - CTCI 6th Edition page 91 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.h index 7edd417..97a027d 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_05_oneAway.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 1/13/18. -// - #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp index bb8085d..34053a9 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.cpp @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 1/13/18. -// /* Chapter 01 - Problem 06 - String Compression - CTCI 6th Edition page 91 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.h index a6e0701..5b731f5 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_06_stringCompression.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 1/13/18. -// #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp index a29e1aa..f7b430a 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 8/24/17. -// /* Chapter 01 - Problem 07 - Rotate Matrix - CTCI 6th Edition page 91 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.h index 107bca0..151c8a0 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// #include "Eigen/Dense" namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp index 944c97a..cd5f216 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 1/19/18. -// /* Chapter 01 - Problem 08 - Set Zero - CTCI 6th Edition page 91 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.h index b074068..7f95b72 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 1/19/18. -// #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp index 7109d87..9fedc57 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 1/13/18. -// - /* Chapter 01 - Problem 09 - String Rotation - CTCI 6th Edition page 91 diff --git a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.h b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.h index 5d9126b..3e60bbd 100644 --- a/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.h +++ b/cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 1/13/18. -// - #include namespace chapter_01{ diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index f483cc2..4ea6851 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/21/17. -// - #pragma once #include diff --git a/cpp_solutions/chapter_02_linked_lists/chapter_02_includes.h b/cpp_solutions/chapter_02_linked_lists/chapter_02_includes.h index 9037870..37aa73f 100644 --- a/cpp_solutions/chapter_02_linked_lists/chapter_02_includes.h +++ b/cpp_solutions/chapter_02_linked_lists/chapter_02_includes.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/21/17. -// - #pragma once #include "problem_02_01_removeDups.h" #include "problem_02_02_returnKthToLast.h" diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_01_removeDups.h b/cpp_solutions/chapter_02_linked_lists/problem_02_01_removeDups.h index 0d50f17..3c3c7d3 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_01_removeDups.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_01_removeDups.h @@ -1,12 +1,8 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// #pragma once #include "Node.h" #include namespace chapter_02{ - // template function implemented in header file template void removeDups(SinglyLinkedNode* head){ SinglyLinkedNode* slowRunner = head; diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h b/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h index bf92c43..ff9121b 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h @@ -1,11 +1,7 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// #pragma once #include "Node.h" namespace chapter_02{ - // template function implemented in header file template SinglyLinkedNode* returnKthToLast(SinglyLinkedNode* head, int k){ if (head == nullptr) return nullptr; diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h b/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h index 4d548f1..cdbf811 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_03_deleteMiddleNode.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 10/14/17. -// - /* Chapter 02 - Problem 03 - Delete Middle Node - CTCI 6th Edition page 211 @@ -25,7 +21,6 @@ Space complexity: O(1). #include "Node.h" namespace chapter_02{ - // template function implemented in header file template void deleteMiddleNode(SinglyLinkedNode* middle){ if (middle == nullptr || middle->getNext() == nullptr){ diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_04_partition.h b/cpp_solutions/chapter_02_linked_lists/problem_02_04_partition.h index c9f6740..7e4c43f 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_04_partition.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_04_partition.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 10/16/17. -// /* Chapter 02 - Problem 04 - Partition - CTCI 6th Edition page 94 diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_05_sumLists.h b/cpp_solutions/chapter_02_linked_lists/problem_02_05_sumLists.h index 11de6d1..5fe9f31 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_05_sumLists.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_05_sumLists.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 1/19/18. -// /* Chapter 02 - Problem 05 - Sum Lists - CTCI 6th Edition page 95 diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h b/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h index 235fe41..725d135 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 2/3/18. -// /* Chapter 02 - Problem 06 - Palindrome - CTCI 6th Edition page 95 diff --git a/cpp_solutions/chapter_03_stacks_and_queues/Stack.h b/cpp_solutions/chapter_03_stacks_and_queues/Stack.h index 5a0426e..df4ec84 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/Stack.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/Stack.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 7/30/18. -// #pragma once #include "chapter_02_linked_lists/Node.h" diff --git a/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h b/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h index 3350e62..cbb2d21 100644 --- a/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h +++ b/cpp_solutions/chapter_03_stacks_and_queues/chapter_03_includes.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 7/30/18. -// - #pragma once #include "problem_03_02_StackMin.h" #include "problem_03_04_QueueViaStacks.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h index 5b5e9d9..2288f76 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/chapter_04_includes.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/4/18. -// - #pragma once #include "problem_04_01_pathExists.h" #include "problem_04_02_minimalTree.h" diff --git a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_03_makeLL.h b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_03_makeLL.h index c286632..d52f0f1 100644 --- a/cpp_solutions/chapter_04_trees_and_graphs/problem_04_03_makeLL.h +++ b/cpp_solutions/chapter_04_trees_and_graphs/problem_04_03_makeLL.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 2019-01-11. -// /* Chapter 04 - Problem 02 - Minimal Tree diff --git a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h index 98fb47e..8b92834 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h +++ b/cpp_solutions/chapter_05_bit_manipulation/chapter_05_includes.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/5/17. -// - #pragma once #include "problem_05_01_insertion.h" diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp index f12d0db..1e0f993 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp @@ -1,6 +1,3 @@ -// -// Created by alex on 8/2/17. -// #include "problem_05_01_insertion.h" namespace chapter_05{ diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.h index bf92357..6de98c1 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// #pragma once namespace chapter_05{ diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp index b2ecf67..e155cfd 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp @@ -1,6 +1,3 @@ -// -// Created by alex on 8/2/17. -// #include "problem_05_02_binaryToString.h" namespace chapter_05{ diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.h index 222a27a..4b3fc66 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp index 1862aa5..e5322e0 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp @@ -1,6 +1,3 @@ -// -// Created by alex on 5/15/2019. -// #include "problem_05_03_flipBitToWin.h" namespace chapter_05 { diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h index d2c4f3a..fe979de 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.h @@ -1,7 +1,3 @@ -// -// Created by alex on 5/15/2019. -// - #pragma once namespace chapter_05 { int flipBitToWin(int input); diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp index 4c2677f..bd4ba05 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_04_nextNumber.cpp @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 2019-05-17. -// #include "problem_05_04_nextNumber.h" #include diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp index 3f48faa..682c468 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/5/17. -// - #include "problem_05_06_conversion.h" namespace chapter_05{ diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.h index 0e2439e..e342ea3 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once namespace chapter_05{ diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp b/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp index da3c868..2863a39 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/5/17. -// - #include "problem_05_07_pairwiseSwap.h" namespace chapter_05{ diff --git a/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.h b/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.h index 592bfbb..4293920 100644 --- a/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.h +++ b/cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once namespace chapter_05{ diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h index 6c0d75d..81ce5c3 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/chapter_08_includes.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/6/17. -// - #pragma once #include "problem_08_01_tripleStep.h" #include "problem_08_02_robotGrid.h" diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp index 308d490..12a5ccc 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp @@ -1,9 +1,5 @@ -// -// Created by Alex Hagiopol on 8/6/17. -// - /* -Gayle's note: +Note from textbook: Regardless of whether or not you use memoization, note that the number of ways will quickly overflow the bounds of an integer. diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.h index 8d214be..9616665 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.h index 97cf4b9..77c9ec7 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include #include diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.h index e3c4f88..c94ad8e 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.h index 0a21803..b1eeea1 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_04_powerSet.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.h index 4ad5f40..986a53e 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_05_recursiveMultiply.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once namespace chapter_08{ diff --git a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.h b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.h index 1cd11b5..42e09e3 100644 --- a/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.h +++ b/cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index 9e9863d..f484ffa 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -1,6 +1,2 @@ -// -// Created by Alex Hagiopol on 8/27/18. -// - #pragma once #include "problem_10_01_sortedMerge.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h index 08523a6..153ef9c 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h @@ -1,6 +1,3 @@ -// -// Created by Alex Hagiopol on 8/27/18. -// /* Chapter 10 - Problem 01 - Sorted Merge diff --git a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h index 6ad3a11..bddc2e5 100644 --- a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h +++ b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once #include "problem_12_02_reverse.h" diff --git a/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp b/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp index 2c9cf70..bf937ae 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp +++ b/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - /* Chapter 12 - Problem 02 - Reverse - CTCI 6th Edition page 163 diff --git a/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.h b/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.h index 11b8020..5ad2b23 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_02_reverse.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 9/5/17. -// - #pragma once namespace chapter_12{ diff --git a/cpp_solutions/chapter_12_cpp/problem_12_08_copyNode.h b/cpp_solutions/chapter_12_cpp/problem_12_08_copyNode.h index 3d47655..62d093d 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_08_copyNode.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_08_copyNode.h @@ -1,7 +1,3 @@ -// -// Created by Alex Hagiopol on 8/26/18. -// - /* Chapter 12 - Problem 08 - Copy Node diff --git a/python_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.py b/python_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.py index bf819f2..de27b5e 100644 --- a/python_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.py +++ b/python_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.py @@ -28,7 +28,7 @@ """ -# in Python, strings are immutable, thus we are forced to implement with lists of single characters e.g. +# in Python, strings are immutable, thus we are forced to implement with lists of single characters def URLify(string): # compute length of new string based on # of spaces in input string new_len = 0 diff --git a/python_solutions/chapter_04_trees_and_graphs/problem_04_02_make_bst.py b/python_solutions/chapter_04_trees_and_graphs/problem_04_02_make_bst.py index da7e939..ae98490 100644 --- a/python_solutions/chapter_04_trees_and_graphs/problem_04_02_make_bst.py +++ b/python_solutions/chapter_04_trees_and_graphs/problem_04_02_make_bst.py @@ -1,4 +1,4 @@ -''' +""" Chapter 04 - Problem 02 - Minimal Tree Problem Statement: @@ -15,7 +15,8 @@ Time complexity: O(log(N)) Space complexity: O(log(N)) -''' +""" + class Node: def __init__(self, left, right, val): diff --git a/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_triple_step.py b/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_triple_step.py index a5769d0..a9b0c4a 100644 --- a/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_triple_step.py +++ b/python_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_triple_step.py @@ -1,5 +1,5 @@ """ -Gayle's note: +Note from textbook: Regardless of whether or not you use memoization, note that the number of ways will quickly overflow the bounds of an integer. From d73979aa2be47b5c474070eff44a73e84c88e0f0 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 9 Jun 2019 17:59:03 -0700 Subject: [PATCH 076/176] implement tests and skeleton for merge sort C++ --- .../chapter_10_includes.h | 1 + .../chapter_10_sorting_and_searching/mergeSort.h | 9 +++++++++ .../problem_10_01_sortedMerge.h | 2 +- tests.cpp | 11 +++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index f484ffa..2d0769b 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -1,2 +1,3 @@ #pragma once #include "problem_10_01_sortedMerge.h" +#include "mergeSort.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h new file mode 100644 index 0000000..dca55ae --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h @@ -0,0 +1,9 @@ +#pragma once +#include + +namespace chapter_10 { + template + void mergeSort(std::vector& array) { + + } +} \ No newline at end of file diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h index 153ef9c..5eb1315 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_01_sortedMerge.h @@ -54,4 +54,4 @@ namespace chapter_10{ mergeA --; } } -} \ No newline at end of file +} diff --git a/tests.cpp b/tests.cpp index 22d2fe4..ab33f66 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1120,6 +1120,17 @@ TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ REQUIRE(threeFilled.isApprox(expectedThreeFilled)); } +TEST_CASE("Chapter 10 - mergeSort()"){ + std::vector input1 = {1000, 10, 7, 3, -1000, 5, 100, 9, 1, 10000, -10000, 6, 2, -10, 4, 8, -100, 0}; + std::vector expectedOutput1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; + std::vector input2 = {}; + std::vector expectedOutput2 = {}; + std::vector input3 = {1}; + std::vector expectedOutput3 = {1}; + std::vector input4 = {-5, -4, -3, -2, -1}; + std::vector expectedOutput4 = {-5, -4, -3, -2, -1}; +} + TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly int B[5] = {3, 6, 9, 12, 15}; From d60eddbbed36b277a9098770fc139f1491000db0 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 10 Jun 2019 16:43:19 -0700 Subject: [PATCH 077/176] implement and test merge sort algorithm in C++ --- .../mergeSort.h | 55 ++++++++++++++++++- tests.cpp | 20 +++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h index dca55ae..ccbc7f9 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h @@ -3,7 +3,58 @@ namespace chapter_10 { template - void mergeSort(std::vector& array) { + void mergeHelper(std::vector& array, std::vector& helperArray, int start, int middle, int end) { + assert(array.size() == helperArray.size()); + int helperIdx = start; + int leftIdx = start; + int rightIdx = middle + 1; + // perform merge operation from left and right halves of input array into helper array + while (leftIdx <= middle && rightIdx <= end) { + if (array[leftIdx] <= array[rightIdx]) { + helperArray[helperIdx] = array[leftIdx]; + leftIdx ++; + } + else { + helperArray[helperIdx] = array[rightIdx]; + rightIdx ++; + } + helperIdx ++; + } + // account for case where one array segment (left or right) is smaller + // only one of these while blocks will be executed because only one side may be smaller + while (leftIdx <= middle) { + helperArray[helperIdx] = array[leftIdx]; + leftIdx ++; + helperIdx ++; + } + while (rightIdx <= end) { + helperArray[helperIdx] = array[rightIdx]; + rightIdx ++; + helperIdx ++; + } + // copy content of helper array into input array at the appropriate indices + for (int i = start; i <= end; i++) { + array[i] = helperArray[i]; + } + } + template + void sortHelper(std::vector& array, std::vector& helperArray, int start, int end) { + assert(array.size() == helperArray.size()); + int middle = (end - start) / 2 + start; + // check for terminating condition and recursively sort left and right halves + if (start < end) { + if (start < middle) sortHelper(array, helperArray, start, middle); + if ((middle + 1) < end) sortHelper(array, helperArray, middle + 1, end); + mergeHelper(array, helperArray, start, middle, end); + } + } + + template + void mergeSort(std::vector& array) { + std::vector helperArray(array); + int start = 0; + int end = array.size() - 1; + sortHelper(array, helperArray, start, end); // by definition, the end of an array range *is* included in sort } -} \ No newline at end of file +} diff --git a/tests.cpp b/tests.cpp index ab33f66..8b20416 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1125,10 +1125,22 @@ TEST_CASE("Chapter 10 - mergeSort()"){ std::vector expectedOutput1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; std::vector input2 = {}; std::vector expectedOutput2 = {}; - std::vector input3 = {1}; - std::vector expectedOutput3 = {1}; - std::vector input4 = {-5, -4, -3, -2, -1}; - std::vector expectedOutput4 = {-5, -4, -3, -2, -1}; + std::vector input3 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + std::vector expectedOutput3 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + std::vector input4 = {1.1}; + std::vector expectedOutput4 = {1.1}; + std::vector input5 = {1.4, 1.6, 1.1, 1.3, 1.5, 1.7, 1.2}; + std::vector expectedOutput5 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + chapter_10::mergeSort(input1); + chapter_10::mergeSort(input2); + chapter_10::mergeSort(input3); + chapter_10::mergeSort(input4); + chapter_10::mergeSort(input5); + REQUIRE(expectedOutput1 == input1); + REQUIRE(expectedOutput2 == input2); + REQUIRE(expectedOutput3 == input3); + REQUIRE(expectedOutput4 == input4); + REQUIRE(expectedOutput5 == input5); } TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ From 892eec0bf38b6e6b9f1f913fdcbc024decb8791f Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 10 Jun 2019 17:52:39 -0700 Subject: [PATCH 078/176] implement and test merge sort in Python --- .../mergeSort.h | 6 ++- .../merge_sort.py | 49 +++++++++++++++++++ .../problem_10_01_sorted_merge.py | 3 +- tests.py | 23 +++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 python_solutions/chapter_10_sorting_and_searching/merge_sort.py diff --git a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h index ccbc7f9..41272b2 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h @@ -9,6 +9,7 @@ namespace chapter_10 { int leftIdx = start; int rightIdx = middle + 1; // perform merge operation from left and right halves of input array into helper array + // this operation stops when either the left or right subarray is depleted while (leftIdx <= middle && rightIdx <= end) { if (array[leftIdx] <= array[rightIdx]) { helperArray[helperIdx] = array[leftIdx]; @@ -33,17 +34,20 @@ namespace chapter_10 { helperIdx ++; } // copy content of helper array into input array at the appropriate indices + /* for (int i = start; i <= end; i++) { array[i] = helperArray[i]; } + */ + array = helperArray; } template void sortHelper(std::vector& array, std::vector& helperArray, int start, int end) { assert(array.size() == helperArray.size()); - int middle = (end - start) / 2 + start; // check for terminating condition and recursively sort left and right halves if (start < end) { + int middle = (end - start) / 2 + start; if (start < middle) sortHelper(array, helperArray, start, middle); if ((middle + 1) < end) sortHelper(array, helperArray, middle + 1, end); mergeHelper(array, helperArray, start, middle, end); diff --git a/python_solutions/chapter_10_sorting_and_searching/merge_sort.py b/python_solutions/chapter_10_sorting_and_searching/merge_sort.py new file mode 100644 index 0000000..258d7cb --- /dev/null +++ b/python_solutions/chapter_10_sorting_and_searching/merge_sort.py @@ -0,0 +1,49 @@ +import copy + + +def merge_helper(array, helper_array, start, middle, end): + assert(len(array) == len(helper_array)) + left_idx = start + right_idx = middle + 1 + helper_idx = start + # perform merge operation from left and right halves of input array into helper array + # this operation stops when either the left or right subarray is depleted + while left_idx <= middle and right_idx <= end: + if array[left_idx] <= array[right_idx]: + helper_array[helper_idx] = array[left_idx] + left_idx += 1 + else: + helper_array[helper_idx] = array[right_idx] + right_idx += 1 + helper_idx += 1 + # account for case where one array segment (left or right) is smaller + # only one of these while blocks will be executed because only one side may be smaller + while left_idx <= middle: + helper_array[helper_idx] = array[left_idx] + left_idx += 1 + helper_idx += 1 + while right_idx <= middle: + helper_array[helper_idx] = array[right_idx] + right_idx += 1 + helper_idx += 1 + # copy content of helper array into input array at the appropriate indices + for i in range(0, len(array)): + array[i] = helper_array[i] # cannot use array = helper_array due to Python mutability rules + + +def sort_helper(array, helper_array, start, end): + assert(len(array) == len(helper_array)) + if start < end: + middle = (end - start) // 2 + start + if start < middle: + sort_helper(array, helper_array, start, middle) + if (middle + 1) < end: + sort_helper(array, helper_array, middle + 1, end) + merge_helper(array, helper_array, start, middle, end) + + +def merge_sort(array): + helper_array = copy.deepcopy(array) + start = 0 + end = len(array) - 1 + sort_helper(array, helper_array, start, end) diff --git a/python_solutions/chapter_10_sorting_and_searching/problem_10_01_sorted_merge.py b/python_solutions/chapter_10_sorting_and_searching/problem_10_01_sorted_merge.py index 6385a0d..1b42b99 100644 --- a/python_solutions/chapter_10_sorting_and_searching/problem_10_01_sorted_merge.py +++ b/python_solutions/chapter_10_sorting_and_searching/problem_10_01_sorted_merge.py @@ -16,6 +16,7 @@ the function does not cause more memory allocations that scale with the size of the input """ + def sorted_merge(A, lastA, B, lastB): mergeA = lastA + lastB + 1 # iterate through arrays A and B from back to front performing the merge operation along the way @@ -26,4 +27,4 @@ def sorted_merge(A, lastA, B, lastB): else: A[mergeA] = B[lastB] lastB -= 1 - mergeA -= 1 \ No newline at end of file + mergeA -= 1 diff --git a/tests.py b/tests.py index 481cff2..2e55bd3 100644 --- a/tests.py +++ b/tests.py @@ -58,6 +58,7 @@ from python_solutions.chapter_08_recursion_and_dynamic_programming import problem_08_09_parens as p_8_9 from python_solutions.chapter_08_recursion_and_dynamic_programming import problem_08_10_paint_fill as p_8_10 from python_solutions.chapter_08_recursion_and_dynamic_programming import problem_08_11_coins as p_8_11 +from python_solutions.chapter_10_sorting_and_searching import merge_sort from python_solutions.chapter_10_sorting_and_searching import problem_10_01_sorted_merge as p_10_1 from python_solutions.chapter_16_moderate import problem_16_03_intersection as p_16_03 from python_solutions.chapter_17_hard import problem_17_10_majority_element as p_17_10 @@ -1080,6 +1081,28 @@ def test_problem_8_13(self): def test_problem_8_14(self): pass + def test_merge_sort(self): + input1 = [1000, 10, 7, 3, -1000, 5, 100, 9, 1, 10000, -10000, 6, 2, -10, 4, 8, -100, 0] + expected_output_1 = [-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000] + input2 = [] + expected_output_2 = [] + input3 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7] + expected_output_3 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7] + input4 = [1.1] + expected_output_4 = [1.1] + input5 = [1.4, 1.6, 1.1, 1.3, 1.5, 1.7, 1.2] + expected_output_5 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7] + merge_sort.merge_sort(input1) + merge_sort.merge_sort(input2) + merge_sort.merge_sort(input3) + merge_sort.merge_sort(input4) + merge_sort.merge_sort(input5) + self.assertEqual(expected_output_1, input1) + self.assertEqual(expected_output_2, input2) + self.assertEqual(expected_output_3, input3) + self.assertEqual(expected_output_4, input4) + self.assertEqual(expected_output_5, input5) + def test_problem_10_01(self): A = [5, 5, 10, 10, 15, 0, 0, 0, 0, 0] B = [3, 6, 9, 12, 15] From 41996e33d595c15c6a6756b304f18e198364997d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 12 Jun 2019 10:58:21 -0700 Subject: [PATCH 079/176] remove dead code in merge sort C++ --- cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h index 41272b2..cf30337 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/mergeSort.h @@ -34,11 +34,6 @@ namespace chapter_10 { helperIdx ++; } // copy content of helper array into input array at the appropriate indices - /* - for (int i = start; i <= end; i++) { - array[i] = helperArray[i]; - } - */ array = helperArray; } From a8f2a19963b89df2b18dedce90af556a824583d6 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 12 Jun 2019 13:44:55 -0700 Subject: [PATCH 080/176] implement quickSort in C++ --- .../chapter_10_includes.h | 1 + .../quickSort.h | 35 +++++++++++++++++++ tests.cpp | 25 +++++++++++-- 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/quickSort.h diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index 2d0769b..2791826 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -1,3 +1,4 @@ #pragma once #include "problem_10_01_sortedMerge.h" +#include "quickSort.h" #include "mergeSort.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h b/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h new file mode 100644 index 0000000..584af69 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h @@ -0,0 +1,35 @@ +#pragma once +#include + +namespace chapter_10 { + template + int partition(std::vector& array, int start, int end) { + T partitionValue = array[end]; + int swapIndex = start; + // perform parition operation: + // swap element to lowest index with unknown partition assignment + for (int i = start; i <= end; i++) { + if (array[i] <= partitionValue) { + std::swap(array[i], array[swapIndex]); + swapIndex ++; + } + } + return swapIndex - 1; // - 1 to undo the increment operation after the final swap of the partitionValue + } + + template + void quickSortHelper(std::vector& array, int start, int end) { + if (start < end) { + int partitionIndex = partition(array, start, end); + if (partitionIndex >= start && partitionIndex <= end) { + quickSortHelper(array, start, partitionIndex - 1); + quickSortHelper(array, partitionIndex + 1, end); + } + } + } + + template + void quickSort(std::vector& array) { + quickSortHelper(array, 0, array.size() - 1); + } +} diff --git a/tests.cpp b/tests.cpp index 8b20416..46e674c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1143,6 +1143,29 @@ TEST_CASE("Chapter 10 - mergeSort()"){ REQUIRE(expectedOutput5 == input5); } +TEST_CASE("Chapter 10 - quickSort()"){ + std::vector input1 = {1000, 10, 7, 3, -1000, 5, 100, 9, 1, 10000, -10000, 6, 2, -10, 4, 8, -100, 0}; + std::vector expectedOutput1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; + std::vector input2 = {}; + std::vector expectedOutput2 = {}; + std::vector input3 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + std::vector expectedOutput3 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + std::vector input4 = {1.1}; + std::vector expectedOutput4 = {1.1}; + std::vector input5 = {1.4, 1.6, 1.1, 1.3, 1.5, 1.7, 1.2}; + std::vector expectedOutput5 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + chapter_10::quickSort(input1); + chapter_10::quickSort(input2); + chapter_10::quickSort(input3); + chapter_10::quickSort(input4); + chapter_10::quickSort(input5); + REQUIRE(expectedOutput1 == input1); + REQUIRE(expectedOutput2 == input2); + REQUIRE(expectedOutput3 == input3); + REQUIRE(expectedOutput4 == input4); + REQUIRE(expectedOutput5 == input5); +} + TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly int B[5] = {3, 6, 9, 12, 15}; @@ -1153,8 +1176,6 @@ TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ for (int i = 0; i < 10; i++){ REQUIRE(A[i] == C[i]); } - - int D[10] = {5, 5, 10, 10}; // remainder of uninitialized values set to zero implicitly int E[6] = {3, 6, 9, 12, 15, 15}; int lastD = 3; // index of last item placed in D From 0dde197452b7af2155bf5b2b109f42a085235a7d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 12 Jun 2019 14:37:14 -0700 Subject: [PATCH 081/176] implement quickSort in Python --- .../quickSort.h | 14 +++++------ .../quick_sort.py | 21 +++++++++++++++++ tests.py | 23 +++++++++++++++++++ 3 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 python_solutions/chapter_10_sorting_and_searching/quick_sort.py diff --git a/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h b/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h index 584af69..3dabce1 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/quickSort.h @@ -5,26 +5,24 @@ namespace chapter_10 { template int partition(std::vector& array, int start, int end) { T partitionValue = array[end]; - int swapIndex = start; + int partitionIndex = start; // perform parition operation: // swap element to lowest index with unknown partition assignment for (int i = start; i <= end; i++) { if (array[i] <= partitionValue) { - std::swap(array[i], array[swapIndex]); - swapIndex ++; + std::swap(array[i], array[partitionIndex]); + partitionIndex ++; } } - return swapIndex - 1; // - 1 to undo the increment operation after the final swap of the partitionValue + return partitionIndex - 1; // - 1 to undo the increment operation after the final swap of the partitionValue } template void quickSortHelper(std::vector& array, int start, int end) { if (start < end) { int partitionIndex = partition(array, start, end); - if (partitionIndex >= start && partitionIndex <= end) { - quickSortHelper(array, start, partitionIndex - 1); - quickSortHelper(array, partitionIndex + 1, end); - } + quickSortHelper(array, start, partitionIndex - 1); + quickSortHelper(array, partitionIndex + 1, end); } } diff --git a/python_solutions/chapter_10_sorting_and_searching/quick_sort.py b/python_solutions/chapter_10_sorting_and_searching/quick_sort.py new file mode 100644 index 0000000..8dc8597 --- /dev/null +++ b/python_solutions/chapter_10_sorting_and_searching/quick_sort.py @@ -0,0 +1,21 @@ +def partition(array, start, end): + partition_index = start + partition_value = array[end] + # perform parition operation: + # swap element to lowest index with unknown partition assignment + for i in range(start, end + 1): + if array[i] <= partition_value: + array[i], array[partition_index] = array[partition_index], array[i] + partition_index += 1 + return partition_index - 1 # - 1 to undo the increment operation after the final swap of the partitionValue + + +def quick_sort_helper(array, start, end): + if start < end: + partition_index = partition(array, start, end) + quick_sort_helper(array, start, partition_index - 1) + quick_sort_helper(array, partition_index + 1, end) + + +def quick_sort(array): + quick_sort_helper(array, 0, len(array) - 1) diff --git a/tests.py b/tests.py index 2e55bd3..a574e2c 100644 --- a/tests.py +++ b/tests.py @@ -59,6 +59,7 @@ from python_solutions.chapter_08_recursion_and_dynamic_programming import problem_08_10_paint_fill as p_8_10 from python_solutions.chapter_08_recursion_and_dynamic_programming import problem_08_11_coins as p_8_11 from python_solutions.chapter_10_sorting_and_searching import merge_sort +from python_solutions.chapter_10_sorting_and_searching import quick_sort from python_solutions.chapter_10_sorting_and_searching import problem_10_01_sorted_merge as p_10_1 from python_solutions.chapter_16_moderate import problem_16_03_intersection as p_16_03 from python_solutions.chapter_17_hard import problem_17_10_majority_element as p_17_10 @@ -1103,6 +1104,28 @@ def test_merge_sort(self): self.assertEqual(expected_output_4, input4) self.assertEqual(expected_output_5, input5) + def test_quick_sort(self): + input1 = [1000, 10, 7, 3, -1000, 5, 100, 9, 1, 10000, -10000, 6, 2, -10, 4, 8, -100, 0] + expected_output_1 = [-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000] + input2 = [] + expected_output_2 = [] + input3 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7] + expected_output_3 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7] + input4 = [1.1] + expected_output_4 = [1.1] + input5 = [1.4, 1.6, 1.1, 1.3, 1.5, 1.7, 1.2] + expected_output_5 = [1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7] + quick_sort.quick_sort(input1) + quick_sort.quick_sort(input2) + quick_sort.quick_sort(input3) + quick_sort.quick_sort(input4) + quick_sort.quick_sort(input5) + self.assertEqual(expected_output_1, input1) + self.assertEqual(expected_output_2, input2) + self.assertEqual(expected_output_3, input3) + self.assertEqual(expected_output_4, input4) + self.assertEqual(expected_output_5, input5) + def test_problem_10_01(self): A = [5, 5, 10, 10, 15, 0, 0, 0, 0, 0] B = [3, 6, 9, 12, 15] From da5147d584876ca53fbeb45fc96a76e06ade7c90 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 13 Jun 2019 14:14:27 -0700 Subject: [PATCH 082/176] implement binary search in C++ --- .../binarySearch.h | 26 +++++++++++++++++++ .../chapter_10_includes.h | 1 + tests.cpp | 19 ++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h diff --git a/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h b/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h new file mode 100644 index 0000000..cf9234c --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h @@ -0,0 +1,26 @@ +#pragma once + +namespace chapter_10 { + template + int binarySearchHelper(const std::vector& array, const T& value, int start, int end) { + if (start > end) return -1; // terminating condition: asked to search empty list + int midpoint = (end - start) / 2 + start; + if (value == array[midpoint]) { // terminating condition: found query + return midpoint; + } + else if (start >= end) { // terminating condition: asked to search single element list which is not query + return -1; + } + else if (value < array[midpoint]) { // recurse left + return binarySearchHelper(array, value, start, midpoint - 1); + } + else { // recurse right + return binarySearchHelper(array, value, midpoint + 1, end); + } + } + + template + int binarySearch(const std::vector& array, const T& value) { + return binarySearchHelper(array, value, 0, array.size() - 1); + } +} \ No newline at end of file diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index 2791826..517acb1 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -2,3 +2,4 @@ #include "problem_10_01_sortedMerge.h" #include "quickSort.h" #include "mergeSort.h" +#include "binarySearch.h" \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index 46e674c..09b2388 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1120,7 +1120,7 @@ TEST_CASE("Chapter 08 - Problem 10 - paintFill()", "test"){ REQUIRE(threeFilled.isApprox(expectedThreeFilled)); } -TEST_CASE("Chapter 10 - mergeSort()"){ +TEST_CASE("Chapter 10 - mergeSort()", "test"){ std::vector input1 = {1000, 10, 7, 3, -1000, 5, 100, 9, 1, 10000, -10000, 6, 2, -10, 4, 8, -100, 0}; std::vector expectedOutput1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; std::vector input2 = {}; @@ -1143,7 +1143,7 @@ TEST_CASE("Chapter 10 - mergeSort()"){ REQUIRE(expectedOutput5 == input5); } -TEST_CASE("Chapter 10 - quickSort()"){ +TEST_CASE("Chapter 10 - quickSort()", "test"){ std::vector input1 = {1000, 10, 7, 3, -1000, 5, 100, 9, 1, 10000, -10000, 6, 2, -10, 4, 8, -100, 0}; std::vector expectedOutput1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; std::vector input2 = {}; @@ -1166,6 +1166,21 @@ TEST_CASE("Chapter 10 - quickSort()"){ REQUIRE(expectedOutput5 == input5); } +TEST_CASE("Chapter 10 - binarySearch()", "test"){ + std::vector input1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; + std::vector input2 = {}; + std::vector input3 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + REQUIRE(-1 == chapter_10::binarySearch(input1, 101)); + REQUIRE(16 == chapter_10::binarySearch(input1, 1000)); + REQUIRE(4 == chapter_10::binarySearch(input1, 0)); + REQUIRE(15 == chapter_10::binarySearch(input1, 100)); + REQUIRE(13 == chapter_10::binarySearch(input1, 9)); + REQUIRE(10 == chapter_10::binarySearch(input1, 6)); + REQUIRE(-1 == chapter_10::binarySearch(input2, 101)); + REQUIRE(3 == chapter_10::binarySearch(input3, 1.4)); + REQUIRE(5 == chapter_10::binarySearch(input3, 1.6)); +} + TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly int B[5] = {3, 6, 9, 12, 15}; From 0c6d077e97d58636d659bb0cc7ef0d42a1e682a5 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 21 Jun 2019 22:10:45 -0700 Subject: [PATCH 083/176] WIP 10.2 --- CMakeLists.txt | 1 + .../chapter_10_sorting_and_searching/chapter_10_includes.h | 3 ++- .../problem_10_02_anagramSort.cpp | 7 +++++++ .../problem_10_02_anagramSort.h | 7 +++++++ tests.cpp | 6 +++++- 5 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dc84b5..603ed43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,7 @@ set(SOURCE_FILES cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp # problem 10.01 not included because it is a template function implemented in .h file + cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index 517acb1..ce540d4 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -1,5 +1,6 @@ #pragma once #include "problem_10_01_sortedMerge.h" +#include "problem_10_02_anagramSort.h" #include "quickSort.h" #include "mergeSort.h" -#include "binarySearch.h" \ No newline at end of file +#include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp new file mode 100644 index 0000000..3f66d68 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -0,0 +1,7 @@ +#include "problem_10_02_anagramSort.h" + +namespace chapter_10 { + void anagramSort(std::vector& array) { + + } +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h new file mode 100644 index 0000000..b8ec2c5 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h @@ -0,0 +1,7 @@ +#pragma once +#include +#include + +namespace chapter_10 { + void anagramSort(std::vector& array); +} diff --git a/tests.cpp b/tests.cpp index 09b2388..0f61ea7 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1181,7 +1181,7 @@ TEST_CASE("Chapter 10 - binarySearch()", "test"){ REQUIRE(5 == chapter_10::binarySearch(input3, 1.6)); } -TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ +TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()", "test"){ int A[10] = {5, 5, 10, 10, 15}; // remainder of uninitialized values set to zero implicitly int B[5] = {3, 6, 9, 12, 15}; int lastA = 4; // index of last item placed in A @@ -1201,6 +1201,10 @@ TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()","test"){ } } +TEST_CASE("Chapter 10 - Problem 02 - anagramSort()", "test"){ + +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From 0d21df091e47750e7cceea87960f86e1e3e9127d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 24 Jun 2019 09:35:21 -0700 Subject: [PATCH 084/176] WIP 10.2 wrote unit test --- .../problem_10_02_anagramSort.cpp | 2 +- .../problem_10_02_anagramSort.h | 2 +- tests.cpp | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp index 3f66d68..389c172 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -1,7 +1,7 @@ #include "problem_10_02_anagramSort.h" namespace chapter_10 { - void anagramSort(std::vector& array) { + void anagramSort(std::vector>& array) { } } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h index b8ec2c5..662a68c 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h @@ -3,5 +3,5 @@ #include namespace chapter_10 { - void anagramSort(std::vector& array); + void anagramSort(std::vector>& array); } diff --git a/tests.cpp b/tests.cpp index 0f61ea7..1c37ce7 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1202,7 +1202,21 @@ TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()", "test"){ } TEST_CASE("Chapter 10 - Problem 02 - anagramSort()", "test"){ - + // define strings as std::vector for compatibility with sort algorithms already implemented in this section + std::vector abc = {'a', 'b', 'c'}; + std::vector acb = {'a', 'c', 'b'}; + std::vector bac = {'b', 'a', 'c'}; + std::vector bca = {'b', 'c', 'a'}; + std::vector cab = {'c', 'a', 'b'}; + std::vector cba = {'c', 'b', 'a'}; + std::vector aaa = {'a', 'a', 'a'}; + std::vector bbb = {'b', 'b', 'b'}; + std::vector ccc = {'c', 'c', 'c'}; + std::vector ddd = {'c', 'c', 'c'}; + std::vector> example1 = {ddd, abc, ccc, bac, aaa, cab, bbb, acb}; + std::vector> expected1 = {aaa, abc, acb, bac, cab, bbb, ccc, ddd}; + chapter_10::anagramSort(example1); + REQUIRE(expected1 == example1); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From 7c1afe6ecb1a0f72bafc2fda13d099e6df390d29 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 24 Jun 2019 14:06:30 -0700 Subject: [PATCH 085/176] refactor tests --- tests.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/tests.cpp b/tests.cpp index 1c37ce7..6714a47 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1202,19 +1202,8 @@ TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()", "test"){ } TEST_CASE("Chapter 10 - Problem 02 - anagramSort()", "test"){ - // define strings as std::vector for compatibility with sort algorithms already implemented in this section - std::vector abc = {'a', 'b', 'c'}; - std::vector acb = {'a', 'c', 'b'}; - std::vector bac = {'b', 'a', 'c'}; - std::vector bca = {'b', 'c', 'a'}; - std::vector cab = {'c', 'a', 'b'}; - std::vector cba = {'c', 'b', 'a'}; - std::vector aaa = {'a', 'a', 'a'}; - std::vector bbb = {'b', 'b', 'b'}; - std::vector ccc = {'c', 'c', 'c'}; - std::vector ddd = {'c', 'c', 'c'}; - std::vector> example1 = {ddd, abc, ccc, bac, aaa, cab, bbb, acb}; - std::vector> expected1 = {aaa, abc, acb, bac, cab, bbb, ccc, ddd}; + std::vector example1 = {"ddd", "abc", "ccc", "bac", "aaa", "cab", "bbb", "acb"}; + std::vector expected1 = {"aaa", "abc", "acb", "bac", "cab", "bbb", "ccc", "ddd"}; chapter_10::anagramSort(example1); REQUIRE(expected1 == example1); } From dd3d419d54735d0d76b3ee178387de871dc2db2e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 24 Jun 2019 14:06:54 -0700 Subject: [PATCH 086/176] change data format to vector of strings. add essay. --- .../problem_10_02_anagramSort.cpp | 36 ++++++++++++++++++- .../problem_10_02_anagramSort.h | 2 +- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp index 389c172..db46467 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -1,7 +1,41 @@ +/* + * PROBLEM: + * Given an array of strings, sort the array such that all anagrams are next to each other. + * Anagrams are strings that contain the same characters e.g. "abc" and "bca". + * + * TEST CASE: + * Input: {ddd, abc, ccc, bac, aaa, cab, bbb, acb} + * Output: {aaa, abc, acb, bac, cab, bbb, ccc, ddd} + * Note that the only requirement is for anagrams to be next to each other. The order of the anagram groups and the + * order of the sorted array does not matter. + * + * ALGORITHM: + * 1. Initialize a hash table (std::unordered_map>) where keys are sorted anagrams + * and values are vectors of unsorted anagrams. This takes advantage of the observation that anagrams, when sorted, are + * identical. + * 2. For each string in input array: + * a. Create a sorted version of the string. + * b. If the sorted string is already in the hash table, add the unsorted string to the vector of strings associated \ + * with the sorted version. + * c. If the string is not in the hash table, add the sorted version as a key and the unsorted version as a value. + * 3. For each key in hash table, add contents of the associated vectors to a vector of strings. + * + * TIME COMPLEXITY: + * Step (1) takes O(1) time. + * Step (2) takes O(N) time assuming the strings are of constant length. + * Step (3) takes O(N) time. + * Thus the algorithm takes O(N) time. + * + * SPACE COMPLEXITY: + * The hash table will require O(N) space. + * + * CODE: + */ + #include "problem_10_02_anagramSort.h" namespace chapter_10 { - void anagramSort(std::vector>& array) { + void anagramSort(std::vector& array) { } } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h index 662a68c..b8ec2c5 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h @@ -3,5 +3,5 @@ #include namespace chapter_10 { - void anagramSort(std::vector>& array); + void anagramSort(std::vector& array); } From cd0d2027d3540961a2dea8a0525be7f63955e31f Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 24 Jun 2019 16:18:24 -0700 Subject: [PATCH 087/176] implement 10.2 C++. add more unit tests. --- .../problem_10_02_anagramSort.cpp | 27 +++++++++++++++++-- tests.cpp | 22 +++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp index db46467..89182a8 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -24,7 +24,7 @@ * Step (1) takes O(1) time. * Step (2) takes O(N) time assuming the strings are of constant length. * Step (3) takes O(N) time. - * Thus the algorithm takes O(N) time. + * Thus, the algorithm takes O(N) time. * * SPACE COMPLEXITY: * The hash table will require O(N) space. @@ -33,9 +33,32 @@ */ #include "problem_10_02_anagramSort.h" +#include namespace chapter_10 { void anagramSort(std::vector& array) { - + std::unordered_map> hashMap; + // traverse input array + for (const std::string& string : array) { + std::string sortedString = string; + std::sort(sortedString.begin(), sortedString.end()); + // sortedString in hashMap + if (hashMap.find(sortedString) != hashMap.end()) { + hashMap[sortedString].push_back(string); + } + // if sortedString not in hashMap ... + else { + std::vector anagramVector = {string}; + hashMap[sortedString] = anagramVector; + } + } + // place all values contents of hashMap into array thus placing anagrams next to each other + int index = 0; + for (const std::pair> pair : hashMap) { + for (const std::string& anagramString : pair.second) { + array[index] = anagramString; + index ++; + } + } } } diff --git a/tests.cpp b/tests.cpp index 6714a47..f7fc721 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1202,10 +1202,28 @@ TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()", "test"){ } TEST_CASE("Chapter 10 - Problem 02 - anagramSort()", "test"){ + // note that the order of std::unordered_map contents is not controllable + // expected values are chosen based on actual results produced by binaries made by a C++ 11 compiler std::vector example1 = {"ddd", "abc", "ccc", "bac", "aaa", "cab", "bbb", "acb"}; - std::vector expected1 = {"aaa", "abc", "acb", "bac", "cab", "bbb", "ccc", "ddd"}; + std::vector expected1 = {"ccc", "bbb", "abc", "bac", "cab", "acb", "aaa", "ddd"}; + std::vector example2 = {"aaa"}; + std::vector expected2 = {"aaa"}; + std::vector example3 = {}; + std::vector expected3 = {}; + std::vector example4 = {"a", "ddd", "abc", "ccc", "a", "bac", "aaa", "cab", "bbb", "acb", "a"}; + std::vector expected4 = { "bbb", "ddd", "ccc", "abc", "bac", "cab", "acb", "aaa", "a", "a", "a"}; + std::vector example5 = {"", "a", "", "b", ""}; + std::vector expected5 = {"a", "b", "", "", ""}; chapter_10::anagramSort(example1); + chapter_10::anagramSort(example2); + chapter_10::anagramSort(example3); + chapter_10::anagramSort(example4); + chapter_10::anagramSort(example5); REQUIRE(expected1 == example1); + REQUIRE(expected2 == example2); + REQUIRE(expected3 == example3); + REQUIRE(expected4 == example4); + REQUIRE(expected5 == example5); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ @@ -1225,7 +1243,7 @@ TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ chapter_02::SinglyLinkedNode* head = chapter_02::vectorToList(targetVector); chapter_02::SinglyLinkedNode* copy = chapter_12::copyNode(head); REQUIRE(targetVector == chapter_02::listToVector(copy)); // check that the values contained in nodes are identical - // Check that the pointers in the head linked list are *not* the same as the pointers in the copy likned list + // Check that the pointers in the head linked list are *not* the same as the pointers in the copy linked list // This is to verify a copy was actually made. while (head != nullptr && copy != nullptr){ REQUIRE(head != copy); From 5658fdf17d5f2dadd8b8da39bbd84d1c230f28d3 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 24 Jun 2019 16:19:45 -0700 Subject: [PATCH 088/176] update completion count --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6ba79b3..4759c1c 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ reference and contribute solutions with confidence. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `2 / 11` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `50` of `141` solutions complete. +C++ Total: `51` of `141` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `50` of `141` solutions complete. Python Total: `56` of `131` solutions complete. -##### Grand Total: `106` unique solutions complete. +##### Grand Total: `107` unique solutions complete. ### Building: #### Mac: From 59dc19c7de50aa5f3647c6f5510cab1300ca6f1e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 24 Jun 2019 19:55:31 -0700 Subject: [PATCH 089/176] fix sort include error --- .../problem_10_02_anagramSort.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp index 89182a8..ad6c191 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -34,6 +34,7 @@ #include "problem_10_02_anagramSort.h" #include +#include namespace chapter_10 { void anagramSort(std::vector& array) { From f7701aecbfb6cf2ca2d8a35e2c4c29fbd561eed0 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 25 Jun 2019 13:22:03 -0700 Subject: [PATCH 090/176] Use std::map instead of std:unordered_map to allow testability regardless of C++ compiler. --- .../problem_10_02_anagramSort.cpp | 8 ++++---- tests.cpp | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp index ad6c191..ce2cecb 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -10,9 +10,9 @@ * order of the sorted array does not matter. * * ALGORITHM: - * 1. Initialize a hash table (std::unordered_map>) where keys are sorted anagrams + * 1. Initialize a hash table (std::map>) where keys are sorted anagrams * and values are vectors of unsorted anagrams. This takes advantage of the observation that anagrams, when sorted, are - * identical. + * identical. Use std::map instead of std:unordered_map to allow testability regardless of C++ compiler. * 2. For each string in input array: * a. Create a sorted version of the string. * b. If the sorted string is already in the hash table, add the unsorted string to the vector of strings associated \ @@ -33,12 +33,12 @@ */ #include "problem_10_02_anagramSort.h" -#include +#include #include namespace chapter_10 { void anagramSort(std::vector& array) { - std::unordered_map> hashMap; + std::map> hashMap; // traverse input array for (const std::string& string : array) { std::string sortedString = string; diff --git a/tests.cpp b/tests.cpp index f7fc721..841d965 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1202,18 +1202,16 @@ TEST_CASE("Chapter 10 - Problem 01 - sortedMerge()", "test"){ } TEST_CASE("Chapter 10 - Problem 02 - anagramSort()", "test"){ - // note that the order of std::unordered_map contents is not controllable - // expected values are chosen based on actual results produced by binaries made by a C++ 11 compiler std::vector example1 = {"ddd", "abc", "ccc", "bac", "aaa", "cab", "bbb", "acb"}; - std::vector expected1 = {"ccc", "bbb", "abc", "bac", "cab", "acb", "aaa", "ddd"}; + std::vector expected1 = {"aaa", "abc", "bac", "cab", "acb", "bbb", "ccc", "ddd" }; std::vector example2 = {"aaa"}; std::vector expected2 = {"aaa"}; std::vector example3 = {}; std::vector expected3 = {}; std::vector example4 = {"a", "ddd", "abc", "ccc", "a", "bac", "aaa", "cab", "bbb", "acb", "a"}; - std::vector expected4 = { "bbb", "ddd", "ccc", "abc", "bac", "cab", "acb", "aaa", "a", "a", "a"}; + std::vector expected4 = {"a", "a", "a", "aaa", "abc", "bac", "cab", "acb", "bbb", "ccc", "ddd" }; std::vector example5 = {"", "a", "", "b", ""}; - std::vector expected5 = {"a", "b", "", "", ""}; + std::vector expected5 = { "", "", "", "a", "b" }; chapter_10::anagramSort(example1); chapter_10::anagramSort(example2); chapter_10::anagramSort(example3); From d16d51813919f78248e6bb32684846891fe58239 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 25 Jun 2019 15:00:38 -0700 Subject: [PATCH 091/176] interface and tests for 10.3 C++ --- .../chapter_10_includes.h | 1 + .../problem_10_03_rotatedSearch.h | 8 +++++ tests.cpp | 29 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index ce540d4..cc17891 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -1,6 +1,7 @@ #pragma once #include "problem_10_01_sortedMerge.h" #include "problem_10_02_anagramSort.h" +#include "problem_10_03_rotatedSearch.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h new file mode 100644 index 0000000..26d2388 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h @@ -0,0 +1,8 @@ +#pragma once + +namespace chapter_10 { + template + int rotatedSearch(const std::vector& array, const T& value) { + return 0; + } +} diff --git a/tests.cpp b/tests.cpp index 841d965..1e2b0e1 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1224,6 +1224,35 @@ TEST_CASE("Chapter 10 - Problem 02 - anagramSort()", "test"){ REQUIRE(expected5 == example5); } +TEST_CASE("Chapter 10 - Problem 03 - rotatedSearch()", "test"){ + // test unrotated + std::vector input1 = {-10000, -1000, -100, -10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; + std::vector input2 = {}; + std::vector input3 = {1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7}; + REQUIRE(-1 == chapter_10::rotatedSearch(input1, 101)); + REQUIRE(16 == chapter_10::rotatedSearch(input1, 1000)); + REQUIRE(4 == chapter_10::rotatedSearch(input1, 0)); + REQUIRE(15 == chapter_10::rotatedSearch(input1, 100)); + REQUIRE(13 == chapter_10::rotatedSearch(input1, 9)); + REQUIRE(10 == chapter_10::rotatedSearch(input1, 6)); + REQUIRE(-1 == chapter_10::rotatedSearch(input2, 101)); + REQUIRE(3 == chapter_10::rotatedSearch(input3, 1.4)); + REQUIRE(5 == chapter_10::rotatedSearch(input3, 1.6)); + // test rotated + std::vector rotatedInput1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000, -10000, -1000, -100, -10, 0}; // -5 rotation + std::vector rotatedInput2 = {}; + std::vector rotatedInput3 = {1.5, 1.6, 1.7, 1.1, 1.2, 1.3, 1.4}; // +3 rotation + REQUIRE(-1 == chapter_10::rotatedSearch(rotatedInput1, 101)); + REQUIRE(11 == chapter_10::rotatedSearch(rotatedInput1, 1000)); + REQUIRE(17 == chapter_10::rotatedSearch(rotatedInput1, 0)); + REQUIRE(10 == chapter_10::rotatedSearch(rotatedInput1, 100)); + REQUIRE(8 == chapter_10::rotatedSearch(rotatedInput1, 9)); + REQUIRE(5 == chapter_10::rotatedSearch(rotatedInput1, 6)); + REQUIRE(-1 == chapter_10::rotatedSearch(rotatedInput2, 101)); + REQUIRE(6 == chapter_10::rotatedSearch(rotatedInput3, 1.4)); + REQUIRE(1 == chapter_10::rotatedSearch(rotatedInput3, 1.6)); +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From e5d1ce6722f2b60cbe74e8821915e59e3d029158 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 25 Jun 2019 18:25:42 -0700 Subject: [PATCH 092/176] implement 10.3 C++ --- .../binarySearch.h | 2 +- .../problem_10_03_rotatedSearch.h | 61 ++++++++++++++++++- 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h b/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h index cf9234c..6b566df 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/binarySearch.h @@ -8,7 +8,7 @@ namespace chapter_10 { if (value == array[midpoint]) { // terminating condition: found query return midpoint; } - else if (start >= end) { // terminating condition: asked to search single element list which is not query + else if (start == end) { // terminating condition: asked to search single element list which is not query return -1; } else if (value < array[midpoint]) { // recurse left diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h index 26d2388..5424f0e 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_03_rotatedSearch.h @@ -1,8 +1,67 @@ +/* + * PROBLEM: + * Given a sorted array that has been rotated by an unknown offset, write code to find + * an element in the array. Assume the array was originally sorted in increasing order. + * + * TEST CASE: + * search({1.5, 1.6, 1.7, 1.1, 1.2, 1.3, 1.4}, 1.6) -> 1 + * + * ALGORITHM: + * 0. Observe that an invariant in this problem is that in such an array, there is one adjacent pair of elements that are + * the sorted first element and sorted last element. Thus, if the array is divided in half, one or both halves must be + * correctly sorted. + * 1. If the array is of size 1 or 0, handle the terminating condition. + * 2. Recursively divide the input array in half. + * 3. For each half... + * a. If the beginning and end elements are in numerical order... + * i. Call binarySearch to find the element. + * b. If the beginning and end elements are *not* in numerical order... + * i. Recurse on the halves of the array. + * + * TIME COMPLEXITY: O(log(N)) in average case. O(N) in worst case. + * + * SPACE COMPLEXITY: O(1) + * + * CODE: + */ + + #pragma once +#include "binarySearch.h" namespace chapter_10 { + template + int rotatedSearchHelper(const std::vector& array, const T& value, int start, int end) { + if (start > end) return -1; // terminating condition: asked to search empty list + int midpoint = (end - start) / 2 + start; + if (value == array[midpoint]) { // terminating condition: found query + return midpoint; + } + else if (start == end) { // terminating condition: asked to search single element list which is not query + return -1; + } + + if (array[start] <= array[end] && value >= array[start] && value <= array[end]) { // this is a normally sorted array - use binary searc + return binarySearchHelper(array, value, start, end); + } + else { // this array was rotated, recurse on its halves + if (array[start] <= array[midpoint - 1] && value >= array[start] && value <= array[midpoint - 1]) { // left half is sorted and may contain value + return binarySearchHelper(array, value, start, midpoint - 1); + } + if (array[midpoint + 1] <= array[end] && value >= array[midpoint + 1] && value <= array[end]) { // right half is sorted and may contain value + return binarySearchHelper(array, value, midpoint + 1, end); + } + // neither sorted half may contain the value. recurse on rotated halves + int left_result = rotatedSearchHelper(array, value, start, midpoint - 1); + if (left_result != -1) return left_result; + int right_result = rotatedSearchHelper(array, value, midpoint + 1, end); + if (right_result != -1) return right_result; + } + return -1; + } + template int rotatedSearch(const std::vector& array, const T& value) { - return 0; + return rotatedSearchHelper(array, value, 0, array.size() - 1); } } From 898e4d9cf2b210297cafaf731c9ee3400243da5d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 25 Jun 2019 18:26:25 -0700 Subject: [PATCH 093/176] update completion count --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4759c1c..d69fea1 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ reference and contribute solutions with confidence. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `2 / 11` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `3 / 11` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `51` of `141` solutions complete. +C++ Total: `52` of `141` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `51` of `141` solutions complete. Python Total: `56` of `131` solutions complete. -##### Grand Total: `107` unique solutions complete. +##### Grand Total: `108` unique solutions complete. ### Building: #### Mac: From b47e7f22a5502ba7c82baabfab5792429f242064 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 26 Jun 2019 14:53:26 -0700 Subject: [PATCH 094/176] implement 10.4 C++ --- CMakeLists.txt | 1 + README.md | 6 +-- .../chapter_10_includes.h | 1 + .../problem_10_02_anagramSort.cpp | 34 ------------- .../problem_10_02_anagramSort.h | 34 +++++++++++++ .../problem_10_04_searchNoSize.cpp | 42 ++++++++++++++++ .../problem_10_04_searchNoSize.h | 48 +++++++++++++++++++ tests.cpp | 11 +++++ 8 files changed, 140 insertions(+), 37 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 603ed43..fbeb35a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ set(SOURCE_FILES cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp + cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp) diff --git a/README.md b/README.md index d69fea1..68270dd 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ reference and contribute solutions with confidence. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `3 / 11` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `4 / 11` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `52` of `141` solutions complete. +C++ Total: `53` of `141` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `52` of `141` solutions complete. Python Total: `56` of `131` solutions complete. -##### Grand Total: `108` unique solutions complete. +##### Grand Total: `109` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index cc17891..a393847 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -2,6 +2,7 @@ #include "problem_10_01_sortedMerge.h" #include "problem_10_02_anagramSort.h" #include "problem_10_03_rotatedSearch.h" +#include "problem_10_04_searchNoSize.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp index ce2cecb..02898bc 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp @@ -1,37 +1,3 @@ -/* - * PROBLEM: - * Given an array of strings, sort the array such that all anagrams are next to each other. - * Anagrams are strings that contain the same characters e.g. "abc" and "bca". - * - * TEST CASE: - * Input: {ddd, abc, ccc, bac, aaa, cab, bbb, acb} - * Output: {aaa, abc, acb, bac, cab, bbb, ccc, ddd} - * Note that the only requirement is for anagrams to be next to each other. The order of the anagram groups and the - * order of the sorted array does not matter. - * - * ALGORITHM: - * 1. Initialize a hash table (std::map>) where keys are sorted anagrams - * and values are vectors of unsorted anagrams. This takes advantage of the observation that anagrams, when sorted, are - * identical. Use std::map instead of std:unordered_map to allow testability regardless of C++ compiler. - * 2. For each string in input array: - * a. Create a sorted version of the string. - * b. If the sorted string is already in the hash table, add the unsorted string to the vector of strings associated \ - * with the sorted version. - * c. If the string is not in the hash table, add the sorted version as a key and the unsorted version as a value. - * 3. For each key in hash table, add contents of the associated vectors to a vector of strings. - * - * TIME COMPLEXITY: - * Step (1) takes O(1) time. - * Step (2) takes O(N) time assuming the strings are of constant length. - * Step (3) takes O(N) time. - * Thus, the algorithm takes O(N) time. - * - * SPACE COMPLEXITY: - * The hash table will require O(N) space. - * - * CODE: - */ - #include "problem_10_02_anagramSort.h" #include #include diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h index b8ec2c5..cbab018 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.h @@ -1,3 +1,37 @@ +/* + * PROBLEM: + * Given an array of strings, sort the array such that all anagrams are next to each other. + * Anagrams are strings that contain the same characters e.g. "abc" and "bca". + * + * TEST CASE: + * Input: {ddd, abc, ccc, bac, aaa, cab, bbb, acb} + * Output: {aaa, abc, acb, bac, cab, bbb, ccc, ddd} + * Note that the only requirement is for anagrams to be next to each other. The order of the anagram groups and the + * order of the sorted array does not matter. + * + * ALGORITHM: + * 1. Initialize a hash table (std::map>) where keys are sorted anagrams + * and values are vectors of unsorted anagrams. This takes advantage of the observation that anagrams, when sorted, are + * identical. Use std::map instead of std:unordered_map to allow testability regardless of C++ compiler. + * 2. For each string in input array: + * a. Create a sorted version of the string. + * b. If the sorted string is already in the hash table, add the unsorted string to the vector of strings associated \ + * with the sorted version. + * c. If the string is not in the hash table, add the sorted version as a key and the unsorted version as a value. + * 3. For each key in hash table, add contents of the associated vectors to a vector of strings. + * + * TIME COMPLEXITY: + * Step (1) takes O(1) time. + * Step (2) takes O(N) time assuming the strings are of constant length. + * Step (3) takes O(N) time. + * Thus, the algorithm takes O(N) time. + * + * SPACE COMPLEXITY: + * The hash table will require O(N) space. + * + * CODE: + */ + #pragma once #include #include diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp new file mode 100644 index 0000000..260fbcf --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp @@ -0,0 +1,42 @@ +#include "problem_10_04_searchNoSize.h" +#include + +namespace chapter_10 { + int searchNoSizeHelper(const Listy& array, const int& value, int start, int end) { + if (start > end) return -1; + int midpoint = (end - start) / 2 + start; + if (array.elementAt(midpoint) == value){ + return midpoint; + } + else if (start == end) { + return -1; + } + int leftRecursionMidpointValue = array.elementAt(midpoint -1); + if (leftRecursionMidpointValue == -1) leftRecursionMidpointValue = INT_MAX; + if (array.elementAt(start) <= value && value <= leftRecursionMidpointValue) { + return searchNoSizeHelper(array, value, start, midpoint - 1); + } + else { + return searchNoSizeHelper(array, value, midpoint + 1, end); + } + } + + int computeIndex(int exponent) { return static_cast(std::pow(2, exponent) - 1); } + + int computeEndpoint(const Listy& array) { + if (array.elementAt(0) == -1) return -1; // handle empty array + int exponent = 0; + int index = computeIndex(exponent); + while (array.elementAt(index) != -1) { + exponent ++; + index = computeIndex(exponent); + } + return index; + } + + int searchNoSize(const Listy& array, int value) { + int end = computeEndpoint(array); + if (end == -1) return -1; + return searchNoSizeHelper(array, value, 0, end); + } +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.h new file mode 100644 index 0000000..b7f1e8e --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.h @@ -0,0 +1,48 @@ +/* + * PROBLEM: + * You are given an array-like data structure Listy which lacks a size method. + * It does, however, have an elementAt (i) method that returns the element at + * index i in 0(1) time. If i is beyond the bounds of the data structure, it + * returns - 1. (For this reason, the data structure only supports positive integers.) + * Given a Listy which contains sorted, positive integers, find the index at which an + * element x occurs. If x occurs multiple times, you may return any index. + * + * TEST CASE: + * Same as for vanilla search: + * searchNoSize({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 3) -> 3 + * + * ALGORITHM: + * We need to find an upper bound for the size of the array. One way to do this is to try + * elementAt() on indices increasing in a linear pattern e.g. 1,2,3,4,... This is a linear + * time procedure which is no worse than just brute force linear searching the array. + * + * To find the upper bounds of the array in O(log(N)) time, we try elementAt() on indices increasing + * in an exponential pattern e.g 2^0, 2^1, 2^2, 2^3, 2^4 until elementAt() returns -1. + * + * We have to account for "-1" values in the binary search by considering -1 to be greater + * than any possible query value. This issue affects only the midpoint values that are used + * to determine which side of the array to recurse on. + * + * TIME COMPLEXITY: O(log(N)) + * + * SPACE COMPLEXITY: O(1) + */ + +#pragma once +#include + +namespace chapter_10 { + // implement "Listy" as described in problem description + // by removing size() from std::vector + // and adding elementAt() + // and supporting only ints + class Listy : public std::vector { + private: + using std::vector::size; // do not allow size computation as specified in problem description + using std::vector::operator[]; // do not allow operator[]; force user to use elementAt() + public: + Listy(std::initializer_list il) : std::vector(il){} // inherit initializer list constructor + int elementAt(int i) const { return (i >= 0 && i < this->size()) ? (*this)[i] : -1; } + }; + int searchNoSize(const Listy& array, int value); +} diff --git a/tests.cpp b/tests.cpp index 1e2b0e1..0483251 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1253,6 +1253,17 @@ TEST_CASE("Chapter 10 - Problem 03 - rotatedSearch()", "test"){ REQUIRE(1 == chapter_10::rotatedSearch(rotatedInput3, 1.6)); } +TEST_CASE("Chapter 10 - Problem 04 - rotatedSearch()", "test"){ + chapter_10::Listy input1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 10000}; + chapter_10::Listy input2 = {}; + REQUIRE(-1 == chapter_10::searchNoSize(input1, 101)); + REQUIRE(11 == chapter_10::searchNoSize(input1, 1000)); + REQUIRE(10 == chapter_10::searchNoSize(input1, 100)); + REQUIRE(8 == chapter_10::searchNoSize(input1, 9)); + REQUIRE(5 == chapter_10::searchNoSize(input1, 6)); + REQUIRE(-1 == chapter_10::searchNoSize(input2, 101)); +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From 941c2a7a0c2d4fb1d4ed593faf8c967a44bb87fb Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 26 Jun 2019 14:56:24 -0700 Subject: [PATCH 095/176] use STL int limits --- .../problem_10_04_searchNoSize.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp index 260fbcf..894a352 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp @@ -1,5 +1,6 @@ #include "problem_10_04_searchNoSize.h" #include +#include namespace chapter_10 { int searchNoSizeHelper(const Listy& array, const int& value, int start, int end) { @@ -12,7 +13,7 @@ namespace chapter_10 { return -1; } int leftRecursionMidpointValue = array.elementAt(midpoint -1); - if (leftRecursionMidpointValue == -1) leftRecursionMidpointValue = INT_MAX; + if (leftRecursionMidpointValue == -1) leftRecursionMidpointValue = std::numeric_limits::max(); if (array.elementAt(start) <= value && value <= leftRecursionMidpointValue) { return searchNoSizeHelper(array, value, start, midpoint - 1); } From a7b0c4951765aa4715616c4668f91053b534b4a0 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 27 Jun 2019 16:25:18 -0700 Subject: [PATCH 096/176] implement 10.5 C++ --- CMakeLists.txt | 1 + README.md | 6 +- .../chapter_10_includes.h | 1 + .../problem_10_05_sparseSearch.cpp | 64 +++++++++++++++++++ .../problem_10_05_sparseSearch.h | 30 +++++++++ tests.cpp | 16 +++++ 6 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fbeb35a..71e9847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,7 @@ set(SOURCE_FILES # problem 10.01 not included because it is a template function implemented in .h file cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp + cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp) diff --git a/README.md b/README.md index 68270dd..3edcc7a 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ reference and contribute solutions with confidence. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `4 / 11` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `5 / 11` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `53` of `141` solutions complete. +C++ Total: `54` of `141` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `53` of `141` solutions complete. Python Total: `56` of `131` solutions complete. -##### Grand Total: `109` unique solutions complete. +##### Grand Total: `110` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index a393847..b849d65 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -3,6 +3,7 @@ #include "problem_10_02_anagramSort.h" #include "problem_10_03_rotatedSearch.h" #include "problem_10_04_searchNoSize.h" +#include "problem_10_05_sparseSearch.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp new file mode 100644 index 0000000..67b9103 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp @@ -0,0 +1,64 @@ +#include "problem_10_05_sparseSearch.h" + +namespace chapter_10 { + int sparseSearchHelper(const std::vector& array, const std::string& query, int start, int end) { + // check terminating conditions + if (start > end) return -1; + int midpoint = (end - start) / 2 + start; + + // handle comparison against empty string + std::string comparisonValue = array[midpoint]; + int leftPotentialMidpoint = midpoint; + int rightPotentialMidpoint = midpoint; + if (comparisonValue == "") { + std::string leftPotentialComparisonValue = comparisonValue; + std::string rightPotentialComparisonValue = comparisonValue; + while ((leftPotentialMidpoint >= start || rightPotentialMidpoint <= end) && leftPotentialComparisonValue == "" && rightPotentialComparisonValue == "") { + // search left + if (leftPotentialMidpoint >= start) { + leftPotentialMidpoint --; + leftPotentialComparisonValue = array[leftPotentialMidpoint]; + } + // search right + if (rightPotentialMidpoint <= end) { + rightPotentialMidpoint ++; + rightPotentialComparisonValue = array[rightPotentialMidpoint]; + } + // check if left midpoint is non-empty + if (leftPotentialComparisonValue != "") { + comparisonValue = leftPotentialComparisonValue; + midpoint = leftPotentialMidpoint; + break; + } + // check if right midpoint is non-empty + if (rightPotentialComparisonValue != "") { + comparisonValue = rightPotentialComparisonValue; + midpoint = rightPotentialMidpoint; + break; + } + } + if (leftPotentialComparisonValue == "" && rightPotentialComparisonValue == "") { + return -1; // the array contains only ""; there no possibility of a match + } + } + // check terminating conditions after midpoint adjustment + if (array[midpoint] == query) { + return midpoint; + } + else if (start == end) { + return -1; + } + + // recurse left - do not include array elements that are known to be empty + if (query >= array[start] && query <= array[midpoint]) { + return sparseSearchHelper(array, query, start, (leftPotentialMidpoint < (midpoint - 1) ? leftPotentialMidpoint : (midpoint - 1))); + } + else { // recurse right - do not include array elements that are known to be empty + return sparseSearchHelper(array, query, (rightPotentialMidpoint > (midpoint - 1) ? rightPotentialMidpoint : (midpoint - 1)), end); + } + } + + int sparseSearch(const std::vector& array, const std::string& query) { + return sparseSearchHelper(array, query, 0, array.size() - 1); + } +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.h new file mode 100644 index 0000000..78bc335 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.h @@ -0,0 +1,30 @@ +/* + * PROBLEM: + * Assume a sparse array of strings where the contents are sorted but separated + * by empty strings. Write an algorithm to search for a given string. + * + * TEST CASE: + * sparseSearch({"at", "", "", "", "ball", "" , "", "car", "", "", "dad", "", ""}, "ball") -> 4 + * + * ALGORITHM: + * Brute force approach is linear search thru array. Vanilla binary search does not work + * because comparison against query value is required at every recursive step. + * + * Design a modified form of binary search that handles midpoint comparison against an empty string + * by doing a local linear search to find the nearest non-empty string. + * + * It is assumed that empty strings are not valid queries, i.e. searching for "" will return -1. + * + * TIME COMPLEXITY: O(N) worst case, O(long(N)) best case + * SPACE COMPLEXITY: O(1) + * + * CODE: + */ + +#pragma once +#include +#include + +namespace chapter_10 { + int sparseSearch(const std::vector& array, const std::string& query); +} diff --git a/tests.cpp b/tests.cpp index 0483251..ae4afae 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1264,6 +1264,22 @@ TEST_CASE("Chapter 10 - Problem 04 - rotatedSearch()", "test"){ REQUIRE(-1 == chapter_10::searchNoSize(input2, 101)); } +TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ + std::vector input1 = {"at", "", "", "", "ball", "" , "", "car", "", "", "dad", "", ""}; + std::vector input2 = {"", "", "", "", ""}; + std::vector input3 = {}; + std::vector input4 = {"alex"}; + REQUIRE(0 == chapter_10::sparseSearch(input1, "at")); + REQUIRE(4 == chapter_10::sparseSearch(input1, "ball")); + REQUIRE(7 == chapter_10::sparseSearch(input1, "car")); + REQUIRE(10 == chapter_10::sparseSearch(input1, "dad")); + REQUIRE(-1 == chapter_10::sparseSearch(input1, "alex")); + REQUIRE(-1 == chapter_10::sparseSearch(input2, "alex")); + REQUIRE(-1 == chapter_10::sparseSearch(input3, "")); + REQUIRE(-1 == chapter_10::sparseSearch(input3, "alex")); + REQUIRE(0 == chapter_10::sparseSearch(input4, "alex")); +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From c9072256a633ce055f1c97b0f051ab4dc31682ae Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 1 Jul 2019 16:23:24 -0700 Subject: [PATCH 097/176] WIP 10.7 --- .../CMakeLists.txt | 1 + .../generate_random_number_file.cpp | 11 +++++ .../problem_10_07_missingInt_dataset.txt | 0 .../chapter_10_includes.h | 1 + .../problem_10_07_missingInt.h | 40 +++++++++++++++++++ tests.cpp | 4 ++ 6 files changed, 57 insertions(+) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/problem_10_07_missingInt_dataset.txt create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt new file mode 100644 index 0000000..04e6b23 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt @@ -0,0 +1 @@ +CMakeLists.txt \ No newline at end of file diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp new file mode 100644 index 0000000..c8c8b08 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp @@ -0,0 +1,11 @@ +#include +#include +#include + +int main(int argc, char* argv[]) { + if (argc != 2) { + std::cout << "Usage: ./generate_random_number_file title.csv" << std::endl; + } + std::cout << "Hello World." << std::endl; + return 0; +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/problem_10_07_missingInt_dataset.txt b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/problem_10_07_missingInt_dataset.txt new file mode 100644 index 0000000..e69de29 diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index b849d65..a0c6592 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -4,6 +4,7 @@ #include "problem_10_03_rotatedSearch.h" #include "problem_10_04_searchNoSize.h" #include "problem_10_05_sparseSearch.h" +#include "problem_10_07_missingInt.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h new file mode 100644 index 0000000..8abd4a0 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h @@ -0,0 +1,40 @@ +/* + * PROBLEM: Given an input file with 4 billion non-negative integers, provide an algorithm + * to generate an integer that is not contained in the file. Assume you have 1GB of memory + * available for this task. + * + * Questions and thoughts: + * 1. Are these 32 bit integers? I.e. what is the possible range of numbers? + * 2. For example, if the integers were limited to 8 unsigned bit ints, then all possible + * numbers in the file would range between 0 and 255. We would thus only need a 2^8 = 256 + * element array of bits to determine uniqueness for any size of input file stored on disk. + * 3. If the integers are 32 bit unsigned integers (uint32_t), then we will need a 2^32 + * element array of bits to keep track of the uniqueness of the numbers in the file. + * 4. 2^32 = 4,294,967,296 bits, so if only 4 billion numbers are stored, there must be possible + * positive unsigned ints that are not in the file. + * 5. 4,294,967,296 bits = 536,870,912 bytes = approximately 500MB. Thus, this array will fit within our + * allotted 1GB of space. + * 6. Thus, one algorithm would be: + * a. Allocate an array of 2^32 bits all set to zero. + * b. For each integer in the file... + * i. Use the integer itself as the index of the array. + * ii. Flip the bit associated with that index if it is not already a 1. + * c. Iterate through the array of bits and return the index with the first 0. + * + * TEST CASE: + * {11, 1, 3, 4, 5, 7, 8, ... } -> 0 + * + * ALGORITHM: See above. + * + * TIME COMPLEXITY: O(N) + * + * SPACE COMPLEXITY: O(1) (2^32 is a constant) + * + * CODE: + */ + +#pragma once + +namespace chapter_10 { + +} diff --git a/tests.cpp b/tests.cpp index ae4afae..58c841e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1280,6 +1280,10 @@ TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ REQUIRE(0 == chapter_10::sparseSearch(input4, "alex")); } +TEST_CASE("Chpater 10 - Problem 07 - missingInt()", "test") { + +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From f7018e8b8b06802a2fd733aa58dcf445e6bbcd0e Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 1 Jul 2019 22:29:26 -0700 Subject: [PATCH 098/176] WIP 10.7 make dataset generator --- .../CMakeLists.txt | 5 +- .../generate_random_number_file.cpp | 22 +- .../problem_10_07_missingInt_dataset.txt | 0 .../random_number_dataset.csv | 10000 ++++++++++++++++ 4 files changed, 10021 insertions(+), 6 deletions(-) delete mode 100644 cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/problem_10_07_missingInt_dataset.txt create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt index 04e6b23..845af85 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/CMakeLists.txt @@ -1 +1,4 @@ -CMakeLists.txt \ No newline at end of file +cmake_minimum_required(VERSION 3.2) +project(ctci) +set(CMAKE_CXX_STANDARD 17) +add_executable(generate_random_number_file generate_random_number_file.cpp) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp index c8c8b08..30828f0 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp @@ -1,11 +1,23 @@ #include #include +#include #include -int main(int argc, char* argv[]) { - if (argc != 2) { - std::cout << "Usage: ./generate_random_number_file title.csv" << std::endl; - } - std::cout << "Hello World." << std::endl; +int main() { + std::string filename = "random_number_dataset.csv"; + std::cout << "Random number file generator outputting to " << filename << std::endl; + // initialize random integer generator + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution dis(0, 0xFFFFFFFF); + // initialize file stream + std::ofstream file; + file.open(filename); + // write to file line by line + for (int i = 0; i < 10000; i++) { // problem 10.7 specifies 4 billion numbers, for testing speed, we only write 10000 + file << dis(gen); + file << ",\n"; + } + file.close(); return 0; } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/problem_10_07_missingInt_dataset.txt b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/problem_10_07_missingInt_dataset.txt deleted file mode 100644 index e69de29..0000000 diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv new file mode 100644 index 0000000..0fb3baf --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv @@ -0,0 +1,10000 @@ +1100477961, +1652447454, +261484134, +2043068596, +3185495719, +1415328266, +4163204002, +1446710750, +730564350, +261503084, +2740822988, +368439367, +2878267789, +1433659097, +2816780038, +178988299, +2984306236, +2176298575, +1003010991, +115438597, +3828740510, +4036064970, +2573562654, +1076366297, +2701360747, +1601213147, +1461289407, +1514292940, +2124588553, +331982679, +94360180, +2709747944, +3063467437, +2376733275, +385877409, +2482807055, +1558226881, +1402451769, +3076224094, +3878055095, +2945557773, +1072729608, +2840197615, +2120390509, +1885441359, +122651044, +37557104, +484377594, +1311623039, +638993534, +2452073556, +1847031156, +1325443041, +99818842, +3813017370, +2046404018, +1283225977, +4226783084, +4273948322, +3075667195, +688658636, +249731199, +1976131964, +827922991, +1706528251, +2565732636, +3206793313, +3965700280, +869117897, +429265681, +3379615961, +3706310532, +4285093195, +1392041644, +2030760141, +1719600413, +1404611149, +4112386107, +2663036421, +264189723, +2170647908, +3040339852, +1033038705, +3119270429, +2654116764, +859814000, +3362154321, +2055586902, +3265146807, +1046772581, +290418451, +2503314879, +3819590370, +3971132823, +1113548352, +1737111099, +2334331800, +4231942272, +864382156, +2175275855, +2991934467, +1121718249, +1653733779, +1624875153, +3691658010, +261980518, +3889553252, +3762220972, +1963013312, +2112573856, +4278620648, +4262473123, +4118277281, +1037011621, +2144529746, +3816564830, +3726556684, +4249332106, +2438364091, +4084228912, +4092871188, +3410518180, +3617016315, +2869299304, +1348722556, +2118937090, +1658089200, +694608989, +1518156758, +364418051, +1429049696, +645545457, +3947358566, +3224550883, +2155803382, +977892224, +1556833341, +249886196, +4196699459, +4136132338, +694496419, +2482762920, +4069434394, +69501383, +195194089, +2941932039, +1066509059, +4239453094, +3115665281, +1213168680, +2114008186, +761299643, +3546151950, +427995915, +2731685436, +941267896, +103285609, +999654280, +4130416661, +2648943707, +1307363936, +1158958269, +1524114715, +1130083105, +936664542, +1502118657, +2427818817, +2662546266, +925499947, +3680028276, +3242306099, +2933692873, +185671027, +1858855275, +387784983, +2249192958, +4020397031, +1893246481, +1997403139, +1827818797, +1713169863, +811659426, +3304167040, +909120617, +3930590834, +676732824, +508131858, +1541172880, +2662383628, +1389631668, +1265591278, +2084191894, +3212372503, +3491045396, +2043975856, +3096981178, +576067518, +797423674, +2767990522, +1748027658, +2821488335, +221068738, +1434338358, +3829669489, +952488733, +1080872600, +2676231383, +2242629260, +2438065083, +1260991665, +2531461610, +441431587, +1625674663, +3862688977, +3024716911, +645146459, +912650877, +297023363, +1202469255, +2574076328, +2801282200, +2970253989, +3539175770, +3277919719, +2099233802, +1982407451, +3997141854, +861042050, +3523316086, +3701558277, +2912583572, +2581785373, +2383576584, +1529165601, +3513688815, +3704780959, +3731007407, +2410671624, +3378864391, +4290242254, +3295971986, +3768310062, +923529540, +546698155, +335204403, +1051837899, +340695435, +1605503799, +2734028774, +3658192465, +515852004, +1626001913, +2002912241, +540822551, +1251405574, +3913455310, +1112304761, +1904483295, +2864706392, +1475047497, +1229519579, +2605518176, +1131354398, +2148454618, +1162848047, +396799844, +2373682447, +809552513, +3613502286, +158307807, +763775550, +434535862, +1395395872, +1755676835, +3088085656, +44534804, +2589729491, +3791161892, +1234335687, +4020565241, +2174078619, +814281428, +2410782751, +1314702019, +516448281, +1296152045, +1073752572, +369088688, +4153591698, +833899074, +569140254, +467164613, +3285420507, +2576814287, +386707535, +687610484, +2514033411, +3762704068, +1165096289, +1087068193, +1339517559, +4127016471, +2804116074, +3172089071, +1941716621, +276472791, +1920669284, +1113510775, +571879707, +3624210036, +354047770, +1786475538, +546839479, +2155381648, +3504211849, +953727281, +2485187088, +1854283937, +3074096956, +2105589714, +2781260887, +3432495676, +278553706, +4115755020, +1470439850, +818528879, +108374485, +2416244887, +363292977, +1888056832, +3195701016, +3058623217, +298048593, +325882732, +2046541899, +2087863575, +4283401375, +3345087278, +4280427815, +1850570291, +745921044, +2809865779, +2859658071, +1080967201, +599342624, +940395135, +2859226690, +4013248248, +4204764808, +2309952594, +1633614237, +3241210163, +735717174, +1873949585, +2940779254, +130665750, +3176258097, +129378850, +3458902572, +1935380199, +1122262229, +591533090, +2684976106, +3579346406, +2529988356, +2844338265, +2360176405, +1808165549, +3773074109, +2691419739, +4194639224, +2642668314, +3890649289, +2332989576, +3990915977, +4002944292, +1267834141, +1121067284, +951391947, +2103414253, +889528141, +551933343, +2248836399, +2897492091, +3951876289, +1600111674, +3201256854, +2489588509, +1234656274, +3120216706, +2009532528, +1903384728, +1024466378, +1603218767, +3160297921, +3900948751, +293424763, +210355672, +1138233373, +2414734655, +4255181124, +3157200213, +1149988917, +2758082382, +1773681037, +1600083343, +492800729, +4016574088, +624497732, +2811368363, +924823715, +2294913707, +3013761916, +1052076323, +389724638, +3691766901, +461922126, +1360247690, +1325817345, +4033579655, +1200553239, +3259232220, +1215489410, +3874448292, +831394595, +1472925473, +2323748845, +3014048734, +136715974, +1824563568, +2872414721, +2079873803, +1028489994, +2813653065, +133768880, +3975444049, +2873992997, +385052527, +1671605681, +588562433, +3398741399, +2898108987, +444206860, +2191591564, +3513058319, +2072928231, +214047629, +2736540647, +2228752268, +464595745, +295594618, +3437542488, +3205272179, +493441210, +1253505611, +1847693502, +1275549209, +3537699366, +1779350630, +2017485618, +3358615723, +3096605876, +1555627925, +3120500152, +758892650, +3880505048, +2238549237, +3969773615, +610150672, +1741463243, +2494382326, +1899611690, +2239814447, +3417436151, +965185602, +2172588487, +1158244281, +526601389, +1814081341, +3819586186, +1600964092, +2067121412, +2036102405, +1371712524, +1230053635, +133390221, +639575804, +2636211606, +2140580237, +587159908, +3794595710, +2005080328, +3666459989, +1249457687, +931876231, +815421747, +414189862, +3744958524, +3339720737, +3565630865, +977940003, +2163439514, +4256872083, +1152564722, +903529089, +3943002628, +144477906, +3182424014, +4274006488, +3687575103, +31685662, +2607111813, +1319546868, +2414011043, +3727291623, +771854470, +2833714688, +3454448216, +846908794, +3967278929, +3246736270, +3730870637, +2198135185, +3021925943, +440827932, +1570738994, +2004102768, +541597714, +4222695306, +445444421, +3511296416, +2809352018, +355983627, +1604238547, +189517530, +2677680363, +3808675282, +1497058862, +3666225849, +3639959291, +1043143072, +3124661061, +327304642, +308157398, +1111886464, +3945372781, +594327217, +841061704, +820589698, +1842795227, +1610366167, +630601318, +1761901230, +1820014881, +1943262146, +525753968, +3102769544, +868144579, +1780087880, +45862275, +357788301, +2344893857, +892288804, +3788659795, +3210994637, +2470810555, +3860658815, +2910538762, +1468683069, +2031421600, +2567822684, +2327177804, +2732479849, +3057793225, +2810866284, +3197002260, +2845735913, +4077751180, +280089851, +4263718325, +4127821354, +197698242, +2232735225, +4098411646, +3258522809, +3242124996, +1795452577, +3797792817, +338202178, +3003560638, +2913238850, +848849110, +2914836538, +3114979352, +528798042, +683329003, +1504700481, +3909292477, +1983892074, +4188173442, +374291470, +4228791656, +4112489926, +1906373083, +1408659822, +864892524, +3323037615, +2421802036, +3678895195, +2850712563, +1446400572, +3620348608, +368451183, +596994593, +1162335617, +2756359957, +3411820436, +4013174286, +2815328888, +2892683858, +1629606863, +2127298000, +3705582288, +2802813393, +1983302423, +2530690582, +698202753, +1456195446, +3927207445, +1635533332, +979932588, +3259827511, +2577526013, +1192814668, +4118375256, +2006116752, +1227179469, +3986873523, +1966898758, +1718164012, +2182307026, +4260080772, +3738289684, +2505263416, +2805471991, +687185054, +294010524, +3159922046, +428014191, +3495813308, +3167526219, +3385519339, +2293855526, +2235419650, +2656103854, +1922926052, +2015233494, +2419225081, +421166411, +3936757637, +2256374172, +3597208409, +3786539583, +470843535, +622747246, +2022496941, +3584730260, +181477613, +1894738132, +1661584751, +4177023093, +2179535391, +1072488843, +1690895848, +2855679964, +301436382, +2290321534, +2211905997, +4002729323, +493459033, +3428447741, +3362391866, +805064919, +3437788837, +1047471401, +1487998798, +4260951328, +2443265101, +739246734, +2830727425, +1335776638, +1948685945, +67477937, +2093401757, +3829003920, +2262610104, +3419329602, +2557272072, +2086911732, +1300327415, +1437831113, +18521712, +764037321, +3694883618, +938829537, +1456677762, +1150457278, +1665418679, +1046938575, +2305353445, +3628641180, +1947185301, +3471600308, +2284513489, +3354237916, +3997593012, +124393372, +711042703, +242717072, +4221335992, +554340229, +2329882317, +617150908, +1593806206, +18277787, +1956805855, +731963339, +3932081507, +1345684139, +802398280, +1467324946, +845690797, +1937838721, +3097877896, +2087266853, +4210998569, +1760654746, +2730689541, +3580661838, +2902214190, +52087673, +3589698862, +285547768, +2150572806, +1586001777, +3136389534, +2740245901, +2248666844, +619512847, +828884843, +672579383, +3204291231, +1122857041, +1728386544, +615252700, +3343927776, +2127110698, +4050816467, +2433333445, +378747301, +3670398947, +2056662657, +348286869, +935681822, +614758827, +1289263739, +3089752674, +3799398902, +3727555305, +1704346301, +298943673, +4257212552, +2053109412, +2887416849, +266044935, +2152851584, +4268753166, +918084747, +919716001, +4067968448, +3733105257, +2112298691, +483010191, +66548301, +4262638676, +3536017313, +1061460878, +3405340082, +3085424017, +492091276, +2977758083, +3821764126, +1688862353, +1700395542, +1424483227, +536499827, +417790448, +2032178806, +729858102, +130839018, +4022505267, +2114377967, +2289262819, +1950218216, +2346979874, +1607760380, +579312231, +2232791197, +131940104, +159776084, +1701984394, +503244241, +114369590, +2738784629, +2674067195, +2317045283, +2760887389, +1657850868, +92181800, +4157752509, +3735373046, +3695470145, +3940277616, +3121553026, +3424670392, +3054021267, +2183132308, +1864271308, +1214414834, +1812805328, +2529052271, +554030053, +4023548879, +1588470569, +2498376000, +3807192887, +2786655072, +1085418282, +4262779677, +5261501, +564256658, +3640994542, +1585603230, +2465642404, +2101884962, +1374932429, +1887900214, +570777568, +2758706488, +3158664926, +1601822439, +3899215867, +8697684, +3375055132, +1325796286, +3417713083, +4810724, +2470631868, +2597747716, +1617278807, +377657170, +3271643040, +2023976461, +3294395028, +1716997834, +1668981780, +2573253033, +753457411, +4258295929, +1777816792, +2566096308, +633042035, +356276037, +3733325936, +871858868, +137759775, +341833648, +3485622992, +3442166613, +1080202412, +1930775198, +3712456985, +1561044305, +111177341, +938639632, +3524172332, +1748855567, +2330499534, +4272848935, +3015438805, +682835942, +1903064304, +3718928678, +1195048982, +1909543434, +478474930, +1073815656, +3839319088, +799156186, +324807884, +3183913807, +3826212419, +4002170049, +2365998048, +3671348598, +352874165, +3958194971, +1087535235, +425211937, +3184203172, +2077027403, +1757840753, +3904765139, +1402602627, +3348940242, +194866035, +1176314932, +1184807345, +2013834647, +2708078553, +1741110078, +2409902889, +3722507255, +1817244845, +2172650439, +4086137111, +2732593466, +3911559517, +3560472021, +2698905384, +2224848123, +2667656595, +3100031357, +293780692, +4064617208, +403130335, +1645079675, +2563952613, +1343914963, +1976069105, +1802787023, +774054175, +910553636, +418893345, +3952358974, +1370203969, +791330361, +4078945448, +537068381, +3067615516, +313709990, +2730801674, +2871206887, +1171875039, +495701927, +601984839, +1035433859, +280534258, +873262776, +3180178852, +1020129568, +1636625570, +258313174, +1558966360, +2580927606, +118636989, +4068515941, +2032183897, +2548423316, +319108692, +4062657815, +1370052647, +136695614, +1698423923, +3781508914, +673559700, +2250884038, +3070512168, +3733817528, +2086992897, +732075959, +2959213244, +3997279996, +3567269766, +3585762129, +347249942, +2441528689, +3689189168, +2476305494, +3210492836, +1009558915, +3754901299, +1515019454, +1963924631, +182332456, +720178696, +635649861, +3753518674, +3515470916, +3641610373, +3788185525, +2348421884, +2049586115, +653508392, +2887690296, +743808278, +224863788, +909961687, +307126486, +2384763494, +1406040129, +1176371372, +128128391, +496536816, +1860822996, +3229693382, +2905092037, +2267228598, +2942957921, +3960238250, +1389296967, +49560547, +2090356096, +1997504540, +603063405, +3483367731, +1553676756, +2877216557, +3886718689, +2610435607, +2404536915, +2276264572, +3402526813, +3845978482, +3414129419, +3426649715, +1612816563, +1608431968, +3045166844, +1765702171, +2137266180, +1414161105, +2201765677, +3251084917, +1765963702, +3632970778, +3119844018, +1350036907, +4165990122, +4131235046, +985583036, +3914305805, +2538270691, +2157320528, +306196584, +1902466710, +1608269814, +3700704139, +946645513, +3937670308, +35755427, +3189293145, +4217664567, +1537413726, +1280605392, +1816677002, +4036771029, +1656854440, +1398499835, +441217715, +979952659, +1271257877, +1453317881, +2781820202, +1154657516, +2281094918, +1222215689, +3101797106, +1082210451, +270226943, +1375087978, +797465007, +516188918, +1539145923, +1320019855, +4978551, +3789849181, +1889936969, +2815113438, +2916168015, +2076124577, +732523638, +2553233428, +4144186783, +1910042420, +1836783796, +943835896, +2227856747, +3484987967, +4140615684, +2183598827, +3041722633, +2498157394, +947960916, +2816282682, +2513648706, +2049235715, +3823665866, +4021277586, +2916250138, +2109878531, +3432119548, +52070157, +4030102455, +3490635850, +372438898, +657494970, +1432906923, +624032612, +2335170251, +549015303, +3689275516, +1575263227, +3978281598, +1347400517, +2506605980, +2748998402, +419215418, +1730748129, +240841351, +2520820771, +1110160692, +3832983500, +1792001248, +209699462, +1068784372, +2513832910, +2472975326, +3862626180, +3763486900, +2195265539, +640214093, +59268889, +2259612719, +1395926952, +2260117136, +148568109, +3572662460, +3527476851, +820792683, +594998116, +764158142, +2803188491, +2730059605, +3883743244, +257599662, +3744060678, +1199811128, +4066330626, +3391539845, +403890121, +3827300395, +512300758, +2178195985, +3380751517, +1863050246, +987943570, +2757138182, +3287728377, +1955702052, +4278012739, +21588380, +3994308784, +4191606290, +3473323247, +3606058838, +3745038267, +1252288952, +1507647838, +617869192, +1428328510, +1431947837, +371133934, +27826984, +693422369, +3604325296, +1202030845, +2588200577, +2799274763, +1828215684, +1415365014, +3152407125, +1723452389, +23135442, +150445909, +1341813429, +4122505495, +3097279159, +3599681468, +2257875100, +1180406661, +1700848536, +708756741, +4238522873, +2455489582, +1822238251, +1541800222, +3253278462, +3559223336, +3402862056, +3772765002, +1260094484, +1120336500, +2844466414, +3568607964, +1029723906, +1222684859, +901431419, +2594098572, +2482981902, +3417714382, +1582336953, +2564702065, +3244548075, +3556428286, +1954950407, +3055510545, +3377706707, +901805244, +4005900388, +3627593026, +717281539, +898051759, +3351280413, +1468687338, +2893743698, +1683551698, +786542946, +2136454516, +3871903477, +291689967, +1455750362, +2308692589, +2189186394, +102839566, +2454730837, +4067402683, +394688145, +2297443642, +1167095672, +3236132229, +3980651712, +1291587911, +1959277531, +1634276986, +2533013494, +1348352163, +1260919943, +3940120091, +937578653, +4029799196, +897499142, +2641854074, +2322130115, +217979351, +1726032628, +2701453091, +2138290324, +1072656096, +1657252388, +3384924480, +4217375993, +2624297726, +1294510064, +1711573819, +151724351, +3279957615, +2984281846, +1014700065, +2877058063, +573720131, +1649307821, +2603286234, +1007093384, +2999113663, +3445866147, +1374959985, +2562270616, +1049130739, +1459339110, +2379711151, +1480920874, +88613397, +4097175379, +2955150179, +245044659, +415309236, +3287130266, +2717150600, +2930177297, +1647774977, +189669541, +3174701556, +1228580493, +415434019, +4033704252, +102249328, +4204817199, +3490015028, +3964086009, +1945355979, +1758956116, +499246347, +1117228429, +1552736690, +38418607, +481217935, +702854008, +414599670, +3703831422, +2052137218, +746082730, +1012097084, +4186762192, +3141532996, +2022045413, +1229475059, +4072865372, +1048469527, +1608800790, +3782868249, +3860960238, +950382025, +3435924663, +624427061, +1392862390, +3683568489, +3168282847, +3124486916, +3875107231, +3236843779, +92552558, +1831758483, +2373233416, +2345255358, +3994849384, +2899446292, +1013488149, +2168560622, +2261482024, +2847266222, +3617301802, +3498490227, +623629465, +3254791063, +368295207, +1058033477, +2434882212, +3733042773, +1442482357, +1913215435, +469561516, +1062460748, +2283008489, +911320698, +50434975, +2018202429, +1776879206, +1077043930, +1997826194, +4194466282, +1934484524, +2062758040, +926278095, +238809559, +592949955, +57732052, +1909484223, +87235467, +1289246333, +190218592, +1076693778, +3481872090, +4020283460, +4148270874, +3817697380, +925536312, +4290718634, +2195652916, +1680876293, +2386549150, +1685154969, +4033780275, +1167903010, +827326580, +1319169596, +785262769, +3976922191, +1827759857, +1657642246, +775174001, +2379674328, +3448993953, +3027005059, +2494280294, +3263909724, +2055499077, +1437966835, +1388060172, +2445825012, +3469696631, +1998404231, +585893851, +555126719, +4127215590, +2077295444, +3337815535, +1676091305, +3141424812, +492370617, +1191283100, +309905693, +2249219203, +4261866512, +4184772860, +836081564, +3326499154, +2035959201, +3172407176, +507241902, +2091118684, +282226227, +376482378, +1336566118, +2547473318, +3141376431, +1527201929, +3586008643, +4248486855, +2793172069, +3360483446, +201253621, +2593449810, +2908786941, +3356710640, +2637843974, +2046237573, +2132642421, +3758053715, +2963943148, +924749233, +2142665169, +209265752, +545248544, +2044337699, +65369576, +3875397090, +1964393981, +68348216, +3528823521, +1925570326, +3692806667, +4268310210, +1632876196, +3986674531, +1875625548, +3675237448, +592790419, +2376297115, +923227905, +283735878, +4135297664, +1896478116, +2171265775, +723340878, +1360589043, +332959425, +1824485229, +3737677120, +2058736302, +500829737, +2126262423, +2544054663, +4283741137, +3777299709, +1889408145, +1672880265, +2883523464, +2056153174, +986268717, +3644372299, +2827658053, +2158083446, +15564445, +2535545166, +622936534, +129314201, +3004687832, +53142571, +923440636, +3032886354, +1516117474, +3920066126, +1490108959, +2397654544, +1654466328, +4119120978, +3452426113, +3961379047, +3525579801, +1281104420, +4026989000, +542640048, +3368165392, +1039413342, +2019136552, +2957356908, +3177198653, +4284160228, +1682487905, +1809783659, +3568096657, +1693772460, +676891460, +2188530525, +1585438738, +597028429, +1153085642, +1546291214, +3228636959, +816087409, +4222601802, +401094015, +2817674838, +4100028223, +1422478640, +2978272690, +1938244805, +1161187558, +61027466, +1403522304, +3666205882, +473514363, +356227588, +261707726, +3716730487, +385217135, +2163230649, +3785474342, +2093406481, +1815822903, +667041695, +1806325032, +1612782919, +3414268076, +1714141677, +1286746009, +1004448141, +1045472724, +4080569371, +926094048, +3015195455, +1258720382, +2482448823, +2393989511, +1527671251, +3912602466, +1423815659, +1010718492, +3463922812, +1729647716, +3042393847, +4261455546, +3598400699, +298910127, +1980451691, +3783279655, +309648181, +3719953652, +2343971400, +3009972327, +3059354524, +2423540965, +1367824992, +620174833, +920108238, +2715864011, +1904443624, +4217766335, +1669808146, +3324004708, +1713365462, +396757692, +1295674983, +523668663, +1951392926, +3106326720, +887140647, +3301951115, +1859573175, +2324669973, +1309366934, +2312009888, +2119618546, +1556450017, +3392716799, +1332652814, +182014613, +1912967756, +1022766733, +626038364, +1034104314, +2776586017, +909043005, +544570737, +275086469, +2644327885, +2260191539, +2297695336, +2097286966, +1701540232, +3320693960, +190925030, +1180509695, +178385005, +3011393526, +2099340471, +3763994108, +1217144911, +1052617616, +3209562727, +2651173807, +239447057, +857387186, +2868194111, +2787329429, +710630747, +2076742785, +3551739286, +1729697057, +1356324665, +2390712621, +2524086497, +2811019523, +1406294923, +4253323928, +2744097642, +3579752195, +4247790245, +4222347284, +3789569241, +3688660572, +2822092252, +2239882729, +4168900778, +1083781148, +1075800624, +523037724, +3529529633, +3334052780, +746728231, +2358590705, +3728713157, +1879558574, +1979494459, +592669285, +440178039, +2979621945, +529169341, +2090371135, +17563637, +1805813280, +220126971, +2883321614, +978656008, +762051047, +2457225121, +2097854792, +2658661638, +1125308043, +3099800977, +35095312, +1067797948, +2013433153, +1959965418, +2623276693, +1441188255, +1691663408, +3642462087, +600629275, +1713190139, +1412366224, +2472681023, +1479145861, +3324195445, +3850638836, +2162234845, +3900815097, +1045349168, +2072887955, +272774208, +2896962162, +4037618723, +4184021101, +3706555990, +3480681221, +3577887557, +3853894432, +2553318342, +997871267, +3172627259, +4292745116, +2327797389, +1161637957, +3451472150, +1422598209, +2441602833, +2066964897, +1942449379, +1200182984, +1325693707, +150563344, +1569570223, +1131330846, +2096583821, +2988726996, +3916424799, +3322150213, +595116720, +1315604657, +4026743091, +2862124912, +1487363233, +606340746, +1099523966, +374404433, +1884071575, +3328489351, +2253223404, +2184227544, +2538100554, +844415650, +535537293, +2878256899, +3105622633, +4016877409, +3949005175, +1283604958, +1964624279, +1948869416, +2256669689, +774456919, +872343482, +3455311309, +2766529227, +3640795941, +2171013626, +2089870265, +787375263, +1424309793, +1847957289, +344730753, +1138067950, +4191114938, +2103424281, +3525038937, +3689602067, +3787232318, +1207173233, +1814942202, +366649596, +407766723, +1450528105, +1020840312, +2576274433, +4081074553, +3179005706, +141974084, +1455499875, +3114300549, +2004267390, +1468323310, +572260527, +3501711479, +2103447988, +1561422014, +2456033591, +2009777577, +2780213342, +2458246283, +666216999, +2657929723, +3505603173, +1113997000, +411414739, +2000362759, +1323891937, +1651662633, +1566518528, +3668170472, +187126308, +3609142216, +3119490764, +1677491075, +1747814303, +3744219173, +1553455080, +4033376596, +168414922, +689847932, +2526747567, +3255381273, +399489109, +3830015464, +3127933250, +4023191609, +2722615975, +3220816294, +1646960830, +3011262966, +956286999, +335742972, +1000236799, +2331976191, +2948927431, +1913842809, +1309379240, +1673236813, +2882627887, +2001453179, +278095361, +994610331, +2616598818, +2788805868, +1327458628, +3354778386, +1259691130, +2953749683, +793580012, +936441666, +3713326121, +1355840525, +187486831, +949760604, +2201713231, +4233645152, +1617802100, +2771156761, +3060779451, +4035557207, +1487549576, +418737239, +3996905485, +58831600, +4261022404, +2619418698, +1197902288, +152771830, +1052466214, +3590129876, +1588303738, +3688163943, +557207091, +2863172917, +1298087960, +261412442, +696891502, +1999222860, +2289925773, +502211990, +2681973422, +3682395882, +2219948771, +3436493419, +2540908608, +2078133099, +98949299, +1146526372, +2006374691, +3023723724, +772733292, +1495525355, +3363606686, +3258711345, +2527726040, +1116171522, +2392972998, +1540937420, +913510311, +3461893028, +76120672, +114260154, +1629647802, +1407336088, +339309569, +1287331274, +1036991486, +449464721, +3056437492, +69339002, +3320268047, +3518875565, +637136043, +889949584, +2281356907, +2060153192, +372036105, +4125028312, +1214254000, +777264710, +2092742012, +3633893648, +220206831, +4124657149, +3309281630, +702993371, +2242589997, +668122868, +4016155200, +2259559111, +3874432580, +1434172496, +894526109, +2111575069, +3228853558, +3283623641, +1339589927, +3942641574, +1313734864, +1564997354, +1715623078, +4252866465, +1853419771, +2513125109, +1214650404, +3618919898, +1158415075, +474489959, +3640392258, +2221085032, +3580034523, +1351338046, +2992238146, +3209675681, +1119337171, +125603417, +2584954807, +910412895, +2964881762, +3994793562, +3851341008, +653639808, +581239235, +3014812555, +1290782212, +3064306558, +3131579914, +2362007164, +1791029204, +2628416487, +771197443, +3126779854, +1521598320, +3150685, +3489499686, +3974231778, +3827439487, +1325536439, +2391160040, +227880907, +2160301719, +3916725093, +611352994, +3816190234, +1145139137, +3441631481, +4160040127, +3335877543, +1253663447, +3964072020, +3242743957, +3080747936, +2671062157, +972824689, +906673910, +1623439960, +964007411, +2915163886, +3336991037, +1638701934, +3745305608, +3812379427, +3796059501, +1563657872, +3443883711, +1628346333, +3512393071, +3153367890, +2433416217, +3154068367, +1776231125, +980137234, +979640661, +3821144439, +1266066248, +269090125, +33468173, +1914405001, +3668346476, +2220825414, +1550232936, +2842698232, +622021626, +2346567185, +3244082887, +2075527555, +1818279504, +2887223007, +1345577382, +1187242913, +2625173385, +1556500069, +1607421417, +3401973396, +3935799759, +3971096720, +4038171040, +3973837181, +3535134941, +454761418, +3957617411, +1803968429, +2879981383, +4157403029, +2900796887, +1736280615, +3151425786, +4190249162, +541861393, +3764530007, +2493610803, +3039657572, +2469539889, +864025230, +3248486462, +3664368109, +2850231001, +3364072091, +569089842, +1280270250, +2342867346, +410679879, +1639387520, +1065019655, +2558946824, +3106511539, +664803662, +556348623, +100008068, +1826990018, +2926546543, +3348095021, +2863636025, +1602738277, +93727769, +257041616, +2355875134, +3278340502, +373873734, +459483264, +3369696605, +267915872, +7050950, +4027566807, +3261225172, +948305259, +3150377874, +1020401916, +872659362, +425724597, +4205087973, +500932251, +2662413213, +4090157473, +1679837495, +102519786, +1583158285, +3359675019, +577339934, +2817292105, +2539222634, +1492084740, +1588944754, +1048546404, +2129866805, +364041357, +3042490088, +2355956807, +4260204628, +1616199280, +4015724585, +3689342933, +317528038, +2370330302, +3935387584, +2399240632, +1538465836, +78332063, +2006697374, +2276676374, +2627526318, +3998233052, +1335152329, +3130205761, +1718019280, +3771954281, +785526812, +2155494559, +3526413386, +408957849, +4191065565, +3577491056, +692490339, +3698621409, +1944977003, +339554211, +2903158757, +73825907, +3875786068, +2596799095, +1180983091, +778291380, +1987220295, +3167438240, +3847084376, +2208858712, +1680529536, +1686311275, +920330783, +2906620438, +2834166539, +4274103793, +1841229748, +351925431, +4183228609, +1519415293, +276416018, +804366570, +3091392721, +2416723415, +3515335600, +3042812855, +1540934528, +1177764024, +414196005, +3003446217, +4048979643, +1705381317, +2453872879, +3967495451, +2248952415, +3423424811, +379971375, +2460631935, +2858735649, +913672914, +1552117052, +2243841016, +3244881292, +2355588772, +2106676445, +981720240, +3224895953, +1485354957, +813428518, +713552012, +231057539, +2063268450, +1871638116, +567068490, +3794709912, +2196615332, +3711225008, +2066038198, +4012972330, +3793443380, +1821612492, +124836926, +2479913836, +3310888413, +1850470061, +52736473, +2231228956, +4140064151, +4032420400, +2843207744, +1772359260, +2648216245, +432665726, +1207670435, +1641644844, +1322511400, +2697782233, +2614345185, +4171741943, +3912931074, +3490674694, +495637699, +2654983610, +1225191761, +330286241, +2138237595, +2707550144, +1514571849, +3428847342, +3886156678, +2042350527, +132001348, +3766548042, +2990547561, +2778928690, +3618041819, +3600276922, +2103430396, +2549722258, +1259598646, +154484430, +1429488206, +1883348320, +3747369265, +1626253677, +367048578, +3821976932, +3850148265, +1218571943, +231084299, +294086635, +3604134202, +2264557085, +2091907136, +1128867323, +765856474, +200409129, +833420419, +3442146752, +1440499778, +3380254514, +2603687545, +3363101652, +2042065153, +128538554, +3075297222, +3271950827, +3232492156, +598737200, +118667069, +4255560726, +1541848898, +572055172, +966921258, +2882098212, +393119297, +1930282433, +3053868808, +2837035301, +448792396, +866538454, +1863895787, +3229007047, +4269126372, +1131921062, +4189746634, +1424945658, +3785678737, +1881122857, +929617011, +3483344218, +3819727242, +930802970, +1501532009, +3928762672, +3448242647, +4018704339, +2208814277, +1599394234, +1644806366, +3024040675, +3803355898, +1947051164, +3778702441, +613516806, +479470006, +750638766, +3752246943, +674022688, +2974348888, +3070399844, +3410061180, +3192856410, +525482207, +3244987659, +655513932, +4269427578, +1107626098, +3462176981, +2386810385, +1900477461, +2559402825, +2022569871, +2518070030, +3097098423, +62392632, +2020595019, +818090333, +2501779736, +2856035513, +1597254193, +166563193, +3465907161, +2222686010, +1789304375, +4044258651, +3470640423, +3614078725, +4079838075, +1043783087, +2155460641, +3431555170, +1498169946, +357359885, +750369444, +382936757, +1564059720, +2645623506, +3556871433, +311017218, +2339209252, +281643470, +2968109067, +3203092270, +3011633907, +2832121530, +4131887833, +3359247683, +206938627, +804067163, +525612534, +2374276190, +3803510965, +2638369376, +209284489, +1781171373, +3211130217, +188792167, +468224946, +251294318, +2251265798, +1505076809, +3452783668, +2094020836, +4144219284, +1781427583, +922757649, +3030577646, +1129416461, +3486757158, +40017713, +4163566765, +2301353686, +3489186427, +2211057869, +1304941517, +1095306195, +363783691, +1783471970, +4253100042, +4016283924, +19184552, +2412907439, +3045141511, +2331762125, +1666990412, +2792367896, +2489217449, +395472153, +3158857321, +52867816, +4013986987, +3302880560, +1807914306, +575278383, +2880418197, +2967635718, +2109101876, +69558262, +250249823, +1743647656, +3870167971, +1058646850, +2603808313, +1805809186, +1048389518, +1156778606, +3098860366, +3217973153, +85274015, +1433085134, +1815766306, +168514016, +3286395163, +3031532535, +1595151738, +2361155649, +1972300711, +1215602895, +4196789885, +2288173234, +1271059839, +1729181936, +1030759003, +1306511490, +851351339, +2493384474, +3834551328, +135383113, +1206987371, +4002350345, +1674586212, +968582860, +3256748619, +3451707229, +1561243888, +1274436645, +332986295, +2961170682, +93622602, +1507046096, +3019551451, +3974375195, +2058693038, +1099722135, +2387450422, +3356254905, +3689667958, +3941956665, +440806846, +841483930, +2442875374, +1764926784, +1776788282, +3286219268, +3287980534, +2183948269, +3848947906, +3550483087, +2915051878, +4231066587, +4044154333, +1699301151, +3115111466, +1810747989, +4106728488, +4093553431, +3726277810, +203637395, +2063256838, +3854564601, +4193874718, +155234961, +1881696225, +4168020314, +2771568799, +3332887654, +2269145124, +3490816260, +1647083786, +3025379184, +1420309799, +4001913823, +1234737729, +2442157418, +2815573157, +2189836365, +821601888, +2564624396, +2924921640, +2444439585, +2779221976, +4076443707, +2933926588, +2371108822, +3319725460, +2852222467, +2162552234, +1133216917, +1762723493, +1668842632, +762530537, +1985075710, +2546042909, +1728706466, +3096059046, +922896705, +1514789016, +1676016009, +2731756601, +3760381800, +2552293955, +4272303684, +3862757312, +2544396306, +1371111388, +2289814235, +2551425225, +1992865385, +3850029496, +2671869639, +1834719354, +3883573567, +73700055, +2308321547, +802733803, +4220910422, +2830360698, +944244630, +640764838, +1670645326, +2702215071, +1410225071, +1790685250, +3500972294, +1958821871, +1318743367, +1265537910, +3401337310, +242526498, +4035450412, +3811432283, +1562300297, +1223997383, +655743585, +62564477, +1105577720, +95219368, +498277737, +537876443, +3286184934, +3939826814, +461733154, +497187737, +79285565, +2849115301, +383172291, +3532113797, +3422510345, +3050086593, +2118793167, +3884086653, +2664680487, +4061148955, +629686310, +919293573, +1017898491, +1880021629, +1420600976, +3049788713, +1739756481, +2846030221, +4089207660, +957718557, +2489155124, +2361217238, +1618458451, +71763243, +1095171065, +3862687978, +4216853909, +2397817458, +3829229955, +3331722764, +763321295, +874935994, +3374217393, +1454304080, +1714857285, +2458581515, +2923668705, +1945332996, +478623729, +2160995609, +1096902572, +337460339, +3596748957, +1885176932, +1377529844, +3856365948, +45646856, +1892976418, +2583307098, +1063524656, +1258783073, +613080550, +1503576230, +1488234818, +1105498300, +3537181703, +3057400431, +1968432797, +973228902, +3842393819, +4227069197, +2705867245, +2436409534, +1273594104, +106969948, +2202208105, +3260667779, +2233216708, +721400718, +3430831540, +2366077967, +3594924931, +2978170685, +1734840850, +764824032, +965679432, +4272775956, +487301963, +2182776304, +1995050449, +2169125622, +1091840309, +1866156853, +326205817, +556191742, +2818056970, +1464698819, +186381141, +168186377, +4113803727, +341004733, +3074086912, +2514495684, +2928964045, +1295428968, +186681969, +615398967, +1484016861, +844167118, +792743778, +2728299784, +2122261482, +3563590722, +2559350205, +1787451796, +1792768203, +136224049, +2861264174, +2259432420, +3949588364, +2471502081, +1042011362, +1249704663, +2278362778, +3787109205, +3201311912, +2695286850, +3102049185, +1158948507, +290963711, +3555969700, +960431654, +1809292230, +1059132908, +1706537920, +2631241926, +492375152, +471237026, +241855662, +1058192440, +1447702081, +3344997962, +1492440726, +3365032201, +3231032725, +357920920, +3068940600, +1916685014, +1903694476, +1014523620, +1297150215, +2190978461, +3788335335, +3608083049, +2574780017, +3269492247, +1899854983, +432335894, +2399169334, +2369324473, +4136701876, +1751099535, +1623170712, +2401294730, +1892592008, +1498613048, +3566844776, +2320665356, +4378750, +1306302166, +3842708184, +1953307179, +391199737, +2939878237, +4269858439, +1749277299, +629424145, +445107622, +664794548, +3933049614, +4158403274, +4204380623, +1310893339, +161974089, +1520870339, +20592842, +433666340, +4232055490, +1043263539, +921974549, +983641400, +3121212039, +1483809317, +2044793045, +1929561519, +2462631808, +3661740196, +4256082238, +298330599, +1295997719, +2576131758, +1553723678, +3186970706, +1961012529, +2795162325, +1631043893, +2380693120, +1835326847, +3103598452, +1037664598, +2405076661, +3118149105, +333680825, +2908483425, +3943688391, +3857788029, +1403517573, +2892650226, +1440653112, +1641591707, +4126476341, +963881657, +3176998148, +2160634532, +4259379393, +756399398, +3239049332, +1772005056, +2667366336, +1886912467, +3534133800, +3818751115, +867943317, +2391314203, +2264386895, +2602462783, +3425086050, +527330629, +1039520609, +2503028612, +3396482983, +3674465993, +1466446378, +476278699, +3718038254, +1650456206, +2683325129, +2931177397, +3515401522, +4041915308, +2159084432, +207464391, +38064980, +3352528652, +2757171192, +616899485, +2752548459, +3712681124, +6137784, +4166315371, +1824479355, +1532020351, +3949210920, +2536306056, +3655348863, +3609694386, +1640898284, +3053519018, +4049080181, +3663220829, +3603105907, +3782154774, +2346263443, +4035126286, +2605534115, +3456385865, +241885802, +3416484550, +1107553722, +456313306, +544100096, +1766935657, +3147552770, +137502599, +2511204859, +1246355338, +1034773505, +1393993155, +1277891873, +2736421189, +4108952517, +767658662, +233446976, +2770062851, +671349418, +2646533445, +3206872694, +69958857, +324562398, +2272334724, +2800279713, +315462795, +2521110804, +1255795655, +44481530, +3663421032, +4204145746, +4208524366, +1838957637, +3589019118, +2758089, +2467114935, +3342871560, +60851253, +279430621, +1823435807, +3338751056, +1440621853, +598536559, +898587028, +3260286910, +675050464, +1406156860, +1308193722, +2821494657, +2077069080, +292685282, +1946947183, +1195668108, +4200852955, +45358742, +1545506182, +2130160891, +1030653807, +1256184893, +2132522121, +3933557709, +3447318303, +4000465109, +2269919476, +3703151789, +1878930248, +3200932974, +1879235732, +3253228219, +4123481718, +21970248, +1395881249, +440836107, +543203855, +2046289291, +885006767, +38495291, +2859789378, +2777925678, +3261902892, +991826136, +1695888522, +3566803419, +2835915814, +1331727429, +3901477357, +2156205769, +2620090673, +2801777410, +3406167780, +1718638966, +3078704324, +382502470, +3109033993, +1059989581, +4283164196, +1302245424, +3176204687, +3809507604, +967015283, +97756412, +3895252749, +3661747757, +601828657, +126815647, +1013477976, +3372537570, +557076077, +3010599862, +2728157987, +3435810869, +3527461608, +1870251663, +3878816528, +993922744, +2709717005, +3297798605, +1254192118, +4143048015, +3502986740, +398041840, +3721330255, +579855688, +3422318380, +1571176699, +544406860, +3991756042, +3097351633, +2526841388, +469575140, +3870978525, +3999594364, +4034044644, +1626774072, +401832316, +3053490862, +2977867325, +2353164622, +3484547070, +3276178467, +3150331471, +1520159090, +1280795328, +3776255370, +2769111385, +1523564749, +1427137340, +2431084996, +400428271, +617902669, +3384349904, +2589779480, +4090014163, +789005631, +2731178925, +33326848, +4288496974, +2460339163, +528656149, +3419811759, +2470361332, +4169958884, +3423239277, +142429272, +212342287, +322293219, +967146624, +655268684, +38268618, +947569657, +4098017566, +63864670, +340677663, +1558584062, +3087846406, +938610955, +2355591601, +423623591, +469268231, +3681688355, +2400774584, +907274484, +1947562588, +806283863, +1149726049, +1767834369, +3574616454, +3525508051, +2579375356, +292105037, +1274748905, +4220766120, +1610502850, +3855923868, +2703933133, +4237494638, +1291780918, +334492441, +2819715946, +4111913994, +1438089879, +927680920, +490106726, +188990901, +1100572371, +3746901811, +3821102950, +288073152, +3774115530, +2615302270, +4025565114, +3457386800, +3467395565, +2876031200, +3308585553, +3795176891, +2334454659, +391058856, +3454931662, +190269889, +3683241730, +4155338177, +770648325, +1344294072, +1580005611, +3233841370, +1400423964, +1343898956, +577731703, +4232981310, +4229568280, +4165840238, +1741592517, +1395021304, +3052276920, +77220199, +3203780291, +2073746012, +1180024714, +1289868086, +1322666966, +809856476, +1441603635, +4019903886, +1372209196, +3392390327, +1898180714, +3150822582, +1762587154, +2376965111, +3935324531, +1119050741, +1521102732, +2965423348, +2435044020, +1644390428, +3872204901, +3586129441, +2710568479, +2447049063, +485849956, +356314934, +3913277689, +211335196, +2624170632, +3500130044, +1683694402, +421749574, +580668744, +4039898690, +1401093572, +665967306, +549811202, +2052397151, +3692538225, +269690087, +3677624154, +3111185739, +2219382359, +1086771275, +1048268910, +2358556574, +597511087, +3404240007, +582247574, +3490259647, +3735351605, +2725898624, +637838120, +3608122037, +1264012125, +142810750, +2773121275, +3272944950, +2136801371, +2349483912, +1747576262, +2240221947, +1762002205, +4138459384, +3527687311, +3931169744, +603809561, +2828014886, +921695159, +726975587, +1804539362, +2805927337, +3682006553, +1336417559, +3328071798, +1698299682, +1590467123, +2183413201, +1213795016, +1695406664, +3706551472, +126491636, +4097541491, +90335119, +2537885923, +3825475498, +2671230920, +3723397166, +79854132, +2670670379, +3586684942, +701628363, +16110325, +2262265617, +3538302109, +101694836, +3156802525, +322646705, +2037222943, +2739126437, +122856998, +3383193272, +3520240618, +1964061292, +2627455269, +3999693334, +2885048847, +2348857895, +1464985434, +3585454201, +350571138, +2678445420, +994722350, +737335646, +3522141120, +350551785, +466823240, +4254514396, +792221396, +2210117389, +2819489385, +831031000, +1119751723, +1241418940, +4094431124, +4269562925, +4096228663, +3763553873, +1134802161, +3137756122, +850799897, +2827917942, +2805676609, +1761828852, +132600457, +4078389698, +3907654112, +3766100528, +2897172068, +1165519687, +1172798564, +457322614, +3091073852, +1980763778, +2272736503, +3346836061, +1976431351, +2348083324, +1506650284, +1395320880, +3953173871, +371529210, +4143850024, +3798626062, +476839849, +2820755785, +578122734, +1772946995, +1834175783, +1730645683, +232751237, +2732530243, +324562824, +4269523993, +2250836477, +1514717415, +2085647919, +3824540879, +733809157, +1561589862, +913827359, +563918464, +1379958731, +1430389033, +2099765098, +333708499, +1927047281, +262783377, +437347451, +1422498203, +168064731, +261928776, +357074177, +2356943962, +3940525462, +465463619, +3925935647, +3254171326, +1503425485, +2068783660, +894307008, +309901322, +1966312390, +863020057, +1362249228, +1457734415, +1540700175, +3816755615, +3934370855, +2266265609, +4282872226, +1450238145, +1979724485, +4106615754, +4198664816, +880480281, +6887455, +2302274373, +941531765, +1960501646, +654739540, +2055704604, +862880479, +4189561476, +1625792756, +4094469169, +2882078541, +2879563428, +3633688390, +3677973263, +3213505814, +2442925934, +763031056, +3261149003, +1537916637, +1987989575, +2993875107, +3833728780, +3018457039, +4089806656, +700424195, +398778225, +1784945327, +4092161430, +1743897897, +3353431291, +3813969504, +2962392307, +2989939021, +2170975022, +2479249080, +1138198542, +3552494530, +1521845202, +1355591084, +116194840, +900870016, +1495976847, +1216189378, +3374685871, +2203120754, +339619967, +3880596906, +1770683656, +3922660566, +3047215979, +1385406608, +660016384, +2600738, +1841412159, +638475975, +2001121564, +969114243, +2265895098, +4094702747, +1241167325, +3876599728, +454914685, +3378931956, +3467517205, +1345805004, +2369774007, +841442686, +2148511184, +2761766898, +2290650445, +1068899503, +68469879, +1935226957, +3577953031, +2927514416, +3240925326, +2133727556, +2356023725, +3528738287, +3303793324, +1993056713, +3160571173, +1009760466, +2888826558, +3952244284, +3827469953, +2772334591, +3626501733, +3488319080, +4283745260, +1920135016, +3559780643, +2036552791, +770168929, +595060285, +2611834763, +1350820935, +3991404710, +3170876529, +3375579109, +2022323577, +619350187, +1215800104, +2449002377, +15991695, +1099068532, +3589663946, +1376882591, +1009240088, +2683602121, +4002761648, +2894927075, +2793759684, +3712402613, +1225888752, +3727084693, +3265042714, +1801532527, +2205407608, +3646115346, +1738742621, +3350048102, +1403509637, +509151654, +3858635489, +3942566737, +2395569222, +328798388, +4155248974, +1646399699, +3100679576, +579178177, +2335593106, +1985027223, +1660963589, +2594769752, +1486815112, +4243098363, +507710332, +1176130348, +3247620091, +1743059430, +1497848173, +427553748, +1599880304, +1692485106, +2127192333, +4189000109, +865913403, +3312824256, +3105381720, +785818770, +2227981859, +3183677527, +4054015895, +68516834, +808296292, +1749474336, +523603, +992998834, +649468587, +3456213411, +353556377, +784753116, +1524163782, +2360722093, +2233143064, +3519830278, +2745003982, +1633977669, +651857528, +2771739916, +2650291281, +4093793222, +1721874640, +3504865960, +2382887078, +1535677539, +3954734696, +48479347, +2090489201, +2087096339, +3981080952, +1983385988, +1048707941, +3067757196, +702896722, +3649259616, +798061722, +1559760085, +1476484014, +3815566117, +3825114907, +2400335363, +608138615, +1327235419, +3948836759, +82261986, +286953878, +1028614192, +3471234693, +936074423, +3605838460, +3002521706, +3830930997, +2740085489, +2020303075, +1795733855, +3206806714, +1010385869, +2115665871, +2548053712, +2953891308, +188229148, +1781821963, +700908048, +2415229113, +3940334568, +2041208836, +1976095558, +148286819, +2984360131, +1355297939, +1339892080, +603421117, +3878747769, +2105651737, +1923161801, +1038894866, +3578963811, +501464764, +239267674, +2861102249, +919193432, +3933093651, +1659077544, +4028513660, +2580305574, +2814045368, +2427432900, +1179641909, +749138293, +2064185259, +2254330996, +1224981897, +2955658357, +2406381464, +1521655421, +546418187, +2075802034, +460473447, +2824449918, +2649494605, +3986377885, +2251412834, +3613047857, +2548976503, +2237069501, +3311549033, +353325222, +1501748677, +2375973857, +4205425727, +290106632, +4186775655, +3547563981, +4008031604, +1600078598, +1173440356, +1696106956, +2123136023, +789104529, +1911017627, +1035586276, +1681870859, +859217250, +2371721574, +4013850329, +67393328, +1696348109, +4064515291, +226485983, +3283385962, +3009513596, +2970631774, +1187468889, +4136956967, +1288333271, +2627172495, +2608917041, +4190852110, +412293286, +2720106828, +2418672220, +3635692249, +2285950071, +2664572333, +2942032361, +4222799860, +2541220351, +2412768455, +1288699283, +3363615556, +1965318330, +2481351782, +670884485, +1257847497, +3275293645, +1147388766, +4072425786, +1569011609, +2197910753, +1292098555, +1762583238, +3118628437, +2704266960, +4138205901, +2988933836, +625878173, +147304119, +3415770887, +4234802213, +3714573523, +4253743078, +378940439, +4063042376, +306064080, +3307093280, +3509472868, +1914629438, +2693046890, +3317848404, +3831687618, +3659648495, +209519355, +3398416893, +2776085526, +2768124279, +725502847, +2110330925, +23832979, +2239283767, +3971750233, +475197662, +3749927677, +497109079, +422381139, +2135538771, +14930994, +1811268405, +4223602668, +2931402494, +2427102034, +1525216641, +2500421171, +2317126441, +909907567, +3521042374, +1301812210, +2372002546, +990856447, +2221727528, +1964809741, +2442792485, +1901776829, +3557114500, +141728157, +2514845006, +4028354420, +2155113128, +2517104393, +4125171933, +1359753318, +934296717, +1540552143, +4090015917, +4244384263, +1341638823, +3504937068, +2517134060, +4071294698, +1530599173, +788469428, +3849631463, +122576144, +687751543, +2791420507, +481168175, +2212222937, +2223640589, +2253095029, +268351333, +1881869776, +4078189112, +4119059585, +688558565, +4009955783, +3710945447, +4132357423, +775788659, +389450625, +3966705299, +2104396124, +1890230011, +817270516, +168539389, +1742456264, +2305700333, +3920874819, +3939826665, +2660108543, +3067602358, +851564404, +216340873, +990112081, +1813115154, +2234986182, +2643530428, +3824840852, +3778328623, +3532395946, +4111040642, +496509205, +3476513120, +2794615883, +1219849499, +2099608254, +1393744416, +857515488, +919454236, +1866405462, +4117378641, +3096294890, +1080749753, +485766283, +2393433071, +1040845638, +1711899808, +2085842258, +2086799566, +2068434120, +1608458324, +1887395074, +4289569908, +979454867, +743899771, +2060899429, +1769225505, +1151956630, +3925828073, +4228314302, +1326615135, +3297859202, +1496513701, +1140040056, +668944109, +1337657704, +253554440, +4103591332, +3635741380, +1623292718, +3059887777, +3001938230, +1539368495, +1669666410, +4020692066, +3985520274, +294088384, +3799560836, +1234662225, +2386350167, +3851783969, +3258619415, +2498544805, +3150553427, +1150520452, +2294334176, +1264967300, +3975255632, +3128398412, +3618057586, +4166830966, +3376514581, +2364298893, +3301139088, +2544816348, +1853739496, +3403620050, +3753960645, +177985873, +1378251428, +2853197872, +3033953298, +486963717, +2379544641, +288702195, +3747738462, +1669897811, +362091764, +256192077, +1398940336, +3931009223, +3679763695, +1149060716, +3454110157, +1845375436, +799277786, +4072206171, +3630019009, +3720781970, +473364658, +2977292828, +2946005756, +2799542174, +4195695062, +3348587044, +4045008036, +515785386, +3463004793, +3666374752, +4198437380, +3374027123, +4112351086, +3703910865, +1210107236, +2337475339, +3733480458, +1892366363, +202118561, +1978225174, +337476005, +2497705653, +2736201502, +3040373294, +226377152, +2604026831, +1302459852, +3556501171, +2375229080, +2028468416, +87271016, +1485396612, +1702214303, +2557392099, +3139099560, +1907626662, +320807749, +3588302858, +286029663, +2064844105, +3543787225, +2221287514, +1257257845, +941790323, +2817007882, +917682404, +2755335346, +2540677399, +3298454481, +691433863, +3278406590, +93394908, +3019661225, +1594214657, +891189263, +10455864, +3499258246, +2037345496, +3147934769, +2972468278, +532856560, +208182942, +2125700467, +1422262553, +2114909031, +2022596048, +3061998421, +310675675, +2120431282, +4183415041, +3691931707, +2437074650, +1863705617, +3670908999, +1472716176, +1051288194, +579183443, +2724274860, +1014915798, +1088751447, +3769050134, +1656149726, +797539835, +3765807231, +4089605235, +4167983574, +772968229, +3344027121, +1818645803, +1205092665, +3204621578, +579901702, +3552372326, +3943457085, +3696454310, +2865793534, +2856904259, +863479005, +1737471531, +4247329997, +4257740265, +2974763440, +4024763235, +879421549, +462671424, +1725574170, +2821408451, +3417955769, +3320547854, +2922929334, +4022147046, +137527709, +947630003, +2226877218, +2948993119, +1379431362, +3058252155, +4147164682, +1043608914, +1987759515, +4016355957, +1195793966, +2868660624, +3629658423, +1787530107, +2844485948, +1424359308, +1560021017, +680947371, +957490158, +78889141, +3643385856, +1344240052, +3656087086, +1716600410, +2586044984, +2541591916, +2036803119, +3598061652, +3346059133, +592281217, +1215673560, +3197655960, +2032007395, +2718659204, +856717898, +498310328, +542903530, +2672819301, +292313101, +970625763, +2614430796, +4085566389, +2314591110, +428896685, +183971868, +246152079, +3936922467, +810319112, +2723677886, +3199262470, +2075139260, +2850389206, +1563560582, +2347059174, +793301819, +1785651562, +3533211067, +893047795, +3585509490, +3498971007, +1896036738, +3581260831, +1269548831, +2959704897, +3248487664, +2752849715, +4210507722, +3236838199, +4053196186, +2643890394, +2440258996, +3415327512, +2576708277, +3941690916, +1815073493, +1182144267, +49334003, +3919518792, +2873396943, +2670129804, +3458207069, +1411581155, +3720667157, +1389485239, +2221016024, +234690612, +1824526791, +2982527636, +2607845825, +3644241733, +166391699, +1505584205, +3854694397, +1894898253, +1496159472, +1178841762, +1803577076, +2706076447, +1995001895, +861064247, +299209263, +4187037447, +1140503829, +736517513, +236169167, +4109252764, +1919174568, +269646170, +1139882973, +2365840766, +1523187334, +3853965837, +3145494511, +1422141732, +3507761121, +3269765032, +1916574627, +2638611671, +1330548254, +1577204530, +4239948006, +3907372123, +1450002787, +1458850551, +1653998265, +3333094512, +3828703689, +179151081, +3049351402, +2672672666, +356653159, +4036240663, +804874368, +1788994993, +1741543415, +3130622347, +1336678379, +2868712260, +1544865920, +3520834815, +4068173886, +121942095, +623917230, +2926357529, +1085261641, +1301442520, +1190587018, +235668617, +116363494, +306868233, +3494789722, +1376374855, +4039534524, +116324307, +4286332747, +1723736376, +2383748525, +3095942811, +33574007, +1303234120, +696417776, +1586176790, +279540117, +3397946102, +2207123002, +1128378917, +3568252478, +3495716646, +2401830778, +2876467887, +3931066694, +17465555, +3961933004, +4093106206, +3113295267, +180775983, +3451258577, +3932723415, +2304451802, +2936700650, +3434731529, +4282233497, +2499836766, +1499307304, +864147734, +1049639743, +612078669, +553228713, +2075091434, +1460267391, +214957092, +985609906, +753823646, +2945594799, +739265599, +965034540, +1504804134, +2912033808, +4038343828, +478006681, +2068096499, +2197927036, +3745733030, +1883060680, +3915080263, +4058371671, +1479455256, +1311071024, +4214706040, +2810537617, +4248229830, +3240751336, +945428458, +856698905, +3860351987, +1449051568, +2159476598, +3316202928, +3255628987, +2105134918, +1326065816, +1593919606, +1588558153, +2862274085, +1530421475, +1042822520, +1732315184, +3686243302, +3800380400, +2372672878, +1185801016, +778307598, +1639740461, +2588163835, +2132437724, +1338755915, +2028207440, +60409489, +2260265909, +3172782085, +95135640, +645923712, +933144392, +3850869536, +3778564148, +3369040296, +2922363135, +2547216961, +3663741386, +1369690461, +2281122221, +3262888576, +1974426892, +720665910, +2606400077, +2420718990, +1535866382, +2316540274, +1415291431, +2023962929, +2410923387, +3592859829, +3900069906, +644874402, +227265943, +2837935666, +3212896318, +2328933829, +1241330445, +2272375622, +1156258998, +2545724098, +2757712033, +3762486064, +3907666073, +3847962738, +77840713, +2531927805, +1240096964, +1534618655, +3833368081, +3266633601, +4180341783, +4021229622, +772548340, +35604170, +3444180355, +3972056326, +243107484, +1105736692, +3686817534, +970876289, +3731853715, +2705622759, +527464571, +1028057093, +1215723409, +2503091799, +2540499307, +131957240, +3936113331, +419166264, +656844229, +2189618422, +3050651447, +2302619937, +1093330048, +2057308480, +3633798012, +3935814089, +3297170632, +369187018, +2308194331, +3286199577, +3976587376, +435886376, +2219745613, +2822564130, +2243048765, +4234745845, +2134535057, +721595121, +294626785, +1296314963, +2033241156, +262605622, +15710337, +464212881, +2974887896, +2846797939, +414336395, +1535149623, +2849397303, +1595830756, +3152482122, +462072240, +1712070223, +1828107887, +912295380, +3474243480, +2556986270, +2527447138, +617814657, +363367346, +1817523240, +916953857, +256179373, +3257384222, +2759283571, +2036205158, +2951367548, +1392068367, +1815804892, +1691878931, +693417899, +2010727729, +1364362412, +756493093, +1370519726, +34966314, +583993257, +305480412, +3458130429, +2070649930, +3121808986, +3607351204, +2889439227, +4148728816, +2701104161, +387080372, +1654471196, +3500854098, +3196997394, +421870316, +3573865552, +1135621128, +1380941141, +3477791549, +1726238377, +4207139856, +2078108468, +4139554373, +2768128449, +3697334549, +3837426331, +1869850943, +2465255230, +2523867055, +2733736233, +652389964, +2760639264, +1418565604, +506657027, +1502374843, +3978969439, +713437231, +1999303945, +933148520, +4283435910, +2355857059, +3955776006, +1812810099, +2992750953, +2503074356, +19318983, +696932806, +768936817, +1926677540, +2284276928, +2957645399, +720553693, +3527999875, +4006582479, +2238557568, +4228769599, +2171874125, +2685690672, +455597084, +4149286789, +1837974627, +3535607377, +1474431602, +1078262225, +3526357281, +2677926435, +329163848, +3646447278, +2681650053, +2565758396, +3175161684, +1170737638, +57079519, +2303451065, +1792413354, +3523097643, +2161124880, +109197963, +517237525, +973744139, +2527293196, +4118772840, +1960055083, +370797925, +4197377928, +2568744786, +805999996, +1091109407, +1726152661, +3262376715, +2760367156, +1500832073, +2814329536, +3681284478, +2392452866, +1761720401, +2988023722, +33851254, +3029613755, +3695351876, +1610008913, +2450136481, +3277899766, +1852432997, +373721893, +2885436174, +10121947, +656647238, +724915827, +3565072590, +1266208808, +1155396347, +3094264827, +2471147500, +3687083943, +1866603369, +743663881, +692404468, +3492584075, +3491756657, +632114987, +715649684, +116354824, +1357074528, +3297071933, +3095559860, +1866529722, +2925710673, +1193162050, +1440783862, +589107443, +800392713, +461811046, +1679985260, +439484481, +183436752, +1265797445, +1671736041, +2467207568, +1749899005, +2208243273, +2611751235, +4276642718, +3891631780, +4246458125, +707674193, +3264779617, +3062859640, +476948876, +825264953, +2892223999, +4007439873, +3552108513, +1497675594, +2806848811, +1213759533, +1193502623, +2837523430, +3552290112, +4052046383, +1479419528, +2392832105, +3334703295, +556575955, +3101237801, +86728268, +1916171085, +1525982212, +164801359, +704667675, +1121650414, +3916103828, +2805646650, +1230215147, +4270670376, +2681208630, +1041963375, +600828176, +2337825911, +3293012800, +1774755946, +933344248, +998107035, +3050023094, +2841716181, +4292238777, +1158770793, +2450861917, +538295990, +669159361, +3224454071, +3219092091, +143509988, +3402179567, +9509302, +2667132513, +599161500, +3422242263, +2756403217, +4046085955, +325932726, +3392909663, +144600817, +3062388491, +1232037762, +3972673282, +1474839254, +2701905595, +4191173567, +1721461621, +1057714367, +3548147499, +3888390066, +1189387153, +3539743048, +1655914900, +1611380017, +114972405, +1012470441, +3130561124, +2525579908, +623102584, +1906124786, +3537885861, +2074480285, +4203910190, +2982393544, +2647369188, +4279638786, +3005334496, +2317973738, +1390866573, +1488402829, +1687109784, +25438061, +1092613216, +2000331816, +3332155679, +2735830233, +1428922402, +3935459342, +734010828, +3973040964, +1155743801, +163618478, +1653383496, +973933036, +1502864340, +1698871551, +4270253667, +2783944069, +1479892964, +609196709, +1015130566, +1160824246, +2457619247, +1512157286, +3970453900, +3092805571, +4173188997, +2323734084, +1256124373, +3341433923, +1380620376, +2243939364, +3166034301, +3969689459, +2296653470, +902106915, +3332252842, +2963994040, +1708327914, +3132796770, +1008825722, +2005493721, +1340707644, +1410535453, +4270561611, +1206004150, +539804928, +3002780113, +3881333635, +3732836854, +1622783922, +3128258372, +2739002709, +1773031513, +4292641424, +1512767020, +3490904855, +1848669175, +2804644749, +2771882905, +4294174131, +50102060, +1506786716, +402551139, +2265475084, +1774112117, +875054054, +701971945, +724126663, +3542028088, +464669634, +2186183332, +2519426944, +1302762973, +2103131734, +1194529954, +3962233414, +3662530260, +2353833565, +2487087887, +1485114051, +3000839106, +3707676300, +2450555254, +1261973652, +3570054674, +3793646096, +663561920, +3993256050, +3928335319, +1195786010, +2967641319, +1507410560, +3507104940, +1294187456, +3431283904, +800236304, +2932289333, +95603550, +3085592884, +3029617095, +2486325366, +2540120528, +3943691315, +1798067825, +520451426, +3634398467, +1599854095, +3712287129, +437421307, +2734588937, +1709542591, +1138060864, +760947419, +926439942, +3895386966, +3352590186, +2951509784, +2390011827, +1208974425, +3883129138, +3657826044, +814782768, +1997763404, +2471093150, +1366283298, +4208778592, +1919050175, +2625841218, +3249329294, +2996574918, +1236642441, +1997118889, +1458013739, +3278351494, +3888251380, +2615272582, +3327527517, +4283593209, +240345559, +2692327951, +3570689780, +2567872868, +1963795431, +1686178244, +913177855, +3288265784, +3296434835, +2216650172, +108825602, +3051119097, +2260903603, +666599409, +956442427, +403065255, +2160355000, +156805428, +3709669053, +988791557, +3903300450, +439697504, +1494553326, +2840139321, +3762187234, +262508157, +415161059, +1447905201, +1770888668, +1251323667, +1832990814, +3597987696, +3361362341, +3836691141, +406380903, +430350128, +1812862498, +3541815004, +2261279076, +3425140609, +1175768615, +1767870654, +4206509586, +2265474131, +741532083, +3144280860, +2237421969, +463602157, +2052476309, +2927417176, +2887373867, +1218393934, +218758890, +1763979609, +3490422804, +3415342314, +1532006953, +2477019468, +131418847, +5058578, +1342008542, +1251858802, +1620778613, +769215157, +4080084157, +801065834, +970300834, +1205858354, +1679634872, +4042873263, +3785868055, +3289841314, +2581982569, +355950224, +1591235762, +3150392545, +674859788, +867248628, +1166250066, +1997034996, +1070561977, +2898761694, +3420258147, +769562366, +2188386799, +389177417, +188054765, +1568059291, +2258258033, +4055915974, +761389923, +365997336, +56397182, +2333297870, +1062539270, +2716174832, +578568866, +525208371, +3751789926, +1433662679, +4037701723, +4014346831, +340611439, +3204551671, +1954766933, +3537853998, +2242623920, +3431588167, +20233670, +4287781363, +3847108863, +2637609190, +326955549, +884446883, +386431897, +2894724110, +47463112, +222310176, +3386003022, +1100893033, +1676222274, +1286236269, +1626267925, +4278562001, +2659565892, +1623905557, +2777304561, +3451998880, +1501499600, +314537254, +3704878655, +7929711, +270375006, +692054616, +481772536, +3139370881, +2063968608, +200230303, +2651004070, +2109107559, +1354390475, +1263338098, +2795570407, +2952266711, +228294863, +3148736732, +2648569588, +4055087679, +2902502704, +4095927008, +1331564512, +4272187824, +2382666948, +1644216324, +1288850719, +178289707, +1559001413, +3695353362, +1369479776, +3105012619, +990795193, +2404010155, +1191313999, +2916483277, +2213031149, +3057852686, +1740876079, +2299199952, +1055596129, +58292168, +3857103893, +781615991, +3153118184, +4097594864, +2251045746, +2768224946, +1532298845, +188013756, +2648232924, +2381701433, +1838673362, +445083144, +681088809, +1545242069, +616212383, +1286453309, +3011088639, +2959842103, +671497509, +3286824324, +2312464420, +3197632657, +4242708417, +3666066048, +939999077, +4219099621, +644903868, +1884048987, +2100571223, +2669286589, +1544596317, +1396460733, +2011914374, +1675881161, +323710706, +192896002, +1968030188, +3141376702, +1126592705, +3299681481, +2219466535, +3444363372, +26090889, +4073543131, +4082940424, +3542076584, +4146289582, +3809450176, +2174890909, +1127983902, +3465564937, +2064191765, +3989294909, +2521776188, +4132241925, +3397830641, +902973961, +1491575322, +2479948106, +3561579770, +3659392134, +2578475942, +111420047, +2733812404, +1235601277, +1455017295, +901080641, +1999152714, +1430354784, +1871301283, +1951649724, +732223107, +2501540643, +2736479902, +1159080839, +1660785374, +4153214571, +2385512292, +4177530065, +2350821276, +1090202292, +685768843, +2936300888, +4030702306, +1774075376, +1352955614, +2237873409, +1844185358, +2143859564, +2928940935, +1798814380, +2804785178, +4135860581, +2323306826, +2280187896, +753797558, +2558753376, +258089537, +1208780992, +4166097494, +1878123692, +198390043, +157874420, +190338917, +456657972, +3805997241, +4271681530, +570418090, +104522991, +723824178, +1397993038, +2816971541, +2542132782, +2925494217, +686937175, +3359454153, +1834431262, +2168808375, +3360507950, +470321311, +4239041801, +1612139425, +1282825954, +382673756, +737231233, +2477896687, +4120976702, +1767666866, +4183991732, +4028145438, +3925938992, +2851180627, +3682844617, +1057583112, +149192406, +3463667715, +581858506, +1299392414, +1221256711, +2958019812, +2146956885, +3191542836, +3532531856, +2024397318, +4156642463, +2983336639, +1342562901, +3161431735, +2513260586, +2518284823, +4220988652, +90919618, +4271989282, +3600928863, +1831973273, +4196524998, +2594047823, +475829309, +2228583934, +4221215107, +967614808, +3162103353, +3483735083, +3968245876, +3158885519, +1221174264, +2016873689, +1798561558, +2284901504, +598520927, +2757302931, +1182344518, +1402021899, +2831731736, +1416934335, +261468301, +2176146274, +1371833183, +4042086727, +877022265, +1653311768, +1516921696, +1175824627, +3621041720, +2393563973, +2891223689, +4118226028, +3710636671, +792347640, +3337104956, +2417690608, +591794431, +729373566, +212502139, +1295025534, +3686167776, +4113339924, +220125420, +2312937156, +346906404, +2745118524, +2220691870, +827398973, +5532175, +684322564, +1432299305, +307823485, +1091678607, +3332035026, +4129460687, +1916564613, +3821286025, +2739513763, +1400617962, +3338307598, +85499240, +11890327, +2117160314, +1907895831, +3899851770, +2114748037, +3722218935, +2326741473, +2611786022, +928536801, +790169521, +529031449, +1994628087, +2592651924, +4185981439, +2114362573, +96927035, +1926025317, +1222776567, +434302020, +2319609926, +4239235250, +2690417922, +1140409417, +202107411, +2333393912, +3510993505, +4063308797, +3497844784, +3263046839, +3668604680, +2386156986, +1416370346, +3882981054, +4268391031, +3210889020, +2088330271, +900404223, +845299138, +1337400307, +3583978801, +1281809728, +3703380034, +2308179823, +3638605085, +3427556426, +1031879756, +2736683099, +1254648751, +189334849, +2008398691, +3309883871, +3881585533, +2138049807, +2327898307, +1887443476, +4231548108, +63234577, +2812358372, +4252918450, +2963068827, +2578814427, +1984998664, +4051492956, +2729954793, +2949499601, +2985984926, +2535408959, +2977065162, +856578237, +1061491082, +1278710196, +2892451527, +2393473372, +699641382, +3612023411, +1655639873, +4190069565, +319245324, +2205734474, +1774583347, +3604074784, +732455451, +2148116233, +4015105710, +2869244536, +160830461, +2228750031, +3422225589, +1872874633, +1331573884, +3918381885, +538642073, +584640206, +2170973539, +1761799792, +1227314607, +3472227097, +3549091691, +12723985, +1393289946, +3916237027, +3816406476, +1366687184, +1929614154, +3276753331, +64883305, +815570301, +2936124027, +3482573501, +3123452654, +2160743692, +1681508704, +4144057790, +2862029909, +1523670886, +3373981507, +526777899, +3446015839, +2474242225, +359752585, +2796225472, +1401262533, +1557704969, +1956028224, +48108021, +3969016381, +195568925, +1123527483, +2619721539, +4252025604, +3613807980, +2052852439, +2643700250, +4149162188, +2877731457, +3563746862, +456191049, +3992649607, +2592947382, +450890889, +3720177044, +419634293, +1128030676, +1857134370, +3631566738, +813202310, +1313309997, +2636197981, +1160812352, +358338694, +2774640484, +661200034, +2302274510, +911756406, +1733222070, +278881717, +2215729765, +302062270, +3085080058, +2865046753, +2671080555, +2865047542, +1821122012, +3096075429, +2225003174, +2507108672, +572768585, +4234218374, +3720945158, +1577531281, +2740917815, +1954351423, +2193871966, +3354742024, +415200661, +2416379519, +3457238048, +2802962448, +3674424811, +709034726, +1451259972, +1670565969, +2795575517, +936111556, +2746170115, +803230219, +611716613, +660553406, +3012410472, +1472653419, +80730080, +284532848, +2691279268, +551730103, +345173911, +2624603313, +3252958517, +2976589452, +3130397736, +1459043254, +3797832732, +1863508810, +1370883742, +2843986513, +3072150666, +3784757170, +1931802016, +2404327738, +2888392243, +2424251343, +2943402953, +3751404987, +1215736889, +988348477, +190094089, +558750676, +3305524392, +2636076616, +3848360292, +4139713701, +2387574878, +3306671627, +4224602980, +89807963, +3789514273, +1755259277, +2584522965, +561122772, +3673723505, +2238838359, +2753051996, +816037991, +454005413, +1724737531, +565622358, +2304692173, +2829385025, +409592064, +1995144893, +827145356, +2859002399, +1588798130, +354458937, +4032070712, +2354807091, +1432120301, +2394546149, +513057714, +390494794, +2959629292, +4203519028, +2000917648, +2142103432, +3640448771, +3787121008, +2642858804, +244128791, +295192119, +3611787862, +1502819219, +3322611667, +3854836003, +2377448358, +4101995756, +545476002, +221545804, +243968175, +2098779217, +4003225852, +2916263470, +3445388293, +3421471519, +3706469627, +3045266220, +2267837458, +1413482344, +336340425, +2181089116, +1517926656, +789045509, +3984103333, +2430177236, +1606809424, +1805525165, +813612184, +491972208, +939104737, +4052883716, +3356540197, +435309739, +1119645994, +1160593378, +3202266009, +2368588228, +294728544, +2545327238, +645640069, +3142889205, +1604917207, +1218957951, +4289773262, +634230442, +4073294426, +4068944017, +1038496607, +2425265761, +1460851271, +1869253176, +1374128082, +4006419760, +1994566949, +484944459, +3178131074, +2997128017, +4247248782, +2911662107, +3641896253, +3962436921, +3082544326, +1303260048, +4060315454, +3496393808, +705117925, +702718085, +1098730364, +484938874, +2542175906, +153894247, +2142951370, +1909586797, +281536887, +4102266729, +3316874815, +2621074243, +3531818530, +2915842858, +3621414111, +3809564546, +116553172, +1336213984, +2053692337, +2467802861, +4257440633, +3345363142, +3415475160, +3526765486, +2397210351, +4105535121, +2521527018, +1143930069, +488515941, +454302826, +2380781814, +3813337618, +3578889450, +4128436051, +1458786474, +2242817538, +767710035, +3323431404, +703171309, +1675455141, +3212556016, +84008268, +4181081692, +3393486666, +1058012534, +373086001, +42388517, +3221535606, +2572984923, +429115585, +3490609848, +180684701, +1271933466, +426606861, +4049129475, +2652373569, +2138071037, +2117742953, +119646517, +2483252209, +548631084, +1161303911, +3736800048, +1833368683, +4233504433, +316318082, +1057806465, +3451722610, +3397979495, +480914999, +1641719461, +1325592766, +1806318197, +2343344594, +4182705508, +2039579888, +4022973287, +312719425, +2184704237, +1921227160, +1934510123, +3265945576, +2717381033, +353206028, +1060449529, +608545290, +1778885341, +1348867814, +808784077, +3272140639, +1108147702, +2414120101, +1021537065, +573164244, +1653784661, +3185119038, +3902011188, +2422115054, +3492010542, +3889585431, +2832600282, +972367912, +384286137, +1125939416, +1726078405, +372059425, +3674846231, +2940301599, +3120551191, +2392294234, +938452337, +3910067770, +32435967, +4277606281, +1153017546, +21398056, +2429424542, +1393838431, +1169476274, +1332426518, +2068674426, +3942098123, +2066373876, +2556591648, +3574475633, +4285684482, +1306325094, +3304794844, +3643181040, +2929980952, +2465454817, +3008106550, +2778335590, +3766798420, +2474269245, +2355695190, +181914008, +365604731, +2878110453, +242782887, +497140826, +533237348, +1776422835, +2457778375, +1682569529, +2899965882, +3187756283, +960220716, +168963812, +2579246016, +260398114, +3521634797, +2618998481, +4109433279, +3306359579, +288188296, +3245611745, +2862859449, +1525504171, +298578061, +3394629369, +3430011244, +4213670821, +3018557045, +4106587906, +3558042585, +3033677055, +664217451, +2910087633, +3904448931, +2686157500, +2855988902, +3539192785, +3820537139, +1280138641, +32012817, +2666058687, +3288390891, +4255571078, +2084043804, +4261542071, +4249384177, +344089401, +2627862622, +2044257114, +3216386238, +3461254415, +2074968020, +3838947374, +3885805725, +2849407638, +3088912959, +2516230324, +3241304276, +1479283297, +2572446548, +1842480354, +752414326, +1783143163, +924596351, +2990977488, +2141046864, +77027702, +203376173, +2285057437, +1109390452, +3405297916, +1761990550, +1134451497, +3129876274, +95536422, +2945411531, +1274522925, +4283583936, +3152354806, +3202115570, +788236114, +2987770248, +3376569037, +2888756347, +3319223115, +516938426, +3362545352, +1534822572, +4240654137, +1223497752, +4153230583, +2274768728, +1082610122, +3795942285, +4184962035, +3937499077, +1032487320, +2472026654, +2807869455, +3507201289, +1100644323, +2558633782, +1463809721, +2374714499, +2419088955, +1421015480, +566276970, +2615340085, +1507013263, +2361974080, +1732903593, +299249236, +3650228113, +1772559322, +3607790212, +1372837888, +3497473157, +667799940, +2381299199, +428615050, +2132585220, +3469974213, +3234417710, +1950078817, +1441809951, +3982664201, +666522073, +3443413403, +3291690168, +3622290554, +4278979564, +1082252668, +4168951804, +2008704072, +3488518823, +230016073, +1016829707, +1012612928, +4237561688, +1497082736, +3723754574, +2006619021, +3736850723, +2938393790, +1588086259, +783927188, +3319457005, +3017293390, +2703723113, +2919912530, +1687820954, +3238246836, +239875127, +507334979, +3921382562, +579149689, +1125791191, +2398394821, +3075957291, +3528649373, +3024493872, +3460968889, +1494249376, +3755406075, +1909732754, +880520692, +4067682234, +1754686085, +3187057582, +2187362811, +3806332329, +1086957039, +2004707387, +505321736, +3386831811, +1938100328, +1187332173, +481503650, +3998627372, +3885446531, +2249824446, +431123899, +2565558152, +1017975588, +3220042062, +2696963917, +794283294, +3884287523, +738014414, +320545399, +2865187842, +88409359, +1403154794, +1607432366, +3024017416, +1112929211, +2587706557, +2681940498, +1465573862, +2340028813, +657891771, +67303113, +2137283268, +1601023385, +1684045262, +3551724845, +1241742863, +1011641019, +3445442079, +2013483898, +3164789618, +384873490, +520295729, +2692577377, +3246280681, +2519506934, +313815462, +1084177366, +2993339336, +3848505083, +1312838152, +68793899, +1167453958, +1620987793, +1372452056, +3731499115, +4267470741, +143938176, +1965561057, +2878150573, +2306886112, +2920657282, +2509548344, +1756903514, +1780344955, +3604355202, +202316000, +295657134, +1744967879, +2350764279, +3901493680, +4078128231, +4013985323, +128697975, +4294823060, +813621514, +1028690406, +2627173269, +2741851383, +652088050, +522930864, +2441241337, +1012680322, +239138885, +2252014941, +2313415725, +3933090688, +2810729237, +1123177519, +3275818052, +3646171874, +1878370652, +3966750391, +3960127423, +3994347549, +885520111, +3132032896, +256459345, +1230723320, +3130731001, +45618745, +3425429520, +3859883891, +99477390, +4164611907, +788485317, +382989136, +2727555975, +1204617981, +3359686186, +1018335636, +2931676796, +4226862094, +1395081972, +1730165299, +4045693151, +1405080188, +415983483, +3820843156, +3966776861, +4124786690, +100127239, +245546261, +1526574665, +2996372384, +3232419816, +2561019315, +3528061094, +2648890537, +3832083373, +212962158, +4222442474, +946988865, +1085147057, +2645272943, +2638717411, +4056077423, +197003015, +4001620003, +436966168, +1329498995, +3765025914, +2329265215, +2882864160, +1800542798, +4199871618, +2629971686, +2484852946, +1687312233, +1585532089, +4252335424, +2323360449, +2606840935, +2106707231, +2621223663, +1932562446, +2192413642, +766605910, +2352847514, +125110882, +2180041040, +371465815, +670522022, +3156434344, +4285358366, +1952009172, +3747716851, +2011874678, +3826495519, +3284011278, +1701418070, +2796853616, +592727371, +2057378348, +2938857990, +1099219223, +323328875, +3032918337, +2706680310, +1429294573, +2629672313, +3486577234, +139819184, +3929319999, +3851195571, +1730098835, +3417055246, +207985257, +3316527481, +3312813166, +1009048432, +1770667473, +3865615132, +1156333657, +879058883, +306774634, +3765557477, +718066744, +90736160, +1236000840, +976904146, +2416999081, +3676944013, +2489185049, +3528708548, +1194276840, +1685352426, +2617930412, +1595152562, +2557410584, +22883281, +337444918, +3931382083, +4189954656, +654228107, +3966640394, +3116206856, +2975756157, +2533080346, +3877698183, +275461185, +3082246817, +1098568304, +2731631996, +2303644086, +548837971, +47347248, +3834566529, +850728532, +1817189677, +2649259761, +632617837, +1750758619, +2541331553, +1021802833, +1408019721, +2769025579, +3284138415, +104647239, +3329728637, +837998311, +3906677350, +3731413605, +3708455556, +2346507086, +1341552967, +286832215, +125019038, +2039608045, +2938089987, +1043790579, +1128728332, +3892451599, +616571976, +1207948064, +1213504516, +2715685773, +3559470224, +995545196, +3042606915, +642778591, +3449185141, +475543196, +2181240162, +340488855, +4231063588, +4201501203, +41505901, +808314570, +916546037, +1875282938, +1671402237, +3468581493, +1765804125, +3617053302, +1183894603, +1925897001, +69561800, +3397606753, +4009511190, +3121714665, +3645126965, +2150331723, +963539337, +530212840, +2068276984, +3936767418, +3238796372, +3712978074, +3009247240, +1116804773, +3772529926, +3871574494, +2656126048, +775529708, +3048351674, +1911911457, +3606117723, +1305798094, +762882358, +831607569, +883219779, +1830012448, +267700499, +436608249, +2869878440, +1547929196, +1136131186, +106151352, +1193196017, +2600958433, +1344020776, +1820932846, +1067351841, +3928397194, +1686717607, +3361712046, +2379660528, +998503551, +1343025591, +1502161854, +2125477916, +3854909808, +2924919525, +2626548076, +3787707901, +4227665293, +1605358101, +414566993, +1059544502, +153082078, +4032802190, +1354463294, +782567984, +4190525791, +462495679, +2096532314, +4199480102, +1071355754, +179851467, +2666403543, +313262139, +2512674928, +1268381312, +2601731298, +459768954, +1242484316, +3439063629, +751993134, +3411491127, +3911319061, +27925806, +2882005703, +4111648582, +2968521852, +4156872418, +2823657540, +2783913006, +361323052, +971576870, +519725577, +263289331, +679681284, +4026700637, +2210602339, +1318805098, +1875293488, +3730330110, +2845159642, +1439761216, +546399635, +2823732394, +54102522, +561121754, +8005168, +2375709020, +2745769346, +3425245534, +2540196760, +4005796544, +2639339387, +942877559, +4268718474, +2757468502, +3262181608, +2797964239, +566194718, +3067842355, +3226470389, +2412209445, +1422612046, +92961461, +2575735017, +2843886145, +1420222168, +3165672967, +1532207529, +3228216170, +3466866972, +4122948690, +3848581434, +3720129081, +702180941, +494306432, +780617255, +595343132, +2477281989, +261927499, +1057344713, +1554578375, +2791132554, +1707348432, +2490130210, +851732885, +1136968381, +2362640636, +561428383, +339283593, +644712514, +3081851754, +2083348390, +3392192296, +3224209958, +3589276079, +656370667, +3190623557, +3726968852, +2424853746, +4180751005, +4224335294, +2007585534, +2089389513, +2604170641, +2015751969, +2431531992, +1779366034, +3093976703, +3250710370, +2072627560, +68957774, +1931124949, +4129839214, +3225038320, +3061816624, +2185642883, +15502339, +1475826794, +3878295222, +1748658800, +2571105377, +3206672947, +386519446, +1350648312, +1518680506, +2387504444, +1948658299, +2588935281, +3812936771, +2979539556, +2312946646, +98622187, +1201913685, +2870249784, +4057003817, +1137844485, +975707707, +1096621033, +3805661254, +1907196913, +1429550288, +3384096867, +2911009334, +537953183, +100818566, +3381412713, +351357629, +2360379422, +3525785281, +2681473113, +246248027, +3019298050, +652820156, +343794793, +2865273892, +2584842713, +4190494862, +1881638554, +3900952502, +1295722826, +2870298864, +2941771984, +1519399849, +68748946, +2100340870, +2092740768, +1747441919, +1300316092, +507301014, +1816263707, +1710011044, +3286002881, +3309365589, +201882829, +2699378853, +3173075871, +3464879213, +2361629933, +741932242, +3000722567, +2769178215, +650424166, +4223943754, +695788030, +2200955098, +2345662733, +1968955115, +1852894422, +1537211215, +977776059, +1011754900, +3968774850, +1518630475, +1398927543, +3488288263, +1924837931, +2213577248, +194247684, +3929642846, +1945855360, +317302655, +1113535290, +1034808660, +83637631, +4247946255, +3818275772, +2084934195, +1790283043, +1336812829, +1078886065, +3704173655, +2345501068, +31395632, +2922516113, +1997644990, +2628828855, +2973249252, +36250096, +323147291, +904590398, +3789437835, +3972700454, +2661948480, +3726751529, +2384245566, +3045223829, +2228699506, +492486297, +3729325520, +360826803, +2016766736, +3218037324, +777271119, +3699592642, +2300187157, +3534231814, +2653039591, +3481775517, +3582070319, +3019559764, +2068053917, +2861550199, +3890766039, +596231157, +1623232078, +549172460, +111751358, +3919703421, +4019826378, +1949494761, +1843255962, +1823944716, +3703778787, +1501073413, +3809307658, +1158118131, +1205181066, +2849466234, +859814303, +2119880475, +1953886063, +41285410, +2165042662, +1887311749, +2697015272, +694621124, +2370915309, +2953082958, +1851702789, +1475591313, +2895599957, +4255783856, +2671892718, +2033256350, +415664846, +3510609889, +2071927375, +3546536583, +3263838114, +2949784618, +2313799658, +873448575, +1521211880, +4157670791, +3792466594, +2150017881, +234582381, +2118823688, +3393862877, +3664750009, +1094978250, +1365469225, +10197374, +1274561444, +3987350422, +966578160, +104579273, +1441040266, +2986780984, +1271651561, +1956490466, +3419670511, +3154782232, +2766887939, +3323265663, +3727504197, +906085272, +1202016963, +1773444202, +3878993627, +3783812279, +1935464082, +4038822003, +536523566, +394186957, +3057738993, +499843491, +54946288, +1632409332, +1005907463, +1383011119, +154737702, +982634457, +2337039732, +3016658844, +4112082482, +1686524478, +2019050, +401886466, +1676690103, +207436422, +2653129844, +2898725695, +2420566388, +3083287353, +3823689407, +1856264475, +585654021, +1373450102, +3087084442, +1236762783, +2583792350, +2667613874, +529997004, +2281383077, +1887458499, +3734667305, +2986503612, +1895885927, +2442306440, +1349041162, +2617125110, +1043323000, +976495505, +3014810569, +4063569116, +2959431797, +999154552, +2390550843, +4001381135, +3982923996, +2318565820, +1798978460, +3887954415, +4159353348, +2544133515, +2681629467, +863865804, +1412144753, +3817189172, +1199123669, +1256706023, +1395249878, +1167259470, +3278156959, +2639921682, +902120279, +2090485372, +1678730837, +1394615533, +3993726960, +1122259933, +3540217949, +1414558881, +1591905968, +2900810486, +3247282609, +245182092, +2194027313, +3484109761, +1889331174, +846958108, +4134390666, +2720581978, +2595226875, +877181519, +2126102359, +3465585416, +1023385510, +2145989826, +400603205, +3565074642, +269581725, +2060172259, +3221548160, +2813305175, +493292177, +1687104784, +3828404966, +3342418110, +2239442295, +1824658373, +1633639252, +1290167053, +4043450544, +219123359, +3641053756, +4025493449, +3760108204, +1595111503, +2764880913, +2657951797, +2313004378, +580633313, +4198416775, +309374661, +930291717, +4275906166, +2402936353, +1926369618, +2355991517, +3133815372, +1234309493, +2080631078, +3702899197, +421871558, +426031934, +1259115404, +4187535828, +3289230278, +892570739, +3667592246, +846365537, +712425979, +4204698515, +1947724648, +2050320214, +1055198449, +3813899641, +4267733651, +2262357422, +2744142912, +3003916533, +2785182168, +3079776701, +2821036068, +1857946641, +1411064834, +1547885709, +2282784063, +4158008843, +2633731938, +1113038196, +935366758, +3473943102, +2463978198, +271957224, +1756728683, +2888093554, +1012359939, +3085078779, +3717737065, +3922090987, +2543084968, +3674733622, +4198015729, +3961749503, +1896115260, +2858885968, +1968967783, +663199624, +2668749749, +2786346686, +3658681250, +2474568421, +1025434894, +121086339, +3284953081, +1076066906, +3340452638, +3956082716, +2700951650, +774428771, +2004649207, +378285122, +2566549747, +2324279141, +408898473, +3433063443, +3415319362, +2732704408, +1270679566, +316861805, +1765656279, +2200563615, +3574532562, +202940922, +2957780548, +1614942399, +1084040036, +887704435, +2699353668, +2992609244, +4187851098, +2778936607, +2735262763, +28585617, +3600362640, +2562895802, +1579539054, +272125718, +2468832228, +1165989053, +2702165592, +795538732, +3152335424, +3914715752, +2734407981, +1805670799, +2402669031, +4149808210, +669473770, +1916341668, +950694082, +2408188229, +969589012, +978821820, +2127981571, +3417098290, +808547525, +2815767844, +3132682068, +3154396461, +4141844100, +1856525748, +3537220085, +2629001944, +4093734920, +143408557, +840596474, +2227360419, +372873189, +2066491043, +1018054782, +2986017087, +2762165727, +11280933, +54201959, +3592466879, +669977185, +149802067, +269513020, +58447602, +2818304034, +133906052, +3747813405, +3199232603, +3926818871, +3850630014, +2928435375, +767156739, +3209452001, +249854387, +2303422848, +3409041158, +1671542397, +328764579, +3232106009, +1340746868, +4036078282, +138192147, +3681251892, +2098760371, +3374394562, +2755834498, +219064127, +2996254964, +2523089639, +114555132, +1847331390, +1549334072, +2278151103, +3515209431, +1658177574, +1420968133, +1376382796, +3592994980, +2774506978, +4076676500, +718887702, +2860616829, +335521407, +3335570406, +640863096, +991716676, +3704614523, +750915514, +2326964852, +2668450790, +988508396, +3999533561, +3129653544, +3346001362, +2014412101, +275170012, +1060484828, +164901719, +3800826515, +2597039006, +975130384, +3490039201, +624255276, +2612182982, +1165029395, +3004596268, +483118702, +3031785812, +4137567382, +4174584999, +2978459029, +3644973298, +808004184, +3226109097, +4172150488, +669952311, +1187842392, +1826302086, +1892088747, +4221210240, +3585829557, +2627860986, +1033078765, +3448307507, +1757419125, +987369636, +3017223349, +831675197, +3206550050, +1820510695, +2798021276, +2714242782, +3938575131, +3665344425, +4119366037, +1975693027, +3501091083, +2182279152, +382965660, +1388698182, +7656682, +2339017692, +1277041578, +540484692, +3742816753, +3366755638, +329519374, +471974174, +1165750562, +4193829680, +3848508216, +1487020026, +2803554705, +2237934044, +2272199153, +1451849332, +1677813657, +13879927, +1264530159, +872595927, +177477477, +1649619380, +2632623656, +2528772474, +855147882, +4017890092, +2213500420, +2672426925, +2023035275, +2694933637, +1682817191, +768880669, +310578402, +3769254481, +226316900, +4276748612, +1375878809, +1669229076, +1833658294, +2922443200, +2618952125, +4288591924, +474425721, +293747099, +2029772982, +3928481210, +3735499376, +3371957019, +1801658986, +173370251, +4200096000, +317572021, +3566660181, +2025567618, +2542017388, +2112086372, +3525865738, +674663555, +3217999612, +1810090675, +3654848561, +1607893274, +3866872158, +3251839448, +2994349238, +1745051773, +2913250791, +4232771291, +3871564548, +757614234, +2228635873, +2283548324, +4179790685, +1930722904, +278468727, +1178034451, +32020078, +3632231971, +1535136887, +1887717916, +1627908374, +3741626558, +1244041481, +3334533350, +1541068957, +1572890930, +158561532, +567725623, +304921822, +2180204998, +1486935283, +1351690052, +1133293788, +627111520, +1782325099, +2438849741, +3999365032, +3938108474, +2600588003, +3728077935, +4211682288, +31736711, +2536193693, +4131543483, +2866828063, +634923790, +2712711070, +3907032757, +697347583, +3794698612, +1196334207, +595492796, +255581428, +2358447611, +2220258640, +506293180, +422459023, +1707480703, +536054436, +1083439592, +479317491, +1793868078, +3622326969, +824844790, +4139538098, +1319914633, +2834172035, +3946908361, +1068646312, +3952250002, +2218458768, +3607910257, +4190306502, +1143188872, +687951768, +263690946, +4204227760, +846003449, +477866612, +2812934259, +3366833863, +1806549911, +1153380162, +3352674929, +4236692982, +3927351127, +3917362252, +1673021081, +1494053143, +3722196655, +3401571981, +1677129755, +604441671, +3495091252, +3797104966, +3794902538, +1399730223, +2228091773, +1593980240, +461928420, +2540217090, +2727755590, +280032045, +2401974587, +1204465975, +3527839227, +3436258185, +1194893063, +937592388, +331018114, +177766117, +1605282321, +3014243547, +513086581, +4273456085, +4246805487, +3685114342, +3103322863, +2300396883, +2114671948, +1947483536, +3729365230, +3162522889, +1148945837, +1468946495, +1994106565, +2808922498, +2265425990, +1191683197, +2001291401, +3624939213, +1864300463, +1397280154, +1482107616, +1245533297, +1864056993, +1410910257, +1512837774, +2777613921, +3780010455, +3313547820, +710329617, +737986132, +1533398062, +2966658658, +1520165151, +351413701, +4044415956, +1295208040, +2081716589, +2765175023, +3601490540, +2923410955, +2371306023, +32652250, +669108674, +3473766573, +319696899, +3698764693, +1621367003, +2054353565, +4198471798, +3488681671, +3297628236, +29622260, +321648052, +4156783829, +589457467, +1949719527, +2097340003, +2125040623, +1741306216, +1381469633, +1954115654, +3723908179, +2429368299, +1478973784, +3833948968, +3641074732, +130254009, +2103947668, +1454252583, +3510899719, +3884507229, +3156964225, +2423810257, +1546828211, +1488287325, +2204042407, +3435165379, +511950525, +34207131, +1779818968, +665791308, +3196976721, +3979699154, +4040504701, +276460750, +1136532217, +2937587343, +3821602467, +2455041374, +1399661753, +1234579192, +2822361447, +2390414398, +2516170815, +2749616287, +2491388664, +1471634731, +3794481972, +2842770881, +1629178111, +173015366, +160900387, +3866722311, +1261060595, +2000235568, +1144073538, +3726893377, +3228424662, +1178248858, +1292805068, +463343514, +582770939, +2412742785, +2970727608, +2543336699, +4139811624, +2675438318, +2153214454, +2171699979, +981880163, +3901322240, +2487366737, +1565386009, +3642572633, +3637089629, +424653204, +251131082, +1002288354, +235383942, +3965477632, +1409527824, +3722926069, +1852854253, +1626706800, +190715476, +623736921, +2206419608, +3494178624, +4081491748, +1136060981, +1152682034, +1422164859, +1926649581, +2000208717, +1344426004, +3411445294, +4136117749, +2211752370, +2755349422, +2029995966, +2320000821, +253704344, +4071937302, +2406261776, +533705409, +2857469532, +1201746446, +417179810, +3324178278, +2705044299, +695669509, +161056231, +1629226227, +1585924176, +2121787812, +624621767, +159402929, +3491935300, +4199729077, +1684687439, +3257984083, +2317327152, +2869889632, +783238505, +873688832, +926898910, +1305839704, +565347769, +3702039138, +746536445, +2516161299, +160090770, +610261138, +3683147740, +2343906514, +1721666231, +2496804204, +2826656418, +2714229174, +769362716, +1063617616, +3550205722, +2580520127, +2030625310, +1098664539, +857894653, +3237996300, +507762617, +964861735, +4265908022, +989258774, +2399667880, +1657497308, +246661941, +499518208, +3210488832, +2669646191, +2262512545, +3089357257, +4184539136, +780274968, +3679730627, +4031640788, +1868546055, +432952392, +3702311429, +891375212, +909956562, +3566094662, +948636799, +618443696, +2220836413, +1735566751, +728781105, +2892539338, +1248310594, +4207390414, +2630076122, +265755555, +2368142846, +2604431531, +956541575, +8064779, +1337803679, +2413576017, +2360054732, +3904718649, +1652601207, +174279593, +3395073851, +109673207, +834678450, +1718706747, +1444912654, +1931514212, +3313368594, +838660136, +1593264407, +1220119890, +867006210, +1207117535, +3409593012, +3210068473, +786943117, +2174768422, +3014169363, +1636980671, +1038861814, +3957330573, +1718777233, +2147922803, +4018933627, +61616776, +2988121763, +160290711, +2371967340, +525658542, +2008269605, +1374355435, +1601700672, +61145375, +1994526533, +1967491816, +182999317, +3290947410, +1953943673, +1188850152, +1140273205, +4209672050, +1584632322, +695538525, +3996782211, +466621497, +2231816662, +2989866076, +1647944173, +957118584, +1893806858, +2561235730, +3141971741, +4146660993, +1053270184, +2624402703, +4179991210, +2331985470, +2853539811, +468871659, +2282635915, +3334834328, +3803347444, +3820202619, +2311180644, +2433238604, +512375421, +3035625393, +2668585249, +981573577, +910296393, +1309791780, +4212758357, +3473101042, +3538940078, +2251502597, +3833572903, +3936409396, +716262613, +1367430686, +1317282603, +3297933892, +998011973, +169045584, +4034280888, +3326610364, +2380508075, +3168543741, +3384863799, +2483374987, +911615322, +2367246427, +4263918197, +2946433459, +1828040939, +1220470613, +3786213373, +1029931653, +531515193, +3822309266, +133497395, +372858391, +3002268041, +2575947808, +2477970865, +2285090856, +3748934547, +2568156164, +1351189724, +3962230643, +1654015488, +3219809510, +213863415, +2854143700, +294475832, +2925259469, +2992958641, +2445609874, +3174843253, +2722543140, +3878609888, +1954483657, +4040252803, +3191805197, +2846470943, +2302718354, +1336624151, +1845829049, +151123609, +334952806, +1179385327, +2131992214, +3343372423, +3971400208, +2081508758, +3205103822, +2953389039, +1966488527, +3981682164, +3100981386, +3825211270, +3732280308, +3614404804, +205963334, +1711620333, +2828816009, +481897818, +1182041800, +2177600552, +2826190207, +4178711563, +740593371, +363800771, +3116609873, +4231139099, +1734154526, +1409541169, +3038848055, +4147733671, +2813838876, +2510410610, +3520658861, +2232895485, +1879439464, +1757326418, +1630908752, +358581623, +2468724149, +3080003526, +2681448926, +1455695492, +240979766, +1570326901, +595231979, +1948276398, +571348963, +1198969049, +1872914995, +3579404268, +185152262, +3157343993, +3562702386, +2447236731, +3871452511, +4254377648, +3950698306, +327241735, +2463422828, +2900679448, +1379936386, +2686924666, +3383689292, +3656321446, +3020407804, +2597384492, +3481280890, +1693842941, +1362617457, +1921048808, +1201105622, +4115706185, +3031844430, +3369435729, +2662708395, +68381033, +496918108, +778593765, +482187465, +4164192808, +2630981296, +3874843849, +537492341, +3527897705, +2324224957, +2880137328, +2270977619, +2839681091, +1432902627, +1119762999, +2107478755, +3276900411, +3869025559, +418653711, +3936790505, +1484487377, +3075736977, +1847878557, +2271266259, +3151328998, +2331887958, +899511962, +4101265034, +1295568395, +2532442524, +1032019548, +2239446867, +3498261076, +3490418187, +3077153311, +2553294355, +4205251900, +2215362351, +2822008631, +1381599025, +2722109546, +230489470, +3238100582, +454625303, +788386940, +1173179450, +1541306729, +3021818788, +4095256074, +477101034, +3415142462, +3502293296, +2615435254, +3923504818, +596289891, +2391269779, +4175718228, +4130491105, +1597534584, +2117917474, +2444737912, +3726384146, +1108530189, +764010725, +145537517, +3956287715, +321432132, +3769224489, +1640616538, +4288392594, +1871187149, +92565602, +1012177144, +961949043, +4196910031, +1129457302, +1939739400, +547287597, +1675581451, +2004233629, +2751764056, +2225499852, +743264266, +190109749, +2477053254, +1324665254, +864478753, +2726100736, +97562733, +2708688289, +3381593055, +1964748589, +3439542859, +1842518289, +2812527593, +2735215105, +747097851, +2579925774, +3233491123, +3346256713, +3806860438, +4221423624, +3977202337, +1010078012, +3698899123, +223531990, +885078958, +1526796541, +3095746615, +2485349314, +1078673575, +1837776206, +552369252, +509434443, +1986967283, +2822096321, +3622586537, +3278998535, +922299570, +1494143818, +3407150185, +1448747792, +3454702586, +3462343483, +2204688536, +1430469710, +1587654637, +1659206472, +2297511422, +2767980691, +3663432796, +1564329168, +167810343, +549914202, +276430170, +3597942809, +111301047, +3437061710, +3716133055, +1454825418, +3484472479, +4106040967, +3687667206, +3860717577, +2522320916, +3867148564, +2599332289, +3548259231, +2106073132, +1828096950, +2557691091, +2832038044, +1327330974, +1037930401, +122909606, +498667704, +1143339727, +1703062872, +3117446548, +3006466297, +2466532272, +1452365863, +1531870332, +3151361050, +2376605833, +4251800894, +2203787046, +2846331652, +3641256943, +437345180, +2866802387, +2368487832, +1288716327, +3874064286, +1961204958, +243105376, +985797628, +3183731440, +615313437, +1074130897, +791158984, +802403013, +3948346757, +2279334041, +4113133314, +1620763024, +3077551002, +1429034428, +3504015820, +2960177462, +237375563, +3084845696, +129866773, +1353479408, +4267263751, +1973343825, +715511510, +2476805593, +1928256950, +2344823449, +1997068132, +1355235887, +2710411933, +3923599412, +1544843346, +3468086010, +4132527984, +990811486, +1373727087, +1744145653, +1306737962, +3964183974, +1705891266, +305922590, +1233033188, +3903708291, +1837760087, +4081441170, +1671045448, +2774975741, +2887013395, +353130185, +1517769950, +650454198, +2628089246, +1755284285, +3155510058, +3610109611, +3459220224, +1617229167, +3005643795, +1527612914, +4100575392, +2735224381, +2557079634, +187665889, +3689800541, +1640469591, +4054490870, +2695902228, +1869701544, +2537199356, +3888076487, +2112096968, +3301855343, +241299522, +880004177, +3605961803, +218470881, +3508308597, +706298114, +3199051610, +603526977, +3589092682, +2721281212, +91313103, +2947851253, +1363090946, +3857746945, +2004724325, +347403425, +3008113656, +370054415, +2990169643, +2373042615, +3915164617, +3435179263, +3116878665, +942315263, +1567369052, +1392310018, +1788645532, +35033987, +2045309968, +1302881817, +3108101877, +1994584563, +2565845916, +2012249375, +1477347155, +584173495, +2528321585, +1641787181, +1575390263, +1795749155, +3048659790, +2387269385, +1266405669, +983424534, +2503427170, +1681517571, +1994588153, +159934859, +2902356434, +3516942418, +3814589313, +3527986984, +3865673904, +3990604844, +990952529, +2341709225, +1947952232, +1490770604, +2267502278, +3034573777, +344543640, +2926293933, +3019230414, +2688082320, +2024323445, +1689023880, +3646561147, +240733957, +1104440307, +3746100789, +906419511, +2678300125, +2688935332, +3671849128, +2006491212, +191060302, +3354825360, +1613040517, +571622322, +4013139871, +81961837, +2096618150, +3138425116, +2407986405, +772381258, +1478411311, +280323840, +1116765820, +3566857175, +1905456909, +736410243, +3636411317, +2951104609, +3333696187, +1619377780, +1971787338, +121636474, +1090529056, +1629546138, +2747316081, +227738777, +3902351475, +874117934, +2201203627, +2891635376, +1682161701, +2681256796, +3104209136, +1509354090, +713748930, +1363975280, +2724510007, +3436680062, +1886633500, +1539393460, +3887279395, +29252314, +3417416990, +3387505181, +1442593997, +1886599082, +3594212662, +2605960239, +2580014268, +2455621948, +2142812682, +3821895822, +1479584572, +3996249409, +1620391498, +2913249856, +3360919197, +2817557024, +3981897379, +94151786, +4050800800, +1915892589, +521694597, +1726593097, +305927680, +4246569131, +1607589104, +1532557509, +2098820312, +3405182169, +2169786650, +3889934776, +3305611569, +415136468, +198331962, +784292515, +2520415563, +23930465, +1638765098, +1222711365, +438681567, +2611660330, +2488796266, +2862750136, +3809955565, +154111947, +1706573983, +306740724, +2286776029, +385305240, +486498299, +2415052390, +1233651887, +2066170667, +1511023088, +705790790, +3413267820, +3828686453, +54591973, +3139790673, +2323931115, +2137410718, +31261611, +1983242259, +3656051544, +2499065085, +1078474669, +3289036811, +4039767182, +2710292480, +523311736, +477057201, +1436491617, +3256383199, +2879344492, +2578981034, +1349839410, +3735998220, +1222650600, +2538403957, +2353322419, +3360912800, +1128457025, +4209782923, +2338075436, +1318145809, +1915925403, +633063010, +2774000747, +1437302084, +3014013030, +1952735329, +4003957377, +3059122381, +3038555378, +3105946324, +295250685, +665740931, +2176020475, +3576330388, +3788863086, +3498919204, +698304973, +1073116372, +3650713391, +3204247720, +1622071355, +3172987202, +2909756157, +578927761, +1933127338, +1912360133, +3585027028, +707898692, +2973949155, +3805767844, +2974610728, +2558191273, +570689394, +1405210178, +4112669924, +2835219107, +3832391427, +3119959974, +2263489392, +650977960, +1113571233, +743224359, +4255866364, +1200197954, +1302675029, +4146371170, +4060172295, +3759825027, +1299594465, +3291413291, +3258127173, +3828846725, +2668171590, +1102802660, +514606392, +1911006606, +4226764084, +3622782315, +3850418256, +4275015673, +932019999, +3083692378, +1372816940, +3205733688, +1526236279, +3594088664, +3630798170, +2700126597, +467198768, +808724215, +621411267, +2627539850, +3714425442, +1644397326, +3141748984, +3933487485, +2222923937, +2494236215, +1565310754, +3837200537, +3911315965, +2148894718, +1419781690, +2545719854, +2017790352, +1060002113, +2439524873, +2112560544, +3375646227, +2175620264, +3525860580, +469468553, +3472776328, +707527629, +873909096, +2781528263, +904617997, +1715475039, +2327697019, +3501919374, +1083581075, +3472852485, +2010350740, +4281348727, +931123904, +2449131599, +1293328590, +3087315738, +1954619703, +1363069108, +4160047805, +2511521117, +4028959986, +1843610467, +691207881, +1055400860, +1176679833, +741418601, +1230421843, +4118313787, +3196237599, +629981413, +1353553401, +2035944913, +1996030028, +3500496252, +3663152113, +1623909093, +1997057671, +2836002996, +1520246398, +2782209204, +3590510553, +782410388, +1229774441, +2654115577, +32610146, +2886797725, +1467090009, +300661539, +2280338505, +3484828602, +3703415311, +2613495257, +2397939148, +3900086374, +3371083678, +255864635, +3661717138, +3780251218, +3229133208, +4126004235, +1827643373, +4161623689, +1076495132, +2773023547, +3977428115, +4027141224, +4022896608, +753888638, +2112393435, +2854753830, +106181885, +1641906509, +4084267189, +3714379640, +3625891484, +666225957, +393417547, +3731594852, +4174908748, +1421467404, +3135141792, +386343862, +4096724097, +1141262772, +109893804, +3333481503, +4268513788, +239162983, +1021621047, +2442738475, +2077444086, +4137696807, +4034666045, +1385758194, +906271054, +3407231920, +324204089, +70283275, +2859814564, +605970575, +3341251473, +1751369058, +1484204455, +4055466698, +1266110710, +834456696, +2945714623, +2463877568, +4126484000, +2914454439, +3473067315, +1152591623, +4067995915, +2187190871, +4287783293, +689752166, +3904096298, +4019239979, +87825513, +3951997429, +3592963055, +2506748886, +1185853860, +1271994722, +1749174670, +2250832728, +106340986, +3316413025, +2104591515, +2808114267, +4231033617, +2849332962, +697483205, +2951013325, +1345366657, +3681086947, +427042456, +1031359086, +4190604605, +3705879351, +651401557, +2168525255, +1179724659, +4000477627, +1110421249, +972392748, +2383989037, +1630156249, +2452228126, +1440249614, +4113588352, +3193445115, +1297426292, +2840036876, +161220938, +178550183, +973233549, +635158319, +4285793974, +3259398303, +939688018, +1797033734, +1561532480, +1577613903, +879984740, +40956427, +3389872591, +2847095066, +889083828, +3567347091, +2960496645, +3173315633, +2752131999, +4248713545, +2103316155, +2763171469, +1806078305, +3732232199, +1876026150, +64419977, +3378334996, +874062501, +2811334487, +3239789501, +3281902468, +1867261708, +3862801401, +4109966978, +3718195893, +1418942753, +2709969239, +2902124094, +2246388478, +2694780828, +3158050976, +3112316111, +1216957597, +1205898319, +4052058170, +1415940708, +2737367930, +3519151385, +3306060375, +3241333061, +3498363222, +2273353015, +3141607614, +822667577, +939582865, +3457216580, +3122300009, +3893679833, +2926719088, +1222217839, +519589852, +2051141001, +1289623747, +3856730233, +580050393, +3578433393, +2940020359, +4251709839, +3078748614, +2383670314, +1947546933, +2131471772, +345467782, +247076074, +2087295771, +1780650796, +3451775872, +2205308566, +1289786910, +1856861201, +3667366857, +2747363240, +3061313017, +3737566580, +746845040, +3365248458, +465879522, +2336691513, +3244424031, +2949945179, +3131938883, +2323193382, +1629473598, +74517872, +693282552, +1401338197, +2059561901, +480679305, +492408773, +2842596738, +1928946974, +1556324852, +644801972, +377604411, +3507352022, +1566394079, +585403091, +4256503215, +4047410449, +599678968, +755847773, +416583332, +924673431, +4068621336, +3299213666, +1858105006, +2209382594, +946582317, +166894942, +2775977964, +35940492, +26720766, +1544640609, +2721386448, +3018648446, +1795105984, +450451871, +47924972, +4018597842, +94333091, +1152798230, +4206357496, +2814688071, +1391174106, +1044262829, +2751113418, +922015423, +3290119843, +2694743434, +1424533290, +3618245730, +148311613, +1669632862, +1259281654, +2112848201, +1267994072, +3752190421, +778092944, +1065306486, +3628422609, +3368833366, +739415868, +3300943646, +3660447357, +1184962005, +1023973971, +1832394431, +1137006121, +1444835716, +2243665804, +1510762575, +2466533739, +3887879731, +87431003, +2245321996, +3488038838, +141734164, +3971165360, +756469155, +3364184523, +754560364, +2665145269, +57637962, +4093465722, +1327652707, +3826955867, +1137517370, +1021828340, +2261392404, +4178377033, +2292992397, +3285905257, +3598194725, +983118410, +1029281061, +2321602652, +1845928321, +3522297760, +1310221761, +2910256805, +4168224398, +469292887, +2256060893, +4146198434, +47048237, +3923355269, +3642888337, +610354337, +1290314301, +4182972872, +1917019737, +2491766577, +290465802, +517620648, +3578997878, +1100297972, +3586316575, +288631148, +2319560691, +1315688103, +4208617262, +861072784, +2753553030, +1707222780, +2488338596, +2824399368, +399952202, +541138014, +2634795111, +1380588065, +2884569974, +1669364475, +1845573784, +727314407, +3079941310, +88920742, +774893565, +644466339, +3355103973, +2508983306, +1616835140, +697521312, +1947166067, +4262913619, +3973161467, +2662724186, +801060278, +1278126817, +3538819829, +1046373780, +1242428115, +1950723138, +3120616612, +3794218520, +2570220606, +157873341, +3681001549, +3174092538, +3297711384, +1178368136, +2615377719, +621866132, +3600082223, +3051974582, +777034085, +502684455, +3588170470, +900568396, +1188169351, +2454690919, +2759485199, +589853708, +1482643341, +3269509858, +4114077244, +1267078290, +2643888426, +2710957447, +3503645526, +2970349503, +2315815958, +1755073321, +1890969605, +664832488, +1612683911, +4091836525, +2052989216, +2487398724, +1119117166, +2831040891, +501543761, +3541142470, +2138402560, +2704123324, +3063894009, +907208337, +2391939173, +1871934161, +2296000970, +316148491, +478616267, +178932848, +1807570335, +170290673, +4200306937, +1235118929, +1632303854, +3929758635, +1719419516, +4202329426, +2270908878, +154892532, +4033642888, +2954638137, +2138805170, +1073292335, +3838880531, +2956744551, +683260113, +1058658521, +145124963, +2114075111, +3098614586, +2265113394, +2766161824, +2618745989, +3796443850, +2961063541, +1345105459, +3086757577, +3492583196, +2411316773, +4203234993, +3555562974, +4019740338, +3200542092, +245388791, +1321239163, +1018098491, +478813805, +1349629360, +116365388, +2829053574, +626660299, +3294643794, +1546456385, +364639417, +2356207603, +1990979592, +3603898189, +635769434, +1759863385, +2465548270, +2176862513, +2837070080, +3606039587, +1294238105, +3745054739, +3548988101, +1772402902, +478273713, +996373041, +3129297085, +4060256071, +3499026742, +3767126528, +1693796377, +4049659957, +2046881553, +3006833263, +3537791334, +3264869214, +2603443626, +3765416659, +1183636515, +1604929602, +3163716127, +208451853, +1405401123, +4233447819, +209051442, +3709348332, +2668688931, +2014257406, +1092145494, +1747115477, +3333235768, +3726796454, +1928065869, +1939661270, +381461895, +2986799666, +2686771108, +852203991, +2940759974, +4288501374, +649669963, +876164358, +2346642848, +3188553501, +2269406376, +2297409734, +3833018712, +1120059300, +610115094, +3293442648, +3406544426, +3441094940, +352194430, +1849275980, +303451921, +1958728118, +3431512226, +107111815, +2792393980, +4196967164, +3387128122, +133410670, +598568870, +1166783145, +2057844438, +2466132563, +1832846732, +3474342601, +3242265320, +4076909099, +4258385544, +2813494117, +837930831, +249012852, +4267886827, +3012543658, +2885922022, +2546885088, +2873663264, +2104689100, +3043603103, +1727701715, +1527566359, +2021285195, +853923682, +1601776501, +1537323330, +3864782999, +1634707762, +2628101842, +3682334223, +531500868, +2249965471, +4023253015, +1396775531, +3400700785, +990984689, +4150109569, +2880104305, +1722217967, +1529229703, +2977166545, +1944579572, +4140284148, +2894291542, +2670872778, +1052986620, +1256528784, +3208561009, +1106595415, +1660227911, +1262912849, +2648045196, +907225341, +2069175786, +2303501909, +4217189804, +4250877671, +4280759246, +3793828201, +3220238174, +3453823961, +2202349049, +154105725, +669884160, +2735732110, +1612371835, +3637165716, +2792594445, +4165140488, +4057719073, +448970477, +2930997281, +3504304141, +76078266, +2895636178, +2754804295, +161221875, +3369697372, +1908781193, +1234242916, +34566267, +1338172967, +1915345325, +3460865100, +725064382, +2310617998, +2326540261, +2493386551, +1218269767, +3284068704, +4178641926, +2618389321, +3676873666, +2171813142, +3431634578, +2519495100, +2289249104, +3018903555, +3885927311, +3471333724, +1461429387, +1775858644, +4182761131, +2689362227, +289868946, +555815918, +1167094243, +650114454, +3210060002, +3524019611, +83955706, +1110148850, +2730747216, +3622483551, +576212994, +3981520799, +1546330989, +2884715884, +3322863329, +2860887719, +3165366072, +1375454844, +1338923403, +2205723429, +2040782351, +1652384314, +681348651, +2607348999, +70510970, +3941035972, +2471511822, +4113378426, +1896136362, +3263853133, +2457342066, +1209090205, +1585596789, +355667979, +3790592385, +3297332770, +664484485, +234938003, +3217017854, +589615710, +2480958624, +552580693, +948786491, +197965089, +3335636823, +1598041325, +1365305971, +640708253, +3064202505, +1869300032, +1535749488, +3200368921, +3573063502, +1097110860, +336354782, +2483127284, +953912137, +3578272246, +2884828291, +2600991933, +1414027328, +4045943680, +1784086928, +2819984730, +1107780363, +1128143179, +636732234, +1205803186, +3830311423, +1729942684, +213769648, +1051667689, +1628813092, +240733154, +279448888, +2042200808, +143969710, +2904964595, +2561127027, +4225400440, +1438481505, +3886109506, +3177068067, +3224818674, +213480066, +2899524783, +2642831213, +5220849, +3004169834, +3406784252, +1767492054, +2146414908, +1310821716, +2905583344, +1172777701, +1973672840, +2791429215, +2989719729, +22737538, +613520387, +3439588231, +4126707069, +4202472767, +2482481949, +3122088206, +1239535014, +2481345226, +528510312, +4039402386, +2936006493, +3756987050, +4191079199, +718727819, +907654619, +1088522230, +1801476214, +1717691184, +3494370575, +1643123996, +249855238, +3622667088, +3380616441, +3950308131, +3758178128, +2334618731, +1066891285, +4045748656, +4292513159, +1404961129, +338530546, +2071787808, +1247190781, +2916068217, +1023311727, +1974533019, +3826556608, +2723922501, +835945731, +3531123024, +2386521540, +3838595928, +3154826415, +616897413, +3526591566, +628562738, +2906363077, +1725708293, +2696647623, +815242900, +3549741924, +2281067671, +1268487497, +4244940167, +1418597659, +1488977888, +796052259, +2935345131, +555798050, +840360737, +252236329, +120420755, +1090533771, +16983157, +3647172663, +4026815419, +3887622047, +621454581, +2862973190, +1234356438, +2111853887, +4196626825, +1018012781, +3772452221, +2672438686, +1871865774, +1056690695, +4012309057, +3263435839, +2103318465, +1584784391, +815195057, +2279845454, +2003013675, +1907738732, +2036562344, +1727215144, +2347324993, +1703275006, +1996550723, +2755419973, +1291679988, +3832798297, +3124328559, +2661399824, +2226020061, +2000621015, +1038151553, +16881353, +2327115439, +3968849475, +3080572551, +1440946974, +3158836783, +4052888457, +2105453117, +772952469, +2934255224, +2120987699, +3646779513, +4026041001, +3681868868, +2141475877, +4286048203, +1373750360, +2086322629, +1755429092, +2364054010, +2449754613, +3819036707, +2732295195, +1410809244, +991111086, +3517342409, +494925338, +1558055924, +724374310, +4266689304, +1977991164, +1871731157, +449642534, +1470426817, +450708433, +3474806685, +1116951386, +1394629698, +3948659857, +2207929480, +3161391161, +2024282236, +1846365440, +3040989520, +3798077976, +3206080669, +113427201, +1162651530, +1854146080, +2510796291, +1147423021, +3749535867, +1101369278, +2285581068, +2331787912, +3112699867, +2192688498, +188206762, +1377049652, +3969104466, +346903321, +4059465978, +2306873777, +1688433202, +3102543393, +98973323, +2309195358, +2544242468, +2632850129, +2013179231, +3587147434, +3898071747, +55299238, +94138685, +3554026983, +3076855938, +2317179824, +3032549583, +905587541, +3785702543, +3744919281, +3150908567, +3918244757, +1655771651, +2796647757, +3901656631, +3042372331, +172594238, +2352955506, +3304263836, +3471985664, +3396936121, +3022674912, +2115246784, +2364634035, +2869133079, +1992949131, +42816507, +1798466902, +3730431613, +2752605872, +3113846125, +1232468123, +58955582, +1017057481, +2306114066, +1223108719, +1819430215, +3352989008, +653893631, +3960963250, +2626964131, +1599136828, +507239730, +2678431883, +3275786863, +2396577458, +1587592677, +1126183079, +342136119, +2528600357, +1769614887, +3970554662, +1843590651, +4243214897, +3237440344, +3857592407, +4164018936, +1737965758, +1024507378, +2798475698, +4023181423, +193124270, +1624836356, +349464871, +1277216793, +2213910090, +3280768999, +2336547754, +3791017403, +2596528658, +4179895454, +3847981053, +1007198738, +1866326261, +624353091, +3171109770, +2218900863, +4063504518, +3066531753, +870976874, +1506382727, +2125589031, +2662671962, +1616219711, +3483738161, +4202403598, +1098253175, +4144080718, +2254471640, +2467198150, +1652062908, +3850727801, +4008845432, +753252493, +1393970727, +2890404448, +642653544, +1403853123, +2844058715, +2817095996, +266265243, +3093354879, +59168634, +374875082, +1142913165, +2989163227, +2087739576, +1846292950, +430536723, +2440477575, +2225848418, +3155819256, +3517245216, +1806127000, +3076628333, +1793759211, +2235700526, +3789985757, +1375793506, +3992601708, +281051104, +756065554, +1859977136, +1851507151, +2683166423, +3715616930, +1069407271, +2648486839, +2994389622, +444946794, +3067682329, +1855321908, +3063042838, +3235448546, +1296709790, +1653983936, +1943213723, +2001513392, +849941959, +2517724738, +3972262104, +1080070512, +4176584460, +1147336519, +3495260868, +1134228864, +4092974699, +4108207586, +2200603062, +3056044010, +40535308, +799206900, +1538803945, +3537375302, +2552874494, +3132043752, +890520775, +1064194921, +2588282356, +3800633163, +4274104570, +2216742089, +1782417719, +3948549862, +1441181290, +2321646972, +2556532088, +3382365594, +1814152693, +2139498607, +1529779873, +2378184202, +2945930372, +516203525, +2944413946, +1733308975, +2212210578, +3080977709, +3710133640, +3453244160, +1393791109, +3284468198, +3420478956, +1255764931, +4078572851, +3459787570, +3755167768, +4108709537, +3338962494, +3117062367, +2680474294, +396668701, +193529478, +3149871866, +1259297548, +1318699516, +1060673250, +250991745, +4041564528, +2608671566, +2408988094, +2390865805, +3621178316, +3008168019, +3109374332, +2708534147, +242046742, +3662627098, +1088522543, +3318081447, +435090776, +634484806, +1402095258, +695752950, +4024050137, +1348842170, +2004122332, +2730609472, +2637182997, +3139924861, +2899821862, +2603511854, +2197892813, +2521701766, +1603301914, +313787101, +2848238398, +3481493700, +611135260, +1845186273, +1353420298, +535591917, +427997301, +2829092376, +1582591810, +1405620579, +4036252795, +2768837036, +1318922640, +788500597, +464430206, +1475859524, +3677098332, +1241981516, +1737701971, +94705548, +3684986005, +3263509577, +1806021626, +1962450569, +1171961048, +3652928825, +1803677046, +3548440221, +2868281680, +2644507898, +888864866, +613145519, +3648829580, +3739101845, +2977085004, +2091925294, +812890899, +2953719729, +1510976860, +681334786, +4267240219, +1454866146, +715185977, +2678293333, +3894027206, +4161893636, +2496420628, +169409569, +3876364417, +1974606807, +1050682684, +2063049220, +1789286993, +1543267393, +2002014655, +2690427820, +1616771703, +3068029361, +1246871634, +3955527145, +4022823011, +2382700982, +1142829837, +4193164707, +428746838, +33699479, +346499672, +2170432689, +507898520, +757843398, +3601650918, +3520796476, +3037448502, +2577411309, +229037415, +3808806159, +1936333285, +3226179528, +3150698150, +1537155637, +1267547975, +2161264921, +100225846, +361618468, +3924681856, +3501184877, +2295547184, +4231322428, +1378651377, +2923697207, +1571052946, +4116309998, +2695310320, +3461722973, +91290826, +1951923152, +1554564830, +4133638839, +3085380253, +2911865643, +4103053769, +1529337327, +1978924775, +1155922327, +722286166, +3140163189, +1602798545, +194650968, +334027145, +4249968797, +2862104972, +2418100014, +3292995758, +3908718919, +1362409842, +909436880, +3313300001, +3455978885, +2610780006, +3025019744, +2369687247, +1819981160, +2797593670, +531866335, +2799381077, +4014390866, +1785132158, +3583388369, +1383415172, +842757831, +3144586563, +476579126, +2690914004, +2815436884, +331566760, +3686577918, +3458479824, +598165823, +1185905171, +2385897187, +3578671481, +3130559476, +2485756643, +2509471276, +3493925324, +2977005389, +285793772, +3750552649, +455370529, +1535488807, +3710527803, +1409667985, +1544145328, +4139867973, +3441868871, +652586784, +1538930748, +1607866306, +2480554227, +339938563, +2276834056, +581464195, +3740791894, +2886087876, +3399169119, +2590812592, +3154608812, +2693109824, +583027342, +2882520098, +3088768831, +3404303893, +2876903629, +574112023, +2985044568, +2982524407, +3034285132, +1186179736, +1752143450, +263628901, +3433999434, +709478379, +3493995213, +2957946720, +2925228496, +344626088, +1462822763, +2244939872, +2622411260, +1148638411, +1059376641, +3806588020, +2672098819, +3137152727, +1754491891, +1543616084, +763034031, +3608640927, +1142805590, +192634961, +2816664904, +421967842, +2192707003, +5466989, +3670734321, +2732244435, +461909929, +1322424724, +810252892, +1811653543, +2088195102, +1002876008, +555177288, +1148209149, +2690801908, +4052223819, +1242549528, +745245967, +1830070819, +2577182974, +2249964177, +332402825, +3212179237, +852635454, +1484791820, +3153323041, +52100584, +3152339932, +3099122265, +1312146473, +192360323, +890267645, +35264041, +2826528526, +176218550, +3630913812, +3559007709, +2089029742, +2485853788, +3573475808, +1245085624, +2091849064, +247737190, +2483402993, +685126191, +842411815, +1182381684, +1347817689, +511717847, +4035744748, +814303696, +237351768, +1136636944, +358982743, +2440619154, +1783132099, +4073095764, +3595208388, +2459525271, +3959967399, +609700355, +3488267302, +466411408, +1324796425, +4077731283, +1593069003, +3004502738, +2174754507, +2322259504, +3810211307, +1370116360, +960869323, +1028094457, +2594629753, +3671622237, +1058466526, +1844596026, +4117222101, +941984048, +1930619712, +1274079829, +2542605674, +144149890, +2437854813, +2183515257, +549578772, +539804838, +3696196179, +1724984246, +772363501, +328939090, +1863147493, +3782382780, +2177586270, +2878092669, +228073533, +4256020665, +1907080446, +3640644831, +1032858832, +2667740207, +202588015, +908321888, +1827071466, +731910062, +1447508040, +1514127579, +2404055796, +330100875, +3006622799, +3375666200, +999442982, +2177555517, +3234765007, +1516623147, +4030449568, +349947679, +4125201867, +1998580954, +4121156500, +482673691, +1381259827, +3977329885, +3189292041, +2339488255, +43826870, +1041196239, +2728779458, +2806878476, +3742203368, +3051314026, +833199208, +978019483, +3963631707, +219491251, +2469264977, +2867259620, +2096106440, +708154761, +853765131, +3188396061, +4000874282, +3765167902, +3766976758, +3525853023, +644661299, +4156853617, +2351146852, +1972661253, +2844631759, +2658114516, +825743799, +2152737909, +1222894206, +28581670, +1574540384, +1062695127, +3862256132, +716463042, +2350120212, +3111649668, +1612313843, +2911871556, +1675499883, +3984482595, +1354456097, +3972538701, +3781110486, +3438165480, +1102801287, +328187810, +1212085751, +471592006, +1328893958, +612057469, +4179611290, +3214977844, +1169542606, +3054478449, +3168549252, +3103412496, +291207821, +1047526180, +1154146323, +476961405, +3380005731, +3410074970, +3390056107, +3990478782, +2834288020, +1386433193, +3952892775, +307254308, +2565364472, +865537976, +380057543, +2570817658, +2616463919, +2231068331, +3219142982, +2223043065, +2583875278, +2290379516, +1967238748, +26640516, +3176385967, +1762477340, +4200070287, +1715552722, +166612344, +1421604132, +364445730, +4209288812, +3573884336, +1271544406, +277809692, +3879697294, +1816738441, +92341008, +3083358859, +3512942846, +1441241989, +3897116442, +2451581909, +2986208801, +3680722876, +2210486764, +3511963040, +323003601, +3753535, +2783425655, +1241624612, +2456697173, +611663803, +2624786342, +2064094191, +3651193443, +509483991, +2707852084, +3935152112, +616744160, +2408397712, +1608455004, +1701094052, +4097132454, +165160910, +3975215784, +3811739047, +4206222294, +3495861102, +2633140154, +4008119342, +4170168680, +1947022167, +2984851762, +2264560731, +3495132144, +4043426969, +254300756, +4171577814, +1816487048, +431942833, +2823505614, +3880837834, +3577882210, +3937178583, +190256347, +1415361984, +79748326, +57798602, +2759512250, +3971246512, +2479378676, +3803561465, +3582709282, +3855617862, +3385719156, +2297900348, +438635613, +1904240036, +1269867838, +2955510883, +3295945165, +3626638515, +4288241783, +3205955229, +3465648650, +1672263461, +279576243, +1033469870, +3012641162, +2523148664, +1033770280, +2453789043, +2571957796, +4047601198, +3968249839, +140753797, +1092399022, +3696258737, +3122148145, +322790497, +3885858708, +2423714240, +3263102841, +3841408376, +3907003288, +3189077896, +1515414571, +2767350326, +3851331804, +1762654176, +311755552, +266280364, +3099101429, +3540441595, +858400940, +3494550023, +3296584411, +494270590, +1121413308, +2403961306, +694768247, +4042061636, +2992502371, +2950124328, +3779015063, +361782229, +2346203612, +3800351376, +1254048278, +3509158051, +3232962766, +59948814, +3885794096, +1693128876, +3512639670, +47527700, +3658858426, +1057602140, +1696266069, +401384488, +2769287646, +3388601813, +2637276885, +1790588740, +2823430431, +1025846056, +1580740390, +1434852411, +3511191973, +3690433645, +4145642678, +15675190, +2473264417, +3798088188, +2640948933, +1330129827, +741632230, +1105070827, +1114311113, +563072149, +873233771, +677485756, +3165796646, +3970270042, +2370235628, +2675720437, +2840325522, +119675196, +2263918001, +2670833757, +4121083389, +1948246652, +1500211988, +2517065, +1248499532, +3250694934, +763372497, +247430468, +193085276, +1895931896, +1861401076, +1729604657, +2823537751, +4218644876, +3856687159, +2825312233, +1070893946, +608836359, +2198035295, +2576702583, +2894306946, +736149592, +4203700213, +2768317502, +673952107, +3650795210, +1892732371, +46231013, +3862305103, +2463217411, +1374739598, +2519785247, +1857939905, +2577388439, +3279157380, +1541765254, +3614468695, +2289295900, +1196876192, +1204567307, +2492715714, +3656632886, +729060106, +190291441, +2480603267, +3032053167, +3987892446, +2479084038, +3083320624, +61708672, +384903402, +1973983801, +212653931, +3382495025, +3229031653, +2447959290, +1537459501, +234500585, +379599349, +2126755578, +168063931, +2022159768, +3242034923, +156822223, +3386119514, +2229900602, +2957594763, +706200667, +648515710, +3303982468, +192192208, +728608237, +3987502541, +3660416178, +3580269426, +1516198246, +2976430980, +3411215582, +1515362558, +51236395, +1219233416, +1697887230, +3330842705, +3014713156, +3718002503, +754507576, +2081533217, +1907276770, +1897501424, +4163128277, +115300738, +2299158534, +3301894420, +2485299437, +3168365947, +3983903341, +940058296, +3848666728, +1437338956, +2437322642, +585966238, +2895633147, +298281734, +970793529, +2714604501, +3893011505, +1645410119, +1930340337, +2519530773, +2390814219, +899912264, +3595876152, +164203321, +2817485280, +1691237152, +3994910276, +3942464483, +2256971397, +3516073408, +1238713034, +2126147732, +2830624908, +1978051010, +2297958610, +605894490, +811114293, +1048433253, +2577415473, +3880000488, +265884060, +2775868623, +1345331417, +411206078, +4015938926, +3274036334, +3860364777, +4019139497, +2517832351, +3314258122, +3782664760, +4275064310, +1470779568, +4086400831, +4200468898, +3533943812, +1995554512, +2202075994, +1162922920, +1025800628, +61464422, +623807249, +2367373693, +2449552654, +984011012, +3757991620, +2402185279, +1825587020, +1655360841, +2496747775, +1484463816, +1684398840, +3210845732, +1214034441, +3758250729, +3432967320, +2757985272, +1631237507, +1623848641, +3528055933, +1481001034, +1767905746, +1328480621, +832104648, +2217187632, +1086817282, +2277856640, +3820307885, +1249977406, +747676289, +3740190922, +2789268521, +1837760063, +1882365922, +2630431294, +324310580, +164160487, +2203329853, +925533837, +1127984902, +2943174864, +3716189633, +1370382166, +2146774645, +1828784587, +1908769026, +1845957244, +727213773, +197711672, +3135257871, +2283552291, +146168301, +3477146533, +716455117, +3044726319, +3293331770, +3375019962, +941012688, +1328705877, +4208016482, +3557230520, +3305260452, +942638831, +2216561954, +2198351701, +334075277, +3095570511, +3881568061, +722677875, +2207023998, +1443953240, +768888878, +2524457910, +1884007599, +498543661, +1218428694, +257862667, +3743406172, +489230306, +41335349, +3380177977, +980374303, +42971781, +72668614, +916188784, +2909038795, +2507973696, +3490384182, +1295761813, +3659824948, +3458361907, +1653430424, +2834151129, +2258503473, +1990677510, +3828791084, +3552551515, +296811476, +3560779996, +3777140492, +3678016569, +3318895044, +281747522, +768187339, +1583265083, +1492215772, +2712869327, +4245528326, +3194913548, +3807612735, +1238802421, +608403781, +2736648343, +4062040765, +1886424145, +3437499712, +4149413278, +286416232, +3973427863, +1534790878, +3096950465, +2442523725, +857833718, +1716287084, +3616629603, +3881483877, +2525931380, +3301136501, +3541629902, +1894662643, +3187829106, +4044922507, +4060861269, +2043228839, +1229439747, +3168337705, +698155569, +3156570180, +2024829500, +731830073, +1383645016, +4176522506, +2487769575, +1952718072, +4114890851, +2584435364, +2936711832, +1502760647, +1292903484, +2348267181, +2586221469, +733965240, +2647755375, +3426857161, +2188540157, +3273081473, +2314206583, +1345164299, +1967411136, +40661835, +1733808951, +2878188249, +1391797727, +3640985056, +1627548509, +1523410345, +2912117082, +2634113575, +3540178494, +2854726165, +3853411024, +3308540798, +3973317449, +3860785075, +2047059310, +1723370999, +3240083356, +2394837864, +1616043483, +2436404767, +393613375, +3561674455, +472369339, +2078546126, +705019416, +2446787209, +2537043752, +2924399203, +3661173745, +3537977525, +1517736734, +1252033732, +254361802, +1288371554, +1665770167, +4151172256, +858412833, +2429732015, +1202658545, +912846648, +2349948623, +3499274075, +972591453, +914569334, +1139163639, +3205324595, +1523935151, +3344228627, +3554576207, +4033228255, +40166711, +2301825405, +1578975235, +2376507566, +2434184865, +1265932785, +1509243532, +3014157016, +1897768785, +1611957702, +2284638551, +4220848871, +1410763253, +925857085, +1190000061, +1863698750, +2466040595, +215066608, +1932373886, +851343400, +2262890905, +3227673184, +261934226, +3617238675, +3252704269, +701673202, +1110230203, +3601069235, +4222849379, +2334434383, +32701353, +521145597, +1407960067, +1098036710, +3031707234, +3134905511, +954557237, +1156421373, +3650768300, +2258626615, +977439374, +33182993, +3768358586, +184890756, +3256395519, +2459840211, +3272664580, +4277178767, +1395727988, +2997041265, +3888004671, +1911109431, +1426665863, +3292851959, +4117272033, +3866154773, +940802546, +2515780528, +3374607710, +506859769, +291776120, +368125450, +1555048383, +2449733576, +745543662, +2216822247, +3749735919, +4060532107, +853865822, +2471899000, +1265474754, +2498694298, +1995053956, +2474183299, +2170796635, +2214548150, +3734798914, +3745723510, +1986988915, +1726048194, +1710421821, +3576780165, +2839164025, +2633704664, +2018518182, +1284698683, +3460673963, +3716306955, +3991189048, +2600339070, +2015141241, +3241819601, +1204011245, +741545022, +3941937473, +574049770, +2638071255, +4170406071, +832998274, +2210898451, +4163786361, +2922994256, +415872293, +4037635731, +2708884547, +1016416710, +3438121629, +1169875466, +4027398161, +1228050410, +2287638968, +4158317292, +1349388777, +2320276240, +2307269469, +1932684273, +2403249517, +1360059137, +3894780727, +2320918367, +4233224173, +853144587, +3186217373, +1681720759, +1667109564, +2704094735, +2661547455, +2838101396, +2465853998, +817416798, +2484593609, +1799893238, +530376255, +2093193091, +1149900754, +963151686, +2458672767, +1397224169, +1373684122, +2722792153, +2514817458, +849323157, +2717572622, +1988596788, +686490963, +1401851016, From 59cb4e7cb590d55d45dc31e048b0c2ce99f94ea6 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 1 Jul 2019 22:35:46 -0700 Subject: [PATCH 099/176] use smaller dataset --- .../generate_random_number_file.cpp | 7 +- .../random_number_dataset.csv | 14000 +++++----------- 2 files changed, 4005 insertions(+), 10002 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp index 30828f0..1a29630 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp @@ -7,14 +7,17 @@ int main() { std::string filename = "random_number_dataset.csv"; std::cout << "Random number file generator outputting to " << filename << std::endl; // initialize random integer generator + // problem 10.7 specifies a max value of 2^32 = 0xFFFFFFFF ~= 4,294,967,296 + // for reasonable test dataset size, we use a smaller range of [0,4300] std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(0, 0xFFFFFFFF); + std::uniform_int_distribution dis(0, 11000); // initialize file stream std::ofstream file; file.open(filename); // write to file line by line - for (int i = 0; i < 10000; i++) { // problem 10.7 specifies 4 billion numbers, for testing speed, we only write 10000 + // problem 10.7 specifies 4 billion numbers, for testing speed, we only write 4000 + for (int i = 0; i < 4000; i++) { file << dis(gen); file << ",\n"; } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv index 0fb3baf..16931c7 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv @@ -1,10000 +1,4000 @@ -1100477961, -1652447454, -261484134, -2043068596, -3185495719, -1415328266, -4163204002, -1446710750, -730564350, -261503084, -2740822988, -368439367, -2878267789, -1433659097, -2816780038, -178988299, -2984306236, -2176298575, -1003010991, -115438597, -3828740510, -4036064970, -2573562654, -1076366297, -2701360747, -1601213147, -1461289407, -1514292940, -2124588553, -331982679, -94360180, -2709747944, -3063467437, -2376733275, -385877409, -2482807055, -1558226881, -1402451769, -3076224094, -3878055095, -2945557773, -1072729608, -2840197615, -2120390509, -1885441359, -122651044, -37557104, -484377594, -1311623039, -638993534, -2452073556, -1847031156, -1325443041, -99818842, -3813017370, -2046404018, -1283225977, -4226783084, -4273948322, -3075667195, -688658636, -249731199, -1976131964, -827922991, -1706528251, -2565732636, -3206793313, -3965700280, -869117897, -429265681, -3379615961, -3706310532, -4285093195, -1392041644, -2030760141, -1719600413, -1404611149, -4112386107, -2663036421, -264189723, -2170647908, -3040339852, -1033038705, -3119270429, -2654116764, -859814000, -3362154321, -2055586902, -3265146807, -1046772581, -290418451, -2503314879, -3819590370, -3971132823, -1113548352, -1737111099, -2334331800, -4231942272, -864382156, -2175275855, -2991934467, -1121718249, -1653733779, -1624875153, -3691658010, -261980518, -3889553252, -3762220972, -1963013312, -2112573856, -4278620648, -4262473123, -4118277281, -1037011621, -2144529746, -3816564830, -3726556684, -4249332106, -2438364091, -4084228912, -4092871188, -3410518180, -3617016315, -2869299304, -1348722556, -2118937090, -1658089200, -694608989, -1518156758, -364418051, -1429049696, -645545457, -3947358566, -3224550883, -2155803382, -977892224, -1556833341, -249886196, -4196699459, -4136132338, -694496419, -2482762920, -4069434394, -69501383, -195194089, -2941932039, -1066509059, -4239453094, -3115665281, -1213168680, -2114008186, -761299643, -3546151950, -427995915, -2731685436, -941267896, -103285609, -999654280, -4130416661, -2648943707, -1307363936, -1158958269, -1524114715, -1130083105, -936664542, -1502118657, -2427818817, -2662546266, -925499947, -3680028276, -3242306099, -2933692873, -185671027, -1858855275, -387784983, -2249192958, -4020397031, -1893246481, -1997403139, -1827818797, -1713169863, -811659426, -3304167040, -909120617, -3930590834, -676732824, -508131858, -1541172880, -2662383628, -1389631668, -1265591278, -2084191894, -3212372503, -3491045396, -2043975856, -3096981178, -576067518, -797423674, -2767990522, -1748027658, -2821488335, -221068738, -1434338358, -3829669489, -952488733, -1080872600, -2676231383, -2242629260, -2438065083, -1260991665, -2531461610, -441431587, -1625674663, -3862688977, -3024716911, -645146459, -912650877, -297023363, -1202469255, -2574076328, -2801282200, -2970253989, -3539175770, -3277919719, -2099233802, -1982407451, -3997141854, -861042050, -3523316086, -3701558277, -2912583572, -2581785373, -2383576584, -1529165601, -3513688815, -3704780959, -3731007407, -2410671624, -3378864391, -4290242254, -3295971986, -3768310062, -923529540, -546698155, -335204403, -1051837899, -340695435, -1605503799, -2734028774, -3658192465, -515852004, -1626001913, -2002912241, -540822551, -1251405574, -3913455310, -1112304761, -1904483295, -2864706392, -1475047497, -1229519579, -2605518176, -1131354398, -2148454618, -1162848047, -396799844, -2373682447, -809552513, -3613502286, -158307807, -763775550, -434535862, -1395395872, -1755676835, -3088085656, -44534804, -2589729491, -3791161892, -1234335687, -4020565241, -2174078619, -814281428, -2410782751, -1314702019, -516448281, -1296152045, -1073752572, -369088688, -4153591698, -833899074, -569140254, -467164613, -3285420507, -2576814287, -386707535, -687610484, -2514033411, -3762704068, -1165096289, -1087068193, -1339517559, -4127016471, -2804116074, -3172089071, -1941716621, -276472791, -1920669284, -1113510775, -571879707, -3624210036, -354047770, -1786475538, -546839479, -2155381648, -3504211849, -953727281, -2485187088, -1854283937, -3074096956, -2105589714, -2781260887, -3432495676, -278553706, -4115755020, -1470439850, -818528879, -108374485, -2416244887, -363292977, -1888056832, -3195701016, -3058623217, -298048593, -325882732, -2046541899, -2087863575, -4283401375, -3345087278, -4280427815, -1850570291, -745921044, -2809865779, -2859658071, -1080967201, -599342624, -940395135, -2859226690, -4013248248, -4204764808, -2309952594, -1633614237, -3241210163, -735717174, -1873949585, -2940779254, -130665750, -3176258097, -129378850, -3458902572, -1935380199, -1122262229, -591533090, -2684976106, -3579346406, -2529988356, -2844338265, -2360176405, -1808165549, -3773074109, -2691419739, -4194639224, -2642668314, -3890649289, -2332989576, -3990915977, -4002944292, -1267834141, -1121067284, -951391947, -2103414253, -889528141, -551933343, -2248836399, -2897492091, -3951876289, -1600111674, -3201256854, -2489588509, -1234656274, -3120216706, -2009532528, -1903384728, -1024466378, -1603218767, -3160297921, -3900948751, -293424763, -210355672, -1138233373, -2414734655, -4255181124, -3157200213, -1149988917, -2758082382, -1773681037, -1600083343, -492800729, -4016574088, -624497732, -2811368363, -924823715, -2294913707, -3013761916, -1052076323, -389724638, -3691766901, -461922126, -1360247690, -1325817345, -4033579655, -1200553239, -3259232220, -1215489410, -3874448292, -831394595, -1472925473, -2323748845, -3014048734, -136715974, -1824563568, -2872414721, -2079873803, -1028489994, -2813653065, -133768880, -3975444049, -2873992997, -385052527, -1671605681, -588562433, -3398741399, -2898108987, -444206860, -2191591564, -3513058319, -2072928231, -214047629, -2736540647, -2228752268, -464595745, -295594618, -3437542488, -3205272179, -493441210, -1253505611, -1847693502, -1275549209, -3537699366, -1779350630, -2017485618, -3358615723, -3096605876, -1555627925, -3120500152, -758892650, -3880505048, -2238549237, -3969773615, -610150672, -1741463243, -2494382326, -1899611690, -2239814447, -3417436151, -965185602, -2172588487, -1158244281, -526601389, -1814081341, -3819586186, -1600964092, -2067121412, -2036102405, -1371712524, -1230053635, -133390221, -639575804, -2636211606, -2140580237, -587159908, -3794595710, -2005080328, -3666459989, -1249457687, -931876231, -815421747, -414189862, -3744958524, -3339720737, -3565630865, -977940003, -2163439514, -4256872083, -1152564722, -903529089, -3943002628, -144477906, -3182424014, -4274006488, -3687575103, -31685662, -2607111813, -1319546868, -2414011043, -3727291623, -771854470, -2833714688, -3454448216, -846908794, -3967278929, -3246736270, -3730870637, -2198135185, -3021925943, -440827932, -1570738994, -2004102768, -541597714, -4222695306, -445444421, -3511296416, -2809352018, -355983627, -1604238547, -189517530, -2677680363, -3808675282, -1497058862, -3666225849, -3639959291, -1043143072, -3124661061, -327304642, -308157398, -1111886464, -3945372781, -594327217, -841061704, -820589698, -1842795227, -1610366167, -630601318, -1761901230, -1820014881, -1943262146, -525753968, -3102769544, -868144579, -1780087880, -45862275, -357788301, -2344893857, -892288804, -3788659795, -3210994637, -2470810555, -3860658815, -2910538762, -1468683069, -2031421600, -2567822684, -2327177804, -2732479849, -3057793225, -2810866284, -3197002260, -2845735913, -4077751180, -280089851, -4263718325, -4127821354, -197698242, -2232735225, -4098411646, -3258522809, -3242124996, -1795452577, -3797792817, -338202178, -3003560638, -2913238850, -848849110, -2914836538, -3114979352, -528798042, -683329003, -1504700481, -3909292477, -1983892074, -4188173442, -374291470, -4228791656, -4112489926, -1906373083, -1408659822, -864892524, -3323037615, -2421802036, -3678895195, -2850712563, -1446400572, -3620348608, -368451183, -596994593, -1162335617, -2756359957, -3411820436, -4013174286, -2815328888, -2892683858, -1629606863, -2127298000, -3705582288, -2802813393, -1983302423, -2530690582, -698202753, -1456195446, -3927207445, -1635533332, -979932588, -3259827511, -2577526013, -1192814668, -4118375256, -2006116752, -1227179469, -3986873523, -1966898758, -1718164012, -2182307026, -4260080772, -3738289684, -2505263416, -2805471991, -687185054, -294010524, -3159922046, -428014191, -3495813308, -3167526219, -3385519339, -2293855526, -2235419650, -2656103854, -1922926052, -2015233494, -2419225081, -421166411, -3936757637, -2256374172, -3597208409, -3786539583, -470843535, -622747246, -2022496941, -3584730260, -181477613, -1894738132, -1661584751, -4177023093, -2179535391, -1072488843, -1690895848, -2855679964, -301436382, -2290321534, -2211905997, -4002729323, -493459033, -3428447741, -3362391866, -805064919, -3437788837, -1047471401, -1487998798, -4260951328, -2443265101, -739246734, -2830727425, -1335776638, -1948685945, -67477937, -2093401757, -3829003920, -2262610104, -3419329602, -2557272072, -2086911732, -1300327415, -1437831113, -18521712, -764037321, -3694883618, -938829537, -1456677762, -1150457278, -1665418679, -1046938575, -2305353445, -3628641180, -1947185301, -3471600308, -2284513489, -3354237916, -3997593012, -124393372, -711042703, -242717072, -4221335992, -554340229, -2329882317, -617150908, -1593806206, -18277787, -1956805855, -731963339, -3932081507, -1345684139, -802398280, -1467324946, -845690797, -1937838721, -3097877896, -2087266853, -4210998569, -1760654746, -2730689541, -3580661838, -2902214190, -52087673, -3589698862, -285547768, -2150572806, -1586001777, -3136389534, -2740245901, -2248666844, -619512847, -828884843, -672579383, -3204291231, -1122857041, -1728386544, -615252700, -3343927776, -2127110698, -4050816467, -2433333445, -378747301, -3670398947, -2056662657, -348286869, -935681822, -614758827, -1289263739, -3089752674, -3799398902, -3727555305, -1704346301, -298943673, -4257212552, -2053109412, -2887416849, -266044935, -2152851584, -4268753166, -918084747, -919716001, -4067968448, -3733105257, -2112298691, -483010191, -66548301, -4262638676, -3536017313, -1061460878, -3405340082, -3085424017, -492091276, -2977758083, -3821764126, -1688862353, -1700395542, -1424483227, -536499827, -417790448, -2032178806, -729858102, -130839018, -4022505267, -2114377967, -2289262819, -1950218216, -2346979874, -1607760380, -579312231, -2232791197, -131940104, -159776084, -1701984394, -503244241, -114369590, -2738784629, -2674067195, -2317045283, -2760887389, -1657850868, -92181800, -4157752509, -3735373046, -3695470145, -3940277616, -3121553026, -3424670392, -3054021267, -2183132308, -1864271308, -1214414834, -1812805328, -2529052271, -554030053, -4023548879, -1588470569, -2498376000, -3807192887, -2786655072, -1085418282, -4262779677, -5261501, -564256658, -3640994542, -1585603230, -2465642404, -2101884962, -1374932429, -1887900214, -570777568, -2758706488, -3158664926, -1601822439, -3899215867, -8697684, -3375055132, -1325796286, -3417713083, -4810724, -2470631868, -2597747716, -1617278807, -377657170, -3271643040, -2023976461, -3294395028, -1716997834, -1668981780, -2573253033, -753457411, -4258295929, -1777816792, -2566096308, -633042035, -356276037, -3733325936, -871858868, -137759775, -341833648, -3485622992, -3442166613, -1080202412, -1930775198, -3712456985, -1561044305, -111177341, -938639632, -3524172332, -1748855567, -2330499534, -4272848935, -3015438805, -682835942, -1903064304, -3718928678, -1195048982, -1909543434, -478474930, -1073815656, -3839319088, -799156186, -324807884, -3183913807, -3826212419, -4002170049, -2365998048, -3671348598, -352874165, -3958194971, -1087535235, -425211937, -3184203172, -2077027403, -1757840753, -3904765139, -1402602627, -3348940242, -194866035, -1176314932, -1184807345, -2013834647, -2708078553, -1741110078, -2409902889, -3722507255, -1817244845, -2172650439, -4086137111, -2732593466, -3911559517, -3560472021, -2698905384, -2224848123, -2667656595, -3100031357, -293780692, -4064617208, -403130335, -1645079675, -2563952613, -1343914963, -1976069105, -1802787023, -774054175, -910553636, -418893345, -3952358974, -1370203969, -791330361, -4078945448, -537068381, -3067615516, -313709990, -2730801674, -2871206887, -1171875039, -495701927, -601984839, -1035433859, -280534258, -873262776, -3180178852, -1020129568, -1636625570, -258313174, -1558966360, -2580927606, -118636989, -4068515941, -2032183897, -2548423316, -319108692, -4062657815, -1370052647, -136695614, -1698423923, -3781508914, -673559700, -2250884038, -3070512168, -3733817528, -2086992897, -732075959, -2959213244, -3997279996, -3567269766, -3585762129, -347249942, -2441528689, -3689189168, -2476305494, -3210492836, -1009558915, -3754901299, -1515019454, -1963924631, -182332456, -720178696, -635649861, -3753518674, -3515470916, -3641610373, -3788185525, -2348421884, -2049586115, -653508392, -2887690296, -743808278, -224863788, -909961687, -307126486, -2384763494, -1406040129, -1176371372, -128128391, -496536816, -1860822996, -3229693382, -2905092037, -2267228598, -2942957921, -3960238250, -1389296967, -49560547, -2090356096, -1997504540, -603063405, -3483367731, -1553676756, -2877216557, -3886718689, -2610435607, -2404536915, -2276264572, -3402526813, -3845978482, -3414129419, -3426649715, -1612816563, -1608431968, -3045166844, -1765702171, -2137266180, -1414161105, -2201765677, -3251084917, -1765963702, -3632970778, -3119844018, -1350036907, -4165990122, -4131235046, -985583036, -3914305805, -2538270691, -2157320528, -306196584, -1902466710, -1608269814, -3700704139, -946645513, -3937670308, -35755427, -3189293145, -4217664567, -1537413726, -1280605392, -1816677002, -4036771029, -1656854440, -1398499835, -441217715, -979952659, -1271257877, -1453317881, -2781820202, -1154657516, -2281094918, -1222215689, -3101797106, -1082210451, -270226943, -1375087978, -797465007, -516188918, -1539145923, -1320019855, -4978551, -3789849181, -1889936969, -2815113438, -2916168015, -2076124577, -732523638, -2553233428, -4144186783, -1910042420, -1836783796, -943835896, -2227856747, -3484987967, -4140615684, -2183598827, -3041722633, -2498157394, -947960916, -2816282682, -2513648706, -2049235715, -3823665866, -4021277586, -2916250138, -2109878531, -3432119548, -52070157, -4030102455, -3490635850, -372438898, -657494970, -1432906923, -624032612, -2335170251, -549015303, -3689275516, -1575263227, -3978281598, -1347400517, -2506605980, -2748998402, -419215418, -1730748129, -240841351, -2520820771, -1110160692, -3832983500, -1792001248, -209699462, -1068784372, -2513832910, -2472975326, -3862626180, -3763486900, -2195265539, -640214093, -59268889, -2259612719, -1395926952, -2260117136, -148568109, -3572662460, -3527476851, -820792683, -594998116, -764158142, -2803188491, -2730059605, -3883743244, -257599662, -3744060678, -1199811128, -4066330626, -3391539845, -403890121, -3827300395, -512300758, -2178195985, -3380751517, -1863050246, -987943570, -2757138182, -3287728377, -1955702052, -4278012739, -21588380, -3994308784, -4191606290, -3473323247, -3606058838, -3745038267, -1252288952, -1507647838, -617869192, -1428328510, -1431947837, -371133934, -27826984, -693422369, -3604325296, -1202030845, -2588200577, -2799274763, -1828215684, -1415365014, -3152407125, -1723452389, -23135442, -150445909, -1341813429, -4122505495, -3097279159, -3599681468, -2257875100, -1180406661, -1700848536, -708756741, -4238522873, -2455489582, -1822238251, -1541800222, -3253278462, -3559223336, -3402862056, -3772765002, -1260094484, -1120336500, -2844466414, -3568607964, -1029723906, -1222684859, -901431419, -2594098572, -2482981902, -3417714382, -1582336953, -2564702065, -3244548075, -3556428286, -1954950407, -3055510545, -3377706707, -901805244, -4005900388, -3627593026, -717281539, -898051759, -3351280413, -1468687338, -2893743698, -1683551698, -786542946, -2136454516, -3871903477, -291689967, -1455750362, -2308692589, -2189186394, -102839566, -2454730837, -4067402683, -394688145, -2297443642, -1167095672, -3236132229, -3980651712, -1291587911, -1959277531, -1634276986, -2533013494, -1348352163, -1260919943, -3940120091, -937578653, -4029799196, -897499142, -2641854074, -2322130115, -217979351, -1726032628, -2701453091, -2138290324, -1072656096, -1657252388, -3384924480, -4217375993, -2624297726, -1294510064, -1711573819, -151724351, -3279957615, -2984281846, -1014700065, -2877058063, -573720131, -1649307821, -2603286234, -1007093384, -2999113663, -3445866147, -1374959985, -2562270616, -1049130739, -1459339110, -2379711151, -1480920874, -88613397, -4097175379, -2955150179, -245044659, -415309236, -3287130266, -2717150600, -2930177297, -1647774977, -189669541, -3174701556, -1228580493, -415434019, -4033704252, -102249328, -4204817199, -3490015028, -3964086009, -1945355979, -1758956116, -499246347, -1117228429, -1552736690, -38418607, -481217935, -702854008, -414599670, -3703831422, -2052137218, -746082730, -1012097084, -4186762192, -3141532996, -2022045413, -1229475059, -4072865372, -1048469527, -1608800790, -3782868249, -3860960238, -950382025, -3435924663, -624427061, -1392862390, -3683568489, -3168282847, -3124486916, -3875107231, -3236843779, -92552558, -1831758483, -2373233416, -2345255358, -3994849384, -2899446292, -1013488149, -2168560622, -2261482024, -2847266222, -3617301802, -3498490227, -623629465, -3254791063, -368295207, -1058033477, -2434882212, -3733042773, -1442482357, -1913215435, -469561516, -1062460748, -2283008489, -911320698, -50434975, -2018202429, -1776879206, -1077043930, -1997826194, -4194466282, -1934484524, -2062758040, -926278095, -238809559, -592949955, -57732052, -1909484223, -87235467, -1289246333, -190218592, -1076693778, -3481872090, -4020283460, -4148270874, -3817697380, -925536312, -4290718634, -2195652916, -1680876293, -2386549150, -1685154969, -4033780275, -1167903010, -827326580, -1319169596, -785262769, -3976922191, -1827759857, -1657642246, -775174001, -2379674328, -3448993953, -3027005059, -2494280294, -3263909724, -2055499077, -1437966835, -1388060172, -2445825012, -3469696631, -1998404231, -585893851, -555126719, -4127215590, -2077295444, -3337815535, -1676091305, -3141424812, -492370617, -1191283100, -309905693, -2249219203, -4261866512, -4184772860, -836081564, -3326499154, -2035959201, -3172407176, -507241902, -2091118684, -282226227, -376482378, -1336566118, -2547473318, -3141376431, -1527201929, -3586008643, -4248486855, -2793172069, -3360483446, -201253621, -2593449810, -2908786941, -3356710640, -2637843974, -2046237573, -2132642421, -3758053715, -2963943148, -924749233, -2142665169, -209265752, -545248544, -2044337699, -65369576, -3875397090, -1964393981, -68348216, -3528823521, -1925570326, -3692806667, -4268310210, -1632876196, -3986674531, -1875625548, -3675237448, -592790419, -2376297115, -923227905, -283735878, -4135297664, -1896478116, -2171265775, -723340878, -1360589043, -332959425, -1824485229, -3737677120, -2058736302, -500829737, -2126262423, -2544054663, -4283741137, -3777299709, -1889408145, -1672880265, -2883523464, -2056153174, -986268717, -3644372299, -2827658053, -2158083446, -15564445, -2535545166, -622936534, -129314201, -3004687832, -53142571, -923440636, -3032886354, -1516117474, -3920066126, -1490108959, -2397654544, -1654466328, -4119120978, -3452426113, -3961379047, -3525579801, -1281104420, -4026989000, -542640048, -3368165392, -1039413342, -2019136552, -2957356908, -3177198653, -4284160228, -1682487905, -1809783659, -3568096657, -1693772460, -676891460, -2188530525, -1585438738, -597028429, -1153085642, -1546291214, -3228636959, -816087409, -4222601802, -401094015, -2817674838, -4100028223, -1422478640, -2978272690, -1938244805, -1161187558, -61027466, -1403522304, -3666205882, -473514363, -356227588, -261707726, -3716730487, -385217135, -2163230649, -3785474342, -2093406481, -1815822903, -667041695, -1806325032, -1612782919, -3414268076, -1714141677, -1286746009, -1004448141, -1045472724, -4080569371, -926094048, -3015195455, -1258720382, -2482448823, -2393989511, -1527671251, -3912602466, -1423815659, -1010718492, -3463922812, -1729647716, -3042393847, -4261455546, -3598400699, -298910127, -1980451691, -3783279655, -309648181, -3719953652, -2343971400, -3009972327, -3059354524, -2423540965, -1367824992, -620174833, -920108238, -2715864011, -1904443624, -4217766335, -1669808146, -3324004708, -1713365462, -396757692, -1295674983, -523668663, -1951392926, -3106326720, -887140647, -3301951115, -1859573175, -2324669973, -1309366934, -2312009888, -2119618546, -1556450017, -3392716799, -1332652814, -182014613, -1912967756, -1022766733, -626038364, -1034104314, -2776586017, -909043005, -544570737, -275086469, -2644327885, -2260191539, -2297695336, -2097286966, -1701540232, -3320693960, -190925030, -1180509695, -178385005, -3011393526, -2099340471, -3763994108, -1217144911, -1052617616, -3209562727, -2651173807, -239447057, -857387186, -2868194111, -2787329429, -710630747, -2076742785, -3551739286, -1729697057, -1356324665, -2390712621, -2524086497, -2811019523, -1406294923, -4253323928, -2744097642, -3579752195, -4247790245, -4222347284, -3789569241, -3688660572, -2822092252, -2239882729, -4168900778, -1083781148, -1075800624, -523037724, -3529529633, -3334052780, -746728231, -2358590705, -3728713157, -1879558574, -1979494459, -592669285, -440178039, -2979621945, -529169341, -2090371135, -17563637, -1805813280, -220126971, -2883321614, -978656008, -762051047, -2457225121, -2097854792, -2658661638, -1125308043, -3099800977, -35095312, -1067797948, -2013433153, -1959965418, -2623276693, -1441188255, -1691663408, -3642462087, -600629275, -1713190139, -1412366224, -2472681023, -1479145861, -3324195445, -3850638836, -2162234845, -3900815097, -1045349168, -2072887955, -272774208, -2896962162, -4037618723, -4184021101, -3706555990, -3480681221, -3577887557, -3853894432, -2553318342, -997871267, -3172627259, -4292745116, -2327797389, -1161637957, -3451472150, -1422598209, -2441602833, -2066964897, -1942449379, -1200182984, -1325693707, -150563344, -1569570223, -1131330846, -2096583821, -2988726996, -3916424799, -3322150213, -595116720, -1315604657, -4026743091, -2862124912, -1487363233, -606340746, -1099523966, -374404433, -1884071575, -3328489351, -2253223404, -2184227544, -2538100554, -844415650, -535537293, -2878256899, -3105622633, -4016877409, -3949005175, -1283604958, -1964624279, -1948869416, -2256669689, -774456919, -872343482, -3455311309, -2766529227, -3640795941, -2171013626, -2089870265, -787375263, -1424309793, -1847957289, -344730753, -1138067950, -4191114938, -2103424281, -3525038937, -3689602067, -3787232318, -1207173233, -1814942202, -366649596, -407766723, -1450528105, -1020840312, -2576274433, -4081074553, -3179005706, -141974084, -1455499875, -3114300549, -2004267390, -1468323310, -572260527, -3501711479, -2103447988, -1561422014, -2456033591, -2009777577, -2780213342, -2458246283, -666216999, -2657929723, -3505603173, -1113997000, -411414739, -2000362759, -1323891937, -1651662633, -1566518528, -3668170472, -187126308, -3609142216, -3119490764, -1677491075, -1747814303, -3744219173, -1553455080, -4033376596, -168414922, -689847932, -2526747567, -3255381273, -399489109, -3830015464, -3127933250, -4023191609, -2722615975, -3220816294, -1646960830, -3011262966, -956286999, -335742972, -1000236799, -2331976191, -2948927431, -1913842809, -1309379240, -1673236813, -2882627887, -2001453179, -278095361, -994610331, -2616598818, -2788805868, -1327458628, -3354778386, -1259691130, -2953749683, -793580012, -936441666, -3713326121, -1355840525, -187486831, -949760604, -2201713231, -4233645152, -1617802100, -2771156761, -3060779451, -4035557207, -1487549576, -418737239, -3996905485, -58831600, -4261022404, -2619418698, -1197902288, -152771830, -1052466214, -3590129876, -1588303738, -3688163943, -557207091, -2863172917, -1298087960, -261412442, -696891502, -1999222860, -2289925773, -502211990, -2681973422, -3682395882, -2219948771, -3436493419, -2540908608, -2078133099, -98949299, -1146526372, -2006374691, -3023723724, -772733292, -1495525355, -3363606686, -3258711345, -2527726040, -1116171522, -2392972998, -1540937420, -913510311, -3461893028, -76120672, -114260154, -1629647802, -1407336088, -339309569, -1287331274, -1036991486, -449464721, -3056437492, -69339002, -3320268047, -3518875565, -637136043, -889949584, -2281356907, -2060153192, -372036105, -4125028312, -1214254000, -777264710, -2092742012, -3633893648, -220206831, -4124657149, -3309281630, -702993371, -2242589997, -668122868, -4016155200, -2259559111, -3874432580, -1434172496, -894526109, -2111575069, -3228853558, -3283623641, -1339589927, -3942641574, -1313734864, -1564997354, -1715623078, -4252866465, -1853419771, -2513125109, -1214650404, -3618919898, -1158415075, -474489959, -3640392258, -2221085032, -3580034523, -1351338046, -2992238146, -3209675681, -1119337171, -125603417, -2584954807, -910412895, -2964881762, -3994793562, -3851341008, -653639808, -581239235, -3014812555, -1290782212, -3064306558, -3131579914, -2362007164, -1791029204, -2628416487, -771197443, -3126779854, -1521598320, -3150685, -3489499686, -3974231778, -3827439487, -1325536439, -2391160040, -227880907, -2160301719, -3916725093, -611352994, -3816190234, -1145139137, -3441631481, -4160040127, -3335877543, -1253663447, -3964072020, -3242743957, -3080747936, -2671062157, -972824689, -906673910, -1623439960, -964007411, -2915163886, -3336991037, -1638701934, -3745305608, -3812379427, -3796059501, -1563657872, -3443883711, -1628346333, -3512393071, -3153367890, -2433416217, -3154068367, -1776231125, -980137234, -979640661, -3821144439, -1266066248, -269090125, -33468173, -1914405001, -3668346476, -2220825414, -1550232936, -2842698232, -622021626, -2346567185, -3244082887, -2075527555, -1818279504, -2887223007, -1345577382, -1187242913, -2625173385, -1556500069, -1607421417, -3401973396, -3935799759, -3971096720, -4038171040, -3973837181, -3535134941, -454761418, -3957617411, -1803968429, -2879981383, -4157403029, -2900796887, -1736280615, -3151425786, -4190249162, -541861393, -3764530007, -2493610803, -3039657572, -2469539889, -864025230, -3248486462, -3664368109, -2850231001, -3364072091, -569089842, -1280270250, -2342867346, -410679879, -1639387520, -1065019655, -2558946824, -3106511539, -664803662, -556348623, -100008068, -1826990018, -2926546543, -3348095021, -2863636025, -1602738277, -93727769, -257041616, -2355875134, -3278340502, -373873734, -459483264, -3369696605, -267915872, -7050950, -4027566807, -3261225172, -948305259, -3150377874, -1020401916, -872659362, -425724597, -4205087973, -500932251, -2662413213, -4090157473, -1679837495, -102519786, -1583158285, -3359675019, -577339934, -2817292105, -2539222634, -1492084740, -1588944754, -1048546404, -2129866805, -364041357, -3042490088, -2355956807, -4260204628, -1616199280, -4015724585, -3689342933, -317528038, -2370330302, -3935387584, -2399240632, -1538465836, -78332063, -2006697374, -2276676374, -2627526318, -3998233052, -1335152329, -3130205761, -1718019280, -3771954281, -785526812, -2155494559, -3526413386, -408957849, -4191065565, -3577491056, -692490339, -3698621409, -1944977003, -339554211, -2903158757, -73825907, -3875786068, -2596799095, -1180983091, -778291380, -1987220295, -3167438240, -3847084376, -2208858712, -1680529536, -1686311275, -920330783, -2906620438, -2834166539, -4274103793, -1841229748, -351925431, -4183228609, -1519415293, -276416018, -804366570, -3091392721, -2416723415, -3515335600, -3042812855, -1540934528, -1177764024, -414196005, -3003446217, -4048979643, -1705381317, -2453872879, -3967495451, -2248952415, -3423424811, -379971375, -2460631935, -2858735649, -913672914, -1552117052, -2243841016, -3244881292, -2355588772, -2106676445, -981720240, -3224895953, -1485354957, -813428518, -713552012, -231057539, -2063268450, -1871638116, -567068490, -3794709912, -2196615332, -3711225008, -2066038198, -4012972330, -3793443380, -1821612492, -124836926, -2479913836, -3310888413, -1850470061, -52736473, -2231228956, -4140064151, -4032420400, -2843207744, -1772359260, -2648216245, -432665726, -1207670435, -1641644844, -1322511400, -2697782233, -2614345185, -4171741943, -3912931074, -3490674694, -495637699, -2654983610, -1225191761, -330286241, -2138237595, -2707550144, -1514571849, -3428847342, -3886156678, -2042350527, -132001348, -3766548042, -2990547561, -2778928690, -3618041819, -3600276922, -2103430396, -2549722258, -1259598646, -154484430, -1429488206, -1883348320, -3747369265, -1626253677, -367048578, -3821976932, -3850148265, -1218571943, -231084299, -294086635, -3604134202, -2264557085, -2091907136, -1128867323, -765856474, -200409129, -833420419, -3442146752, -1440499778, -3380254514, -2603687545, -3363101652, -2042065153, -128538554, -3075297222, -3271950827, -3232492156, -598737200, -118667069, -4255560726, -1541848898, -572055172, -966921258, -2882098212, -393119297, -1930282433, -3053868808, -2837035301, -448792396, -866538454, -1863895787, -3229007047, -4269126372, -1131921062, -4189746634, -1424945658, -3785678737, -1881122857, -929617011, -3483344218, -3819727242, -930802970, -1501532009, -3928762672, -3448242647, -4018704339, -2208814277, -1599394234, -1644806366, -3024040675, -3803355898, -1947051164, -3778702441, -613516806, -479470006, -750638766, -3752246943, -674022688, -2974348888, -3070399844, -3410061180, -3192856410, -525482207, -3244987659, -655513932, -4269427578, -1107626098, -3462176981, -2386810385, -1900477461, -2559402825, -2022569871, -2518070030, -3097098423, -62392632, -2020595019, -818090333, -2501779736, -2856035513, -1597254193, -166563193, -3465907161, -2222686010, -1789304375, -4044258651, -3470640423, -3614078725, -4079838075, -1043783087, -2155460641, -3431555170, -1498169946, -357359885, -750369444, -382936757, -1564059720, -2645623506, -3556871433, -311017218, -2339209252, -281643470, -2968109067, -3203092270, -3011633907, -2832121530, -4131887833, -3359247683, -206938627, -804067163, -525612534, -2374276190, -3803510965, -2638369376, -209284489, -1781171373, -3211130217, -188792167, -468224946, -251294318, -2251265798, -1505076809, -3452783668, -2094020836, -4144219284, -1781427583, -922757649, -3030577646, -1129416461, -3486757158, -40017713, -4163566765, -2301353686, -3489186427, -2211057869, -1304941517, -1095306195, -363783691, -1783471970, -4253100042, -4016283924, -19184552, -2412907439, -3045141511, -2331762125, -1666990412, -2792367896, -2489217449, -395472153, -3158857321, -52867816, -4013986987, -3302880560, -1807914306, -575278383, -2880418197, -2967635718, -2109101876, -69558262, -250249823, -1743647656, -3870167971, -1058646850, -2603808313, -1805809186, -1048389518, -1156778606, -3098860366, -3217973153, -85274015, -1433085134, -1815766306, -168514016, -3286395163, -3031532535, -1595151738, -2361155649, -1972300711, -1215602895, -4196789885, -2288173234, -1271059839, -1729181936, -1030759003, -1306511490, -851351339, -2493384474, -3834551328, -135383113, -1206987371, -4002350345, -1674586212, -968582860, -3256748619, -3451707229, -1561243888, -1274436645, -332986295, -2961170682, -93622602, -1507046096, -3019551451, -3974375195, -2058693038, -1099722135, -2387450422, -3356254905, -3689667958, -3941956665, -440806846, -841483930, -2442875374, -1764926784, -1776788282, -3286219268, -3287980534, -2183948269, -3848947906, -3550483087, -2915051878, -4231066587, -4044154333, -1699301151, -3115111466, -1810747989, -4106728488, -4093553431, -3726277810, -203637395, -2063256838, -3854564601, -4193874718, -155234961, -1881696225, -4168020314, -2771568799, -3332887654, -2269145124, -3490816260, -1647083786, -3025379184, -1420309799, -4001913823, -1234737729, -2442157418, -2815573157, -2189836365, -821601888, -2564624396, -2924921640, -2444439585, -2779221976, -4076443707, -2933926588, -2371108822, -3319725460, -2852222467, -2162552234, -1133216917, -1762723493, -1668842632, -762530537, -1985075710, -2546042909, -1728706466, -3096059046, -922896705, -1514789016, -1676016009, -2731756601, -3760381800, -2552293955, -4272303684, -3862757312, -2544396306, -1371111388, -2289814235, -2551425225, -1992865385, -3850029496, -2671869639, -1834719354, -3883573567, -73700055, -2308321547, -802733803, -4220910422, -2830360698, -944244630, -640764838, -1670645326, -2702215071, -1410225071, -1790685250, -3500972294, -1958821871, -1318743367, -1265537910, -3401337310, -242526498, -4035450412, -3811432283, -1562300297, -1223997383, -655743585, -62564477, -1105577720, -95219368, -498277737, -537876443, -3286184934, -3939826814, -461733154, -497187737, -79285565, -2849115301, -383172291, -3532113797, -3422510345, -3050086593, -2118793167, -3884086653, -2664680487, -4061148955, -629686310, -919293573, -1017898491, -1880021629, -1420600976, -3049788713, -1739756481, -2846030221, -4089207660, -957718557, -2489155124, -2361217238, -1618458451, -71763243, -1095171065, -3862687978, -4216853909, -2397817458, -3829229955, -3331722764, -763321295, -874935994, -3374217393, -1454304080, -1714857285, -2458581515, -2923668705, -1945332996, -478623729, -2160995609, -1096902572, -337460339, -3596748957, -1885176932, -1377529844, -3856365948, -45646856, -1892976418, -2583307098, -1063524656, -1258783073, -613080550, -1503576230, -1488234818, -1105498300, -3537181703, -3057400431, -1968432797, -973228902, -3842393819, -4227069197, -2705867245, -2436409534, -1273594104, -106969948, -2202208105, -3260667779, -2233216708, -721400718, -3430831540, -2366077967, -3594924931, -2978170685, -1734840850, -764824032, -965679432, -4272775956, -487301963, -2182776304, -1995050449, -2169125622, -1091840309, -1866156853, -326205817, -556191742, -2818056970, -1464698819, -186381141, -168186377, -4113803727, -341004733, -3074086912, -2514495684, -2928964045, -1295428968, -186681969, -615398967, -1484016861, -844167118, -792743778, -2728299784, -2122261482, -3563590722, -2559350205, -1787451796, -1792768203, -136224049, -2861264174, -2259432420, -3949588364, -2471502081, -1042011362, -1249704663, -2278362778, -3787109205, -3201311912, -2695286850, -3102049185, -1158948507, -290963711, -3555969700, -960431654, -1809292230, -1059132908, -1706537920, -2631241926, -492375152, -471237026, -241855662, -1058192440, -1447702081, -3344997962, -1492440726, -3365032201, -3231032725, -357920920, -3068940600, -1916685014, -1903694476, -1014523620, -1297150215, -2190978461, -3788335335, -3608083049, -2574780017, -3269492247, -1899854983, -432335894, -2399169334, -2369324473, -4136701876, -1751099535, -1623170712, -2401294730, -1892592008, -1498613048, -3566844776, -2320665356, -4378750, -1306302166, -3842708184, -1953307179, -391199737, -2939878237, -4269858439, -1749277299, -629424145, -445107622, -664794548, -3933049614, -4158403274, -4204380623, -1310893339, -161974089, -1520870339, -20592842, -433666340, -4232055490, -1043263539, -921974549, -983641400, -3121212039, -1483809317, -2044793045, -1929561519, -2462631808, -3661740196, -4256082238, -298330599, -1295997719, -2576131758, -1553723678, -3186970706, -1961012529, -2795162325, -1631043893, -2380693120, -1835326847, -3103598452, -1037664598, -2405076661, -3118149105, -333680825, -2908483425, -3943688391, -3857788029, -1403517573, -2892650226, -1440653112, -1641591707, -4126476341, -963881657, -3176998148, -2160634532, -4259379393, -756399398, -3239049332, -1772005056, -2667366336, -1886912467, -3534133800, -3818751115, -867943317, -2391314203, -2264386895, -2602462783, -3425086050, -527330629, -1039520609, -2503028612, -3396482983, -3674465993, -1466446378, -476278699, -3718038254, -1650456206, -2683325129, -2931177397, -3515401522, -4041915308, -2159084432, -207464391, -38064980, -3352528652, -2757171192, -616899485, -2752548459, -3712681124, -6137784, -4166315371, -1824479355, -1532020351, -3949210920, -2536306056, -3655348863, -3609694386, -1640898284, -3053519018, -4049080181, -3663220829, -3603105907, -3782154774, -2346263443, -4035126286, -2605534115, -3456385865, -241885802, -3416484550, -1107553722, -456313306, -544100096, -1766935657, -3147552770, -137502599, -2511204859, -1246355338, -1034773505, -1393993155, -1277891873, -2736421189, -4108952517, -767658662, -233446976, -2770062851, -671349418, -2646533445, -3206872694, -69958857, -324562398, -2272334724, -2800279713, -315462795, -2521110804, -1255795655, -44481530, -3663421032, -4204145746, -4208524366, -1838957637, -3589019118, -2758089, -2467114935, -3342871560, -60851253, -279430621, -1823435807, -3338751056, -1440621853, -598536559, -898587028, -3260286910, -675050464, -1406156860, -1308193722, -2821494657, -2077069080, -292685282, -1946947183, -1195668108, -4200852955, -45358742, -1545506182, -2130160891, -1030653807, -1256184893, -2132522121, -3933557709, -3447318303, -4000465109, -2269919476, -3703151789, -1878930248, -3200932974, -1879235732, -3253228219, -4123481718, -21970248, -1395881249, -440836107, -543203855, -2046289291, -885006767, -38495291, -2859789378, -2777925678, -3261902892, -991826136, -1695888522, -3566803419, -2835915814, -1331727429, -3901477357, -2156205769, -2620090673, -2801777410, -3406167780, -1718638966, -3078704324, -382502470, -3109033993, -1059989581, -4283164196, -1302245424, -3176204687, -3809507604, -967015283, -97756412, -3895252749, -3661747757, -601828657, -126815647, -1013477976, -3372537570, -557076077, -3010599862, -2728157987, -3435810869, -3527461608, -1870251663, -3878816528, -993922744, -2709717005, -3297798605, -1254192118, -4143048015, -3502986740, -398041840, -3721330255, -579855688, -3422318380, -1571176699, -544406860, -3991756042, -3097351633, -2526841388, -469575140, -3870978525, -3999594364, -4034044644, -1626774072, -401832316, -3053490862, -2977867325, -2353164622, -3484547070, -3276178467, -3150331471, -1520159090, -1280795328, -3776255370, -2769111385, -1523564749, -1427137340, -2431084996, -400428271, -617902669, -3384349904, -2589779480, -4090014163, -789005631, -2731178925, -33326848, -4288496974, -2460339163, -528656149, -3419811759, -2470361332, -4169958884, -3423239277, -142429272, -212342287, -322293219, -967146624, -655268684, -38268618, -947569657, -4098017566, -63864670, -340677663, -1558584062, -3087846406, -938610955, -2355591601, -423623591, -469268231, -3681688355, -2400774584, -907274484, -1947562588, -806283863, -1149726049, -1767834369, -3574616454, -3525508051, -2579375356, -292105037, -1274748905, -4220766120, -1610502850, -3855923868, -2703933133, -4237494638, -1291780918, -334492441, -2819715946, -4111913994, -1438089879, -927680920, -490106726, -188990901, -1100572371, -3746901811, -3821102950, -288073152, -3774115530, -2615302270, -4025565114, -3457386800, -3467395565, -2876031200, -3308585553, -3795176891, -2334454659, -391058856, -3454931662, -190269889, -3683241730, -4155338177, -770648325, -1344294072, -1580005611, -3233841370, -1400423964, -1343898956, -577731703, -4232981310, -4229568280, -4165840238, -1741592517, -1395021304, -3052276920, -77220199, -3203780291, -2073746012, -1180024714, -1289868086, -1322666966, -809856476, -1441603635, -4019903886, -1372209196, -3392390327, -1898180714, -3150822582, -1762587154, -2376965111, -3935324531, -1119050741, -1521102732, -2965423348, -2435044020, -1644390428, -3872204901, -3586129441, -2710568479, -2447049063, -485849956, -356314934, -3913277689, -211335196, -2624170632, -3500130044, -1683694402, -421749574, -580668744, -4039898690, -1401093572, -665967306, -549811202, -2052397151, -3692538225, -269690087, -3677624154, -3111185739, -2219382359, -1086771275, -1048268910, -2358556574, -597511087, -3404240007, -582247574, -3490259647, -3735351605, -2725898624, -637838120, -3608122037, -1264012125, -142810750, -2773121275, -3272944950, -2136801371, -2349483912, -1747576262, -2240221947, -1762002205, -4138459384, -3527687311, -3931169744, -603809561, -2828014886, -921695159, -726975587, -1804539362, -2805927337, -3682006553, -1336417559, -3328071798, -1698299682, -1590467123, -2183413201, -1213795016, -1695406664, -3706551472, -126491636, -4097541491, -90335119, -2537885923, -3825475498, -2671230920, -3723397166, -79854132, -2670670379, -3586684942, -701628363, -16110325, -2262265617, -3538302109, -101694836, -3156802525, -322646705, -2037222943, -2739126437, -122856998, -3383193272, -3520240618, -1964061292, -2627455269, -3999693334, -2885048847, -2348857895, -1464985434, -3585454201, -350571138, -2678445420, -994722350, -737335646, -3522141120, -350551785, -466823240, -4254514396, -792221396, -2210117389, -2819489385, -831031000, -1119751723, -1241418940, -4094431124, -4269562925, -4096228663, -3763553873, -1134802161, -3137756122, -850799897, -2827917942, -2805676609, -1761828852, -132600457, -4078389698, -3907654112, -3766100528, -2897172068, -1165519687, -1172798564, -457322614, -3091073852, -1980763778, -2272736503, -3346836061, -1976431351, -2348083324, -1506650284, -1395320880, -3953173871, -371529210, -4143850024, -3798626062, -476839849, -2820755785, -578122734, -1772946995, -1834175783, -1730645683, -232751237, -2732530243, -324562824, -4269523993, -2250836477, -1514717415, -2085647919, -3824540879, -733809157, -1561589862, -913827359, -563918464, -1379958731, -1430389033, -2099765098, -333708499, -1927047281, -262783377, -437347451, -1422498203, -168064731, -261928776, -357074177, -2356943962, -3940525462, -465463619, -3925935647, -3254171326, -1503425485, -2068783660, -894307008, -309901322, -1966312390, -863020057, -1362249228, -1457734415, -1540700175, -3816755615, -3934370855, -2266265609, -4282872226, -1450238145, -1979724485, -4106615754, -4198664816, -880480281, -6887455, -2302274373, -941531765, -1960501646, -654739540, -2055704604, -862880479, -4189561476, -1625792756, -4094469169, -2882078541, -2879563428, -3633688390, -3677973263, -3213505814, -2442925934, -763031056, -3261149003, -1537916637, -1987989575, -2993875107, -3833728780, -3018457039, -4089806656, -700424195, -398778225, -1784945327, -4092161430, -1743897897, -3353431291, -3813969504, -2962392307, -2989939021, -2170975022, -2479249080, -1138198542, -3552494530, -1521845202, -1355591084, -116194840, -900870016, -1495976847, -1216189378, -3374685871, -2203120754, -339619967, -3880596906, -1770683656, -3922660566, -3047215979, -1385406608, -660016384, -2600738, -1841412159, -638475975, -2001121564, -969114243, -2265895098, -4094702747, -1241167325, -3876599728, -454914685, -3378931956, -3467517205, -1345805004, -2369774007, -841442686, -2148511184, -2761766898, -2290650445, -1068899503, -68469879, -1935226957, -3577953031, -2927514416, -3240925326, -2133727556, -2356023725, -3528738287, -3303793324, -1993056713, -3160571173, -1009760466, -2888826558, -3952244284, -3827469953, -2772334591, -3626501733, -3488319080, -4283745260, -1920135016, -3559780643, -2036552791, -770168929, -595060285, -2611834763, -1350820935, -3991404710, -3170876529, -3375579109, -2022323577, -619350187, -1215800104, -2449002377, -15991695, -1099068532, -3589663946, -1376882591, -1009240088, -2683602121, -4002761648, -2894927075, -2793759684, -3712402613, -1225888752, -3727084693, -3265042714, -1801532527, -2205407608, -3646115346, -1738742621, -3350048102, -1403509637, -509151654, -3858635489, -3942566737, -2395569222, -328798388, -4155248974, -1646399699, -3100679576, -579178177, -2335593106, -1985027223, -1660963589, -2594769752, -1486815112, -4243098363, -507710332, -1176130348, -3247620091, -1743059430, -1497848173, -427553748, -1599880304, -1692485106, -2127192333, -4189000109, -865913403, -3312824256, -3105381720, -785818770, -2227981859, -3183677527, -4054015895, -68516834, -808296292, -1749474336, -523603, -992998834, -649468587, -3456213411, -353556377, -784753116, -1524163782, -2360722093, -2233143064, -3519830278, -2745003982, -1633977669, -651857528, -2771739916, -2650291281, -4093793222, -1721874640, -3504865960, -2382887078, -1535677539, -3954734696, -48479347, -2090489201, -2087096339, -3981080952, -1983385988, -1048707941, -3067757196, -702896722, -3649259616, -798061722, -1559760085, -1476484014, -3815566117, -3825114907, -2400335363, -608138615, -1327235419, -3948836759, -82261986, -286953878, -1028614192, -3471234693, -936074423, -3605838460, -3002521706, -3830930997, -2740085489, -2020303075, -1795733855, -3206806714, -1010385869, -2115665871, -2548053712, -2953891308, -188229148, -1781821963, -700908048, -2415229113, -3940334568, -2041208836, -1976095558, -148286819, -2984360131, -1355297939, -1339892080, -603421117, -3878747769, -2105651737, -1923161801, -1038894866, -3578963811, -501464764, -239267674, -2861102249, -919193432, -3933093651, -1659077544, -4028513660, -2580305574, -2814045368, -2427432900, -1179641909, -749138293, -2064185259, -2254330996, -1224981897, -2955658357, -2406381464, -1521655421, -546418187, -2075802034, -460473447, -2824449918, -2649494605, -3986377885, -2251412834, -3613047857, -2548976503, -2237069501, -3311549033, -353325222, -1501748677, -2375973857, -4205425727, -290106632, -4186775655, -3547563981, -4008031604, -1600078598, -1173440356, -1696106956, -2123136023, -789104529, -1911017627, -1035586276, -1681870859, -859217250, -2371721574, -4013850329, -67393328, -1696348109, -4064515291, -226485983, -3283385962, -3009513596, -2970631774, -1187468889, -4136956967, -1288333271, -2627172495, -2608917041, -4190852110, -412293286, -2720106828, -2418672220, -3635692249, -2285950071, -2664572333, -2942032361, -4222799860, -2541220351, -2412768455, -1288699283, -3363615556, -1965318330, -2481351782, -670884485, -1257847497, -3275293645, -1147388766, -4072425786, -1569011609, -2197910753, -1292098555, -1762583238, -3118628437, -2704266960, -4138205901, -2988933836, -625878173, -147304119, -3415770887, -4234802213, -3714573523, -4253743078, -378940439, -4063042376, -306064080, -3307093280, -3509472868, -1914629438, -2693046890, -3317848404, -3831687618, -3659648495, -209519355, -3398416893, -2776085526, -2768124279, -725502847, -2110330925, -23832979, -2239283767, -3971750233, -475197662, -3749927677, -497109079, -422381139, -2135538771, -14930994, -1811268405, -4223602668, -2931402494, -2427102034, -1525216641, -2500421171, -2317126441, -909907567, -3521042374, -1301812210, -2372002546, -990856447, -2221727528, -1964809741, -2442792485, -1901776829, -3557114500, -141728157, -2514845006, -4028354420, -2155113128, -2517104393, -4125171933, -1359753318, -934296717, -1540552143, -4090015917, -4244384263, -1341638823, -3504937068, -2517134060, -4071294698, -1530599173, -788469428, -3849631463, -122576144, -687751543, -2791420507, -481168175, -2212222937, -2223640589, -2253095029, -268351333, -1881869776, -4078189112, -4119059585, -688558565, -4009955783, -3710945447, -4132357423, -775788659, -389450625, -3966705299, -2104396124, -1890230011, -817270516, -168539389, -1742456264, -2305700333, -3920874819, -3939826665, -2660108543, -3067602358, -851564404, -216340873, -990112081, -1813115154, -2234986182, -2643530428, -3824840852, -3778328623, -3532395946, -4111040642, -496509205, -3476513120, -2794615883, -1219849499, -2099608254, -1393744416, -857515488, -919454236, -1866405462, -4117378641, -3096294890, -1080749753, -485766283, -2393433071, -1040845638, -1711899808, -2085842258, -2086799566, -2068434120, -1608458324, -1887395074, -4289569908, -979454867, -743899771, -2060899429, -1769225505, -1151956630, -3925828073, -4228314302, -1326615135, -3297859202, -1496513701, -1140040056, -668944109, -1337657704, -253554440, -4103591332, -3635741380, -1623292718, -3059887777, -3001938230, -1539368495, -1669666410, -4020692066, -3985520274, -294088384, -3799560836, -1234662225, -2386350167, -3851783969, -3258619415, -2498544805, -3150553427, -1150520452, -2294334176, -1264967300, -3975255632, -3128398412, -3618057586, -4166830966, -3376514581, -2364298893, -3301139088, -2544816348, -1853739496, -3403620050, -3753960645, -177985873, -1378251428, -2853197872, -3033953298, -486963717, -2379544641, -288702195, -3747738462, -1669897811, -362091764, -256192077, -1398940336, -3931009223, -3679763695, -1149060716, -3454110157, -1845375436, -799277786, -4072206171, -3630019009, -3720781970, -473364658, -2977292828, -2946005756, -2799542174, -4195695062, -3348587044, -4045008036, -515785386, -3463004793, -3666374752, -4198437380, -3374027123, -4112351086, -3703910865, -1210107236, -2337475339, -3733480458, -1892366363, -202118561, -1978225174, -337476005, -2497705653, -2736201502, -3040373294, -226377152, -2604026831, -1302459852, -3556501171, -2375229080, -2028468416, -87271016, -1485396612, -1702214303, -2557392099, -3139099560, -1907626662, -320807749, -3588302858, -286029663, -2064844105, -3543787225, -2221287514, -1257257845, -941790323, -2817007882, -917682404, -2755335346, -2540677399, -3298454481, -691433863, -3278406590, -93394908, -3019661225, -1594214657, -891189263, -10455864, -3499258246, -2037345496, -3147934769, -2972468278, -532856560, -208182942, -2125700467, -1422262553, -2114909031, -2022596048, -3061998421, -310675675, -2120431282, -4183415041, -3691931707, -2437074650, -1863705617, -3670908999, -1472716176, -1051288194, -579183443, -2724274860, -1014915798, -1088751447, -3769050134, -1656149726, -797539835, -3765807231, -4089605235, -4167983574, -772968229, -3344027121, -1818645803, -1205092665, -3204621578, -579901702, -3552372326, -3943457085, -3696454310, -2865793534, -2856904259, -863479005, -1737471531, -4247329997, -4257740265, -2974763440, -4024763235, -879421549, -462671424, -1725574170, -2821408451, -3417955769, -3320547854, -2922929334, -4022147046, -137527709, -947630003, -2226877218, -2948993119, -1379431362, -3058252155, -4147164682, -1043608914, -1987759515, -4016355957, -1195793966, -2868660624, -3629658423, -1787530107, -2844485948, -1424359308, -1560021017, -680947371, -957490158, -78889141, -3643385856, -1344240052, -3656087086, -1716600410, -2586044984, -2541591916, -2036803119, -3598061652, -3346059133, -592281217, -1215673560, -3197655960, -2032007395, -2718659204, -856717898, -498310328, -542903530, -2672819301, -292313101, -970625763, -2614430796, -4085566389, -2314591110, -428896685, -183971868, -246152079, -3936922467, -810319112, -2723677886, -3199262470, -2075139260, -2850389206, -1563560582, -2347059174, -793301819, -1785651562, -3533211067, -893047795, -3585509490, -3498971007, -1896036738, -3581260831, -1269548831, -2959704897, -3248487664, -2752849715, -4210507722, -3236838199, -4053196186, -2643890394, -2440258996, -3415327512, -2576708277, -3941690916, -1815073493, -1182144267, -49334003, -3919518792, -2873396943, -2670129804, -3458207069, -1411581155, -3720667157, -1389485239, -2221016024, -234690612, -1824526791, -2982527636, -2607845825, -3644241733, -166391699, -1505584205, -3854694397, -1894898253, -1496159472, -1178841762, -1803577076, -2706076447, -1995001895, -861064247, -299209263, -4187037447, -1140503829, -736517513, -236169167, -4109252764, -1919174568, -269646170, -1139882973, -2365840766, -1523187334, -3853965837, -3145494511, -1422141732, -3507761121, -3269765032, -1916574627, -2638611671, -1330548254, -1577204530, -4239948006, -3907372123, -1450002787, -1458850551, -1653998265, -3333094512, -3828703689, -179151081, -3049351402, -2672672666, -356653159, -4036240663, -804874368, -1788994993, -1741543415, -3130622347, -1336678379, -2868712260, -1544865920, -3520834815, -4068173886, -121942095, -623917230, -2926357529, -1085261641, -1301442520, -1190587018, -235668617, -116363494, -306868233, -3494789722, -1376374855, -4039534524, -116324307, -4286332747, -1723736376, -2383748525, -3095942811, -33574007, -1303234120, -696417776, -1586176790, -279540117, -3397946102, -2207123002, -1128378917, -3568252478, -3495716646, -2401830778, -2876467887, -3931066694, -17465555, -3961933004, -4093106206, -3113295267, -180775983, -3451258577, -3932723415, -2304451802, -2936700650, -3434731529, -4282233497, -2499836766, -1499307304, -864147734, -1049639743, -612078669, -553228713, -2075091434, -1460267391, -214957092, -985609906, -753823646, -2945594799, -739265599, -965034540, -1504804134, -2912033808, -4038343828, -478006681, -2068096499, -2197927036, -3745733030, -1883060680, -3915080263, -4058371671, -1479455256, -1311071024, -4214706040, -2810537617, -4248229830, -3240751336, -945428458, -856698905, -3860351987, -1449051568, -2159476598, -3316202928, -3255628987, -2105134918, -1326065816, -1593919606, -1588558153, -2862274085, -1530421475, -1042822520, -1732315184, -3686243302, -3800380400, -2372672878, -1185801016, -778307598, -1639740461, -2588163835, -2132437724, -1338755915, -2028207440, -60409489, -2260265909, -3172782085, -95135640, -645923712, -933144392, -3850869536, -3778564148, -3369040296, -2922363135, -2547216961, -3663741386, -1369690461, -2281122221, -3262888576, -1974426892, -720665910, -2606400077, -2420718990, -1535866382, -2316540274, -1415291431, -2023962929, -2410923387, -3592859829, -3900069906, -644874402, -227265943, -2837935666, -3212896318, -2328933829, -1241330445, -2272375622, -1156258998, -2545724098, -2757712033, -3762486064, -3907666073, -3847962738, -77840713, -2531927805, -1240096964, -1534618655, -3833368081, -3266633601, -4180341783, -4021229622, -772548340, -35604170, -3444180355, -3972056326, -243107484, -1105736692, -3686817534, -970876289, -3731853715, -2705622759, -527464571, -1028057093, -1215723409, -2503091799, -2540499307, -131957240, -3936113331, -419166264, -656844229, -2189618422, -3050651447, -2302619937, -1093330048, -2057308480, -3633798012, -3935814089, -3297170632, -369187018, -2308194331, -3286199577, -3976587376, -435886376, -2219745613, -2822564130, -2243048765, -4234745845, -2134535057, -721595121, -294626785, -1296314963, -2033241156, -262605622, -15710337, -464212881, -2974887896, -2846797939, -414336395, -1535149623, -2849397303, -1595830756, -3152482122, -462072240, -1712070223, -1828107887, -912295380, -3474243480, -2556986270, -2527447138, -617814657, -363367346, -1817523240, -916953857, -256179373, -3257384222, -2759283571, -2036205158, -2951367548, -1392068367, -1815804892, -1691878931, -693417899, -2010727729, -1364362412, -756493093, -1370519726, -34966314, -583993257, -305480412, -3458130429, -2070649930, -3121808986, -3607351204, -2889439227, -4148728816, -2701104161, -387080372, -1654471196, -3500854098, -3196997394, -421870316, -3573865552, -1135621128, -1380941141, -3477791549, -1726238377, -4207139856, -2078108468, -4139554373, -2768128449, -3697334549, -3837426331, -1869850943, -2465255230, -2523867055, -2733736233, -652389964, -2760639264, -1418565604, -506657027, -1502374843, -3978969439, -713437231, -1999303945, -933148520, -4283435910, -2355857059, -3955776006, -1812810099, -2992750953, -2503074356, -19318983, -696932806, -768936817, -1926677540, -2284276928, -2957645399, -720553693, -3527999875, -4006582479, -2238557568, -4228769599, -2171874125, -2685690672, -455597084, -4149286789, -1837974627, -3535607377, -1474431602, -1078262225, -3526357281, -2677926435, -329163848, -3646447278, -2681650053, -2565758396, -3175161684, -1170737638, -57079519, -2303451065, -1792413354, -3523097643, -2161124880, -109197963, -517237525, -973744139, -2527293196, -4118772840, -1960055083, -370797925, -4197377928, -2568744786, -805999996, -1091109407, -1726152661, -3262376715, -2760367156, -1500832073, -2814329536, -3681284478, -2392452866, -1761720401, -2988023722, -33851254, -3029613755, -3695351876, -1610008913, -2450136481, -3277899766, -1852432997, -373721893, -2885436174, -10121947, -656647238, -724915827, -3565072590, -1266208808, -1155396347, -3094264827, -2471147500, -3687083943, -1866603369, -743663881, -692404468, -3492584075, -3491756657, -632114987, -715649684, -116354824, -1357074528, -3297071933, -3095559860, -1866529722, -2925710673, -1193162050, -1440783862, -589107443, -800392713, -461811046, -1679985260, -439484481, -183436752, -1265797445, -1671736041, -2467207568, -1749899005, -2208243273, -2611751235, -4276642718, -3891631780, -4246458125, -707674193, -3264779617, -3062859640, -476948876, -825264953, -2892223999, -4007439873, -3552108513, -1497675594, -2806848811, -1213759533, -1193502623, -2837523430, -3552290112, -4052046383, -1479419528, -2392832105, -3334703295, -556575955, -3101237801, -86728268, -1916171085, -1525982212, -164801359, -704667675, -1121650414, -3916103828, -2805646650, -1230215147, -4270670376, -2681208630, -1041963375, -600828176, -2337825911, -3293012800, -1774755946, -933344248, -998107035, -3050023094, -2841716181, -4292238777, -1158770793, -2450861917, -538295990, -669159361, -3224454071, -3219092091, -143509988, -3402179567, -9509302, -2667132513, -599161500, -3422242263, -2756403217, -4046085955, -325932726, -3392909663, -144600817, -3062388491, -1232037762, -3972673282, -1474839254, -2701905595, -4191173567, -1721461621, -1057714367, -3548147499, -3888390066, -1189387153, -3539743048, -1655914900, -1611380017, -114972405, -1012470441, -3130561124, -2525579908, -623102584, -1906124786, -3537885861, -2074480285, -4203910190, -2982393544, -2647369188, -4279638786, -3005334496, -2317973738, -1390866573, -1488402829, -1687109784, -25438061, -1092613216, -2000331816, -3332155679, -2735830233, -1428922402, -3935459342, -734010828, -3973040964, -1155743801, -163618478, -1653383496, -973933036, -1502864340, -1698871551, -4270253667, -2783944069, -1479892964, -609196709, -1015130566, -1160824246, -2457619247, -1512157286, -3970453900, -3092805571, -4173188997, -2323734084, -1256124373, -3341433923, -1380620376, -2243939364, -3166034301, -3969689459, -2296653470, -902106915, -3332252842, -2963994040, -1708327914, -3132796770, -1008825722, -2005493721, -1340707644, -1410535453, -4270561611, -1206004150, -539804928, -3002780113, -3881333635, -3732836854, -1622783922, -3128258372, -2739002709, -1773031513, -4292641424, -1512767020, -3490904855, -1848669175, -2804644749, -2771882905, -4294174131, -50102060, -1506786716, -402551139, -2265475084, -1774112117, -875054054, -701971945, -724126663, -3542028088, -464669634, -2186183332, -2519426944, -1302762973, -2103131734, -1194529954, -3962233414, -3662530260, -2353833565, -2487087887, -1485114051, -3000839106, -3707676300, -2450555254, -1261973652, -3570054674, -3793646096, -663561920, -3993256050, -3928335319, -1195786010, -2967641319, -1507410560, -3507104940, -1294187456, -3431283904, -800236304, -2932289333, -95603550, -3085592884, -3029617095, -2486325366, -2540120528, -3943691315, -1798067825, -520451426, -3634398467, -1599854095, -3712287129, -437421307, -2734588937, -1709542591, -1138060864, -760947419, -926439942, -3895386966, -3352590186, -2951509784, -2390011827, -1208974425, -3883129138, -3657826044, -814782768, -1997763404, -2471093150, -1366283298, -4208778592, -1919050175, -2625841218, -3249329294, -2996574918, -1236642441, -1997118889, -1458013739, -3278351494, -3888251380, -2615272582, -3327527517, -4283593209, -240345559, -2692327951, -3570689780, -2567872868, -1963795431, -1686178244, -913177855, -3288265784, -3296434835, -2216650172, -108825602, -3051119097, -2260903603, -666599409, -956442427, -403065255, -2160355000, -156805428, -3709669053, -988791557, -3903300450, -439697504, -1494553326, -2840139321, -3762187234, -262508157, -415161059, -1447905201, -1770888668, -1251323667, -1832990814, -3597987696, -3361362341, -3836691141, -406380903, -430350128, -1812862498, -3541815004, -2261279076, -3425140609, -1175768615, -1767870654, -4206509586, -2265474131, -741532083, -3144280860, -2237421969, -463602157, -2052476309, -2927417176, -2887373867, -1218393934, -218758890, -1763979609, -3490422804, -3415342314, -1532006953, -2477019468, -131418847, -5058578, -1342008542, -1251858802, -1620778613, -769215157, -4080084157, -801065834, -970300834, -1205858354, -1679634872, -4042873263, -3785868055, -3289841314, -2581982569, -355950224, -1591235762, -3150392545, -674859788, -867248628, -1166250066, -1997034996, -1070561977, -2898761694, -3420258147, -769562366, -2188386799, -389177417, -188054765, -1568059291, -2258258033, -4055915974, -761389923, -365997336, -56397182, -2333297870, -1062539270, -2716174832, -578568866, -525208371, -3751789926, -1433662679, -4037701723, -4014346831, -340611439, -3204551671, -1954766933, -3537853998, -2242623920, -3431588167, -20233670, -4287781363, -3847108863, -2637609190, -326955549, -884446883, -386431897, -2894724110, -47463112, -222310176, -3386003022, -1100893033, -1676222274, -1286236269, -1626267925, -4278562001, -2659565892, -1623905557, -2777304561, -3451998880, -1501499600, -314537254, -3704878655, -7929711, -270375006, -692054616, -481772536, -3139370881, -2063968608, -200230303, -2651004070, -2109107559, -1354390475, -1263338098, -2795570407, -2952266711, -228294863, -3148736732, -2648569588, -4055087679, -2902502704, -4095927008, -1331564512, -4272187824, -2382666948, -1644216324, -1288850719, -178289707, -1559001413, -3695353362, -1369479776, -3105012619, -990795193, -2404010155, -1191313999, -2916483277, -2213031149, -3057852686, -1740876079, -2299199952, -1055596129, -58292168, -3857103893, -781615991, -3153118184, -4097594864, -2251045746, -2768224946, -1532298845, -188013756, -2648232924, -2381701433, -1838673362, -445083144, -681088809, -1545242069, -616212383, -1286453309, -3011088639, -2959842103, -671497509, -3286824324, -2312464420, -3197632657, -4242708417, -3666066048, -939999077, -4219099621, -644903868, -1884048987, -2100571223, -2669286589, -1544596317, -1396460733, -2011914374, -1675881161, -323710706, -192896002, -1968030188, -3141376702, -1126592705, -3299681481, -2219466535, -3444363372, -26090889, -4073543131, -4082940424, -3542076584, -4146289582, -3809450176, -2174890909, -1127983902, -3465564937, -2064191765, -3989294909, -2521776188, -4132241925, -3397830641, -902973961, -1491575322, -2479948106, -3561579770, -3659392134, -2578475942, -111420047, -2733812404, -1235601277, -1455017295, -901080641, -1999152714, -1430354784, -1871301283, -1951649724, -732223107, -2501540643, -2736479902, -1159080839, -1660785374, -4153214571, -2385512292, -4177530065, -2350821276, -1090202292, -685768843, -2936300888, -4030702306, -1774075376, -1352955614, -2237873409, -1844185358, -2143859564, -2928940935, -1798814380, -2804785178, -4135860581, -2323306826, -2280187896, -753797558, -2558753376, -258089537, -1208780992, -4166097494, -1878123692, -198390043, -157874420, -190338917, -456657972, -3805997241, -4271681530, -570418090, -104522991, -723824178, -1397993038, -2816971541, -2542132782, -2925494217, -686937175, -3359454153, -1834431262, -2168808375, -3360507950, -470321311, -4239041801, -1612139425, -1282825954, -382673756, -737231233, -2477896687, -4120976702, -1767666866, -4183991732, -4028145438, -3925938992, -2851180627, -3682844617, -1057583112, -149192406, -3463667715, -581858506, -1299392414, -1221256711, -2958019812, -2146956885, -3191542836, -3532531856, -2024397318, -4156642463, -2983336639, -1342562901, -3161431735, -2513260586, -2518284823, -4220988652, -90919618, -4271989282, -3600928863, -1831973273, -4196524998, -2594047823, -475829309, -2228583934, -4221215107, -967614808, -3162103353, -3483735083, -3968245876, -3158885519, -1221174264, -2016873689, -1798561558, -2284901504, -598520927, -2757302931, -1182344518, -1402021899, -2831731736, -1416934335, -261468301, -2176146274, -1371833183, -4042086727, -877022265, -1653311768, -1516921696, -1175824627, -3621041720, -2393563973, -2891223689, -4118226028, -3710636671, -792347640, -3337104956, -2417690608, -591794431, -729373566, -212502139, -1295025534, -3686167776, -4113339924, -220125420, -2312937156, -346906404, -2745118524, -2220691870, -827398973, -5532175, -684322564, -1432299305, -307823485, -1091678607, -3332035026, -4129460687, -1916564613, -3821286025, -2739513763, -1400617962, -3338307598, -85499240, -11890327, -2117160314, -1907895831, -3899851770, -2114748037, -3722218935, -2326741473, -2611786022, -928536801, -790169521, -529031449, -1994628087, -2592651924, -4185981439, -2114362573, -96927035, -1926025317, -1222776567, -434302020, -2319609926, -4239235250, -2690417922, -1140409417, -202107411, -2333393912, -3510993505, -4063308797, -3497844784, -3263046839, -3668604680, -2386156986, -1416370346, -3882981054, -4268391031, -3210889020, -2088330271, -900404223, -845299138, -1337400307, -3583978801, -1281809728, -3703380034, -2308179823, -3638605085, -3427556426, -1031879756, -2736683099, -1254648751, -189334849, -2008398691, -3309883871, -3881585533, -2138049807, -2327898307, -1887443476, -4231548108, -63234577, -2812358372, -4252918450, -2963068827, -2578814427, -1984998664, -4051492956, -2729954793, -2949499601, -2985984926, -2535408959, -2977065162, -856578237, -1061491082, -1278710196, -2892451527, -2393473372, -699641382, -3612023411, -1655639873, -4190069565, -319245324, -2205734474, -1774583347, -3604074784, -732455451, -2148116233, -4015105710, -2869244536, -160830461, -2228750031, -3422225589, -1872874633, -1331573884, -3918381885, -538642073, -584640206, -2170973539, -1761799792, -1227314607, -3472227097, -3549091691, -12723985, -1393289946, -3916237027, -3816406476, -1366687184, -1929614154, -3276753331, -64883305, -815570301, -2936124027, -3482573501, -3123452654, -2160743692, -1681508704, -4144057790, -2862029909, -1523670886, -3373981507, -526777899, -3446015839, -2474242225, -359752585, -2796225472, -1401262533, -1557704969, -1956028224, -48108021, -3969016381, -195568925, -1123527483, -2619721539, -4252025604, -3613807980, -2052852439, -2643700250, -4149162188, -2877731457, -3563746862, -456191049, -3992649607, -2592947382, -450890889, -3720177044, -419634293, -1128030676, -1857134370, -3631566738, -813202310, -1313309997, -2636197981, -1160812352, -358338694, -2774640484, -661200034, -2302274510, -911756406, -1733222070, -278881717, -2215729765, -302062270, -3085080058, -2865046753, -2671080555, -2865047542, -1821122012, -3096075429, -2225003174, -2507108672, -572768585, -4234218374, -3720945158, -1577531281, -2740917815, -1954351423, -2193871966, -3354742024, -415200661, -2416379519, -3457238048, -2802962448, -3674424811, -709034726, -1451259972, -1670565969, -2795575517, -936111556, -2746170115, -803230219, -611716613, -660553406, -3012410472, -1472653419, -80730080, -284532848, -2691279268, -551730103, -345173911, -2624603313, -3252958517, -2976589452, -3130397736, -1459043254, -3797832732, -1863508810, -1370883742, -2843986513, -3072150666, -3784757170, -1931802016, -2404327738, -2888392243, -2424251343, -2943402953, -3751404987, -1215736889, -988348477, -190094089, -558750676, -3305524392, -2636076616, -3848360292, -4139713701, -2387574878, -3306671627, -4224602980, -89807963, -3789514273, -1755259277, -2584522965, -561122772, -3673723505, -2238838359, -2753051996, -816037991, -454005413, -1724737531, -565622358, -2304692173, -2829385025, -409592064, -1995144893, -827145356, -2859002399, -1588798130, -354458937, -4032070712, -2354807091, -1432120301, -2394546149, -513057714, -390494794, -2959629292, -4203519028, -2000917648, -2142103432, -3640448771, -3787121008, -2642858804, -244128791, -295192119, -3611787862, -1502819219, -3322611667, -3854836003, -2377448358, -4101995756, -545476002, -221545804, -243968175, -2098779217, -4003225852, -2916263470, -3445388293, -3421471519, -3706469627, -3045266220, -2267837458, -1413482344, -336340425, -2181089116, -1517926656, -789045509, -3984103333, -2430177236, -1606809424, -1805525165, -813612184, -491972208, -939104737, -4052883716, -3356540197, -435309739, -1119645994, -1160593378, -3202266009, -2368588228, -294728544, -2545327238, -645640069, -3142889205, -1604917207, -1218957951, -4289773262, -634230442, -4073294426, -4068944017, -1038496607, -2425265761, -1460851271, -1869253176, -1374128082, -4006419760, -1994566949, -484944459, -3178131074, -2997128017, -4247248782, -2911662107, -3641896253, -3962436921, -3082544326, -1303260048, -4060315454, -3496393808, -705117925, -702718085, -1098730364, -484938874, -2542175906, -153894247, -2142951370, -1909586797, -281536887, -4102266729, -3316874815, -2621074243, -3531818530, -2915842858, -3621414111, -3809564546, -116553172, -1336213984, -2053692337, -2467802861, -4257440633, -3345363142, -3415475160, -3526765486, -2397210351, -4105535121, -2521527018, -1143930069, -488515941, -454302826, -2380781814, -3813337618, -3578889450, -4128436051, -1458786474, -2242817538, -767710035, -3323431404, -703171309, -1675455141, -3212556016, -84008268, -4181081692, -3393486666, -1058012534, -373086001, -42388517, -3221535606, -2572984923, -429115585, -3490609848, -180684701, -1271933466, -426606861, -4049129475, -2652373569, -2138071037, -2117742953, -119646517, -2483252209, -548631084, -1161303911, -3736800048, -1833368683, -4233504433, -316318082, -1057806465, -3451722610, -3397979495, -480914999, -1641719461, -1325592766, -1806318197, -2343344594, -4182705508, -2039579888, -4022973287, -312719425, -2184704237, -1921227160, -1934510123, -3265945576, -2717381033, -353206028, -1060449529, -608545290, -1778885341, -1348867814, -808784077, -3272140639, -1108147702, -2414120101, -1021537065, -573164244, -1653784661, -3185119038, -3902011188, -2422115054, -3492010542, -3889585431, -2832600282, -972367912, -384286137, -1125939416, -1726078405, -372059425, -3674846231, -2940301599, -3120551191, -2392294234, -938452337, -3910067770, -32435967, -4277606281, -1153017546, -21398056, -2429424542, -1393838431, -1169476274, -1332426518, -2068674426, -3942098123, -2066373876, -2556591648, -3574475633, -4285684482, -1306325094, -3304794844, -3643181040, -2929980952, -2465454817, -3008106550, -2778335590, -3766798420, -2474269245, -2355695190, -181914008, -365604731, -2878110453, -242782887, -497140826, -533237348, -1776422835, -2457778375, -1682569529, -2899965882, -3187756283, -960220716, -168963812, -2579246016, -260398114, -3521634797, -2618998481, -4109433279, -3306359579, -288188296, -3245611745, -2862859449, -1525504171, -298578061, -3394629369, -3430011244, -4213670821, -3018557045, -4106587906, -3558042585, -3033677055, -664217451, -2910087633, -3904448931, -2686157500, -2855988902, -3539192785, -3820537139, -1280138641, -32012817, -2666058687, -3288390891, -4255571078, -2084043804, -4261542071, -4249384177, -344089401, -2627862622, -2044257114, -3216386238, -3461254415, -2074968020, -3838947374, -3885805725, -2849407638, -3088912959, -2516230324, -3241304276, -1479283297, -2572446548, -1842480354, -752414326, -1783143163, -924596351, -2990977488, -2141046864, -77027702, -203376173, -2285057437, -1109390452, -3405297916, -1761990550, -1134451497, -3129876274, -95536422, -2945411531, -1274522925, -4283583936, -3152354806, -3202115570, -788236114, -2987770248, -3376569037, -2888756347, -3319223115, -516938426, -3362545352, -1534822572, -4240654137, -1223497752, -4153230583, -2274768728, -1082610122, -3795942285, -4184962035, -3937499077, -1032487320, -2472026654, -2807869455, -3507201289, -1100644323, -2558633782, -1463809721, -2374714499, -2419088955, -1421015480, -566276970, -2615340085, -1507013263, -2361974080, -1732903593, -299249236, -3650228113, -1772559322, -3607790212, -1372837888, -3497473157, -667799940, -2381299199, -428615050, -2132585220, -3469974213, -3234417710, -1950078817, -1441809951, -3982664201, -666522073, -3443413403, -3291690168, -3622290554, -4278979564, -1082252668, -4168951804, -2008704072, -3488518823, -230016073, -1016829707, -1012612928, -4237561688, -1497082736, -3723754574, -2006619021, -3736850723, -2938393790, -1588086259, -783927188, -3319457005, -3017293390, -2703723113, -2919912530, -1687820954, -3238246836, -239875127, -507334979, -3921382562, -579149689, -1125791191, -2398394821, -3075957291, -3528649373, -3024493872, -3460968889, -1494249376, -3755406075, -1909732754, -880520692, -4067682234, -1754686085, -3187057582, -2187362811, -3806332329, -1086957039, -2004707387, -505321736, -3386831811, -1938100328, -1187332173, -481503650, -3998627372, -3885446531, -2249824446, -431123899, -2565558152, -1017975588, -3220042062, -2696963917, -794283294, -3884287523, -738014414, -320545399, -2865187842, -88409359, -1403154794, -1607432366, -3024017416, -1112929211, -2587706557, -2681940498, -1465573862, -2340028813, -657891771, -67303113, -2137283268, -1601023385, -1684045262, -3551724845, -1241742863, -1011641019, -3445442079, -2013483898, -3164789618, -384873490, -520295729, -2692577377, -3246280681, -2519506934, -313815462, -1084177366, -2993339336, -3848505083, -1312838152, -68793899, -1167453958, -1620987793, -1372452056, -3731499115, -4267470741, -143938176, -1965561057, -2878150573, -2306886112, -2920657282, -2509548344, -1756903514, -1780344955, -3604355202, -202316000, -295657134, -1744967879, -2350764279, -3901493680, -4078128231, -4013985323, -128697975, -4294823060, -813621514, -1028690406, -2627173269, -2741851383, -652088050, -522930864, -2441241337, -1012680322, -239138885, -2252014941, -2313415725, -3933090688, -2810729237, -1123177519, -3275818052, -3646171874, -1878370652, -3966750391, -3960127423, -3994347549, -885520111, -3132032896, -256459345, -1230723320, -3130731001, -45618745, -3425429520, -3859883891, -99477390, -4164611907, -788485317, -382989136, -2727555975, -1204617981, -3359686186, -1018335636, -2931676796, -4226862094, -1395081972, -1730165299, -4045693151, -1405080188, -415983483, -3820843156, -3966776861, -4124786690, -100127239, -245546261, -1526574665, -2996372384, -3232419816, -2561019315, -3528061094, -2648890537, -3832083373, -212962158, -4222442474, -946988865, -1085147057, -2645272943, -2638717411, -4056077423, -197003015, -4001620003, -436966168, -1329498995, -3765025914, -2329265215, -2882864160, -1800542798, -4199871618, -2629971686, -2484852946, -1687312233, -1585532089, -4252335424, -2323360449, -2606840935, -2106707231, -2621223663, -1932562446, -2192413642, -766605910, -2352847514, -125110882, -2180041040, -371465815, -670522022, -3156434344, -4285358366, -1952009172, -3747716851, -2011874678, -3826495519, -3284011278, -1701418070, -2796853616, -592727371, -2057378348, -2938857990, -1099219223, -323328875, -3032918337, -2706680310, -1429294573, -2629672313, -3486577234, -139819184, -3929319999, -3851195571, -1730098835, -3417055246, -207985257, -3316527481, -3312813166, -1009048432, -1770667473, -3865615132, -1156333657, -879058883, -306774634, -3765557477, -718066744, -90736160, -1236000840, -976904146, -2416999081, -3676944013, -2489185049, -3528708548, -1194276840, -1685352426, -2617930412, -1595152562, -2557410584, -22883281, -337444918, -3931382083, -4189954656, -654228107, -3966640394, -3116206856, -2975756157, -2533080346, -3877698183, -275461185, -3082246817, -1098568304, -2731631996, -2303644086, -548837971, -47347248, -3834566529, -850728532, -1817189677, -2649259761, -632617837, -1750758619, -2541331553, -1021802833, -1408019721, -2769025579, -3284138415, -104647239, -3329728637, -837998311, -3906677350, -3731413605, -3708455556, -2346507086, -1341552967, -286832215, -125019038, -2039608045, -2938089987, -1043790579, -1128728332, -3892451599, -616571976, -1207948064, -1213504516, -2715685773, -3559470224, -995545196, -3042606915, -642778591, -3449185141, -475543196, -2181240162, -340488855, -4231063588, -4201501203, -41505901, -808314570, -916546037, -1875282938, -1671402237, -3468581493, -1765804125, -3617053302, -1183894603, -1925897001, -69561800, -3397606753, -4009511190, -3121714665, -3645126965, -2150331723, -963539337, -530212840, -2068276984, -3936767418, -3238796372, -3712978074, -3009247240, -1116804773, -3772529926, -3871574494, -2656126048, -775529708, -3048351674, -1911911457, -3606117723, -1305798094, -762882358, -831607569, -883219779, -1830012448, -267700499, -436608249, -2869878440, -1547929196, -1136131186, -106151352, -1193196017, -2600958433, -1344020776, -1820932846, -1067351841, -3928397194, -1686717607, -3361712046, -2379660528, -998503551, -1343025591, -1502161854, -2125477916, -3854909808, -2924919525, -2626548076, -3787707901, -4227665293, -1605358101, -414566993, -1059544502, -153082078, -4032802190, -1354463294, -782567984, -4190525791, -462495679, -2096532314, -4199480102, -1071355754, -179851467, -2666403543, -313262139, -2512674928, -1268381312, -2601731298, -459768954, -1242484316, -3439063629, -751993134, -3411491127, -3911319061, -27925806, -2882005703, -4111648582, -2968521852, -4156872418, -2823657540, -2783913006, -361323052, -971576870, -519725577, -263289331, -679681284, -4026700637, -2210602339, -1318805098, -1875293488, -3730330110, -2845159642, -1439761216, -546399635, -2823732394, -54102522, -561121754, -8005168, -2375709020, -2745769346, -3425245534, -2540196760, -4005796544, -2639339387, -942877559, -4268718474, -2757468502, -3262181608, -2797964239, -566194718, -3067842355, -3226470389, -2412209445, -1422612046, -92961461, -2575735017, -2843886145, -1420222168, -3165672967, -1532207529, -3228216170, -3466866972, -4122948690, -3848581434, -3720129081, -702180941, -494306432, -780617255, -595343132, -2477281989, -261927499, -1057344713, -1554578375, -2791132554, -1707348432, -2490130210, -851732885, -1136968381, -2362640636, -561428383, -339283593, -644712514, -3081851754, -2083348390, -3392192296, -3224209958, -3589276079, -656370667, -3190623557, -3726968852, -2424853746, -4180751005, -4224335294, -2007585534, -2089389513, -2604170641, -2015751969, -2431531992, -1779366034, -3093976703, -3250710370, -2072627560, -68957774, -1931124949, -4129839214, -3225038320, -3061816624, -2185642883, -15502339, -1475826794, -3878295222, -1748658800, -2571105377, -3206672947, -386519446, -1350648312, -1518680506, -2387504444, -1948658299, -2588935281, -3812936771, -2979539556, -2312946646, -98622187, -1201913685, -2870249784, -4057003817, -1137844485, -975707707, -1096621033, -3805661254, -1907196913, -1429550288, -3384096867, -2911009334, -537953183, -100818566, -3381412713, -351357629, -2360379422, -3525785281, -2681473113, -246248027, -3019298050, -652820156, -343794793, -2865273892, -2584842713, -4190494862, -1881638554, -3900952502, -1295722826, -2870298864, -2941771984, -1519399849, -68748946, -2100340870, -2092740768, -1747441919, -1300316092, -507301014, -1816263707, -1710011044, -3286002881, -3309365589, -201882829, -2699378853, -3173075871, -3464879213, -2361629933, -741932242, -3000722567, -2769178215, -650424166, -4223943754, -695788030, -2200955098, -2345662733, -1968955115, -1852894422, -1537211215, -977776059, -1011754900, -3968774850, -1518630475, -1398927543, -3488288263, -1924837931, -2213577248, -194247684, -3929642846, -1945855360, -317302655, -1113535290, -1034808660, -83637631, -4247946255, -3818275772, -2084934195, -1790283043, -1336812829, -1078886065, -3704173655, -2345501068, -31395632, -2922516113, -1997644990, -2628828855, -2973249252, -36250096, -323147291, -904590398, -3789437835, -3972700454, -2661948480, -3726751529, -2384245566, -3045223829, -2228699506, -492486297, -3729325520, -360826803, -2016766736, -3218037324, -777271119, -3699592642, -2300187157, -3534231814, -2653039591, -3481775517, -3582070319, -3019559764, -2068053917, -2861550199, -3890766039, -596231157, -1623232078, -549172460, -111751358, -3919703421, -4019826378, -1949494761, -1843255962, -1823944716, -3703778787, -1501073413, -3809307658, -1158118131, -1205181066, -2849466234, -859814303, -2119880475, -1953886063, -41285410, -2165042662, -1887311749, -2697015272, -694621124, -2370915309, -2953082958, -1851702789, -1475591313, -2895599957, -4255783856, -2671892718, -2033256350, -415664846, -3510609889, -2071927375, -3546536583, -3263838114, -2949784618, -2313799658, -873448575, -1521211880, -4157670791, -3792466594, -2150017881, -234582381, -2118823688, -3393862877, -3664750009, -1094978250, -1365469225, -10197374, -1274561444, -3987350422, -966578160, -104579273, -1441040266, -2986780984, -1271651561, -1956490466, -3419670511, -3154782232, -2766887939, -3323265663, -3727504197, -906085272, -1202016963, -1773444202, -3878993627, -3783812279, -1935464082, -4038822003, -536523566, -394186957, -3057738993, -499843491, -54946288, -1632409332, -1005907463, -1383011119, -154737702, -982634457, -2337039732, -3016658844, -4112082482, -1686524478, -2019050, -401886466, -1676690103, -207436422, -2653129844, -2898725695, -2420566388, -3083287353, -3823689407, -1856264475, -585654021, -1373450102, -3087084442, -1236762783, -2583792350, -2667613874, -529997004, -2281383077, -1887458499, -3734667305, -2986503612, -1895885927, -2442306440, -1349041162, -2617125110, -1043323000, -976495505, -3014810569, -4063569116, -2959431797, -999154552, -2390550843, -4001381135, -3982923996, -2318565820, -1798978460, -3887954415, -4159353348, -2544133515, -2681629467, -863865804, -1412144753, -3817189172, -1199123669, -1256706023, -1395249878, -1167259470, -3278156959, -2639921682, -902120279, -2090485372, -1678730837, -1394615533, -3993726960, -1122259933, -3540217949, -1414558881, -1591905968, -2900810486, -3247282609, -245182092, -2194027313, -3484109761, -1889331174, -846958108, -4134390666, -2720581978, -2595226875, -877181519, -2126102359, -3465585416, -1023385510, -2145989826, -400603205, -3565074642, -269581725, -2060172259, -3221548160, -2813305175, -493292177, -1687104784, -3828404966, -3342418110, -2239442295, -1824658373, -1633639252, -1290167053, -4043450544, -219123359, -3641053756, -4025493449, -3760108204, -1595111503, -2764880913, -2657951797, -2313004378, -580633313, -4198416775, -309374661, -930291717, -4275906166, -2402936353, -1926369618, -2355991517, -3133815372, -1234309493, -2080631078, -3702899197, -421871558, -426031934, -1259115404, -4187535828, -3289230278, -892570739, -3667592246, -846365537, -712425979, -4204698515, -1947724648, -2050320214, -1055198449, -3813899641, -4267733651, -2262357422, -2744142912, -3003916533, -2785182168, -3079776701, -2821036068, -1857946641, -1411064834, -1547885709, -2282784063, -4158008843, -2633731938, -1113038196, -935366758, -3473943102, -2463978198, -271957224, -1756728683, -2888093554, -1012359939, -3085078779, -3717737065, -3922090987, -2543084968, -3674733622, -4198015729, -3961749503, -1896115260, -2858885968, -1968967783, -663199624, -2668749749, -2786346686, -3658681250, -2474568421, -1025434894, -121086339, -3284953081, -1076066906, -3340452638, -3956082716, -2700951650, -774428771, -2004649207, -378285122, -2566549747, -2324279141, -408898473, -3433063443, -3415319362, -2732704408, -1270679566, -316861805, -1765656279, -2200563615, -3574532562, -202940922, -2957780548, -1614942399, -1084040036, -887704435, -2699353668, -2992609244, -4187851098, -2778936607, -2735262763, -28585617, -3600362640, -2562895802, -1579539054, -272125718, -2468832228, -1165989053, -2702165592, -795538732, -3152335424, -3914715752, -2734407981, -1805670799, -2402669031, -4149808210, -669473770, -1916341668, -950694082, -2408188229, -969589012, -978821820, -2127981571, -3417098290, -808547525, -2815767844, -3132682068, -3154396461, -4141844100, -1856525748, -3537220085, -2629001944, -4093734920, -143408557, -840596474, -2227360419, -372873189, -2066491043, -1018054782, -2986017087, -2762165727, -11280933, -54201959, -3592466879, -669977185, -149802067, -269513020, -58447602, -2818304034, -133906052, -3747813405, -3199232603, -3926818871, -3850630014, -2928435375, -767156739, -3209452001, -249854387, -2303422848, -3409041158, -1671542397, -328764579, -3232106009, -1340746868, -4036078282, -138192147, -3681251892, -2098760371, -3374394562, -2755834498, -219064127, -2996254964, -2523089639, -114555132, -1847331390, -1549334072, -2278151103, -3515209431, -1658177574, -1420968133, -1376382796, -3592994980, -2774506978, -4076676500, -718887702, -2860616829, -335521407, -3335570406, -640863096, -991716676, -3704614523, -750915514, -2326964852, -2668450790, -988508396, -3999533561, -3129653544, -3346001362, -2014412101, -275170012, -1060484828, -164901719, -3800826515, -2597039006, -975130384, -3490039201, -624255276, -2612182982, -1165029395, -3004596268, -483118702, -3031785812, -4137567382, -4174584999, -2978459029, -3644973298, -808004184, -3226109097, -4172150488, -669952311, -1187842392, -1826302086, -1892088747, -4221210240, -3585829557, -2627860986, -1033078765, -3448307507, -1757419125, -987369636, -3017223349, -831675197, -3206550050, -1820510695, -2798021276, -2714242782, -3938575131, -3665344425, -4119366037, -1975693027, -3501091083, -2182279152, -382965660, -1388698182, -7656682, -2339017692, -1277041578, -540484692, -3742816753, -3366755638, -329519374, -471974174, -1165750562, -4193829680, -3848508216, -1487020026, -2803554705, -2237934044, -2272199153, -1451849332, -1677813657, -13879927, -1264530159, -872595927, -177477477, -1649619380, -2632623656, -2528772474, -855147882, -4017890092, -2213500420, -2672426925, -2023035275, -2694933637, -1682817191, -768880669, -310578402, -3769254481, -226316900, -4276748612, -1375878809, -1669229076, -1833658294, -2922443200, -2618952125, -4288591924, -474425721, -293747099, -2029772982, -3928481210, -3735499376, -3371957019, -1801658986, -173370251, -4200096000, -317572021, -3566660181, -2025567618, -2542017388, -2112086372, -3525865738, -674663555, -3217999612, -1810090675, -3654848561, -1607893274, -3866872158, -3251839448, -2994349238, -1745051773, -2913250791, -4232771291, -3871564548, -757614234, -2228635873, -2283548324, -4179790685, -1930722904, -278468727, -1178034451, -32020078, -3632231971, -1535136887, -1887717916, -1627908374, -3741626558, -1244041481, -3334533350, -1541068957, -1572890930, -158561532, -567725623, -304921822, -2180204998, -1486935283, -1351690052, -1133293788, -627111520, -1782325099, -2438849741, -3999365032, -3938108474, -2600588003, -3728077935, -4211682288, -31736711, -2536193693, -4131543483, -2866828063, -634923790, -2712711070, -3907032757, -697347583, -3794698612, -1196334207, -595492796, -255581428, -2358447611, -2220258640, -506293180, -422459023, -1707480703, -536054436, -1083439592, -479317491, -1793868078, -3622326969, -824844790, -4139538098, -1319914633, -2834172035, -3946908361, -1068646312, -3952250002, -2218458768, -3607910257, -4190306502, -1143188872, -687951768, -263690946, -4204227760, -846003449, -477866612, -2812934259, -3366833863, -1806549911, -1153380162, -3352674929, -4236692982, -3927351127, -3917362252, -1673021081, -1494053143, -3722196655, -3401571981, -1677129755, -604441671, -3495091252, -3797104966, -3794902538, -1399730223, -2228091773, -1593980240, -461928420, -2540217090, -2727755590, -280032045, -2401974587, -1204465975, -3527839227, -3436258185, -1194893063, -937592388, -331018114, -177766117, -1605282321, -3014243547, -513086581, -4273456085, -4246805487, -3685114342, -3103322863, -2300396883, -2114671948, -1947483536, -3729365230, -3162522889, -1148945837, -1468946495, -1994106565, -2808922498, -2265425990, -1191683197, -2001291401, -3624939213, -1864300463, -1397280154, -1482107616, -1245533297, -1864056993, -1410910257, -1512837774, -2777613921, -3780010455, -3313547820, -710329617, -737986132, -1533398062, -2966658658, -1520165151, -351413701, -4044415956, -1295208040, -2081716589, -2765175023, -3601490540, -2923410955, -2371306023, -32652250, -669108674, -3473766573, -319696899, -3698764693, -1621367003, -2054353565, -4198471798, -3488681671, -3297628236, -29622260, -321648052, -4156783829, -589457467, -1949719527, -2097340003, -2125040623, -1741306216, -1381469633, -1954115654, -3723908179, -2429368299, -1478973784, -3833948968, -3641074732, -130254009, -2103947668, -1454252583, -3510899719, -3884507229, -3156964225, -2423810257, -1546828211, -1488287325, -2204042407, -3435165379, -511950525, -34207131, -1779818968, -665791308, -3196976721, -3979699154, -4040504701, -276460750, -1136532217, -2937587343, -3821602467, -2455041374, -1399661753, -1234579192, -2822361447, -2390414398, -2516170815, -2749616287, -2491388664, -1471634731, -3794481972, -2842770881, -1629178111, -173015366, -160900387, -3866722311, -1261060595, -2000235568, -1144073538, -3726893377, -3228424662, -1178248858, -1292805068, -463343514, -582770939, -2412742785, -2970727608, -2543336699, -4139811624, -2675438318, -2153214454, -2171699979, -981880163, -3901322240, -2487366737, -1565386009, -3642572633, -3637089629, -424653204, -251131082, -1002288354, -235383942, -3965477632, -1409527824, -3722926069, -1852854253, -1626706800, -190715476, -623736921, -2206419608, -3494178624, -4081491748, -1136060981, -1152682034, -1422164859, -1926649581, -2000208717, -1344426004, -3411445294, -4136117749, -2211752370, -2755349422, -2029995966, -2320000821, -253704344, -4071937302, -2406261776, -533705409, -2857469532, -1201746446, -417179810, -3324178278, -2705044299, -695669509, -161056231, -1629226227, -1585924176, -2121787812, -624621767, -159402929, -3491935300, -4199729077, -1684687439, -3257984083, -2317327152, -2869889632, -783238505, -873688832, -926898910, -1305839704, -565347769, -3702039138, -746536445, -2516161299, -160090770, -610261138, -3683147740, -2343906514, -1721666231, -2496804204, -2826656418, -2714229174, -769362716, -1063617616, -3550205722, -2580520127, -2030625310, -1098664539, -857894653, -3237996300, -507762617, -964861735, -4265908022, -989258774, -2399667880, -1657497308, -246661941, -499518208, -3210488832, -2669646191, -2262512545, -3089357257, -4184539136, -780274968, -3679730627, -4031640788, -1868546055, -432952392, -3702311429, -891375212, -909956562, -3566094662, -948636799, -618443696, -2220836413, -1735566751, -728781105, -2892539338, -1248310594, -4207390414, -2630076122, -265755555, -2368142846, -2604431531, -956541575, -8064779, -1337803679, -2413576017, -2360054732, -3904718649, -1652601207, -174279593, -3395073851, -109673207, -834678450, -1718706747, -1444912654, -1931514212, -3313368594, -838660136, -1593264407, -1220119890, -867006210, -1207117535, -3409593012, -3210068473, -786943117, -2174768422, -3014169363, -1636980671, -1038861814, -3957330573, -1718777233, -2147922803, -4018933627, -61616776, -2988121763, -160290711, -2371967340, -525658542, -2008269605, -1374355435, -1601700672, -61145375, -1994526533, -1967491816, -182999317, -3290947410, -1953943673, -1188850152, -1140273205, -4209672050, -1584632322, -695538525, -3996782211, -466621497, -2231816662, -2989866076, -1647944173, -957118584, -1893806858, -2561235730, -3141971741, -4146660993, -1053270184, -2624402703, -4179991210, -2331985470, -2853539811, -468871659, -2282635915, -3334834328, -3803347444, -3820202619, -2311180644, -2433238604, -512375421, -3035625393, -2668585249, -981573577, -910296393, -1309791780, -4212758357, -3473101042, -3538940078, -2251502597, -3833572903, -3936409396, -716262613, -1367430686, -1317282603, -3297933892, -998011973, -169045584, -4034280888, -3326610364, -2380508075, -3168543741, -3384863799, -2483374987, -911615322, -2367246427, -4263918197, -2946433459, -1828040939, -1220470613, -3786213373, -1029931653, -531515193, -3822309266, -133497395, -372858391, -3002268041, -2575947808, -2477970865, -2285090856, -3748934547, -2568156164, -1351189724, -3962230643, -1654015488, -3219809510, -213863415, -2854143700, -294475832, -2925259469, -2992958641, -2445609874, -3174843253, -2722543140, -3878609888, -1954483657, -4040252803, -3191805197, -2846470943, -2302718354, -1336624151, -1845829049, -151123609, -334952806, -1179385327, -2131992214, -3343372423, -3971400208, -2081508758, -3205103822, -2953389039, -1966488527, -3981682164, -3100981386, -3825211270, -3732280308, -3614404804, -205963334, -1711620333, -2828816009, -481897818, -1182041800, -2177600552, -2826190207, -4178711563, -740593371, -363800771, -3116609873, -4231139099, -1734154526, -1409541169, -3038848055, -4147733671, -2813838876, -2510410610, -3520658861, -2232895485, -1879439464, -1757326418, -1630908752, -358581623, -2468724149, -3080003526, -2681448926, -1455695492, -240979766, -1570326901, -595231979, -1948276398, -571348963, -1198969049, -1872914995, -3579404268, -185152262, -3157343993, -3562702386, -2447236731, -3871452511, -4254377648, -3950698306, -327241735, -2463422828, -2900679448, -1379936386, -2686924666, -3383689292, -3656321446, -3020407804, -2597384492, -3481280890, -1693842941, -1362617457, -1921048808, -1201105622, -4115706185, -3031844430, -3369435729, -2662708395, -68381033, -496918108, -778593765, -482187465, -4164192808, -2630981296, -3874843849, -537492341, -3527897705, -2324224957, -2880137328, -2270977619, -2839681091, -1432902627, -1119762999, -2107478755, -3276900411, -3869025559, -418653711, -3936790505, -1484487377, -3075736977, -1847878557, -2271266259, -3151328998, -2331887958, -899511962, -4101265034, -1295568395, -2532442524, -1032019548, -2239446867, -3498261076, -3490418187, -3077153311, -2553294355, -4205251900, -2215362351, -2822008631, -1381599025, -2722109546, -230489470, -3238100582, -454625303, -788386940, -1173179450, -1541306729, -3021818788, -4095256074, -477101034, -3415142462, -3502293296, -2615435254, -3923504818, -596289891, -2391269779, -4175718228, -4130491105, -1597534584, -2117917474, -2444737912, -3726384146, -1108530189, -764010725, -145537517, -3956287715, -321432132, -3769224489, -1640616538, -4288392594, -1871187149, -92565602, -1012177144, -961949043, -4196910031, -1129457302, -1939739400, -547287597, -1675581451, -2004233629, -2751764056, -2225499852, -743264266, -190109749, -2477053254, -1324665254, -864478753, -2726100736, -97562733, -2708688289, -3381593055, -1964748589, -3439542859, -1842518289, -2812527593, -2735215105, -747097851, -2579925774, -3233491123, -3346256713, -3806860438, -4221423624, -3977202337, -1010078012, -3698899123, -223531990, -885078958, -1526796541, -3095746615, -2485349314, -1078673575, -1837776206, -552369252, -509434443, -1986967283, -2822096321, -3622586537, -3278998535, -922299570, -1494143818, -3407150185, -1448747792, -3454702586, -3462343483, -2204688536, -1430469710, -1587654637, -1659206472, -2297511422, -2767980691, -3663432796, -1564329168, -167810343, -549914202, -276430170, -3597942809, -111301047, -3437061710, -3716133055, -1454825418, -3484472479, -4106040967, -3687667206, -3860717577, -2522320916, -3867148564, -2599332289, -3548259231, -2106073132, -1828096950, -2557691091, -2832038044, -1327330974, -1037930401, -122909606, -498667704, -1143339727, -1703062872, -3117446548, -3006466297, -2466532272, -1452365863, -1531870332, -3151361050, -2376605833, -4251800894, -2203787046, -2846331652, -3641256943, -437345180, -2866802387, -2368487832, -1288716327, -3874064286, -1961204958, -243105376, -985797628, -3183731440, -615313437, -1074130897, -791158984, -802403013, -3948346757, -2279334041, -4113133314, -1620763024, -3077551002, -1429034428, -3504015820, -2960177462, -237375563, -3084845696, -129866773, -1353479408, -4267263751, -1973343825, -715511510, -2476805593, -1928256950, -2344823449, -1997068132, -1355235887, -2710411933, -3923599412, -1544843346, -3468086010, -4132527984, -990811486, -1373727087, -1744145653, -1306737962, -3964183974, -1705891266, -305922590, -1233033188, -3903708291, -1837760087, -4081441170, -1671045448, -2774975741, -2887013395, -353130185, -1517769950, -650454198, -2628089246, -1755284285, -3155510058, -3610109611, -3459220224, -1617229167, -3005643795, -1527612914, -4100575392, -2735224381, -2557079634, -187665889, -3689800541, -1640469591, -4054490870, -2695902228, -1869701544, -2537199356, -3888076487, -2112096968, -3301855343, -241299522, -880004177, -3605961803, -218470881, -3508308597, -706298114, -3199051610, -603526977, -3589092682, -2721281212, -91313103, -2947851253, -1363090946, -3857746945, -2004724325, -347403425, -3008113656, -370054415, -2990169643, -2373042615, -3915164617, -3435179263, -3116878665, -942315263, -1567369052, -1392310018, -1788645532, -35033987, -2045309968, -1302881817, -3108101877, -1994584563, -2565845916, -2012249375, -1477347155, -584173495, -2528321585, -1641787181, -1575390263, -1795749155, -3048659790, -2387269385, -1266405669, -983424534, -2503427170, -1681517571, -1994588153, -159934859, -2902356434, -3516942418, -3814589313, -3527986984, -3865673904, -3990604844, -990952529, -2341709225, -1947952232, -1490770604, -2267502278, -3034573777, -344543640, -2926293933, -3019230414, -2688082320, -2024323445, -1689023880, -3646561147, -240733957, -1104440307, -3746100789, -906419511, -2678300125, -2688935332, -3671849128, -2006491212, -191060302, -3354825360, -1613040517, -571622322, -4013139871, -81961837, -2096618150, -3138425116, -2407986405, -772381258, -1478411311, -280323840, -1116765820, -3566857175, -1905456909, -736410243, -3636411317, -2951104609, -3333696187, -1619377780, -1971787338, -121636474, -1090529056, -1629546138, -2747316081, -227738777, -3902351475, -874117934, -2201203627, -2891635376, -1682161701, -2681256796, -3104209136, -1509354090, -713748930, -1363975280, -2724510007, -3436680062, -1886633500, -1539393460, -3887279395, -29252314, -3417416990, -3387505181, -1442593997, -1886599082, -3594212662, -2605960239, -2580014268, -2455621948, -2142812682, -3821895822, -1479584572, -3996249409, -1620391498, -2913249856, -3360919197, -2817557024, -3981897379, -94151786, -4050800800, -1915892589, -521694597, -1726593097, -305927680, -4246569131, -1607589104, -1532557509, -2098820312, -3405182169, -2169786650, -3889934776, -3305611569, -415136468, -198331962, -784292515, -2520415563, -23930465, -1638765098, -1222711365, -438681567, -2611660330, -2488796266, -2862750136, -3809955565, -154111947, -1706573983, -306740724, -2286776029, -385305240, -486498299, -2415052390, -1233651887, -2066170667, -1511023088, -705790790, -3413267820, -3828686453, -54591973, -3139790673, -2323931115, -2137410718, -31261611, -1983242259, -3656051544, -2499065085, -1078474669, -3289036811, -4039767182, -2710292480, -523311736, -477057201, -1436491617, -3256383199, -2879344492, -2578981034, -1349839410, -3735998220, -1222650600, -2538403957, -2353322419, -3360912800, -1128457025, -4209782923, -2338075436, -1318145809, -1915925403, -633063010, -2774000747, -1437302084, -3014013030, -1952735329, -4003957377, -3059122381, -3038555378, -3105946324, -295250685, -665740931, -2176020475, -3576330388, -3788863086, -3498919204, -698304973, -1073116372, -3650713391, -3204247720, -1622071355, -3172987202, -2909756157, -578927761, -1933127338, -1912360133, -3585027028, -707898692, -2973949155, -3805767844, -2974610728, -2558191273, -570689394, -1405210178, -4112669924, -2835219107, -3832391427, -3119959974, -2263489392, -650977960, -1113571233, -743224359, -4255866364, -1200197954, -1302675029, -4146371170, -4060172295, -3759825027, -1299594465, -3291413291, -3258127173, -3828846725, -2668171590, -1102802660, -514606392, -1911006606, -4226764084, -3622782315, -3850418256, -4275015673, -932019999, -3083692378, -1372816940, -3205733688, -1526236279, -3594088664, -3630798170, -2700126597, -467198768, -808724215, -621411267, -2627539850, -3714425442, -1644397326, -3141748984, -3933487485, -2222923937, -2494236215, -1565310754, -3837200537, -3911315965, -2148894718, -1419781690, -2545719854, -2017790352, -1060002113, -2439524873, -2112560544, -3375646227, -2175620264, -3525860580, -469468553, -3472776328, -707527629, -873909096, -2781528263, -904617997, -1715475039, -2327697019, -3501919374, -1083581075, -3472852485, -2010350740, -4281348727, -931123904, -2449131599, -1293328590, -3087315738, -1954619703, -1363069108, -4160047805, -2511521117, -4028959986, -1843610467, -691207881, -1055400860, -1176679833, -741418601, -1230421843, -4118313787, -3196237599, -629981413, -1353553401, -2035944913, -1996030028, -3500496252, -3663152113, -1623909093, -1997057671, -2836002996, -1520246398, -2782209204, -3590510553, -782410388, -1229774441, -2654115577, -32610146, -2886797725, -1467090009, -300661539, -2280338505, -3484828602, -3703415311, -2613495257, -2397939148, -3900086374, -3371083678, -255864635, -3661717138, -3780251218, -3229133208, -4126004235, -1827643373, -4161623689, -1076495132, -2773023547, -3977428115, -4027141224, -4022896608, -753888638, -2112393435, -2854753830, -106181885, -1641906509, -4084267189, -3714379640, -3625891484, -666225957, -393417547, -3731594852, -4174908748, -1421467404, -3135141792, -386343862, -4096724097, -1141262772, -109893804, -3333481503, -4268513788, -239162983, -1021621047, -2442738475, -2077444086, -4137696807, -4034666045, -1385758194, -906271054, -3407231920, -324204089, -70283275, -2859814564, -605970575, -3341251473, -1751369058, -1484204455, -4055466698, -1266110710, -834456696, -2945714623, -2463877568, -4126484000, -2914454439, -3473067315, -1152591623, -4067995915, -2187190871, -4287783293, -689752166, -3904096298, -4019239979, -87825513, -3951997429, -3592963055, -2506748886, -1185853860, -1271994722, -1749174670, -2250832728, -106340986, -3316413025, -2104591515, -2808114267, -4231033617, -2849332962, -697483205, -2951013325, -1345366657, -3681086947, -427042456, -1031359086, -4190604605, -3705879351, -651401557, -2168525255, -1179724659, -4000477627, -1110421249, -972392748, -2383989037, -1630156249, -2452228126, -1440249614, -4113588352, -3193445115, -1297426292, -2840036876, -161220938, -178550183, -973233549, -635158319, -4285793974, -3259398303, -939688018, -1797033734, -1561532480, -1577613903, -879984740, -40956427, -3389872591, -2847095066, -889083828, -3567347091, -2960496645, -3173315633, -2752131999, -4248713545, -2103316155, -2763171469, -1806078305, -3732232199, -1876026150, -64419977, -3378334996, -874062501, -2811334487, -3239789501, -3281902468, -1867261708, -3862801401, -4109966978, -3718195893, -1418942753, -2709969239, -2902124094, -2246388478, -2694780828, -3158050976, -3112316111, -1216957597, -1205898319, -4052058170, -1415940708, -2737367930, -3519151385, -3306060375, -3241333061, -3498363222, -2273353015, -3141607614, -822667577, -939582865, -3457216580, -3122300009, -3893679833, -2926719088, -1222217839, -519589852, -2051141001, -1289623747, -3856730233, -580050393, -3578433393, -2940020359, -4251709839, -3078748614, -2383670314, -1947546933, -2131471772, -345467782, -247076074, -2087295771, -1780650796, -3451775872, -2205308566, -1289786910, -1856861201, -3667366857, -2747363240, -3061313017, -3737566580, -746845040, -3365248458, -465879522, -2336691513, -3244424031, -2949945179, -3131938883, -2323193382, -1629473598, -74517872, -693282552, -1401338197, -2059561901, -480679305, -492408773, -2842596738, -1928946974, -1556324852, -644801972, -377604411, -3507352022, -1566394079, -585403091, -4256503215, -4047410449, -599678968, -755847773, -416583332, -924673431, -4068621336, -3299213666, -1858105006, -2209382594, -946582317, -166894942, -2775977964, -35940492, -26720766, -1544640609, -2721386448, -3018648446, -1795105984, -450451871, -47924972, -4018597842, -94333091, -1152798230, -4206357496, -2814688071, -1391174106, -1044262829, -2751113418, -922015423, -3290119843, -2694743434, -1424533290, -3618245730, -148311613, -1669632862, -1259281654, -2112848201, -1267994072, -3752190421, -778092944, -1065306486, -3628422609, -3368833366, -739415868, -3300943646, -3660447357, -1184962005, -1023973971, -1832394431, -1137006121, -1444835716, -2243665804, -1510762575, -2466533739, -3887879731, -87431003, -2245321996, -3488038838, -141734164, -3971165360, -756469155, -3364184523, -754560364, -2665145269, -57637962, -4093465722, -1327652707, -3826955867, -1137517370, -1021828340, -2261392404, -4178377033, -2292992397, -3285905257, -3598194725, -983118410, -1029281061, -2321602652, -1845928321, -3522297760, -1310221761, -2910256805, -4168224398, -469292887, -2256060893, -4146198434, -47048237, -3923355269, -3642888337, -610354337, -1290314301, -4182972872, -1917019737, -2491766577, -290465802, -517620648, -3578997878, -1100297972, -3586316575, -288631148, -2319560691, -1315688103, -4208617262, -861072784, -2753553030, -1707222780, -2488338596, -2824399368, -399952202, -541138014, -2634795111, -1380588065, -2884569974, -1669364475, -1845573784, -727314407, -3079941310, -88920742, -774893565, -644466339, -3355103973, -2508983306, -1616835140, -697521312, -1947166067, -4262913619, -3973161467, -2662724186, -801060278, -1278126817, -3538819829, -1046373780, -1242428115, -1950723138, -3120616612, -3794218520, -2570220606, -157873341, -3681001549, -3174092538, -3297711384, -1178368136, -2615377719, -621866132, -3600082223, -3051974582, -777034085, -502684455, -3588170470, -900568396, -1188169351, -2454690919, -2759485199, -589853708, -1482643341, -3269509858, -4114077244, -1267078290, -2643888426, -2710957447, -3503645526, -2970349503, -2315815958, -1755073321, -1890969605, -664832488, -1612683911, -4091836525, -2052989216, -2487398724, -1119117166, -2831040891, -501543761, -3541142470, -2138402560, -2704123324, -3063894009, -907208337, -2391939173, -1871934161, -2296000970, -316148491, -478616267, -178932848, -1807570335, -170290673, -4200306937, -1235118929, -1632303854, -3929758635, -1719419516, -4202329426, -2270908878, -154892532, -4033642888, -2954638137, -2138805170, -1073292335, -3838880531, -2956744551, -683260113, -1058658521, -145124963, -2114075111, -3098614586, -2265113394, -2766161824, -2618745989, -3796443850, -2961063541, -1345105459, -3086757577, -3492583196, -2411316773, -4203234993, -3555562974, -4019740338, -3200542092, -245388791, -1321239163, -1018098491, -478813805, -1349629360, -116365388, -2829053574, -626660299, -3294643794, -1546456385, -364639417, -2356207603, -1990979592, -3603898189, -635769434, -1759863385, -2465548270, -2176862513, -2837070080, -3606039587, -1294238105, -3745054739, -3548988101, -1772402902, -478273713, -996373041, -3129297085, -4060256071, -3499026742, -3767126528, -1693796377, -4049659957, -2046881553, -3006833263, -3537791334, -3264869214, -2603443626, -3765416659, -1183636515, -1604929602, -3163716127, -208451853, -1405401123, -4233447819, -209051442, -3709348332, -2668688931, -2014257406, -1092145494, -1747115477, -3333235768, -3726796454, -1928065869, -1939661270, -381461895, -2986799666, -2686771108, -852203991, -2940759974, -4288501374, -649669963, -876164358, -2346642848, -3188553501, -2269406376, -2297409734, -3833018712, -1120059300, -610115094, -3293442648, -3406544426, -3441094940, -352194430, -1849275980, -303451921, -1958728118, -3431512226, -107111815, -2792393980, -4196967164, -3387128122, -133410670, -598568870, -1166783145, -2057844438, -2466132563, -1832846732, -3474342601, -3242265320, -4076909099, -4258385544, -2813494117, -837930831, -249012852, -4267886827, -3012543658, -2885922022, -2546885088, -2873663264, -2104689100, -3043603103, -1727701715, -1527566359, -2021285195, -853923682, -1601776501, -1537323330, -3864782999, -1634707762, -2628101842, -3682334223, -531500868, -2249965471, -4023253015, -1396775531, -3400700785, -990984689, -4150109569, -2880104305, -1722217967, -1529229703, -2977166545, -1944579572, -4140284148, -2894291542, -2670872778, -1052986620, -1256528784, -3208561009, -1106595415, -1660227911, -1262912849, -2648045196, -907225341, -2069175786, -2303501909, -4217189804, -4250877671, -4280759246, -3793828201, -3220238174, -3453823961, -2202349049, -154105725, -669884160, -2735732110, -1612371835, -3637165716, -2792594445, -4165140488, -4057719073, -448970477, -2930997281, -3504304141, -76078266, -2895636178, -2754804295, -161221875, -3369697372, -1908781193, -1234242916, -34566267, -1338172967, -1915345325, -3460865100, -725064382, -2310617998, -2326540261, -2493386551, -1218269767, -3284068704, -4178641926, -2618389321, -3676873666, -2171813142, -3431634578, -2519495100, -2289249104, -3018903555, -3885927311, -3471333724, -1461429387, -1775858644, -4182761131, -2689362227, -289868946, -555815918, -1167094243, -650114454, -3210060002, -3524019611, -83955706, -1110148850, -2730747216, -3622483551, -576212994, -3981520799, -1546330989, -2884715884, -3322863329, -2860887719, -3165366072, -1375454844, -1338923403, -2205723429, -2040782351, -1652384314, -681348651, -2607348999, -70510970, -3941035972, -2471511822, -4113378426, -1896136362, -3263853133, -2457342066, -1209090205, -1585596789, -355667979, -3790592385, -3297332770, -664484485, -234938003, -3217017854, -589615710, -2480958624, -552580693, -948786491, -197965089, -3335636823, -1598041325, -1365305971, -640708253, -3064202505, -1869300032, -1535749488, -3200368921, -3573063502, -1097110860, -336354782, -2483127284, -953912137, -3578272246, -2884828291, -2600991933, -1414027328, -4045943680, -1784086928, -2819984730, -1107780363, -1128143179, -636732234, -1205803186, -3830311423, -1729942684, -213769648, -1051667689, -1628813092, -240733154, -279448888, -2042200808, -143969710, -2904964595, -2561127027, -4225400440, -1438481505, -3886109506, -3177068067, -3224818674, -213480066, -2899524783, -2642831213, -5220849, -3004169834, -3406784252, -1767492054, -2146414908, -1310821716, -2905583344, -1172777701, -1973672840, -2791429215, -2989719729, -22737538, -613520387, -3439588231, -4126707069, -4202472767, -2482481949, -3122088206, -1239535014, -2481345226, -528510312, -4039402386, -2936006493, -3756987050, -4191079199, -718727819, -907654619, -1088522230, -1801476214, -1717691184, -3494370575, -1643123996, -249855238, -3622667088, -3380616441, -3950308131, -3758178128, -2334618731, -1066891285, -4045748656, -4292513159, -1404961129, -338530546, -2071787808, -1247190781, -2916068217, -1023311727, -1974533019, -3826556608, -2723922501, -835945731, -3531123024, -2386521540, -3838595928, -3154826415, -616897413, -3526591566, -628562738, -2906363077, -1725708293, -2696647623, -815242900, -3549741924, -2281067671, -1268487497, -4244940167, -1418597659, -1488977888, -796052259, -2935345131, -555798050, -840360737, -252236329, -120420755, -1090533771, -16983157, -3647172663, -4026815419, -3887622047, -621454581, -2862973190, -1234356438, -2111853887, -4196626825, -1018012781, -3772452221, -2672438686, -1871865774, -1056690695, -4012309057, -3263435839, -2103318465, -1584784391, -815195057, -2279845454, -2003013675, -1907738732, -2036562344, -1727215144, -2347324993, -1703275006, -1996550723, -2755419973, -1291679988, -3832798297, -3124328559, -2661399824, -2226020061, -2000621015, -1038151553, -16881353, -2327115439, -3968849475, -3080572551, -1440946974, -3158836783, -4052888457, -2105453117, -772952469, -2934255224, -2120987699, -3646779513, -4026041001, -3681868868, -2141475877, -4286048203, -1373750360, -2086322629, -1755429092, -2364054010, -2449754613, -3819036707, -2732295195, -1410809244, -991111086, -3517342409, -494925338, -1558055924, -724374310, -4266689304, -1977991164, -1871731157, -449642534, -1470426817, -450708433, -3474806685, -1116951386, -1394629698, -3948659857, -2207929480, -3161391161, -2024282236, -1846365440, -3040989520, -3798077976, -3206080669, -113427201, -1162651530, -1854146080, -2510796291, -1147423021, -3749535867, -1101369278, -2285581068, -2331787912, -3112699867, -2192688498, -188206762, -1377049652, -3969104466, -346903321, -4059465978, -2306873777, -1688433202, -3102543393, -98973323, -2309195358, -2544242468, -2632850129, -2013179231, -3587147434, -3898071747, -55299238, -94138685, -3554026983, -3076855938, -2317179824, -3032549583, -905587541, -3785702543, -3744919281, -3150908567, -3918244757, -1655771651, -2796647757, -3901656631, -3042372331, -172594238, -2352955506, -3304263836, -3471985664, -3396936121, -3022674912, -2115246784, -2364634035, -2869133079, -1992949131, -42816507, -1798466902, -3730431613, -2752605872, -3113846125, -1232468123, -58955582, -1017057481, -2306114066, -1223108719, -1819430215, -3352989008, -653893631, -3960963250, -2626964131, -1599136828, -507239730, -2678431883, -3275786863, -2396577458, -1587592677, -1126183079, -342136119, -2528600357, -1769614887, -3970554662, -1843590651, -4243214897, -3237440344, -3857592407, -4164018936, -1737965758, -1024507378, -2798475698, -4023181423, -193124270, -1624836356, -349464871, -1277216793, -2213910090, -3280768999, -2336547754, -3791017403, -2596528658, -4179895454, -3847981053, -1007198738, -1866326261, -624353091, -3171109770, -2218900863, -4063504518, -3066531753, -870976874, -1506382727, -2125589031, -2662671962, -1616219711, -3483738161, -4202403598, -1098253175, -4144080718, -2254471640, -2467198150, -1652062908, -3850727801, -4008845432, -753252493, -1393970727, -2890404448, -642653544, -1403853123, -2844058715, -2817095996, -266265243, -3093354879, -59168634, -374875082, -1142913165, -2989163227, -2087739576, -1846292950, -430536723, -2440477575, -2225848418, -3155819256, -3517245216, -1806127000, -3076628333, -1793759211, -2235700526, -3789985757, -1375793506, -3992601708, -281051104, -756065554, -1859977136, -1851507151, -2683166423, -3715616930, -1069407271, -2648486839, -2994389622, -444946794, -3067682329, -1855321908, -3063042838, -3235448546, -1296709790, -1653983936, -1943213723, -2001513392, -849941959, -2517724738, -3972262104, -1080070512, -4176584460, -1147336519, -3495260868, -1134228864, -4092974699, -4108207586, -2200603062, -3056044010, -40535308, -799206900, -1538803945, -3537375302, -2552874494, -3132043752, -890520775, -1064194921, -2588282356, -3800633163, -4274104570, -2216742089, -1782417719, -3948549862, -1441181290, -2321646972, -2556532088, -3382365594, -1814152693, -2139498607, -1529779873, -2378184202, -2945930372, -516203525, -2944413946, -1733308975, -2212210578, -3080977709, -3710133640, -3453244160, -1393791109, -3284468198, -3420478956, -1255764931, -4078572851, -3459787570, -3755167768, -4108709537, -3338962494, -3117062367, -2680474294, -396668701, -193529478, -3149871866, -1259297548, -1318699516, -1060673250, -250991745, -4041564528, -2608671566, -2408988094, -2390865805, -3621178316, -3008168019, -3109374332, -2708534147, -242046742, -3662627098, -1088522543, -3318081447, -435090776, -634484806, -1402095258, -695752950, -4024050137, -1348842170, -2004122332, -2730609472, -2637182997, -3139924861, -2899821862, -2603511854, -2197892813, -2521701766, -1603301914, -313787101, -2848238398, -3481493700, -611135260, -1845186273, -1353420298, -535591917, -427997301, -2829092376, -1582591810, -1405620579, -4036252795, -2768837036, -1318922640, -788500597, -464430206, -1475859524, -3677098332, -1241981516, -1737701971, -94705548, -3684986005, -3263509577, -1806021626, -1962450569, -1171961048, -3652928825, -1803677046, -3548440221, -2868281680, -2644507898, -888864866, -613145519, -3648829580, -3739101845, -2977085004, -2091925294, -812890899, -2953719729, -1510976860, -681334786, -4267240219, -1454866146, -715185977, -2678293333, -3894027206, -4161893636, -2496420628, -169409569, -3876364417, -1974606807, -1050682684, -2063049220, -1789286993, -1543267393, -2002014655, -2690427820, -1616771703, -3068029361, -1246871634, -3955527145, -4022823011, -2382700982, -1142829837, -4193164707, -428746838, -33699479, -346499672, -2170432689, -507898520, -757843398, -3601650918, -3520796476, -3037448502, -2577411309, -229037415, -3808806159, -1936333285, -3226179528, -3150698150, -1537155637, -1267547975, -2161264921, -100225846, -361618468, -3924681856, -3501184877, -2295547184, -4231322428, -1378651377, -2923697207, -1571052946, -4116309998, -2695310320, -3461722973, -91290826, -1951923152, -1554564830, -4133638839, -3085380253, -2911865643, -4103053769, -1529337327, -1978924775, -1155922327, -722286166, -3140163189, -1602798545, -194650968, -334027145, -4249968797, -2862104972, -2418100014, -3292995758, -3908718919, -1362409842, -909436880, -3313300001, -3455978885, -2610780006, -3025019744, -2369687247, -1819981160, -2797593670, -531866335, -2799381077, -4014390866, -1785132158, -3583388369, -1383415172, -842757831, -3144586563, -476579126, -2690914004, -2815436884, -331566760, -3686577918, -3458479824, -598165823, -1185905171, -2385897187, -3578671481, -3130559476, -2485756643, -2509471276, -3493925324, -2977005389, -285793772, -3750552649, -455370529, -1535488807, -3710527803, -1409667985, -1544145328, -4139867973, -3441868871, -652586784, -1538930748, -1607866306, -2480554227, -339938563, -2276834056, -581464195, -3740791894, -2886087876, -3399169119, -2590812592, -3154608812, -2693109824, -583027342, -2882520098, -3088768831, -3404303893, -2876903629, -574112023, -2985044568, -2982524407, -3034285132, -1186179736, -1752143450, -263628901, -3433999434, -709478379, -3493995213, -2957946720, -2925228496, -344626088, -1462822763, -2244939872, -2622411260, -1148638411, -1059376641, -3806588020, -2672098819, -3137152727, -1754491891, -1543616084, -763034031, -3608640927, -1142805590, -192634961, -2816664904, -421967842, -2192707003, -5466989, -3670734321, -2732244435, -461909929, -1322424724, -810252892, -1811653543, -2088195102, -1002876008, -555177288, -1148209149, -2690801908, -4052223819, -1242549528, -745245967, -1830070819, -2577182974, -2249964177, -332402825, -3212179237, -852635454, -1484791820, -3153323041, -52100584, -3152339932, -3099122265, -1312146473, -192360323, -890267645, -35264041, -2826528526, -176218550, -3630913812, -3559007709, -2089029742, -2485853788, -3573475808, -1245085624, -2091849064, -247737190, -2483402993, -685126191, -842411815, -1182381684, -1347817689, -511717847, -4035744748, -814303696, -237351768, -1136636944, -358982743, -2440619154, -1783132099, -4073095764, -3595208388, -2459525271, -3959967399, -609700355, -3488267302, -466411408, -1324796425, -4077731283, -1593069003, -3004502738, -2174754507, -2322259504, -3810211307, -1370116360, -960869323, -1028094457, -2594629753, -3671622237, -1058466526, -1844596026, -4117222101, -941984048, -1930619712, -1274079829, -2542605674, -144149890, -2437854813, -2183515257, -549578772, -539804838, -3696196179, -1724984246, -772363501, -328939090, -1863147493, -3782382780, -2177586270, -2878092669, -228073533, -4256020665, -1907080446, -3640644831, -1032858832, -2667740207, -202588015, -908321888, -1827071466, -731910062, -1447508040, -1514127579, -2404055796, -330100875, -3006622799, -3375666200, -999442982, -2177555517, -3234765007, -1516623147, -4030449568, -349947679, -4125201867, -1998580954, -4121156500, -482673691, -1381259827, -3977329885, -3189292041, -2339488255, -43826870, -1041196239, -2728779458, -2806878476, -3742203368, -3051314026, -833199208, -978019483, -3963631707, -219491251, -2469264977, -2867259620, -2096106440, -708154761, -853765131, -3188396061, -4000874282, -3765167902, -3766976758, -3525853023, -644661299, -4156853617, -2351146852, -1972661253, -2844631759, -2658114516, -825743799, -2152737909, -1222894206, -28581670, -1574540384, -1062695127, -3862256132, -716463042, -2350120212, -3111649668, -1612313843, -2911871556, -1675499883, -3984482595, -1354456097, -3972538701, -3781110486, -3438165480, -1102801287, -328187810, -1212085751, -471592006, -1328893958, -612057469, -4179611290, -3214977844, -1169542606, -3054478449, -3168549252, -3103412496, -291207821, -1047526180, -1154146323, -476961405, -3380005731, -3410074970, -3390056107, -3990478782, -2834288020, -1386433193, -3952892775, -307254308, -2565364472, -865537976, -380057543, -2570817658, -2616463919, -2231068331, -3219142982, -2223043065, -2583875278, -2290379516, -1967238748, -26640516, -3176385967, -1762477340, -4200070287, -1715552722, -166612344, -1421604132, -364445730, -4209288812, -3573884336, -1271544406, -277809692, -3879697294, -1816738441, -92341008, -3083358859, -3512942846, -1441241989, -3897116442, -2451581909, -2986208801, -3680722876, -2210486764, -3511963040, -323003601, -3753535, -2783425655, -1241624612, -2456697173, -611663803, -2624786342, -2064094191, -3651193443, -509483991, -2707852084, -3935152112, -616744160, -2408397712, -1608455004, -1701094052, -4097132454, -165160910, -3975215784, -3811739047, -4206222294, -3495861102, -2633140154, -4008119342, -4170168680, -1947022167, -2984851762, -2264560731, -3495132144, -4043426969, -254300756, -4171577814, -1816487048, -431942833, -2823505614, -3880837834, -3577882210, -3937178583, -190256347, -1415361984, -79748326, -57798602, -2759512250, -3971246512, -2479378676, -3803561465, -3582709282, -3855617862, -3385719156, -2297900348, -438635613, -1904240036, -1269867838, -2955510883, -3295945165, -3626638515, -4288241783, -3205955229, -3465648650, -1672263461, -279576243, -1033469870, -3012641162, -2523148664, -1033770280, -2453789043, -2571957796, -4047601198, -3968249839, -140753797, -1092399022, -3696258737, -3122148145, -322790497, -3885858708, -2423714240, -3263102841, -3841408376, -3907003288, -3189077896, -1515414571, -2767350326, -3851331804, -1762654176, -311755552, -266280364, -3099101429, -3540441595, -858400940, -3494550023, -3296584411, -494270590, -1121413308, -2403961306, -694768247, -4042061636, -2992502371, -2950124328, -3779015063, -361782229, -2346203612, -3800351376, -1254048278, -3509158051, -3232962766, -59948814, -3885794096, -1693128876, -3512639670, -47527700, -3658858426, -1057602140, -1696266069, -401384488, -2769287646, -3388601813, -2637276885, -1790588740, -2823430431, -1025846056, -1580740390, -1434852411, -3511191973, -3690433645, -4145642678, -15675190, -2473264417, -3798088188, -2640948933, -1330129827, -741632230, -1105070827, -1114311113, -563072149, -873233771, -677485756, -3165796646, -3970270042, -2370235628, -2675720437, -2840325522, -119675196, -2263918001, -2670833757, -4121083389, -1948246652, -1500211988, -2517065, -1248499532, -3250694934, -763372497, -247430468, -193085276, -1895931896, -1861401076, -1729604657, -2823537751, -4218644876, -3856687159, -2825312233, -1070893946, -608836359, -2198035295, -2576702583, -2894306946, -736149592, -4203700213, -2768317502, -673952107, -3650795210, -1892732371, -46231013, -3862305103, -2463217411, -1374739598, -2519785247, -1857939905, -2577388439, -3279157380, -1541765254, -3614468695, -2289295900, -1196876192, -1204567307, -2492715714, -3656632886, -729060106, -190291441, -2480603267, -3032053167, -3987892446, -2479084038, -3083320624, -61708672, -384903402, -1973983801, -212653931, -3382495025, -3229031653, -2447959290, -1537459501, -234500585, -379599349, -2126755578, -168063931, -2022159768, -3242034923, -156822223, -3386119514, -2229900602, -2957594763, -706200667, -648515710, -3303982468, -192192208, -728608237, -3987502541, -3660416178, -3580269426, -1516198246, -2976430980, -3411215582, -1515362558, -51236395, -1219233416, -1697887230, -3330842705, -3014713156, -3718002503, -754507576, -2081533217, -1907276770, -1897501424, -4163128277, -115300738, -2299158534, -3301894420, -2485299437, -3168365947, -3983903341, -940058296, -3848666728, -1437338956, -2437322642, -585966238, -2895633147, -298281734, -970793529, -2714604501, -3893011505, -1645410119, -1930340337, -2519530773, -2390814219, -899912264, -3595876152, -164203321, -2817485280, -1691237152, -3994910276, -3942464483, -2256971397, -3516073408, -1238713034, -2126147732, -2830624908, -1978051010, -2297958610, -605894490, -811114293, -1048433253, -2577415473, -3880000488, -265884060, -2775868623, -1345331417, -411206078, -4015938926, -3274036334, -3860364777, -4019139497, -2517832351, -3314258122, -3782664760, -4275064310, -1470779568, -4086400831, -4200468898, -3533943812, -1995554512, -2202075994, -1162922920, -1025800628, -61464422, -623807249, -2367373693, -2449552654, -984011012, -3757991620, -2402185279, -1825587020, -1655360841, -2496747775, -1484463816, -1684398840, -3210845732, -1214034441, -3758250729, -3432967320, -2757985272, -1631237507, -1623848641, -3528055933, -1481001034, -1767905746, -1328480621, -832104648, -2217187632, -1086817282, -2277856640, -3820307885, -1249977406, -747676289, -3740190922, -2789268521, -1837760063, -1882365922, -2630431294, -324310580, -164160487, -2203329853, -925533837, -1127984902, -2943174864, -3716189633, -1370382166, -2146774645, -1828784587, -1908769026, -1845957244, -727213773, -197711672, -3135257871, -2283552291, -146168301, -3477146533, -716455117, -3044726319, -3293331770, -3375019962, -941012688, -1328705877, -4208016482, -3557230520, -3305260452, -942638831, -2216561954, -2198351701, -334075277, -3095570511, -3881568061, -722677875, -2207023998, -1443953240, -768888878, -2524457910, -1884007599, -498543661, -1218428694, -257862667, -3743406172, -489230306, -41335349, -3380177977, -980374303, -42971781, -72668614, -916188784, -2909038795, -2507973696, -3490384182, -1295761813, -3659824948, -3458361907, -1653430424, -2834151129, -2258503473, -1990677510, -3828791084, -3552551515, -296811476, -3560779996, -3777140492, -3678016569, -3318895044, -281747522, -768187339, -1583265083, -1492215772, -2712869327, -4245528326, -3194913548, -3807612735, -1238802421, -608403781, -2736648343, -4062040765, -1886424145, -3437499712, -4149413278, -286416232, -3973427863, -1534790878, -3096950465, -2442523725, -857833718, -1716287084, -3616629603, -3881483877, -2525931380, -3301136501, -3541629902, -1894662643, -3187829106, -4044922507, -4060861269, -2043228839, -1229439747, -3168337705, -698155569, -3156570180, -2024829500, -731830073, -1383645016, -4176522506, -2487769575, -1952718072, -4114890851, -2584435364, -2936711832, -1502760647, -1292903484, -2348267181, -2586221469, -733965240, -2647755375, -3426857161, -2188540157, -3273081473, -2314206583, -1345164299, -1967411136, -40661835, -1733808951, -2878188249, -1391797727, -3640985056, -1627548509, -1523410345, -2912117082, -2634113575, -3540178494, -2854726165, -3853411024, -3308540798, -3973317449, -3860785075, -2047059310, -1723370999, -3240083356, -2394837864, -1616043483, -2436404767, -393613375, -3561674455, -472369339, -2078546126, -705019416, -2446787209, -2537043752, -2924399203, -3661173745, -3537977525, -1517736734, -1252033732, -254361802, -1288371554, -1665770167, -4151172256, -858412833, -2429732015, -1202658545, -912846648, -2349948623, -3499274075, -972591453, -914569334, -1139163639, -3205324595, -1523935151, -3344228627, -3554576207, -4033228255, -40166711, -2301825405, -1578975235, -2376507566, -2434184865, -1265932785, -1509243532, -3014157016, -1897768785, -1611957702, -2284638551, -4220848871, -1410763253, -925857085, -1190000061, -1863698750, -2466040595, -215066608, -1932373886, -851343400, -2262890905, -3227673184, -261934226, -3617238675, -3252704269, -701673202, -1110230203, -3601069235, -4222849379, -2334434383, -32701353, -521145597, -1407960067, -1098036710, -3031707234, -3134905511, -954557237, -1156421373, -3650768300, -2258626615, -977439374, -33182993, -3768358586, -184890756, -3256395519, -2459840211, -3272664580, -4277178767, -1395727988, -2997041265, -3888004671, -1911109431, -1426665863, -3292851959, -4117272033, -3866154773, -940802546, -2515780528, -3374607710, -506859769, -291776120, -368125450, -1555048383, -2449733576, -745543662, -2216822247, -3749735919, -4060532107, -853865822, -2471899000, -1265474754, -2498694298, -1995053956, -2474183299, -2170796635, -2214548150, -3734798914, -3745723510, -1986988915, -1726048194, -1710421821, -3576780165, -2839164025, -2633704664, -2018518182, -1284698683, -3460673963, -3716306955, -3991189048, -2600339070, -2015141241, -3241819601, -1204011245, -741545022, -3941937473, -574049770, -2638071255, -4170406071, -832998274, -2210898451, -4163786361, -2922994256, -415872293, -4037635731, -2708884547, -1016416710, -3438121629, -1169875466, -4027398161, -1228050410, -2287638968, -4158317292, -1349388777, -2320276240, -2307269469, -1932684273, -2403249517, -1360059137, -3894780727, -2320918367, -4233224173, -853144587, -3186217373, -1681720759, -1667109564, -2704094735, -2661547455, -2838101396, -2465853998, -817416798, -2484593609, -1799893238, -530376255, -2093193091, -1149900754, -963151686, -2458672767, -1397224169, -1373684122, -2722792153, -2514817458, -849323157, -2717572622, -1988596788, -686490963, -1401851016, +2494, +8449, +4406, +3397, +6521, +1726, +7045, +10151, +453, +7517, +74, +6818, +10142, +3664, +6193, +4998, +2714, +2874, +961, +579, +686, +3124, +8066, +676, +8838, +10031, +532, +976, +2430, +1748, +8388, +6721, +3354, +9743, +827, +8657, +4417, +3759, +2998, +6479, +4573, +17, +5090, +8717, +2710, +9419, +271, +9083, +101, +2517, +8782, +4923, +9899, +9312, +3057, +5331, +8219, +2865, +1390, +8377, +9894, +687, +4536, +10664, +4951, +312, +7001, +7934, +5572, +1162, +9162, +7323, +5560, +8645, +6906, +10110, +3237, +9903, +9762, +1550, +2298, +3142, +3929, +6872, +5714, +1149, +5982, +9141, +6002, +7121, +4534, +934, +7435, +10346, +5830, +2688, +8078, +8093, +5388, +3037, +2454, +2625, +4980, +5913, +4228, +9398, +9756, +7990, +4294, +9159, +10369, +8359, +4523, +2781, +2114, +10188, +665, +6669, +7738, +1692, +4407, +937, +8266, +7212, +5623, +6624, +4496, +3261, +888, +3013, +2889, +8467, +1797, +9048, +3514, +8970, +2515, +2342, +2551, +4420, +8361, +10063, +10088, +5239, +1688, +9713, +5287, +907, +5566, +3460, +8419, +4502, +3489, +3335, +6278, +4547, +10266, +9005, +2473, +9526, +9022, +8742, +5475, +10604, +3465, +2666, +7441, +7693, +4745, +3553, +10463, +1226, +9983, +9466, +1993, +10116, +9278, +10056, +8897, +10436, +779, +10747, +5920, +9347, +10152, +8473, +6641, +8523, +9549, +6256, +3554, +10337, +10258, +10626, +2046, +3379, +10962, +9398, +5203, +1602, +7381, +8663, +6119, +8499, +8769, +4632, +786, +4067, +1060, +3035, +2873, +8712, +154, +8670, +10183, +8387, +9261, +7221, +7245, +10020, +7881, +7574, +8087, +8382, +2641, +7422, +6580, +7325, +10834, +7650, +3846, +5720, +233, +7008, +984, +10708, +10114, +514, +2740, +7464, +4329, +6092, +10031, +3644, +9949, +2271, +646, +2452, +426, +8931, +7878, +2690, +7016, +1926, +6996, +9351, +1938, +1050, +1085, +7170, +1008, +7950, +5652, +7477, +2255, +7039, +432, +9263, +6669, +9354, +10490, +6576, +3356, +9283, +1447, +2438, +8698, +8222, +3971, +10386, +1421, +8145, +4494, +69, +8560, +2323, +10323, +1690, +975, +10855, +8421, +9985, +2151, +4727, +3316, +3008, +4997, +10466, +1382, +3394, +8076, +7786, +276, +6143, +10653, +1199, +1273, +3019, +10836, +1646, +5092, +3924, +2615, +9386, +5328, +6393, +3456, +1407, +4647, +5589, +4019, +6808, +2426, +9151, +5625, +6609, +8808, +3143, +6579, +4354, +9586, +4685, +5287, +4514, +2553, +446, +9316, +7113, +8589, +7194, +6404, +7407, +10228, +2151, +2081, +4368, +10515, +1854, +7580, +9228, +6915, +2631, +10649, +2619, +4864, +3581, +3569, +7094, +3815, +3637, +6978, +610, +7453, +3305, +3386, +6429, +9499, +1064, +5814, +6151, +940, +10267, +7768, +1407, +8934, +4682, +7582, +1725, +9539, +4129, +2554, +1941, +2663, +1222, +5947, +836, +4001, +2857, +9940, +8876, +10012, +5784, +3353, +5827, +8645, +141, +4741, +2155, +4815, +7072, +4540, +10734, +6420, +3583, +9424, +1298, +7012, +6603, +5232, +7227, +8234, +1439, +920, +5365, +6998, +2036, +1683, +5327, +9970, +7986, +3866, +10676, +4820, +10604, +5067, +3774, +9075, +9886, +2098, +3902, +6260, +6820, +2486, +6773, +4006, +9933, +475, +874, +9028, +7841, +857, +3930, +3712, +10535, +6386, +6214, +8509, +7776, +10233, +2978, +8148, +7315, +8094, +7784, +10285, +10527, +10386, +7549, +8188, +6045, +6146, +7608, +7762, +6715, +8104, +2885, +7110, +749, +941, +180, +5848, +7643, +10912, +6250, +7694, +2059, +2404, +8178, +4062, +7213, +8850, +5320, +5260, +9154, +1275, +3401, +3726, +1205, +10723, +10024, +10020, +9396, +9035, +4747, +6552, +2593, +8971, +10736, +10813, +166, +9971, +441, +3105, +6474, +711, +1374, +5053, +3680, +3461, +4988, +1510, +10490, +2138, +5993, +6490, +7104, +9890, +8755, +1369, +1972, +3906, +3961, +6944, +4357, +5683, +8776, +8033, +3991, +7299, +10705, +9168, +5530, +2242, +1355, +6986, +1136, +8127, +665, +1136, +9137, +8369, +7092, +8887, +9584, +8137, +3319, +8735, +9047, +6986, +4012, +6258, +745, +8116, +4377, +4619, +8480, +10523, +4612, +4245, +4695, +6142, +2275, +9510, +9688, +7067, +6118, +7519, +2603, +6408, +5046, +8158, +7330, +5480, +1554, +6093, +2126, +10213, +10791, +7287, +5373, +1437, +377, +6445, +5674, +4245, +10761, +8478, +5960, +5197, +6996, +8927, +8341, +1403, +10756, +2296, +174, +5985, +7456, +4412, +1987, +10249, +3666, +1227, +7832, +4215, +8292, +3116, +866, +965, +4451, +9311, +8638, +4443, +1612, +3299, +6381, +4365, +8372, +3833, +3996, +9268, +3684, +2016, +6124, +10359, +2043, +31, +10680, +773, +6087, +6707, +1441, +8741, +4612, +6003, +2981, +8608, +4442, +5190, +10734, +8194, +9641, +9660, +3394, +4076, +7341, +7382, +5193, +8828, +6725, +9569, +4787, +3410, +3144, +352, +6636, +5043, +9965, +4461, +1074, +1094, +4938, +9659, +1830, +5644, +4919, +3884, +3279, +7628, +9805, +10494, +5143, +6146, +6213, +1131, +5061, +1118, +10137, +3203, +5980, +5550, +6141, +2013, +10164, +10437, +2047, +2167, +5222, +6200, +8591, +8252, +2107, +2821, +5058, +2846, +10752, +6550, +851, +1985, +6133, +7273, +3993, +3903, +7310, +3043, +10122, +1448, +7626, +4690, +690, +6308, +7587, +7501, +9435, +1827, +5848, +5692, +4538, +10059, +618, +5272, +7935, +3707, +8882, +10284, +5428, +6815, +10580, +936, +8789, +6635, +3190, +3902, +6578, +5382, +435, +6029, +1253, +4264, +8183, +5907, +10434, +2038, +6077, +9982, +756, +9824, +4974, +7259, +6700, +3063, +6122, +6074, +2693, +9848, +3493, +1390, +5588, +993, +10923, +1103, +202, +6971, +4397, +4947, +2528, +1538, +8702, +7695, +1155, +336, +9823, +3391, +8183, +9912, +5639, +10523, +9198, +4596, +9018, +8656, +1796, +10445, +9346, +5457, +7821, +1513, +2299, +5760, +841, +1503, +2504, +4115, +3843, +92, +10706, +1694, +1868, +6065, +1531, +10120, +9640, +2037, +4580, +5831, +10577, +7527, +4778, +5861, +2407, +7288, +5766, +5333, +5323, +10838, +2357, +689, +6492, +2671, +7752, +5150, +725, +141, +10531, +3327, +1900, +9921, +2210, +8333, +5101, +5562, +1954, +4150, +10, +7454, +7963, +8670, +809, +8200, +1217, +9159, +7113, +7263, +6755, +4492, +464, +8208, +8157, +6540, +7352, +9195, +5748, +7662, +4351, +307, +1146, +5773, +9220, +433, +2570, +6640, +2016, +4465, +7276, +4950, +9067, +9841, +631, +1396, +6599, +4528, +5219, +2057, +4064, +420, +8375, +1568, +4592, +34, +8126, +1395, +8911, +7057, +3191, +2836, +8532, +832, +9555, +6466, +10886, +9464, +8115, +5385, +14, +6285, +4229, +3751, +5302, +8195, +9543, +10256, +3010, +6182, +7156, +9424, +7656, +3983, +3777, +1558, +8606, +1899, +9245, +8686, +7277, +6857, +7213, +1981, +6582, +7201, +9868, +7395, +5144, +6072, +6471, +8324, +2619, +3319, +3875, +9855, +1327, +10570, +1357, +8413, +4850, +9146, +351, +748, +10189, +5810, +55, +2983, +7176, +2114, +7868, +10752, +4699, +2773, +6948, +4246, +10904, +4197, +428, +1586, +10985, +4155, +3656, +2493, +3577, +9165, +6278, +4731, +5203, +8559, +3214, +8591, +1295, +3299, +4366, +7147, +7317, +5086, +10043, +9299, +8463, +7784, +3530, +2799, +7898, +5637, +7197, +10150, +5062, +2423, +4841, +5948, +9218, +10485, +8688, +617, +5832, +5794, +1383, +8844, +7489, +2789, +10147, +6308, +5998, +3055, +1669, +5084, +3270, +10903, +7448, +5829, +7097, +561, +10354, +6162, +3827, +69, +9032, +8627, +1266, +8066, +6173, +5081, +308, +4691, +10163, +8569, +7688, +10520, +5800, +7197, +2521, +5071, +795, +8779, +10883, +3961, +635, +3551, +5433, +7025, +2132, +4751, +10765, +8564, +10794, +9677, +10653, +3098, +8904, +181, +867, +1509, +101, +183, +2034, +10130, +10515, +3369, +7573, +10710, +5825, +1910, +2425, +8773, +2364, +10386, +7982, +1667, +9242, +6169, +10580, +1942, +1181, +9147, +759, +9050, +7728, +10225, +5131, +9179, +2197, +7524, +6095, +6845, +2693, +2440, +7821, +2239, +2752, +1433, +4928, +3724, +5185, +498, +8072, +525, +4315, +8762, +2346, +7344, +3878, +3432, +7017, +9882, +1200, +6100, +8579, +10018, +4426, +9080, +9513, +6150, +9356, +3306, +7875, +6030, +4096, +5194, +6225, +3906, +8926, +8830, +7293, +10297, +1366, +9919, +4592, +942, +8143, +5671, +7731, +5345, +3688, +7916, +349, +5385, +6220, +4098, +7382, +3015, +1257, +9360, +10442, +7144, +10780, +961, +9980, +7533, +7818, +6547, +10213, +5420, +8030, +7675, +681, +3663, +2313, +4880, +5140, +102, +5064, +8220, +6333, +303, +3364, +8337, +2899, +9488, +1523, +5106, +7194, +6041, +1701, +1912, +3028, +4636, +830, +2801, +6606, +3700, +8425, +7086, +6170, +10006, +5224, +3594, +4008, +1882, +527, +6841, +7012, +9084, +6481, +2050, +6523, +6965, +2442, +1801, +943, +2390, +10816, +7728, +10806, +1748, +8467, +9307, +3015, +9612, +4043, +9746, +3153, +6794, +2437, +8616, +1749, +4930, +4033, +6007, +7714, +5045, +4581, +3659, +1102, +6225, +3639, +9998, +6803, +5641, +4578, +5448, +2291, +5955, +8108, +1774, +5727, +7177, +6110, +4805, +8383, +8156, +6704, +8011, +10179, +76, +3740, +4715, +7051, +7559, +8106, +3723, +9002, +2939, +10919, +8964, +4750, +9954, +6076, +5444, +9492, +396, +2854, +9688, +3995, +1595, +1120, +9352, +6228, +913, +5371, +9624, +5399, +6767, +1417, +2931, +5935, +2381, +1866, +7558, +493, +7980, +6709, +7471, +975, +9839, +5746, +9603, +4040, +948, +4702, +1605, +7140, +3123, +5521, +7664, +8627, +5024, +3144, +7469, +9192, +10552, +4659, +2578, +5888, +1835, +3302, +4886, +10872, +9114, +7794, +131, +8749, +1760, +434, +7462, +9014, +6858, +7603, +223, +8112, +518, +2602, +5072, +2119, +5946, +3811, +8111, +9578, +1924, +1514, +10862, +8192, +7330, +988, +1837, +589, +9185, +5826, +9274, +5524, +3528, +8274, +9256, +4561, +2605, +8704, +9565, +10841, +3807, +2071, +10633, +1027, +8053, +3281, +9872, +2019, +9584, +2909, +3122, +9110, +9298, +5160, +8485, +7243, +1799, +10648, +4398, +3342, +7064, +6288, +4396, +4536, +5497, +6875, +3734, +8056, +3430, +2106, +5717, +3708, +2960, +8741, +10543, +5575, +10273, +6409, +7273, +6061, +2727, +172, +476, +2468, +4672, +8681, +460, +343, +10923, +10111, +3190, +5852, +2976, +9945, +9293, +510, +7903, +2223, +2001, +7010, +10744, +489, +987, +10955, +6904, +10694, +2733, +8295, +7505, +1501, +8026, +7629, +4036, +10778, +1078, +7462, +8224, +5264, +1904, +2197, +9185, +4720, +3726, +9401, +4178, +10416, +9739, +9869, +9557, +2091, +6872, +10525, +6552, +1216, +9059, +4610, +2752, +7577, +1140, +1756, +10391, +4577, +4596, +6232, +5073, +6828, +33, +9704, +610, +4068, +7857, +4653, +6455, +113, +10677, +5562, +1964, +520, +10072, +10878, +5898, +2613, +9766, +4919, +6399, +9125, +1882, +1689, +7751, +2840, +5762, +4500, +8745, +7658, +5516, +8186, +3196, +4082, +3840, +5644, +8335, +6471, +395, +6280, +2675, +901, +6496, +707, +6013, +5722, +6159, +5685, +7509, +1441, +2114, +7019, +10038, +718, +4513, +10895, +5158, +2788, +2529, +1634, +10858, +10187, +9783, +10374, +7809, +862, +7393, +3785, +5043, +6801, +9163, +2975, +8559, +3163, +3938, +7329, +2011, +6203, +4904, +5813, +120, +10397, +5435, +3493, +9949, +3432, +7785, +5700, +51, +381, +2559, +3793, +4091, +9162, +3979, +703, +4902, +3453, +2962, +6644, +7407, +6729, +7045, +3478, +6153, +5385, +1017, +4072, +7457, +5904, +7607, +10885, +8118, +10261, +4411, +3638, +7118, +2790, +8671, +8248, +619, +9693, +1831, +9603, +818, +7812, +1573, +14, +4095, +208, +2917, +9313, +870, +3321, +4971, +10003, +9592, +1305, +6616, +5610, +6524, +1766, +538, +5301, +9135, +1367, +2834, +1959, +3913, +6701, +10044, +5365, +2460, +3698, +10352, +1433, +84, +8095, +1120, +7913, +3633, +412, +3687, +10238, +9953, +2757, +10502, +3705, +8023, +771, +2779, +10389, +10459, +2889, +8493, +6798, +4330, +663, +2893, +10486, +7439, +6456, +4113, +6063, +6841, +9510, +7209, +8728, +79, +7163, +6792, +5433, +3856, +1158, +7837, +679, +4145, +4569, +1649, +4775, +993, +1403, +5613, +6111, +911, +3616, +9142, +1259, +5621, +8449, +4778, +7544, +5119, +2370, +7226, +2445, +6680, +9432, +215, +1828, +1630, +10297, +8148, +3959, +2759, +8003, +2647, +3348, +6832, +7637, +1099, +9211, +8589, +10635, +4437, +4080, +8448, +7502, +7974, +3297, +2160, +1204, +1981, +8121, +10721, +368, +8018, +1182, +5622, +10343, +4773, +6127, +8214, +3233, +10922, +8659, +8132, +589, +7306, +10601, +6079, +2242, +1583, +876, +4933, +7151, +6534, +2051, +1849, +3246, +10301, +1115, +4350, +3782, +10243, +3784, +5188, +5072, +265, +10613, +8500, +10008, +7771, +3230, +8852, +4226, +9249, +5117, +5138, +1888, +568, +9655, +7856, +1860, +6206, +9884, +5672, +10941, +959, +8000, +6934, +4388, +9608, +2932, +3991, +10446, +4430, +3392, +2787, +2299, +10726, +1945, +2345, +609, +8851, +9445, +3114, +5603, +2161, +376, +8934, +8214, +2420, +3653, +10720, +804, +8931, +6703, +8024, +1060, +4641, +5307, +2689, +3107, +5697, +3431, +2236, +9570, +476, +10824, +2796, +5243, +6325, +4981, +901, +1599, +3530, +8959, +10655, +8411, +10124, +4232, +2079, +7851, +7005, +8575, +8483, +2010, +9267, +1799, +617, +9261, +9771, +6098, +9933, +7027, +6101, +10471, +592, +10471, +6822, +9252, +10666, +5371, +3102, +8588, +1497, +9748, +1710, +10103, +10090, +4494, +9110, +9162, +1841, +844, +9346, +6546, +1143, +9036, +7657, +5130, +8036, +3654, +9012, +3991, +5637, +10428, +1233, +9978, +3836, +7762, +10449, +6160, +6675, +5960, +4118, +3515, +1553, +2185, +7788, +3202, +10503, +5366, +4806, +9477, +8470, +3308, +8991, +4367, +344, +3253, +292, +9789, +618, +2433, +3747, +301, +694, +5565, +1086, +6807, +8519, +6707, +7935, +5423, +10118, +453, +1781, +6929, +1087, +10263, +6086, +2181, +5196, +1468, +7799, +9959, +9876, +8051, +1390, +3334, +10801, +7346, +3815, +4089, +2190, +10689, +225, +8254, +10969, +6670, +10320, +1232, +9240, +9688, +5098, +6566, +6058, +9548, +5419, +8202, +5223, +6391, +8146, +6867, +3428, +1255, +6903, +10708, +6466, +6847, +9776, +7156, +1521, +6355, +9474, +3873, +963, +7008, +2400, +2662, +5050, +6684, +4279, +4883, +6733, +6135, +10610, +1061, +2503, +2393, +9298, +3640, +8160, +4223, +1977, +4001, +9278, +7851, +3982, +6325, +10675, +7990, +4666, +5913, +10796, +4572, +7022, +328, +6830, +10639, +6229, +1826, +7710, +2539, +3622, +2538, +9980, +1769, +62, +3634, +6023, +3730, +7256, +1796, +1213, +5066, +1074, +2854, +6626, +657, +8818, +2776, +1633, +814, +6975, +7698, +3580, +2498, +10308, +6634, +6476, +1125, +7815, +2370, +2453, +230, +4638, +5948, +244, +2594, +5511, +4623, +2037, +4932, +6517, +3939, +657, +5791, +9597, +8060, +9077, +9695, +8263, +143, +7967, +10615, +3749, +359, +8009, +9717, +8147, +6684, +5920, +2980, +3001, +3398, +2507, +10051, +9346, +10680, +7006, +4855, +377, +7181, +5570, +7756, +36, +10289, +3466, +5936, +1621, +5427, +6131, +2543, +1809, +5569, +6877, +3190, +5387, +5048, +3613, +9198, +6866, +10690, +5998, +6976, +8092, +35, +3213, +8605, +8844, +1265, +10116, +1498, +8692, +7358, +7806, +6013, +1189, +6309, +10576, +9500, +2607, +56, +5900, +4963, +464, +368, +7188, +2398, +10806, +6470, +867, +4214, +5167, +6145, +1797, +1643, +4707, +9286, +8048, +1403, +7693, +6660, +8474, +7513, +9341, +3516, +10294, +5474, +9697, +2619, +9018, +1138, +2335, +9674, +5125, +805, +8097, +303, +10580, +336, +2840, +1616, +8599, +10946, +7093, +919, +10685, +1465, +8032, +3981, +5072, +1049, +3552, +3379, +1863, +3841, +4609, +8864, +6123, +7469, +3194, +8541, +2006, +41, +10723, +8401, +2791, +2073, +5831, +5019, +2079, +10304, +360, +2737, +6723, +5772, +6268, +9717, +4897, +216, +5229, +5238, +5056, +681, +6234, +6763, +4511, +10277, +7312, +8291, +1714, +9929, +5990, +1050, +9757, +5177, +8713, +1976, +7038, +7954, +7511, +10413, +3, +1560, +2858, +2336, +3375, +3222, +7635, +4722, +3105, +10160, +4182, +9410, +239, +2600, +1067, +7255, +6025, +5976, +9983, +8904, +8215, +4755, +5425, +2399, +9879, +8291, +4545, +6238, +6285, +3175, +6432, +3781, +7316, +10621, +5736, +7614, +2050, +9466, +3247, +4295, +2397, +998, +7979, +10647, +5605, +8708, +1784, +8042, +4977, +3810, +1898, +8720, +7600, +6620, +606, +7165, +4570, +9079, +5358, +260, +8372, +4629, +787, +5524, +6699, +212, +1168, +3085, +10296, +1489, +4281, +8290, +9317, +4048, +3508, +5465, +318, +10140, +969, +958, +9958, +9281, +9773, +8535, +8776, +4195, +10993, +3514, +7574, +6476, +7577, +5989, +1697, +10443, +9125, +10679, +1625, +3073, +2673, +3656, +6282, +5977, +7603, +10974, +3619, +1616, +6408, +1381, +523, +33, +3568, +3377, +8468, +4270, +7636, +10544, +3259, +6492, +6573, +5171, +1880, +7846, +3308, +3620, +2418, +7251, +5671, +9427, +4323, +206, +10372, +1268, +4442, +133, +7559, +8214, +1011, +4645, +1059, +5926, +5189, +8754, +1716, +6631, +9234, +7734, +6396, +5119, +7832, +3349, +2308, +4706, +495, +587, +4835, +4114, +7183, +1228, +425, +5518, +10024, +511, +1629, +6826, +7217, +5428, +5401, +9443, +83, +3989, +8674, +5418, +446, +7315, +10792, +6186, +4852, +4301, +7020, +4812, +2247, +1980, +9438, +3139, +5895, +1235, +536, +9070, +10648, +6114, +4503, +3912, +8544, +8678, +4385, +550, +5835, +1936, +8511, +1485, +5029, +4712, +2388, +1198, +7367, +7276, +9919, +1650, +6748, +105, +2004, +4453, +8603, +7623, +6584, +9149, +6550, +111, +4290, +8833, +8221, +9270, +6287, +4656, +3576, +8865, +883, +7953, +1222, +8272, +5346, +9195, +5612, +3818, +6081, +2232, +6243, +455, +4644, +5654, +7645, +2776, +10088, +410, +8272, +2820, +5272, +10366, +3261, +1356, +8204, +5657, +408, +7067, +8611, +10574, +2122, +2019, +468, +10183, +5254, +8033, +7705, +3794, +6993, +8722, +399, +4225, +6778, +10906, +10234, +3097, +5096, +5633, +3196, +9102, +4708, +10464, +2034, +5674, +8327, +9143, +6131, +9334, +4723, +4679, +10002, +10308, +695, +3774, +9288, +4342, +9325, +1588, +9901, +10173, +5624, +9344, +4732, +9409, +5196, +9112, +911, +7440, +43, +2938, +187, +10855, +10111, +9530, +4788, +5626, +581, +10156, +6050, +3758, +1549, +8606, +9685, +10622, +6978, +7126, +6779, +604, +8105, +1395, +8718, +10634, +10945, +2278, +10316, +5540, +2228, +277, +3975, +10568, +4215, +1998, +9751, +3311, +5469, +4278, +8614, +4701, +10499, +7, +4288, +7660, +10633, +10396, +1576, +5305, +9019, +3507, +4241, +4802, +513, +1073, +10734, +0, +8810, +2125, +669, +2066, +9928, +10630, +2854, +2205, +4968, +7251, +303, +10319, +4403, +5715, +7727, +7269, +1679, +10778, +618, +5494, +4104, +1081, +2796, +7500, +1174, +763, +9636, +6220, +4656, +10511, +7881, +539, +5631, +9650, +8228, +7839, +6252, +4927, +9898, +7606, +7951, +87, +997, +1907, +2811, +5551, +445, +5549, +1590, +3523, +9025, +3130, +2793, +955, +2417, +8291, +2286, +7395, +5547, +7107, +9103, +5526, +6038, +8168, +152, +909, +2232, +1582, +5700, +2781, +10720, +3605, +8040, +1710, +168, +1716, +7776, +8080, +5775, +3332, +7849, +7533, +79, +5798, +411, +9402, +1344, +779, +10504, +6224, +6424, +7171, +10992, +10408, +4299, +8319, +6195, +175, +9336, +5245, +4558, +3618, +9286, +1157, +7171, +9022, +7189, +6400, +3465, +8143, +4040, +3821, +4571, +10407, +8716, +5884, +9383, +7426, +9410, +4356, +2488, +8100, +9730, +7438, +8495, +737, +6732, +2500, +7072, +614, +10201, +1012, +3452, +3583, +6546, +4174, +2022, +8735, +8011, +1019, +7286, +9250, +3683, +5146, +4941, +10270, +3838, +4035, +4192, +7024, +7819, +1852, +10618, +9828, +3781, +6632, +1109, +2104, +6183, +1956, +10271, +1671, +5468, +1553, +1940, +2298, +10719, +7717, +8388, +5651, +8039, +3945, +10883, +3537, +4885, +714, +4598, +6457, +9782, +9459, +2717, +2471, +7044, +10398, +1399, +9345, +8011, +897, +9309, +3720, +6762, +2235, +1479, +3474, +3841, +7801, +5972, +4110, +4101, +6189, +991, +3332, +8822, +588, +6854, +425, +2545, +5234, +8548, +9420, +7237, +3270, +5063, +9390, +888, +2914, +9589, +10520, +322, +1870, +6433, +8059, +462, +8321, +5410, +573, +998, +5607, +3482, +8901, +7514, +10109, +4473, +6790, +3236, +10719, +9201, +875, +5796, +2846, +3183, +10817, +4027, +5620, +6218, +5437, +5712, +8351, +1563, +209, +6671, +8961, +5382, +1021, +8522, +7612, +3199, +1937, +4645, +268, +5573, +1715, +10849, +3159, +5921, +4384, +3194, +7255, +3122, +4055, +3206, +823, +6546, +4719, +4753, +4263, +3124, +5495, +5239, +1404, +5209, +9493, +9350, +2488, +786, +10047, +7226, +3807, +6410, +8206, +3184, +1588, +5589, +1785, +3626, +5486, +712, +5224, +7709, +4521, +8365, +1876, +2311, +4945, +6094, +4178, +9107, +9519, +4114, +7185, +760, +3948, +5264, +4657, +2335, +9968, +8285, +7528, +9213, +3466, +4358, +4771, +5340, +5406, +8324, +955, +4756, +10362, +283, +4448, +8430, +6409, +8125, +9483, +10026, +1923, +3195, +5862, +2360, +1769, +274, +4427, +388, +3069, +1661, +8930, +2836, +8503, +4454, +9128, +4494, +2895, +1280, +10999, +3091, +10875, +2367, +2419, +4803, +2040, +1152, +8652, +9364, +7544, +5151, +6289, +8170, +442, +5180, +664, +1396, +5084, +8107, +4443, +9766, +2439, +8950, +189, +8362, +3908, +9903, +10327, +4139, +5369, +10155, +10582, +6550, +7864, +4090, +584, +10673, +10383, +1636, +6169, +5283, +8274, +536, +7381, +690, +1787, +1569, +1818, +1991, +517, +3510, +3443, +5257, +10087, +515, +1612, +2490, +5208, +3049, +3799, +10479, +2208, +3277, +9905, +4415, +2200, +5670, +4340, +6402, +247, +6744, +5459, +3449, +8608, +2493, +8953, +2329, +10470, +3489, +5014, +942, +3033, +5517, +7124, +9458, +912, +4719, +8003, +7849, +8968, +6323, +4333, +2231, +10255, +5734, +7819, +761, +3018, +7711, +6540, +10359, +967, +8518, +6944, +4272, +10419, +970, +7970, +649, +2804, +27, +2860, +987, +5989, +1244, +4408, +6822, +8328, +6969, +3241, +8932, +5919, +10825, +2147, +2146, +9458, +3547, +8628, +2580, +506, +4800, +7062, +10165, +1459, +7442, +9935, +7895, +1007, +987, +5940, +9392, +10782, +7521, +4584, +5441, +8823, +4099, +10435, +3401, +6446, +5123, +1595, +8734, +6232, +3258, +7920, +2136, +4597, +2214, +6978, +4778, +4613, +6608, +8627, +10160, +9077, +9818, +2613, +10686, +1947, +6014, +10709, +10607, +4619, +9422, +10289, +1786, +8250, +10572, +2179, +869, +5794, +8534, +5379, +4341, +2606, +1211, +2456, +978, +4853, +1795, +4426, +5814, +9734, +2306, +8299, +3861, +5181, +1936, +2921, +8830, +7968, +5555, +8043, +7961, +6242, +5054, +1946, +1789, +4613, +1979, +9578, +8544, +8087, +497, +3405, +10226, +10006, +8807, +6271, +10633, +7887, +7386, +1618, +2939, +10093, +6471, +3672, +3548, +9370, +2636, +10878, +6138, +5662, +8622, +5454, +10653, +3914, +8645, +3253, +10947, +10077, +5737, +10504, +4763, +7483, +1907, +1881, +8326, +184, +6423, +4437, +10405, +3855, +4041, +6355, +5249, +8908, +8667, +4116, +6949, +5027, +3707, +2247, +6096, +1609, +4998, +10193, +7897, +3707, +9221, +2139, +7381, +7163, +9295, +6008, +10733, +7586, +5280, +3631, +5661, +10702, +407, +2904, +1151, +4765, +9341, +6075, +5673, +4462, +1891, +3764, +61, +6401, +8834, +10567, +10949, +9554, +4874, +2972, +8451, +9201, +5534, +4160, +9449, +10156, +6495, +10572, +15, +921, +2620, +9973, +7346, +9121, +996, +9731, +8740, +8401, +248, +3436, +743, +9858, +6059, +9358, +904, +6668, +5496, +6191, +9685, +3028, +8259, +3658, +8988, +7059, +8558, +1229, +2049, +6791, +10363, +4316, +4480, +6247, +10619, +1566, +10765, +352, +4756, +2883, +6094, +188, +10236, +3880, +2146, +2805, +1985, +8722, +9625, +5453, +10885, +10506, +7475, +500, +1504, +335, +1183, +4235, +5854, +6525, +6214, +8658, +9912, +1739, +10148, +10501, +2923, +6472, +6017, +8190, +9384, +8307, +10923, +7192, +4010, +9232, +2498, +2054, +5250, +8415, +9657, +3295, +145, +8141, +9300, +4152, +4603, +9864, +6482, +2940, +603, +3684, +8916, +7639, +7797, +3768, +2514, +8486, +5682, +253, +103, +3261, +9001, +3449, +7279, +4595, +6083, +203, +2863, +2409, +4656, +2609, +8409, +877, +4853, +8985, +2369, +9288, +5088, +9223, +9015, +7662, +2204, +6674, +990, +9538, +1939, +6833, +6592, +2230, +8085, +1815, +10114, +6981, +4982, +43, +5519, +5233, +405, +5279, +2897, +10711, +10644, +9459, +5979, +10117, +2975, +6702, +9712, +3464, +6026, +1203, +4293, +9680, +4986, +5548, +1903, +9821, +1787, +9402, +4650, +3271, +10581, +2762, +7257, +5968, +2669, +4481, +4697, +5841, +9906, +5870, +1639, +2564, +9288, +6963, +7745, +2788, +3147, +6372, +7254, +9354, +6230, +3583, +7660, +8449, +9028, +9323, +9323, +352, +3536, +10230, +2476, +1339, +2469, +7970, +251, +4384, +6248, +9395, +2483, +611, +1631, +2355, +10541, +2916, +2307, +9399, +7123, +186, +2868, +6178, +4976, +8232, +9270, +7938, +792, +2151, +5129, +7702, +6419, +9239, +4878, +4514, +6608, +10976, +10212, +3670, +3648, +2073, +4476, +9794, +4889, +9853, +954, +6203, +1520, +3108, +8423, +7038, +24, +6786, +3760, +1432, +6951, +10170, +8823, +2328, +4931, +4750, +2807, +7169, +2439, +2398, +467, +9116, +906, +7338, +7350, +4995, +2190, +9427, +9800, +2091, +4318, +5852, +8811, +8598, +7484, +2824, +6929, +3187, +9222, +10408, +11, +582, +6829, +10690, +1871, +5690, +8255, +1389, +8103, +4025, +404, +4172, +7599, +899, +2088, +403, +7825, +2006, +6983, +3995, +8249, +4426, +9717, +8994, +4216, +4995, +3628, +2569, +2611, +4720, +3896, +10296, +9651, +5651, +186, +7244, +273, +5324, +8614, +805, +8602, +2365, +831, +2412, +1741, +829, +7347, +4197, +2968, +5194, +8267, +2714, +1245, +1704, +1290, +2409, +633, +10246, +3811, +3256, +7996, +7186, +3922, +9875, +5807, +8984, +5949, +9122, +1342, +1253, +3516, +6117, +5294, +1539, +24, +3854, +7077, +7922, +7596, +7600, +10368, +10448, +5212, +6656, +5528, +7489, +9073, +1100, +5019, +7325, +382, +9519, +3491, +10783, +5058, +3091, +2912, +5173, +2326, +8838, +8391, +2475, +5056, +3017, +6244, +390, +7942, +5708, +8738, +1276, +5284, +7432, +5666, +10882, +10506, +5902, +7413, +6282, +10111, +7012, +8939, +8421, +3998, +4344, +8319, +8210, +3504, +9606, +7405, +6521, +6416, +4558, +9145, +5157, +5261, +5696, +1390, +9195, +6772, +4410, +3080, +1959, +702, +2365, +3812, +7136, +85, +3787, +1117, +9472, +9654, +7874, +8557, +7441, +4110, +2641, +5284, +8988, +8097, +4289, +772, +9230, +5183, +2857, +2075, +5816, +2750, +5819, +6340, +8620, +3720, +2316, +4666, +7723, +9328, +2144, +6482, +2916, +2326, +3978, +10502, +6481, +9549, +8936, +8988, +137, +2644, +928, +3605, +9292, +6807, +3963, +4318, +7767, +5404, +10245, +6493, +2416, +1305, +3418, +9534, +1321, +10452, +7148, +6403, +5168, +7197, +6178, +1847, +8922, +4099, +8369, +1440, +7243, +9735, +2763, +6544, +10712, +6667, +6680, +5302, +3157, +3830, +80, +10506, +10828, +3364, +9628, +3060, +7295, +6502, +1823, +2647, +3987, +8714, +5754, +6887, +6016, +6205, +2793, +10515, +6822, +10977, +2433, +7005, +3584, +188, +5249, +6393, +2647, +10429, +2382, +10384, +2608, +7758, +9690, +7786, +6908, +6182, +2547, +9532, +10877, +2518, +948, +30, +2696, +9065, +8878, +2113, +138, +497, +3297, +7455, +854, +870, +4672, +7445, +2102, +8940, +1951, +4280, +6241, +8585, +4233, +7950, +6460, +10857, +6740, +2287, +1364, +4446, +8426, +3348, +4988, +9895, +2677, +2606, +8787, +9497, +4451, +96, +7674, +1386, +567, +5985, +7270, +9207, +825, +7390, +4937, +7625, +8803, +8381, +9831, +7961, +9935, +3507, +2041, +9029, +2973, +133, +6078, +6846, +10617, +4484, +1830, +8710, +4019, +7032, +3032, +1738, +10740, +9501, +9449, +1429, +7317, +664, +3981, +6158, +6048, +7072, +9500, +2648, +7706, +10187, +3941, +2286, +10653, +8998, +1233, +8702, +7320, +1499, +8392, +1622, +499, +3121, +6399, +10088, +5705, +7765, +2227, +4082, +5011, +9342, +6450, +10661, +9309, +5120, +5454, +5940, +3575, +8150, +55, +3696, +2656, +4758, +10772, +8299, +4604, +8331, +3823, +5859, +8966, +1341, +1072, +7909, +4881, +8386, +3336, +404, +5364, +606, +1088, +8046, +2712, +8096, +1937, +2318, +7295, +6381, +2025, +7230, +8354, +5917, +9999, +1886, +5907, +8152, +1757, +2054, +670, +10069, +2316, +3199, +9556, +2830, +5499, +6990, +9435, +7814, +7890, +4419, +4335, +481, +7620, +9966, +10498, +3221, +3472, +1819, +8189, +3264, +3364, +2091, +5224, +2504, +638, +3823, +2417, +10976, +9368, +9749, +9415, +10115, +5702, +10319, +7192, +4601, +448, +9098, +6839, +8539, +5966, +1009, +3913, +6537, +8496, +4878, +6895, +8462, +2208, +6362, +7066, +6652, +3827, +10877, +9197, +7500, +2529, +10389, +7599, +2357, +6571, +6613, +3363, +8278, +1587, +1707, +4397, +6828, +3185, +7187, +1063, +8132, +77, +5256, +3074, +1991, +5472, +4758, +368, +7729, +3408, +2702, +8175, +936, +10581, +9242, +5737, +8262, +9763, +7053, +9733, +9879, +3568, +10853, +1027, +2059, +10605, +9117, +4152, +10609, +2905, +129, +8415, +525, +2864, +1786, +5196, +1593, +7395, From 8e21b7ea704e774cd2871d78a814c5e7e954f78d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 2 Jul 2019 10:26:44 -0700 Subject: [PATCH 100/176] WIP 10.7 - debugging test failure in previous problem implementation --- CMakeLists.txt | 1 + .../problem_10_07_missingInt.cpp | 19 +++++++++++++++++++ .../problem_10_07_missingInt.h | 4 +++- tests.cpp | 4 +++- 4 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 71e9847..38a6f03 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ set(SOURCE_FILES cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp + cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp new file mode 100644 index 0000000..7fd7a17 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp @@ -0,0 +1,19 @@ +#include "problem_10_07_missingInt.h" +#include +#include +#include + + +namespace chapter_10 { + uint32_t missingInt(const std::string& filename) { + std::cout << "filename=" << filename << std::endl; + /* + std::ifstream file(filename); + std::string line = ""; + while (std::getline(file, line)){ + std::cout << line << std::endl; + } + */ + return 0; + } +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h index 8abd4a0..56f6a3a 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.h @@ -34,7 +34,9 @@ */ #pragma once +#include +#include namespace chapter_10 { - + uint32_t missingInt(const std::string& filename); } diff --git a/tests.cpp b/tests.cpp index 58c841e..332a94d 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1280,9 +1280,11 @@ TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ REQUIRE(0 == chapter_10::sparseSearch(input4, "alex")); } +/* TEST_CASE("Chpater 10 - Problem 07 - missingInt()", "test") { - + REQUIRE(1 == chapter_10::missingInt("../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv")); } +*/ TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; From 941f34aeb668d33e79b0d5ed0f23360e069c0ee7 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 2 Jul 2019 14:29:37 -0700 Subject: [PATCH 101/176] fix illegal mem access in 10.5 C++ --- .../problem_10_05_sparseSearch.cpp | 18 ++++++++++++------ tests.cpp | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp index 67b9103..5b13eb3 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp @@ -3,7 +3,9 @@ namespace chapter_10 { int sparseSearchHelper(const std::vector& array, const std::string& query, int start, int end) { // check terminating conditions - if (start > end) return -1; + if (start > end) { + return -1; + } int midpoint = (end - start) / 2 + start; // handle comparison against empty string @@ -13,17 +15,18 @@ namespace chapter_10 { if (comparisonValue == "") { std::string leftPotentialComparisonValue = comparisonValue; std::string rightPotentialComparisonValue = comparisonValue; - while ((leftPotentialMidpoint >= start || rightPotentialMidpoint <= end) && leftPotentialComparisonValue == "" && rightPotentialComparisonValue == "") { + while ((leftPotentialMidpoint > start || rightPotentialMidpoint < end) && leftPotentialComparisonValue == "" && rightPotentialComparisonValue == "") { // search left - if (leftPotentialMidpoint >= start) { + if (leftPotentialMidpoint > start) { leftPotentialMidpoint --; leftPotentialComparisonValue = array[leftPotentialMidpoint]; } // search right - if (rightPotentialMidpoint <= end) { + if (rightPotentialMidpoint < end) { rightPotentialMidpoint ++; rightPotentialComparisonValue = array[rightPotentialMidpoint]; } + // check if left midpoint is non-empty if (leftPotentialComparisonValue != "") { comparisonValue = leftPotentialComparisonValue; @@ -41,6 +44,7 @@ namespace chapter_10 { return -1; // the array contains only ""; there no possibility of a match } } + // check terminating conditions after midpoint adjustment if (array[midpoint] == query) { return midpoint; @@ -51,10 +55,12 @@ namespace chapter_10 { // recurse left - do not include array elements that are known to be empty if (query >= array[start] && query <= array[midpoint]) { - return sparseSearchHelper(array, query, start, (leftPotentialMidpoint < (midpoint - 1) ? leftPotentialMidpoint : (midpoint - 1))); + int newLocation = (leftPotentialMidpoint < (midpoint - 1) ? leftPotentialMidpoint : (midpoint - 1)); + return sparseSearchHelper(array, query, start, newLocation); } else { // recurse right - do not include array elements that are known to be empty - return sparseSearchHelper(array, query, (rightPotentialMidpoint > (midpoint - 1) ? rightPotentialMidpoint : (midpoint - 1)), end); + int newLocation = (rightPotentialMidpoint > (midpoint + 1) ? rightPotentialMidpoint : (midpoint + 1)); + return sparseSearchHelper(array, query, newLocation, end); } } diff --git a/tests.cpp b/tests.cpp index ae4afae..17849ab 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1278,7 +1278,7 @@ TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ REQUIRE(-1 == chapter_10::sparseSearch(input3, "")); REQUIRE(-1 == chapter_10::sparseSearch(input3, "alex")); REQUIRE(0 == chapter_10::sparseSearch(input4, "alex")); -} + } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; From 562f24e8033807af090d7673c1bfcdf4300c89ed Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 2 Jul 2019 21:33:52 -0700 Subject: [PATCH 102/176] implement 10.7 C++ --- README.md | 6 +- .../generate_random_number_file.cpp | 11 +- .../random_number_dataset.csv | 7892 ++++++++--------- .../problem_10_07_missingInt.cpp | 19 +- tests.cpp | 3 +- 5 files changed, 3971 insertions(+), 3960 deletions(-) diff --git a/README.md b/README.md index 3edcc7a..1dc96a9 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ reference and contribute solutions with confidence. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `5 / 11` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `6 / 11` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -39,7 +39,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `54` of `141` solutions complete. +C++ Total: `55` of `141` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -63,7 +63,7 @@ C++ Total: `54` of `141` solutions complete. Python Total: `56` of `131` solutions complete. -##### Grand Total: `110` unique solutions complete. +##### Grand Total: `111` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp index 1a29630..0321a14 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp @@ -6,18 +6,21 @@ int main() { std::string filename = "random_number_dataset.csv"; std::cout << "Random number file generator outputting to " << filename << std::endl; - // initialize random integer generator // problem 10.7 specifies a max value of 2^32 = 0xFFFFFFFF ~= 4,294,967,296 // for reasonable test dataset size, we use a smaller range of [0,4300] + const int numberRange = 1000; + // problem 10.7 specifies 4 billion numbers, for testing speed, we only write 4000 + const int numberCount = 4000; + + // initialize random integer generator std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(0, 11000); + std::uniform_int_distribution dis(0, numberRange); // initialize file stream std::ofstream file; file.open(filename); // write to file line by line - // problem 10.7 specifies 4 billion numbers, for testing speed, we only write 4000 - for (int i = 0; i < 4000; i++) { + for (int i = 0; i < numberCount; i++) { file << dis(gen); file << ",\n"; } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv index 16931c7..e6b16c3 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv @@ -1,4000 +1,4000 @@ -2494, -8449, -4406, -3397, -6521, -1726, -7045, -10151, -453, -7517, -74, -6818, -10142, -3664, -6193, -4998, -2714, -2874, -961, -579, -686, -3124, -8066, -676, -8838, -10031, +411, +223, +856, +482, +26, +944, +874, +242, +786, +835, +853, +892, +336, +644, +161, +875, +127, +534, +998, +351, +36, +777, +833, +826, +685, +59, +14, +905, +572, +131, +487, +185, +68, +229, +974, +617, +942, +501, +13, +400, +245, +536, +416, +559, +971, +549, +842, +869, +879, +790, +995, +410, +412, +530, 532, -976, -2430, -1748, -8388, -6721, -3354, -9743, -827, -8657, -4417, -3759, -2998, -6479, -4573, -17, -5090, -8717, -2710, -9419, -271, -9083, -101, -2517, -8782, -4923, -9899, -9312, -3057, -5331, -8219, -2865, -1390, -8377, -9894, -687, -4536, -10664, -4951, -312, -7001, -7934, -5572, -1162, -9162, -7323, -5560, -8645, -6906, -10110, -3237, -9903, -9762, -1550, -2298, -3142, -3929, -6872, -5714, -1149, -5982, -9141, -6002, -7121, -4534, -934, -7435, -10346, -5830, -2688, -8078, -8093, -5388, -3037, -2454, -2625, -4980, -5913, -4228, -9398, -9756, -7990, -4294, -9159, -10369, -8359, -4523, -2781, -2114, -10188, -665, -6669, -7738, -1692, -4407, +95, +516, +90, +344, +998, +258, +86, +734, +500, +331, +514, +953, +746, +54, +181, +195, +712, +944, +362, +414, +981, +560, +26, +3, +799, +896, +59, +280, +73, +116, +352, +471, +129, +285, +958, +359, +815, +165, +252, +469, +456, +16, +577, +644, +232, +26, +874, +477, +848, +783, +451, +248, +828, +575, +494, +287, +614, +982, +132, +70, +632, +913, +197, +241, +151, +607, +520, +698, +371, +364, 937, -8266, -7212, -5623, -6624, -4496, -3261, -888, -3013, -2889, -8467, -1797, -9048, -3514, -8970, -2515, -2342, -2551, -4420, -8361, -10063, -10088, -5239, -1688, -9713, -5287, -907, -5566, -3460, -8419, -4502, -3489, -3335, -6278, -4547, -10266, -9005, -2473, -9526, -9022, -8742, -5475, -10604, -3465, -2666, -7441, -7693, -4745, -3553, -10463, -1226, -9983, -9466, -1993, -10116, -9278, -10056, -8897, -10436, -779, -10747, -5920, -9347, -10152, -8473, -6641, -8523, -9549, -6256, -3554, -10337, -10258, -10626, -2046, -3379, -10962, -9398, -5203, -1602, -7381, -8663, -6119, -8499, -8769, -4632, +69, +590, +573, +271, +485, +599, +153, +486, +245, +275, +419, +848, +849, +768, +605, +360, +67, +521, +726, +893, +219, +607, +963, +434, +193, +15, +941, +371, +79, +926, +843, +146, +370, +817, +774, +126, +24, +136, +532, +225, +1, +238, +334, +382, +419, +925, +680, +579, +654, +168, 786, -4067, -1060, -3035, -2873, -8712, -154, -8670, -10183, -8387, -9261, -7221, -7245, -10020, -7881, -7574, -8087, -8382, -2641, -7422, -6580, -7325, -10834, -7650, -3846, -5720, -233, -7008, -984, -10708, -10114, -514, -2740, -7464, -4329, -6092, -10031, -3644, -9949, -2271, -646, -2452, -426, -8931, -7878, -2690, -7016, -1926, -6996, -9351, -1938, -1050, -1085, -7170, -1008, -7950, -5652, -7477, -2255, -7039, -432, -9263, -6669, -9354, -10490, -6576, -3356, -9283, -1447, -2438, -8698, -8222, -3971, -10386, -1421, -8145, -4494, +155, +896, +14, +924, +980, +59, +320, +821, +140, +319, +849, +622, +316, +571, +733, +80, +735, +651, +96, +502, +385, +602, +15, +800, +281, +899, +411, +145, +92, +110, +421, +601, +838, +971, +470, +62, +119, +915, +16, +294, +207, +739, +55, +291, +217, +955, +568, +992, +530, +200, +525, +90, +747, +478, +899, +605, +626, +958, +769, 69, -8560, -2323, -10323, -1690, -975, -10855, -8421, -9985, -2151, -4727, -3316, -3008, -4997, -10466, -1382, -3394, -8076, -7786, +612, +908, +402, +314, +250, +486, +734, +703, +925, +739, +820, +221, +56, +275, +891, +791, +733, +112, +304, +363, +41, +910, +502, +696, +27, +764, +208, +241, +527, +347, +743, +229, +311, +758, +370, +207, +506, +569, +961, +629, +517, +557, +753, +790, +322, +855, +417, +427, +820, +518, +314, +722, +317, +270, +904, +598, +126, +202, +250, +47, +116, +400, +114, +500, +234, +205, +924, +932, +949, +175, +375, +136, +534, +969, +332, 276, -6143, -10653, -1199, -1273, -3019, -10836, -1646, -5092, -3924, -2615, -9386, -5328, -6393, -3456, -1407, -4647, -5589, -4019, -6808, -2426, -9151, -5625, -6609, -8808, -3143, -6579, -4354, -9586, -4685, -5287, -4514, -2553, -446, -9316, -7113, -8589, -7194, -6404, -7407, -10228, -2151, -2081, -4368, -10515, -1854, -7580, -9228, -6915, -2631, -10649, -2619, -4864, -3581, -3569, -7094, -3815, -3637, -6978, -610, -7453, -3305, -3386, -6429, -9499, -1064, -5814, -6151, -940, -10267, -7768, -1407, -8934, -4682, -7582, -1725, -9539, -4129, -2554, -1941, -2663, -1222, -5947, -836, -4001, -2857, -9940, -8876, -10012, -5784, -3353, -5827, -8645, -141, -4741, -2155, -4815, -7072, -4540, -10734, -6420, -3583, -9424, -1298, -7012, -6603, -5232, -7227, -8234, -1439, -920, -5365, -6998, -2036, -1683, -5327, -9970, -7986, -3866, -10676, -4820, -10604, -5067, -3774, -9075, -9886, -2098, -3902, -6260, -6820, -2486, -6773, -4006, -9933, -475, -874, -9028, -7841, -857, -3930, -3712, -10535, -6386, -6214, -8509, -7776, -10233, -2978, -8148, -7315, -8094, -7784, -10285, -10527, -10386, -7549, -8188, -6045, -6146, -7608, -7762, -6715, -8104, -2885, -7110, -749, -941, -180, -5848, -7643, -10912, -6250, -7694, -2059, -2404, -8178, -4062, -7213, -8850, -5320, -5260, -9154, -1275, -3401, -3726, -1205, -10723, -10024, -10020, -9396, -9035, -4747, -6552, -2593, -8971, -10736, -10813, -166, -9971, -441, -3105, -6474, -711, -1374, -5053, -3680, -3461, -4988, -1510, -10490, -2138, -5993, -6490, -7104, -9890, -8755, -1369, -1972, -3906, -3961, -6944, -4357, -5683, -8776, -8033, -3991, -7299, -10705, -9168, -5530, -2242, -1355, -6986, -1136, -8127, -665, -1136, -9137, -8369, -7092, -8887, -9584, -8137, -3319, -8735, -9047, -6986, -4012, -6258, -745, -8116, -4377, -4619, -8480, -10523, -4612, -4245, -4695, -6142, -2275, -9510, -9688, -7067, -6118, -7519, -2603, -6408, -5046, -8158, -7330, -5480, -1554, -6093, -2126, -10213, -10791, -7287, -5373, -1437, -377, -6445, -5674, -4245, -10761, -8478, -5960, -5197, -6996, -8927, -8341, -1403, -10756, -2296, +599, +691, +442, +437, +535, +875, +925, +640, +761, +116, +570, +714, +366, +755, +637, +919, +922, +5, +32, +637, +47, +877, +297, +757, +999, +448, +81, +808, +119, +870, +305, +84, +254, +321, +899, +508, +26, +397, +955, +206, +510, +265, +145, +124, +279, +641, +373, +916, +886, +112, +862, +205, +639, 174, -5985, -7456, -4412, -1987, -10249, -3666, -1227, -7832, -4215, -8292, -3116, -866, -965, -4451, -9311, -8638, -4443, -1612, -3299, -6381, -4365, -8372, -3833, -3996, -9268, -3684, -2016, -6124, -10359, -2043, -31, -10680, -773, -6087, -6707, -1441, -8741, -4612, -6003, -2981, -8608, -4442, -5190, -10734, -8194, -9641, -9660, -3394, -4076, -7341, -7382, -5193, -8828, -6725, -9569, -4787, -3410, -3144, -352, -6636, -5043, -9965, -4461, -1074, -1094, -4938, -9659, -1830, -5644, -4919, -3884, -3279, -7628, -9805, -10494, -5143, -6146, -6213, -1131, -5061, -1118, -10137, -3203, -5980, -5550, -6141, -2013, -10164, -10437, -2047, -2167, -5222, -6200, -8591, -8252, -2107, -2821, -5058, -2846, -10752, -6550, -851, -1985, -6133, -7273, -3993, -3903, -7310, -3043, -10122, -1448, -7626, -4690, -690, -6308, -7587, -7501, -9435, -1827, -5848, -5692, -4538, -10059, -618, -5272, -7935, -3707, -8882, -10284, -5428, -6815, -10580, -936, -8789, -6635, -3190, -3902, -6578, -5382, -435, -6029, -1253, -4264, -8183, -5907, -10434, -2038, -6077, -9982, +117, +981, +247, +800, +526, +569, +295, +277, +136, +165, +744, +422, +73, +621, +700, +522, +247, +560, 756, -9824, -4974, -7259, -6700, -3063, -6122, -6074, -2693, -9848, -3493, -1390, -5588, -993, -10923, -1103, -202, -6971, -4397, -4947, -2528, -1538, -8702, -7695, -1155, -336, -9823, -3391, -8183, -9912, -5639, -10523, -9198, -4596, -9018, -8656, -1796, -10445, -9346, -5457, -7821, -1513, -2299, -5760, -841, -1503, -2504, -4115, -3843, -92, -10706, -1694, -1868, -6065, -1531, -10120, -9640, -2037, -4580, -5831, -10577, -7527, -4778, -5861, -2407, -7288, -5766, -5333, -5323, -10838, -2357, -689, -6492, -2671, -7752, -5150, -725, -141, -10531, -3327, -1900, -9921, -2210, -8333, -5101, -5562, -1954, -4150, -10, -7454, -7963, -8670, -809, -8200, -1217, -9159, -7113, -7263, -6755, -4492, -464, -8208, -8157, -6540, -7352, -9195, -5748, -7662, -4351, -307, -1146, -5773, -9220, +604, 433, -2570, -6640, -2016, -4465, -7276, -4950, -9067, -9841, -631, -1396, -6599, -4528, -5219, -2057, -4064, -420, -8375, -1568, -4592, -34, -8126, -1395, -8911, -7057, -3191, -2836, -8532, -832, -9555, -6466, -10886, -9464, -8115, -5385, -14, -6285, -4229, -3751, -5302, -8195, -9543, -10256, -3010, -6182, -7156, -9424, -7656, -3983, -3777, -1558, -8606, -1899, -9245, -8686, -7277, -6857, -7213, -1981, -6582, -7201, -9868, -7395, -5144, -6072, -6471, -8324, -2619, -3319, -3875, -9855, -1327, -10570, -1357, -8413, -4850, -9146, -351, -748, -10189, -5810, -55, -2983, -7176, -2114, -7868, -10752, -4699, -2773, -6948, -4246, -10904, -4197, -428, -1586, -10985, -4155, -3656, -2493, -3577, -9165, -6278, -4731, -5203, -8559, -3214, -8591, -1295, -3299, -4366, -7147, -7317, -5086, -10043, -9299, -8463, -7784, -3530, -2799, -7898, -5637, -7197, -10150, -5062, -2423, -4841, -5948, -9218, -10485, -8688, -617, -5832, -5794, -1383, -8844, -7489, -2789, -10147, -6308, -5998, -3055, -1669, -5084, -3270, -10903, -7448, -5829, -7097, +148, +116, +721, +920, +72, +689, +89, +683, +267, 561, -10354, -6162, -3827, -69, -9032, -8627, -1266, -8066, -6173, -5081, -308, -4691, -10163, -8569, -7688, -10520, -5800, -7197, -2521, -5071, -795, -8779, -10883, -3961, -635, -3551, -5433, -7025, -2132, -4751, -10765, -8564, -10794, -9677, -10653, -3098, -8904, +581, +288, +371, +240, +74, +920, +985, +642, +672, +718, +318, +362, +667, +88, +533, +28, +717, +530, +813, +916, +648, +406, +934, +673, +31, +8, +879, +20, +596, +231, 181, -867, -1509, -101, -183, -2034, -10130, -10515, -3369, -7573, -10710, -5825, -1910, -2425, -8773, -2364, -10386, -7982, -1667, -9242, -6169, -10580, -1942, -1181, -9147, -759, -9050, -7728, -10225, -5131, -9179, -2197, -7524, -6095, -6845, -2693, -2440, -7821, -2239, -2752, -1433, -4928, -3724, -5185, -498, -8072, -525, -4315, -8762, -2346, -7344, -3878, -3432, -7017, -9882, -1200, -6100, -8579, -10018, -4426, -9080, -9513, -6150, -9356, -3306, -7875, -6030, -4096, -5194, -6225, -3906, -8926, -8830, -7293, -10297, -1366, -9919, -4592, -942, -8143, -5671, -7731, -5345, -3688, -7916, -349, -5385, -6220, -4098, -7382, -3015, -1257, -9360, -10442, -7144, -10780, -961, -9980, -7533, -7818, -6547, -10213, -5420, -8030, -7675, -681, -3663, -2313, -4880, -5140, -102, -5064, -8220, -6333, -303, -3364, -8337, -2899, -9488, -1523, -5106, -7194, -6041, -1701, -1912, -3028, -4636, -830, -2801, -6606, -3700, -8425, -7086, -6170, -10006, -5224, -3594, -4008, -1882, -527, -6841, -7012, -9084, -6481, -2050, -6523, -6965, -2442, -1801, +912, +305, +494, +788, +339, +305, +138, +461, +418, +169, 943, -2390, -10816, -7728, -10806, -1748, -8467, -9307, -3015, -9612, -4043, -9746, -3153, -6794, -2437, -8616, -1749, -4930, -4033, -6007, -7714, -5045, -4581, -3659, -1102, -6225, -3639, -9998, -6803, -5641, -4578, -5448, -2291, -5955, -8108, -1774, -5727, -7177, -6110, -4805, -8383, -8156, -6704, -8011, -10179, -76, -3740, -4715, -7051, -7559, -8106, -3723, -9002, -2939, -10919, -8964, -4750, -9954, -6076, -5444, -9492, -396, -2854, -9688, -3995, -1595, -1120, -9352, -6228, -913, -5371, -9624, -5399, -6767, -1417, -2931, -5935, -2381, -1866, -7558, -493, -7980, -6709, -7471, -975, -9839, -5746, -9603, -4040, -948, -4702, -1605, -7140, -3123, -5521, -7664, -8627, -5024, -3144, -7469, -9192, -10552, -4659, -2578, -5888, -1835, -3302, -4886, -10872, -9114, -7794, -131, -8749, -1760, -434, -7462, -9014, -6858, -7603, -223, -8112, +698, +271, +175, +556, +285, +4, +55, +856, +864, +849, +924, +572, +931, +93, +969, +986, +815, +838, +548, +789, +9, +762, +263, +652, +967, +409, +181, +302, +966, +890, +165, +34, +673, +480, +356, +799, +327, +401, +737, +424, +722, +908, +168, +479, +951, +625, +124, +886, +101, +564, +313, +602, +762, +803, +981, +580, +43, +426, +842, +837, +728, +890, +7, +569, +7, +1000, +613, +156, +947, +805, 518, -2602, -5072, -2119, -5946, -3811, -8111, -9578, -1924, -1514, -10862, -8192, -7330, -988, -1837, -589, -9185, -5826, -9274, -5524, -3528, -8274, -9256, -4561, -2605, -8704, -9565, -10841, -3807, -2071, -10633, -1027, -8053, -3281, -9872, -2019, -9584, -2909, -3122, -9110, -9298, -5160, -8485, -7243, -1799, -10648, -4398, -3342, -7064, -6288, -4396, -4536, -5497, -6875, -3734, -8056, -3430, -2106, -5717, -3708, -2960, -8741, -10543, -5575, -10273, -6409, -7273, -6061, -2727, -172, -476, -2468, -4672, -8681, -460, -343, -10923, -10111, -3190, -5852, -2976, -9945, -9293, -510, -7903, -2223, -2001, -7010, -10744, -489, -987, -10955, -6904, -10694, -2733, -8295, -7505, -1501, -8026, -7629, -4036, -10778, -1078, -7462, -8224, -5264, -1904, -2197, -9185, -4720, -3726, -9401, -4178, -10416, -9739, -9869, -9557, -2091, -6872, -10525, -6552, -1216, -9059, -4610, -2752, -7577, -1140, -1756, -10391, -4577, -4596, -6232, -5073, -6828, -33, -9704, -610, -4068, -7857, -4653, -6455, -113, -10677, -5562, -1964, -520, -10072, -10878, -5898, -2613, -9766, -4919, -6399, -9125, -1882, -1689, -7751, -2840, -5762, -4500, -8745, -7658, -5516, -8186, -3196, -4082, -3840, -5644, -8335, -6471, +739, +287, +104, +90, +374, +427, +824, +199, 395, -6280, -2675, -901, -6496, -707, -6013, -5722, -6159, -5685, -7509, -1441, -2114, -7019, -10038, -718, -4513, -10895, -5158, -2788, -2529, -1634, -10858, -10187, -9783, -10374, -7809, -862, -7393, -3785, -5043, -6801, -9163, -2975, -8559, -3163, -3938, -7329, -2011, -6203, -4904, -5813, -120, -10397, -5435, -3493, -9949, -3432, -7785, -5700, -51, -381, -2559, -3793, -4091, -9162, -3979, -703, -4902, -3453, -2962, -6644, -7407, -6729, -7045, -3478, -6153, -5385, -1017, -4072, -7457, -5904, -7607, -10885, -8118, -10261, -4411, -3638, -7118, -2790, -8671, -8248, -619, -9693, -1831, -9603, +328, +535, +539, +970, +328, +824, +522, +793, +689, 818, -7812, -1573, +404, +99, +912, 14, -4095, -208, -2917, -9313, +532, +731, +478, +992, +306, +348, +343, +14, +123, +875, +283, +32, +558, +266, +718, +163, +646, +254, +416, +240, +580, +514, +490, +230, +743, +678, +321, +63, +216, +657, +26, +269, +688, +757, +497, +848, +431, +770, +818, +804, +390, +793, +815, +537, +358, +528, +8, +43, +52, +856, +674, +798, +969, +207, +217, +855, +780, +480, +159, +330, +9, +616, +573, +533, +796, +341, +323, +955, +692, +490, +841, +43, +119, +152, +278, +514, +520, +598, +591, +723, +834, +342, +6, +848, +252, +611, +267, +527, +32, +398, +485, +179, +575, +989, +981, +735, +663, +736, +765, +81, +608, +84, +320, +536, +172, +506, +27, +319, +896, +765, +219, +881, +886, +360, +45, +543, +261, +710, +809, +961, +426, +573, +11, +850, +147, +573, +135, +948, +727, +790, +142, +948, +661, +537, +277, +575, +954, +397, +121, +137, +192, +634, +225, +636, +756, +120, +180, +595, +327, +541, +759, +930, +301, +489, +878, +286, +700, +686, +912, +39, +515, +703, +135, +711, +461, +370, +351, +734, +234, +515, +521, +335, +808, +664, +851, +981, +960, +451, +272, +199, +114, +878, +755, +73, +379, +519, +198, +6, +938, +381, +381, +276, +962, +543, +175, +227, +757, +889, +448, +933, +728, +211, +357, +957, +800, +830, +394, +350, +636, +126, +702, +135, +741, +461, +725, +452, +821, +46, +129, +709, +231, +325, +301, +494, +942, +147, +711, +589, +326, +822, +590, +172, +554, +28, +184, +667, +482, +228, +897, +398, +459, +379, +58, +179, +325, +996, +784, +813, +356, +69, +719, +117, +483, +127, +889, +771, +883, +347, +158, +258, +6, +887, +630, +268, +648, +310, +430, +925, +728, +601, +751, +828, +521, +173, +604, +406, +777, +389, +117, +269, +957, +141, +729, +249, +611, +605, +233, +767, +122, +341, +773, +506, +745, +509, +427, +167, +867, +835, +826, +387, +297, +111, +955, +142, +693, +585, +805, +576, +918, +761, +42, +430, +333, +411, +119, +192, +682, +376, +509, +448, +720, +772, +391, +512, +864, +839, +612, +556, +642, +415, +930, +850, +691, +671, +0, +932, +160, +510, +678, +433, +719, +55, +37, +526, +290, +192, +239, +726, +775, +451, +33, +367, +586, +970, +215, +446, +765, +807, +515, +482, +492, +667, +523, +132, +193, +30, +104, +74, +332, +256, +780, +398, +526, +972, +940, +524, +554, +298, +73, +426, +668, +520, +387, +799, +952, +794, +629, +643, +284, +682, +65, +467, +674, +853, +500, +566, +830, +367, +374, +388, +69, +80, +424, +30, +912, +776, +106, +115, +146, +903, +14, +901, +742, +843, +492, +338, +402, +72, +306, +820, +573, +410, +183, +609, +79, +424, +783, +508, +601, +224, +922, +65, +765, +12, +535, +753, +177, +452, +550, +989, +147, +465, +763, +478, +299, +71, +182, +329, +270, +889, +77, +931, +490, +723, +283, +809, +792, +224, +2, +315, +823, +188, +21, +1000, +757, +716, +578, +921, +386, +612, +707, +166, +400, +432, +385, +653, +742, +142, +923, +926, +855, +265, +594, +846, +346, +126, +382, +656, +477, +795, +470, +270, +710, +218, +224, +324, +135, +56, +762, +55, +495, +646, +121, +776, +208, +254, +852, +577, +293, +693, +81, +10, +245, +904, +228, +191, +784, +821, 870, -3321, -4971, -10003, -9592, -1305, -6616, -5610, -6524, -1766, +197, +453, +263, +375, +254, +304, +726, +958, +726, +956, +501, +936, +115, +831, +960, +534, +973, +613, +453, +658, +827, +806, +486, +516, +512, +652, +435, +318, +44, +437, +495, +767, +1, +641, +896, +8, +777, +567, +369, +14, +272, +741, +600, +975, +296, +774, +662, +15, +485, +415, +803, +674, +565, +554, +895, +201, +734, +759, +576, +499, +687, +205, +499, +654, +815, +293, +729, +489, +705, +892, +51, +597, +625, +96, +216, +589, +506, +32, +251, +76, +280, +829, +334, +262, +399, +275, +11, +392, +298, +485, +506, +324, +26, +971, +89, +615, +971, +678, +866, +51, +42, +972, +352, +691, +363, +687, +778, +446, +82, +458, +700, +309, +224, +728, +779, +656, +507, +851, +402, +402, +495, +380, +663, +815, +279, +508, +603, +54, +154, +872, +806, +683, +542, +771, +118, +994, +760, +323, +369, +765, +570, +761, +556, +703, +436, +175, +992, +981, +168, +204, +168, +100, +739, +407, +385, +583, +837, +62, +104, +734, +726, +737, +492, +598, +789, +251, +947, +910, +540, +120, +907, +269, +279, +640, +192, +782, +413, +834, +992, +901, +814, +482, +796, +8, +300, +188, +302, +93, +671, +653, +285, +60, +868, +490, +52, +584, +248, +244, +949, +204, +278, +202, +905, +749, +805, +953, +647, +642, +289, +826, +145, +181, +968, +286, +707, +760, +48, +390, +983, +69, +461, +668, +864, +932, +758, +622, +453, +101, +517, +543, +735, +748, +687, +224, +735, +703, +480, +770, +566, +553, +382, +801, +629, +616, +742, +819, +341, +313, +45, +468, +479, +321, +399, +869, +796, +435, +864, +847, +494, +663, +818, +655, +828, +620, +235, +749, +559, +36, +537, +32, +731, +309, +951, +886, +153, +324, +951, +455, +435, +17, +410, +279, +390, +408, +637, +93, +600, +34, +936, +133, +929, +565, +930, +287, +902, +513, +84, +434, +564, +992, +785, +715, +213, +928, +25, +465, +13, +954, +629, +100, +224, +217, +652, +188, +405, +915, +71, +222, +512, +961, +408, +732, +221, +890, +780, +355, +46, +79, +726, +868, +935, +102, +958, +794, +208, +659, +738, +360, +385, +926, +502, +72, +664, +330, +569, +535, +160, +111, +584, +625, +246, +904, +72, +698, +937, +155, +619, +682, +851, +675, +953, +266, +632, +906, +122, +680, +913, +557, +247, +352, +804, +885, +138, +781, +51, +281, +34, +876, +256, +455, +841, +847, +816, +598, +984, +76, +756, +896, +192, +625, +670, +134, +36, +258, +906, +897, +732, +797, +468, +17, +109, +480, +304, +762, +575, +639, +466, +374, +132, +403, +875, +315, +170, 538, -5301, -9135, -1367, -2834, -1959, -3913, -6701, -10044, -5365, -2460, -3698, -10352, -1433, +118, +25, +380, +72, +579, +106, +756, +539, +810, +939, +529, +782, +797, +407, +762, +106, +204, +517, +737, +730, +521, +599, +986, +656, +179, +175, +208, +775, +723, +982, +440, +69, +518, +626, +709, +824, +951, +30, +201, +692, +163, +587, +554, +694, +202, +827, +465, +561, +973, +681, +27, +88, +905, +557, +936, +746, +147, +610, +454, +887, +349, +44, +355, +333, +760, +134, +688, +869, +738, +43, +891, +50, +782, +65, +190, +529, +792, +807, +597, +373, +188, +585, +398, +671, +637, +450, +142, +573, +408, +825, +565, +983, +159, +399, +752, +589, +617, +336, +885, +925, +577, +12, +816, +127, +0, +924, +816, +915, +540, +276, +174, +695, +943, +45, 84, -8095, -1120, -7913, -3633, -412, -3687, -10238, -9953, -2757, -10502, -3705, -8023, -771, -2779, -10389, -10459, -2889, -8493, -6798, -4330, +862, +340, +306, +407, +644, 663, -2893, -10486, -7439, -6456, -4113, -6063, -6841, -9510, -7209, -8728, -79, -7163, -6792, -5433, -3856, -1158, -7837, -679, -4145, -4569, -1649, -4775, -993, -1403, -5613, -6111, +756, +540, +319, +974, +961, +564, +359, +597, +505, +62, +765, +380, +439, +212, +433, +95, +940, +222, +730, +824, +262, +779, +671, +333, +118, +192, +263, +299, +165, +842, +594, +617, +963, +157, +110, +906, +115, +367, +313, +880, +117, +678, +114, +28, +808, +590, +259, +271, +138, +36, +177, +814, +985, +837, +448, +542, +492, +657, +146, +745, +734, +200, +369, +612, +350, +39, +461, +284, +260, +522, +808, +954, +879, +333, +459, +307, +912, +27, +777, +421, +865, +128, +686, +879, +759, +628, +618, +351, +173, +723, +20, +535, +16, +227, +918, +824, +538, +673, +833, +513, +20, +385, +876, +875, +257, +873, +446, +133, +640, +368, +94, +750, +662, +969, +110, +757, +283, +263, +100, +759, +19, +202, +895, +507, +600, +208, +753, +479, +203, +218, +103, +334, +194, +331, +656, +654, +325, +847, +139, +340, +650, +742, +796, +54, +664, +220, +610, +273, +682, +109, +307, +798, +582, +318, +136, +632, +979, +285, +755, +148, +890, +912, +496, +138, +742, +450, +339, +640, +539, +357, +741, +726, +301, +355, +318, +279, +220, +768, +909, +161, +646, +416, +118, +1, +630, +897, +198, +753, +999, +456, +277, +715, +107, +405, +746, +419, +531, +1, +168, +185, 911, -3616, -9142, -1259, -5621, -8449, -4778, -7544, -5119, -2370, -7226, -2445, -6680, -9432, +812, +97, +56, +966, +928, +755, +667, +785, +739, +183, +502, +61, +872, +516, +377, +48, +433, +18, +383, +48, +941, +4, +455, +316, +390, +767, +703, +513, +154, +781, +644, +322, +656, +358, +839, +368, +589, +986, +562, +667, +274, +767, +460, +128, +590, +81, +930, +454, +257, +177, +153, +889, +781, +116, +35, +463, +126, +544, +176, +621, +174, +335, +569, +457, +156, +931, +469, +631, +711, +259, +239, +469, +834, +432, +873, +815, +517, +175, +424, +337, +555, +326, +1, +179, +306, +472, +628, +326, +368, +600, +551, +616, +405, +338, +44, +417, +322, +762, +414, +607, +919, +661, +731, +794, +984, +614, +810, +432, +665, +901, +421, +538, +534, +804, +400, +524, +852, +809, +814, +157, +849, +487, +366, +418, +479, +935, +549, +298, +667, +740, +537, +867, +454, +284, +397, +504, +737, +675, +648, +952, +824, +51, +631, +624, +343, +260, +437, +572, +922, +987, +756, +102, +318, +306, +39, +622, +620, +273, +772, +599, +639, +282, +655, +562, +766, +261, +422, +501, +26, +942, +456, +174, +927, +998, +50, +350, +258, +231, +198, +394, +149, +727, +88, +891, +281, +901, +925, +793, +786, +696, +941, +130, +144, +233, +195, +322, +86, +329, +479, +534, +6, +939, +410, +848, +242, +714, +556, +260, +636, +818, +810, +985, +458, +845, +353, +204, +810, +262, +586, +895, +491, +459, +73, +537, +873, +138, +233, +799, +91, +778, +802, +191, +436, +164, +470, +550, +557, +330, +380, +387, +147, +74, +919, +888, +323, +789, +428, +422, +740, +637, +606, +850, +562, +775, +721, +926, +627, +231, +468, +163, +587, +141, +361, +409, +564, +873, +563, +420, +117, +556, +165, +70, +271, +19, +813, +984, +551, +560, +808, +437, +424, +725, +291, +275, +976, +93, +613, +502, +477, +364, +25, +116, +94, +72, +18, +581, +493, +33, +734, +445, +633, +899, +200, +823, +493, +889, +550, 215, -1828, -1630, -10297, -8148, -3959, -2759, -8003, -2647, -3348, -6832, -7637, -1099, -9211, -8589, -10635, -4437, -4080, -8448, -7502, -7974, -3297, -2160, -1204, -1981, -8121, -10721, +670, +690, +400, +774, +144, +473, +279, +178, +331, +807, +792, +329, +366, +337, +18, +427, +705, +444, +775, +868, +698, +808, +574, +450, +337, +267, +213, +126, +15, +782, +891, +823, +550, +211, +883, +556, +54, +237, +583, +91, +7, +607, +241, +505, +669, +864, +213, +532, +641, +460, +503, +843, +380, +662, +949, +149, +452, +928, +753, +716, +24, +728, +599, +223, +43, +770, +559, +158, +463, +641, +637, +858, +557, +258, +755, +59, +940, +513, +196, +189, +646, +259, +241, +547, +61, +198, +827, +5, +939, +694, +429, +705, +936, +296, +724, +399, +710, +646, +246, +645, +703, +447, +929, +623, +586, +791, +808, +174, +289, +352, +731, +514, +48, +604, +634, +343, +370, +827, +872, +586, +720, +106, +469, +880, +955, +792, +818, +849, +458, +995, +109, +966, +632, +892, +142, +207, +39, +939, +711, +862, +798, +858, +118, +906, +896, +619, +501, +125, +617, +131, +306, +949, +90, +736, +89, +308, +316, +813, +744, +23, +842, +284, +816, +300, +204, +932, +486, +241, +438, +433, +869, +954, +619, +900, +77, +342, +633, +40, +399, +271, +482, +472, +486, +648, +357, +712, +923, +102, +540, +1000, +732, +410, +87, +223, +768, +152, +811, +904, +116, +944, +500, +809, +995, +829, +972, +162, +912, +767, +131, +706, +55, +996, +336, +306, 368, -8018, -1182, -5622, -10343, -4773, -6127, -8214, -3233, -10922, -8659, -8132, -589, -7306, -10601, -6079, -2242, -1583, -876, -4933, -7151, -6534, -2051, -1849, -3246, -10301, -1115, -4350, -3782, -10243, -3784, -5188, -5072, +745, +980, +308, +386, +36, +268, +118, +463, +640, +598, +907, +535, +369, +431, +284, +87, +81, +164, +13, +830, +711, +524, +988, +173, +31, +997, +939, +7, +45, +309, +298, +316, +936, +320, +107, +484, +127, +520, +783, +921, +240, +150, +945, +85, +335, +290, +533, +759, +673, +342, +144, +1000, +46, +815, +257, +189, +764, +351, +152, +29, +180, +239, +104, +274, +824, +766, +501, +182, +91, +998, +233, +955, +307, +513, +618, +917, +746, +600, +76, +681, +197, +56, +578, +154, +997, +500, +146, +756, +840, +449, +913, +454, +424, +420, +987, +460, +771, +632, +30, +570, +613, +243, +673, +100, +521, +143, +989, +561, +473, +490, +236, +599, +837, +683, +964, +333, +17, +736, +915, +262, +675, +668, +907, +468, +959, +645, +857, +499, +28, +287, +172, +129, +162, +807, +232, +356, +138, +810, +588, 265, -10613, -8500, -10008, -7771, -3230, -8852, -4226, -9249, -5117, -5138, -1888, -568, -9655, -7856, -1860, -6206, -9884, -5672, -10941, +670, +492, +297, +829, +341, +748, +825, +833, +636, +375, +974, +250, +83, +27, +641, +179, +806, +775, +648, +869, +487, +138, +865, +696, +621, +0, +78, +449, 959, -8000, -6934, -4388, -9608, -2932, -3991, -10446, -4430, -3392, -2787, -2299, -10726, -1945, -2345, -609, -8851, -9445, -3114, -5603, -2161, +675, +144, +681, +373, +28, +901, +899, +562, +597, +43, +254, +318, +354, +549, +896, +802, +920, +879, +864, +86, +615, +639, +525, +812, +266, +868, +61, +962, +882, +980, +756, +90, +35, +215, +930, +94, +446, +348, +927, +514, +886, +993, +681, +277, +653, +573, +853, +236, +82, +283, +756, +803, +226, +656, +808, +904, +169, +605, +854, +39, +399, +600, +703, +792, +851, +878, +374, +610, +476, +979, +285, +985, +823, +991, +725, +477, +420, +87, +328, +229, +825, +750, +226, +148, +770, +523, +843, +327, +734, +247, +490, +988, +753, +381, +325, +86, +678, +513, +33, +273, +443, +526, +834, +344, +210, +266, +262, +745, +515, +921, +439, +753, +658, +473, +339, +631, +143, +699, +731, +850, +547, +585, +744, +363, +689, +53, +170, +737, +664, +390, +964, +673, +340, +275, +574, +414, +713, +377, +812, +743, +489, +292, +991, +768, +673, +858, +745, +497, +982, +955, +156, +153, +949, +245, +375, +267, +166, +888, +35, +475, +897, +207, +497, +126, +134, +744, +820, +861, +781, +529, +579, +829, +870, +695, +819, +294, +427, +769, +727, +524, +463, +356, +71, +392, +58, +523, +261, +186, +98, +485, +591, +845, +292, +304, +251, +640, +292, +794, +441, +969, +717, +548, +645, +57, +990, +192, +49, +966, +328, +860, +761, +937, +221, +623, +113, +418, +473, +827, +228, +924, +656, +209, +766, +917, +75, +932, +163, +815, +356, +677, +770, +820, +809, +245, +795, +587, +526, +655, +238, +219, +448, +482, +356, +60, +318, +173, +46, +184, +69, +251, +886, +389, +433, +790, +791, +557, +552, +453, +177, +968, +558, +205, +703, +463, +373, +792, +716, +45, +282, +837, +588, +752, +263, +613, +670, +171, +359, +878, +734, +259, +850, +235, +310, +376, +505, +646, +443, +456, +863, +786, +0, +543, +226, +119, +488, +797, +731, +778, +945, +957, +210, +802, +677, +131, +621, +957, +944, +583, +12, +968, +408, +734, +579, +10, +473, +319, +506, +470, +4, +369, +298, +936, +999, +978, +544, +600, +965, +603, +113, +940, +984, +158, +333, +211, +990, +360, +285, +449, +836, +825, +787, +199, +912, +799, +793, +965, +198, +830, +708, +684, +49, +951, +518, +334, +27, +848, +741, +922, +166, +109, +248, +101, +570, +800, +350, +585, +952, +268, +897, +332, +997, +280, +949, +314, +89, +175, +675, +227, +27, +976, +758, +989, +793, +256, +673, +160, +571, +28, +326, +251, +246, +872, +587, +288, +972, +162, +255, +959, +189, +457, +615, +394, +51, +681, +117, +128, +907, +222, +39, +447, +939, +549, +27, +359, +266, +294, +810, +123, +189, +770, +960, +161, +853, +579, +724, +402, +477, +430, +455, +58, +175, +683, 376, -8934, -8214, -2420, -3653, -10720, +181, +571, 804, -8931, -6703, -8024, -1060, -4641, -5307, -2689, -3107, -5697, -3431, -2236, -9570, -476, -10824, -2796, -5243, -6325, -4981, -901, -1599, -3530, -8959, -10655, -8411, -10124, -4232, -2079, -7851, -7005, -8575, -8483, -2010, -9267, -1799, -617, -9261, -9771, -6098, -9933, -7027, -6101, -10471, -592, -10471, -6822, -9252, -10666, -5371, -3102, -8588, -1497, -9748, -1710, -10103, -10090, -4494, -9110, -9162, -1841, +359, +607, +74, +308, +78, +580, +741, +457, +100, +244, +998, +22, +690, +53, +619, +882, +338, +288, +598, +965, +748, +657, 844, -9346, -6546, -1143, -9036, -7657, -5130, -8036, -3654, -9012, -3991, -5637, -10428, -1233, -9978, -3836, -7762, -10449, -6160, -6675, -5960, -4118, -3515, -1553, -2185, -7788, -3202, -10503, -5366, -4806, -9477, -8470, -3308, -8991, -4367, -344, -3253, -292, -9789, -618, -2433, -3747, +693, +921, +108, +185, +44, +695, +76, +321, +400, +852, +820, +511, +145, +585, +206, +544, +623, +773, +498, +865, +985, +551, 301, -694, -5565, -1086, -6807, -8519, -6707, -7935, -5423, -10118, -453, -1781, -6929, -1087, -10263, -6086, -2181, -5196, -1468, -7799, -9959, -9876, -8051, -1390, -3334, -10801, -7346, -3815, -4089, -2190, -10689, -225, -8254, -10969, -6670, -10320, -1232, -9240, -9688, -5098, -6566, -6058, -9548, -5419, -8202, -5223, -6391, -8146, -6867, -3428, -1255, -6903, -10708, -6466, -6847, -9776, -7156, -1521, -6355, -9474, -3873, +865, +880, +740, +77, +172, +970, +717, +62, +106, +58, +294, +384, +746, +99, +644, +882, +18, +219, +214, +612, +901, +115, +529, +332, +99, +768, +301, +77, +951, +599, +775, +783, +700, +978, +465, +772, +744, +834, +35, +408, 963, -7008, -2400, -2662, -5050, -6684, -4279, -4883, -6733, -6135, -10610, -1061, -2503, -2393, -9298, -3640, -8160, -4223, -1977, -4001, -9278, -7851, -3982, -6325, -10675, -7990, -4666, -5913, -10796, -4572, -7022, -328, -6830, -10639, -6229, -1826, -7710, -2539, -3622, -2538, -9980, -1769, +482, +159, +10, +646, +205, +753, +538, +600, +208, +731, +627, +468, +624, +344, +77, +144, +132, +503, +499, +15, +145, +385, +707, +595, +924, +113, +952, +325, +906, +471, +209, +505, +396, +989, +321, +68, +507, +811, +434, +816, +349, +696, +840, +750, +515, +246, +408, +282, +134, +916, +115, +858, +309, +706, +937, +273, 62, -3634, -6023, -3730, -7256, -1796, -1213, -5066, -1074, -2854, -6626, -657, -8818, -2776, -1633, -814, -6975, -7698, -3580, -2498, -10308, -6634, -6476, -1125, -7815, -2370, -2453, -230, -4638, -5948, -244, -2594, -5511, -4623, -2037, -4932, -6517, -3939, -657, -5791, -9597, -8060, -9077, -9695, -8263, -143, -7967, -10615, -3749, +601, +431, +997, +1, +216, +365, +497, +119, +893, +351, +762, +588, +932, +317, +11, +174, +319, +438, +65, +41, +301, +906, +639, +720, +606, +352, +168, +727, +727, +363, +688, +102, +942, +487, +11, +68, +420, +379, +504, +504, +637, +269, +639, +921, +595, +128, +836, +398, +225, +75, +628, +480, +961, +492, +510, +552, +414, +746, +719, +572, +620, +717, +201, +269, +635, 359, -8009, -9717, -8147, -6684, -5920, -2980, -3001, -3398, -2507, -10051, -9346, -10680, -7006, -4855, -377, -7181, -5570, -7756, -36, -10289, -3466, -5936, -1621, -5427, -6131, -2543, -1809, -5569, -6877, -3190, -5387, -5048, -3613, -9198, -6866, -10690, -5998, -6976, -8092, -35, -3213, -8605, -8844, -1265, -10116, -1498, -8692, -7358, -7806, -6013, -1189, -6309, -10576, -9500, -2607, -56, -5900, -4963, -464, -368, -7188, -2398, -10806, -6470, +513, +274, +960, +989, +912, +488, +393, +258, +268, +811, +565, +597, +714, +101, +531, +493, +330, 867, -4214, -5167, -6145, -1797, -1643, -4707, -9286, -8048, -1403, -7693, -6660, -8474, -7513, -9341, -3516, -10294, -5474, -9697, -2619, -9018, -1138, -2335, -9674, -5125, -805, -8097, -303, -10580, +183, +978, +861, +348, +649, +106, +696, 336, -2840, -1616, -8599, -10946, -7093, -919, -10685, -1465, -8032, -3981, -5072, -1049, -3552, -3379, -1863, -3841, -4609, -8864, -6123, -7469, -3194, -8541, -2006, -41, -10723, -8401, -2791, -2073, -5831, -5019, -2079, -10304, -360, -2737, -6723, -5772, -6268, -9717, -4897, -216, -5229, -5238, -5056, -681, -6234, -6763, -4511, -10277, -7312, -8291, -1714, -9929, -5990, -1050, -9757, -5177, -8713, -1976, -7038, -7954, -7511, -10413, -3, -1560, -2858, -2336, -3375, -3222, -7635, -4722, -3105, -10160, -4182, -9410, -239, -2600, -1067, -7255, -6025, -5976, -9983, -8904, -8215, -4755, -5425, -2399, -9879, -8291, -4545, -6238, -6285, -3175, -6432, -3781, -7316, -10621, -5736, -7614, -2050, -9466, -3247, -4295, -2397, -998, -7979, -10647, -5605, -8708, -1784, -8042, -4977, -3810, -1898, -8720, -7600, -6620, -606, -7165, -4570, -9079, -5358, -260, -8372, -4629, -787, -5524, -6699, -212, -1168, -3085, -10296, -1489, -4281, -8290, -9317, -4048, -3508, -5465, -318, -10140, -969, -958, -9958, -9281, -9773, -8535, -8776, -4195, -10993, -3514, -7574, -6476, -7577, -5989, -1697, -10443, -9125, -10679, -1625, -3073, -2673, -3656, -6282, -5977, -7603, -10974, -3619, -1616, -6408, -1381, -523, -33, -3568, -3377, -8468, -4270, -7636, -10544, -3259, -6492, -6573, -5171, -1880, -7846, -3308, -3620, -2418, -7251, -5671, -9427, -4323, -206, -10372, -1268, -4442, -133, -7559, -8214, -1011, -4645, -1059, -5926, -5189, -8754, -1716, -6631, -9234, -7734, -6396, -5119, -7832, -3349, -2308, -4706, -495, -587, -4835, -4114, -7183, -1228, -425, -5518, -10024, -511, -1629, -6826, -7217, -5428, -5401, -9443, -83, -3989, -8674, -5418, -446, -7315, -10792, -6186, -4852, -4301, -7020, -4812, -2247, -1980, -9438, -3139, -5895, -1235, -536, -9070, -10648, -6114, -4503, -3912, -8544, -8678, -4385, -550, -5835, -1936, -8511, -1485, -5029, -4712, -2388, -1198, -7367, -7276, -9919, -1650, -6748, -105, -2004, -4453, -8603, -7623, -6584, -9149, -6550, -111, -4290, -8833, -8221, -9270, -6287, -4656, -3576, -8865, -883, -7953, -1222, -8272, -5346, -9195, -5612, -3818, -6081, -2232, -6243, -455, -4644, -5654, -7645, -2776, -10088, -410, -8272, -2820, -5272, -10366, -3261, -1356, -8204, -5657, -408, -7067, -8611, -10574, -2122, -2019, -468, -10183, -5254, -8033, -7705, -3794, -6993, -8722, -399, -4225, -6778, -10906, -10234, -3097, -5096, -5633, -3196, -9102, -4708, -10464, -2034, -5674, -8327, -9143, -6131, -9334, -4723, -4679, -10002, -10308, -695, -3774, -9288, -4342, -9325, -1588, -9901, -10173, -5624, -9344, -4732, -9409, -5196, -9112, -911, -7440, -43, -2938, -187, -10855, -10111, -9530, -4788, -5626, +869, +490, +27, +860, +421, +641, +123, +314, +299, +114, +341, +732, +268, +201, +799, +837, +596, +382, +810, +613, +800, +914, +633, 581, -10156, -6050, -3758, -1549, -8606, -9685, -10622, -6978, -7126, -6779, -604, -8105, -1395, -8718, -10634, -10945, -2278, -10316, -5540, -2228, -277, -3975, -10568, -4215, -1998, -9751, -3311, -5469, -4278, -8614, -4701, -10499, -7, -4288, -7660, -10633, -10396, -1576, -5305, -9019, -3507, -4241, -4802, -513, -1073, -10734, -0, -8810, -2125, -669, -2066, -9928, -10630, -2854, -2205, -4968, -7251, -303, -10319, -4403, -5715, -7727, -7269, -1679, -10778, +313, +310, +755, +192, +908, +552, +149, +497, +31, +346, +531, +178, +309, +924, +170, +19, +449, +85, +729, +818, +708, +633, +309, +221, +723, +404, +530, +758, +755, +397, +438, +688, +310, +621, +555, +595, +60, +248, +423, +502, +45, +411, +857, +306, +925, +534, +111, +516, +875, 618, -5494, -4104, -1081, -2796, -7500, -1174, -763, -9636, -6220, -4656, -10511, -7881, -539, -5631, -9650, -8228, -7839, -6252, -4927, -9898, -7606, -7951, -87, -997, -1907, -2811, -5551, -445, -5549, -1590, -3523, -9025, -3130, -2793, -955, -2417, -8291, -2286, -7395, -5547, -7107, -9103, -5526, -6038, -8168, -152, -909, -2232, -1582, -5700, -2781, -10720, -3605, -8040, -1710, +390, +291, +14, +456, +924, +673, +713, +273, +5, +368, +585, +733, +512, +489, +18, +903, +455, +36, +95, +191, +431, +659, +241, +850, +567, +904, +129, +673, +65, +592, +577, 168, -1716, -7776, -8080, -5775, -3332, -7849, -7533, -79, -5798, +473, +599, +429, +631, +274, +692, +390, +657, +728, +10, +198, +980, +257, +481, +704, +101, +17, +893, +288, +169, +821, +721, +829, +654, +139, +731, +90, 411, -9402, -1344, +377, +833, +22, +720, +296, +960, +916, +351, +787, +520, +922, +223, +302, +843, +703, +782, +737, +920, +874, +631, +982, +430, +85, +415, +19, +726, +301, +765, +839, +663, +726, +337, +624, +715, +865, +312, +236, +843, +326, +581, +76, +635, +237, +104, +116, +950, +485, +994, +837, +853, +479, +880, +39, +502, +607, +559, +656, +741, +916, +307, +313, +925, +141, +899, +348, +379, +189, +296, +432, +606, +818, +320, +977, +190, +681, +987, +857, +84, +470, +803, +435, +799, +856, +925, +965, +471, +792, +962, 779, -10504, -6224, -6424, -7171, -10992, -10408, -4299, -8319, -6195, +70, +88, +370, +730, +376, +863, +279, +173, +263, +838, +605, +568, +596, +928, +137, +633, +85, +315, +898, +36, +249, +544, +71, +520, +942, +945, +664, +586, +196, +752, +866, +575, +92, +841, +919, +647, +613, +528, +864, +989, +635, +283, +162, +589, +583, +173, +697, +37, +227, +448, +265, +479, +934, +712, +206, +880, +641, +674, +311, 175, -9336, -5245, -4558, -3618, -9286, -1157, -7171, -9022, -7189, -6400, -3465, -8143, -4040, -3821, -4571, -10407, -8716, -5884, -9383, -7426, -9410, -4356, -2488, -8100, -9730, -7438, -8495, -737, -6732, -2500, -7072, -614, -10201, -1012, -3452, -3583, -6546, -4174, -2022, -8735, -8011, -1019, -7286, -9250, -3683, -5146, -4941, -10270, -3838, -4035, -4192, -7024, -7819, -1852, -10618, -9828, -3781, -6632, -1109, -2104, -6183, -1956, -10271, -1671, -5468, -1553, -1940, -2298, -10719, -7717, -8388, -5651, -8039, -3945, -10883, -3537, -4885, -714, -4598, -6457, -9782, -9459, -2717, -2471, -7044, -10398, -1399, -9345, -8011, -897, -9309, -3720, -6762, -2235, -1479, -3474, -3841, -7801, -5972, -4110, -4101, -6189, +513, +322, +875, +905, +325, +444, +698, +500, +858, +733, +871, +490, +740, +71, +12, +981, +877, +356, +454, +260, +95, +39, +332, +692, +334, 991, -3332, -8822, +189, +907, +358, +431, +473, +376, +716, +405, +884, +890, +545, +165, +512, +642, +784, +14, +896, +841, +926, +229, +296, +186, +362, +848, +782, +175, +459, +454, +681, +376, +691, +714, +414, +133, +100, +212, +550, +213, +318, +479, +25, +363, +187, +983, +736, +377, +535, +505, +14, +125, +871, +13, 588, -6854, -425, -2545, -5234, -8548, -9420, -7237, -3270, -5063, -9390, -888, -2914, -9589, -10520, -322, -1870, -6433, -8059, -462, -8321, -5410, -573, -998, -5607, -3482, -8901, -7514, -10109, -4473, -6790, -3236, -10719, -9201, -875, -5796, -2846, -3183, -10817, -4027, -5620, -6218, -5437, -5712, -8351, -1563, -209, -6671, -8961, -5382, -1021, -8522, -7612, -3199, -1937, -4645, -268, -5573, -1715, -10849, -3159, -5921, -4384, -3194, -7255, -3122, -4055, -3206, -823, -6546, -4719, -4753, -4263, -3124, -5495, -5239, -1404, -5209, -9493, -9350, -2488, -786, -10047, -7226, -3807, -6410, -8206, -3184, -1588, -5589, -1785, -3626, -5486, -712, -5224, -7709, -4521, -8365, -1876, -2311, -4945, -6094, -4178, -9107, -9519, -4114, -7185, -760, -3948, -5264, -4657, -2335, -9968, -8285, -7528, -9213, -3466, -4358, -4771, -5340, -5406, -8324, -955, -4756, -10362, -283, -4448, -8430, -6409, -8125, -9483, -10026, -1923, -3195, -5862, -2360, -1769, -274, -4427, -388, -3069, -1661, -8930, -2836, -8503, -4454, -9128, -4494, -2895, -1280, -10999, -3091, -10875, -2367, -2419, -4803, -2040, -1152, -8652, -9364, -7544, -5151, -6289, -8170, +763, 442, -5180, -664, -1396, -5084, -8107, -4443, -9766, -2439, -8950, -189, -8362, -3908, -9903, -10327, -4139, -5369, -10155, -10582, -6550, -7864, -4090, -584, -10673, -10383, -1636, -6169, -5283, -8274, -536, -7381, -690, -1787, -1569, -1818, -1991, -517, -3510, -3443, -5257, -10087, -515, -1612, -2490, -5208, -3049, -3799, -10479, -2208, -3277, -9905, -4415, -2200, -5670, -4340, -6402, -247, -6744, -5459, -3449, -8608, -2493, -8953, -2329, -10470, -3489, -5014, -942, -3033, -5517, -7124, -9458, -912, -4719, -8003, -7849, -8968, -6323, -4333, -2231, -10255, -5734, -7819, -761, -3018, -7711, -6540, -10359, -967, -8518, -6944, -4272, -10419, -970, -7970, -649, -2804, +480, +630, +337, +413, +953, +182, +44, +156, +883, +346, +721, +896, +225, +206, +374, +506, +182, +233, +676, +394, +841, +35, +337, 27, -2860, -987, -5989, -1244, -4408, -6822, -8328, -6969, -3241, -8932, -5919, -10825, -2147, -2146, -9458, -3547, -8628, -2580, +540, +926, +125, 506, -4800, -7062, -10165, -1459, -7442, -9935, -7895, -1007, -987, -5940, -9392, -10782, -7521, -4584, -5441, -8823, -4099, -10435, -3401, -6446, -5123, -1595, -8734, -6232, -3258, -7920, -2136, -4597, -2214, -6978, -4778, -4613, -6608, -8627, -10160, -9077, -9818, -2613, -10686, -1947, -6014, -10709, -10607, -4619, -9422, -10289, -1786, -8250, -10572, -2179, -869, -5794, -8534, -5379, -4341, -2606, -1211, -2456, +121, +661, +217, +434, +414, +324, +489, +446, +487, +274, +894, +0, +133, +937, +764, +415, +169, +267, +449, +610, +380, +155, +903, +785, +273, +487, +906, +616, +782, +264, +165, +33, +689, +472, +635, +574, +582, +525, +694, +79, +696, +190, +750, +607, +880, +903, +741, +592, +313, +897, +789, +257, +596, +183, +399, +271, +598, +823, +659, +680, +119, +975, +354, +83, +602, +233, +781, +815, +514, +400, +304, +79, +314, +901, +496, +733, +985, +88, +725, +937, +101, +446, +510, +685, +551, +270, +85, +847, +477, +893, +992, +349, +493, +691, +116, +696, +329, +522, +787, +458, +112, +83, +852, +16, +168, +718, +553, +818, +713, +843, +142, +76, +547, +688, +904, +354, +45, +801, +668, +826, +977, +287, +256, +990, +13, +456, +414, +752, +100, +471, +867, +58, +914, +733, +960, +746, +35, 978, -4853, -1795, -4426, -5814, -9734, -2306, -8299, -3861, -5181, -1936, -2921, -8830, -7968, -5555, -8043, -7961, -6242, -5054, -1946, -1789, -4613, -1979, -9578, -8544, -8087, -497, -3405, -10226, -10006, -8807, -6271, -10633, -7887, -7386, -1618, -2939, -10093, -6471, -3672, -3548, -9370, -2636, -10878, -6138, -5662, -8622, -5454, -10653, -3914, -8645, -3253, -10947, -10077, -5737, -10504, -4763, -7483, -1907, -1881, -8326, +350, +23, +10, +931, +345, +768, +140, +734, +218, +939, +154, +902, +1000, +828, +185, +749, +566, +147, +468, +953, +792, +33, +859, +208, +633, +994, +246, +670, +575, +525, +119, +741, +547, +936, +371, +4, +338, +161, +421, +342, +98, +36, +984, +799, +803, +496, +606, +659, +822, +23, +380, +965, +144, +196, +91, +703, +879, +330, +510, +76, +922, +670, +397, +787, +178, +707, +936, +435, +344, +145, +776, +977, +55, +886, +385, +314, +565, +495, +84, +758, +943, +811, +602, +266, +279, +802, +528, +222, +513, +136, +49, +765, +77, +919, +158, +38, +292, 184, -6423, -4437, -10405, -3855, -4041, -6355, -5249, -8908, -8667, -4116, -6949, -5027, -3707, -2247, -6096, -1609, -4998, -10193, -7897, -3707, -9221, -2139, -7381, -7163, -9295, -6008, -10733, -7586, -5280, -3631, -5661, -10702, -407, -2904, -1151, -4765, -9341, -6075, -5673, -4462, -1891, -3764, -61, -6401, -8834, -10567, -10949, -9554, -4874, -2972, -8451, -9201, -5534, -4160, -9449, -10156, -6495, -10572, -15, +242, +778, +70, +92, +110, +155, +470, +406, +396, +895, +806, +84, +982, +780, +114, +906, 921, -2620, -9973, -7346, -9121, -996, -9731, -8740, -8401, +837, +937, +157, +81, +964, +613, +692, +53, +976, +428, +864, +726, +559, +292, +895, +686, +850, +568, +163, +405, +385, +477, +817, 248, -3436, -743, -9858, -6059, -9358, -904, -6668, -5496, -6191, -9685, -3028, -8259, -3658, -8988, -7059, -8558, -1229, -2049, -6791, -10363, -4316, -4480, -6247, -10619, -1566, -10765, -352, -4756, -2883, -6094, -188, -10236, -3880, -2146, -2805, -1985, -8722, -9625, -5453, -10885, -10506, -7475, -500, -1504, -335, -1183, -4235, -5854, -6525, -6214, -8658, -9912, -1739, -10148, -10501, -2923, -6472, -6017, -8190, -9384, -8307, -10923, -7192, -4010, -9232, -2498, -2054, -5250, -8415, -9657, -3295, -145, -8141, -9300, -4152, -4603, -9864, -6482, -2940, -603, -3684, -8916, -7639, -7797, -3768, -2514, -8486, -5682, +607, +731, +290, +545, +456, +843, +858, +637, 253, -103, -3261, -9001, -3449, -7279, -4595, -6083, -203, -2863, -2409, -4656, -2609, -8409, -877, -4853, -8985, -2369, -9288, -5088, -9223, -9015, -7662, -2204, -6674, -990, -9538, -1939, -6833, -6592, -2230, -8085, -1815, -10114, -6981, -4982, -43, -5519, -5233, -405, -5279, -2897, -10711, -10644, -9459, -5979, -10117, -2975, -6702, -9712, -3464, -6026, -1203, -4293, -9680, -4986, -5548, -1903, -9821, -1787, -9402, -4650, -3271, -10581, -2762, -7257, -5968, -2669, -4481, -4697, -5841, -9906, -5870, -1639, -2564, -9288, -6963, -7745, -2788, -3147, -6372, -7254, -9354, -6230, -3583, -7660, -8449, -9028, -9323, -9323, -352, -3536, -10230, -2476, -1339, -2469, -7970, -251, -4384, -6248, -9395, -2483, -611, -1631, -2355, -10541, -2916, -2307, -9399, -7123, -186, -2868, -6178, -4976, -8232, -9270, -7938, -792, -2151, -5129, -7702, -6419, -9239, -4878, -4514, -6608, -10976, -10212, -3670, -3648, -2073, -4476, -9794, -4889, -9853, -954, -6203, -1520, -3108, -8423, -7038, -24, -6786, -3760, -1432, -6951, -10170, -8823, -2328, -4931, -4750, -2807, -7169, -2439, -2398, -467, -9116, -906, -7338, -7350, -4995, -2190, -9427, -9800, -2091, -4318, -5852, -8811, -8598, -7484, -2824, -6929, -3187, -9222, -10408, -11, -582, -6829, -10690, -1871, -5690, -8255, -1389, -8103, -4025, -404, -4172, -7599, +568, +10, +114, +513, +688, +431, +437, +980, +842, +728, +54, +575, +599, +681, 899, -2088, -403, -7825, -2006, -6983, -3995, -8249, -4426, -9717, -8994, -4216, -4995, -3628, -2569, -2611, -4720, -3896, -10296, -9651, -5651, -186, -7244, -273, -5324, -8614, -805, -8602, -2365, -831, -2412, -1741, -829, -7347, -4197, -2968, -5194, -8267, -2714, -1245, -1704, -1290, -2409, -633, -10246, -3811, -3256, -7996, -7186, -3922, -9875, -5807, -8984, -5949, -9122, -1342, -1253, -3516, -6117, -5294, -1539, -24, -3854, -7077, -7922, -7596, -7600, -10368, -10448, -5212, -6656, -5528, -7489, -9073, -1100, -5019, -7325, -382, -9519, -3491, -10783, -5058, -3091, -2912, -5173, -2326, -8838, -8391, -2475, -5056, -3017, -6244, -390, -7942, -5708, -8738, -1276, -5284, -7432, -5666, -10882, -10506, -5902, -7413, -6282, -10111, -7012, -8939, -8421, -3998, -4344, -8319, -8210, -3504, -9606, -7405, -6521, -6416, -4558, -9145, -5157, -5261, -5696, -1390, -9195, -6772, -4410, -3080, -1959, -702, -2365, -3812, -7136, -85, -3787, -1117, -9472, -9654, -7874, -8557, -7441, -4110, -2641, -5284, -8988, -8097, -4289, +664, +902, +589, +524, +181, +282, +579, +569, +407, +637, +790, +65, +11, +370, +221, +498, +611, +67, +262, +588, +122, +16, +87, +191, +876, +724, +81, +715, +38, 772, -9230, -5183, -2857, -2075, -5816, -2750, -5819, -6340, -8620, -3720, -2316, -4666, -7723, -9328, -2144, -6482, -2916, -2326, -3978, -10502, -6481, -9549, -8936, -8988, -137, -2644, -928, -3605, -9292, -6807, -3963, -4318, -7767, -5404, -10245, -6493, -2416, -1305, -3418, -9534, -1321, -10452, -7148, -6403, -5168, -7197, -6178, -1847, -8922, -4099, -8369, -1440, -7243, -9735, -2763, -6544, -10712, -6667, -6680, -5302, -3157, -3830, -80, -10506, -10828, -3364, -9628, -3060, -7295, -6502, -1823, -2647, -3987, -8714, -5754, -6887, -6016, -6205, -2793, -10515, -6822, -10977, -2433, -7005, -3584, -188, -5249, -6393, -2647, -10429, -2382, -10384, -2608, -7758, -9690, -7786, -6908, -6182, -2547, -9532, -10877, -2518, -948, -30, -2696, -9065, -8878, -2113, -138, -497, -3297, -7455, -854, -870, -4672, -7445, -2102, -8940, -1951, -4280, -6241, -8585, -4233, -7950, -6460, -10857, -6740, -2287, -1364, -4446, -8426, -3348, -4988, -9895, -2677, -2606, -8787, -9497, -4451, +344, +128, +995, +77, +742, +481, +253, +621, +248, +893, +256, +513, +324, +91, +250, +842, +981, 96, -7674, -1386, -567, -5985, -7270, -9207, -825, -7390, -4937, -7625, -8803, -8381, -9831, -7961, -9935, -3507, -2041, -9029, -2973, -133, -6078, -6846, -10617, -4484, -1830, -8710, -4019, -7032, -3032, -1738, -10740, -9501, -9449, -1429, -7317, -664, -3981, -6158, -6048, -7072, -9500, -2648, -7706, -10187, -3941, -2286, -10653, -8998, -1233, -8702, -7320, -1499, -8392, -1622, -499, -3121, -6399, -10088, -5705, -7765, -2227, -4082, -5011, -9342, -6450, -10661, -9309, -5120, -5454, -5940, -3575, -8150, -55, -3696, -2656, -4758, -10772, -8299, -4604, -8331, -3823, -5859, -8966, -1341, -1072, -7909, -4881, -8386, -3336, -404, -5364, -606, -1088, -8046, -2712, -8096, -1937, -2318, -7295, -6381, -2025, -7230, -8354, -5917, -9999, -1886, -5907, -8152, -1757, -2054, +647, +66, +555, 670, -10069, -2316, -3199, -9556, -2830, -5499, -6990, -9435, -7814, -7890, -4419, -4335, -481, -7620, -9966, -10498, -3221, -3472, -1819, -8189, -3264, -3364, -2091, -5224, -2504, +889, +400, +109, +929, +933, +986, +780, +185, +890, +423, +249, +737, +781, +604, +353, +54, +844, +507, +774, +536, +617, +439, +339, +170, +884, +491, +51, +726, +272, +67, +720, +717, +291, +921, +501, +192, +738, +132, +617, +664, +621, +224, +855, +629, +417, +692, +137, +610, +960, +536, +484, +872, +783, +70, +993, +401, +639, +446, +637, +691, +261, +477, +792, +167, +885, +249, 638, -3823, -2417, -10976, -9368, -9749, -9415, -10115, -5702, -10319, -7192, -4601, -448, -9098, -6839, -8539, -5966, -1009, -3913, -6537, -8496, -4878, -6895, -8462, -2208, -6362, -7066, -6652, -3827, -10877, -9197, -7500, -2529, -10389, -7599, -2357, -6571, -6613, -3363, -8278, -1587, -1707, -4397, -6828, -3185, -7187, -1063, -8132, -77, -5256, -3074, -1991, -5472, -4758, -368, -7729, -3408, -2702, -8175, -936, -10581, -9242, -5737, -8262, -9763, -7053, -9733, -9879, -3568, -10853, -1027, -2059, -10605, -9117, -4152, -10609, -2905, -129, -8415, -525, -2864, -1786, -5196, -1593, -7395, +125, +363, +189, +800, +128, +809, +459, +251, +608, +165, +347, +23, +616, +251, +653, +266, +391, +981, +105, +329, +375, +462, +149, +923, +787, +230, +787, +243, +145, +575, +625, +949, +428, +965, +503, diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp index 7fd7a17..44175ce 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp @@ -6,14 +6,23 @@ namespace chapter_10 { uint32_t missingInt(const std::string& filename) { - std::cout << "filename=" << filename << std::endl; - /* + // problem 10.7 specifies a max value of 2^32 = 0xFFFFFFFF ~= 4,294,967,296 + // for reasonable test dataset size, we use a smaller range of [0,2000] + // create a bitVector with one bit for each possible number + const int numberRange = 1000; + bool bitVector[numberRange + 1] = {0}; + // problem 10.7 specifies 4 billion numbers, for testing speed, we only read 4000 + // read integers from file std::ifstream file(filename); std::string line = ""; while (std::getline(file, line)){ - std::cout << line << std::endl; + uint32_t number = static_cast(std::stoi(line)); + if (0 <= number && number <= numberRange && !bitVector[number]) bitVector[number] = true; } - */ - return 0; + // search bitVector for first occurrence of unique number + for (uint32_t i = 0; i <= numberRange; i++) { + if (!bitVector[i]) return static_cast(i); + } + return -1; } } diff --git a/tests.cpp b/tests.cpp index 946d33f..824e9ce 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1280,11 +1280,10 @@ TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ REQUIRE(0 == chapter_10::sparseSearch(input4, "alex")); } -/* + TEST_CASE("Chpater 10 - Problem 07 - missingInt()", "test") { REQUIRE(1 == chapter_10::missingInt("../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv")); } -*/ TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; From 27ba1f89791b4f45c3a35a4888826d49c2a9c2e3 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 2 Jul 2019 21:35:13 -0700 Subject: [PATCH 103/176] fix incorrect unit test for 10.7 C++ --- tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.cpp b/tests.cpp index 824e9ce..50e88cc 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1282,7 +1282,7 @@ TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ TEST_CASE("Chpater 10 - Problem 07 - missingInt()", "test") { - REQUIRE(1 == chapter_10::missingInt("../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv")); + REQUIRE(64 == chapter_10::missingInt("../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv")); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From 0ffd05cb3e63eaa56165a88232b24e7054c1d0a4 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 2 Jul 2019 21:47:57 -0700 Subject: [PATCH 104/176] update completion. add note about problem counts --- README.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1dc96a9..46b2432 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,10 @@ the Internet's only solutions repository with this level of testing rigor: >90% reference and contribute solutions with confidence. ### Table of Contents + +N.B. this project contains solutions only to problems solvable with C++ or Python program code. +Conceptual problems solved through discussion are omitted. + #### [C++ Solutions](cpp_solutions): 0. [C++ Unit Tests](tests.cpp) 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. @@ -30,7 +34,7 @@ reference and contribute solutions with confidence. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `6 / 11` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `6 / 10` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -39,7 +43,7 @@ reference and contribute solutions with confidence. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `55` of `141` solutions complete. +C++ Total: `55` of `140` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -52,7 +56,7 @@ C++ Total: `55` of `141` solutions complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 10` complete. 11. Chapter 11 - Testing: N/A 12. Chapter 12 - C and C++: N/A 13. Chapter 13 - Java: N/A @@ -61,7 +65,7 @@ C++ Total: `55` of `141` solutions complete. 16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. 17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. -Python Total: `56` of `131` solutions complete. +Python Total: `56` of `130` solutions complete. ##### Grand Total: `111` unique solutions complete. From a7b6a4355e1778db8996934934610a2e414aeeb1 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 4 Jul 2019 19:58:13 -0700 Subject: [PATCH 105/176] WIP: interface for 10.8 C++ --- CMakeLists.txt | 1 + .../chapter_10_includes.h | 1 + .../problem_10_08_findDuplicates.cpp | 7 +++++++ .../problem_10_08_findDuplicates.h | 21 +++++++++++++++++++ tests.cpp | 13 +++++++++--- 5 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 38a6f03..446b6fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set(SOURCE_FILES cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp + cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index a0c6592..61fac04 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -5,6 +5,7 @@ #include "problem_10_04_searchNoSize.h" #include "problem_10_05_sparseSearch.h" #include "problem_10_07_missingInt.h" +#include "problem_10_08_findDuplicates.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp new file mode 100644 index 0000000..ef77f67 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp @@ -0,0 +1,7 @@ +#include "problem_10_08_findDuplicates.h" + +namespace chapter_10 { + void findDuplicates(std::vector& duplicates, const std::string& filepath) { + + } +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h new file mode 100644 index 0000000..a5ecbc0 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h @@ -0,0 +1,21 @@ +/* + * PROBLEM: + * You have an array with all the numbers from 1 to N, where N is atmost 32,000. + * The array may have duplicate entries and you do not know what N is. With only 4 kilobytes + * of memory available, how would you print all duplicate elements in the array? + * + * TEST CASE: + * {3, 11, 1, 3, 4, 5, 11, 7, 8, ... } -> {3, 11, ...} + * + * ALGORITHM: + * Thoughts and questions: + * + */ + +#pragma once +#include +#include + +namespace chapter_10 { + void findDuplicates(std::vector& duplicates, const std::string& filepath); +} diff --git a/tests.cpp b/tests.cpp index 50e88cc..8d2e75b 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1278,13 +1278,20 @@ TEST_CASE("Chapter 10 - Problem 05 - sparseSearch()", "test"){ REQUIRE(-1 == chapter_10::sparseSearch(input3, "")); REQUIRE(-1 == chapter_10::sparseSearch(input3, "alex")); REQUIRE(0 == chapter_10::sparseSearch(input4, "alex")); - } - +} -TEST_CASE("Chpater 10 - Problem 07 - missingInt()", "test") { +TEST_CASE("Chapter 10 - Problem 07 - missingInt()", "test") { REQUIRE(64 == chapter_10::missingInt("../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv")); } +TEST_CASE("Chapter 10 - Problem 08 - findDuplicates()", "test") { + const std::string filepath = "../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv"; + const std::vector expectedDuplicates = {411}; + std::vector actualDuplicates = {}; + chapter_10::findDuplicates(actualDuplicates, filepath); + REQUIRE(expectedDuplicates == actualDuplicates); +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From ee797b41c5d717621c4a5fc680529023bf1586e2 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 5 Jul 2019 00:55:04 -0700 Subject: [PATCH 106/176] first pass implementation of 10.8 --- .../problem_10_07_missingInt.cpp | 2 +- .../problem_10_08_findDuplicates.cpp | 75 +++++++++++++++++++ .../problem_10_08_findDuplicates.h | 31 +++++++- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp index 44175ce..8a20a9a 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp @@ -10,7 +10,7 @@ namespace chapter_10 { // for reasonable test dataset size, we use a smaller range of [0,2000] // create a bitVector with one bit for each possible number const int numberRange = 1000; - bool bitVector[numberRange + 1] = {0}; + bool bitVector[numberRange + 1] = {false}; // problem 10.7 specifies 4 billion numbers, for testing speed, we only read 4000 // read integers from file std::ifstream file(filename); diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp index ef77f67..c76af2b 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp @@ -1,7 +1,82 @@ #include "problem_10_08_findDuplicates.h" +#include +#include +#include namespace chapter_10 { + // Returns pair associated with number + std::pair getPairValues(int number, const bool* array) { + std::pair pair; + pair.first = array[(number - 1)]; + pair.second = array[(number - 1) + 16000]; + return pair; + } + + // Sets pair associated with number + void setPairValues(int number, bool* array, const std::pair& pair) { + array[(number - 1)] = pair.first; + array[(number - 1) + 16000] = pair.second; + } + void findDuplicates(std::vector& duplicates, const std::string& filepath) { + bool bitVector[32000] = {false}; + + // first pass of duplicate detection for values 1 to 16000 + std::ifstream file(filepath); + std::string line = ""; + while (std::getline(file, line)){ + int number = std::stoi(line); + if (number < 1 || number > 16000) continue; + std::pair pair = getPairValues(number, &bitVector[0]); + if (!pair.first) { + pair.first = true; + } + else { + if (!pair.second) { + pair.second = true; + } + } + setPairValues(number, &bitVector[0], pair); + } + file.close(); + + // iterate over bit vector and add duplicates + for (int number = 1; number <= 16000; number ++) { + std::pair pair = getPairValues(number, bitVector); + if (pair.second) { + duplicates.push_back(number); + } + } + + // reset bitVector + memset(&bitVector[0], false, 32000 * sizeof(bool)); + + // second pass of duplicate detection for values 16001 to 32000 + file.open(filepath); + while (std::getline(file, line)){ + int number = std::stoi(line); + number -= 16000; // convert numbers from range 16001-32000 to range 1-16000 + if (number < 1 || number > 16000) continue; + std::pair pair = getPairValues(number, &bitVector[0]); + if (!pair.first) { + pair.first = true; + } + else { + if (!pair.second) { + pair.second = true; + } + } + setPairValues(number, &bitVector[0], pair); + } + file.close(); + // iterate over bit vector and add duplicates + for (int number = 1; number <= 16000; number ++) { + int convertedNumber = number + 16000; + std::pair pair = getPairValues(number, bitVector); + if (pair.second) { + duplicates.push_back(convertedNumber); + } + } } } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h index a5ecbc0..35c24b5 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.h @@ -1,6 +1,6 @@ /* * PROBLEM: - * You have an array with all the numbers from 1 to N, where N is atmost 32,000. + * You have an array with all the numbers from 1 to N, where N is at most 32,000. * The array may have duplicate entries and you do not know what N is. With only 4 kilobytes * of memory available, how would you print all duplicate elements in the array? * @@ -8,8 +8,35 @@ * {3, 11, 1, 3, 4, 5, 11, 7, 8, ... } -> {3, 11, ...} * * ALGORITHM: - * Thoughts and questions: + * Thoughts and questions: + * 1. The 4 KB number seems significant: 4 KB = 4000 Bytes = 4000 * 8 bits = 32,000 bits + * 2. Thus, we have 1 bit for each and every possible number in the array. + * 3. The problem is that 1 bit per number is not enough to determine duplicate-ness. There is no + * way to distinguish between presence and duplicate-ness with 1 bit of data per possible number. + * 4. Thus, we need to make 2 passes using 2 bits per possible number: 1 to indicate presence, and 1 to + * indicate duplicate-ness. + * 5. NOTE: In the textbook solution, the author suggests using only 1 bit per number and printing the + * number if it's corresponding bitVector value is 1. The problem with this is that it pollutes the output + * with "duplicate duplicates"! There is no way to know if an identified duplicate has already been printed. + * This is why I implement my strategy that outputs *unique* duplicates. * + * This leads to the following algorithm: + * + * 1. Initialize an array of bits pairs (bitPaiVector) that is 16000 elements long and initially contains all [0, 0]s + * and representing numbers 1 to 16000. + * 2. Read each number from a file line by line. + * a. Look at the bitPairVector pair at the index equal to the number read from file. + * b. If the first value is 0, make it a 1. + * c. If the first value is 1, make the second value 1. + * d. If the value of the number is not a possible array index, do nothing. + * 3. Iterate through the bitPairVector and print every index that points to pair whose second value is a 1. + * 4. Repeat steps 1., 2., and 3., with another 16000 element long array where the numbers represented are + * 16001 to 32000. + * 5. For testability, we do not print the duplicate numbers and instead add them to an std::vector whose address + * was passed to the function. + * + * TIME COMPLEXITY: O(N) + * SPACE COMPLEXITY: O(1) */ #pragma once From 645988f1071b7b2d1a9762cb26fa68fe51dcce49 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 5 Jul 2019 01:08:12 -0700 Subject: [PATCH 107/176] implement 10.8 C++ --- README.md | 6 +- .../generate_random_number_file.cpp | 16 +- .../random_number_dataset_32000.csv | 1000 +++++++++++++++++ tests.cpp | 7 +- 4 files changed, 1018 insertions(+), 11 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset_32000.csv diff --git a/README.md b/README.md index 46b2432..3c4c525 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Conceptual problems solved through discussion are omitted. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `6 / 10` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `7 / 10` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -43,7 +43,7 @@ Conceptual problems solved through discussion are omitted. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `55` of `140` solutions complete. +C++ Total: `56` of `140` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -67,7 +67,7 @@ C++ Total: `55` of `140` solutions complete. Python Total: `56` of `130` solutions complete. -##### Grand Total: `111` unique solutions complete. +##### Grand Total: `112` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp index 0321a14..5c3773c 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/generate_random_number_file.cpp @@ -3,24 +3,28 @@ #include #include -int main() { - std::string filename = "random_number_dataset.csv"; +int main(int argc, const char* argv[]) { + if (argc != 4) { + std::cout << "Usage: \ngenerate_random_number_file filename.csv max_value count" << std::endl; + return 1; + } + std::string filename = argv[1]; std::cout << "Random number file generator outputting to " << filename << std::endl; // problem 10.7 specifies a max value of 2^32 = 0xFFFFFFFF ~= 4,294,967,296 // for reasonable test dataset size, we use a smaller range of [0,4300] - const int numberRange = 1000; + const int max_value = std::stoi(argv[2]); // problem 10.7 specifies 4 billion numbers, for testing speed, we only write 4000 - const int numberCount = 4000; + const int count = std::stoi(argv[3]); // initialize random integer generator std::random_device rd; std::mt19937 gen(rd()); - std::uniform_int_distribution dis(0, numberRange); + std::uniform_int_distribution dis(1, max_value); // initialize file stream std::ofstream file; file.open(filename); // write to file line by line - for (int i = 0; i < numberCount; i++) { + for (int i = 0; i < count; i++) { file << dis(gen); file << ",\n"; } diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset_32000.csv b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset_32000.csv new file mode 100644 index 0000000..a9c5388 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset_32000.csv @@ -0,0 +1,1000 @@ +4568, +6739, +10538, +7195, +29648, +10913, +3616, +31621, +26714, +13504, +6771, +19004, +13803, +24455, +15545, +25996, +30239, +5712, +24990, +7100, +17114, +26880, +8061, +30345, +22320, +24756, +28584, +5367, +19315, +26381, +13900, +9479, +4316, +14805, +4710, +13651, +1847, +24942, +21452, +11261, +9005, +25953, +25494, +26651, +27365, +3290, +23088, +8676, +25213, +21126, +13407, +25682, +12537, +2682, +30706, +477, +3391, +17452, +18570, +2069, +6050, +11589, +25844, +17836, +18281, +9631, +18469, +22197, +5881, +21820, +10471, +1539, +9437, +16618, +22272, +29492, +12880, +3993, +13092, +29481, +31426, +23393, +31388, +13245, +13153, +11333, +2987, +5824, +23860, +15726, +6690, +16449, +18820, +2777, +2398, +1148, +24042, +15197, +4451, +28054, +3222, +27369, +9742, +8573, +2012, +17676, +8925, +959, +24118, +5418, +26426, +24395, +2207, +24681, +28720, +12773, +10615, +28159, +29788, +9779, +3547, +28498, +24079, +7164, +12081, +8969, +30791, +11899, +1901, +21803, +13937, +24316, +2130, +20885, +5582, +27343, +1497, +28839, +29710, +21238, +25721, +5993, +31443, +4428, +26617, +3205, +30775, +23680, +4981, +19511, +123, +680, +16676, +22081, +12097, +16253, +21487, +31393, +11854, +23736, +14214, +12040, +14603, +31702, +1263, +4564, +9021, +12689, +28727, +22768, +1355, +8220, +21816, +22730, +11147, +4572, +29895, +31461, +15432, +30704, +27881, +13195, +21357, +4677, +3060, +4758, +13302, +10240, +26888, +17932, +15633, +18490, +30098, +917, +8529, +21654, +11118, +10999, +29129, +27164, +3571, +981, +8528, +23028, +4965, +26090, +23397, +31769, +31063, +27895, +29148, +28035, +26948, +11541, +2313, +28399, +17420, +24743, +9131, +29509, +13298, +22800, +23323, +29974, +15528, +27234, +27759, +588, +11996, +12341, +10139, +21135, +16746, +11023, +6963, +30357, +30265, +1175, +10132, +18201, +23671, +9286, +11949, +18254, +1582, +30538, +2144, +23826, +20776, +17415, +26235, +4286, +4893, +27700, +20424, +26269, +12493, +24640, +22089, +11262, +17222, +26232, +24149, +25201, +15341, +29118, +22488, +23436, +2226, +448, +2932, +5570, +15167, +26831, +21280, +22662, +9349, +16497, +21046, +23098, +4578, +2519, +6937, +21626, +17693, +7234, +26404, +15819, +25133, +19585, +1873, +14172, +20116, +15115, +12303, +8971, +17831, +20105, +30134, +25744, +23529, +11398, +9215, +27504, +31611, +22787, +19344, +28904, +8767, +16574, +17841, +19283, +29196, +6260, +8767, +24265, +9940, +19619, +27591, +5283, +26916, +18697, +6581, +26811, +278, +8647, +14010, +7210, +12912, +8875, +985, +13686, +27366, +13004, +4469, +2286, +3399, +13724, +30190, +27967, +27966, +2623, +26622, +10753, +2480, +13671, +5497, +17479, +22811, +30323, +9867, +14912, +16437, +10552, +22226, +158, +19868, +26417, +12279, +3556, +13862, +17176, +28499, +15294, +18036, +13945, +5105, +25334, +884, +10211, +16595, +29372, +27438, +12012, +7, +4678, +2788, +23047, +11324, +1733, +5839, +22772, +311, +24767, +24005, +24726, +6724, +11698, +27091, +3787, +20283, +23618, +17559, +2488, +27662, +24853, +6463, +25202, +3529, +3212, +26304, +13643, +11603, +11814, +8093, +23191, +13118, +6273, +15196, +1827, +15362, +5399, +3345, +792, +23392, +19717, +2386, +25369, +6026, +13727, +7825, +5645, +8581, +9959, +13803, +3158, +20984, +22881, +22076, +31606, +18255, +10580, +6905, +8684, +15992, +29408, +20922, +23979, +22336, +27018, +27889, +10464, +18005, +3845, +23089, +9388, +13180, +10945, +18281, +14020, +22873, +3078, +17996, +4436, +24871, +26870, +4597, +29126, +31486, +28974, +10313, +5782, +10044, +29918, +21083, +13472, +27556, +27644, +19120, +23793, +31971, +485, +20067, +25462, +2861, +24790, +18307, +1848, +26315, +21743, +27878, +3268, +2134, +10018, +13512, +19713, +28427, +27772, +11811, +31694, +10501, +14039, +12862, +19160, +23012, +17801, +25108, +20513, +10007, +20176, +12456, +17553, +29179, +18393, +4340, +1922, +17839, +10681, +180, +6603, +13438, +2716, +22095, +4638, +4492, +1827, +8623, +13500, +21520, +17017, +31723, +17496, +3246, +24811, +2755, +21720, +1906, +16136, +31174, +20877, +20265, +13854, +21266, +25995, +11032, +19520, +23610, +1659, +640, +27454, +11218, +16646, +14888, +7120, +11049, +7064, +14452, +24697, +19237, +31221, +18827, +14147, +7943, +28036, +18014, +26010, +25448, +5040, +3769, +8591, +9054, +27670, +8445, +22036, +12740, +5797, +683, +23162, +8940, +19067, +13308, +5824, +26001, +30074, +16291, +12720, +776, +10712, +11119, +7122, +14259, +19945, +23474, +28538, +18550, +28552, +20876, +30527, +29143, +12356, +25642, +14211, +1770, +11282, +16424, +25901, +8921, +4387, +25538, +29377, +10902, +1413, +13336, +12565, +12457, +24601, +12423, +1887, +14089, +8537, +31975, +8908, +17497, +17528, +2674, +3041, +21319, +17810, +18192, +7457, +20659, +10521, +19540, +16283, +20244, +28369, +8423, +6987, +6294, +4880, +20113, +17643, +25799, +23068, +24060, +28417, +6068, +4341, +11756, +24266, +29153, +31258, +18282, +7766, +552, +12715, +30802, +21548, +13781, +13427, +19128, +15656, +4803, +10171, +7914, +4357, +11741, +15497, +768, +29415, +1455, +12462, +19178, +21264, +23962, +10024, +23835, +9929, +19891, +10995, +8170, +30942, +8198, +30163, +5645, +27827, +25866, +23131, +24801, +6487, +24314, +30758, +28333, +13779, +21917, +27235, +30946, +2467, +563, +13993, +26886, +25521, +15349, +17617, +26308, +16077, +7528, +13294, +8074, +7748, +17819, +19965, +18911, +22460, +21717, +6221, +12417, +17744, +7496, +8702, +7287, +8969, +10241, +26565, +7448, +17785, +15440, +19579, +25336, +3688, +10720, +5236, +24651, +17887, +30945, +14871, +27163, +1101, +18614, +18745, +27020, +10574, +19020, +9350, +12565, +22637, +16629, +516, +19749, +21376, +3085, +30336, +14127, +16127, +15412, +22814, +28790, +24384, +26371, +12255, +3769, +5005, +25489, +11980, +5389, +16683, +21948, +1662, +27361, +20382, +31924, +4780, +15107, +850, +25955, +21020, +17218, +31409, +1237, +15542, +3037, +9701, +1246, +16003, +8813, +20776, +14428, +6308, +15678, +23637, +22210, +26214, +6390, +7525, +31588, +18468, +6655, +30323, +5917, +28672, +28240, +12586, +11991, +19911, +1566, +12568, +7443, +140, +17879, +26791, +3366, +21022, +31705, +25055, +16009, +22860, +20776, +8031, +16587, +16844, +17496, +5496, +24145, +1196, +11477, +13822, +31204, +4604, +18761, +6492, +22683, +18175, +27806, +5472, +8, +13643, +11714, +4987, +28328, +31373, +12440, +26371, +18599, +24178, +14493, +1945, +160, +13321, +23071, +14141, +2387, +19958, +29318, +1364, +17013, +1245, +26576, +4653, +7881, +21807, +16246, +14189, +14158, +19644, +25002, +1900, +16981, +2168, +10576, +9539, +28910, +10099, +22282, +12145, +21200, +27843, +9607, +19913, +9003, +7607, +1800, +17728, +7850, +11363, +29785, +12741, +11224, +23323, +5359, +9716, +19853, +27420, +5649, +21753, +15991, +15754, +13581, +23402, +9330, +9283, +1778, +10294, +821, +6386, +6890, +8095, +31876, +29900, +30024, +30783, +16622, +19843, +10577, +14977, +13596, +31184, +28701, +21594, +24355, +13129, +18479, +13137, +24224, +14865, +5320, +11353, +6811, +7072, +13115, +6106, +25799, +11665, +5895, +2222, +13854, +23244, +12086, +5018, +18996, +18432, +4345, +19631, +20170, +20024, +2165, +29019, +490, +2958, +21736, +3772, +26080, +7997, +18883, +5909, +12846, +14874, +21335, +31514, +9877, +27916, +19515, +15836, +6236, +12101, +9709, +30296, +18867, +25150, +21436, +13906, +14728, +20954, +4538, +30389, +21058, +22294, +12862, +8052, +16971, +24180, +16337, +23058, +10730, +30645, +73, +1513, +9652, +7787, +19080, +5676, +12472, +19715, +9249, +8588, +22090, +20221, +16049, +24131, +18495, +27832, +16006, +2635, +26182, +30752, +25861, +28100, +21930, +19776, +27343, +26376, diff --git a/tests.cpp b/tests.cpp index 8d2e75b..480eda2 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1285,8 +1285,11 @@ TEST_CASE("Chapter 10 - Problem 07 - missingInt()", "test") { } TEST_CASE("Chapter 10 - Problem 08 - findDuplicates()", "test") { - const std::string filepath = "../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset.csv"; - const std::vector expectedDuplicates = {411}; + const std::string filepath = "../cpp_solutions/chapter_10_sorting_and_searching/chapter_10_dataset_generation/random_number_dataset_32000.csv"; + const std::vector expectedDuplicates = { 1827, 3769, 5645, 5824, 8767, + 8969, 12565, 12862, 13643, 13803, + 13854, 17496, 18281, 20776, 23323, + 25799, 26371, 27343, 30323 }; std::vector actualDuplicates = {}; chapter_10::findDuplicates(actualDuplicates, filepath); REQUIRE(expectedDuplicates == actualDuplicates); From 705174cd481abe8f4314849fc52c2dc1f7224e63 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 5 Jul 2019 01:12:00 -0700 Subject: [PATCH 108/176] include path for memset --- .../problem_10_08_findDuplicates.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp index c76af2b..35efc88 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp @@ -1,4 +1,5 @@ #include "problem_10_08_findDuplicates.h" +#include #include #include #include From 2ec126e71c682e94451f3e1d88cd2efc5d988a36 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 14 Jul 2019 18:13:45 -0700 Subject: [PATCH 109/176] WIP unit tests for 10.9 C++ --- .../chapter_10_includes.h | 1 + .../problem_10_09_matrixSearch.h | 10 ++++++++++ tests.cpp | 17 +++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index 61fac04..93530ea 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -6,6 +6,7 @@ #include "problem_10_05_sparseSearch.h" #include "problem_10_07_missingInt.h" #include "problem_10_08_findDuplicates.h" +#include "problem_10_09_matrixSearch.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h new file mode 100644 index 0000000..0e3de71 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -0,0 +1,10 @@ +#pragma once +#include + +namespace chapter_10 { + template typename + std::pair matrixSearch(const Eigen::Matrix& matrix) { + std::pair coordinates(0,0); + return coordinates; + } +} diff --git a/tests.cpp b/tests.cpp index 480eda2..7da7b2f 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1295,6 +1295,23 @@ TEST_CASE("Chapter 10 - Problem 08 - findDuplicates()", "test") { REQUIRE(expectedDuplicates == actualDuplicates); } +TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { + Eigen::Matrix example1; + example1 << 0, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 2, 2, + 1, 1, 1, 2, 2, 5, + 1, 2, 2, 3, 5, 5, + 1, 5, 5, 5, 5, 5, + 1, 5, 5, 5, 5, 5; + Eigen::Matrix example2; + example2 << 0, 1, 2, 3, 4, 5, 6, + 1, 11, 21, 31, 41, 51, 61, + 2, 22, 32, 42, 52, 62, 72, + 3, 33, 43, 53, 63, 73, 83, + 4, 44, 54, 64, 74, 84, 94, + 5, 55, 65, 75, 85, 95, 105; +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From 0af1078c110cf9919417bf10047bfa52632cfd49 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 14 Jul 2019 23:34:29 -0700 Subject: [PATCH 110/176] WIP 10.9 C++ function interface and basic unit tests --- .../problem_10_09_matrixSearch.h | 4 ++-- tests.cpp | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h index 0e3de71..a9a304e 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -2,8 +2,8 @@ #include namespace chapter_10 { - template typename - std::pair matrixSearch(const Eigen::Matrix& matrix) { + template + std::pair matrixSearch(const Eigen::Matrix& matrix, const Type& query) { std::pair coordinates(0,0); return coordinates; } diff --git a/tests.cpp b/tests.cpp index 7da7b2f..88ac6ca 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1303,13 +1303,17 @@ TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { 1, 2, 2, 3, 5, 5, 1, 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, 5; - Eigen::Matrix example2; + Eigen::Matrix example2; example2 << 0, 1, 2, 3, 4, 5, 6, 1, 11, 21, 31, 41, 51, 61, 2, 22, 32, 42, 52, 62, 72, 3, 33, 43, 53, 63, 73, 83, 4, 44, 54, 64, 74, 84, 94, 5, 55, 65, 75, 85, 95, 105; + std::pair expectedCoordinate1(1, 4); + std::pair expectedCoordinate2(2, 4); + REQUIRE(expectedCoordinate1 == chapter_10::matrixSearch(example1, 2)); + REQUIRE(expectedCoordinate2 == chapter_10::matrixSearch(example2, 52)); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From 8a29058bab2838a4831c0f9d5e69edefc1c10a29 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 16 Jul 2019 19:25:47 -0700 Subject: [PATCH 111/176] add essay for 10.8 C++ --- .../problem_10_09_matrixSearch.h | 61 +++++++++++++++++++ tests.cpp | 10 +-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h index a9a304e..8ff8e52 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -1,3 +1,64 @@ +/* PROBLEM: + * Given an M x N matrix in which each row and each column is sorted in ascending order, + * write a method to find an element. + * + * TEST CASE: + * matrix = + * { 0, 1, 2, 3, 4, 5, 6, + * 1, 11, 21, 31, 41, 51, 61, + * 2, 22, 32, 42, 52, 62, 72, + * 3, 33, 43, 53, 63, 73, 83, + * 4, 44, 54, 64, 74, 84, 94, + * 5, 55, 65, 75, 85, 95, 105; } + * + * matrixSearch(matrix, 52) -> [2, 4] + * + * THOUGHTS: + * 1. The brute force approach is linear search which takes O(N*M) time. + * 2. One might think to concatenate the matrix rows into a single row and apply binary search in O(M*N) time, + * but this is not an option. Concatenating the rows into an array does not yield a sorted array and + * likewise for the columns. + * 3. One might think to apply binary search to the outer rows and columns in a way that narrows + * down the possible location of the query to a rectangular area. This is close to the right idea, but unfortunately, + * testing equality/inequality with outer rows and columns does not guarantee that the interior of the matrix will + * conform to the inequality rules of the outer rows and columns. For example, in the bottom row, the query 52 is + * valued between bottom row values at horizontal indices 0 and 1, but it's true horizontal index in the matrix is 4. + * 4. We can improve on the idea from #3 and apply binary search but use matrix diagonal values for equality comparison + * with the search query. For example, when searching for 52 in the example, we can apply binary search to the matrix + * diagonal values [0, 21, 42, 63, 84, 105] to determine that 52 is > 42 but 52 < 63. This means that 52 is *not* in + * the rectangular area + * 63, 73, 83, + * 74, 84, 94, + * 85, 95, 105; + * + * and also that 52 is *not* in the rectangular area + * 0, 1, 2, 3, + * 1, 11, 21, 31, + * 2, 22, 32, 42, + * + * Thus 52 may either be in the rectangular area + * 3, 33, 43, 53, + * 4, 44, 54, 64, + * 5, 55, 65, 75, + * + * or 52 may be in the rectangular area + * 4, 5, 6, + * 41, 51, 61, + * 52, 62, 72, + * + * Thus to continue the search after determining that 52 is between 42 and 63, we recurse the search algorithm on + * the two rectangular areas that may still contain 52. We continue recursing as the rectangular areas get smaller + * and smaller until the rectangular areas become the size of a single value. At this point we hit the terminating condition, + * check for equality against the query, and return the coordinate indices of the single value if it is equal to the query. + * If we continue recursing in this manner, we divide the potential search space in 2 with every level of the recursion. + * This algorithm can be performed in place on the input matrix, but there will be one stack frame for each level of the recursion. + * Thus, the algorithm requires O(log(M*N)) time and O(log(M*N)) space. + * + * This procedure requires that we implement a method for determining matrix diagonal values even for non-square matrices + * as well as check + * + */ + #pragma once #include diff --git a/tests.cpp b/tests.cpp index 88ac6ca..31e31af 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1298,11 +1298,11 @@ TEST_CASE("Chapter 10 - Problem 08 - findDuplicates()", "test") { TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { Eigen::Matrix example1; example1 << 0, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 2, 2, - 1, 1, 1, 2, 2, 5, - 1, 2, 2, 3, 5, 5, - 1, 5, 5, 5, 5, 5, - 1, 5, 5, 5, 5, 5; + 1, 1, 1, 1, 2, 2, + 1, 1, 1, 2, 2, 5, + 1, 2, 2, 3, 5, 5, + 1, 5, 5, 5, 5, 5, + 1, 5, 5, 5, 5, 5; Eigen::Matrix example2; example2 << 0, 1, 2, 3, 4, 5, 6, 1, 11, 21, 31, 41, 51, 61, From 616b38775d36a4f9651e521a79479774f0978eb7 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 16 Jul 2019 21:15:14 -0700 Subject: [PATCH 112/176] switch from std::pair to Point2 --- .../problem_10_09_matrixSearch.h | 22 ++++++++++++++++--- tests.cpp | 6 ++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h index 8ff8e52..2a5b700 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -15,14 +15,17 @@ * * THOUGHTS: * 1. The brute force approach is linear search which takes O(N*M) time. + * * 2. One might think to concatenate the matrix rows into a single row and apply binary search in O(M*N) time, * but this is not an option. Concatenating the rows into an array does not yield a sorted array and * likewise for the columns. + * * 3. One might think to apply binary search to the outer rows and columns in a way that narrows * down the possible location of the query to a rectangular area. This is close to the right idea, but unfortunately, * testing equality/inequality with outer rows and columns does not guarantee that the interior of the matrix will * conform to the inequality rules of the outer rows and columns. For example, in the bottom row, the query 52 is * valued between bottom row values at horizontal indices 0 and 1, but it's true horizontal index in the matrix is 4. + * * 4. We can improve on the idea from #3 and apply binary search but use matrix diagonal values for equality comparison * with the search query. For example, when searching for 52 in the example, we can apply binary search to the matrix * diagonal values [0, 21, 42, 63, 84, 105] to determine that 52 is > 42 but 52 < 63. This means that 52 is *not* in @@ -63,9 +66,22 @@ #include namespace chapter_10 { + struct Point2 { + int _row; + int _col; + Point2(int row, int col) : _row(row), _col(col) {} + bool operator== (const Point2& other) { + return (_row == other._row && _col == other._col); + } + }; + + template + Point2 submatrixSearchHelper(const Eigen::Matrix& matrix, const Type& query, const Point2& start, const Point2& end){ + return Point2(0,0); + } + template - std::pair matrixSearch(const Eigen::Matrix& matrix, const Type& query) { - std::pair coordinates(0,0); - return coordinates; + Point2 matrixSearch(const Eigen::Matrix& matrix, const Type& query) { + return submatrixSearchHelper(matrix, query, Point2(0,0), Point2(Rows - 1, Cols - 1)); } } diff --git a/tests.cpp b/tests.cpp index 31e31af..16705f7 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1310,10 +1310,10 @@ TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { 3, 33, 43, 53, 63, 73, 83, 4, 44, 54, 64, 74, 84, 94, 5, 55, 65, 75, 85, 95, 105; - std::pair expectedCoordinate1(1, 4); - std::pair expectedCoordinate2(2, 4); + chapter_10::Point2 expectedCoordinate1(1, 4); + chapter_10::Point2 expectedCoordinate2(2, 4); REQUIRE(expectedCoordinate1 == chapter_10::matrixSearch(example1, 2)); - REQUIRE(expectedCoordinate2 == chapter_10::matrixSearch(example2, 52)); + //REQUIRE(expectedCoordinate2 == chapter_10::matrixSearch(example2, 52)); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From 2095eae2838906995dcb7850a996b6c29923921d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 16 Jul 2019 22:01:31 -0700 Subject: [PATCH 113/176] WIP implement diagonal binary search --- .../problem_10_09_matrixSearch.h | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h index 2a5b700..9b4785a 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -73,10 +73,17 @@ namespace chapter_10 { bool operator== (const Point2& other) { return (_row == other._row && _col == other._col); } + bool operator> (const Point2& other) { + return (_row > other._row || _col > other._col); + } }; template Point2 submatrixSearchHelper(const Eigen::Matrix& matrix, const Type& query, const Point2& start, const Point2& end){ + // if starting point has higher values row and col values than ending point, + if (start > end) return Point2(-1, -1); + // if bottom right value is less than the query, then there is no way that the query can be contained in this submatrix + // apply binary search to diagonal values return Point2(0,0); } @@ -85,3 +92,28 @@ namespace chapter_10 { return submatrixSearchHelper(matrix, query, Point2(0,0), Point2(Rows - 1, Cols - 1)); } } + + + + + + + + + + + + + + + + + + + + + + + + + From 4cfaa519669a25ca6bc915e7205eaecf8dee1e1c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 17 Jul 2019 10:09:25 -0700 Subject: [PATCH 114/176] WIP 10.9. solution concept implemented, need to debug. --- .../problem_10_09_matrixSearch.h | 75 +++++++++++++++++-- tests.cpp | 2 +- 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h index 9b4785a..879b6f0 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -70,21 +70,82 @@ namespace chapter_10 { int _row; int _col; Point2(int row, int col) : _row(row), _col(col) {} - bool operator== (const Point2& other) { + bool operator!= (const Point2& other) const { + return !(*this == other); + } + bool operator== (const Point2& other) const { return (_row == other._row && _col == other._col); } - bool operator> (const Point2& other) { + bool operator> (const Point2& other) const { return (_row > other._row || _col > other._col); } + bool operator>= (const Point2& other) const { + return (_row >= other._row || _col >= other._col); + } + bool operator< (const Point2& other) const { + return (_row < other._row || _col < other._col); + } + bool operator<= (const Point2& other) const { + return (_row <= other._row || _col <= other._col); + } + Point2 operator- (const Point2& other) const { + return Point2(_row - other._row, _col - other._col); + } + Point2 operator+ (const Point2& other) const { + return Point2(_row + other._row, _col + other._col); + } + Point2 operator/ (const Point2& other) const { + return Point2(_row * other._row, _col * other._col); + } + Point2 operator* (const Point2& other) const { + return Point2(_row / other._row, _col / other._col); + } + template + Point2 operator- (const T& scalar) const { + return Point2(_row - scalar, _col - scalar); + } + template + Point2 operator+ (const T& scalar) const { + return Point2(_row + scalar, _col + scalar); + } + template + Point2 operator/ (const T& scalar) const { + return Point2(_row / scalar, _col / scalar); + } + template + Point2 operator* (const T& scalar) const { + return Point2(_row * scalar, _col * scalar); + } }; template Point2 submatrixSearchHelper(const Eigen::Matrix& matrix, const Type& query, const Point2& start, const Point2& end){ - // if starting point has higher values row and col values than ending point, - if (start > end) return Point2(-1, -1); - // if bottom right value is less than the query, then there is no way that the query can be contained in this submatrix - // apply binary search to diagonal values - return Point2(0,0); + // check for out of bounds termination conditions + if (start > end || start >= Point2(Rows, Cols) || start < Point2(0, 0) || end >= Point2(Rows, Cols) || end < Point2(0, 0)) return Point2(-1, -1); + // check for endpoint query equality + if (matrix(start._row, start._col) == query) return start; + if (matrix(end._row, end._col) == query) return end; + // if start > query || end < query, then there is no way that the query can be contained in this submatrix + if (matrix(end._row, start._col) < query || matrix(start._row, start._col) > query) return Point2(-1, -1); + // compute midpoint and determine submatrices for further search + Point2 midpoint = (end - start) / 2 + start; + // try "upper left" submatrix + if (matrix(midpoint._row, midpoint._col) >= query) { + return submatrixSearchHelper(matrix, query, start, midpoint); + } + // try "lower left" submatrix + Point2 returnValue = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, start._col), Point2(end._row, midpoint._col)); + if (returnValue != Point2(-1, -1)) { + return returnValue; + } + // try "upper right" submatrix + returnValue = submatrixSearchHelper(matrix, query, Point2(start._row, midpoint._col + 1), Point2(midpoint._row, end._col)); + if (returnValue != Point2(-1, -1)) { + return returnValue; + } + // try "lower right" submatrix + returnValue = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, midpoint._col + 1), Point2(end._row, end._col)); + return returnValue; } template diff --git a/tests.cpp b/tests.cpp index 16705f7..2ceee7c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1313,7 +1313,7 @@ TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { chapter_10::Point2 expectedCoordinate1(1, 4); chapter_10::Point2 expectedCoordinate2(2, 4); REQUIRE(expectedCoordinate1 == chapter_10::matrixSearch(example1, 2)); - //REQUIRE(expectedCoordinate2 == chapter_10::matrixSearch(example2, 52)); + REQUIRE(expectedCoordinate2 == chapter_10::matrixSearch(example2, 52)); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From 36cb6549598e49ed6b45619da5ac90c790ad1d89 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 21 Jul 2019 01:15:26 -0700 Subject: [PATCH 115/176] complete implementation and testing of 10.9 C++ --- .../problem_10_09_matrixSearch.h | 56 ++++++++++++------- tests.cpp | 30 +++++++--- 2 files changed, 58 insertions(+), 28 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h index 879b6f0..1a7b14c 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_09_matrixSearch.h @@ -95,10 +95,10 @@ namespace chapter_10 { return Point2(_row + other._row, _col + other._col); } Point2 operator/ (const Point2& other) const { - return Point2(_row * other._row, _col * other._col); + return Point2(_row / other._row, _col / other._col); } Point2 operator* (const Point2& other) const { - return Point2(_row / other._row, _col / other._col); + return Point2(_row * other._row, _col * other._col); } template Point2 operator- (const T& scalar) const { @@ -116,6 +116,9 @@ namespace chapter_10 { Point2 operator* (const T& scalar) const { return Point2(_row * scalar, _col * scalar); } + void print(const std::string& title) const { + std::cout << title << "[" << _row << "," << _col << "]" << std::endl; + } }; template @@ -126,26 +129,39 @@ namespace chapter_10 { if (matrix(start._row, start._col) == query) return start; if (matrix(end._row, end._col) == query) return end; // if start > query || end < query, then there is no way that the query can be contained in this submatrix - if (matrix(end._row, start._col) < query || matrix(start._row, start._col) > query) return Point2(-1, -1); + if (matrix(end._row, end._col) < query || matrix(start._row, start._col) > query) return Point2(-1, -1); // compute midpoint and determine submatrices for further search Point2 midpoint = (end - start) / 2 + start; - // try "upper left" submatrix - if (matrix(midpoint._row, midpoint._col) >= query) { - return submatrixSearchHelper(matrix, query, start, midpoint); - } - // try "lower left" submatrix - Point2 returnValue = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, start._col), Point2(end._row, midpoint._col)); - if (returnValue != Point2(-1, -1)) { - return returnValue; - } - // try "upper right" submatrix - returnValue = submatrixSearchHelper(matrix, query, Point2(start._row, midpoint._col + 1), Point2(midpoint._row, end._col)); - if (returnValue != Point2(-1, -1)) { - return returnValue; - } - // try "lower right" submatrix - returnValue = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, midpoint._col + 1), Point2(end._row, end._col)); - return returnValue; + // if midpoint == query, return + if (matrix(midpoint._row, midpoint._col) == query) return midpoint; + + // if midpoint > query, then query can be in UL, UR, LL + Point2 returnedLocation(-1, -1); + if (matrix(midpoint._row, midpoint._col) > query) { + // try UL + returnedLocation = submatrixSearchHelper(matrix, query, start, midpoint); + if (returnedLocation != Point2(-1, -1)) return returnedLocation; + // try UR + returnedLocation = submatrixSearchHelper(matrix, query, Point2(start._row, midpoint._col + 1), Point2(midpoint._row, end._col)); + if (returnedLocation != Point2(-1, -1)) return returnedLocation; + // try LL + returnedLocation = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, start._col), Point2(end._row, midpoint._col)); + if (returnedLocation != Point2(-1, -1)) return returnedLocation; + } + + // if midpoint < query, then query can be in LR, LL, UL + if (matrix(midpoint._row, midpoint._col) < query) { + // try LR + returnedLocation = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, midpoint._col + 1), Point2(end._row, end._col)); + if (returnedLocation != Point2(-1, -1)) return returnedLocation; + // try LL + returnedLocation = submatrixSearchHelper(matrix, query, Point2(midpoint._row + 1, start._col), Point2(end._row, midpoint._col)); + if (returnedLocation != Point2(-1, -1)) return returnedLocation; + // try UR + returnedLocation = submatrixSearchHelper(matrix, query, Point2(start._row, midpoint._col + 1), Point2(midpoint._row, end._col)); + if (returnedLocation != Point2(-1, -1)) return returnedLocation; + } + return returnedLocation; } template diff --git a/tests.cpp b/tests.cpp index 2ceee7c..f14acc9 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1298,11 +1298,11 @@ TEST_CASE("Chapter 10 - Problem 08 - findDuplicates()", "test") { TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { Eigen::Matrix example1; example1 << 0, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 2, 2, - 1, 1, 1, 2, 2, 5, - 1, 2, 2, 3, 5, 5, - 1, 5, 5, 5, 5, 5, - 1, 5, 5, 5, 5, 5; + 1, 1, 1, 1, 2, 2, + 1, 1, 1, 2, 2, 5, + 1, 2, 2, 3, 5, 5, + 1, 5, 5, 5, 5, 5, + 1, 5, 5, 5, 5, 5; Eigen::Matrix example2; example2 << 0, 1, 2, 3, 4, 5, 6, 1, 11, 21, 31, 41, 51, 61, @@ -1310,10 +1310,24 @@ TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { 3, 33, 43, 53, 63, 73, 83, 4, 44, 54, 64, 74, 84, 94, 5, 55, 65, 75, 85, 95, 105; - chapter_10::Point2 expectedCoordinate1(1, 4); + chapter_10::Point2 expectedCoordinate1(3, 1); chapter_10::Point2 expectedCoordinate2(2, 4); - REQUIRE(expectedCoordinate1 == chapter_10::matrixSearch(example1, 2)); - REQUIRE(expectedCoordinate2 == chapter_10::matrixSearch(example2, 52)); + chapter_10::Point2 expectedCoordinate3(5, 6); + chapter_10::Point2 expectedCoordinate4(0, 5); + chapter_10::Point2 expectedCoordinate5(5, 4); + chapter_10::Point2 expectedCoordinate6(3, 3); + chapter_10::Point2 actualCoordinate1 = chapter_10::matrixSearch(example1, 2); + chapter_10::Point2 actualCoordinate2 = chapter_10::matrixSearch(example2, 52); + chapter_10::Point2 actualCoordinate3 = chapter_10::matrixSearch(example2, 105); + chapter_10::Point2 actualCoordinate4 = chapter_10::matrixSearch(example2, 5); + chapter_10::Point2 actualCoordinate5 = chapter_10::matrixSearch(example2, 85); + chapter_10::Point2 actualCoordinate6 = chapter_10::matrixSearch(example1, 3); + REQUIRE(expectedCoordinate1 == actualCoordinate1); + REQUIRE(expectedCoordinate2 == actualCoordinate2); + REQUIRE(expectedCoordinate3 == actualCoordinate3); + REQUIRE(expectedCoordinate4 == actualCoordinate4); + REQUIRE(expectedCoordinate5 == actualCoordinate5); + REQUIRE(expectedCoordinate6 == actualCoordinate6); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From a0f4d566e0c40d0f50943929216af8fe49e8ebe8 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 21 Jul 2019 01:16:19 -0700 Subject: [PATCH 116/176] update completion --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3c4c525..3e5263d 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Conceptual problems solved through discussion are omitted. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `7 / 10` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `8 / 10` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -43,7 +43,7 @@ Conceptual problems solved through discussion are omitted. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `56` of `140` solutions complete. +C++ Total: `57` of `140` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -67,7 +67,7 @@ C++ Total: `56` of `140` solutions complete. Python Total: `56` of `130` solutions complete. -##### Grand Total: `112` unique solutions complete. +##### Grand Total: `113` unique solutions complete. ### Building: #### Mac: From b8343bf93f1e4db0a15f4ad45f3f613782006fb2 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 22 Jul 2019 10:22:46 -0700 Subject: [PATCH 117/176] implement 10.10 C++, tests, and completion count --- CMakeLists.txt | 18 ++-- README.md | 6 +- .../chapter_10_includes.h | 1 + .../problem_10_10_rankFromStream.cpp | 52 ++++++++++ .../problem_10_10_rankFromStream.h | 97 +++++++++++++++++++ tests.cpp | 22 +++++ 6 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.cpp create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 446b6fb..b4d17e6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cpp_solutions/third_party/eigen) # set source files set(SOURCE_FILES tests.cpp - # chapter 1 + # CHAPTER 1 cpp_solutions/chapter_01_arrays_and_strings/problem_01_01_isUnique.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_02_arePermutations.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_03_URLify.cpp @@ -19,12 +19,13 @@ set(SOURCE_FILES cpp_solutions/chapter_01_arrays_and_strings/problem_01_07_rotateMatrix.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_08_setZero.cpp cpp_solutions/chapter_01_arrays_and_strings/problem_01_09_stringRotation.cpp - # chapter 2 .cpp files not included because they are template functions implemented in .h files - # chapter 3 .cpp files not included because they are template functions implemented in .h files + # CHAPTER 2 + # .cpp files not included because they are template functions implemented in .h files + # CHAPTER 3 cpp_solutions/chapter_03_stacks_and_queues/problem_03_06_animalShelter.cpp - # chapter 4 .cpp files not included because they are template functions implemented in .h files + # CHAPTER 4 cpp_solutions/chapter_04_trees_and_graphs/problem_04_07_buildOrder.cpp - # chapter 5 + # CHAPTER 5 cpp_solutions/chapter_05_bit_manipulation/problem_05_01_insertion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_02_binaryToString.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_03_flipBitToWin.cpp @@ -32,7 +33,7 @@ set(SOURCE_FILES cpp_solutions/chapter_05_bit_manipulation/problem_05_06_conversion.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_07_pairwiseSwap.cpp cpp_solutions/chapter_05_bit_manipulation/problem_05_08_drawLine.cpp - # chapter 8 + # CHAPTER 8 cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_01_tripleStep.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_02_robotGrid.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_03_magicIndex.cpp @@ -41,14 +42,15 @@ set(SOURCE_FILES cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_07_permutationsNoDups.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_08_permutationsWithDups.cpp cpp_solutions/chapter_08_recursion_and_dynamic_programming/problem_08_10_paintFill.cpp - # problem 10.01 not included because it is a template function implemented in .h file + # CHAPTER 10 cpp_solutions/chapter_10_sorting_and_searching/problem_10_02_anagramSort.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_04_searchNoSize.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_05_sparseSearch.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_07_missingInt.cpp cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp + cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.cpp + # CHAPTER 12 cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp - # problem 12.08 not included because it is a template function implemented in .h file cpp_solutions/misc_exercises/integralImage.cpp) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/README.md b/README.md index 3e5263d..2ec9640 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Conceptual problems solved through discussion are omitted. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `8 / 10` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `9 / 10` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -43,7 +43,7 @@ Conceptual problems solved through discussion are omitted. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `57` of `140` solutions complete. +C++ Total: `58` of `140` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -67,7 +67,7 @@ C++ Total: `57` of `140` solutions complete. Python Total: `56` of `130` solutions complete. -##### Grand Total: `113` unique solutions complete. +##### Grand Total: `114` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index 93530ea..ec9bd5d 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -7,6 +7,7 @@ #include "problem_10_07_missingInt.h" #include "problem_10_08_findDuplicates.h" #include "problem_10_09_matrixSearch.h" +#include "problem_10_10_rankFromStream.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.cpp new file mode 100644 index 0000000..27b3ec7 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.cpp @@ -0,0 +1,52 @@ +#include "problem_10_10_rankFromStream.h" + +namespace chapter_10 { + void RankTracker::track(int number) { + // if BST does not exist, make new head + if (_head == nullptr) { + _head = new RankBinaryNode(number); + } + else { + // if BST does exist, traverse it + RankBinaryNode* temp = _head; + // traverse BST until proper location for number is found + while (temp != nullptr) { + if (number == temp->getValue()) { + temp->incrementLeft(); + return; + } else if (number < temp->getValue()) { + temp->incrementLeft(); + if (temp->getLeft() == nullptr) { + temp->setLeft(new RankBinaryNode(number)); + return; + } + temp = static_cast*>(temp->getLeft()); + } else { + // no need to track right children in this algorithm + if (temp->getRight() == nullptr) { + temp->setRight(new RankBinaryNode(number)); + return; + } + temp = static_cast*>(temp->getRight()); + } + } + } + } + + int RankTracker::getRank(int number) { + int rank = 0; + RankBinaryNode* temp = _head; + while (temp != nullptr) { + if (number == temp->getValue()) { + rank += (temp->getLeftChildrenCount() - 1); + return rank; + } else if (number < temp->getValue()) { + temp = static_cast*>(temp->getLeft()); + } else { + rank += (temp->getLeftChildrenCount()); + temp = static_cast*>(temp->getRight()); + } + } + return -1; + } +} diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.h new file mode 100644 index 0000000..a8ad9cc --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.h @@ -0,0 +1,97 @@ +/* + * PROBLEM: + * Assuming we are reading in a stream of integers, write code to look up the rank of a given integer + * in the stream. The rank of an integer is equal to the number of integers less than or equal to it. + * Assume that a function track(x) is called on every member of the stream. Also assume that a + * function getRank(x) is called to compute the rank. + * + * TEST CASE: + * track(5); + * track(1); + * track(4); + * track(4); + * track(5); + * track(9); + * track(7); + * track(13); + * track(3); + * track(6); + * track(7); + * getRank(1) = 0; + * getRank(3) = 1; + * getRank(4) = 3; + * getRank(0) = -1; + * getRank(7) = 8; + * getRank(13) = 10; + * getRank(6) = 6; + * + * ALGORITHM: + * Implement a binary search tree where each node's value is the value of a number + * in the stream. Each track() call will take O(log(N)) time and each getRank() + * call will also take O(log(N)) time. + * + * 5(2) + * / \ + * 1 9 + * \ / \ + * 4(2) 7(2) 13 + * / / + * 3 6 + * In both cases the tree will have to be traversed. In the case of track(), we will traverse + * the tree until we find the correct node placement for a gien number. In the case of getRank(), we + * traverse the tree to find the node we are looking for (return -1 if we do not find it) + * then count all nodes to the left of the target node. We can optimize this counting procedure + * by storing the number of left children per node as the tree is being built up. The + * number of nodes to the left of a given node is equal to the sum of a given node's left children + * plus all left-branch ancestors and their children. We can keep track of duplicate numbers also within + * this left children count: simply add to left children when a duplicate is encountered. In this way, + * the algorithm will account for duplicates when computing rank. + * + * To compute the rank, we traverse the tree and increment a rank counter by the current node's number of + * left children every time we traverse right. If we traverse left, we do not increment the rank counter. + * If we find the node we are looking for, we increment the rank counter by its number of left children -1 + * to account for the node itself. If we do not find the node we are looking for, we return -1. + * + * TIME COMPLEXITY: O(log(N)) for track(), O(log(N)) for getRank(). + * SPACE COMPLEXITY: O(N) - one node is required for each number in stream. + * + * CODE: + */ + +#pragma once +#include "../chapter_02_linked_lists/Node.h" + +namespace chapter_10 { + // binary node class that keeps track of left and right children + template + class RankBinaryNode : public chapter_02::BinaryNode { + private: + int _leftChildrenCount; + public: + RankBinaryNode(T value) : chapter_02::BinaryNode(value) { + _leftChildrenCount = 1; // consider itself as part of left children count + } + RankBinaryNode(const RankBinaryNode& other) = delete; // for simplicity, don't allow copy construction + ~RankBinaryNode() { + RankBinaryNode* tempLeft = static_cast*>(this->getLeft()); + RankBinaryNode* tempRight = static_cast*>(this->getRight()); + delete tempLeft; + delete tempRight; + } + int getLeftChildrenCount() const {return _leftChildrenCount; } + void incrementLeft() { _leftChildrenCount ++; } + }; + + class RankTracker { + private: + RankBinaryNode* _head; + public: + RankTracker() { + _head = nullptr; + } + RankTracker(const RankTracker& other) = delete; // for simplicity, don't allow copy construction + ~RankTracker() { delete _head; } + void track(int number); + int getRank(int number); + }; +} diff --git a/tests.cpp b/tests.cpp index f14acc9..e3c0000 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1330,6 +1330,28 @@ TEST_CASE("Chapter 10 - Problem 09 - matrixSearch()", "test") { REQUIRE(expectedCoordinate6 == actualCoordinate6); } +TEST_CASE("Chapter 10 - Problem 10 - rankFromStream()", "test") { + chapter_10::RankTracker rankTracker; + rankTracker.track(5); + rankTracker.track(1); + rankTracker.track(4); + rankTracker.track(4); + rankTracker.track(5); + rankTracker.track(9); + rankTracker.track(7); + rankTracker.track(13); + rankTracker.track(3); + rankTracker.track(6); + rankTracker.track(7); + REQUIRE(rankTracker.getRank(1) == 0); + REQUIRE(rankTracker.getRank(3) == 1); + REQUIRE(rankTracker.getRank(4) == 3); + REQUIRE(rankTracker.getRank(0) == -1); + REQUIRE(rankTracker.getRank(7) == 8); + REQUIRE(rankTracker.getRank(13) == 10); + REQUIRE(rankTracker.getRank(6) == 6); +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From b6f86d424c10a10db98e547484eb2669066e9b63 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 23 Jul 2019 17:15:59 -0700 Subject: [PATCH 118/176] implement 10.11 C++ --- README.md | 6 +- .../chapter_10_includes.h | 1 + .../problem_10_11_peaksAndValleys.h | 61 +++++++++++++++++++ tests.cpp | 39 ++++++++++++ 4 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_10_sorting_and_searching/problem_10_11_peaksAndValleys.h diff --git a/README.md b/README.md index 2ec9640..9994fcc 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Conceptual problems solved through discussion are omitted. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. 9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `9 / 10` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 10` complete. 11. Chapter 11 - Testing: N/A 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A @@ -43,7 +43,7 @@ Conceptual problems solved through discussion are omitted. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `58` of `140` solutions complete. +C++ Total: `59` of `140` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -67,7 +67,7 @@ C++ Total: `58` of `140` solutions complete. Python Total: `56` of `130` solutions complete. -##### Grand Total: `114` unique solutions complete. +##### Grand Total: `115` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h index ec9bd5d..134cc37 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h +++ b/cpp_solutions/chapter_10_sorting_and_searching/chapter_10_includes.h @@ -8,6 +8,7 @@ #include "problem_10_08_findDuplicates.h" #include "problem_10_09_matrixSearch.h" #include "problem_10_10_rankFromStream.h" +#include "problem_10_11_peaksAndValleys.h" #include "quickSort.h" #include "mergeSort.h" #include "binarySearch.h" diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_11_peaksAndValleys.h b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_11_peaksAndValleys.h new file mode 100644 index 0000000..d63efd6 --- /dev/null +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_11_peaksAndValleys.h @@ -0,0 +1,61 @@ +/* + * PROBLEM: + * Given an array of integers, sort the array into one of alternating peaks and valleys + * where a peak is an integer greater than or equal to its neighbors and a valley is an + * integer less than or equal to its neighbors. + * + * TEST CASES: + * {5, 3, 1, 2, 3} --> {5, 1, 3, 2, 3} + * {5, 8, 6, 2, 3, 4, 6} --> {5, 8, 2, 6, 3, 6, 4}; + * {} --> {} + * {5} --> {5} + * {54} --> {54} + * {554} --> {554} + * + * ALGORITHM: + * Examine three numbers at a time, determine if second and third numbers need + * to be swapped to conform to peaks and valleys rule, modify the array if a swap is needed, + * move on to next group of 3 numbers as shown in example below: + * + * Example 1: + * {5, 3, 1, 2, 3} + * {5, 3, 1} -> {5, 1, 3} (swap 2nd & 3rd) + * array is now {5, 1, 3, 2, 3} + * {1, 3, 2} -> (no change) + * {3, 2, 3} -> (no change) + * + * Example 2: + * {5, 8, 6, 2, 3, 4, 6} + * {5, 8, 6} -> no change + * {8, 6, 2} -> swap second and last -> {8, 2, 6} + * array is now {5, 8, 2, 6, 3, 4, 6} + * {2, 6, 3} -> no change + * {6, 3, 4} -> no change + * {3, 4, 6} -> swap second and last -> {3, 6, 4} + * array is now {5, 8, 2, 6, 3, 6, 4} + * + * When processing each triple, we follow this logic: + * 1. If first <= second <= third: + * a. swap second and third + * 2. If first >= second >= third: + * a. swap second and third + * 3. If first <= second >= third: + * a. do nothing + * 4. If first >= second <= third: + * a. do nothing + * + * TIME COMPLEXITY: O(N) + * SPACE COMPLEXITY: O(1) + */ + +#pragma once + +namespace chapter_10 { + void peaksAndValleys(std::vector& array) { + for (int i = 0; i < (static_cast(array.size()) - 2); i++) { + if ((array[i] < array[i + 1] && array[i + 1] < array[i + 2]) || (array[i] > array[i + 1] && array[i + 1] > array[i + 2])) { + std::swap(array[i + 1], array[i + 2]); + } + } + } +} diff --git a/tests.cpp b/tests.cpp index e3c0000..cbdeece 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1352,6 +1352,45 @@ TEST_CASE("Chapter 10 - Problem 10 - rankFromStream()", "test") { REQUIRE(rankTracker.getRank(6) == 6); } +TEST_CASE("Chapter 10 - Problem 11 - peaksAndValleys()", "test") { + std::vector input1 = {5, 3, 1, 2, 3}; + std::vector expectedOutput1 = {5, 1, 3, 2, 3}; + std::vector input2 = {5, 8, 6, 2, 3, 4, 6}; + std::vector expectedOutput2 = {5, 8, 2, 6, 3, 6, 4}; + std::vector input3 = {}; + std::vector expectedOutput3 = {}; + std::vector input4 = {5}; + std::vector expectedOutput4 = {5}; + std::vector input5 = {55}; + std::vector expectedOutput5 = {55}; + std::vector input6 = {54}; + std::vector expectedOutput6 = {54}; + std::vector input7 = {45}; + std::vector expectedOutput7 = {45}; + std::vector input8 = {554}; + std::vector expectedOutput8 = {554}; + std::vector input9 = {5, 5, 8, 6, 6, 2, 3, 3, 4, 6, 6}; + std::vector expectedOutput9 = {5, 5, 8, 6, 6, 2, 3, 3, 6, 4, 6}; + chapter_10::peaksAndValleys(input1); + chapter_10::peaksAndValleys(input2); + chapter_10::peaksAndValleys(input3); + chapter_10::peaksAndValleys(input4); + chapter_10::peaksAndValleys(input5); + chapter_10::peaksAndValleys(input6); + chapter_10::peaksAndValleys(input7); + chapter_10::peaksAndValleys(input8); + chapter_10::peaksAndValleys(input9); + REQUIRE(input1 == expectedOutput1); + REQUIRE(input2 == expectedOutput2); + REQUIRE(input3 == expectedOutput3); + REQUIRE(input4 == expectedOutput4); + REQUIRE(input5 == expectedOutput5); + REQUIRE(input6 == expectedOutput6); + REQUIRE(input7 == expectedOutput7); + REQUIRE(input8 == expectedOutput8); + REQUIRE(input9 == expectedOutput9); +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; char s1Rev[] = "xelA"; From 63ff57c0847b810e4821460efbee4a69907cde29 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Tue, 23 Jul 2019 17:40:52 -0700 Subject: [PATCH 119/176] remove redundant import statements --- .../problem_01_07_rotate_matrix.py | 2 ++ tests.py | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python_solutions/chapter_01_arrays_and_strings/problem_01_07_rotate_matrix.py b/python_solutions/chapter_01_arrays_and_strings/problem_01_07_rotate_matrix.py index a09956c..3c55d1f 100644 --- a/python_solutions/chapter_01_arrays_and_strings/problem_01_07_rotate_matrix.py +++ b/python_solutions/chapter_01_arrays_and_strings/problem_01_07_rotate_matrix.py @@ -20,6 +20,8 @@ """ import math + + def rotate_matrix(matrix): # assume clockwise rotation N, M = matrix.shape diff --git a/tests.py b/tests.py index a574e2c..aae27c8 100644 --- a/tests.py +++ b/tests.py @@ -132,7 +132,6 @@ def test_problem_1_6(self): self.assertEqual('a10', p_1_6.string_compression('aaaaaaaaaa')) def test_problem_1_7(self): - import numpy as np input_4x4 = np.array([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], @@ -156,7 +155,6 @@ def test_problem_1_7(self): self.assertTrue(np.array_equal(p_1_7.rotate_matrix(input_5x5), output_5x5)) def test_problem_1_8(self): - import numpy as np input_4x4 = np.array([[1, 2, 3, 4], [1, 2, 0, 4], [1, 2, 3, 4], From 1a9ee1a28ae96276623cefa86d70774a54cec3ca Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Wed, 24 Jul 2019 15:44:50 -0700 Subject: [PATCH 120/176] add incompletre discussion questions to count --- README.md | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 9994fcc..56b3e86 100644 --- a/README.md +++ b/README.md @@ -20,30 +20,27 @@ reference and contribute solutions with confidence. ### Table of Contents -N.B. this project contains solutions only to problems solvable with C++ or Python program code. -Conceptual problems solved through discussion are omitted. - #### [C++ Solutions](cpp_solutions): 0. [C++ Unit Tests](tests.cpp) 1. [Chapter 1 - Arrays and Strings](cpp_solutions/chapter_01_arrays_and_strings): `9 / 9` complete. 2. [Chapter 2 - Linked Lists](cpp_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](cpp_solutions/chapter_03_stacks_and_queues): `4 / 6` complete. 4. [Chapter 4 - Trees and Graphs](cpp_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: N/A +5. [Chapter 5 - Bit Manipulation](cpp_solutions/chapter_05_bit_manipulation): `7 / 8` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](cpp_solutions/chapter_08_recursion_and_dynamic_programming): `8 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 10` complete. -11. Chapter 11 - Testing: N/A +9. Chapter 9 - System Design and Scalability: `0 / 8` complete. +10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. +11. Chapter 11 - Testing: `0 / 6` complete. 12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` 13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A -15. Chapter 15 - Threads and Locks: `0 / 4` +14. Chapter 14 - Databases: `0 / 7` complete. +15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `59` of `140` solutions complete. +C++ Total: `59` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -51,21 +48,21 @@ C++ Total: `59` of `140` solutions complete. 2. [Chapter 2 - Linked Lists](python_solutions/chapter_02_linked_lists): `8 / 8` complete. 3. [Chapter 3 - Stacks and Queues](python_solutions/chapter_03_stacks_queues): `6 / 6` complete. 4. [Chapter 4 - Trees and Graphs](python_solutions/chapter_04_trees_and_graphs): `11 / 12` complete. -5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 7` complete. -6. Chapter 6 - Math and Logic: N/A +5. [Chapter 5 - Bit Manipulation](python_solutions/chapter_05_bit_manipulation): `7 / 8` complete. +6. Chapter 6 - Math and Logic: `0 / 10` complete. 7. Chapter 7 - Object Oriented Design: `0 / 12` complete. 8. [Chapter 8 - Recursion and Dynamic Programming](python_solutions/chapter_08_recursion_and_dynamic_programming): `11 / 14` complete. -9. Chapter 9 - System Design and Scalability: N/A -10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 10` complete. -11. Chapter 11 - Testing: N/A +9. Chapter 9 - System Design and Scalability: `0 / 8` complete. +10. [Chapter 10 - Sorting and Searching](python_solutions/chapter_10_sorting_and_searching): `1 / 11` complete. +11. Chapter 11 - Testing: `0 / 6` complete. 12. Chapter 12 - C and C++: N/A 13. Chapter 13 - Java: N/A -14. Chapter 14 - Databases: N/A +14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: N/A 16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. 17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. -Python Total: `56` of `130` solutions complete. +Python Total: `56` solutions complete. ##### Grand Total: `115` unique solutions complete. From 04e752f3d40bfd291254f6929315a97ae91c4038 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 15:04:53 -0700 Subject: [PATCH 121/176] upgrade to C++ 17 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b4d17e6..b1da831 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.2) project(ctci) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) # include source folder include_directories(cpp_solutions) # include Eigen From aeda5fd1d08ef81f3704514361d81462bc237d1c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 15:34:45 -0700 Subject: [PATCH 122/176] remove unneeded #includes --- .../problem_10_08_findDuplicates.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp index 35efc88..29e1aae 100644 --- a/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp +++ b/cpp_solutions/chapter_10_sorting_and_searching/problem_10_08_findDuplicates.cpp @@ -1,8 +1,6 @@ #include "problem_10_08_findDuplicates.h" #include -#include #include -#include namespace chapter_10 { // Returns pair associated with number From ea544ea5601ad6c331e2f47a88d48fa5c94883c4 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 15:35:19 -0700 Subject: [PATCH 123/176] WIP 12.1 --- .../chapter_12_cpp/chapter_12_includes.h | 3 +- .../chapter_12_cpp/problem_12_01_data_1.txt | 22 +++++++ .../chapter_12_cpp/problem_12_01_data_2.txt | 1 + .../chapter_12_cpp/problem_12_01_data_3.txt | 0 .../chapter_12_cpp/problem_12_01_lastKLines.h | 65 +++++++++++++++++++ 5 files changed, 90 insertions(+), 1 deletion(-) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_01_data_1.txt create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_01_data_2.txt create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_01_data_3.txt create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h diff --git a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h index bddc2e5..0f03c76 100644 --- a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h +++ b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h @@ -1,4 +1,5 @@ #pragma once +#include "problem_12_01_lastKLines.h" #include "problem_12_02_reverse.h" -#include "problem_12_08_copyNode.h" \ No newline at end of file +#include "problem_12_08_copyNode.h" diff --git a/cpp_solutions/chapter_12_cpp/problem_12_01_data_1.txt b/cpp_solutions/chapter_12_cpp/problem_12_01_data_1.txt new file mode 100644 index 0000000..d56d9a7 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_01_data_1.txt @@ -0,0 +1,22 @@ +Invictus +By William Ernest Henley + +Out of the night that covers me, +Black as the pit from pole to pole, +I thank whatever gods may be +For my unconquerable soul. + +In the fell clutch of circumstance +I have not winced nor cried aloud. +Under the bludgeonings of chance +My head is bloody, but unbowed. + +Beyond this place of wrath and tears +Looms but the Horror of the shade, +And yet the menace of the years +Finds and shall find me unafraid. + +It matters not how strait the gate, +How charged with punishments the scroll, +I am the master of my fate, +I am the captain of my soul. diff --git a/cpp_solutions/chapter_12_cpp/problem_12_01_data_2.txt b/cpp_solutions/chapter_12_cpp/problem_12_01_data_2.txt new file mode 100644 index 0000000..64d18f7 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_01_data_2.txt @@ -0,0 +1 @@ +this is a single line diff --git a/cpp_solutions/chapter_12_cpp/problem_12_01_data_3.txt b/cpp_solutions/chapter_12_cpp/problem_12_01_data_3.txt new file mode 100644 index 0000000..e69de29 diff --git a/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h b/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h new file mode 100644 index 0000000..dd633b1 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h @@ -0,0 +1,65 @@ +/* + * PROBLEM: + * Read the last K lines of a file. + * + * TEST CASE: + * We would provide a text file with multiple lines + * and test for equality against the last K lines. + * Edge cases include empty file and file with less + * than K lines. + * + * ALGORITHM: + * We can maintain a circular array of length K. We can + * implement this circular array as a circular singly linked + * list whose node values are std::string. Initially, each + * string has an empty value. + * + * After the circularly linked list of K nodes is initialized, + * we assign a runner pointer to a node in the list. + * + * As we read the input text file line by line, we store the + * contents of the line in the node to which the runner + * currently points. We then advance the pointer without regard + * to overwriting node contents. In this way, the runner always + * points to either an empty string or the oldest line. + * + * Once the file is done reading, the pointer can be advanced + * K times to copy data from the circular array to a non-circular + * std::vector of std::strings for testing. + * + * TIME COMPLEXITY: O(N) + * SPACE COMPLEXITY: O(1) + */ + +/* +#pragma once +#include "../chapter_02_linked_lists/Node.h" +#include +#include +//#include +//#include +#include +//#include + +namespace chapter_12 { + void lastKLines(std::vector lines, const std::string& filepath) { + int K = lines.size(); + if (K <= 0) return; // handle empty lines vector + // initialize circular array + auto head = new chapter_02::SinglyLinkedNode(""); + auto prev = head; + for (int i = 1; i < K; i++) { + auto node = new chapter_02::SinglyLinkedNode(""); + prev->setNext(node); + prev = node; + } + prev->setNext(head); + // read from file + std::ifstream file(filepath); + std::string line = ""; + while (std::getline(file, line)){ + + } + } +} +*/ \ No newline at end of file From 1ae7c2ee4be3a675673160c4fd0b4d1a8c1a79f4 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 16:07:26 -0700 Subject: [PATCH 124/176] WIP 12.1: complete untested implementation --- .../chapter_12_cpp/problem_12_01_lastKLines.h | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h b/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h index dd633b1..960c2cc 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h @@ -31,20 +31,19 @@ * SPACE COMPLEXITY: O(1) */ -/* + #pragma once #include "../chapter_02_linked_lists/Node.h" #include #include -//#include -//#include #include -//#include + namespace chapter_12 { void lastKLines(std::vector lines, const std::string& filepath) { - int K = lines.size(); + const int K = lines.size(); if (K <= 0) return; // handle empty lines vector + // initialize circular array auto head = new chapter_02::SinglyLinkedNode(""); auto prev = head; @@ -54,12 +53,21 @@ namespace chapter_12 { prev = node; } prev->setNext(head); - // read from file + + // read from file into circular array std::ifstream file(filepath); std::string line = ""; while (std::getline(file, line)){ + head->setValue(line); + head = head->getNext(); + } + // copy contents of circular array to vector of strings; clean up allocated memory + for (int i = 0; i < K; i++) { + lines[i] = head->getValue(); + auto temp = head; + head=head->getNext(); + delete temp; } } } -*/ \ No newline at end of file From 32c61103d2d5a0a498ab4bbfaca5ec7a72436957 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 16:07:42 -0700 Subject: [PATCH 125/176] WIP enforce const correctness --- .../problem_02_02_returnKthToLast.h | 6 +- tests.cpp | 60 ++++++++++--------- 2 files changed, 36 insertions(+), 30 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h b/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h index ff9121b..3c8526d 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_02_returnKthToLast.h @@ -3,10 +3,10 @@ namespace chapter_02{ template - SinglyLinkedNode* returnKthToLast(SinglyLinkedNode* head, int k){ + const SinglyLinkedNode* returnKthToLast(const SinglyLinkedNode* head, int k) { if (head == nullptr) return nullptr; - SinglyLinkedNode* slowRunner = head; - SinglyLinkedNode* fastRunner = head; + const SinglyLinkedNode* slowRunner = head; + const SinglyLinkedNode* fastRunner = head; while(k > 0){ if (fastRunner == nullptr) return nullptr; fastRunner = fastRunner->getNext(); diff --git a/tests.cpp b/tests.cpp index cbdeece..cab9246 100644 --- a/tests.cpp +++ b/tests.cpp @@ -34,21 +34,21 @@ TEST_CASE("Chapter 01 - Problem 02 - isPermutation()", "test"){ 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"; + std::string input2 = ""; + std::string input3 = " "; + std::string input4 = "Alex"; + const std::string expectedOutput1 = "Mr.%20John%20Smith%20"; + const std::string expectedOutput2 = ""; + const std::string expectedOutput3 = "%20"; + const std::string expectedOutput4 = "Alex"; 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); + chapter_01::URLify(input2); + chapter_01::URLify(input3); + chapter_01::URLify(input4); + REQUIRE(input1 == expectedOutput1); + REQUIRE(input2 == expectedOutput2); + REQUIRE(input3 == expectedOutput3); + REQUIRE(input4 == expectedOutput4); } TEST_CASE("Chapter 01 - Problem 04 - palindromePermutation()", "test") { @@ -154,10 +154,10 @@ TEST_CASE("Chapter 02 - Basic LinkedList Functionality", "test"){ } 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; + const std::vector noDups = {1,7,3,6,5,4,2}; + const std::vector dups = {2,2,1,5,6,2,5,2,7,7}; + const std::vector fixedDups = {2,1,5,6,7}; + const std::vector emptyVec; // check that remove dups function doesn't affect lists with no dups chapter_02::SinglyLinkedNode* noDupsHead = chapter_02::vectorToList(noDups); @@ -176,12 +176,12 @@ TEST_CASE("Chapter 02 - Problem 01 - removeDups()", "test"){ } 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); + const std::vector testVec1 = {1,7,3,6,5,4,2}; + const std::vector testVec2 = {2,2,1,5,6,2,5,2,7,7}; + const std::vector testVec3; + const chapter_02::SinglyLinkedNode* testVec1Head = chapter_02::vectorToList(testVec1); + const chapter_02::SinglyLinkedNode* testVec2Head = chapter_02::vectorToList(testVec2); + const 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()); @@ -1354,7 +1354,7 @@ TEST_CASE("Chapter 10 - Problem 10 - rankFromStream()", "test") { TEST_CASE("Chapter 10 - Problem 11 - peaksAndValleys()", "test") { std::vector input1 = {5, 3, 1, 2, 3}; - std::vector expectedOutput1 = {5, 1, 3, 2, 3}; + const std::vector expectedOutput1 = {5, 1, 3, 2, 3}; std::vector input2 = {5, 8, 6, 2, 3, 4, 6}; std::vector expectedOutput2 = {5, 8, 2, 6, 3, 6, 4}; std::vector input3 = {}; @@ -1391,11 +1391,17 @@ TEST_CASE("Chapter 10 - Problem 11 - peaksAndValleys()", "test") { REQUIRE(input9 == expectedOutput9); } +TEST_CASE("Chapter 12 - Problem 01 - lastKLines()", "test"){ + const std::string filepath1 = "../cpp_solutions/chapter_12_sorting_and_searching/problem_12_01_data1.txt"; + const std::string filepath2 = "../cpp_solutions/chapter_12_sorting_and_searching/problem_12_01_data2.txt"; + const std::string filepath3 = "../cpp_solutions/chapter_12_sorting_and_searching/problem_12_01_data3.txt"; +} + TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ char s1[] = "Alex"; - char s1Rev[] = "xelA"; + const char s1Rev[] = "xelA"; char s2[] = "a"; - char s2Rev[] = "a"; + const char s2Rev[] = "a"; chapter_12::reverse(&s1[0]); chapter_12::reverse(&s2[0]); // strcmp returns 0 if the 2 strings are equal. From b9692bafe5fb8bccdc4e8cde6f3c27e8235dfa6c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 16:19:40 -0700 Subject: [PATCH 126/176] improve const correctness --- cpp_solutions/chapter_02_linked_lists/Node.h | 2 +- tests.cpp | 67 ++++++++++---------- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 4ea6851..3e9d00d 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -8,7 +8,7 @@ namespace chapter_02{ protected: T _value; public: - Node(T value) : _value(value) {} // constructor + Node(const T& value) : _value(value) {} // constructor Node(const Node& other) : _value(other.getValue()) {} // copy constructor ~Node(){} // destructor bool operator== (const Node& other) {return _value == other.getValue();} // equality check diff --git a/tests.cpp b/tests.cpp index cab9246..a396963 100644 --- a/tests.cpp +++ b/tests.cpp @@ -195,10 +195,10 @@ TEST_CASE("Chapter 02 - Problem 02 - returnKthToLast()", "test"){ TEST_CASE("Chapter 02 - Problem 03 - deleteMiddleNode()", "test"){ // create test dataset - std::vector testVec = {"a", "b", "c", "d", "e", "f"}; - std::vector expectedVec = {"a", "b", "d", "e", "f"}; + const std::vector testVec = {"a", "b", "c", "d", "e", "f"}; + const std::vector expectedVec = {"a", "b", "d", "e", "f"}; chapter_02::SinglyLinkedNode* testVecHead = chapter_02::vectorToList(testVec); - chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); + const chapter_02::SinglyLinkedNode* expectedVecHead = chapter_02::vectorToList(expectedVec); // traverse input to find node with content "c" chapter_02::SinglyLinkedNode* head = testVecHead; while (head != nullptr && head->getValue() != "c"){ @@ -216,10 +216,10 @@ TEST_CASE("Chapter 02 - Problem 03 - deleteMiddleNode()", "test"){ 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}; + const std::vector inputVec = {3, 5, 8, 5, 10, 2, 1}; + const 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); + const 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 @@ -233,27 +233,26 @@ TEST_CASE("Chapter 02 - Problem 04 - partition()", "test"){ 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)); + const std::vector n1Vec = {3, 2, 4, 9}; + const std::vector n2Vec = {1, 5, 9}; + const std::vector sumVecExpected = {4, 7, 3, 0, 1}; + const chapter_02::SinglyLinkedNode* n1Head = chapter_02::vectorToList(n1Vec); + const chapter_02::SinglyLinkedNode* n2Head = chapter_02::vectorToList(n2Vec); + const 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 list4 = {"a", "l", "e", "x"}; - std::vector 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* head4 = chapter_02::vectorToList(list4); - chapter_02::SinglyLinkedNode* head5 = chapter_02::vectorToList(list5); + const std::vector list1 = {0, 4, 7, 0, 0, 7, 4, 0}; + const std::vector list2 = {3, 5, 2, 5, 3}; + const std::vector list3 = {0, 1, 0, 1, 0, 1}; + const std::vector list4 = {"a", "l", "e", "x"}; + const std::vector list5 = {"A", "B", "B", "A"}; + const chapter_02::SinglyLinkedNode* head1 = chapter_02::vectorToList(list1); + const chapter_02::SinglyLinkedNode* head2 = chapter_02::vectorToList(list2); + const chapter_02::SinglyLinkedNode* head3 = chapter_02::vectorToList(list3); + const chapter_02::SinglyLinkedNode* head4 = chapter_02::vectorToList(list4); + const chapter_02::SinglyLinkedNode* head5 = chapter_02::vectorToList(list5); REQUIRE(chapter_02::palindrome(head1)); REQUIRE(chapter_02::palindrome(head2)); REQUIRE(!chapter_02::palindrome(head3)); @@ -263,19 +262,19 @@ TEST_CASE("Chapter 02 - Problem 06 - palindrome()", "test"){ 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); + 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); + 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); + 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*>(nullptr), static_cast*>(nullptr))); From c5312d3932fa3c04fa804c1b255a52308a97dd7d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 16:51:30 -0700 Subject: [PATCH 127/176] complete 12.1 --- .../chapter_12_cpp/problem_12_01_lastKLines.h | 13 +++++++++++- tests.cpp | 21 ++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h b/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h index 960c2cc..9037cd3 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_01_lastKLines.h @@ -40,7 +40,7 @@ namespace chapter_12 { - void lastKLines(std::vector lines, const std::string& filepath) { + void lastKLines(std::vector& lines, const std::string& filepath) { const int K = lines.size(); if (K <= 0) return; // handle empty lines vector @@ -55,11 +55,22 @@ namespace chapter_12 { prev->setNext(head); // read from file into circular array + int numLines = 0; // track number of lines to account for case where numLines < K std::ifstream file(filepath); std::string line = ""; while (std::getline(file, line)){ head->setValue(line); head = head->getNext(); + numLines ++; + } + file.close(); + + // reset position of head pointer back to beginning if there were fewer lines than K + // this is to make the output remain in order with blank lines below non-blank ones + if (numLines < K) { + for (int i = 0; i < (K - numLines); i++) { + head = head->getNext(); + } } // copy contents of circular array to vector of strings; clean up allocated memory diff --git a/tests.cpp b/tests.cpp index a396963..29b0f83 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1391,9 +1391,24 @@ TEST_CASE("Chapter 10 - Problem 11 - peaksAndValleys()", "test") { } TEST_CASE("Chapter 12 - Problem 01 - lastKLines()", "test"){ - const std::string filepath1 = "../cpp_solutions/chapter_12_sorting_and_searching/problem_12_01_data1.txt"; - const std::string filepath2 = "../cpp_solutions/chapter_12_sorting_and_searching/problem_12_01_data2.txt"; - const std::string filepath3 = "../cpp_solutions/chapter_12_sorting_and_searching/problem_12_01_data3.txt"; + const std::string filepath1 = "../cpp_solutions/chapter_12_cpp/problem_12_01_data_1.txt"; + const std::string filepath2 = "../cpp_solutions/chapter_12_cpp/problem_12_01_data_2.txt"; + const std::string filepath3 = "../cpp_solutions/chapter_12_cpp/problem_12_01_data_3.txt"; + std::vector lines1 = {"", "", "", ""}; + std::vector lines2 = {"", "", "", ""}; + std::vector lines3 = {"", "", "", ""}; + const std::vector expectedLines1 = {"It matters not how strait the gate, ", + "How charged with punishments the scroll, ", + "I am the master of my fate, ", + "I am the captain of my soul."}; + const std::vector expectedLines2 = {"this is a single line", "", "", ""}; + const std::vector expectedLines3 = {"", "", "", ""}; + chapter_12::lastKLines(lines1, filepath1); + chapter_12::lastKLines(lines2, filepath2); + chapter_12::lastKLines(lines3, filepath3); + REQUIRE(lines1 == expectedLines1); + REQUIRE(lines2 == expectedLines2); + REQUIRE(lines3 == expectedLines3); } TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ From 7434b6767200fb2a2b847a40fefe59996e2b1fe6 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 25 Jul 2019 16:52:51 -0700 Subject: [PATCH 128/176] update completion --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 56b3e86..6940833 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `2 / 6` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `3 / 6` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `59` solutions complete. +C++ Total: `60` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) From e04126baef1fd16682e493d8495a7756c2ea165e Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 25 Jul 2019 23:23:21 -0700 Subject: [PATCH 129/176] correct completion --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6940833..c78d0f3 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ C++ Total: `60` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `115` unique solutions complete. +##### Grand Total: `116` unique solutions complete. ### Building: #### Mac: From 13705d2764751168233bccb0f78181e6a7efa32d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 27 Jul 2019 19:05:29 -0700 Subject: [PATCH 130/176] complete 12.3 --- README.md | 6 +- .../chapter_12_cpp/problem_12_03_hashTable.h | 57 +++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h diff --git a/README.md b/README.md index c78d0f3..128f084 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `3 / 6` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `4 / 6` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `60` solutions complete. +C++ Total: `61` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `60` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `116` unique solutions complete. +##### Grand Total: `117` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h b/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h new file mode 100644 index 0000000..acaee2d --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h @@ -0,0 +1,57 @@ +/* + * PROBLEM: + * Compare and contrast hash table and STL map. + * + * a. How is a hash table implemented? + * b. If the number of inputs is small, which data structure options can be used instead of a + * hash table? + * + * + * Discussion for Part (a): + * + * A hash table is a key-value pair data structure that allows O(1) time lookup of a value given its key. + * + * First a hash table relies on a hashing function that converts a key into an index used to look up + * that key's associated value. The hashing function is important to implement well because the set + * of total possible keys could be very vast while the set of total possible indices could be very small. + * Thus, index collison is a problem for hash table implementation. For example, if the hashing function + * is not ideal, multiple keys could map to the same value index. For small datasets, a trivial hashing function + * may be the key itself. Creating a hashing function usually requires good knowledge of the data type + * of the key: different hashing functions may be more appropriate for different key data types. The C++ 11 + * standard provides a hash template that unordered associate containers such as unordered_map use by default. + * Specializations of this template define hashing functions for the different primitive types in C++. Programmers + * would have to define their own hashing functions for custom types. + * + * The second component of the hash table is the data structure itself which typically is an array of linked + * lists. The index computed by the hash function is used to look up array elements; in the case of an + * index collision, multiple values associated with that index are pushed to the back of the linked list + * at that index. Below is an example of hash table operation: + * + * Keys: Values: + * A 78 + * B 12 + * C 90 + * + * Assume that the hashing function has a collision for keys A and B. + * Thus the array of linked lists looks like this: + * + * Array Index: 0, 1 + * Linked List Content: [A, 78], [B, 12] [C, 90] + * + * When the key "B" is looked up, its index collides with the index for "A". Thus, to retrieve the + * value for "B" the linked list at array index 0 must be traversed one element at a time in order to find + * "B"'s value. This means that hash tables have amortized O(1) lookup time. In the absolute worst case + * - e.g. a very bad hashing function that assigns all N keys to the same array index - the lookup time is O(N). + * + * One final issue in hash table implementation is expanding the hash table size when the memory allocated for + * it has been depleted. This expansion operation would require copying all contents of the hash table, and so + * must not be done too often. + * + * Discussion for Part (b): + * + * If the keys support >, <, = relationships, a map could be implemented as a binary search tree or a derivative + * of a binary search tree. In this case, the lookup time is O(long(N)), but if N is small this time could be negligible. + * The std::map structure is implemented using a red-black tree, which is a binary search tree with one extra bit per node: + * a color red or black. According to CLRS: "by constraining the node colors on any simple path from root to leaf, + * red-black trees ensure that no such path is more than twice as long as any other so that the tree is approximately balanced." + */ From cb9a3bc92078f3b4f67673c0d4de65653d0d9405 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 28 Jul 2019 17:02:49 -0700 Subject: [PATCH 131/176] formatting change for discussion questions --- cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h b/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h index acaee2d..427b7ea 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_03_hashTable.h @@ -1,5 +1,5 @@ /* - * PROBLEM: + * QUESTION: * Compare and contrast hash table and STL map. * * a. How is a hash table implemented? @@ -7,7 +7,7 @@ * hash table? * * - * Discussion for Part (a): + * DISCUSSION PART (a): * * A hash table is a key-value pair data structure that allows O(1) time lookup of a value given its key. * @@ -47,7 +47,7 @@ * it has been depleted. This expansion operation would require copying all contents of the hash table, and so * must not be done too often. * - * Discussion for Part (b): + * DISCUSSION PART (b): * * If the keys support >, <, = relationships, a map could be implemented as a binary search tree or a derivative * of a binary search tree. In this case, the lookup time is O(long(N)), but if N is small this time could be negligible. From a87800804c85c17cfedf2c50e21956f52385d211 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 28 Jul 2019 21:20:23 -0700 Subject: [PATCH 132/176] fix typo in completion --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 128f084..525b54f 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `4 / 6` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `4 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. From 59b5dae0ac2d38e86d71f637baa0f7d41d8734e3 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 28 Jul 2019 21:21:10 -0700 Subject: [PATCH 133/176] conform to rule that base class destructors need to be virtual --- cpp_solutions/chapter_02_linked_lists/Node.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/Node.h b/cpp_solutions/chapter_02_linked_lists/Node.h index 3e9d00d..4a069eb 100644 --- a/cpp_solutions/chapter_02_linked_lists/Node.h +++ b/cpp_solutions/chapter_02_linked_lists/Node.h @@ -5,12 +5,12 @@ namespace chapter_02{ // Node base class template class Node{ - protected: + private: T _value; public: Node(const T& value) : _value(value) {} // constructor Node(const Node& other) : _value(other.getValue()) {} // copy constructor - ~Node(){} // destructor + virtual ~Node(){} // destructor bool operator== (const Node& other) {return _value == other.getValue();} // equality check T getValue() const {return _value;} void setValue(const T& value) {_value = value;} From 5b8836e5a7fb53b6f429c7dd0bb9747660cf1272 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 28 Jul 2019 22:02:43 -0700 Subject: [PATCH 134/176] complete 12.4 --- README.md | 6 +-- .../problem_12_04_virtualFunctions.h | 44 +++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h diff --git a/README.md b/README.md index 525b54f..7f3ed39 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `4 / 11` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `5 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `61` solutions complete. +C++ Total: `62` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `61` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `117` unique solutions complete. +##### Grand Total: `118` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h b/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h new file mode 100644 index 0000000..ee9199c --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h @@ -0,0 +1,44 @@ +/* + * QUESTION: + * How do virtual functions work in C++? + * + * DISCUSSION (researched from C++ Primer Plus and Jumping into C++): + * + * In C++, the virtual function concept enables polymorphism. A function is declared virtual + * in a base class if it may be reimplemented by the derived class. This allows constructs such + * as declaring an array of base class pointers (all the same size and type) to point to a multitude + * of different derived class objects and enable a multitude of different implementations for common functions to be invoked. + * + * For example, assume Student and Teacher classes are derived from the Person class. Assume + * also that we create an std::vector array to represent the people in a school course. + * The Person class declares and implements a function getID() which prints "I am a Person." However in the + * Student and Teacher classes, getID() prints "I am a Student" and "I am a Teacher" respectively. The problem + * is that these different implementations of getID() would not be accessible from the Person* pointers stored + * in the std::vector unless getID() were declared virtual in the Person class definition. + * + * To implement this behavior, object instances carry an extra hidden member that is a pointer to block of data + * called a vtable or "virtual table". There is one vptr ("virtual table pointer") per object for each interface the + * object inherits. There is one vtable per interface. I.e. there would be one vtable for Person, one for Student, + * and one for Teacher. Each object would contain a pointer to the class vtable of its type. + * A vtable contains memory addresses of the possible functions that may be used by an object. Each entry in the + * table corresponds to a different possible function, and the address in each entry is the address of the + * version of that function (base class version or derived class version) that is appropriate to use. So if a + * derived class reimplements a virtual function in the base class, the vtable will point to the derived class + * reimplementation. If the derived class does not reimplement a virtual function in the base class, the vtable + * entry will point to the base class version of that function. + * + * vtables enable dynamic binding as opposed to static binding. Static binding happens at compile time in cases when the + * executable function code that must be bound to a function name call is unambiguous. This happens - among other cases - for + * non-virtual member functions of classes. However, there are cases where the executable function code that must be + * bound to a function call is not known at compile time and is only found out at runtime. An example of this is if + * the choice of Student or Teacher derived classes depends on user input. The vtable object thus enables this dynamic + * binding of executable function code along with the polymorphism concept. + * + * In C++, static binding is the default instead of dynamic binding for performance reasons: there is a compute cost + * associated with vtable storage and operation. At each function call, there is an extra lookup operation that must + * be made before the function call itself is executed. Furthermore, each object must carry a vtable pointer for each inherited + * interface which costs a couple of bytes. In practice these are very small costs but they are non-zero. The storage + * cost would become significant if there are many many objects with few member variables and thus the vtable memory + * consumption may become significant. + * + */ From ebcd7e40f98f82cff4be51985841264afb02c134 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 28 Jul 2019 22:26:01 -0700 Subject: [PATCH 135/176] complete 12.5 and 12.7 --- README.md | 6 ++--- .../problem_12_04_virtualFunctions.h | 1 - .../problem_12_05_shallowVsDeepCopy.h | 23 +++++++++++++++++++ .../problem_12_07_virtualBaseClass.h | 16 +++++++++++++ 4 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_05_shallowVsDeepCopy.h create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_07_virtualBaseClass.h diff --git a/README.md b/README.md index 7f3ed39..be69022 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `5 / 11` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `7 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `0 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `62` solutions complete. +C++ Total: `64` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `62` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `118` unique solutions complete. +##### Grand Total: `120` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h b/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h index ee9199c..221ac83 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_04_virtualFunctions.h @@ -40,5 +40,4 @@ * interface which costs a couple of bytes. In practice these are very small costs but they are non-zero. The storage * cost would become significant if there are many many objects with few member variables and thus the vtable memory * consumption may become significant. - * */ diff --git a/cpp_solutions/chapter_12_cpp/problem_12_05_shallowVsDeepCopy.h b/cpp_solutions/chapter_12_cpp/problem_12_05_shallowVsDeepCopy.h new file mode 100644 index 0000000..09d3a90 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_05_shallowVsDeepCopy.h @@ -0,0 +1,23 @@ +/* + * QUESTION: + * What is the difference between deep copy and shallow copy? Explain how you would use each. + * + * DISCUSSION: + * A shallow copy of an object copies all of its member variables. This sounds simple, but it hides one big + * piece of complexity: if among the object's + * member variables there exist pointers to allocated memory, only the pointers themselves are copied + * while the allocated memory remains the same. Thus if two such shallow copied objects exist, they will + * contain different pointers to the same block of allocated memory. Unless this behavior is intended (it usually + * isn't), it could cause program logic errors as well as memory access violation errors because. + * + * Shallow copies are useful when we need const pointers or const references to a large block of memory that + * does not change and has the proper const keywords to prevent change. An example of this would be passing copies of + * pointers to a large image do different image processing functions that each needs to read the raw image, do computation, + * and return a result. + * + * Deep copies are what the name implies: the copy operation travels recursively to all pointed-to allocated + * memory, allocates new memory, copies the data over, and then returns a new pointer to the newly allocated block. + * Deep copies are useful when different segments of the same program must alter a set of data in different ways + * and the further operate on the results of the changes. + * + */ diff --git a/cpp_solutions/chapter_12_cpp/problem_12_07_virtualBaseClass.h b/cpp_solutions/chapter_12_cpp/problem_12_07_virtualBaseClass.h new file mode 100644 index 0000000..52cc8d3 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_07_virtualBaseClass.h @@ -0,0 +1,16 @@ +/* + * QUESTION: + * Why does a destructor in a base class need to be declared virtual? + * + * DISCUSSION (researched from C++ Primer Plus and Jumping into C++): + * This issue arises when we use a base class pointer to point to an object of a derived class + * e.g. assume the Student class is derived from the Parent class: + * + * Person * p = new Student(); + * + * If Person's destructor were not virtual, the Student object would be destructed with + * the destructor in Parent because the pointer to p is a Parent pointer. This could + * lead to situations in which Student-specific memory allocations are not cleaned up which lead + * to memory corruption. + * + */ From dcc6441fbc3fe45ad0cdac47570b2710733a1454 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 29 Jul 2019 22:23:13 -0700 Subject: [PATCH 136/176] WIP 16.3 C++ --- CMakeLists.txt | 2 ++ .../chapter_16_moderate/chapter_16_includes.h | 3 ++ .../problem_16_03_intersection.cpp | 10 +++++++ .../problem_16_03_intersection.h | 28 +++++++++++++++++++ tests.cpp | 25 +++++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 cpp_solutions/chapter_16_moderate/chapter_16_includes.h create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b1da831..e360d56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,8 @@ set(SOURCE_FILES cpp_solutions/chapter_10_sorting_and_searching/problem_10_10_rankFromStream.cpp # CHAPTER 12 cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp + # CHAPTER 16 + cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp cpp_solutions/misc_exercises/integralImage.cpp) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h new file mode 100644 index 0000000..d4ab733 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -0,0 +1,3 @@ +#pragma once + +#include "problem_16_03_intersection.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp new file mode 100644 index 0000000..7d6e97d --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp @@ -0,0 +1,10 @@ +#include "problem_16_03_intersection.h" + +namespace chapter_16 { + Point2* intersection(const LineSegment2& s1, + const LineSegment2& s2){ + // follow book implementation: ignore vertical slopes, ignore colinear overlap + auto intersection = new Point2(0,0); + return intersection; + } +} \ No newline at end of file diff --git a/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h new file mode 100644 index 0000000..1cdc18a --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h @@ -0,0 +1,28 @@ +#pragma once + +namespace chapter_16 { + struct Point2 { + float _x; + float _y; + Point2(float x, float y) : _x(x), _y(y) {}; + Point2(const Point2& other) : _x(other._x), _y(other._y) {}; + bool operator==(const Point2& other) { + return other._x == _x && other._y == _y; + } + }; + + struct Line2 { + float _m; + float _b; + Line2(float m, float b) : _m(m), _b(b){}; + }; + + struct LineSegment2 { + Point2 _p1; + Point2 _p2; + LineSegment2(const Point2& p1, const Point2& p2) : _p1(p1), _p2(p2) {}; + }; + + Point2* intersection(const LineSegment2& s1, + const LineSegment2& s2); +}; \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index 29b0f83..f24e3df 100644 --- a/tests.cpp +++ b/tests.cpp @@ -10,6 +10,7 @@ #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/chapter_16_moderate/chapter_16_includes.h" #include "cpp_solutions/misc_exercises/misc_includes.h" #define CATCH_CONFIG_MAIN #include "cpp_solutions/third_party/Catch/include/catch.hpp" @@ -1437,6 +1438,30 @@ TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ } } +TEST_CASE("Chapter 16 - Problem 03 - intersection()") { + // follow book implementation: ignore vertical slopes, ignore colinear overlap + /* + segment1 = p_16_03.LineSegment(p_16_03.Point2(5, 5), p_16_03.Point2(0, 0)) + segment2 = p_16_03.LineSegment(p_16_03.Point2(0, 3), p_16_03.Point2(3, 0)) + segment3 = p_16_03.LineSegment(p_16_03.Point2(3, 0), p_16_03.Point2(6, 0)) + segment4 = p_16_03.LineSegment(p_16_03.Point2(4, 0), p_16_03.Point2(7, 0)) + segment5 = p_16_03.LineSegment(p_16_03.Point2(7, 7), p_16_03.Point2(5, 5)) + self.assertEqual(p_16_03.Point2(1.5, 1.5), p_16_03.intersection(segment1, segment2)) + self.assertEqual(None, p_16_03.intersection(segment1, segment3)) + self.assertEqual(None, p_16_03.intersection(segment4, segment3)) + self.assertEqual(p_16_03.Point2(5, 5), p_16_03.intersection(segment1, segment5)) + */ + auto s1 = chapter_16::LineSegment2(chapter_16::Point2(5, 5), chapter_16::Point2(0, 0)); + auto s2 = chapter_16::LineSegment2(chapter_16::Point2(0, 3), chapter_16::Point2(3, 0)); + auto s3 = chapter_16::LineSegment2(chapter_16::Point2(3, 0), chapter_16::Point2(6, 0)); + auto s4 = chapter_16::LineSegment2(chapter_16::Point2(4, 0), chapter_16::Point2(7, 0)); + auto s5 = chapter_16::LineSegment2(chapter_16::Point2(7, 7), chapter_16::Point2(5, 5)); + REQUIRE(chapter_16::Point2(1.5, 1.5) == *chapter_16::intersection(s1, s2)); + REQUIRE(nullptr == chapter_16::intersection(s1, s3)); + REQUIRE(nullptr == chapter_16::intersection(s4, s3)); + REQUIRE(chapter_16::Point2(5, 5) == *chapter_16::intersection(s1, s5)); +} + TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ Eigen::MatrixXd input1(4, 4); input1 << 1, 1, 1, 1, From 609f34167e30296b625da8c85f23fbdc4e46dc84 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 29 Jul 2019 23:58:55 -0700 Subject: [PATCH 137/176] implement 16.3 C++ --- README.md | 6 ++-- .../problem_16_03_intersection.cpp | 35 +++++++++++++++++-- .../problem_16_03_intersection.h | 34 +++++++++++++----- .../problem_16_03_intersection.py | 6 +--- tests.cpp | 26 ++++++-------- 5 files changed, 74 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index be69022..e65c809 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. Chapter 16 - Moderate: `0 / 26` complete. +16. Chapter 16 - Moderate: `1 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `64` solutions complete. +C++ Total: `65` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `64` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `120` unique solutions complete. +##### Grand Total: `121` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp index 7d6e97d..5b35b03 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp +++ b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp @@ -4,7 +4,38 @@ namespace chapter_16 { Point2* intersection(const LineSegment2& s1, const LineSegment2& s2){ // follow book implementation: ignore vertical slopes, ignore colinear overlap - auto intersection = new Point2(0,0); - return intersection; + // check slope equality + // if slopes are not equal, assume lines are infinite and compute their intersection + // then determine if this intersection is within the bounds of the segments + if (!approxEqual(s1._m, s2._m)) { + /* + * y = m1x + b1 + * y = m2x + b2 + * m1x + b1 = m2x + b2 + * (m1 - m2)x = b2 - b1 + * x = (b2 - b1) / (m1 - m2) + * y = m1x + b + */ + float xIntersection = (s2._b - s1._b) / (s1._m - s2._m); + auto intersection = new Point2(xIntersection, s1._m * xIntersection + s1._b); + if (s1.inBounds(*intersection) && s2.inBounds(*intersection)) { + return intersection; + } + else { + delete intersection; + return nullptr; + } + } + else { // if slope equal, only endpoint equality indicates intersection + if (s1._p1 == s2._p1 || s1._p1 == s2._p2) { + auto intersection = new Point2(s1._p1); + return intersection; + } + if (s1._p2 == s2._p1 || s1._p2 == s2._p2) { + auto intersection = new Point2(s1._p2); + return intersection; + } + return nullptr; + } } } \ No newline at end of file diff --git a/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h index 1cdc18a..6e2b47b 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_03_intersection.h @@ -1,26 +1,44 @@ #pragma once +#include namespace chapter_16 { + template + bool approxEqual(const T& a, const T& b, float epsilon = 1e-6) { + return (a > (b - static_cast(epsilon)) && a < (b + static_cast(epsilon))); + } + struct Point2 { float _x; float _y; Point2(float x, float y) : _x(x), _y(y) {}; Point2(const Point2& other) : _x(other._x), _y(other._y) {}; - bool operator==(const Point2& other) { + bool operator==(const Point2& other) const { return other._x == _x && other._y == _y; } }; - struct Line2 { - float _m; - float _b; - Line2(float m, float b) : _m(m), _b(b){}; - }; - struct LineSegment2 { Point2 _p1; Point2 _p2; - LineSegment2(const Point2& p1, const Point2& p2) : _p1(p1), _p2(p2) {}; + float _m; + float _b; + LineSegment2(const Point2& p1, const Point2& p2) : _p1(p1), _p2(p2) { + // reorder the points in x order to make further logic easier + if (_p1._x > _p2._x) { + Point2 temp = _p1; + _p1 = _p2; + _p2 = temp; + } + // when constructed from two points, compute the slope and y-intercept of infinite line + _m = (_p2._y - _p1._y) / (_p2._x - _p1._x); + _b = _p1._y - _m * _p1._x; + }; + bool inBounds(const Point2& p) const { + return (p._x >= std::min(_p1._x, _p2._x) && + p._x <= std::max(_p1._x, _p2._x) && + p._y >= std::min(_p1._y, _p2._y) && + p._y <= std::max(_p1._y, _p2._y)); + } }; Point2* intersection(const LineSegment2& s1, diff --git a/python_solutions/chapter_16_moderate/problem_16_03_intersection.py b/python_solutions/chapter_16_moderate/problem_16_03_intersection.py index 0fe85b9..ac40f62 100644 --- a/python_solutions/chapter_16_moderate/problem_16_03_intersection.py +++ b/python_solutions/chapter_16_moderate/problem_16_03_intersection.py @@ -29,13 +29,9 @@ def intersection(segment1, segment2): if segment1.start.x <= x_intersection <= segment1.end.x and segment2.start.x <= x_intersection <= segment2.end.x: intersection_point = Point2(x_intersection, y_intersection_1) return intersection_point - else: + else: # slopes equal: intersection happens only if endpoints are identical if segment1.start == segment2.start or segment1.start == segment2.end: return segment1.start if segment1.end == segment2.start or segment1.end == segment2.end: return segment1.end - if segment2.start == segment1.start or segment2.start == segment1.end: - return segment2.start - if segment2.end == segment1.start or segment2.end == segment1.end: - return segment2.end return None diff --git a/tests.cpp b/tests.cpp index f24e3df..c49e716 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1440,26 +1440,22 @@ TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ TEST_CASE("Chapter 16 - Problem 03 - intersection()") { // follow book implementation: ignore vertical slopes, ignore colinear overlap - /* - segment1 = p_16_03.LineSegment(p_16_03.Point2(5, 5), p_16_03.Point2(0, 0)) - segment2 = p_16_03.LineSegment(p_16_03.Point2(0, 3), p_16_03.Point2(3, 0)) - segment3 = p_16_03.LineSegment(p_16_03.Point2(3, 0), p_16_03.Point2(6, 0)) - segment4 = p_16_03.LineSegment(p_16_03.Point2(4, 0), p_16_03.Point2(7, 0)) - segment5 = p_16_03.LineSegment(p_16_03.Point2(7, 7), p_16_03.Point2(5, 5)) - self.assertEqual(p_16_03.Point2(1.5, 1.5), p_16_03.intersection(segment1, segment2)) - self.assertEqual(None, p_16_03.intersection(segment1, segment3)) - self.assertEqual(None, p_16_03.intersection(segment4, segment3)) - self.assertEqual(p_16_03.Point2(5, 5), p_16_03.intersection(segment1, segment5)) - */ auto s1 = chapter_16::LineSegment2(chapter_16::Point2(5, 5), chapter_16::Point2(0, 0)); auto s2 = chapter_16::LineSegment2(chapter_16::Point2(0, 3), chapter_16::Point2(3, 0)); auto s3 = chapter_16::LineSegment2(chapter_16::Point2(3, 0), chapter_16::Point2(6, 0)); auto s4 = chapter_16::LineSegment2(chapter_16::Point2(4, 0), chapter_16::Point2(7, 0)); auto s5 = chapter_16::LineSegment2(chapter_16::Point2(7, 7), chapter_16::Point2(5, 5)); - REQUIRE(chapter_16::Point2(1.5, 1.5) == *chapter_16::intersection(s1, s2)); - REQUIRE(nullptr == chapter_16::intersection(s1, s3)); - REQUIRE(nullptr == chapter_16::intersection(s4, s3)); - REQUIRE(chapter_16::Point2(5, 5) == *chapter_16::intersection(s1, s5)); + chapter_16::Point2 expected_p1(1.5, 1.5); + chapter_16::Point2 expected_p4(5, 5); + auto actual_p1 = chapter_16::intersection(s1, s2); + auto actual_p2 = chapter_16::intersection(s1, s3); + auto actual_p3 = chapter_16::intersection(s4, s3); + auto actual_p4 = chapter_16::intersection(s1, s5); + REQUIRE(expected_p1 == *actual_p1); + REQUIRE(nullptr == actual_p2); + REQUIRE(nullptr == actual_p3); + REQUIRE(expected_p4 == *actual_p4); + delete actual_p1, actual_p2, actual_p3, actual_p4; } TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ From a175d440dfecb8af7ea99933d9e38a5be4da2c54 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 2 Aug 2019 11:21:02 -0700 Subject: [PATCH 138/176] complete 12.6 C++ --- .../chapter_12_cpp/problem_12_06_volatile.h | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_06_volatile.h diff --git a/cpp_solutions/chapter_12_cpp/problem_12_06_volatile.h b/cpp_solutions/chapter_12_cpp/problem_12_06_volatile.h new file mode 100644 index 0000000..a291f5c --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_06_volatile.h @@ -0,0 +1,21 @@ +/* + * PROBLEM: + * What is the significance of the keyword "volatile" in C? + * + * DISCUSSION: + * The volatile keyword indicates to the compiler that a variable may be changed + * outside the scope of the current block of code. This applies to situations in which + * the variable may be changed by the hardware such as memory-mapped I/O. Syntactically the + * volatile keyword is used in the same way as const. + * + * The keyword is necessary to prevent compiler optimizations that are done based on the + * assumption that the variable does *not* change when it is *not* modified in the current + * scope. If such compiler optimizations are done and the variable *is* modified e.g. by the + * hardware outside the current scope, it would lead to undefined behavior. In the above case, + * the compiler would re-use a stale variable value which would yield incorrect calculation + * results. + * + * Note that in C++ 11, the volatile keyword is *not* intended for use in multithreaded scenarios, + * and the std::atomic template is intended to be used instead for inter-thread communication. + * In C++ 11, the volatile keyword is only intended to handle hardware access scenarios. + */ \ No newline at end of file From d88e32c9febccef658acfc5de8bdff5ac560e2e4 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 2 Aug 2019 11:26:58 -0700 Subject: [PATCH 139/176] update completion --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e65c809..b9a0c1c 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `7 / 11` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `8 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `1 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `65` solutions complete. +C++ Total: `66` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `65` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `121` unique solutions complete. +##### Grand Total: `122` unique solutions complete. ### Building: #### Mac: From bcd9384e9742d5407dde23dc6f7fef682ef1e2da Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 2 Aug 2019 14:05:16 -0700 Subject: [PATCH 140/176] (1) implement 12.9 C++, (2) update completion, (3) fix incorrect deletion of objects in unit test case --- README.md | 6 +- .../chapter_12_cpp/chapter_12_includes.h | 1 + .../problem_12_09_smartPointer.h | 74 +++++++++++++++++++ tests.cpp | 21 +++++- 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_09_smartPointer.h diff --git a/README.md b/README.md index b9a0c1c..e003f5a 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `8 / 11` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `9 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `1 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `66` solutions complete. +C++ Total: `67` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `66` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `122` unique solutions complete. +##### Grand Total: `123` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h index 0f03c76..31f52be 100644 --- a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h +++ b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h @@ -3,3 +3,4 @@ #include "problem_12_01_lastKLines.h" #include "problem_12_02_reverse.h" #include "problem_12_08_copyNode.h" +#include "problem_12_09_smartPointer.h" diff --git a/cpp_solutions/chapter_12_cpp/problem_12_09_smartPointer.h b/cpp_solutions/chapter_12_cpp/problem_12_09_smartPointer.h new file mode 100644 index 0000000..f226abe --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_09_smartPointer.h @@ -0,0 +1,74 @@ +/* + * PROBLEM: + * Implement a smart pointer class that performs reference counting. + * I.e. implement a class that performs the work a programmer would have + * to perform if using raw pointers. + * + * ALGORITHM: + * The times when an object's reference count would have to be adjusted + * are when the object is (1) constructed, (2) copied, or (3) destructed. + * Case (2) is covered by the copy constructor and copy assignment operator. + * The textbook does not cover a move constructor and move assignment operator, + * although for C++ 11 and beyond, we should. + * + * We thus implement a constructor, copy constructor, copy assignment operator, + * and a destructor that are member functions of a SmartPointer class template. Member + * variables of the SmartPointer class are a pointer to an actual object and a + * pointer to a reference count. Note that it is crucial that these are pointers: + * there can be only one object and only one reference count in memory for one + * object of interest. The member functions increment and decrement the reference + * counter as needed and delete the object when the reference counter reaches 0. + * + * The way to test this functionality (see tests.cpp) is to + * use lambda functions to simulate copies of the SmartPointer object coming onto + * and off of the call stack and check the reference count before and after the lambda + * is executed. + * + * TIME COMPLEXITY: O(1) + * SPACE COMPLEXITY: O(1) + */ + +#pragma once + +namespace chapter_12 { + template + class SmartPointer { + protected: + T* _obj; + size_t* _referenceCount; + void remove() { + (*_referenceCount) --; + if ((*_referenceCount) == 0) { + delete _obj; + delete _referenceCount; + } + } + public: + // regular constructor + SmartPointer(T* object) : _obj(object), _referenceCount(new size_t(1)) {}; + // copy constructor + SmartPointer(const SmartPointer& other) : _obj(other._obj) { + _referenceCount = other._referenceCount; + (*_referenceCount) ++; + } + // assignment operator + SmartPointer& operator=(const SmartPointer& other) { + if (this == &other) { + return *this; + } + remove(); + _obj = other._obj; + _referenceCount = other._referenceCount; + (*_referenceCount) ++; + return *this; + } + // destructor + ~SmartPointer() { + remove(); + } + // getters and setters + T getValue() const {return *_obj;} + void setValue(T objectValue) {*_obj = objectValue;} + size_t getRefCount() {return *_referenceCount;} + }; +} \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index c49e716..31e6f53 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1424,7 +1424,7 @@ TEST_CASE("Chapter 12 - Problem 02 - reverse()", "test"){ REQUIRE(strcmp(&s2[0], &s2Rev[0]) == 0); } -TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ +TEST_CASE("Chapter 12 - Problem 08 - copyNode()", "test"){ std::vector targetVector = {1,2,3,4,5,6,7}; chapter_02::SinglyLinkedNode* head = chapter_02::vectorToList(targetVector); chapter_02::SinglyLinkedNode* copy = chapter_12::copyNode(head); @@ -1438,6 +1438,20 @@ TEST_CASE("Chapter 12 - Problem 12 - copyNode()", "test"){ } } +TEST_CASE("Chapter 12 - Problem 09 - smartPointer()", "test"){ + chapter_12::SmartPointer intSP(new int(5)); + REQUIRE(intSP.getRefCount() == 1); + auto doSomethingLambda = [](chapter_12::SmartPointer sp){ + sp.setValue(6); + REQUIRE(sp.getRefCount() == 2); + chapter_12::SmartPointer intSP2(sp); + REQUIRE(intSP2.getRefCount() == 3); + REQUIRE(sp.getRefCount() == 3); + }; + doSomethingLambda(intSP); + REQUIRE(intSP.getRefCount() == 1); +} + TEST_CASE("Chapter 16 - Problem 03 - intersection()") { // follow book implementation: ignore vertical slopes, ignore colinear overlap auto s1 = chapter_16::LineSegment2(chapter_16::Point2(5, 5), chapter_16::Point2(0, 0)); @@ -1455,7 +1469,10 @@ TEST_CASE("Chapter 16 - Problem 03 - intersection()") { REQUIRE(nullptr == actual_p2); REQUIRE(nullptr == actual_p3); REQUIRE(expected_p4 == *actual_p4); - delete actual_p1, actual_p2, actual_p3, actual_p4; + delete actual_p1; + delete actual_p2; + delete actual_p3; + delete actual_p4; } TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ From f2aa53c5846bbc5e0ad97c66713eb986523c0e14 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 10:07:16 -0700 Subject: [PATCH 141/176] implement 16.6 --- README.md | 6 +-- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_06_smallestDifference.h | 41 +++++++++++++++++++ tests.cpp | 14 +++++++ 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_06_smallestDifference.h diff --git a/README.md b/README.md index e003f5a..1c7e913 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. Chapter 16 - Moderate: `1 / 26` complete. +16. Chapter 16 - Moderate: `2 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `67` solutions complete. +C++ Total: `68` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `67` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `123` unique solutions complete. +##### Grand Total: `124` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index d4ab733..3af203e 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -1,3 +1,4 @@ #pragma once #include "problem_16_03_intersection.h" +#include "problem_16_06_smallestDifference.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_06_smallestDifference.h b/cpp_solutions/chapter_16_moderate/problem_16_06_smallestDifference.h new file mode 100644 index 0000000..5ccf935 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_06_smallestDifference.h @@ -0,0 +1,41 @@ +/* + * PROBLEM: Given two arrays of integers, compute the pair of values (one value in each array) with the + * smallest (non-negative) difference. Return the difference. + * + * TEST CASES: See tests.cpp. + * + * ALGORITHM: + * 1. Sort the two arrays. + * 2. "Merge" the two arrays as in the mergeSort() merge operation. + * 3. Pairs of elements considered for a merge are candidates for smallest difference. + * 4. At each potential merge, calculate the difference and update smallest difference if necessary. + * + * TIME COMPLEXITY: O(M*log(M) + N*log(N) + M + N) + * SPACE COMPLEXITY: O(M + N) if the caller is not ok with having their inputs become sorted. O(1) otherwise. + */ + +#pragma once +#include +#include +#include + +namespace chapter_16 { + int smallestDifference(std::vector a1, std::vector a2) { + std::sort(a1.begin(), a1.end()); + std::sort(a2.begin(), a2.end()); + int a1i = 0; + int a2i = 0; + int smallestDifference = std::numeric_limits::max(); + while (a1i < a1.size() && a2i < a2.size()) { + int difference = std::abs(a1[a1i] - a2[a2i]); + if (difference < smallestDifference) smallestDifference = difference; + if (a1[a1i] <= a2[a2i]) { + a1i ++; + } + else { + a2i ++; + } + } + return smallestDifference; + } +} diff --git a/tests.cpp b/tests.cpp index 31e6f53..6fcee69 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1475,6 +1475,20 @@ TEST_CASE("Chapter 16 - Problem 03 - intersection()") { delete actual_p4; } +TEST_CASE("Chapter 16 - Problem 06 - smallestDifference()") { + std::vector example1 = {1, 3, 15, 11, 2}; + std::vector example2 = {23, 127, 235, 19, 8}; + std::vector example3 = {-5, 4, -3, 2, 12}; + std::vector example4 = {-7, 6, 12, 1, -3}; + std::vector example5 = {-5, 3}; + std::vector example6 = {}; + REQUIRE(3 == chapter_16::smallestDifference(example1, example2)); + REQUIRE(0 == chapter_16::smallestDifference(example3, example4)); + REQUIRE(2 == chapter_16::smallestDifference(example4, example5)); + REQUIRE(std::numeric_limits::max() == chapter_16::smallestDifference(example5, example6)); + REQUIRE(std::numeric_limits::max() == chapter_16::smallestDifference(example6, example6)); +} + TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ Eigen::MatrixXd input1(4, 4); input1 << 1, 1, 1, 1, From 96941881ca7d7f57973b2532a7224a023d4e9608 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 10:57:48 -0700 Subject: [PATCH 142/176] implement 16.10 --- README.md | 6 +- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_10_livingPeople.h | 56 +++++++++++++++++++ tests.cpp | 16 ++++++ 4 files changed, 76 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h diff --git a/README.md b/README.md index 1c7e913..fe6e79f 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. Chapter 16 - Moderate: `2 / 26` complete. +16. Chapter 16 - Moderate: `3 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `68` solutions complete. +C++ Total: `69` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `68` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `124` unique solutions complete. +##### Grand Total: `125` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index 3af203e..ed570b9 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -2,3 +2,4 @@ #include "problem_16_03_intersection.h" #include "problem_16_06_smallestDifference.h" +#include "problem_16_10_livingPeople.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h new file mode 100644 index 0000000..a41c764 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h @@ -0,0 +1,56 @@ +/* + * PROBLEM: Given a list of people with their birth and death years, implement a method to compute the year + * with the most number of people alive. You may assume that all people were born between 1900 and 2000 (inclusive). + * If a person was alive during any portion of that year, they should be included in that year's count. For example, + * Person (birth = 1908, death = 1909) is included in the counts for both 1908 and 1909. + * + * TEST CASES: see tests.cpp + * + * ALGORITHM: + * 0. Create an array of ints with a number of elements equal to the number of years range. + * 1. Iterate over all people. For each person, increment the array element corresponding to + * the person's birth. Decrement the array element corresponding to the year *after* the + * person's death. + * 2. Iterate over the array of years keeping a sum of all the elements seen so far, a "maxSum" + * with the highest value sum ever seen, and the year that the maxSum was recorded. + * 3. Return the year of the maxSum. + * + * TIME COMPLEXITY: O(N) + * SPACE COMPLEXITY: O(1) + */ + +#pragma once + +namespace chapter_16 { + struct Person { + int birth; + int death; + Person(int _birth, int _death) : birth(_birth), death(_death) {}; + }; + + int livingPeople(const std::vector& people, int startYear, int endYear) { + assert(startYear < endYear); + const int numYears = endYear - startYear + 1; // 101 years from 1900 to 2000 + int years[numYears] = {0}; + for (const Person& p : people) { + if (p.birth >= startYear && p.birth <= endYear) { + years[p.birth - startYear]++; + } + if (p.death >= startYear && p.death < endYear) { // strict less than to conform to rule (see below) + years[p.death + 1 - startYear] --; // rule in problem statement: if someone was alive for any part of a year + // they are considered to have been alive the whole year + } + } + int bestYear = startYear; + int mostPeople = 0; + int currentPeople = 0; + for (int i = 0; i < numYears; i++) { + currentPeople += years[i]; + if (currentPeople > mostPeople) { + mostPeople = currentPeople; + bestYear = i + startYear; + } + } + return bestYear; + } +} diff --git a/tests.cpp b/tests.cpp index 6fcee69..940296e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1489,6 +1489,22 @@ TEST_CASE("Chapter 16 - Problem 06 - smallestDifference()") { REQUIRE(std::numeric_limits::max() == chapter_16::smallestDifference(example6, example6)); } +TEST_CASE("Chapter 16 - Problem 10 - livingPeople()") { + std::vector people1 = { + chapter_16::Person(1930, 2000), + chapter_16::Person(1940, 2010), + chapter_16::Person(1920, 2000), + chapter_16::Person(1980, 1990), + chapter_16::Person(1982, 1982), + chapter_16::Person(1900, 1920), + chapter_16::Person(1910, 1920), + chapter_16::Person(1945, 1995)}; + std::vector people2 = {}; + REQUIRE(1982 == livingPeople(people1, 1900, 2020)); + REQUIRE(1945 == livingPeople(people1, 1900, 1950)); + REQUIRE(1900 == livingPeople(people2, 1900, 2020)); +}; + TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ Eigen::MatrixXd input1(4, 4); input1 << 1, 1, 1, 1, From fb8201e0e7558cf301eabebdbc55873b7b91e15c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 11:04:22 -0700 Subject: [PATCH 143/176] implement 16.5. fix bug in 16.10 --- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_05_factorialZeros.h | 58 +++++++++++++++++++ .../problem_16_10_livingPeople.h | 2 +- tests.cpp | 17 ++++++ 4 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index ed570b9..5296c73 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -1,5 +1,6 @@ #pragma once #include "problem_16_03_intersection.h" +#include "problem_16_05_factorialZeros.h" #include "problem_16_06_smallestDifference.h" #include "problem_16_10_livingPeople.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h b/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h new file mode 100644 index 0000000..c6bd282 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h @@ -0,0 +1,58 @@ +/* + * PROBLEM: Write an algorithm which computes the number of trailing 0s in N!. + * + * TEST CASES: + * 1! = 1 -> 0 + * 2! = 2 -> 0 + * 5! = 120 -> 1 + * 7! = 5040 -> 1 + * 10! = 3628800 -> 2 + * + * ALGORITHM: + * The easy solution is to compute N! then iteratively divide by 10 until + * the division yields a fractional value. However, N! will quickly overwhelm + * the maximum integer size on a 32 bit machine, so this solution is not practical + * for large values of N. + * + * We observe that the only way to generate a trailing zero is for a + * factorial multiplication series is for the series to contain a (5, 2) pair. Thus 5! can be represented + * as 5 * 2 * 2 * 3 * 2 * 1 which contains 1 such pair. We observe that in a factorial operation, there will + * always be more 2 factors than 5 factors. Thus the number of trailing zeros is equal + * to the number of 5 factors in the factorial operation. Note that a number like 25 + * is 5^2 and thus contains two 5 factors. + * + * To solve, we iterate over the values [5, 10, 15, 20, 25, ... ] and stop iterating + * when N > the current multiple of 5 value. We also keep track of the current exponent + * of 5 [5->1, 10->1, 15->1, 20->1, 25->2, ...] during the iteration. At each iteration, + * we add the current exponent to the count of total zeros. + * + * TIME COMPLEXITY: O(N) + * SPACE COMPLEXITY: O(1) + */ + +#pragma once + +namespace chapter_16 { + int factorialZeros(long N) { + if (N < 0) { + return -1; + } + int factorialZeros = 0; + int multipleOf5 = 5; + int exponentOf5 = 1; + int exponentCount = 1; + while (N >= multipleOf5) { + // increment number of zeros + factorialZeros += exponentOf5; + // update multiple + multipleOf5 += 5; + // update exponent + exponentCount += 1; + if (exponentCount == 5) { + exponentCount = 1; + exponentOf5 ++; + } + } + return factorialZeros; + } +} \ No newline at end of file diff --git a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h index a41c764..4d871c9 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h @@ -31,7 +31,7 @@ namespace chapter_16 { int livingPeople(const std::vector& people, int startYear, int endYear) { assert(startYear < endYear); const int numYears = endYear - startYear + 1; // 101 years from 1900 to 2000 - int years[numYears] = {0}; + std::vector years(numYears, 0); for (const Person& p : people) { if (p.birth >= startYear && p.birth <= endYear) { years[p.birth - startYear]++; diff --git a/tests.cpp b/tests.cpp index 940296e..4ca09ce 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1475,6 +1475,23 @@ TEST_CASE("Chapter 16 - Problem 03 - intersection()") { delete actual_p4; } +TEST_CASE("Chapter 16 - Problem 05 - factorialZeros()") { + REQUIRE(-1 == chapter_16::factorialZeros(-1)); + REQUIRE(0 == chapter_16::factorialZeros(1)); + REQUIRE(0 == chapter_16::factorialZeros(2)); + REQUIRE(1 == chapter_16::factorialZeros(5)); + REQUIRE(1 == chapter_16::factorialZeros(7)); + REQUIRE(2 == chapter_16::factorialZeros(10)); + REQUIRE(2 == chapter_16::factorialZeros(14)); + REQUIRE(3 == chapter_16::factorialZeros(15)); + REQUIRE(3 == chapter_16::factorialZeros(16)); + REQUIRE(3 == chapter_16::factorialZeros(19)); + REQUIRE(4 == chapter_16::factorialZeros(20)); + REQUIRE(4 == chapter_16::factorialZeros(21)); + REQUIRE(6 == chapter_16::factorialZeros(25)); + REQUIRE(6 == chapter_16::factorialZeros(26)); +} + TEST_CASE("Chapter 16 - Problem 06 - smallestDifference()") { std::vector example1 = {1, 3, 15, 11, 2}; std::vector example2 = {23, 127, 235, 19, 8}; From 2b35b624d49348d0356a0f12b3003a79dad9ffdb Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 11:07:26 -0700 Subject: [PATCH 144/176] fix improper spacing --- cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h index 4d871c9..35d0dad 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h @@ -38,7 +38,7 @@ namespace chapter_16 { } if (p.death >= startYear && p.death < endYear) { // strict less than to conform to rule (see below) years[p.death + 1 - startYear] --; // rule in problem statement: if someone was alive for any part of a year - // they are considered to have been alive the whole year + // they are considered to have been alive the whole year } } int bestYear = startYear; From 1fb5c128c43557299fbefeb962f1b07e1bb2f3cf Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 11:08:48 -0700 Subject: [PATCH 145/176] update completion --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe6e79f..12281d2 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. Chapter 16 - Moderate: `3 / 26` complete. +16. Chapter 16 - Moderate: `4 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `69` solutions complete. +C++ Total: `70` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `69` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `125` unique solutions complete. +##### Grand Total: `126` unique solutions complete. ### Building: #### Mac: From 89490fb9ffdbc5ea78fb8f73671b8f3a3d3b6b22 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 12:30:57 -0700 Subject: [PATCH 146/176] implement 16.2 --- README.md | 6 +-- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_02_wordFrequencies.h | 49 +++++++++++++++++++ tests.cpp | 34 +++++++++++++ 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h diff --git a/README.md b/README.md index 12281d2..6145858 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,10 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. Chapter 16 - Moderate: `4 / 26` complete. +16. Chapter 16 - Moderate: `5 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `70` solutions complete. +C++ Total: `71` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `70` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `126` unique solutions complete. +##### Grand Total: `127` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index 5296c73..60a73a8 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -1,5 +1,6 @@ #pragma once +#include "problem_16_02_wordFrequencies.h" #include "problem_16_03_intersection.h" #include "problem_16_05_factorialZeros.h" #include "problem_16_06_smallestDifference.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h b/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h new file mode 100644 index 0000000..458b797 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h @@ -0,0 +1,49 @@ +/* + * PROBLEM: Design a method to find the frequency of occurrences of any given word in a book. + * What if we were running this algorithm mUltiple times? + * + * TEST CASES: See tests.cpp + * + * ALGORITHM: Make a hash table that stores the counts of each word. Then simply look up the counts + * in the hash table when queried. + * + * TIME COMPLEXITY: O(1) lookup + * SPACE COMPLEXITY: O(N) + */ + +#pragma once + +#include +#include +#include +#include + +namespace chapter_16 { + void trimCopy(std::string& target, const std::string& source) { + for (char c : source) { + char c_lower = static_cast(std::tolower(c)); + if (c_lower >= 97 && c_lower <= 122) { + target += c_lower; + } + } + } + + void makeDatabase(const std::vector& book, std::unordered_map& database) { + for (const std::string& word : book) { + std::string trimmedWord; + trimCopy(trimmedWord, word); + if (!trimmedWord.empty()) { + if (database.count(trimmedWord) == 0) { + database[trimmedWord] = 1; + } + else { + database[trimmedWord] ++; + } + } + } + } + + int wordFrequencies(const std::string& word, const std::unordered_map& database) { + return database.count(word) ? database.at(word) : 0; + } +} diff --git a/tests.cpp b/tests.cpp index 4ca09ce..4ccd18e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1452,6 +1452,40 @@ TEST_CASE("Chapter 12 - Problem 09 - smartPointer()", "test"){ REQUIRE(intSP.getRefCount() == 1); } +TEST_CASE("Chapter 16 - Problem 02 - wordFrequencies()") { + std::vector book = {"Invictus\n", + "By", + "William","Ernest","Henley\n", + "\n", + "Out", "of", "the", "night", "that","covers","me,\n", + "Black","as","the","pit","from","pole","to","pole,\n", + "I","thank","whatever","gods","may","be\n", + "For","my","unconquerable soul.\n", + "\n", + "In","the","fell","clutch","of","circumstance\n", + "I","have","not","winced","nor","cried","aloud.\n", + "Under","the","bludgeonings","of","chance\n", + "My","head","is","bloody,","but","unbowed.\n", + "\n", + "Beyond","this","place","of","wrath","and","tears\n", + "Looms","but","the","Horror","of","the","shade,\n", + "And","yet","the","menace","of","the","years\n", + "Finds","and","shall","find","me","unafraid.\n", + "\n", + "It","matters","not","how","strait","the","gate,\n", + "How","charged","with","punishments","the","scroll,\n", + "I","am","the","master","of","my","fate,\n", + "I","am","the","captain","of","my","soul."}; + std::unordered_map database; + chapter_16::makeDatabase(book, database); + REQUIRE(8 == chapter_16::wordFrequencies("of", database)); + REQUIRE(1 == chapter_16::wordFrequencies("captain", database)); + REQUIRE(4 == chapter_16::wordFrequencies("my", database)); + REQUIRE(12 == chapter_16::wordFrequencies("the", database)); + REQUIRE(1 == chapter_16::wordFrequencies("it", database)); + REQUIRE(2 == chapter_16::wordFrequencies("but", database)); +} + TEST_CASE("Chapter 16 - Problem 03 - intersection()") { // follow book implementation: ignore vertical slopes, ignore colinear overlap auto s1 = chapter_16::LineSegment2(chapter_16::Point2(5, 5), chapter_16::Point2(0, 0)); From c0b1490b30474d56cc1a3e11959d79bf93a6fbf2 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 12:37:27 -0700 Subject: [PATCH 147/176] maintenance: move implementations to cpp files --- CMakeLists.txt | 3 ++ .../problem_16_02_wordFrequencies.cpp | 32 +++++++++++++++++++ .../problem_16_02_wordFrequencies.h | 30 ++--------------- .../problem_16_05_factorialZeros.cpp | 26 +++++++++++++++ .../problem_16_05_factorialZeros.h | 23 +------------ .../problem_16_10_livingPeople.cpp | 30 +++++++++++++++++ .../problem_16_10_livingPeople.h | 27 ++-------------- 7 files changed, 97 insertions(+), 74 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e360d56..4499f69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,7 +52,10 @@ set(SOURCE_FILES # CHAPTER 12 cpp_solutions/chapter_12_cpp/problem_12_02_reverse.cpp # CHAPTER 16 + cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.cpp cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp + cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp + cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp cpp_solutions/misc_exercises/integralImage.cpp) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.cpp b/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.cpp new file mode 100644 index 0000000..e09432d --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.cpp @@ -0,0 +1,32 @@ +#include "problem_16_02_wordFrequencies.h" + +namespace chapter_16 { + void trimCopy(std::string& target, const std::string& source) { + for (char c : source) { + char c_lower = static_cast(std::tolower(c)); + if (c_lower >= 97 && c_lower <= 122) { + target += c_lower; + } + } + } + + void makeDatabase(const std::vector& book, std::unordered_map& database) { + for (const std::string& word : book) { + std::string trimmedWord; + trimCopy(trimmedWord, word); + if (!trimmedWord.empty()) { + if (database.count(trimmedWord) == 0) { + database[trimmedWord] = 1; + } + else { + database[trimmedWord] ++; + } + } + } + } + + int wordFrequencies(const std::string& word, const std::unordered_map& database) { + return database.count(word) ? database.at(word) : 0; + } +} + diff --git a/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h b/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h index 458b797..f62ae94 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.h @@ -19,31 +19,7 @@ #include namespace chapter_16 { - void trimCopy(std::string& target, const std::string& source) { - for (char c : source) { - char c_lower = static_cast(std::tolower(c)); - if (c_lower >= 97 && c_lower <= 122) { - target += c_lower; - } - } - } - - void makeDatabase(const std::vector& book, std::unordered_map& database) { - for (const std::string& word : book) { - std::string trimmedWord; - trimCopy(trimmedWord, word); - if (!trimmedWord.empty()) { - if (database.count(trimmedWord) == 0) { - database[trimmedWord] = 1; - } - else { - database[trimmedWord] ++; - } - } - } - } - - int wordFrequencies(const std::string& word, const std::unordered_map& database) { - return database.count(word) ? database.at(word) : 0; - } + void trimCopy(std::string& target, const std::string& source); + void makeDatabase(const std::vector& book, std::unordered_map& database); + int wordFrequencies(const std::string& word, const std::unordered_map& database); } diff --git a/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp b/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp new file mode 100644 index 0000000..94154bf --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp @@ -0,0 +1,26 @@ +#include "problem_16_05_factorialZeros.h" + +namespace chapter_16 { + int factorialZeros(long N) { + if (N < 0) { + return -1; + } + int factorialZeros = 0; + int multipleOf5 = 5; + int exponentOf5 = 1; + int exponentCount = 1; + while (N >= multipleOf5) { + // increment number of zeros + factorialZeros += exponentOf5; + // update multiple + multipleOf5 += 5; + // update exponent + exponentCount += 1; + if (exponentCount == 5) { + exponentCount = 1; + exponentOf5 ++; + } + } + return factorialZeros; + } +} diff --git a/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h b/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h index c6bd282..ffd1680 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.h @@ -33,26 +33,5 @@ #pragma once namespace chapter_16 { - int factorialZeros(long N) { - if (N < 0) { - return -1; - } - int factorialZeros = 0; - int multipleOf5 = 5; - int exponentOf5 = 1; - int exponentCount = 1; - while (N >= multipleOf5) { - // increment number of zeros - factorialZeros += exponentOf5; - // update multiple - multipleOf5 += 5; - // update exponent - exponentCount += 1; - if (exponentCount == 5) { - exponentCount = 1; - exponentOf5 ++; - } - } - return factorialZeros; - } + int factorialZeros(long N); } \ No newline at end of file diff --git a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp new file mode 100644 index 0000000..43f3203 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp @@ -0,0 +1,30 @@ +#include "problem_16_10_livingPeople.h" + +namespace chapter_16 { + int livingPeople(const std::vector& people, int startYear, int endYear) { + assert(startYear < endYear); + const int numYears = endYear - startYear + 1; // 101 years from 1900 to 2000 + std::vector years(numYears, 0); + for (const Person& p : people) { + if (p.birth >= startYear && p.birth <= endYear) { + years[p.birth - startYear]++; + } + if (p.death >= startYear && p.death < endYear) { // strict less than to conform to rule (see below) + years[p.death + 1 - startYear] --; // rule in problem statement: if someone was alive for any part of a year + // they are considered to have been alive the whole year + } + } + int bestYear = startYear; + int mostPeople = 0; + int currentPeople = 0; + for (int i = 0; i < numYears; i++) { + currentPeople += years[i]; + if (currentPeople > mostPeople) { + mostPeople = currentPeople; + bestYear = i + startYear; + } + } + return bestYear; + } +} + diff --git a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h index 35d0dad..346762f 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.h @@ -20,6 +20,7 @@ */ #pragma once +#include namespace chapter_16 { struct Person { @@ -28,29 +29,5 @@ namespace chapter_16 { Person(int _birth, int _death) : birth(_birth), death(_death) {}; }; - int livingPeople(const std::vector& people, int startYear, int endYear) { - assert(startYear < endYear); - const int numYears = endYear - startYear + 1; // 101 years from 1900 to 2000 - std::vector years(numYears, 0); - for (const Person& p : people) { - if (p.birth >= startYear && p.birth <= endYear) { - years[p.birth - startYear]++; - } - if (p.death >= startYear && p.death < endYear) { // strict less than to conform to rule (see below) - years[p.death + 1 - startYear] --; // rule in problem statement: if someone was alive for any part of a year - // they are considered to have been alive the whole year - } - } - int bestYear = startYear; - int mostPeople = 0; - int currentPeople = 0; - for (int i = 0; i < numYears; i++) { - currentPeople += years[i]; - if (currentPeople > mostPeople) { - mostPeople = currentPeople; - bestYear = i + startYear; - } - } - return bestYear; - } + int livingPeople(const std::vector& people, int startYear, int endYear); } From 6a0207de319e4fe0ea067982d3fc82ef2d703044 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 5 Aug 2019 12:42:59 -0700 Subject: [PATCH 148/176] remove assert --- .../chapter_16_moderate/problem_16_10_livingPeople.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp index 43f3203..50b1c8c 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp +++ b/cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp @@ -2,7 +2,7 @@ namespace chapter_16 { int livingPeople(const std::vector& people, int startYear, int endYear) { - assert(startYear < endYear); + if (startYear >= endYear) return startYear; const int numYears = endYear - startYear + 1; // 101 years from 1900 to 2000 std::vector years(numYears, 0); for (const Person& p : people) { From d17a7a08f6ba6a4001a3859a6f3fa262f05708e8 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 8 Aug 2019 14:54:08 -0700 Subject: [PATCH 149/176] skeleton for 12.10 and 12.11 --- cpp_solutions/chapter_12_cpp/chapter_12_includes.h | 2 ++ .../chapter_12_cpp/problem_12_10_alignedMalloc.h | 3 +++ cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h | 3 +++ tests.cpp | 8 ++++++++ 4 files changed, 16 insertions(+) create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h create mode 100644 cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h diff --git a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h index 31f52be..bce0f05 100644 --- a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h +++ b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h @@ -4,3 +4,5 @@ #include "problem_12_02_reverse.h" #include "problem_12_08_copyNode.h" #include "problem_12_09_smartPointer.h" +#include "problem_12_10_alignedMalloc.h" +#include "problem_12_11_malloc2D.h" diff --git a/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h b/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h new file mode 100644 index 0000000..45dcbb0 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h b/cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h new file mode 100644 index 0000000..45dcbb0 --- /dev/null +++ b/cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/tests.cpp b/tests.cpp index 4ccd18e..613d91e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1452,6 +1452,14 @@ TEST_CASE("Chapter 12 - Problem 09 - smartPointer()", "test"){ REQUIRE(intSP.getRefCount() == 1); } +TEST_CASE("Chapter 12 - Problem 10 - alignedMalloc()", "test"){ + +} + +TEST_CASE("Chapter 12 - Problem 11 - malloc2D()", "test"){ + +} + TEST_CASE("Chapter 16 - Problem 02 - wordFrequencies()") { std::vector book = {"Invictus\n", "By", From 0c325bb8ba50d35f3b276706e585e55dbd9c9570 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 8 Aug 2019 22:16:39 -0700 Subject: [PATCH 150/176] update completion --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6145858..600e8f3 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `9 / 11` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `11 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `5 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `71` solutions complete. +C++ Total: `73` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `71` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `127` unique solutions complete. +##### Grand Total: `129` unique solutions complete. ### Building: #### Mac: From cca3ca72aeba693123fda7af3ead5040bf2e1d99 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 11 Aug 2019 18:01:19 -0700 Subject: [PATCH 151/176] WIP 12.10 --- .../problem_12_10_alignedMalloc.h | 39 +++++++++++++++++++ .../misc_exercises/integralImage.cpp | 1 - 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h b/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h index 45dcbb0..2f764a2 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h @@ -1,3 +1,42 @@ +/* + * PROBLEM: + * Write an aligned malloc and free function that supports allocating memory such that the + * memory address returned is divisible by a specific power of two. + * + * These articles discuss the importance of aligned memory allocation: + * https://developer.ibm.com/articles/pa-dalign/ + * https://codeyarns.com/2017/02/28/aligned-memory-allocation/ + * + * The general idea is that CPU hardware is designed to read multiple bytes of data from + * memory in a single read instruction, and therefore one must keep this design choice in + * mind when allocating memory. For example, a CPU with 64 bit architecture can + * read addresses 0-7 (1 byte each) in a single read instruction. If a data structure + * requires 32 bits of memory but those 32 bits are spread out over addresses 5, 7, 8, and 9, + * then the CPU will require two read instructions to read 32 bits instead of one. One instruction + * will read addresses 0-7, a second will read addresses 8-15, and more instructions will be + * required to shift the results for further operations. Had the 32 bit data structure been + * aligned in memory to fit completely inside of addresses 0-7 or 8-15, it could have been read + * in just one read instruction. Thus by aligning data to the CPU's memory access granularity, + * one can improve performance. + * + * ALGORITHM: + * 1. Write a wrapper around the built in malloc() and free() functionality in C that + * takes into account the alignment issues discussed above. + * 2. The core feature to implement is returning a memory address whose value is + * divisible by the alignment parameter of the function and which points to the required + * number of bytes. + * + * + */ + #pragma once +namespace chapter_12 { + void* alignedMalloc(size_t required_bytes, size_t alignment) { + return nullptr; + } + + void alignedFree(void* pointer) { + } +} diff --git a/cpp_solutions/misc_exercises/integralImage.cpp b/cpp_solutions/misc_exercises/integralImage.cpp index ac0a789..2a21af0 100644 --- a/cpp_solutions/misc_exercises/integralImage.cpp +++ b/cpp_solutions/misc_exercises/integralImage.cpp @@ -1,5 +1,4 @@ #include "integralImage.h" -#include namespace misc{ Eigen::MatrixXd makeIntegralImage(const Eigen::MatrixXd& input){ From 9bd32bff50b37e25d4c63e250ffed3992975b5ad Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 11 Aug 2019 19:06:39 -0700 Subject: [PATCH 152/176] update completion --- README.md | 6 +++--- cpp_solutions/chapter_12_cpp/chapter_12_includes.h | 1 - cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) delete mode 100644 cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h diff --git a/README.md b/README.md index 600e8f3..5758f1a 100644 --- a/README.md +++ b/README.md @@ -33,14 +33,14 @@ reference and contribute solutions with confidence. 9. Chapter 9 - System Design and Scalability: `0 / 8` complete. 10. [Chapter 10 - Sorting and Searching](cpp_solutions/chapter_10_sorting_and_searching): `10 / 11` complete. 11. Chapter 11 - Testing: `0 / 6` complete. -12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `11 / 11` +12. [Chapter 12 - C and C++](cpp_solutions/chapter_12_cpp): `10 / 11` 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `5 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. -C++ Total: `73` solutions complete. +C++ Total: `72` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +64,7 @@ C++ Total: `73` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `129` unique solutions complete. +##### Grand Total: `128` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h index bce0f05..9251230 100644 --- a/cpp_solutions/chapter_12_cpp/chapter_12_includes.h +++ b/cpp_solutions/chapter_12_cpp/chapter_12_includes.h @@ -5,4 +5,3 @@ #include "problem_12_08_copyNode.h" #include "problem_12_09_smartPointer.h" #include "problem_12_10_alignedMalloc.h" -#include "problem_12_11_malloc2D.h" diff --git a/cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h b/cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h deleted file mode 100644 index 45dcbb0..0000000 --- a/cpp_solutions/chapter_12_cpp/problem_12_11_malloc2D.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - - From c4503505edd275b2864f5bc9042bb3dbd77d13c9 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 11 Aug 2019 20:00:48 -0700 Subject: [PATCH 153/176] implement 12.10 --- .../problem_12_10_alignedMalloc.h | 17 ++++++++++++----- tests.cpp | 14 +++++++++----- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h b/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h index 2f764a2..78bbd29 100644 --- a/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h +++ b/cpp_solutions/chapter_12_cpp/problem_12_10_alignedMalloc.h @@ -25,18 +25,25 @@ * 2. The core feature to implement is returning a memory address whose value is * divisible by the alignment parameter of the function and which points to the required * number of bytes. - * - * */ #pragma once namespace chapter_12 { void* alignedMalloc(size_t required_bytes, size_t alignment) { - return nullptr; + // allocate enough space for required bytes, pointer to full memory block that enables alignedFree(), and alignment space + void* p1; // initial block + void* p2; // aligned block inside initial block + int offset = alignment - 1 + sizeof(void*); // offset to achieve alignment - includes size of extra pointer + p1 = (void*)malloc(required_bytes + offset); + if (p1 == NULL) return NULL; // handle case where user tries to allocate more memory than they have + p2 = (void*)(((size_t)(p1) + offset) & ~(alignment - 1)); + ((void**)p2)[-1] = p1; + return p2; } - void alignedFree(void* pointer) { - + void alignedFree(void* p2) { + void* p1 = ((void**)p2)[-1]; + free(p1); } } diff --git a/tests.cpp b/tests.cpp index 613d91e..f3c322b 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1453,11 +1453,15 @@ TEST_CASE("Chapter 12 - Problem 09 - smartPointer()", "test"){ } TEST_CASE("Chapter 12 - Problem 10 - alignedMalloc()", "test"){ - -} - -TEST_CASE("Chapter 12 - Problem 11 - malloc2D()", "test"){ - + int* intPointer = (int*) chapter_12::alignedMalloc(sizeof(int), 128); + double* doublePointer = (double*) chapter_12::alignedMalloc(sizeof(double), 32); + long* longPointer = (long*) chapter_12::alignedMalloc(sizeof(long), 64); + REQUIRE(reinterpret_cast(intPointer) % 128 == 0); + REQUIRE(reinterpret_cast(doublePointer) % 32 == 0); + REQUIRE(reinterpret_cast(longPointer) % 64 == 0); + chapter_12::alignedFree(intPointer); + chapter_12::alignedFree(doublePointer); + chapter_12::alignedFree(longPointer); } TEST_CASE("Chapter 16 - Problem 02 - wordFrequencies()") { From 02115d83d250d353d4eb09f111027e208b75065c Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 12 Aug 2019 14:15:22 -0700 Subject: [PATCH 154/176] switch integral image implementation to shared pointers --- .../misc_exercises/integralImage.cpp | 27 ------------------- cpp_solutions/misc_exercises/integralImage.h | 8 ------ 2 files changed, 35 deletions(-) delete mode 100644 cpp_solutions/misc_exercises/integralImage.cpp delete mode 100644 cpp_solutions/misc_exercises/integralImage.h diff --git a/cpp_solutions/misc_exercises/integralImage.cpp b/cpp_solutions/misc_exercises/integralImage.cpp deleted file mode 100644 index 2a21af0..0000000 --- a/cpp_solutions/misc_exercises/integralImage.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "integralImage.h" - -namespace misc{ - Eigen::MatrixXd makeIntegralImage(const Eigen::MatrixXd& input){ - Eigen::MatrixXd output(input.rows(), input.cols()); - output << Eigen::MatrixXd::Zero(input.rows(), input.cols()); - for (int r = 0; r < input.rows(); r++){ - for (int c = 0; c < input.cols(); c++){ - if (r == 0 && c == 0){ - output(r, c) = input(r, c); - } else if (r == 0) { - output(r, c) = input(r, c) + output(r, c - 1); - } else if (c == 0){ - output(r, c) = input(r, c) + output(r - 1, c); - } else { - output(r, c) = input(r, c) + output(r, c - 1) + output(r - 1, c) - output(r - 1, c - 1); - } - } - } - return output; - } - - Eigen::MatrixXd boxFilter(const Eigen::MatrixXd& input, int k){ - Eigen::MatrixXd output = Eigen::MatrixXd::Zero(input.rows(), input.cols()); - return output; - } -} diff --git a/cpp_solutions/misc_exercises/integralImage.h b/cpp_solutions/misc_exercises/integralImage.h deleted file mode 100644 index 96116db..0000000 --- a/cpp_solutions/misc_exercises/integralImage.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once -#include - -namespace misc{ - Eigen::MatrixXd makeIntegralImage(const Eigen::MatrixXd& input); - Eigen::MatrixXd boxFilter(const Eigen::MatrixXd& input, int k); // assume k x k box filter with all values = to 1 -} - From f268dd31693976df022878c26d6943afeedf6ac3 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 12 Aug 2019 14:15:55 -0700 Subject: [PATCH 155/176] switch integral image implementation to shared pointers --- .../misc_exercises/misc_01_integralImage.cpp | 22 +++++++++++++++++++ .../misc_exercises/misc_01_integralImage.h | 12 ++++++++++ 2 files changed, 34 insertions(+) create mode 100644 cpp_solutions/misc_exercises/misc_01_integralImage.cpp create mode 100644 cpp_solutions/misc_exercises/misc_01_integralImage.h diff --git a/cpp_solutions/misc_exercises/misc_01_integralImage.cpp b/cpp_solutions/misc_exercises/misc_01_integralImage.cpp new file mode 100644 index 0000000..ee48cff --- /dev/null +++ b/cpp_solutions/misc_exercises/misc_01_integralImage.cpp @@ -0,0 +1,22 @@ +#include "misc_01_integralImage.h" + +namespace misc{ + std::shared_ptr makeIntegralImage(const Eigen::MatrixXd& input){ + auto output = std::shared_ptr(new Eigen::MatrixXd(input.rows(), input.cols())); + (*output) << Eigen::MatrixXd::Zero(input.rows(), input.cols()); + for (int r = 0; r < input.rows(); r++){ + for (int c = 0; c < input.cols(); c++){ + if (r == 0 && c == 0){ + (*output)(r, c) = input(r, c); + } else if (r == 0) { + (*output)(r, c) = input(r, c) + (*output)(r, c - 1); + } else if (c == 0){ + (*output)(r, c) = input(r, c) + (*output)(r - 1, c); + } else { + (*output)(r, c) = input(r, c) + (*output)(r, c - 1) + (*output)(r - 1, c) - (*output)(r - 1, c - 1); + } + } + } + return output; + } +} diff --git a/cpp_solutions/misc_exercises/misc_01_integralImage.h b/cpp_solutions/misc_exercises/misc_01_integralImage.h new file mode 100644 index 0000000..f880821 --- /dev/null +++ b/cpp_solutions/misc_exercises/misc_01_integralImage.h @@ -0,0 +1,12 @@ +/* + * PROBLEM: + * Implement integral image computation as explained here: + * https://en.wikipedia.org/wiki/Summed-area_table + */ + +#pragma once +#include + +namespace misc{ + std::shared_ptr makeIntegralImage(const Eigen::MatrixXd& input); +} From bdc03175a540a882b553793b160516a8c2fc3677 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 12 Aug 2019 14:19:02 -0700 Subject: [PATCH 156/176] implement kernel convolution --- CMakeLists.txt | 4 ++- README.md | 5 +-- .../misc_02_kernelConvolution.cpp | 32 +++++++++++++++++++ .../misc_02_kernelConvolution.h | 11 +++++++ cpp_solutions/misc_exercises/misc_includes.h | 3 +- tests.cpp | 22 +++++++++++-- 6 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp create mode 100644 cpp_solutions/misc_exercises/misc_02_kernelConvolution.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4499f69..f2f5cc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,8 @@ set(SOURCE_FILES cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp - cpp_solutions/misc_exercises/integralImage.cpp) + # MISC + cpp_solutions/misc_exercises/misc_01_integralImage.cpp + cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp) # create executable add_executable(tests ${SOURCE_FILES}) diff --git a/README.md b/README.md index 5758f1a..7cb64af 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,9 @@ reference and contribute solutions with confidence. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. 16. Chapter 16 - Moderate: `5 / 26` complete. 17. Chapter 17 - Hard: `0 / 26` complete. +18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `72` solutions complete. +C++ Total: `74` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -64,7 +65,7 @@ C++ Total: `72` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `128` unique solutions complete. +##### Grand Total: `130` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp b/cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp new file mode 100644 index 0000000..0aca188 --- /dev/null +++ b/cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp @@ -0,0 +1,32 @@ +#include "misc_02_kernelConvolution.h" + +namespace misc { + std::shared_ptr kernelConvolution(const Eigen::MatrixXd& image, const Eigen::MatrixXd& kernel){ + std::shared_ptr output = std::shared_ptr(new Eigen::MatrixXd(image)); + // support only odd width square kernels + if (kernel.rows() != kernel.cols() || kernel.rows() % 2 != 1) { + return output; + } + // perform convolution computation + const int kernelHalfWidth = kernel.rows() / 2; + for (int imageR = 0; imageR < image.rows(); imageR ++) { + for (int imageC = 0; imageC < image.cols(); imageC++) { + const int startR = imageR - kernelHalfWidth; + const int startC = imageC - kernelHalfWidth; + double accumulator = 0.0f; + for (int kernelR = 0; kernelR < kernel.rows(); kernelR ++) { + for (int kernelC = 0; kernelC < kernel.cols(); kernelC ++) { + const int accumulatorR = startR + kernelR; + const int accumulatorC = startC + kernelC; + // check bounds conditions - implicitly this means image is zero padded + if (accumulatorR >= 0 && accumulatorR < image.rows() && accumulatorC >= 0 && accumulatorC < image.cols()) { + accumulator += image(accumulatorR, accumulatorC) * kernel(kernelR, kernelC); + } + } + } + (*output)(imageR, imageC) = accumulator; + } + } + return output; + } +} diff --git a/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h b/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h new file mode 100644 index 0000000..8cfd5b7 --- /dev/null +++ b/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h @@ -0,0 +1,11 @@ +/* + * PROBLEM: + * Implement matrix - kernel convolution as for image processing as explained here: + * https://docs.gimp.org/2.8/en/plug-in-convmatrix.html + */ +#pragma once +#include + +namespace misc { + std::shared_ptr kernelConvolution(const Eigen::MatrixXd& image, const Eigen::MatrixXd& kernel); +} diff --git a/cpp_solutions/misc_exercises/misc_includes.h b/cpp_solutions/misc_exercises/misc_includes.h index cc909e2..e35e4cd 100644 --- a/cpp_solutions/misc_exercises/misc_includes.h +++ b/cpp_solutions/misc_exercises/misc_includes.h @@ -1,2 +1,3 @@ #pragma once -#include "integralImage.h" +#include "misc_01_integralImage.h" +#include "misc_02_kernelConvolution.h" diff --git a/tests.cpp b/tests.cpp index f3c322b..144c94e 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1579,11 +1579,29 @@ TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16; - REQUIRE(output1.isApprox(misc::makeIntegralImage(input1))); + REQUIRE(output1.isApprox(*misc::makeIntegralImage(input1))); Eigen::MatrixXd output2(4, 4); output2 << 1, 3, 6, 10, 3, 9, 18, 30, 6, 18, 36, 60, 10, 30, 60, 100; - REQUIRE(output2.isApprox(misc::makeIntegralImage(output1))); + REQUIRE(output2.isApprox(*misc::makeIntegralImage(output1))); +} + +TEST_CASE("Misc Exercises - kernelConvolution()", "test") { + Eigen::MatrixXd input1(4,4); + input1 << 0, 0, 0, 1, + 0, 1, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0; + Eigen::MatrixXd kernel1(3, 3); + kernel1 << 0, 1, 0, + 1, 1, 1, + 0, 1, 0; + Eigen::MatrixXd output1(4, 4); + output1 << 0, 1, 1, 1, + 1, 1, 1, 1, + 0, 1, 0, 0, + 0, 0, 0, 0; + REQUIRE(output1.isApprox(*misc::kernelConvolution(input1, kernel1))); } From 9524e0df9f4ecf9f5d97456e948c798c7c0a968f Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 12 Aug 2019 14:21:36 -0700 Subject: [PATCH 157/176] include memory header for shared_ptr in GCC? --- cpp_solutions/misc_exercises/misc_01_integralImage.h | 1 + cpp_solutions/misc_exercises/misc_02_kernelConvolution.h | 1 + 2 files changed, 2 insertions(+) diff --git a/cpp_solutions/misc_exercises/misc_01_integralImage.h b/cpp_solutions/misc_exercises/misc_01_integralImage.h index f880821..f29315d 100644 --- a/cpp_solutions/misc_exercises/misc_01_integralImage.h +++ b/cpp_solutions/misc_exercises/misc_01_integralImage.h @@ -6,6 +6,7 @@ #pragma once #include +#include namespace misc{ std::shared_ptr makeIntegralImage(const Eigen::MatrixXd& input); diff --git a/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h b/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h index 8cfd5b7..cf48869 100644 --- a/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h +++ b/cpp_solutions/misc_exercises/misc_02_kernelConvolution.h @@ -5,6 +5,7 @@ */ #pragma once #include +#include namespace misc { std::shared_ptr kernelConvolution(const Eigen::MatrixXd& image, const Eigen::MatrixXd& kernel); From 51db8f11818ee8174cbad8352e1961b261a03985 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 22 Sep 2019 22:11:50 -0700 Subject: [PATCH 158/176] implement 17.21 C++ --- README.md | 8 ++++---- tests.cpp | 12 +++++++++++- tests.py | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 7cb64af..aa64971 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. Chapter 16 - Moderate: `5 / 26` complete. -17. Chapter 17 - Hard: `0 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `5 / 26` complete. +17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `74` solutions complete. +C++ Total: `75` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -65,7 +65,7 @@ C++ Total: `74` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `130` unique solutions complete. +##### Grand Total: `131` unique solutions complete. ### Building: #### Mac: diff --git a/tests.cpp b/tests.cpp index 144c94e..c303b4f 100644 --- a/tests.cpp +++ b/tests.cpp @@ -11,6 +11,7 @@ #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/chapter_16_moderate/chapter_16_includes.h" +#include "cpp_solutions/chapter_17_hard/chapter_17_includes.h" #include "cpp_solutions/misc_exercises/misc_includes.h" #define CATCH_CONFIG_MAIN #include "cpp_solutions/third_party/Catch/include/catch.hpp" @@ -1552,7 +1553,7 @@ TEST_CASE("Chapter 16 - Problem 06 - smallestDifference()") { REQUIRE(std::numeric_limits::max() == chapter_16::smallestDifference(example6, example6)); } -TEST_CASE("Chapter 16 - Problem 10 - livingPeople()") { +TEST_CASE("Chapter 16 - Problem 10 - livingPeople()", "test") { std::vector people1 = { chapter_16::Person(1930, 2000), chapter_16::Person(1940, 2010), @@ -1568,6 +1569,15 @@ TEST_CASE("Chapter 16 - Problem 10 - livingPeople()") { REQUIRE(1900 == livingPeople(people2, 1900, 2020)); }; +TEST_CASE("Chapter 17 - Problem 21 - histogramVolume()", "test") { + const std::vector histogram1 = {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0}; + const std::vector histogram2 = {5, 0, 0, 0, 1}; + const std::vector histogram3 = {0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1}; // test case from leetcode problem https://leetcode.com/problems/trapping-rain-water/ + REQUIRE(chapter_17::histogramVolume(histogram1) == 46); + REQUIRE(chapter_17::histogramVolume(histogram2) == 3); + REQUIRE(chapter_17::histogramVolume(histogram3) == 6); +} + TEST_CASE("Misc Exercises - makeIntegralImage()", "test"){ Eigen::MatrixXd input1(4, 4); input1 << 1, 1, 1, 1, diff --git a/tests.py b/tests.py index aae27c8..e07dd21 100644 --- a/tests.py +++ b/tests.py @@ -1179,8 +1179,10 @@ def test_problem_17_15(self): def test_problem_17_21(self): histogram1 = [0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0] histogram2 = [5, 0, 0, 0, 1] + histogram3 = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1] # test case from leetcode problem https://leetcode.com/problems/trapping-rain-water/ self.assertEqual(p_17_21.histogram_volume(histogram1), 46) self.assertEqual(p_17_21.histogram_volume(histogram2), 3) + self.assertEqual(p_17_21.histogram_volume(histogram3), 6) def tearDown(self): pass From 09b1aa9c8fe154ea9758766b896b16402e76ebee Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 22 Sep 2019 22:35:42 -0700 Subject: [PATCH 159/176] add missing files for 17.21 C++ --- .../chapter_17_hard/chapter_17_includes.h | 3 ++ .../problem_17_21_histogramVolume.h | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 cpp_solutions/chapter_17_hard/chapter_17_includes.h create mode 100644 cpp_solutions/chapter_17_hard/problem_17_21_histogramVolume.h diff --git a/cpp_solutions/chapter_17_hard/chapter_17_includes.h b/cpp_solutions/chapter_17_hard/chapter_17_includes.h new file mode 100644 index 0000000..dc247a6 --- /dev/null +++ b/cpp_solutions/chapter_17_hard/chapter_17_includes.h @@ -0,0 +1,3 @@ +#pragma once + +#include "problem_17_21_histogramVolume.h" diff --git a/cpp_solutions/chapter_17_hard/problem_17_21_histogramVolume.h b/cpp_solutions/chapter_17_hard/problem_17_21_histogramVolume.h new file mode 100644 index 0000000..31ee57f --- /dev/null +++ b/cpp_solutions/chapter_17_hard/problem_17_21_histogramVolume.h @@ -0,0 +1,47 @@ +/* +PROBLEM: +Imagine a histogram (bar graph). Design an algorithm to compute the volume of water +it could hold if someone poured water across the top. You can assume that each histogram +bar has width 1. + +ALGORITHM: +heights [0,1,0,2,1,0,1,3,2,1,2,1] +maxFromLeft [0,1,1,2,2,2,2,3,3,3,3,3] +maxFromRight[3,3,3,3,3,3,3,3,2,2,2,1] + +We observe that the accumulated water at position X is equal to min(max_to_left, max_to_right) - height(X) + +TIME COMPLEXITY: O(N) +SPACE COMPLEXITY: O(N) +*/ + +#pragma once + +#include +#include + +namespace chapter_17 { + template + T histogramVolume(const std::vector& histogram) { + std::vector maxHeightsToLeft(histogram.size(), 0); + std::vector maxHeightsToRight(histogram.size(), 0); + int maxHeightToLeft = 0; + int maxHeightToRight = 0; + int totalAccumulation = 0; + // compute maxFromLeft for each position + for (int i = 0; i < histogram.size(); i++) { + if (histogram[i] > maxHeightToLeft) maxHeightToLeft = histogram[i]; + maxHeightsToLeft[i] = maxHeightToLeft; + } + // compute maxFromRight for each position + for (int i = histogram.size() - 1; i >= 0; i--) { + if (histogram[i] > maxHeightToRight) maxHeightToRight = histogram[i]; + maxHeightsToRight[i] = maxHeightToRight; + } + // compute water accumulation at each position + for (int i = 0; i < histogram.size(); i++) { + totalAccumulation += (std::min(maxHeightsToLeft[i], maxHeightsToRight[i]) - histogram[i]); + } + return totalAccumulation; + } +} \ No newline at end of file From 5c5c7c6f9eea657e6d8641ae25d393975dd31386 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 10 Nov 2019 22:48:44 -0800 Subject: [PATCH 160/176] implement and test 16.1 C++ --- README.md | 6 +++--- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_01_swapNumbers.h | 13 +++++++++++++ tests.cpp | 18 ++++++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h diff --git a/README.md b/README.md index aa64971..d3b4d7a 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `5 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `6 / 26` complete. 17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `75` solutions complete. +C++ Total: `76` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -65,7 +65,7 @@ C++ Total: `75` solutions complete. Python Total: `56` solutions complete. -##### Grand Total: `131` unique solutions complete. +##### Grand Total: `132` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index 60a73a8..d6be8dc 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -1,5 +1,6 @@ #pragma once +#include "problem_16_01_swapNumbers.h" #include "problem_16_02_wordFrequencies.h" #include "problem_16_03_intersection.h" #include "problem_16_05_factorialZeros.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h b/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h new file mode 100644 index 0000000..dbdcc8e --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h @@ -0,0 +1,13 @@ +#pragma once + +namespace chapter_16 { + template + void swapNumbers(T& a, T& b) { + static_assert(std::is_arithmetic::value, "T must be an arithmetic type"); + // ex: a=5 b=9 + a = a + b; // 5 + 9 = 14 + b = a - b; // 14 - 9 = 5 + a = a - b; // 14 - 5 = 9 + // ex: a=9 b=5 + } +} \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index c303b4f..12ffb4c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1465,6 +1465,24 @@ TEST_CASE("Chapter 12 - Problem 10 - alignedMalloc()", "test"){ chapter_12::alignedFree(longPointer); } +TEST_CASE("Chapter 16 - Problem 01 - swapNumbers()") { + int a = 5; + int b = 9; + chapter_16::swapNumbers(a, b); + REQUIRE(a == 9); + REQUIRE(b == 5); + float c = 5.1f; + float d = -9.6f; + chapter_16::swapNumbers(c, d); + REQUIRE(c == -9.6f); + REQUIRE(d == 5.1f); + long e = -50435; + long f = -89048; + chapter_16::swapNumbers(e, f); + REQUIRE(e == -89048); + REQUIRE(f == -50435); +} + TEST_CASE("Chapter 16 - Problem 02 - wordFrequencies()") { std::vector book = {"Invictus\n", "By", From 6631f916c508dddb15cfc1f2b9c2e5f445321614 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 23 Dec 2019 15:38:23 -0800 Subject: [PATCH 161/176] implement 16.1 python --- .../chapter_16_moderate/problem_16_01_swapNumbers.h | 4 ++++ .../problem_16_01_swap_numbers.py | 12 ++++++++++++ tests.py | 12 ++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 python_solutions/chapter_16_moderate/problem_16_01_swap_numbers.py diff --git a/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h b/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h index dbdcc8e..7cc2e0c 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_01_swapNumbers.h @@ -1,3 +1,7 @@ +/* + * Write a function to swap a number in place (that is, without temporary variables) . + */ + #pragma once namespace chapter_16 { diff --git a/python_solutions/chapter_16_moderate/problem_16_01_swap_numbers.py b/python_solutions/chapter_16_moderate/problem_16_01_swap_numbers.py new file mode 100644 index 0000000..173cce5 --- /dev/null +++ b/python_solutions/chapter_16_moderate/problem_16_01_swap_numbers.py @@ -0,0 +1,12 @@ +""" +Write a function to swap a number in place (that is, without temporary variables) . +""" + + +def swap_numbers(pair_ab): + if not len(pair_ab) == 2: + return + # assume a = 9; b = 5 + pair_ab[0] = pair_ab[1] - pair_ab[0] # a = -4; b = 5 + pair_ab[1] = pair_ab[1] - pair_ab[0] # a = -4; b = 9 + pair_ab[0] = pair_ab[1] + pair_ab[0] # a = 5; b = 9 diff --git a/tests.py b/tests.py index e07dd21..59c105a 100644 --- a/tests.py +++ b/tests.py @@ -61,6 +61,7 @@ from python_solutions.chapter_10_sorting_and_searching import merge_sort from python_solutions.chapter_10_sorting_and_searching import quick_sort from python_solutions.chapter_10_sorting_and_searching import problem_10_01_sorted_merge as p_10_1 +from python_solutions.chapter_16_moderate import problem_16_01_swap_numbers as p_16_01 from python_solutions.chapter_16_moderate import problem_16_03_intersection as p_16_03 from python_solutions.chapter_17_hard import problem_17_10_majority_element as p_17_10 from python_solutions.chapter_17_hard import problem_17_15_longest_combination as p_17_15 @@ -1140,6 +1141,17 @@ def test_problem_10_01(self): p_10_1.sorted_merge(D, lastD, E, lastE) self.assertEqual(D, C) + def test_problem_16_01(self): + pair_ab = [5, 9] + p_16_01.swap_numbers(pair_ab) + self.assertEqual(pair_ab, [9, 5]) + pair_cd = [5.1, -9.6] + p_16_01.swap_numbers(pair_cd) + self.assertEqual(pair_cd, [-9.6, 5.1]) + pair_ef = [-50435, -89048] + p_16_01.swap_numbers(pair_ef) + self.assertEqual(pair_ef, [-89048, -50435]) + def test_problem_16_03(self): segment1 = p_16_03.LineSegment(p_16_03.Point2(5, 5), p_16_03.Point2(0, 0)) segment2 = p_16_03.LineSegment(p_16_03.Point2(0, 3), p_16_03.Point2(3, 0)) From fcf3eff7043479b8293739717938ffdfcdf20357 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Thu, 2 Jan 2020 12:16:36 -0800 Subject: [PATCH 162/176] implement most complete solution for 16.4 in C++ --- CMakeLists.txt | 1 + .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_04_ticTacWin.cpp | 90 +++++++++++++++++++ .../problem_16_04_ticTacWin.h | 27 ++++++ tests.cpp | 76 ++++++++++++++++ 5 files changed, 195 insertions(+) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f2f5cc0..a0f12d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ set(SOURCE_FILES # CHAPTER 16 cpp_solutions/chapter_16_moderate/problem_16_02_wordFrequencies.cpp cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp + cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp # MISC diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index d6be8dc..9a472c4 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -3,6 +3,7 @@ #include "problem_16_01_swapNumbers.h" #include "problem_16_02_wordFrequencies.h" #include "problem_16_03_intersection.h" +#include "problem_16_04_ticTacWin.h" #include "problem_16_05_factorialZeros.h" #include "problem_16_06_smallestDifference.h" #include "problem_16_10_livingPeople.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp new file mode 100644 index 0000000..067f4f9 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp @@ -0,0 +1,90 @@ +#include "problem_16_04_ticTacWin.h" +namespace chapter_16 { + TTTDatabase::TTTDatabase() { + // build database + buildDB(); + } + + bool TTTDatabase::ticTacWin(const char *board) { + // check board correctness by looking up in DB + return winsLookup(board); + } + + uint16_t TTTDatabase::board2Hash(const char* board) const { + // hashing function: + // V0 * 3^0 + V1* 3^1 + V2 * 3^2 ... + V8 * 3^8 + uint16_t hash = 0; + for (int i = 0; i < boardLength; i++) { + uint16_t V = 0; // board[i] = '_' or something else + if (board[i] == 'X') { + V = 2; + } + else if (board[i] == 'O') { + V = 1; + } + hash += V * std::pow(3, i); + } + return hash; + } + + bool TTTDatabase::winsLookup(const char* board) const { + // determine if this board is a winning board + uint16_t hash = board2Hash(board); + return database.count(hash) ? database.at(hash) : false; + } + + uint8_t TTTDatabase::linearIndex(uint8_t R, uint8_t C) const { + return R*3 + C; + } + + bool TTTDatabase::wins(const char* board) const { + // check rows + for (int r = 0; r < 3; r++) { + uint8_t index = linearIndex(r, 0); + char first = board[index]; + char second = board[index + 1]; + char third = board[index + 2]; + if ((first == 'X' || first == 'O') && first == second && second == third) return true; + } + // check cols + for (int c = 0; c < 3; c++) { + uint8_t index = linearIndex(0, c); + char first = board[index]; + char second = board[index + 3]; + char third = board[index + 6]; + if ((first == 'X' || first == 'O') && first == second && second == third) return true; + } + // check diags + // LR downward diag + char first = board[0]; + char second = board[4]; + char third = board[8]; + if ((first == 'X' || first == 'O') && first == second && second == third) return true; + // LR upward diag + first = board[6]; + second = board[4]; + third = board[2]; + return (first == 'X' || first == 'O') && first == second && second == third; + } + + void TTTDatabase::updateDB(const char* board) { + bool win = wins(&board[0]); + uint16_t hash = board2Hash(&board[0]); + database[hash] = win; + } + + void TTTDatabase::permuteAndCheckBoard(char* board, uint8_t index) { + if (index >= boardLength) return; + char states[3] = {'_', 'O', 'X'}; + for (auto state : states) { + board[index] = state; + updateDB(&board[0]); + permuteAndCheckBoard(board, index+1); + } + } + + void TTTDatabase::buildDB(){ + char board[9] = {0}; + permuteAndCheckBoard(&board[0], 0); + } +} diff --git a/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h new file mode 100644 index 0000000..ad43755 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h @@ -0,0 +1,27 @@ +#pragma once +#include + +namespace chapter_16 { + class TTTDatabase { + private: + /* + * A TTT board has 9 positions with 3 possible values at each position: + * blank, X, or O. Thus, all possible TTT boards can be represented by + * 3^9 = 19683 hash values. Thus we only need to store true or false + * for 19683 different numbers which fits in a uint16_t whose max value is + * 2^16 - 1 = 65536 - 1 = 65535. The range of the key integers is 0 - 19682. + */ + std::unordered_map database; + const uint16_t boardLength = 9; + uint16_t board2Hash(const char* board) const; + bool winsLookup(const char* board) const; + uint8_t linearIndex(uint8_t R, uint8_t C) const; + bool wins(const char* board) const; + void updateDB(const char* board); + void permuteAndCheckBoard(char* board, uint8_t index); + void buildDB(); + public: + TTTDatabase(); + bool ticTacWin(const char* board); + }; +} // namespace chapter_16 diff --git a/tests.cpp b/tests.cpp index 12ffb4c..6529368 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1540,6 +1540,82 @@ TEST_CASE("Chapter 16 - Problem 03 - intersection()") { delete actual_p4; } +TEST_CASE("Chapter 16 - Problem 04 - ticTacWin()") { + // store data in row major order + char board0[9] = {'O', 'O', 'X', + 'O', 'X', '_', + 'X', '_', '_'}; + char board1[9] = {'_', '_', 'O', + '_', 'X', 'O', + 'X', 'X', 'O'}; + // this is a board that violates TTT rules but we still judge it as a winner + char board2[9] = {'X', 'X', 'X', + 'O', 'O', 'O', + 'X', 'O', 'O'}; + // we judge a character that is not X or O as a blank + char board3[9] = {'_', '_', 'X', + '_', '_', 'O', + '_', 'Z', '_'}; + // complete garbage board + char board4[9] = {'a', 'l', 'e', + 'x', 'a', 'l', + 'e', 'x', 'a'}; + char board5[9] = {'O', 'O', 'X', + 'X', 'X', 'X', + 'X', 'O', 'O'}; + char board6[9] = {'X', 'X', 'X', + 'O', 'O', 'X', + 'X', 'O', 'O'}; + char board7[9] = {'O', 'O', 'X', + 'X', 'O', 'O', + 'X', 'X', 'X'}; + char board8[9] = {'X', 'O', 'X', + 'X', 'O', 'X', + 'O', 'X', 'O'}; + char board9[9] = {'O', 'X', 'O', + 'O', 'X', 'X', + 'O', 'O', 'X'}; + char board10[9] = {'X', 'O', 'O', + 'X', 'O', 'X', + 'O', 'O', 'X'}; + char board11[9] = {'X', 'O', 'O', + 'X', 'X', 'O', + 'O', 'X', 'O'}; + char board12[9] = {'X', 'X', 'O', + 'X', 'O', '_', + 'O', '_', '_'}; + char board13[9] = {'X', 'O', 'O', + 'X', 'X', '_', + 'O', '_', 'X'}; + char board14[9] = {'_', '_', 'X', + '_', '_', 'O', + '_', 'X', '_'}; + char board15[9] = {'X', '_', 'X', + '_', 'O', 'O', + 'X', 'X', '_'}; + char board16[9] = {'X', 'O', '_', + 'O', 'X', 'O', + 'X', 'X', '_'}; + auto database = chapter_16::TTTDatabase(); + REQUIRE(database.ticTacWin(&board0[0]) == true); + REQUIRE(database.ticTacWin(&board1[0]) == true); + REQUIRE(database.ticTacWin(&board2[0]) == true); + REQUIRE(database.ticTacWin(&board3[0]) == false); + REQUIRE(database.ticTacWin(&board4[0]) == false); + REQUIRE(database.ticTacWin(&board5[0]) == true); + REQUIRE(database.ticTacWin(&board6[0]) == true); + REQUIRE(database.ticTacWin(&board7[0]) == true); + REQUIRE(database.ticTacWin(&board8[0]) == false); + REQUIRE(database.ticTacWin(&board9[0]) == true); + REQUIRE(database.ticTacWin(&board10[0]) == true); + REQUIRE(database.ticTacWin(&board11[0]) == true); + REQUIRE(database.ticTacWin(&board12[0]) == true); + REQUIRE(database.ticTacWin(&board13[0]) == true); + REQUIRE(database.ticTacWin(&board14[0]) == false); + REQUIRE(database.ticTacWin(&board15[0]) == false); + REQUIRE(database.ticTacWin(&board16[0]) == false); +} + TEST_CASE("Chapter 16 - Problem 05 - factorialZeros()") { REQUIRE(-1 == chapter_16::factorialZeros(-1)); REQUIRE(0 == chapter_16::factorialZeros(1)); From 33282cdc63a14173bf55696d3c3c832b21996a77 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 3 Jan 2020 17:23:02 -0800 Subject: [PATCH 163/176] include cmath for std::pow to fix GCC compilation --- cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp index 067f4f9..b6566b3 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp +++ b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp @@ -1,4 +1,6 @@ #include "problem_16_04_ticTacWin.h" +#include + namespace chapter_16 { TTTDatabase::TTTDatabase() { // build database From f49efbc9e078b60da1419426aabc5fdf848e1103 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 3 Jan 2020 17:26:46 -0800 Subject: [PATCH 164/176] update problem completion on readme --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d3b4d7a..c0c51a5 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `6 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `7 / 26` complete. 17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `76` solutions complete. +C++ Total: `77` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -60,12 +60,12 @@ C++ Total: `76` solutions complete. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: N/A -16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `1 / 26` complete. +16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `2 / 26` complete. 17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. -Python Total: `56` solutions complete. +Python Total: `57` solutions complete. -##### Grand Total: `132` unique solutions complete. +##### Grand Total: `134` unique solutions complete. ### Building: #### Mac: From 2f94060a357561c3bdd29b62144902d343f5eaf5 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 3 Jan 2020 17:42:21 -0800 Subject: [PATCH 165/176] add essay for 16.4 C++ --- .../problem_16_04_ticTacWin.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h index ad43755..6edb436 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.h @@ -1,3 +1,20 @@ +/* PROBLEM: + * Design an algorithm to figure out if someone has won a game of tic-tac-toe. + * + * SOLUTION: + * 1. An algorithm to check if a TTT board is a winning board. Check all rows, all cols, and both diagonals for equality. + * 2. An algorithm to store the wiining-ness of all possible TTT boards in a hash map. Generate every possible TTT board + * using a recursion tree that assigns one of three possible cell states (blank, X, or O) to one of 9 cells at each level + * of the recursion. + * 3. A class that populates the hash map in (2) upon construction and only queries the hash map when + * asked to determine if a TTT board is a winning board. + * + * SPACE / TIME: + * If we assume that there will be N calls to determine if a TTT board is a winning board, each call will require O(1) + * time and O(1) space will be required to store the hash table. + * + */ + #pragma once #include From 99dc32ccf7eace3c26d0f9b9bd5fe27c887dfce6 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Fri, 3 Jan 2020 18:31:58 -0800 Subject: [PATCH 166/176] implement 16.11 C++ --- CMakeLists.txt | 1 + README.md | 6 ++-- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_11_divingBoard.cpp | 12 +++++++ .../problem_16_11_divingBoard.h | 32 +++++++++++++++++++ tests.cpp | 31 +++++++++++++++++- 6 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a0f12d1..c8b4528 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ set(SOURCE_FILES cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp + cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp # MISC cpp_solutions/misc_exercises/misc_01_integralImage.cpp cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp) diff --git a/README.md b/README.md index c0c51a5..92a9b6f 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `7 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `8 / 26` complete. 17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `77` solutions complete. +C++ Total: `78` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -65,7 +65,7 @@ C++ Total: `77` solutions complete. Python Total: `57` solutions complete. -##### Grand Total: `134` unique solutions complete. +##### Grand Total: `138` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index 9a472c4..fe20ba6 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -7,3 +7,4 @@ #include "problem_16_05_factorialZeros.h" #include "problem_16_06_smallestDifference.h" #include "problem_16_10_livingPeople.h" +#include "problem_16_11_divingBoard.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp b/cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp new file mode 100644 index 0000000..912214b --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp @@ -0,0 +1,12 @@ +#include "problem_16_11_divingBoard.h" + +namespace chapter_16 { + std::unordered_set divingBoard(int shorter, int longer, int K ) { + std::unordered_set lengths; + for (int i = 0; i <= K; i++) { + int length = i * shorter + (K - i) * longer; + if (!lengths.count(length)) lengths.insert(length); + } + return lengths; + } +} diff --git a/cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.h b/cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.h new file mode 100644 index 0000000..d95636e --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.h @@ -0,0 +1,32 @@ +/* + * PROBLEM: + * You are building a diving board by placing a bunch of planks of wood end-to-end. + * There are two types of planks, one of length shorter and one of length longer. You must use + * exactly K planks of wood. Write a method to generate all possible lengths for the diving board. + * + * SOLUTION: + * The order of the K plans doesn't matter. 3 long + 2 short planks will yield the same length + * as 2 short + 3 long planks. Thus there are K + 1 possible lengths for the diving board. + * + * For example, if K = 3: + * + * Length 1: 0 short + 3 long + * Length 2: 1 short + 2 long + * Length 3: 2 short + 1 long + * Length 4: 3 short + 0 long + * + * Thus, to solve this problem, we iterate from i = 0 to K and + * create one length for each value of i short planks and k-i long planks. + * We can get in trouble with this approach if there are duplicate lengths, + * so we add each length to an unordered_set to ensure uniqueness. + * + * TIME: O(N) + * SPACE: O(N) + */ + +#pragma once +#include + +namespace chapter_16 { + std::unordered_set divingBoard(int shorter, int longer, int K ); +} diff --git a/tests.cpp b/tests.cpp index 6529368..b324575 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1661,7 +1661,36 @@ TEST_CASE("Chapter 16 - Problem 10 - livingPeople()", "test") { REQUIRE(1982 == livingPeople(people1, 1900, 2020)); REQUIRE(1945 == livingPeople(people1, 1900, 1950)); REQUIRE(1900 == livingPeople(people2, 1900, 2020)); -}; +} + +TEST_CASE("Chapter 16 - Problem 11 - divingBoard()") { + const int short1 = 2; + const int long1 = 3; + const int K1 = 5; + const std::unordered_set lengths1Expected = {10, // 0 long + 5 short + 11, // 1 long + 4 short + 12, // 2 long + 3 short + 13, // 3 long + 2 short + 14, // 4 long + 1 short + 15}; // 5 long + 0 short + + const int short2 = 2; + const int long2 = 2; + const int K2 = 5; + const std::unordered_set lengths2Expected = {10}; + const int short3 = 1; + const int long3 = 5; + const int K3 = 5; + const std::unordered_set lengths3Expected = {5, // 0 long + 5 short + 9, // 1 long + 4 short + 13, // 2 long + 3 short + 17, // 3 long + 2 short + 21, // 4 long + 1 short + 25}; // 5 long + 0 short + REQUIRE(chapter_16::divingBoard(short1, long1, K1) == lengths1Expected); + REQUIRE(chapter_16::divingBoard(short2, long2, K2) == lengths2Expected); + REQUIRE(chapter_16::divingBoard(short3, long3, K3) == lengths3Expected); +} TEST_CASE("Chapter 17 - Problem 21 - histogramVolume()", "test") { const std::vector histogram1 = {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0}; From 747d0beb0426d34157250816fe56b502a7f17444 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 4 Jan 2020 21:08:09 -0800 Subject: [PATCH 167/176] implement 16.17 C++ --- CMakeLists.txt | 1 + README.md | 6 ++--- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_17_contiguousSequence.cpp | 16 +++++++++++++ .../problem_16_17_contiguousSequence.h | 24 +++++++++++++++++++ tests.cpp | 8 +++++++ 6 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c8b4528..374e89c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,7 @@ set(SOURCE_FILES cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp + cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp # MISC cpp_solutions/misc_exercises/misc_01_integralImage.cpp cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp) diff --git a/README.md b/README.md index 92a9b6f..55d179c 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `8 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `9 / 26` complete. 17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `78` solutions complete. +C++ Total: `79` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -65,7 +65,7 @@ C++ Total: `78` solutions complete. Python Total: `57` solutions complete. -##### Grand Total: `138` unique solutions complete. +##### Grand Total: `139` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index fe20ba6..f44c0c0 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -8,3 +8,4 @@ #include "problem_16_06_smallestDifference.h" #include "problem_16_10_livingPeople.h" #include "problem_16_11_divingBoard.h" +#include "problem_16_17_contiguousSequence.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp b/cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp new file mode 100644 index 0000000..d084edf --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp @@ -0,0 +1,16 @@ +#include "problem_16_17_contiguousSequence.h" +#include + +namespace chapter_16 { + int contiguousSequence(const std::vector& input) { + if (input.size() < 1) return 0; + int maxSum = std::numeric_limits::min(); + int sum = 0; + for (auto num : input) { + sum += num; + if (sum > maxSum) maxSum = sum; + if (sum < 0) sum = 0; + } + return maxSum; + } +} diff --git a/cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.h b/cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.h new file mode 100644 index 0000000..1bdb6d7 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.h @@ -0,0 +1,24 @@ +/* + * PROBLEM: + * You are given an array of integers (both positive and negative). Find the + * contiguous sequence with the largest sum. Return the sum. + * + * SOLUTION: + * We make some observations. If all #s are positive, then the result is the sum of the entire array. If all #s are + * negative, then the result is the single largest element. So we observe next that if the sum of a subarray is + * negative, then that subarray is guaranteed to be beaten by a single element. + * + * Thus we develop the following strategy: + * Maintain a single pointer, sum so far init at 0, max sum init at -INF. Advance pointer. Add each element to sum. + * If sum becomes negative, reset sum to 0. If sum > max sum, update max sum. Return max sum. + * + * O(N) time. + * O(1) space. + */ + +#pragma once +#include + +namespace chapter_16 { + int contiguousSequence(const std::vector& input); +} diff --git a/tests.cpp b/tests.cpp index b324575..5b2cf98 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1692,6 +1692,14 @@ TEST_CASE("Chapter 16 - Problem 11 - divingBoard()") { REQUIRE(chapter_16::divingBoard(short3, long3, K3) == lengths3Expected); } +TEST_CASE("Chapter 16 - Problem 17 - contiguousSubarray()", "test") { + REQUIRE(0 == chapter_16::contiguousSequence({})); + REQUIRE(29 == chapter_16::contiguousSequence({2, 8, 3, 2, 4, 10})); + REQUIRE(-2 == chapter_16::contiguousSequence({-2, -8, -3, -2, -4, -10})); + REQUIRE(5 == chapter_16::contiguousSequence({2, -8, 3, -2, 4, -10})); + REQUIRE(6 == chapter_16::contiguousSequence({-2, 1, -3, 4, -1, 2, 1, -5, 4})); +}; + TEST_CASE("Chapter 17 - Problem 21 - histogramVolume()", "test") { const std::vector histogram1 = {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0}; const std::vector histogram2 = {5, 0, 0, 0, 1}; From 537f1b9b48304cda3ec9e9e0aa3f140b60c5f531 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 12 Jan 2020 19:32:38 -0800 Subject: [PATCH 168/176] implement 10.7 C++ --- CMakeLists.txt | 1 + README.md | 6 +-- .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_07_numberMax.cpp | 14 +++++++ .../problem_16_07_numberMax.h | 40 +++++++++++++++++++ tests.cpp | 11 +++++ 6 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 374e89c..438ffde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,7 @@ set(SOURCE_FILES cpp_solutions/chapter_16_moderate/problem_16_03_intersection.cpp cpp_solutions/chapter_16_moderate/problem_16_04_ticTacWin.cpp cpp_solutions/chapter_16_moderate/problem_16_05_factorialZeros.cpp + cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.cpp cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp diff --git a/README.md b/README.md index 55d179c..151e4c9 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `9 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `10 / 26` complete. 17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `79` solutions complete. +C++ Total: `80` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -65,7 +65,7 @@ C++ Total: `79` solutions complete. Python Total: `57` solutions complete. -##### Grand Total: `139` unique solutions complete. +##### Grand Total: `140` unique solutions complete. ### Building: #### Mac: diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index f44c0c0..37304c0 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -6,6 +6,7 @@ #include "problem_16_04_ticTacWin.h" #include "problem_16_05_factorialZeros.h" #include "problem_16_06_smallestDifference.h" +#include "problem_16_07_numberMax.h" #include "problem_16_10_livingPeople.h" #include "problem_16_11_divingBoard.h" #include "problem_16_17_contiguousSequence.h" diff --git a/cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.cpp b/cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.cpp new file mode 100644 index 0000000..9f3571f --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.cpp @@ -0,0 +1,14 @@ +#include "problem_16_07_numberMax.h" + +namespace chapter_16 { + uint16_t numberMax(uint16_t A, uint16_t B) { + uint32_t tempA = static_cast(A) + 1; // ensure we do not divide by zero in quotient computation. ensure that we do not overflow. + uint32_t tempB = static_cast(B) + 1; // ensure we do not divide by zero in quotient computation. ensure that we do not overflow. + bool quotientA = static_cast(tempA / tempB); // may have value of 0 or 1 + bool quotientB = static_cast(tempB / tempA); // may have value of 0 or 1 + // if qA and qB are both 0, then the numbers are both 0. in that case we want to divide by 1 + // if qA = 0 and qB = 1, then we want to divide by 1 + // if qA = 1 and qB = 1, then the numbers are the same and we want to divide by 2 + return (quotientA * A + quotientB * B) / ((quotientA && quotientB) + 1); + } +} diff --git a/cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.h b/cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.h new file mode 100644 index 0000000..b749bad --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_07_numberMax.h @@ -0,0 +1,40 @@ +/* +PROBLEM: +Write a method that finds the maximum of two numbers. You should not use if-else +or any other comparison operator. + +ALGORITHM: +If the numbers are integers, we can take advantage of the properties of integer division. +Dividing the smaller number by the larger number will yield 0. Example: + +A = 7.5 +B = 1.0 +quotientA = static_cast(A / B) = 7.5 -> 7 -> 1 +quotientB = static_cast(B / A) = 0.13 -> 0 -> 0 + +We can then return the following: + +quotientA * A + quotientB * B / (quotientA + quotientB) + +However, this formulation has issues where either or both A and B are zero. Thus we use a revised +formulation. First we increment both A and B by 1 to avoid division by zero. This incrementation does +not affect which number is bigger or smaller. Next we use the && operator to create a divisor that can +never be zero as shown: + +(quotientA * A + quotientB * B) / ((quotientA && quotientB) + 1); + +With this formula, we solve the problem with much fewer lines than the book author's solution, but we are limited to only +positive integers. + +TIME: +O(1) time +SPACE: +O(1) space +*/ + +#pragma once +#include + +namespace chapter_16 { + uint16_t numberMax(uint16_t A, uint16_t B); +} diff --git a/tests.cpp b/tests.cpp index 5b2cf98..a93de6c 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1647,6 +1647,17 @@ TEST_CASE("Chapter 16 - Problem 06 - smallestDifference()") { REQUIRE(std::numeric_limits::max() == chapter_16::smallestDifference(example6, example6)); } +TEST_CASE("Chapter 16 - Problem 07 - numberMax()", "test") { + REQUIRE(8 == chapter_16::numberMax(8,4)); + REQUIRE(8 == chapter_16::numberMax(4,8)); + REQUIRE(65535 == chapter_16::numberMax(65535, 65534)); + REQUIRE(1 == chapter_16::numberMax(1,0)); + REQUIRE(0b10001 == chapter_16::numberMax(0b10001,0b1001)); + REQUIRE(0 == chapter_16::numberMax(0,0)); + REQUIRE(5 == chapter_16::numberMax(5,0)); + REQUIRE(8 == chapter_16::numberMax(8,8)); +} + TEST_CASE("Chapter 16 - Problem 10 - livingPeople()", "test") { std::vector people1 = { chapter_16::Person(1930, 2000), From a05d267834dc16b06f330c77455e63004d9a908d Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sun, 12 Jan 2020 19:42:46 -0800 Subject: [PATCH 169/176] fix error in problem count --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 151e4c9..06e6737 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,9 @@ C++ Total: `80` solutions complete. 16. [Chapter 16 - Moderate](python_solutions/chapter_16_moderate): `2 / 26` complete. 17. [Chapter 17 - Hard](python_solutions/chapter_17_hard): `3 / 26` complete. -Python Total: `57` solutions complete. +Python Total: `58` solutions complete. -##### Grand Total: `140` unique solutions complete. +##### Grand Total: `138` unique solutions complete. ### Building: #### Mac: From 31ac7843ef9f8a444a429442a80e23cb7e0dee12 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 20 Jan 2020 21:19:51 -0800 Subject: [PATCH 170/176] implemente dunit tests and skeleton for 16.19 C++ --- CMakeLists.txt | 1 + .../chapter_16_moderate/chapter_16_includes.h | 1 + .../problem_16_19_pondSizes.cpp | 7 ++++ .../problem_16_19_pondSizes.h | 18 +++++++++++ tests.cpp | 32 +++++++++++++++++++ 5 files changed, 59 insertions(+) create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp create mode 100644 cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 438ffde..a93a419 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ set(SOURCE_FILES cpp_solutions/chapter_16_moderate/problem_16_10_livingPeople.cpp cpp_solutions/chapter_16_moderate/problem_16_11_divingBoard.cpp cpp_solutions/chapter_16_moderate/problem_16_17_contiguousSequence.cpp + cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp # MISC cpp_solutions/misc_exercises/misc_01_integralImage.cpp cpp_solutions/misc_exercises/misc_02_kernelConvolution.cpp) diff --git a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h index 37304c0..70bb9d5 100644 --- a/cpp_solutions/chapter_16_moderate/chapter_16_includes.h +++ b/cpp_solutions/chapter_16_moderate/chapter_16_includes.h @@ -10,3 +10,4 @@ #include "problem_16_10_livingPeople.h" #include "problem_16_11_divingBoard.h" #include "problem_16_17_contiguousSequence.h" +#include "problem_16_19_pondSizes.h" \ No newline at end of file diff --git a/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp new file mode 100644 index 0000000..8eda407 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp @@ -0,0 +1,7 @@ +#include "problem_16_19_pondSizes.h" + +namespace chapter_16 { + std::multiset pondSizes(std::vector> plot) { + return {}; + } +} diff --git a/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h new file mode 100644 index 0000000..119f822 --- /dev/null +++ b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h @@ -0,0 +1,18 @@ +/* PROBLEM: + * You have an integer matrix representing a plot of land, where the value at that location + * represents the height above sea level. A value of zero indicates water. A pond is a region of + * water connected vertically, horizontally, or diagonally. The size of the pond is the total number of + * connected water cells. Write a method to compute the sizes of all ponds in the matrix. + * + * ALGORITHM: + * Iterate over every cell of the matrix. + * + */ + +#pragma once +#include +#include + +namespace chapter_16 { + std::multiset pondSizes(std::vector> plot); +} \ No newline at end of file diff --git a/tests.cpp b/tests.cpp index a93de6c..fdf5bb8 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1711,6 +1711,38 @@ TEST_CASE("Chapter 16 - Problem 17 - contiguousSubarray()", "test") { REQUIRE(6 == chapter_16::contiguousSequence({-2, 1, -3, 4, -1, 2, 1, -5, 4})); }; +TEST_CASE("Chapter 16 - problem 19 - pondSizes()", "test") { + // test 1 + const std::vector> plot1 = {{0, 2, 1, 0}, + {0, 1, 0, 1}, + {1, 1, 0, 1}, + {0, 1, 0, 1}}; + std::multiset expected1 = {2, 4, 1}; + REQUIRE(chapter_16::pondSizes(plot1) == expected1); + // test 2 + const std::vector> plot2 = {{}}; + std::multiset expected2 = {}; + REQUIRE(chapter_16::pondSizes(plot2) == expected2); + // test 3 + const std::vector> plot3 = {{0, 2, 1, 0}}; + std::multiset expected3 = {1, 1}; + REQUIRE(chapter_16::pondSizes(plot3) == expected3); + // test 4 + const std::vector> plot4 = {{0, 2, 1, 0}, + {0, 0, 0, 1}, + {0, 1, 0, 1}, + {0, 0, 0, 1}}; + std::multiset expected4 = {9, 1}; + REQUIRE(chapter_16::pondSizes(plot4) == expected4); + // test 5 + const std::vector> plot5= {{0, 2, 0, 2}, + {2, 0, 1, 0}, + {0, 1, 0, 1}, + {1, 0, 0, 0}}; + std::multiset expected5 = {1, 1, 1, 1, 1, 4}; + REQUIRE(chapter_16::pondSizes(plot5) == expected5); +}; + TEST_CASE("Chapter 17 - Problem 21 - histogramVolume()", "test") { const std::vector histogram1 = {0, 0, 4, 0, 0, 6, 0, 0, 3, 0, 8, 0, 2, 0, 5, 2, 0, 3, 0, 0}; const std::vector histogram2 = {5, 0, 0, 0, 1}; From 55830c8a65666c7d023a57d92e7e58fecec8a5cd Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 20 Jan 2020 22:20:52 -0800 Subject: [PATCH 171/176] implement 16.19 C++ --- .../problem_16_19_pondSizes.cpp | 29 ++++++++++++++++++- .../problem_16_19_pondSizes.h | 6 +++- tests.cpp | 10 +++---- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp index 8eda407..d1b408a 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp +++ b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.cpp @@ -1,7 +1,34 @@ #include "problem_16_19_pondSizes.h" +#include namespace chapter_16 { + int dfsHelper(std::vector>& plot, const int r, const int c, const int rows, const int cols) { + if (r < 0 || r >= rows || c < 0 || c >= cols || plot[r][c] != 0) return 0; // out of bounds check + plot[r][c] = -1; + int count = 1; + for (int newR = r - 1; newR <= r + 1; newR++) { + for (int newC = c - 1; newC <= c + 1; newC++) { + count += dfsHelper(plot, newR, newC, rows, cols); + } + } + return count; + } + std::multiset pondSizes(std::vector> plot) { - return {}; + const int rows = plot.size(); + if (rows < 1) return {}; // check for empty plot + const int cols = plot[0].size(); + std::multiset result = {}; + + for (int r = 0; r < rows; r++) { + for (int c = 0; c < cols; c++) { + if (plot[r][c] == 0) { + // spawn a DFS and add counter to multiset + int pondSize = dfsHelper(plot, r, c, rows, cols); + result.insert(pondSize); + } + } + } + return result; } } diff --git a/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h index 119f822..740b335 100644 --- a/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h +++ b/cpp_solutions/chapter_16_moderate/problem_16_19_pondSizes.h @@ -5,8 +5,12 @@ * connected water cells. Write a method to compute the sizes of all ponds in the matrix. * * ALGORITHM: - * Iterate over every cell of the matrix. + * Iterate over every cell of the matrix. At each zero cell, start a DFS that searches through all 8-connected + * zero cells and marks them invalid along the way. The DFS procedure will increment a counter for every cell + * explored. For every DFS done, add the returned counter to a multiset and return the multiset. * + * TIME: O(N*N) (assuming matrix is N*N size) + * SPACE: O(N*N) */ #pragma once diff --git a/tests.cpp b/tests.cpp index fdf5bb8..d564692 100644 --- a/tests.cpp +++ b/tests.cpp @@ -1729,17 +1729,17 @@ TEST_CASE("Chapter 16 - problem 19 - pondSizes()", "test") { REQUIRE(chapter_16::pondSizes(plot3) == expected3); // test 4 const std::vector> plot4 = {{0, 2, 1, 0}, - {0, 0, 0, 1}, + {0, 0, 1, 1}, {0, 1, 0, 1}, {0, 0, 0, 1}}; - std::multiset expected4 = {9, 1}; + std::multiset expected4 = {8, 1}; REQUIRE(chapter_16::pondSizes(plot4) == expected4); // test 5 const std::vector> plot5= {{0, 2, 0, 2}, {2, 0, 1, 0}, - {0, 1, 0, 1}, - {1, 0, 0, 0}}; - std::multiset expected5 = {1, 1, 1, 1, 1, 4}; + {0, 1, 3, 1}, + {1, 0, 2, 0}}; + std::multiset expected5 = {6, 1}; REQUIRE(chapter_16::pondSizes(plot5) == expected5); }; From e74f1b620a1fabc11239e42bc6f0f07e7a7d3057 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Mon, 20 Jan 2020 22:30:21 -0800 Subject: [PATCH 172/176] update readme problem count --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 06e6737..c5c8fa3 100644 --- a/README.md +++ b/README.md @@ -37,11 +37,11 @@ reference and contribute solutions with confidence. 13. Chapter 13 - Java: N/A 14. Chapter 14 - Databases: `0 / 7` complete. 15. Chapter 15 - Threads and Locks: `0 / 4` complete. -16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `10 / 26` complete. +16. [Chapter 16 - Moderate](cpp_solutions/chapter_16_moderate): `11 / 26` complete. 17. [Chapter 17 - Hard](cpp_solutions/chapter_17_hard): `1 / 26` complete. 18. [Miscellaneous Exercises](cpp_solutions/misc_exercises): `2` complete. -C++ Total: `80` solutions complete. +C++ Total: `81` solutions complete. #### [Python Solutions](python_solutions): 0. [Python Unit tests](tests.py) @@ -65,7 +65,7 @@ C++ Total: `80` solutions complete. Python Total: `58` solutions complete. -##### Grand Total: `138` unique solutions complete. +##### Grand Total: `139` unique solutions complete. ### Building: #### Mac: From bb84bf519b3677713c3cc400ae99aab1e4b224cc Mon Sep 17 00:00:00 2001 From: Vipul Gharde Date: Fri, 14 Aug 2020 04:14:46 +0300 Subject: [PATCH 173/176] Remove Example Example used here was irrelevant as it was from the previous question. --- .../chapter_02_linked_lists/problem_02_06_palindrome.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py b/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py index 5e595cc..7c8d4b3 100644 --- a/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py +++ b/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py @@ -4,10 +4,6 @@ Problem Statement: Implement a function to check if a linked list is a palindrome. -Example: -Input: (7 -> 1 -> 6) + (5 -> 9 -> 2). That is, 617 + 295. -Output: (2 -> 1 -> 9). That is, 912. - Solution: A palindrome is a list that is the same forwards as it is backwards. We traverse the input list From 165a965bc974cdfadd851f49fe1906a7789e2771 Mon Sep 17 00:00:00 2001 From: Vipul Gharde Date: Mon, 7 Sep 2020 11:31:46 +0300 Subject: [PATCH 174/176] Update Example --- .../chapter_02_linked_lists/problem_02_06_palindrome.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py b/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py index 7c8d4b3..e3a1965 100644 --- a/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py +++ b/python_solutions/chapter_02_linked_lists/problem_02_06_palindrome.py @@ -4,6 +4,10 @@ Problem Statement: Implement a function to check if a linked list is a palindrome. +Example: +Input: 1 -> 3 -> 5 -> 3 -> 1 +Output: True + Solution: A palindrome is a list that is the same forwards as it is backwards. We traverse the input list From 0acdd4e4f4b3fb35f9d53f7442c0be669f23dff8 Mon Sep 17 00:00:00 2001 From: Vipul Gharde Date: Mon, 7 Sep 2020 11:33:10 +0300 Subject: [PATCH 175/176] Update Example --- .../chapter_02_linked_lists/problem_02_06_palindrome.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h b/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h index 725d135..f50d276 100644 --- a/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h +++ b/cpp_solutions/chapter_02_linked_lists/problem_02_06_palindrome.h @@ -5,8 +5,8 @@ Problem Statement: Implement a function to check if a linked list is a palindrome. Example: -Input: (7 -> 1 -> 6) + (5 -> 9 -> 2). That is, 617 + 295. -Output: (2 -> 1 -> 9). That is, 912. +Input: 1 -> 3 -> 5 -> 3 -> 1 +Output: true Solution: From a3795228188a66340a146cbff0c7552519773d56 Mon Sep 17 00:00:00 2001 From: Alex Hagiopol Date: Sat, 19 Sep 2020 00:16:15 -0700 Subject: [PATCH 176/176] update license to BSD 3 clause --- LICENSE | 27 +++++++++++++++++++++++++++ LICENSE.txt | 26 -------------------------- 2 files changed, 27 insertions(+), 26 deletions(-) create mode 100644 LICENSE delete mode 100644 LICENSE.txt diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f342ad3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2020, Alex Hagiopol +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index 0bd5828..0000000 --- a/LICENSE.txt +++ /dev/null @@ -1,26 +0,0 @@ -Copyright (c) 2017, Alex Hagiopol -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those -of the authors and should not be interpreted as representing official policies, -either expressed or implied, of the FreeBSD Project. \ No newline at end of file