diff --git a/sorting_searching/selection_sort/selection_sort_challenge.ipynb b/sorting_searching/selection_sort/selection_sort_challenge.ipynb index c77c0d5..529fe22 100644 --- a/sorting_searching/selection_sort/selection_sort_challenge.ipynb +++ b/sorting_searching/selection_sort/selection_sort_challenge.ipynb @@ -37,6 +37,10 @@ "* Is a naiive solution sufficient (ie not stable, not based on a heap)?\n", " * Yes\n", "* Are duplicates allowed?\n", + " * Yes\n", + "* Can we assume the input is valid?\n", + " * No\n", + "* Can we assume this fits memory?\n", " * Yes" ] }, @@ -46,7 +50,7 @@ "source": [ "## Test Cases\n", "\n", - "* None -> None\n", + "* None -> Exception\n", "* Empty input -> []\n", "* One element -> [element]\n", "* Two or more elements" @@ -76,22 +80,11 @@ }, "outputs": [], "source": [ - "def selection_sort(data, start=0):\n", - " # TODO: Implement me (recursive)\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def selection_sort_iterative(data):\n", - " # TODO: Implement me (iterative)\n", - " pass" + "class SelectionSort(object):\n", + "\n", + " def sort(self, data):\n", + " # TODO: Implement me (recursive)\n", + " pass" ] }, { @@ -114,41 +107,35 @@ "outputs": [], "source": [ "# %load test_selection_sort.py\n", - "from nose.tools import assert_equal\n", + "from nose.tools import assert_equal, assert_raises\n", "\n", "\n", "class TestSelectionSort(object):\n", "\n", " def test_selection_sort(self, func):\n", " print('None input')\n", - " data = None\n", - " func(data)\n", - " assert_equal(data, None)\n", + " assert_raises(TypeError, func, None)\n", "\n", " print('Empty input')\n", - " data = []\n", - " func(data)\n", - " assert_equal(data, [])\n", + " assert_equal(func([]), [])\n", "\n", " print('One element')\n", - " data = [5]\n", - " func(data)\n", - " assert_equal(data, [5])\n", + " assert_equal(func([5]), [5])\n", "\n", " print('Two or more elements')\n", " data = [5, 1, 7, 2, 6, -3, 5, 7, -10]\n", - " func(data)\n", - " assert_equal(data, sorted(data))\n", + " assert_equal(func(data), sorted(data))\n", "\n", " print('Success: test_selection_sort\\n')\n", "\n", "\n", "def main():\n", " test = TestSelectionSort()\n", - " test.test_selection_sort(selection_sort)\n", + " selection_sort = SelectionSort()\n", + " test.test_selection_sort(selection_sort.sort)\n", " try:\n", - " test.test_selection_sort(selection_sort_recursive)\n", - " test.test_selection_sort(selection_sort_iterative_alt)\n", + " test.test_selection_sort(selection_sort.sort_recursive)\n", + " test.test_selection_sort(selection_sort.sor_iterative_alt)\n", " except NameError:\n", " # Alternate solutions are only defined\n", " # in the solutions file\n", diff --git a/sorting_searching/selection_sort/selection_sort_solution.ipynb b/sorting_searching/selection_sort/selection_sort_solution.ipynb index 23c92cc..8fbd7ae 100644 --- a/sorting_searching/selection_sort/selection_sort_solution.ipynb +++ b/sorting_searching/selection_sort/selection_sort_solution.ipynb @@ -36,6 +36,10 @@ "* Is a naiive solution sufficient (ie not stable, not based on a heap)?\n", " * Yes\n", "* Are duplicates allowed?\n", + " * Yes\n", + "* Can we assume the input is valid?\n", + " * No\n", + "* Can we assume this fits memory?\n", " * Yes" ] }, @@ -45,7 +49,7 @@ "source": [ "## Test Cases\n", "\n", - "* None -> None\n", + "* None -> Exception\n", "* [] -> []\n", "* One element -> [element]\n", "* Two or more elements" @@ -87,64 +91,57 @@ }, "outputs": [], "source": [ - "def selection_sort(data):\n", - " if data is None or len(data) < 2:\n", - " return\n", - " for i in range(len(data)-1):\n", - " min_index = i\n", - " for j in range(i + 1, len(data)):\n", - " if data[j] < data[min_index]:\n", - " min_index = j\n", - " data[i], data[min_index] = data[min_index], data[i]" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Below are alternate solutions with helper functions:" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def find_min_index(data, start):\n", - " # Raises an exception if: \n", - " # -data is None\n", - " # -start >= len(data) - 1\n", - " min_index = start\n", - " for i in range(start + 1, len(data)):\n", - " if data[i] < data[min_index]:\n", + "class SelectionSort(object):\n", + "\n", + " def sort(self, data):\n", + " if data is None:\n", + " raise TypeError('data cannot be None')\n", + " if len(data) < 2:\n", + " return data\n", + " for i in range(len(data)-1):\n", " min_index = i\n", - " return min_index\n", + " for j in range(i+1, len(data)):\n", + " if data[j] < data[min_index]:\n", + " min_index = j\n", + " if data[min_index] < data[i]:\n", + " data[i], data[min_index] = data[min_index], data[i]\n", + " return data\n", "\n", + " def sort_iterative_alt(self, data):\n", + " if data is None:\n", + " raise TypeError('data cannot be None')\n", + " if len(data) < 2:\n", + " return data\n", + " for i in range(len(data)-1):\n", + " self._swap(data, i, self._find_min_index(data, i))\n", + " return data\n", "\n", - "def swap(data, i, j):\n", - " # Raises an exception if: \n", - " # -data is None\n", - " # -i or j are >= len(data)\n", - " if i != j:\n", - " data[i], data[j] = data[j], data[i]\n", + " def sort_recursive(self, data, start=0):\n", + " if data is None:\n", + " raise TypeError('data cannot be None')\n", + " if len(data) < 2:\n", + " return data\n", + " return self._sort_recursive(data, start)\n", "\n", + " def _sort_recursive(self, data, start):\n", + " if data is None:\n", + " return\n", + " if start < len(data) - 1:\n", + " swap(data, start, self._find_min_index(data, start))\n", + " self._sort_recursive(data, start+1)\n", + " return data\n", "\n", - "def selection_sort_recursive(data, start=0):\n", - " if data is None:\n", - " return\n", - " if start < len(data) - 1:\n", - " swap(data, start, find_min_index(data, start))\n", - " selection_sort_recursive(data, start+1)\n", + " def _find_min_index(self, data, start):\n", + " min_index = start\n", + " for i in range(start+1, len(data)):\n", + " if data[i] < data[min_index]:\n", + " min_index = i\n", + " return min_index\n", "\n", - "\n", - "def selection_sort_iterative_alt(data):\n", - " if data is None or len(data) < 2:\n", - " return\n", - " for i in range(len(data)-1):\n", - " swap(data, i, find_min_index(data, i))" + " def _swap(self, data, i, j):\n", + " if i != j:\n", + " data[i], data[j] = data[j], data[i]\n", + " return data" ] }, { @@ -157,7 +154,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": { "collapsed": false }, @@ -172,41 +169,35 @@ ], "source": [ "%%writefile test_selection_sort.py\n", - "from nose.tools import assert_equal\n", + "from nose.tools import assert_equal, assert_raises\n", "\n", "\n", "class TestSelectionSort(object):\n", "\n", " def test_selection_sort(self, func):\n", " print('None input')\n", - " data = None\n", - " func(data)\n", - " assert_equal(data, None)\n", + " assert_raises(TypeError, func, None)\n", "\n", " print('Empty input')\n", - " data = []\n", - " func(data)\n", - " assert_equal(data, [])\n", + " assert_equal(func([]), [])\n", "\n", " print('One element')\n", - " data = [5]\n", - " func(data)\n", - " assert_equal(data, [5])\n", + " assert_equal(func([5]), [5])\n", "\n", " print('Two or more elements')\n", " data = [5, 1, 7, 2, 6, -3, 5, 7, -10]\n", - " func(data)\n", - " assert_equal(data, sorted(data))\n", + " assert_equal(func(data), sorted(data))\n", "\n", " print('Success: test_selection_sort\\n')\n", "\n", "\n", "def main():\n", " test = TestSelectionSort()\n", - " test.test_selection_sort(selection_sort)\n", + " selection_sort = SelectionSort()\n", + " test.test_selection_sort(selection_sort.sort)\n", " try:\n", - " test.test_selection_sort(selection_sort_recursive)\n", - " test.test_selection_sort(selection_sort_iterative_alt)\n", + " test.test_selection_sort(selection_sort.sort_recursive)\n", + " test.test_selection_sort(selection_sort.sor_iterative_alt)\n", " except NameError:\n", " # Alternate solutions are only defined\n", " # in the solutions file\n", @@ -219,7 +210,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": { "collapsed": false }, @@ -237,15 +228,7 @@ "None input\n", "Empty input\n", "One element\n", - "Two or more elements\n", - "Success: test_selection_sort\n", - "\n", - "None input\n", - "Empty input\n", - "One element\n", - "Two or more elements\n", - "Success: test_selection_sort\n", - "\n" + "Two or more elements\n" ] } ], diff --git a/sorting_searching/selection_sort/test_selection_sort.py b/sorting_searching/selection_sort/test_selection_sort.py index 17652c7..51bf128 100644 --- a/sorting_searching/selection_sort/test_selection_sort.py +++ b/sorting_searching/selection_sort/test_selection_sort.py @@ -1,38 +1,32 @@ -from nose.tools import assert_equal +from nose.tools import assert_equal, assert_raises class TestSelectionSort(object): def test_selection_sort(self, func): print('None input') - data = None - func(data) - assert_equal(data, None) + assert_raises(TypeError, func, None) print('Empty input') - data = [] - func(data) - assert_equal(data, []) + assert_equal(func([]), []) print('One element') - data = [5] - func(data) - assert_equal(data, [5]) + assert_equal(func([5]), [5]) print('Two or more elements') data = [5, 1, 7, 2, 6, -3, 5, 7, -10] - func(data) - assert_equal(data, sorted(data)) + assert_equal(func(data), sorted(data)) print('Success: test_selection_sort\n') def main(): test = TestSelectionSort() - test.test_selection_sort(selection_sort) + selection_sort = SelectionSort() + test.test_selection_sort(selection_sort.sort) try: - test.test_selection_sort(selection_sort_recursive) - test.test_selection_sort(selection_sort_iterative_alt) + test.test_selection_sort(selection_sort.sort_recursive) + test.test_selection_sort(selection_sort.sor_iterative_alt) except NameError: # Alternate solutions are only defined # in the solutions file