diff --git a/README.md b/README.md index d56d970..711f82a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,23 @@ -# Chapter programs and solutions +# Doing Math with Python -Chapter programs/snippets and Solutions to Challenges for "Doing Math with Python". +This repository basically contains the chapter programs and solutions to challenges discussed in "Doing Math with Python" - written by Amit Saha, published by No Starch Press. Please do check the [website](http://doingmathwithpython.github.io/) to learn more about the book, updates and reviews. -# Jupyter +# Chapter code -If you know what Jupyter (previously, IPython notebooks are), click below to launch the program notebooks in Jupyter powered by Binder: +- [Chapter 1](https://github.com/doingmathwithpython/code/blob/master/chapter1/Chapter1.ipynb) +- [Chapter 2](https://github.com/doingmathwithpython/code/blob/master/chapter2/Chapter2.ipynb) +- [Chapter 3](https://github.com/doingmathwithpython/code/blob/master/chapter3/Chapter3.ipynb) +- [Chapter 4](https://github.com/doingmathwithpython/code/blob/master/chapter4/Chapter4.ipynb) +- [Chapter 5](https://github.com/doingmathwithpython/code/blob/master/chapter5/Chapter5.ipynb) +- [Chapter 6](https://github.com/doingmathwithpython/code/blob/master/chapter6/Chapter6.ipynb) +- [Chapter 7](https://github.com/doingmathwithpython/code/blob/master/chapter7/Chapter7.ipynb) + +If you are familiar with Jupyter (previously, IPython notebooks are), click below to launch the program notebooks in Jupyter powered by Binder: [![Binder](http://mybinder.org/badge.svg)](http://mybinder.org/repo/doingmathwithpython/code) + +# Solutions to challenges + +Please check the [blog post](https://doingmathwithpython.github.io/trying-out-solutions.html) on how to download these and try them out. + + diff --git a/chapter1/solutions/even_odd_vending.py b/chapter1/solutions/even_odd_vending.py index f666747..f7b1927 100644 --- a/chapter1/solutions/even_odd_vending.py +++ b/chapter1/solutions/even_odd_vending.py @@ -11,6 +11,7 @@ def even_odd_vending(num): else: print('Odd') count = 1 + print(num) while count <= 9: num += 2 print(num) diff --git a/chapter2/solutions/nyc_forecast_owm.py b/chapter2/solutions/nyc_forecast_owm.py index 309e68f..7a84079 100644 --- a/chapter2/solutions/nyc_forecast_owm.py +++ b/chapter2/solutions/nyc_forecast_owm.py @@ -4,22 +4,37 @@ ''' import matplotlib.pyplot as plt from pyowm import OWM +import pytz -owm = OWM() +owm = OWM('') def get_forecast(city): - fc = owm.daily_forecast(city, limit=1) + # this used to be daily_forecast + # https://github.com/csparpa/pyowm/issues/266 + fc = owm.three_hours_forecast(city) f = fc.get_forecast() - w = f.get_weathers()[0] - forecast_temp = w.get_temperature('celsius') - day_intervals = ['morn', 'day', 'eve', 'night'] + + # three_hours_forecast() returns 5 day forecast at a granularity + # of three hours + # We plot the forecast for the next 24 hours (so, first 8 intervals) + weathers = f.get_weathers()[0:8] + data_points = ['temp', 'temp_max', 'temp_min', 'temp_kf'] temp = [] - for timeofday in day_intervals: - temp.append(forecast_temp[point]) - x = range(1, len(day_intervals)+1) + date_time = [] + for w in weathers: + forecast_temp = w.get_temperature('celsius') + utc_dt = datetime.utcfromtimestamp(w.get_reference_time()).replace(tzinfo=pytz.utc) + tz = pytz.timezone('America/New_York') + dt = utc_dt.astimezone(tz) + date_time.append(dt.strftime('%Y-%m-%d %H:%M')) + temp.append(forecast_temp['temp']) + x = range(1, len(temp)+1) plt.plot(x, temp, 'o-') - plt.xticks(x, day_intervals) + plt.xticks(x, date_time, rotation=45) plt.show() + # Uncomment below and comment the previous line to save the image + # plt.savefig('nyc_owm_forecast.png') + if __name__ == '__main__': get_forecast('new york, us') diff --git a/chapter3/solutions/stats.py b/chapter3/solutions/stats.py index 85a0385..3450e11 100644 --- a/chapter3/solutions/stats.py +++ b/chapter3/solutions/stats.py @@ -18,7 +18,7 @@ def median(numbers): N = len(numbers) # sort the list in ascending order - numbers.sort() + numbers = sorted(numbers) # find the median if N % 2 == 0: diff --git a/chapter3/solutions/us_population_stats_figure_2.png b/chapter3/solutions/us_population_stats_figure_2.png index 303208a..c3b6fea 100644 Binary files a/chapter3/solutions/us_population_stats_figure_2.png and b/chapter3/solutions/us_population_stats_figure_2.png differ diff --git a/chapter6/Interactive Barnsley Fern.ipynb b/chapter6/Interactive Barnsley Fern.ipynb new file mode 100644 index 0000000..13d3ca5 --- /dev/null +++ b/chapter6/Interactive Barnsley Fern.ipynb @@ -0,0 +1,133 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\ntyQV6P8Dfr3xodos2HMAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#P165 of \"Doing Math with Python\": Interactive version of drawing the Barnsley Fern\n", + "\n", + "%matplotlib inline\n", + "\n", + "from ipywidgets import interact\n", + "import ipywidgets as widgets\n", + "\n", + "import random\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def transformation_1(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = 0.85*x + 0.04*y\n", + " y1 = -0.04*x + 0.85*y + 1.6\n", + " return x1, y1\n", + "\n", + "def transformation_2(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = 0.2*x - 0.26*y\n", + " y1 = 0.23*x + 0.22*y + 1.6\n", + " return x1, y1\n", + "\n", + "def transformation_3(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = -0.15*x + 0.28*y\n", + " y1 = 0.26*x + 0.24*y + 0.44\n", + " return x1, y1\n", + "\n", + "def transformation_4(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = 0\n", + " y1 = 0.16*y\n", + " return x1, y1\n", + "\n", + "def get_index(probability):\n", + " r = random.random()\n", + " c_probability = 0\n", + " sum_probability = []\n", + " for p in probability:\n", + " c_probability += p\n", + " sum_probability.append(c_probability)\n", + " for item, sp in enumerate(sum_probability):\n", + " if r <= sp:\n", + " return item\n", + " return len(probability)-1\n", + "\n", + "def transform(p):\n", + " # list of transformation functions\n", + " transformations = [transformation_1, transformation_2,\n", + " transformation_3, transformation_4]\n", + " probability = [0.85, 0.07, 0.07, 0.01]\n", + " # pick a random transformation function and call it\n", + " tindex = get_index(probability)\n", + " t = transformations[tindex]\n", + " x, y = t(p)\n", + " return x, y\n", + "\n", + "def draw_fern(n):\n", + " # We start with (0, 0)\n", + " x = [0]\n", + " y = [0]\n", + " x1, y1 = 0, 0\n", + " for i in range(n):\n", + " x1, y1 = transform((x1, y1))\n", + " x.append(x1)\n", + " y.append(y1)\n", + " \n", + " # Plot the points\n", + " plt.plot(x, y, 'o')\n", + " plt.title('Fern with {0} points'.format(n))\n", + " plt.show()\n", + " \n", + "# Allow interaction via the interact() function and an Integer slider widget\n", + "i = interact(draw_fern, n=widgets.IntSlider(min=0, max=10000,step=1,value=10))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "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.5.1" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/chapter6/Interactive Mandelbrot Set.ipynb b/chapter6/Interactive Mandelbrot Set.ipynb new file mode 100644 index 0000000..a23a2ab --- /dev/null +++ b/chapter6/Interactive Mandelbrot Set.ipynb @@ -0,0 +1,130 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "slideshow": { + "slide_type": "-" + } + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Interactive version of the \"Mandelbrot Set\" - solution to challenge in \n", + "# \"Doing Math with Python\", chapter 6\n", + "%matplotlib inline\n", + "'''\n", + "mandelbrot.py\n", + "\n", + "Draw a Mandelbrot set\n", + "\n", + "Using \"Escape time algorithm\" from:\n", + "http://en.wikipedia.org/wiki/Mandelbrot_set#Computer_drawings\n", + "\n", + "Thanks to http://www.vallis.org/salon/summary-10.html for some important\n", + "ideas for implementation.\n", + "\n", + "'''\n", + "\n", + "from ipywidgets import interact\n", + "import ipywidgets as widgets\n", + "\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib.cm as cm\n", + "\n", + "# Subset of the complex plane we are considering\n", + "x0, x1 = -2.5, 1\n", + "y0, y1 = -1, 1\n", + "\n", + "def initialize_image(x_p, y_p):\n", + " image = []\n", + " for i in range(y_p):\n", + " x_colors = []\n", + " for j in range(x_p):\n", + " x_colors.append(0)\n", + " image.append(x_colors)\n", + " return image\n", + "\n", + "def mandelbrot_set(n, max_iterations):\n", + " image = initialize_image(n, n)\n", + " \n", + " # Generate a set of equally spaced points in the region\n", + " # above\n", + " dx = (x1-x0)/(n-1)\n", + " dy = (y1-y0)/(n-1)\n", + " x_coords = [x0 + i*dx for i in range(n)]\n", + " y_coords = [y0 + i*dy for i in range(n)]\n", + "\n", + " for i, x in enumerate(x_coords):\n", + " for k, y in enumerate(y_coords):\n", + " z1 = complex(0, 0)\n", + " iteration = 0\n", + " c = complex(x, y)\n", + " while (abs(z1) < 2 and iteration < max_iterations):\n", + " z1 = z1**2 + c\n", + " iteration += 1\n", + " image[k][i] = iteration\n", + " return image\n", + "\n", + "def draw_mandelbrot(n, max_iterations):\n", + " image = mandelbrot_set(n, max_iterations)\n", + " plt.imshow(image, origin='lower', extent=(x0, x1, y0,y1),\n", + " cmap=cm.Greys_r, interpolation='nearest')\n", + " plt.show()\n", + " \n", + "\n", + "# Allow interaction via the interact() function and an Integer slider widget\n", + "i = interact(draw_mandelbrot, \n", + " n=widgets.IntSlider(min=100, max=600,step=1,value=10), \n", + " max_iterations=widgets.IntSlider(min=100, max=10000,step=1,value=10),\n", + " # This keyword argument adds a button so that the drawing happens\n", + " # only when the button is clicked\n", + " __manual=True\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "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.5.1" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/chapter6/Interactive Sierpinski Triangle.ipynb b/chapter6/Interactive Sierpinski Triangle.ipynb new file mode 100644 index 0000000..10df014 --- /dev/null +++ b/chapter6/Interactive Sierpinski Triangle.ipynb @@ -0,0 +1,121 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\n9w1fi3ozsNrMDNgLON7Mtrr7msqVlUqlyeeFQoFCodBgkaURQ0NLWLt2cErec2jozA6XTLKk9pAE\nSut1QrlcplwuJ7KuODn5HYCHCBpeHwd+AZzk7utqLP8t4EfKyWeH8p5ST3//IOXyiqqv33TT1Neb\noREqm5dqTt7dXzKzM4AbCLpcXu7u68zstGC2r6p8SzMFkfQo7yn1pJ3WUzqoc3TFa8pUe5FukHZ3\nRvXyao2ueM0o1V6kW8yfP48bbzyTZctWRtJ6ye2n6uXVOQryKVJjlnSTNNN66uXVOdrCKVLtRSSg\n4a87RzX5FKn2IhJIOx0ktanhNUUam0NEkqDx5DNMfdRFpFUK8iIiOaYulBmhPvEikjWqySdE+XcR\nSUsrNXl180hI7T7xV3SwVCLS6xTkE6I+8SKSRQryCdH9KkUkixSBEqIr+kQki9TwmiD1iReRNKif\nvDRM3T1FuoeCvDRE3T1FukvqXSjNbJGZrTezDWZ2XpX5J5jZfWZ2j5n9wsze3kxhpD3U3VOkd9S9\n4tXMZgCXEtzjdTNwt5ld6+7rI4v9dOKm3Wb2euBq4JAUyisJUHdPkd4Rpya/AHjY3cfcfSuwGlgc\nXcDdX4hM7gooWmSYunuK9I44v+o5wKbI9KPha9sxs/eb2TrgR8ApyRRP0qDuniK9I7EBytz9GuAa\nMzsa+DxwXLXlSqXS5PNCoUChUEiqCBKTbuAgkm3lcplyuZzIuur2rjGzhUDJ3ReF0+cD7u4XTvOe\njcBb3P3pitfVu0ZEplCX3umlPdTw3cABZjYPeBw4ETipogB97r4xfP4mYOfKAJ9HvbJj9sr3lM6o\n1qV37Vp16U2Mu9d9AIuAh4CHgfPD104DTg2f/z3wAPBr4A7grTXW43kxPDzqfX3nOIw7uMO49/Wd\n48PDo50uWqJ65XtK5xSLpcj+5ZP7WbFY6nTRMiOMnbHideUjVncKd7/e3Q9y9//m7heEr13m7qvC\n519y98Pd/U3u/nZ3vzPB41AmZaWv+cjIGAMDK+jvH2RgYAUjI2OJrj8r31PyS11606U7QzUpCztm\nO05zs/A9JbuSSOVt69Ib3c/UpTcp2opNykJf82Zq2Y3W/LPwPSWbJioZV111LuXyCq666lyOO+6S\nhs8m1aU3Zc3meZp5oJx8ogqF5RV5zODR3788sTJn4XtKNiWZSx8eHvViseT9/cu9WCxp/6pACzl5\n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\n+KHgvuHhAAAAAElFTkSuQmCC\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "\n", + "from ipywidgets import interact\n", + "import ipywidgets as widgets\n", + "\n", + "# Interactive version of drawing the Sierpinski triangle\n", + "# Doing Math with Python (Chapter 6)\n", + "\n", + "'''\n", + "sierpinski.py\n", + "\n", + "Draw Sierpinski Triangle\n", + "'''\n", + "import random\n", + "import matplotlib.pyplot as plt\n", + "\n", + "def transformation_1(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = 0.5*x\n", + " y1 = 0.5*y\n", + " return x1, y1\n", + "\n", + "def transformation_2(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = 0.5*x + 0.5\n", + " y1 = 0.5*y + 0.5\n", + " return x1, y1\n", + "\n", + "def transformation_3(p):\n", + " x = p[0]\n", + " y = p[1]\n", + " x1 = 0.5*x + 1\n", + " y1 = 0.5*y\n", + " return x1, y1\n", + "\n", + "def get_index(probability):\n", + " r = random.random()\n", + " c_probability = 0\n", + " sum_probability = []\n", + " for p in probability:\n", + " c_probability += p\n", + " sum_probability.append(c_probability)\n", + " for item, sp in enumerate(sum_probability):\n", + " if r <= sp:\n", + " return item\n", + " return len(probability)-1\n", + "\n", + "def transform(p):\n", + " # list of transformation functions\n", + " transformations = [transformation_1, transformation_2, transformation_3]\n", + " probability = [1/3, 1/3, 1/3]\n", + " # pick a random transformation function and call it\n", + " tindex = get_index(probability)\n", + " t = transformations[tindex]\n", + " x, y = t(p)\n", + " return x, y\n", + "\n", + "def draw_sierpinski(n):\n", + " # We start with (0, 0)\n", + " x = [0]\n", + " y = [0]\n", + "\n", + " x1, y1 = 0, 0\n", + " for i in range(n):\n", + " x1, y1 = transform((x1, y1))\n", + " x.append(x1)\n", + " y.append(y1) \n", + " \n", + " plt.plot(x, y, 'o')\n", + " plt.title('Sierpinski with {0} points'.format(n))\n", + " plt.show()\n", + "\n", + "i = interact(draw_sierpinski, n=widgets.IntSlider(min=100, max=10000, step=1, value=10))" + ] + } + ], + "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.5.1" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/explorations/PyScript/chap2/horizontal_bar_chart.html b/explorations/PyScript/chap2/horizontal_bar_chart.html new file mode 100644 index 0000000..60e0e77 --- /dev/null +++ b/explorations/PyScript/chap2/horizontal_bar_chart.html @@ -0,0 +1,46 @@ + + + + + + + - matplotlib + + + + +
+ + +import matplotlib.pyplot as plt +def create_bar_chart(data, labels): + # number of bars + num_bars = len(data) + # this list is the point on the y-axis where each + # bar is centered. Here it will be [1, 2, 3..] + positions = range(1, num_bars+1) + plt.barh(positions, data, align='center') + # set the label of each bar + plt.yticks(positions, labels) + plt.xlabel('Steps') + plt.ylabel('Day') + plt.title('Number of steps walked') + # Turns on the grid which may assist in visual estimation + plt.grid() + plt.show() + + +fig = plt.figure() +if __name__ == '__main__': + # Number of steps I walked during the past week + steps = [6534, 7000, 8900, 10786, 3467, 11045, 5095] + # Corresponding days + labels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] + create_bar_chart(steps, labels) +fig + + + + + + diff --git a/explorations/PyScript/chap2/newtons_gravitation.html b/explorations/PyScript/chap2/newtons_gravitation.html new file mode 100644 index 0000000..bff54c7 --- /dev/null +++ b/explorations/PyScript/chap2/newtons_gravitation.html @@ -0,0 +1,45 @@ + + + + + + + - matplotlib + + + + +
+ +import matplotlib.pyplot as plt +# draw the graph +def draw_graph(x, y): + plt.plot(x, y, marker='o') + plt.xlabel('Distance in meters') + plt.ylabel('Gravitational force in newtons') + plt.title('Gravitational force and distance') + plt.show() +def generate_F_r(): + # generate values for r + r = range(100, 1001, 50) + # empty list to store the calculated values of F + F = [] + # constant, G + G = 6.674*(10**-11) + # two masses + m1 = 0.5 + m2 = 1.5 + # calculate Force and add it to the list, F + for dist in r: + force = G*(m1*m2)/(dist**2) + F.append(force) + # call the draw_graph function + draw_graph(r, F) + +fig = plt.figure() +generate_F_r() +fig + + + + diff --git a/explorations/PyScript/chap2/nyc_forecast_owm.html b/explorations/PyScript/chap2/nyc_forecast_owm.html new file mode 100644 index 0000000..eae6c0d --- /dev/null +++ b/explorations/PyScript/chap2/nyc_forecast_owm.html @@ -0,0 +1,74 @@ + + + + + + + - matplotlib + - setuptools + - pyowm + - pytz + + + + +
+ +import pyodide +import json +import matplotlib.pyplot as plt +from unittest import mock +from datetime import datetime +import pytz + +from pyowm import OWM + +class MyResponse: + def __init__(self, status_code, message, json_body): + self.status_code = status_code + self.text = message + self.json_body = json_body + def json(self): + return self.json_body + +class JustEnoughRequests: + def __init__(self): + pass + + def get(self, uri, **kwargs): + print("Sending request to:", uri) + print("Got kwargs, igoring everyting other than params", kwargs) + query_params = [] + for k, v in kwargs["params"].items(): + query_params.append(k + "=" + v) + query_string = "&".join(query_params) + response = pyodide.open_url(uri + "?" + query_string) + json_response = response.getvalue() + d = json.loads(json_response) + return MyResponse(int(d["cod"]), d["message"], json.loads(json_response)) + +just_enough_requests = JustEnoughRequests() +fig = plt.figure() +with mock.patch('pyowm.commons.http_client.requests', just_enough_requests): + # Get a token from https://home.openweathermap.org/users/sign_up + owm = OWM('your token') + mgr = owm.weather_manager() + three_h_forecast = mgr.forecast_at_place('new york, us', '3h').forecast + temp = [] + date_time = [] + for w in three_h_forecast: + forecast_temp = w.temperature('celsius') + utc_dt = datetime.utcfromtimestamp(w.reference_time()).replace(tzinfo=pytz.utc) + tz = pytz.timezone('America/New_York') + dt = utc_dt.astimezone(tz) + date_time.append(dt.strftime('%Y-%m-%d %H:%M')) + temp.append(forecast_temp['temp']) + x = range(1, len(temp)+1) + plt.plot(x, temp, 'o-') + plt.xticks(x, date_time, rotation=45) +fig + + + + + diff --git a/explorations/PyScript/chap2/projectile_motion.html b/explorations/PyScript/chap2/projectile_motion.html new file mode 100644 index 0000000..7ad32d9 --- /dev/null +++ b/explorations/PyScript/chap2/projectile_motion.html @@ -0,0 +1,60 @@ + + + + + + + - matplotlib + + + + +
+ +from matplotlib import pyplot as plt +import math +def draw_graph(x, y): + print("Drawing the graph") + plt.plot(x, y) + plt.xlabel('x-coordinate') + plt.ylabel('y-coordinate') + plt.title('Projectile motion of a ball') + +def frange(start, final, interval): + numbers = [] + while start < final: + numbers.append(start) + start = start + interval + return numbers + +def draw_trajectory(u, theta): + theta = math.radians(theta) + g = 9.8 + # Time of flight + t_flight = 2*u*math.sin(theta)/g + # find time intervals + intervals = frange(0, t_flight, 0.001) + # list of x and y coordinates + x = [] + y = [] + for t in intervals: + x.append(u*math.cos(theta)*t) + y.append(u*math.sin(theta)*t - 0.5*g*t*t) + draw_graph(x, y) + +fig = plt.figure() +try: + u = float(input('Enter the initial velocity (m/s): ')) + theta = float(input('Enter the angle of projection (degrees): ')) +except ValueError: + print('You entered an invalid input') +else: + print(u,theta) + draw_trajectory(u, theta) +fig + + + + + + diff --git a/explorations/PyScript/chap2/projectile_motion_comparison.html b/explorations/PyScript/chap2/projectile_motion_comparison.html new file mode 100644 index 0000000..3fab935 --- /dev/null +++ b/explorations/PyScript/chap2/projectile_motion_comparison.html @@ -0,0 +1,57 @@ + + + + + + + - matplotlib + + + + +
+ +from matplotlib import pyplot as plt +import math +def draw_graph(x, y): + print("Drawing the graph") + plt.plot(x, y) + plt.xlabel('x-coordinate') + plt.ylabel('y-coordinate') + plt.title('Projectile motion of a ball') + +def frange(start, final, interval): + numbers = [] + while start < final: + numbers.append(start) + start = start + interval + return numbers + +def draw_trajectory(u, theta): + theta = math.radians(theta) + g = 9.8 + # Time of flight + t_flight = 2*u*math.sin(theta)/g + # find time intervals + intervals = frange(0, t_flight, 0.001) + # list of x and y coordinates + x = [] + y = [] + for t in intervals: + x.append(u*math.cos(theta)*t) + y.append(u*math.sin(theta)*t - 0.5*g*t*t) + draw_graph(x, y) + +fig = plt.figure() +u_list = [20, 40, 60] +theta = 45 +for u in u_list: + draw_trajectory(u, theta) + # Add a legend and show the graph + plt.legend(['20', '40', '60']) + plt.show() +fig + + + + diff --git a/explorations/PyScript/chap2/projectile_motion_comparison_gen.html b/explorations/PyScript/chap2/projectile_motion_comparison_gen.html new file mode 100644 index 0000000..24fa47e --- /dev/null +++ b/explorations/PyScript/chap2/projectile_motion_comparison_gen.html @@ -0,0 +1,88 @@ + + + + + + + - matplotlib + + + + +
+ +""" + +projectile_comparison_gen.py + +Compare the projectile motion of a body thrown with various combinations of initial +velocity and angle of projection. +""" + +import matplotlib.pyplot as plt +import math + +g = 9.8 + +def draw_graph(x, y): + plt.plot(x, y) + plt.xlabel('x-coordinate') + plt.ylabel('y-coordinate') + plt.title('Projectile motion at different initial velocities and angles') + +def frange(start, final, interval): + + numbers = [] + while start < final: + numbers.append(start) + start = start + interval + + return numbers + +def draw_trajectory(u, theta, t_flight): + # list of x and y co-ordinates + x = [] + y = [] + intervals = frange(0, t_flight, 0.001) + for t in intervals: + x.append(u*math.cos(theta)*t) + y.append(u*math.sin(theta)*t - 0.5*g*t*t) + + #create the graph + draw_graph(x, y) + +fig = plt.figure() +if __name__ == '__main__': + + num_trajectories = int(input('How many trajectories? ')) + + velocities = [] + angles = [] + for i in range(1, num_trajectories+1): + v = input('Enter the initial velocity for trajectory {0} (m/s): '.format(i)) + theta = input('Enter the angle of projection for trajectory {0} (degrees): '.format(i)) + velocities.append(float(v)) + angles.append(math.radians(float(theta))) + + for i in range(num_trajectories): + # calculate time of flight, maximum horizontal distance and + # maximum vertical distance + t_flight = 2*velocities[i]*math.sin(angles[i])/g + S_x = velocities[i]*math.cos(angles[i])*t_flight + S_y = velocities[i]*math.sin(angles[i])*(t_flight/2) - (1/2)*g*(t_flight/2)**2 + print('Initial velocity: {0} Angle of Projection: {1}'.format(velocities[i], math.degrees(angles[i]))) + print('T: {0} S_x: {1} S_y: {2}'.format(t_flight, S_x, S_y)) + print() + draw_trajectory(velocities[i], angles[i], t_flight) + + # Add a legend and show the graph + legends = [] + for i in range(0, num_trajectories): + legends.append('{0} - {1}'.format(velocities[i], math.degrees(angles[i]))) + plt.legend(legends) + plt.show() +fig + + + + diff --git a/explorations/PyScript/chap2/pylab_demo.html b/explorations/PyScript/chap2/pylab_demo.html new file mode 100644 index 0000000..891d16e --- /dev/null +++ b/explorations/PyScript/chap2/pylab_demo.html @@ -0,0 +1,30 @@ + + + + + + + - matplotlib + + + + +
+ +x_numbers = [1, 2, 3] +y_numbers = [2, 4, 6] +import matplotlib.pyplot as plt +fig = plt.figure() + +from pylab import plot, show +plot(x_numbers, y_numbers) +fig + +print("hello world!!") +#import matplotlib.pyplot as plt +#plt.plot(x_numbers, y_numbers) +#plt + + + + \ No newline at end of file diff --git a/explorations/PyScript/chap2/pyowm_pyodide.html b/explorations/PyScript/chap2/pyowm_pyodide.html new file mode 100644 index 0000000..5aa1cd2 --- /dev/null +++ b/explorations/PyScript/chap2/pyowm_pyodide.html @@ -0,0 +1,83 @@ + + + + + + + Pyodide test page
+ Open your browser console to see Pyodide output + + + diff --git a/explorations/PyScript/chap2/pyplot_demo_1.html b/explorations/PyScript/chap2/pyplot_demo_1.html new file mode 100644 index 0000000..6029b10 --- /dev/null +++ b/explorations/PyScript/chap2/pyplot_demo_1.html @@ -0,0 +1,27 @@ + + + + + + + - matplotlib + + + + +
+ +import matplotlib.pyplot + +def create_graph(): + x_numbers = [1, 2, 3] + y_numbers = [2, 4, 6] + matplotlib.pyplot.plot(x_numbers, y_numbers) + +fig = matplotlib.pyplot.figure() +create_graph() +fig + + + + diff --git a/explorations/PyScript/hello.html b/explorations/PyScript/hello.html new file mode 100644 index 0000000..83c309c --- /dev/null +++ b/explorations/PyScript/hello.html @@ -0,0 +1,20 @@ + + + + + + + - matplotlib + + + + +
+ +import matplotlib.pyplot as plt +plt.plot([1,2,3], [4,5,6]) +plt + + + + diff --git a/explorations/trailing_zeros/trailing_zeros.png b/explorations/trailing_zeros/trailing_zeros.png new file mode 100644 index 0000000..8d833ec Binary files /dev/null and b/explorations/trailing_zeros/trailing_zeros.png differ diff --git a/explorations/trailing_zeros/trailing_zeros.py b/explorations/trailing_zeros/trailing_zeros.py new file mode 100644 index 0000000..9a8ccd1 --- /dev/null +++ b/explorations/trailing_zeros/trailing_zeros.py @@ -0,0 +1,43 @@ +# This program will print the number of trailing zeros the factorial +# of a number +# The formula and the associated explanations are available at: +# https://brilliant.org/wiki/trailing-number-of-zeros/ + +# Notes on the Python implementation are available on https://doingmathwithpython.github.io + +import math + + +def is_positive_integer(x): + try: + x = float(x) + except ValueError: + return False + else: + if x.is_integer() and x > 0: + return True + else: + return False + + +def trailing_zeros(num): + if is_positive_integer(num): + # The above function call has done all the sanity checks for us + # so we can just convert this into an integer here + num = int(num) + + k = math.floor(math.log(num, 5)) + zeros = 0 + for i in range(1, k + 1): + zeros = zeros + math.floor(num/math.pow(5, i)) + return zeros + else: + print("Factorial of a non-positive non-integer is undefined") + + +if __name__ == "__main__": + fact_num = input( + "Enter the number whose factorial's trailing zeros you want to find: " + ) + num_zeros = trailing_zeros(fact_num) + print("Number of trailing zeros: {0}".format(num_zeros)) diff --git a/explorations/trailing_zeros/trailing_zeros_plot.py b/explorations/trailing_zeros/trailing_zeros_plot.py new file mode 100644 index 0000000..47cc13f --- /dev/null +++ b/explorations/trailing_zeros/trailing_zeros_plot.py @@ -0,0 +1,48 @@ +# This program will print the number of trailing zeros the factorial +# of a number +# The formula and the associated explanations are available at: +# https://brilliant.org/wiki/trailing-number-of-zeros/ + +# Notes on the Python implementation are available on https://doingmathwithpython.github.io + +import math +import matplotlib.pyplot as plt + + +def is_positive_integer(x): + try: + x = float(x) + except ValueError: + return False + else: + if x.is_integer() and x > 0: + return True + else: + return False + + +def trailing_zeros(num): + if is_positive_integer(num): + # The above function call has done all the sanity checks for us + # so we can just convert this into an integer here + num = int(num) + + k = math.floor(math.log(num, 5)) + zeros = 0 + for i in range(1, k + 1): + zeros = zeros + math.floor(num/math.pow(5, i)) + return zeros + else: + print("Factorial of a non-positive integer is undefined") + + +if __name__ == "__main__": + num_range = range(5, 10000, 10) + zeros = [] + for num in num_range: + num_zeros = trailing_zeros(num) + zeros.append(num_zeros) + for x, y in zip(num_range, zeros): + print(x,y) + plt.plot(num_range, zeros) + plt.savefig('trailing_zeros.png') diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..069c25c --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +matplotlib +sympy +matplotlib-venn + +# secondary dependencies for solutions +pyowm +pytz