diff --git a/graphs_trees/tree_dfs/__init__.py b/graphs_trees/tree_dfs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/graphs_trees/tree_dfs/dfs_challenge.ipynb b/graphs_trees/tree_dfs/dfs_challenge.ipynb new file mode 100644 index 0000000..5c12580 --- /dev/null +++ b/graphs_trees/tree_dfs/dfs_challenge.ipynb @@ -0,0 +1,234 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Challenge Notebook" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Problem: Implement depth-first searches (in-order, pre-order, post-order traversals) on a binary tree.\n", + "\n", + "* [Constraints](#Constraints)\n", + "* [Test Cases](#Test-Cases)\n", + "* [Algorithm](#Algorithm)\n", + "* [Code](#Code)\n", + "* [Unit Test](#Unit-Test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Constraints\n", + "\n", + "* Can we assume we already have a Node class with an insert method?\n", + " * Yes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test Cases\n", + "\n", + "### In-Order Traversal\n", + "\n", + "* 5, 2, 8, 1, 3 -> 1, 2, 3, 5, 8\n", + "* 1, 2, 3, 4, 5 -> 1, 2, 3, 4, 5\n", + "\n", + "### Pre-Order Traversal\n", + "\n", + "* 5, 2, 8, 1, 3 -> 5, 2, 1, 3, 8\n", + "* 1, 2, 3, 4, 5 -> 1, 2, 3, 4, 5\n", + "\n", + "### Post-Order Traversal\n", + "\n", + "* 5, 2, 8, 1, 3 -> 1, 3, 2, 8, 5\n", + "* 1, 2, 3, 4, 5 -> 5, 4, 3, 2, 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Algorithm\n", + "\n", + "Refer to the [solution notebook](https://github.com/donnemartin/interactive-coding-challenges/graphs_trees/tree_dfs/dfs_solution.ipynb). If you are stuck and need a hint, the solution notebook's algorithm discussion might be a good place to start." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../bst/bst.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class MyNode(Node):\n", + " def in_order_traversal(self, visit_func):\n", + " # TODO: Implement me\n", + "\n", + " def pre_order_traversal(self, visit_func):\n", + " # TODO: Implement me\n", + "\n", + " def post_order_traversal(self, visit_func):\n", + " # TODO: Implement me" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unit Test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../utils/captured_output.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# %load test_dfs.py\n", + "from __future__ import print_function\n", + "from nose.tools import assert_equal\n", + "\n", + "\n", + "class TestDfs(object):\n", + "\n", + " def test_dfs(self):\n", + " root = Node(5)\n", + " root.insert(2)\n", + " root.insert(8)\n", + " root.insert(1)\n", + " root.insert(3)\n", + "\n", + " with captured_output() as (out, err):\n", + " root.in_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '12358')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.pre_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '52138')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.post_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '13285')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.bfs(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '52813')\n", + "\n", + " root = Node(1)\n", + " root.insert(2)\n", + " root.insert(3)\n", + " root.insert(4)\n", + " root.insert(5)\n", + "\n", + " with captured_output() as (out, err):\n", + " root.in_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '12345')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.pre_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '12345')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.post_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '54321')\n", + "\n", + " print('Success: test_dfs')\n", + "\n", + "\n", + "def main():\n", + " test = TestDfs()\n", + " test.test_dfs()\n", + "\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Solution Notebook\n", + "\n", + "Review the [solution notebook](https://github.com/donnemartin/interactive-coding-challenges/graphs_trees/tree_dfs/dfs_solution.ipynb) for a discussion on algorithms and code solutions." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/graphs_trees/tree_dfs/dfs_solution.ipynb b/graphs_trees/tree_dfs/dfs_solution.ipynb new file mode 100644 index 0000000..0a0b26d --- /dev/null +++ b/graphs_trees/tree_dfs/dfs_solution.ipynb @@ -0,0 +1,294 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook was prepared by [Donne Martin](https://github.com/donnemartin). Source and license info is on [GitHub](https://github.com/donnemartin/interactive-coding-challenges)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Solution Notebook" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Problem: Implement depth-first searches (in-order, pre-order, post-order traversals) on a binary tree.\n", + "\n", + "* [Constraints](#Constraints)\n", + "* [Test Cases](#Test-Cases)\n", + "* [Algorithm](#Algorithm)\n", + "* [Code](#Code)\n", + "* [Unit Test](#Unit-Test)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Constraints\n", + "\n", + "* Can we assume we already have a Node class with an insert method?\n", + " * Yes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test Cases\n", + "\n", + "### In-Order Traversal\n", + "\n", + "* 5, 2, 8, 1, 3 -> 1, 2, 3, 5, 8\n", + "* 1, 2, 3, 4, 5 -> 1, 2, 3, 4, 5\n", + "\n", + "### Pre-Order Traversal\n", + "\n", + "* 5, 2, 8, 1, 3 -> 5, 2, 1, 3, 8\n", + "* 1, 2, 3, 4, 5 -> 1, 2, 3, 4, 5\n", + "\n", + "### Post-Order Traversal\n", + "\n", + "* 5, 2, 8, 1, 3 -> 1, 3, 2, 8, 5\n", + "* 1, 2, 3, 4, 5 -> 5, 4, 3, 2, 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Algorithm\n", + "\n", + "## Test Cases\n", + "\n", + "### In-Order Traversal\n", + "\n", + "* Recursively call in-order traversal on the left child\n", + "* Visit the current node\n", + "* Recursively call in-order traversal on the right child\n", + "\n", + "Complexity:\n", + "* Time: O(n)\n", + "* Space: O(log n)\n", + "\n", + "Note:\n", + "* This is a form of a depth-first traversal\n", + "\n", + "### Pre-Order Traversal\n", + "\n", + "* Visit the current node\n", + "* Recursively call pre-order traversal on the left child\n", + "* Recursively call pre-order traversal on the right child\n", + "\n", + "Complexity:\n", + "* Time: O(n)\n", + "* Space: O(log n)\n", + "\n", + "Note:\n", + "* This is a form of a depth-first traversal\n", + "\n", + "### Post-Order Traversal\n", + "\n", + "* Recursively call post-order traversal on the left child\n", + "* Recursively call post-order traversal on the right child\n", + "* Visit the current node\n", + "\n", + "Complexity:\n", + "* Time: O(n)\n", + "* Space: O(log n)\n", + "\n", + "Note:\n", + "* This is a form of a depth-first traversal" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Code" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%run ../bst/bst.py" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class MyNode(Node):\n", + " def in_order_traversal(self, visit_func):\n", + " if self.left is not None:\n", + " self.left.in_order_traversal(visit_func)\n", + " visit_func(self.data)\n", + " if self.right is not None:\n", + " self.right.in_order_traversal(visit_func)\n", + "\n", + " def pre_order_traversal(self, visit_func):\n", + " visit_func(self.data)\n", + " if self.left is not None:\n", + " self.left.pre_order_traversal(visit_func)\n", + " if self.right is not None:\n", + " self.right.pre_order_traversal(visit_func)\n", + "\n", + " def post_order_traversal(self, visit_func):\n", + " if self.left is not None:\n", + " self.left.post_order_traversal(visit_func)\n", + " if self.right is not None:\n", + " self.right.post_order_traversal(visit_func)\n", + " visit_func(self.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unit Test" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "%run ../utils/captured_output.py" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Overwriting test_dfs.py\n" + ] + } + ], + "source": [ + "%%writefile test_dfs.py\n", + "from __future__ import print_function\n", + "from nose.tools import assert_equal\n", + "\n", + "\n", + "class TestDfs(object):\n", + "\n", + " def test_dfs(self):\n", + " root = Node(5)\n", + " root.insert(2)\n", + " root.insert(8)\n", + " root.insert(1)\n", + " root.insert(3)\n", + "\n", + " with captured_output() as (out, err):\n", + " root.in_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '12358')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.pre_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '52138')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.post_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '13285')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.bfs(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '52813')\n", + "\n", + " root = Node(1)\n", + " root.insert(2)\n", + " root.insert(3)\n", + " root.insert(4)\n", + " root.insert(5)\n", + "\n", + " with captured_output() as (out, err):\n", + " root.in_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '12345')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.pre_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '12345')\n", + "\n", + " with captured_output() as (out, err):\n", + " root.post_order_traversal(sys.stdout.write)\n", + " assert_equal(out.getvalue().strip(), '54321')\n", + "\n", + " print('Success: test_dfs')\n", + "\n", + "\n", + "def main():\n", + " test = TestDfs()\n", + " test.test_dfs()\n", + "\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success: test_dfs\n" + ] + } + ], + "source": [ + "%run -i test_dfs.py" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/graphs_trees/tree_dfs/test_dfs.py b/graphs_trees/tree_dfs/test_dfs.py new file mode 100644 index 0000000..f5763e5 --- /dev/null +++ b/graphs_trees/tree_dfs/test_dfs.py @@ -0,0 +1,57 @@ +from __future__ import print_function +from nose.tools import assert_equal + + +class TestDfs(object): + + def test_dfs(self): + root = Node(5) + root.insert(2) + root.insert(8) + root.insert(1) + root.insert(3) + + with captured_output() as (out, err): + root.in_order_traversal(sys.stdout.write) + assert_equal(out.getvalue().strip(), '12358') + + with captured_output() as (out, err): + root.pre_order_traversal(sys.stdout.write) + assert_equal(out.getvalue().strip(), '52138') + + with captured_output() as (out, err): + root.post_order_traversal(sys.stdout.write) + assert_equal(out.getvalue().strip(), '13285') + + with captured_output() as (out, err): + root.bfs(sys.stdout.write) + assert_equal(out.getvalue().strip(), '52813') + + root = Node(1) + root.insert(2) + root.insert(3) + root.insert(4) + root.insert(5) + + with captured_output() as (out, err): + root.in_order_traversal(sys.stdout.write) + assert_equal(out.getvalue().strip(), '12345') + + with captured_output() as (out, err): + root.pre_order_traversal(sys.stdout.write) + assert_equal(out.getvalue().strip(), '12345') + + with captured_output() as (out, err): + root.post_order_traversal(sys.stdout.write) + assert_equal(out.getvalue().strip(), '54321') + + print('Success: test_dfs') + + +def main(): + test = TestDfs() + test.test_dfs() + + +if __name__ == '__main__': + main() \ No newline at end of file