diff --git a/linked_lists/add_reverse/__init__.py b/linked_lists/add_reverse/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/linked_lists/add_reverse/add_reverse_challenge.ipynb b/linked_lists/add_reverse/add_reverse_challenge.ipynb new file mode 100644 index 0000000..ca78e6b --- /dev/null +++ b/linked_lists/add_reverse/add_reverse_challenge.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This notebook was prepared by [Donne Martin](http://donnemartin.com). Source and license info is on [GitHub](https://bit.ly/code-notes)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Problem: Add two numbers whose digits are stored in a linked list in reverse order.\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", + "*Problem statements are often intentionally ambiguous. Identifying constraints and stating assumptions can help to ensure you code the intended solution.*\n", + "\n", + "* Do you expect the return to be in reverse order too?\n", + " * Yes\n", + "* What if one of the inputs is NULL?\n", + " * Return NULL for an invalid operation\n", + "* How large are these numbers--can they fit in memory?\n", + " * Yes\n", + "* Can we assume we already have a linked list class that can be used for this problem?\n", + " * Yes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test Cases\n", + "\n", + "* Empty list(s) -> None\n", + "* Add values of different lengths\n", + " * Input 1: 6->5->None\n", + " * Input 2: 9->8->7\n", + " * Result: 5->4->8\n", + "* Add values of same lengths\n", + " * Exercised from values of different lengths\n", + " * Done here for completeness" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Algorithm\n", + "\n", + "Refer to the solution notebook. 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 ../linked_list/linked_list.py" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "class MyLinkedList(LinkedList):\n", + " \n", + " def add(self, first_list, second_list):\n", + " # TODO: Implement me\n", + " pass" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unit Test" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "*It is important to identify and run through general and edge cases from the [Test Cases](#Test-Cases) section by hand. You generally will not be asked to write a unit test like what is shown below.*\n", + "\n", + "**The following unit test is expected to fail until you solve the challenge.**" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "# %load test_add_reverse.py\n", + "from nose.tools import assert_equal\n", + "\n", + "\n", + "class TestAddReverse(object):\n", + " \n", + " def test_add(self):\n", + " print('Test: Empty list(s)')\n", + " assert_equal(MyLinkedList().add(None, None), None)\n", + " assert_equal(MyLinkedList().add(Node(5), None), None)\n", + " assert_equal(MyLinkedList().add(None, Node(10)), None)\n", + "\n", + " print('Test: Add values of different lengths')\n", + " # Input 1: 6->5->None\n", + " # Input 2: 9->8->7\n", + " # Result: 5->4->8\n", + " first_list = MyLinkedList(Node(6))\n", + " first_list.append(5)\n", + " second_list = MyLinkedList(Node(9))\n", + " second_list.append(8)\n", + " second_list.append(7)\n", + " result = MyLinkedList().add(first_list, second_list)\n", + " assert_equal(result.get_all_data(), [5, 4, 8])\n", + "\n", + " print('Test: Add values of same lengths')\n", + " # Input 1: 6->5->4\n", + " # Input 2: 9->8->7\n", + " # Result: 5->4->2->1\n", + " first_head = Node(6)\n", + " first_list = MyLinkedList(first_head)\n", + " first_list.append(5)\n", + " first_list.append(4)\n", + " second_head = Node(9)\n", + " second_list = MyLinkedList(second_head)\n", + " second_list.append(8)\n", + " second_list.append(7)\n", + " result = MyLinkedList().add(first_list, second_list)\n", + " assert_equal(result.get_all_data(), [5, 4, 2, 1])\n", + " \n", + " print('Success: test_add')\n", + "\n", + "def main():\n", + " test = TestAddReverse()\n", + " test.test_add()\n", + "\n", + "if __name__ == '__main__':\n", + " main()" + ] + } + ], + "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/linked_lists/add_reverse/add_reverse_solution.ipynb b/linked_lists/add_reverse/add_reverse_solution.ipynb index 8690051..f8182fa 100644 --- a/linked_lists/add_reverse/add_reverse_solution.ipynb +++ b/linked_lists/add_reverse/add_reverse_solution.ipynb @@ -44,7 +44,7 @@ "source": [ "## Test Cases\n", "\n", - "* Empty list(s)\n", + "* Empty list(s) -> None\n", "* Add values of different lengths\n", " * Input 1: 6->5->None\n", " * Input 2: 9->8->7\n", @@ -99,7 +99,7 @@ }, "outputs": [], "source": [ - "%run linked_list.py" + "%run ../linked_list/linked_list.py" ] }, { @@ -111,11 +111,16 @@ "outputs": [], "source": [ "class MyLinkedList(LinkedList):\n", + " \n", " def __add__(self, first_node, second_node, carry):\n", " if type(carry) != int and carry < 0:\n", " raise ValueError('Invalid int argument: carry')\n", + " \n", + " # Base case\n", " if first_node is None and second_node is None and carry == 0:\n", " return None\n", + " \n", + " # Recursive case\n", " value = carry\n", " value += first_node.data if first_node is not None else 0\n", " value += second_node.data if second_node is not None else 0\n", @@ -159,17 +164,17 @@ "name": "stdout", "output_type": "stream", "text": [ - "Test: Empty list(s)\n", - "Test: Add values of different lengths\n", - "Test: Add values of same lengths\n", - "Success: test_add\n" + "Overwriting test_add_reverse.py\n" ] } ], "source": [ + "%%writefile test_add_reverse.py\n", "from nose.tools import assert_equal\n", "\n", - "class Test(object):\n", + "\n", + "class TestAddReverse(object):\n", + " \n", " def test_add(self):\n", " print('Test: Empty list(s)')\n", " assert_equal(MyLinkedList().add(None, None), None)\n", @@ -205,9 +210,34 @@ " \n", " print('Success: test_add')\n", "\n", + "def main():\n", + " test = TestAddReverse()\n", + " test.test_add()\n", + "\n", "if __name__ == '__main__':\n", - " test = Test()\n", - " test.test_add()" + " main()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Test: Empty list(s)\n", + "Test: Add values of different lengths\n", + "Test: Add values of same lengths\n", + "Success: test_add\n" + ] + } + ], + "source": [ + "%run -i test_add_reverse.py" ] } ], diff --git a/linked_lists/add_reverse/test_add_reverse.py b/linked_lists/add_reverse/test_add_reverse.py new file mode 100644 index 0000000..a5dc6a3 --- /dev/null +++ b/linked_lists/add_reverse/test_add_reverse.py @@ -0,0 +1,46 @@ +from nose.tools import assert_equal + + +class TestAddReverse(object): + + def test_add(self): + print('Test: Empty list(s)') + assert_equal(MyLinkedList().add(None, None), None) + assert_equal(MyLinkedList().add(Node(5), None), None) + assert_equal(MyLinkedList().add(None, Node(10)), None) + + print('Test: Add values of different lengths') + # Input 1: 6->5->None + # Input 2: 9->8->7 + # Result: 5->4->8 + first_list = MyLinkedList(Node(6)) + first_list.append(5) + second_list = MyLinkedList(Node(9)) + second_list.append(8) + second_list.append(7) + result = MyLinkedList().add(first_list, second_list) + assert_equal(result.get_all_data(), [5, 4, 8]) + + print('Test: Add values of same lengths') + # Input 1: 6->5->4 + # Input 2: 9->8->7 + # Result: 5->4->2->1 + first_head = Node(6) + first_list = MyLinkedList(first_head) + first_list.append(5) + first_list.append(4) + second_head = Node(9) + second_list = MyLinkedList(second_head) + second_list.append(8) + second_list.append(7) + result = MyLinkedList().add(first_list, second_list) + assert_equal(result.get_all_data(), [5, 4, 2, 1]) + + print('Success: test_add') + +def main(): + test = TestAddReverse() + test.test_add() + +if __name__ == '__main__': + main() \ No newline at end of file