diff --git a/.ipynb_checkpoints/assignment-scratch-checkpoint.ipynb b/.ipynb_checkpoints/assignment-scratch-checkpoint.ipynb new file mode 100644 index 000000000..2fd64429b --- /dev/null +++ b/.ipynb_checkpoints/assignment-scratch-checkpoint.ipynb @@ -0,0 +1,6 @@ +{ + "cells": [], + "metadata": {}, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.ipynb_checkpoints/lecture-notes-checkpoint.ipynb b/.ipynb_checkpoints/lecture-notes-checkpoint.ipynb new file mode 100644 index 000000000..a56c434ef --- /dev/null +++ b/.ipynb_checkpoints/lecture-notes-checkpoint.ipynb @@ -0,0 +1,87 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Questions 1\n", + "Given an image represented by `NxN` matrix, where each pixel is an integer from 0-9, write a function `rotateImage` that rotates the image by 90 degrees in the counter-clockwise direction.\n", + "### Asking Questions\n", + "- How is the matrix represented\n", + "- How do I move matrix elements around\n", + "- How do I rotate a metrix in *any* direction?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 2\n", + "Write a function to return the `nth` term in the Fibonacci sequence.\n", + "\n", + "$F_n = F_{n-1} + F_{n-2}$\n", + "\n", + "\n", + "The Python solution:\n", + "```python\n", + "def nth_fib(n):\n", + " if n < 2:\n", + " return n\n", + " return nth_fib(n-1) + nth_fib(n-2)\n", + "```\n", + "\n", + "## Questions\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Write a `getFactorial()` function.\n", + "\n", + "```python\n", + "Base cases:\n", + "0! = 1\n", + "1! = 1\n", + "\n", + "Recusrive case:\n", + "n! = n + (n-1)!\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "def getFactorial(n):\n", + " if n < 2:\n", + " return 1\n", + " factored = n * getFactorial(n-1)\n", + " return factored" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/assignment-scratch.ipynb b/assignment-scratch.ipynb new file mode 100644 index 000000000..826f1d18b --- /dev/null +++ b/assignment-scratch.ipynb @@ -0,0 +1,826 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Stock Prices" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "prices = [2,3,1,4,5,0] " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0, 5, 4, 1, 3, 2]" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "prices[::-1]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "def find_max_profit(prices):\n", + " differentials = []\n", + " cursor = 1\n", + " for pricepoint in prices:\n", + " for next_pricepoint in prices[cursor:]:\n", + " differentials.append(next_pricepoint - pricepoint)\n", + " cursor += 1\n", + " return max(differentials)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "94" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "find_max_profit([100, 55, 4, 98, 10, 18, 90, 95, 43, 11, 47, 67, 89, 42, 49, 79])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Recipe Batches" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Write a function that receives a recipe in the form of a dictionary, as well as all of the ingredients you have available to you, also in the form of a dictionary. Your function should output the maximum number of whole batches that can be made for the supplied recipe using the ingredients available to you, as indicated by the second dictionary.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [], + "source": [ + "def recipe_batches(recipe, ingredients):\n", + " need = []\n", + " have = []\n", + " for i in recipe.keys():\n", + " need.append(i)\n", + " for i in ingredients.keys():\n", + " have.append(i)\n", + " for i in need:\n", + " if i not in have:\n", + " return 0\n", + " ratios = []\n", + " for i in recipe:\n", + " ratio = ingredients[i] // recipe[i]\n", + " if ratio < 1:\n", + " return 0\n", + " ratios.append(ratio)\n", + " return min(ratios)" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [], + "source": [ + "recipe = {\n", + " 'eggs': 5,\n", + " 'butter': 10,\n", + " 'sugar': 8,\n", + " 'flour': 15\n", + "}\n", + "ingredients = {}" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['eggs', 'butter', 'sugar', 'flour'])" + ] + }, + "execution_count": 80, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ingredients.keys()" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [], + "source": [ + "for i in recipe:\n", + " ingredients[i] = recipe[i]*2" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "eggs\n", + "butter\n", + "sugar\n", + "flour\n", + "[2, 2, 2, 2]\n" + ] + } + ], + "source": [ + "ratios = []\n", + "for i in recipe:\n", + " print(i)\n", + " ratio = ingredients[i] // recipe[i]\n", + " ratios.append(ratio)\n", + "print(ratios)" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ingredients['eggs']" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [], + "source": [ + "rec = { 'milk': 100, 'flour': 4, 'sugar': 10, 'butter': 5 }\n", + "\n", + "\n", + "ing = { 'milk': 1288, 'flour': 9, 'sugar': 95 }" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "recipe_batches(rec, ing)" + ] + }, + { + "cell_type": "code", + "execution_count": 103, + "metadata": {}, + "outputs": [], + "source": [ + "def eating_cookies(n, cache=None):\n", + " ways = 0\n", + " if n < 0:\n", + " ways += 0\n", + " if n == 0:\n", + " ways += 1\n", + " if n == 1:\n", + " ways += 1\n", + " if n == 2:\n", + " ways += 2\n", + " if n == 3:\n", + " ways += 4\n", + " if n > 3:\n", + " ways +=2\n", + " return ways" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def eating_cookies(n, cache=None):\n", + " ways = [1,1,2,3]" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [], + "source": [ + "def __calculatePaths(currPathLength, paths, currSeries):\n", + " if currPathLength == 0:\n", + " return 1\n", + " elif currPathLength < 0:\n", + " return 0\n", + " paths = 0\n", + " for i in range(1, 4):\n", + " newSeries = list(currSeries) # make new series to track steps\n", + " newSeries.append(i)\n", + " paths += __calculatePaths(currPathLength - i, paths, newSeries)\n", + " return paths\n", + "\n", + "def calculatePaths(pathLength):\n", + " paths = __calculatePaths(pathLength, 0, [])\n", + " return paths" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1\n", + "1 1\n", + "2 2\n", + "3 4\n", + "4 7\n", + "5 13\n", + "6 24\n", + "7 44\n", + "8 81\n", + "9 149\n", + "10 274\n", + "11 504\n", + "12 927\n", + "13 1705\n", + "14 3136\n", + "15 5768\n", + "16 10609\n", + "17 19513\n", + "18 35890\n", + "19 66012\n", + "20 121415\n", + "21 223317\n", + "22 410744\n", + "23 755476\n", + "24 1389537\n", + "25 2555757\n", + "26 4700770\n", + "27 8646064\n", + "28 15902591\n" + ] + } + ], + "source": [ + "for i in range(29):\n", + " print(i,calculatePaths(i))" + ] + }, + { + "cell_type": "code", + "execution_count": 104, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 104, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eating_cookies(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[1, 2, 3, 4, 5]\n" + ] + } + ], + "source": [ + "\"\"\"\n", + "write a function that recursively returns the sum of a list of numbers\n", + "\"\"\"\n", + "\n", + "numbers = [1,2,3,4,5]\n", + "\n", + "def sum_of_numbers(num_list):\n", + " # What is our base case?\n", + "\n", + " return num_list\n", + "\n", + "print(sum_of_numbers(numbers))" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [], + "source": [ + "# e_c(n) = e_c(n-1) + e_c(n-2) + e_c(n-3)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [], + "source": [ + "def eating_cookies(n, cache=None):\n", + " if cache is None:\n", + " cache = {}\n", + " if n == 0:\n", + " return 1\n", + " elif n == 1:\n", + " return 1\n", + " elif n == 2:\n", + " return 2\n", + " elif n == 3:\n", + " return 4\n", + " elif cache and cache[n]:\n", + " return cache[n]\n", + " else:\n", + " cache[n] = eating_cookies(n-1, cache) + eating_cookies(n-2, cache) + eating_cookies(n-3, cache)\n", + " return cache[n]" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "410744" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "eating_cookies(22)" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "def making_change(amount, denominations):\n", + " cache = [0] * (amount + 1)\n", + " cache[0] = 1\n", + " for coin in denominations:\n", + " for higher_amount in range(coin, amount + 1):\n", + " cache[higher_amount] += cache[higher_amount - coin]\n", + " return cache[amount]" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "50" + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "making_change(50,[1,5,10,25,50])" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "def making_change(n):\n", + " if n == 0:\n", + " return 1\n", + " elif 1 <= n < 5:\n", + " return 1\n", + " elif 5 <= n < 10:\n", + " return 2\n", + " elif n == 10:\n", + " return 4\n", + " elif n == 25:\n", + " return 13\n", + " elif n == 50:\n", + " return 50\n", + " else:\n", + " return making_change(n) + making_change(n-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [], + "source": [ + "def bunnyEars(bunnies):\n", + " if bunnies == 0:\n", + " return 0\n", + "\n", + " return 2 + bunnyEars(bunnies-1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for i in range(1,100):\n", + " print(bunnyEars(i))" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [], + "source": [ + "a = 0\n", + "a = a + 10\n", + "ry" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "10" + ] + }, + "execution_count": 87, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 137, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0:00:00.000047\n" + ] + } + ], + "source": [ + "from datetime import datetime\n" + ] + }, + { + "cell_type": "code", + "execution_count": 142, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0:00:00.000118\n" + ] + } + ], + "source": [ + "start_time = datetime.now()\n", + "n = 1\n", + "a = 0\n", + "while (a < n * n * n):\n", + " a = a + n * n\n", + "end_time = datetime.now()\n", + "print (end_time - start_time)" + ] + }, + { + "cell_type": "code", + "execution_count": 143, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0:00:00.000295\n" + ] + } + ], + "source": [ + "start_time = datetime.now()\n", + "n = 500\n", + "a = 0\n", + "while (a < n * n * n):\n", + " a = a + n * n\n", + "end_time = datetime.now()\n", + "print (end_time - start_time)" + ] + }, + { + "cell_type": "code", + "execution_count": 147, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 0:00:00.000084\n", + "501 0:00:00.000538\n", + "1001 0:00:00.000877\n", + "1501 0:00:00.001361\n", + "2001 0:00:00.001988\n", + "2501 0:00:00.002945\n", + "3001 0:00:00.004047\n", + "3501 0:00:00.005362\n", + "4001 0:00:00.007522\n", + "4501 0:00:00.009259\n", + "5001 0:00:00.011594\n", + "5501 0:00:00.013601\n", + "6001 0:00:00.018891\n", + "6501 0:00:00.022141\n", + "7001 0:00:00.024703\n", + "7501 0:00:00.028870\n", + "8001 0:00:00.032867\n", + "8501 0:00:00.037575\n", + "9001 0:00:00.041736\n", + "9501 0:00:00.045391\n" + ] + } + ], + "source": [ + "start_time = datetime.now()\n", + "for n in range(1,10000,500):\n", + " a = 0\n", + " while (a < n * n * n):\n", + " a = a + n * n\n", + " end_time = datetime.now()\n", + " print(n, end_time - start_time)" + ] + }, + { + "cell_type": "code", + "execution_count": 105, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "25\n", + "50\n", + "75\n", + "100\n", + "125\n" + ] + } + ], + "source": [ + "a = 0\n", + "while (a < 5 * 5 * 5):\n", + " a = a + 5 * 5\n", + " print(a)" + ] + }, + { + "cell_type": "code", + "execution_count": 148, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n" + ] + }, + { + "cell_type": "code", + "execution_count": 152, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "s = pd.Series([1, 2, 2.5, 3, 3.5, 4, 5])\n", + "ax = s.plot.kde()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Rock Paper Scissors\n", + "\n", + "Write a function `rock_paper_scissors` to generate all of the possible plays that can be made in a game of \"Rock Paper Scissors\", given some input `n`, which represents the number of plays per round. \n", + "\n", + "For example, given n = 2, your function should output the following:\n", + "\n", + "```python\n", + "[['rock', 'rock'], ['rock', 'paper'], ['rock', 'scissors'], ['paper', 'rock'], ['paper', 'paper'], ['paper', 'scissors'], ['scissors', 'rock'], ['scissors', 'paper'], ['scissors', 'scissors']]\n", + "```\n", + "\n", + "Your output should be a list of lists containing strings. Each inner list should have length equal to the input n.\n", + "\n", + "## Testing\n", + "\n", + "Run the test file by executing `python test_rps.py`.\n", + "\n", + "You can also test your implementation manually by executing `python rps.py [n]`.\n", + "\n", + "## Hints\n", + "\n", + " * You'll want to define a list with all of the possible Rock Paper Scissors plays.\n", + " * Another problem that asks you to generate a bunch of permutations, so we're probably going to want to opt for using recursion again. Since we're building up a list of results, we'll have to pass the list we're constructing around to multiple recursive calls so that each recursive call can add to the overall result. However, the tests only give our function `n` as input. To get around this, we could define an inner recursive helper function that will perform the recursion for us, while allowing us to preserve the outer function's function signature. \n", + " * In Python, you can concatenate two lists with the `+` operator. However, you'll want to make sure that both operands are lists!\n", + " * If you opt to define an inner recursive helper function, don't forget to make an initial call to the recursive helper function to kick off the recursion." + ] + }, + { + "cell_type": "code", + "execution_count": 157, + "metadata": {}, + "outputs": [], + "source": [ + "def add_one_more(list_plays):\n", + " list_return = []\n", + " strings = [['rock'],['paper'],['scissors']]\n", + " for i in list_plays:\n", + " for j in strings:\n", + " list_return.append(i+j)\n", + " return list_return\n", + " \n", + "\n", + "def rock_paper_scissors(n):\n", + " if n <= 0:\n", + " return [[]]\n", + " else:\n", + " return add_one_more(rock_paper_scissors(n-1))" + ] + }, + { + "cell_type": "code", + "execution_count": 168, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "0 1\n", + "1 3\n", + "2 9\n", + "3 27\n", + "4 81\n", + "5 243\n", + "6 729\n", + "7 2187\n", + "8 6561\n", + "9 19683\n", + "10 59049\n", + "11 177147\n", + "12 531441\n" + ] + } + ], + "source": [ + "for i in range(13):\n", + " lists = rock_paper_scissors(i)\n", + " print(i,len(lists))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/eating_cookies/eating_cookies.py b/eating_cookies/eating_cookies.py index 62655d803..0c6e687d0 100644 --- a/eating_cookies/eating_cookies.py +++ b/eating_cookies/eating_cookies.py @@ -5,8 +5,23 @@ # The cache parameter is here for if you want to implement # a solution that is more efficient than the naive # recursive solution + def eating_cookies(n, cache=None): - pass + if cache is None: + cache = {} + if n == 0: + return 1 + elif n == 1: + return 1 + elif n == 2: + return 2 + elif n == 3: + return 4 + elif cache and cache[n]: + return cache[n] + else: + cache[n] = eating_cookies(n-1, cache) + eating_cookies(n-2, cache) + eating_cookies(n-3, cache) + return cache[n] if __name__ == "__main__": if len(sys.argv) > 1: diff --git a/lecture-notes.ipynb b/lecture-notes.ipynb new file mode 100644 index 000000000..2ad496b23 --- /dev/null +++ b/lecture-notes.ipynb @@ -0,0 +1,273 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 1\n", + "Given an image represented by `NxN` matrix, where each pixel is an integer from 0-9, write a function `rotateImage` that rotates the image by 90 degrees in the counter-clockwise direction.\n", + "### Asking Questions\n", + "- How is the matrix represented\n", + "- How do I move matrix elements around\n", + "- How do I rotate a metrix in *any* direction?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 2\n", + "Write a function to return the `nth` term in the Fibonacci sequence.\n", + "\n", + "$F_n = F_{n-1} + F_{n-2}$\n", + "\n", + "\n", + "The Python solution:\n", + "```python\n", + "def nth_fib(n):\n", + " if n < 2:\n", + " return n\n", + " return nth_fib(n-1) + nth_fib(n-2)\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 3\n", + "Write a `getFactorial()` function.\n", + "\n", + "```python\n", + "Base cases:\n", + "0! = 1\n", + "1! = 1\n", + "\n", + "Recusrive case:\n", + "n! = n + (n-1)!\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "def getFactorial(n):\n", + " if n < 2:\n", + " return 1\n", + " factored = n * getFactorial(n-1)\n", + " return factored" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "120" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "getFactorial(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 4\n", + "Implement quicksort algorithm" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "def quicksort(data):\n", + " # base case: if array length 0 or 1\n", + " if len(data) < 2:\n", + " # return array\n", + " return data\n", + " \n", + " else:\n", + " # pick pivot (first element will do)\n", + " pivot = data[0]\n", + " left = []\n", + " right = []\n", + " # put anything smaller into left array\n", + " # put anything bigger into right array\n", + " for value in data[1:]:\n", + " if value <= pivot:\n", + " left.append(value)\n", + " if value > pivot:\n", + " right.append(value)\n", + " \n", + " # return quicksort(left) + pivot + quicksort(right)\n", + " return quicksort(left) + [pivot] + quicksort(right)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 4, 5]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "quicksort([5,4,3,2,1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Question 5 (last night's assignment)\n", + "Implement merge sort.\n", + "```python\n", + " [5 9 3 7 2 8 1 6]\n", + " [5 9 3 7] [2 8 1 6]\n", + " [5 9] [3 7] [2 8] [1 6]\n", + " [5] [9] [3] [7] [2] [8] [1] [6] # Viola! Each (sub)array is individually sorted\n", + " ↑ ↑\n", + "# Now let's compare each subarray pairwise, keeping track with two cursors\n", + "\n", + " # Here one of our cursors hit the end of its subarray,\n", + " # so we can append the remainder of the other array since we know its sorted\n", + " ↓\n", + "i i i\n", + "[5] [ ] [ ]\n", + "[ ] -->[5] -->[5 9] \n", + "[9] [9] [ ]\n", + "j j j\n", + "\n", + "# Repeat for every other one recursively\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "# Implementation\n", + "def merge(arrA, arrB):\n", + " elements = len(arrA) + len(arrB)\n", + " merged_arr = [0] * elements\n", + " # put back together here\n", + " # SORTING happens here\n", + " \n", + " # our cursors\n", + " a = 0\n", + " b = 0\n", + "\n", + " for k in range(0, elements):\n", + " # compare a and b\n", + " # if a is out of range, push b and iterate\n", + " # if b is out of range, push a and iterate\n", + " if a >= len(arrA): # we're done with arrA, push remaining arrB\n", + " merged_arr[k] = arrB[b]\n", + " b += 1\n", + " elif b >= len(arrB): # we're done with arrB, push remaining arrA\n", + " merged_arr[k] = arrA[a]\n", + " a += 1\n", + " # if a is smaller, put in array and iterate\n", + " # if b is smaller, put in array and iterate\n", + " elif arrA[a] < arrB[b]:\n", + " merged_arr[k] = arrA[a]\n", + " a += 1\n", + " else:\n", + " merged_arr[k] = arrB[b]\n", + " b += 1\n", + " return merged_arr\n", + "\n", + "def merge_sort(arr):\n", + " # split here\n", + " # find the middle of arr\n", + " mid = len(arr)//2\n", + " # base case:\n", + " # if array size > 1:\n", + " if len(arr) > 1:\n", + " # sort stuff in left and put it to the left\n", + " left = merge_sort(arr[:mid])\n", + " \n", + " # sort stuff in right and put it to the right\n", + " right = merge_sort(arr[mid:])\n", + " \n", + " # merge left and right\n", + " arr = merge(left, right)\n", + " return arr" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 5, 6, 7, 8, 9]" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "merge_sort([5,9,3,7,2,8,1,6])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/making_change/making_change.py b/making_change/making_change.py index 9adad4470..e00e0c7f3 100644 --- a/making_change/making_change.py +++ b/making_change/making_change.py @@ -3,7 +3,12 @@ import sys def making_change(amount, denominations): - pass + cache = [0] * (amount + 1) + cache[0] = 1 + for coin in denominations: + for higher_amount in range(coin, amount + 1): + cache[higher_amount] += cache[higher_amount - coin] + return cache[amount] if __name__ == "__main__": @@ -14,4 +19,4 @@ def making_change(amount, denominations): amount = int(sys.argv[1]) print("There are {ways} ways to make {amount} cents.".format(ways=making_change(amount, denominations), amount=amount)) else: - print("Usage: making_change.py [amount]") \ No newline at end of file + print("Usage: making_change.py [amount]") diff --git a/recipe_batches/recipe_batches.py b/recipe_batches/recipe_batches.py index c845950c5..8db80f2ab 100644 --- a/recipe_batches/recipe_batches.py +++ b/recipe_batches/recipe_batches.py @@ -3,7 +3,22 @@ import math def recipe_batches(recipe, ingredients): - pass + need = [] + have = [] + for i in recipe.keys(): + need.append(i) + for i in ingredients.keys(): + have.append(i) + for i in need: + if i not in have: + return 0 + ratios = [] + for i in recipe: + ratio = ingredients[i] // recipe[i] + if ratio < 1: + return 0 + ratios.append(ratio) + return min(ratios) if __name__ == '__main__': diff --git a/rock_paper_scissors/rps.py b/rock_paper_scissors/rps.py index 0fc53356e..9e4f4c713 100644 --- a/rock_paper_scissors/rps.py +++ b/rock_paper_scissors/rps.py @@ -2,8 +2,20 @@ import sys +def add_one_more(list_plays): + list_return = [] + strings = [['rock'],['paper'],['scissors']] + for i in list_plays: + for j in strings: + list_return.append(i+j) + return list_return + + def rock_paper_scissors(n): - pass + if n <= 0: + return [[]] + else: + return add_one_more(rock_paper_scissors(n-1)) if __name__ == "__main__": diff --git a/stock_prices/stock_prices.py b/stock_prices/stock_prices.py index 9de20bc94..379478f27 100644 --- a/stock_prices/stock_prices.py +++ b/stock_prices/stock_prices.py @@ -3,7 +3,16 @@ import argparse def find_max_profit(prices): - pass + differentials = [] + cursor = 1 + for pricepoint in prices: + for next_pricepoint in prices[cursor:]: + differentials.append(next_pricepoint - pricepoint) + cursor += 1 + return max(differentials) + + + if __name__ == '__main__':