diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 95b6c3c..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..afc9998 --- /dev/null +++ b/.gitignore @@ -0,0 +1,69 @@ +# These are some examples of commonly ignored file patterns. +# You should customize this list as applicable to your project. +# Learn more about .gitignore: +# https://www.atlassian.com/git/tutorials/saving-changes/gitignore + +# Project specifics +sandbox.py +sandbox/ + + + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class +# Virtualenv +venv/ +.vscode/ +# Project specific +*.egg-info.egg-info/ +*.egg-info + +# Sanbox file +sandbox/ + +# Node artifact files +node_modules/ +dist/ + +# Compiled Java class files +*.class + +# Compiled Python bytecode +*.py[cod] + +# Log files +*.log + +# Package files +*.jar + +# Maven +target/ +dist/ + +# JetBrains IDE +.idea/ + +# Unit test reports +TEST*.xml + +# Generated by MacOS +.DS_Store + +# Generated by Windows +Thumbs.db + +# Applications +*.app +*.exe +*.war + +# Large media files +*.mp4 +*.tiff +*.avi +*.flv +*.mov +*.wmv diff --git a/Assignment/.DS_Store b/Assignment/.DS_Store deleted file mode 100644 index 3023cf2..0000000 Binary files a/Assignment/.DS_Store and /dev/null differ diff --git a/Assignment/A1/.DS_Store b/Assignment/A1/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/Assignment/A1/.DS_Store and /dev/null differ diff --git a/Assignment/A1/.ipynb_checkpoints/assignment1-checkpoint.ipynb b/Assignment/A1/.ipynb_checkpoints/assignment1-checkpoint.ipynb deleted file mode 100644 index 5a1a9ad..0000000 --- a/Assignment/A1/.ipynb_checkpoints/assignment1-checkpoint.ipynb +++ /dev/null @@ -1,454 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "17e335f5", - "metadata": {}, - "source": [ - "### Question 1.31" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b3cefb27", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.31.in\n", - "# 3\n", - "# 21/02/2021 21/02/2021\n", - "# 01/03/2021 20/04/2021\n", - "# 10/12/2021 07/01/2022" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "a98db412", - "metadata": {}, - "outputs": [], - "source": [ - "def validate_hour(day):\n", - " if int(day[::-1]) < 24:\n", - " return True\n", - " else:\n", - " return False" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "34a9b35a", - "metadata": {}, - "outputs": [], - "source": [ - "def days_in_month(y, m):\n", - " y, m = int(y), int(m)\n", - " leap = 0\n", - " if y % 400 == 0:\n", - " leap = 1\n", - " elif y % 100 == 0:\n", - " leap = 0\n", - " elif y % 4 == 0:\n", - " leap = 1\n", - " if m==2:\n", - " return 28 + leap\n", - " list = [1,3,5,7,8,10,12]\n", - " if m in list:\n", - " return 31\n", - " return 30" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "77010103", - "metadata": {}, - "outputs": [], - "source": [ - "def months(start_month, start_year, end_month, end_year):\n", - " excluded_months = [6,7,8,9]\n", - " if int(start_year) == int(end_year):\n", - " month_list = [month for month in range(int(start_month), int(end_month)+1)]\n", - " else:\n", - " month_list = [month for month in range(int(start_month), 12+1)] + [month for month in range(1,int(end_month)+1)]\n", - "\n", - " #excluding the month 06, 07,08,09 as reversing them 60,70,80,90 over minutes as for min: up to 59th min only\n", - " month_list = [f\"{month:02d}\" for month in month_list if month not in excluded_months]\n", - " #print(month_list)\n", - " return month_list\n", - "\n", - "#months(\"12\", \"2021\", \"01\", \"2022\")\n", - "#months(\"03\", \"2021\", \"07\", \"2022\") \n", - "#months(\"02\", \"2021\", \"02\", \"2021\") " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "57e87762", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "02:21:12:20\n", - "-----------\n", - "03:01:10:30\n", - "03:02:20:30\n", - "03:10:01:30\n", - "03:11:11:30\n", - "03:12:21:30\n", - "03:20:02:30\n", - "03:21:12:30\n", - "03:22:22:30\n", - "03:30:03:30\n", - "03:31:13:30\n", - "04:01:10:40\n", - "04:02:20:40\n", - "04:10:01:40\n", - "04:11:11:40\n", - "04:12:21:40\n", - "04:20:02:40\n", - "-----------\n", - "12:10:01:21\n", - "12:11:11:21\n", - "12:12:21:21\n", - "12:20:02:21\n", - "12:21:12:21\n", - "12:22:22:21\n", - "12:30:03:21\n", - "12:31:13:21\n", - "01:01:10:10\n", - "01:02:20:10\n" - ] - } - ], - "source": [ - "fin = open('Q1.31.in')\n", - "num_case = int(fin.readline())\n", - "day, month, year = 0,1,2\n", - "for i in range(num_case):\n", - " if i:\n", - " print('-' * 11)\n", - " start, end = fin.readline().split()\n", - " start, end = start.split(\"/\"), end.split(\"/\")\n", - " #identify possible months lists \n", - " month_list = months(start[month], start[year], end[month], end[year])\n", - " #for each month, we need to find possible a \"days\" list\n", - " for m in month_list:\n", - " if m == start[month] and m !=end[month]:\n", - " days = [day for day in range(int(start[day]), days_in_month(start[year], m)+1)]\n", - " elif m == start[month] and m ==end[month]:\n", - " days = [day for day in range(int(start[day]), int(start[day])+1)]\n", - " elif m == end[month]:\n", - " days = [day for day in range(1, int(end[day])+1)]\n", - " else:\n", - " days = [day for day in range(1, days_in_month(start[year], m)+1)]\n", - " #print(m, days)\n", - " days = [f\"{d:02d}\" for d in days]\n", - " for d in days:\n", - " if validate_hour(d):\n", - " print(f\"{m}:{d}:{d[::-1]}:{m[::-1]}\")" - ] - }, - { - "cell_type": "markdown", - "id": "09dcec18", - "metadata": {}, - "source": [ - "### Question 1.32" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "c85cd2a5", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.32.in\n", - "# 2\n", - "# 8 9\n", - "# 10 10" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "3f3e6fae", - "metadata": {}, - "outputs": [], - "source": [ - "def max_chair(p,q):\n", - " r = 0.5\n", - " pack_long = p #if chair packing along width or length\n", - " d = q #d: total length of number of row of chairs\n", - "\n", - " rec_chair = int((pack_long+1)/(r*2)) #No. of chair based on Rec\n", - " tri_chair = rec_chair -1 #No. of chair based on Tri \n", - " #print(rec_chair, tri_chair)\n", - " max_chair = float(\"-inf\")\n", - " #pos_m, pos_n = 0,0\n", - " # m*[r*sqrt(3)] + n*(2r) = d, with the constraint: m from 0 to d/(r*sqrt(3)) and n from 0 to d/2r\n", - " for m in range(0, int(math.ceil(d/(math.sqrt(3)*r)))+1):\n", - " for n in range(0, int(math.ceil(d/2*r))+1):\n", - " if (math.ceil(m*r*(math.sqrt(3)) + 2*r*n) == float(d)):\n", - " total_chair = 0\n", - " for i in range(m+1):\n", - " if i%2 == 0:\n", - " total_chair+=rec_chair\n", - " else:\n", - " total_chair+=tri_chair\n", - " total_chair+= n*rec_chair\n", - " if total_chair > max_chair:\n", - " max_chair = total_chair\n", - " #pos_m, pos_n = m,n\n", - " return max_chair" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "1eaa9db3", - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "96\n", - "128\n" - ] - } - ], - "source": [ - "import math\n", - "\n", - "fin = open('Q1.32.in')\n", - "num_case = int(fin.readline())\n", - "for i in range(num_case):\n", - " p, q = [int(s) for s in fin.readline().split()]\n", - " print(max(max_chair(p,q), max_chair(q,p)))" - ] - }, - { - "cell_type": "markdown", - "id": "7edc77b5", - "metadata": {}, - "source": [ - "### Question 1.33" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "fbe6b41e", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.33.in\n", - "# 4 18 5 0 10 10 60 40 20 30 28 36\n", - "# 20 10 30 50" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "dd179bb1", - "metadata": {}, - "outputs": [], - "source": [ - "fin = open('Q1.33.in')\n", - "\n", - "height = [int(s) for s in fin.readline().split()]\n", - "rainfall = [int(s) for s in fin.readline().split()]" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "27c57485", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[4, 18, 5, 0, 10, 10, 60, 40, 20, 30, 28, 36]" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "height" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "id": "0b6498ca", - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import matplotlib.pyplot as plt\n", - "\n", - "# function to add value labels\n", - "def addlabels(x,y):\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "id": "9913b732", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "x = [i for i in range(len(height))]\n", - "new_height = [4, 18, 5, 5, 10, 10, 60, 40, 20, 30, 30, 36]\n", - "# 2. Setup plot\n", - "fig, ax = plt.subplots(figsize=(6,8)) #Figure size = Width & Height of the Plot\n", - "\n", - "# 3. Plot data\n", - "ax.bar(x, new_height, width=1.0, color=\"blue\")\n", - "ax.bar(x, height, width=1.0, color=\"black\")\n", - "\n", - "for i in range(len(x)):\n", - " ax.text(i, height[i]-3, height[i], ha = 'center', c=\"white\", size=\"large\")\n", - "\n", - "\n", - "ax.set_xlim(-0.5,len(height)-0.5)\n", - "ax.set_ylim(0, 70);" - ] - }, - { - "cell_type": "markdown", - "id": "bdfdd782", - "metadata": {}, - "source": [ - "### Question 1.34" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "18a44639", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.34.in\n", - "# conjugate continuous\n", - "# convergence\n", - "# convex conjunction\n", - "# congruent concrete\n", - "# conjecture concave\n", - "# consecutive constant concentric" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "eff7b97f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['conjugate', 'continuous', 'convergence', 'convex', 'conjunction', 'congruent', 'concrete', 'conjecture', 'concave', 'consecutive', 'constant', 'concentric']\n" - ] - } - ], - "source": [ - "fin = open('Q1.34.in')\n", - "words = [word for word in fin.read().split()]\n", - "print(words)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "29de5070", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "convex\n", - "concave\n", - "concrete\n", - "constant\n", - "congruent\n", - "conjugate\n", - "concentric\n", - "conjecture\n", - "continuous\n", - "conjunction\n", - "consecutive\n", - "convergence\n" - ] - } - ], - "source": [ - "words.sort()\n", - "words = sorted(words, key=lambda x: len(x))\n", - "\n", - "for word in words:\n", - " print(word)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd9c4a39", - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/Assignment/A1/Q1.31.in b/Assignment/A1/Q1.31.in deleted file mode 100644 index 55a6269..0000000 --- a/Assignment/A1/Q1.31.in +++ /dev/null @@ -1,4 +0,0 @@ -3 -21/02/2021 21/02/2021 -01/03/2021 20/04/2021 -10/12/2021 07/01/2022 diff --git a/Assignment/A1/Q1.32.in b/Assignment/A1/Q1.32.in deleted file mode 100644 index cdeebf4..0000000 --- a/Assignment/A1/Q1.32.in +++ /dev/null @@ -1,3 +0,0 @@ -2 -8 9 -10 10 diff --git a/Assignment/A1/Q1.33.in b/Assignment/A1/Q1.33.in deleted file mode 100644 index 29b0587..0000000 --- a/Assignment/A1/Q1.33.in +++ /dev/null @@ -1,2 +0,0 @@ -4 18 5 0 10 10 60 40 20 30 28 36 -20 10 30 50 diff --git a/Assignment/A1/Q1.34.in b/Assignment/A1/Q1.34.in deleted file mode 100644 index c4a0332..0000000 --- a/Assignment/A1/Q1.34.in +++ /dev/null @@ -1,6 +0,0 @@ -conjugate continuous -convergence -convex conjunction -congruent concrete -conjecture concave -consecutive constant concentric diff --git a/Assignment/A1/assignment1.ipynb b/Assignment/A1/assignment1.ipynb deleted file mode 100644 index 5a1a9ad..0000000 --- a/Assignment/A1/assignment1.ipynb +++ /dev/null @@ -1,454 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "17e335f5", - "metadata": {}, - "source": [ - "### Question 1.31" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "b3cefb27", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.31.in\n", - "# 3\n", - "# 21/02/2021 21/02/2021\n", - "# 01/03/2021 20/04/2021\n", - "# 10/12/2021 07/01/2022" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "a98db412", - "metadata": {}, - "outputs": [], - "source": [ - "def validate_hour(day):\n", - " if int(day[::-1]) < 24:\n", - " return True\n", - " else:\n", - " return False" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "34a9b35a", - "metadata": {}, - "outputs": [], - "source": [ - "def days_in_month(y, m):\n", - " y, m = int(y), int(m)\n", - " leap = 0\n", - " if y % 400 == 0:\n", - " leap = 1\n", - " elif y % 100 == 0:\n", - " leap = 0\n", - " elif y % 4 == 0:\n", - " leap = 1\n", - " if m==2:\n", - " return 28 + leap\n", - " list = [1,3,5,7,8,10,12]\n", - " if m in list:\n", - " return 31\n", - " return 30" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "77010103", - "metadata": {}, - "outputs": [], - "source": [ - "def months(start_month, start_year, end_month, end_year):\n", - " excluded_months = [6,7,8,9]\n", - " if int(start_year) == int(end_year):\n", - " month_list = [month for month in range(int(start_month), int(end_month)+1)]\n", - " else:\n", - " month_list = [month for month in range(int(start_month), 12+1)] + [month for month in range(1,int(end_month)+1)]\n", - "\n", - " #excluding the month 06, 07,08,09 as reversing them 60,70,80,90 over minutes as for min: up to 59th min only\n", - " month_list = [f\"{month:02d}\" for month in month_list if month not in excluded_months]\n", - " #print(month_list)\n", - " return month_list\n", - "\n", - "#months(\"12\", \"2021\", \"01\", \"2022\")\n", - "#months(\"03\", \"2021\", \"07\", \"2022\") \n", - "#months(\"02\", \"2021\", \"02\", \"2021\") " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "57e87762", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "02:21:12:20\n", - "-----------\n", - "03:01:10:30\n", - "03:02:20:30\n", - "03:10:01:30\n", - "03:11:11:30\n", - "03:12:21:30\n", - "03:20:02:30\n", - "03:21:12:30\n", - "03:22:22:30\n", - "03:30:03:30\n", - "03:31:13:30\n", - "04:01:10:40\n", - "04:02:20:40\n", - "04:10:01:40\n", - "04:11:11:40\n", - "04:12:21:40\n", - "04:20:02:40\n", - "-----------\n", - "12:10:01:21\n", - "12:11:11:21\n", - "12:12:21:21\n", - "12:20:02:21\n", - "12:21:12:21\n", - "12:22:22:21\n", - "12:30:03:21\n", - "12:31:13:21\n", - "01:01:10:10\n", - "01:02:20:10\n" - ] - } - ], - "source": [ - "fin = open('Q1.31.in')\n", - "num_case = int(fin.readline())\n", - "day, month, year = 0,1,2\n", - "for i in range(num_case):\n", - " if i:\n", - " print('-' * 11)\n", - " start, end = fin.readline().split()\n", - " start, end = start.split(\"/\"), end.split(\"/\")\n", - " #identify possible months lists \n", - " month_list = months(start[month], start[year], end[month], end[year])\n", - " #for each month, we need to find possible a \"days\" list\n", - " for m in month_list:\n", - " if m == start[month] and m !=end[month]:\n", - " days = [day for day in range(int(start[day]), days_in_month(start[year], m)+1)]\n", - " elif m == start[month] and m ==end[month]:\n", - " days = [day for day in range(int(start[day]), int(start[day])+1)]\n", - " elif m == end[month]:\n", - " days = [day for day in range(1, int(end[day])+1)]\n", - " else:\n", - " days = [day for day in range(1, days_in_month(start[year], m)+1)]\n", - " #print(m, days)\n", - " days = [f\"{d:02d}\" for d in days]\n", - " for d in days:\n", - " if validate_hour(d):\n", - " print(f\"{m}:{d}:{d[::-1]}:{m[::-1]}\")" - ] - }, - { - "cell_type": "markdown", - "id": "09dcec18", - "metadata": {}, - "source": [ - "### Question 1.32" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "c85cd2a5", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.32.in\n", - "# 2\n", - "# 8 9\n", - "# 10 10" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "3f3e6fae", - "metadata": {}, - "outputs": [], - "source": [ - "def max_chair(p,q):\n", - " r = 0.5\n", - " pack_long = p #if chair packing along width or length\n", - " d = q #d: total length of number of row of chairs\n", - "\n", - " rec_chair = int((pack_long+1)/(r*2)) #No. of chair based on Rec\n", - " tri_chair = rec_chair -1 #No. of chair based on Tri \n", - " #print(rec_chair, tri_chair)\n", - " max_chair = float(\"-inf\")\n", - " #pos_m, pos_n = 0,0\n", - " # m*[r*sqrt(3)] + n*(2r) = d, with the constraint: m from 0 to d/(r*sqrt(3)) and n from 0 to d/2r\n", - " for m in range(0, int(math.ceil(d/(math.sqrt(3)*r)))+1):\n", - " for n in range(0, int(math.ceil(d/2*r))+1):\n", - " if (math.ceil(m*r*(math.sqrt(3)) + 2*r*n) == float(d)):\n", - " total_chair = 0\n", - " for i in range(m+1):\n", - " if i%2 == 0:\n", - " total_chair+=rec_chair\n", - " else:\n", - " total_chair+=tri_chair\n", - " total_chair+= n*rec_chair\n", - " if total_chair > max_chair:\n", - " max_chair = total_chair\n", - " #pos_m, pos_n = m,n\n", - " return max_chair" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "1eaa9db3", - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "96\n", - "128\n" - ] - } - ], - "source": [ - "import math\n", - "\n", - "fin = open('Q1.32.in')\n", - "num_case = int(fin.readline())\n", - "for i in range(num_case):\n", - " p, q = [int(s) for s in fin.readline().split()]\n", - " print(max(max_chair(p,q), max_chair(q,p)))" - ] - }, - { - "cell_type": "markdown", - "id": "7edc77b5", - "metadata": {}, - "source": [ - "### Question 1.33" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "fbe6b41e", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.33.in\n", - "# 4 18 5 0 10 10 60 40 20 30 28 36\n", - "# 20 10 30 50" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "dd179bb1", - "metadata": {}, - "outputs": [], - "source": [ - "fin = open('Q1.33.in')\n", - "\n", - "height = [int(s) for s in fin.readline().split()]\n", - "rainfall = [int(s) for s in fin.readline().split()]" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "27c57485", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[4, 18, 5, 0, 10, 10, 60, 40, 20, 30, 28, 36]" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "height" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "id": "0b6498ca", - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "import matplotlib.pyplot as plt\n", - "\n", - "# function to add value labels\n", - "def addlabels(x,y):\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "id": "9913b732", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "x = [i for i in range(len(height))]\n", - "new_height = [4, 18, 5, 5, 10, 10, 60, 40, 20, 30, 30, 36]\n", - "# 2. Setup plot\n", - "fig, ax = plt.subplots(figsize=(6,8)) #Figure size = Width & Height of the Plot\n", - "\n", - "# 3. Plot data\n", - "ax.bar(x, new_height, width=1.0, color=\"blue\")\n", - "ax.bar(x, height, width=1.0, color=\"black\")\n", - "\n", - "for i in range(len(x)):\n", - " ax.text(i, height[i]-3, height[i], ha = 'center', c=\"white\", size=\"large\")\n", - "\n", - "\n", - "ax.set_xlim(-0.5,len(height)-0.5)\n", - "ax.set_ylim(0, 70);" - ] - }, - { - "cell_type": "markdown", - "id": "bdfdd782", - "metadata": {}, - "source": [ - "### Question 1.34" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "18a44639", - "metadata": {}, - "outputs": [], - "source": [ - "# %load Q1.34.in\n", - "# conjugate continuous\n", - "# convergence\n", - "# convex conjunction\n", - "# congruent concrete\n", - "# conjecture concave\n", - "# consecutive constant concentric" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "eff7b97f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['conjugate', 'continuous', 'convergence', 'convex', 'conjunction', 'congruent', 'concrete', 'conjecture', 'concave', 'consecutive', 'constant', 'concentric']\n" - ] - } - ], - "source": [ - "fin = open('Q1.34.in')\n", - "words = [word for word in fin.read().split()]\n", - "print(words)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "29de5070", - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "convex\n", - "concave\n", - "concrete\n", - "constant\n", - "congruent\n", - "conjugate\n", - "concentric\n", - "conjecture\n", - "continuous\n", - "conjunction\n", - "consecutive\n", - "convergence\n" - ] - } - ], - "source": [ - "words.sort()\n", - "words = sorted(words, key=lambda x: len(x))\n", - "\n", - "for word in words:\n", - " print(word)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bd9c4a39", - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/Assignment/A1/assignment1_Sep9.pdf b/Assignment/A1/assignment1_Sep9.pdf deleted file mode 100644 index 4ee5fd1..0000000 Binary files a/Assignment/A1/assignment1_Sep9.pdf and /dev/null differ diff --git a/README.md b/README.md index 9dab691..41d9fde 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ # Python + Python Programming and Data Analysis # Table of contents + - [Table of contents](#table-of-contents) -- [0. Common Syntax](./Readings/common_syntax.md) +- [0. Common Syntax](./docs/common_syntax.md) - [1. Basics](#1-basics) - [1.1. Naming Convention](#11-naming-convention) - [1.2 Operators](#12-operators) @@ -14,11 +16,11 @@ Python Programming and Data Analysis - [2.2. Variable Scopes](#22-variable-scopes) - [3. Lambda Expressions](#3-lambda-expressions) - [3.1. Sorted](#31-sorted) - - [3.2. Filter and Map](#32-filter-and-map) + - [3.2. Filter and Map](#32-filter-and-map) - [4. Module](#4-module) - [5. Class](#5-class) - [5.1. Object](#51-Object) - - [5.1.1. Variable Assignment and Aliasing](#511-variable-assignment-and-aliasing) + - [5.1.1. Variable Assignment and Aliasing](#511-variable-assignment-and-aliasing) - [5.1.2. Comparison Operators](#512-comparison-operators) - [5.1.3. Integer Caching](#513-integer-caching) - [5.1.4. Shallow Copy vs Deep Copy](#514-shallow-copy-vs-deep-copy) @@ -28,52 +30,60 @@ Python Programming and Data Analysis - [5.4. Magic Methods](#54-magic-methods) - [6. Regular Expression](#6-regular-expression) - [6.0. Regex Summary](#60-regex-summary) - - [6.1. What is Regex](#61-what-is-regex) + - [6.1. What is Regex](#61-what-is-regex) - [6.2. Search for a pattern](#62-search-for-a-pattern) - [6.3. Metacharacters](#63-metacharacters) - [6.4. Grouping Constructs](#64-grouping-constructs) - [6.5. Flags](#65-flags) - [6.6. Module-Level re Methods](#66-module-level-re-methods) - [6.7. Look ahead & Look behind](#67-look-ahead-and-look-behind) -- [7. Numpy](./Readings/numpy.md) -- [8. Pandas](./Readings/pandas.md) -- [9. Matplotlib](./Readings/matplotlib.md) +- [7. Numpy](./docs/numpy.md) +- [8. Pandas](./docs/pandas.md) +- [9. Matplotlib](./docs/matplotlib.md) # 1. Basics + ## 1.1. Naming Convention +

Screenshot 2021-09-08 at 22 32 46

## 1.2. Operators -* **4 Bascis Data Types**: String, Integer, Float and Boolean -* **Logical Variable**: `not`, `and`, `or` - -| Operator | Name | Description | -|--------------|----------------|--------------------------------------------------------| -| ``a / b`` | True division | Quotient of ``a`` and ``b`` | -| ``a // b`` | Floor division | Quotient of ``a`` and ``b``, removing fractional parts | -| ``a % b`` | Modulus | Integer remainder after division of ``a`` by ``b`` | -| ``a ** b`` | Exponentiation | ``a`` raised to the power of ``b`` | -* **Membership Operators**: `in` and `not in` -* **Identify Operators**: `is` and `is not` to identify if 2 variables are same class + +- **4 Bascis Data Types**: String, Integer, Float and Boolean +- **Logical Variable**: `not`, `and`, `or` + +| Operator | Name | Description | +| -------- | -------------- | -------------------------------------------------- | +| `a / b` | True division | Quotient of `a` and `b` | +| `a // b` | Floor division | Quotient of `a` and `b`, removing fractional parts | +| `a % b` | Modulus | Integer remainder after division of `a` by `b` | +| `a ** b` | Exponentiation | `a` raised to the power of `b` | + +- **Membership Operators**: `in` and `not in` +- **Identify Operators**: `is` and `is not` to identify if 2 variables are same class + ```Python x =5 type(x) is int #True ``` ## 1.3. Iterables and Iterators + - **iterable**: types of iterables - list/tuple/str/dict - zip/enumerate/range/reversed - **iterator**: An iterable can be passed to the built-in function `iter()`, which returns some object called **iterator** + ```Python -it = iter([4, 3, 2, 1]) +it = iter([4, 3, 2, 1]) print(next(it))#4 print(next(it))#3 ``` -

Screenshot 2021-09-08 at 22 32 46

+

Screenshot 2021-09-08 at 22 32 46

## 1.4. Zip and Enumerate + - `zip()`: to zip 2 lists together - `enumerate()`: to return both item & index corresponding to that item in the list @@ -85,6 +95,7 @@ print(next(it))#3 >>> list(zipped) [(1, 'a', 4.0), (2, 'b', 5.0), (3, 'c', 6.0)] ``` + ```Python l1 = ['h', 'e', 'l', 'l', 'o'] for idx, item in enumerate(l1): @@ -100,71 +111,88 @@ for idx, item in enumerate(l1): [(Back to top)](#table-of-contents) # 2. Functions -## 2.1. Argument Types + +## 2.1. Argument Types + - **2.1.1. Positional Arguments** - **2.1.2. Keyword Arguments** - **2.1.3. Default Arguments** - **2.1.4. Variable-Length Arguments** - 1) `*args` (Non-Keyword Arguments): extra arguments can be tacked on to your current formal parameters (including zero extra arguments) - 2) `**kwargs` (Keyword Arguments) : dictionary that maps each keyword to the value that we pass alongside it - **Example of** `*args` - ```Python - def info(name, *args): - hobby = [] - for a in args: - hobby.append(a) - print(name +"'s hobbies: " + ', '.join(hobby)) - info('Mike') #Mike's hobbies: - info('Mike', 'hiking', 'reading') #Mike's hobbies: hiking, reading - ``` - **Example of** `**kwargs` - ```Python - def info(name, **kwargs): - hobby = [] - for k, v in kwargs.items(): - hobby.append(k+'-'+v) - print(name +"'s hobbies: " + ', '.join(hobby)) - info('Mike', first='hiking', second='reading') #Mike's hobbies: first-hiking, second-reading - ``` + 1. `*args` (Non-Keyword Arguments): extra arguments can be tacked on to your current formal parameters (including zero extra arguments) + 2. `**kwargs` (Keyword Arguments) : dictionary that maps each keyword to the value that we pass alongside it + + **Example of** `*args` + + ```Python + def info(name, *args): + hobby = [] + for a in args: + hobby.append(a) + print(name +"'s hobbies: " + ', '.join(hobby)) + info('Mike') #Mike's hobbies: + info('Mike', 'hiking', 'reading') #Mike's hobbies: hiking, reading + ``` + + **Example of** `**kwargs` + + ```Python + def info(name, **kwargs): + hobby = [] + for k, v in kwargs.items(): + hobby.append(k+'-'+v) + print(name +"'s hobbies: " + ', '.join(hobby)) + info('Mike', first='hiking', second='reading') #Mike's hobbies: first-hiking, second-reading + ``` [(Back to top)](#table-of-contents) ## 2.2. Variable Scopes + - There are 2 types of Variable: `Local` and `Global` scope - - `global` variable + + - `global` variable ```Python y = 'global' - def test(): + def test(): global y #This to declare y is global scope print(y) test() #will print 'global' ``` -[(Back to top)](#table-of-contents) + + [(Back to top)](#table-of-contents) # 3. Lambda Expressions + - Syntax: `lambda argument_list: expression` - - **argument_list** (same as argument list in functions): `x,y, *arg, **kwargs` + - **argument_list** (same as argument list in functions): `x,y, *arg, **kwargs` - **expression** (Output) must be single line -**Example of** `lambda` +**Example of** `lambda` + ```Python lambda x, y: x*y #input: x, y; output: x*y lambda *args: sum(args). #input: any number of parameters; output: their summation lambda x: 1 #input: x; output: 1 ``` + ## 3.1. Sorted + - Syntax: `sorted(iterable, key=None, reverse=False)` sorts the elements in the given iterable by key + ```Python sorted([1, 2, 3, 4, 5], key = lambda x: abs(3 - x)) #[3, 2, 4, 1, 5] ``` + ## 3.2. Filter and Map + - **Filter** syntax: `filter(function, iterable)` filters the given iterable (list) based on the given function -- **Map** syntax : `map(function, iterable)` applies a given function to each item of the given iterable +- **Map** syntax : `map(function, iterable)` applies a given function to each item of the given iterable - Note: Both Filter and Map will return **Iterable Object**, so need to use `list()` function to convert to a lsit -**Example of** `filter` and `map` +**Example of** `filter` and `map` + ```Python list(filter(lambda n: n % 2 == 1, [1, 2, 3, 4, 5])) #[1, 3, 5] @@ -174,7 +202,9 @@ list(map(lambda x: x + 1, [1, 2, 3])) #[2, 3, 4] [(Back to top)](#table-of-contents) # 4. Module + ## 4.1. Random Module + ```Python import random random.seed(42) #make results reproducible, @@ -204,22 +234,26 @@ random.shuffle(items) #randomize a sequence in-place [(Back to top)](#table-of-contents) # 5. Class +

Screenshot 2021-09-08 at 22 38 12

## 5.1. Object + ### 5.1.1. Variable Assignment and Aliasing + - **Aliasing**: many variables (a,b) refer to the same object list `[1,2]`

Screenshot 2021-09-08 at 22 52 48

### 5.1.2. Comparison Operators + - `==`: compares the values of the object - `is`: compares objects ```Python a = [1,2] -b = [1,2] +b = [1,2] -print(id(a)) #2661200625736 +print(id(a)) #2661200625736 print(id(b)) #2661202091528 a == b #True @@ -227,11 +261,13 @@ a is b #False ``` ### 5.1.3. Integer Caching -- In Python, interpreters will typically cache small integers in the range of -5 to 256. + +- In Python, interpreters will typically cache small integers in the range of -5 to 256. - When the Python interpreter is launched, these integer objects will be created and available for later use in the memory.

Screenshot 2021-09-08 at 23 32 57

### 5.1.4. Shallow Copy vs Deep Copy + ```Python import copy a = [[0, 1], 2, 3] @@ -240,78 +276,90 @@ c = copy.deepcopy(a) ``` #### Shallow Copy - copy() -- Shallow Copy will **only create a new object for the parent layer**. + +- Shallow Copy will **only create a new object for the parent layer**. - It will **NOT** create a new object **for any of the child layer**.

Screenshot 2021-09-08 at 23 38 28

#### Deep Copy - deepcopy() -- Deep Copy will **create new objects for the parent & child layers**. + +- Deep Copy will **create new objects for the parent & child layers**.

Screenshot 2021-09-08 at 23 45 50

### 5.1.5. Data Mutability -- **Immutable** (when values are changed, a new object will be created): integers, strings, and tuples -- **Mutable** (values can be changed after creation): lists, dictionaries, and sets + +- **Immutable** (when values are changed, a new object will be created): integers, strings, and tuples +- **Mutable** (values can be changed after creation): lists, dictionaries, and sets

Screenshot 2021-09-09 at 04 35 03

[(Back to top)](#table-of-contents) ## 5.2. Class + ### 5.2.1. Class Definition + - **Class** is a "blue-print" for creating **Object** - - For example: Cars may not be exactly same, but the structures are same. -

Screenshot 2021-09-09 at 04 38 24

+ - For example: Cars may not be exactly same, but the structures are same. +

Screenshot 2021-09-09 at 04 38 24

### 5.2.2. Class Syntax -- **Class attribute**: `Student.num_of_stu` is an attribute for the whole class, *cannot* use self.num_of_stu + +- **Class attribute**: `Student.num_of_stu` is an attribute for the whole class, _cannot_ use self.num_of_stu - **Init method**: `__init__` & using self as the first argument - **Class Method**: at least one argument – self and can be include other method argument like `birth_year` ```Python class Student: #Class attribute - num_of_stu = 0 - + num_of_stu = 0 + #Special init method def __init__(self, first, last): #use self as the first argument self.first = first self.last = last self.email = first + '.' + last + '@smu.edu.sg' Student.num_of_stu += 1 #attribute for the whole class, cannot use self.num_of_stu - + def full_name(self, birth_year): #Method, we have at least one argument – self & birth_year - return self.first + ' ' + self.last + ' was born in ' + birth_year + return self.first + ' ' + self.last + ' was born in ' + birth_year -print(Student.num_of_stu) #0 -stu_1 = Student('Ryan','Tan') +print(Student.num_of_stu) #0 +stu_1 = Student('Ryan','Tan') stu_1.full_name('1995') # "Ryan Tan was born in 1995" print(Student.num_of_stu) #1 ``` ## 5.3. Inheritance + - For example, Create `Representative` class based on the `Student` class - `super()`: to inherite all the attributes in parent class & Initiate more information than parent class - **Override**: to override the method of parent class + ```Python class Rep(Student): def __init__(self, first, last, cat): - #parent class Student handles existing arguments + #parent class Student handles existing arguments super().__init__(first, last) #new information - self.cat = cat + self.cat = cat def full_name(self): #override the full_name method of parent - return self.cat + ' representative: ' + super().full_name() + return self.cat + ' representative: ' + super().full_name() ``` + [(Back to top)](#table-of-contents) ## 5.4. Magic Methods -- Magic methods in Python are the special methods that start and end with the double underscores __ + +- Magic methods in Python are the special methods that start and end with the double underscores \_\_ - Built-in classes in Python define many magic methods. Use the `dir()` function to see the number of magic methods inherited by a class. ```Python >>> dir(int) ['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', ...] ``` - Magic methods are most **frequently used to define behaviors of predefined operators** in Python + - For example: `__str__()` method is executed when we want to `print` an object in a printable format. We can override the functionality of the `__str__()` method. As an instance: + ```Python class Human: def __init__(self, id, name, addresses=[], maps={}): @@ -326,36 +374,41 @@ class Rep(Student): print(human) #Id 1: Quan Nguyen ``` - [(Back to top)](#table-of-contents) - # 6. Regular Expression + ## 6.0. Regex Summary -- **Character class**: `[]` specify a set of characters to match -- **Metacharacters**: `\w` [a-zA-Z0-9_], `\W` [^a-zA-Z0-9_], `\d`, `\D`, `\s` (white-space), `\S` (non white-space), `.` match anything except \n -- `\` to remove special meaning of the metacharacter. For example: [\.] means match "." dot in the text, not mean match anything -- **Anchors**: `^`, `$`, `\b` to get grid of \n at beginning & end of text: + +- **Character class**: `[]` specify a set of characters to match +- **Metacharacters**: `\w` [a-zA-Z0-9_], `\W` [^a-za-z0-9_], `\d`, `\D`, `\s` (white-space), `\S` (non white-space), `.` match anything except \n +- `\` to remove special meaning of the metacharacter. For example: [\.] means match "." dot in the text, not mean match anything +- **Anchors**: `^`, `$`, `\b` to get grid of \n at beginning & end of text: - `^` beginning of text line, `$` end of text line: use `re.M` to match the beginning ^ /end $ pattern in multiple lines - `\b` word boundary match until last word character `[a-zA-Z0-9_]` -- **Quantifiers**: `*` zero or more , `?` zero or one, `+` one or more, `{m}` m repetitions, `{m, n}` any number of repetitions from m to n, inclusive: to repeating literal/metacharacter/group/backreference +- **Quantifiers**: `*` zero or more , `?` zero or one, `+` one or more, `{m}` m repetitions, `{m, n}` any number of repetitions from m to n, inclusive: to repeating literal/metacharacter/group/backreference - **Group**: to keep certain part out of the entire match, or match a repeat with backref - **Backreference**: Numbered groups: `\1`, `\2`, `\3` numbering: from out to in, from left to right - [**Look ahead & Look behind**](#67-look-ahead-and-look-behind) -## 6.1. What is Regex + +## 6.1. What is Regex + - **Regex**: is a tiny programming language used for data manipulation -- **re** module: is a Python module containing *re engine* and providing the regular expression functionality +- **re** module: is a Python module containing _re engine_ and providing the regular expression functionality

Screenshot 2021-09-09 at 04 35 03

## 6.2. Search for a pattern + - To search for a pattern, there are 2 steps: - **Step 1**: Compile the pattern - - **Step 2**: Perform the search -

Screenshot 2021-09-09 at 04 35 03

+ - **Step 2**: Perform the search +

Screenshot 2021-09-09 at 04 35 03

### 6.2.1. Compile the pattern -- `re.compile()` function compiles a pattern so that the re engine can perform the search. + +- `re.compile()` function compiles a pattern so that the re engine can perform the search. + ```Python pat = re.compile(r'abc') print(pat) @@ -364,9 +417,13 @@ print(type(pat)) re.compile('abc') ``` + ### 6.2.2. Perform the search + #### 6.2.2.1. Match() + - `match()`: match the pattern **from the beginning**. + ```Python mat_abc1 = pat.match('ABC,ABc,AbC,abc') mat_abc2 = pat.match('abc,ABc,AbC,abc') @@ -375,8 +432,10 @@ print(mat_abc2) # ``` #### 6.2.2.2. Search() + - `search()`: match the pattern in **any position** in the text and returns the match in `re.Match` class. -- BUT it **only returns the first match** +- BUT it **only returns the first match** + ```Python sear_abc1 = pat.search('ABC,ABc,AbC,abc') sear_abc2 = pat.search('abc,ABc,AbC,abc') @@ -387,7 +446,9 @@ print(type(sear_abc1))# ``` #### 6.2.2.3. Findall() + - `findall()` method: finds all the matched strings and return them in a list. + ```Python find_abc1 = pat.findall('ABC,ABc,AbC,abc') find_abc2 = pat.findall('abc,ABc,AbC,abc') @@ -397,8 +458,10 @@ print(find_abc2) #['abc', 'abc'] ``` #### 6.2.2.4. FindIter() + - The `findall()` method returns all the matched strings in a list. - `finditer()`: returns an iterator that lazily splits matches one at a time. + ```Python finditer_abc = pat.finditer('abc,ABc,AbC,abc') @@ -407,120 +470,140 @@ print(finditer_abc) # for m in finditer_abc: # # - print(m) + print(m) ``` ## 6.3. Metacharacters + The metacharacters can be categorized into several types as below: - `. ^ $ * + ? { } [ ] \ | ( )` - `"["` and `"]"` -- *Type 1* `. [] - ^ \d \D \w \W \s \S`: Metacharacters that match a single character: - - `.` **Dot**: match any single character except the newline **\n** character +- _Type 1_ `. [] - ^ \d \D \w \W \s \S`: Metacharacters that match a single character: + + - `.` **Dot**: match any single character except the newline **\n** character ```Python p = re.compile(r'.at') m = p.findall('cat bat\n sat cap') #['cat', 'bat', 'sat'] - ``` + ``` - `[]` **character class**: specify a set of characters to match - - Metacharacters lose their special meaning inside character class. + - Metacharacters lose their special meaning inside character class. ```Python p = re.compile(r'[abcABC]') m = p.findall('abcABC') #['a', 'b', 'c', 'A', 'B', 'C'] - ``` + ``` - `-` **hyphen**: specify a range of characters to match + - If you want to match a literal hyphen, put it in the beginning or the end inside [], for ex: `[-a-e]` or `[a-e-]` + ```Python p = re.compile(r'[a-z0-9]') m = p.findall('d0A3z6P') #['d', '0', '3', 'z', '6'] p = re.compile(r'[-a-e]') # or [a-e-] if you want to match a hyphen - m = p.findall('e-a-s-y, easy') #['e', '-', 'a', '-', '-', 'e', 'a'] - ``` - - `^` **caret**: match any character NOT in the character class + ``` + + - `^` **caret**: match any character NOT in the character class + - A caret ^ not at the beginning of a character class, it works as a normal character - A caret outside a character class has a different meaning. + ```Python p = re.compile(r'[^0-9a-z]') #Pattern exclude 0-9 and lowecase of a to z m = p.findall('1 2 3 Go') #Result: [' ', ' ', ' ', 'G'] → Only match space + G p = re.compile(r'[0-9^a-z]')#if ^ not at the beginning of a character class, it works as a normal character m = p.findall('1 2 3 ^Go') #['1', '2', '3', '^', 'o'] - ``` + ``` + - `\d` vs `\D` **digits**: \d (numeric digits) \D (non-digit, including \n) ```Python p = re.compile(r'\d') m = p.findall('a1\nA#') #['1'] p = re.compile(r'\D') m = p.findall('a1\nA#') #['a', '\n', 'A', '#'] - ``` + ``` - `\w` vs `\W` **word characters**: \w (`[a-zA-Z0-9_]`) \W (`[^a-zA-Z0-9_]`)

Screenshot 2021-09-09 at 04 35 03

- + ```Python p = re.compile(r'\w') m = p.findall('_#a!E$4-') #['_', 'a', 'E', '4'] p = re.compile(r'\W') m = p.findall('_#a!E$4-') #['#', '!', '$', '-'] - ``` + ``` + - `\s` vs `\S` **white space**: \s (white-space) \S (non white-space) match based on whether a character is a whitespace

Screenshot 2021-09-09 at 04 35 03

```Python - text = 'Name\tISSS610\tISSS666\nJoe Jones\tA\tA\n' + text = 'Name\tISSS610\tISSS666\nJoe Jones\tA\tA\n' p = re.compile(r'\s') m = p.findall(text) #['\t', '\t', '\n', ' ', '\t', '\t', '\n'] - ``` -- *Type 2*: Escaping metacharacters: `\` Removes the special meaning of a metacharacter + ``` + +- _Type 2_: Escaping metacharacters: `\` Removes the special meaning of a metacharacter + ```Python p1 = re.compile(r'.') p2 = re.compile(r'\.') m1 = p1.findall('smu.edu.sg') #['s', 'm', 'u', '.', 'e', 'd', 'u', '.', 's', 'g'] m2 = p2.findall('smu.edu.sg') #['.', '.'] - + p = re.compile(r'\d\\d') #First \d is to match any digit, then second \\d is to match "\d" m = p.findall('135\d') #['5\\d'] i.e: 5\d ``` -- *Type 3*: Anchors: `^` beginning of text, `$` end of text, `\b` word boundary - - `^` **beginning of text**: We have seen a caret used in a character class. Here the caret is used without a character class. - - It matches the starting position in the text. - - In the case of Multiline text, we can add flag `re.MULTILINE` or `re.M` in `re.compile` - ```Python - p = re.compile(r'^a[ab]c') - m = p.findall('''aac\nabc''') #['aac'] - - p = re.compile(r'^a[ab]c', re.M) #Add flag re.M to match multiple text - m = p.findall('''aac\nabc''') #['aac', 'abc'] - ``` - - `$` **end of text**: - - It matches the ending position in the text - - Similar to caret, dollar sign matches the ending position but not in each line in multiline text, but this behavior can also be changed with `re.MULTILINE` or `re.M` - ```Python - p = re.compile(r'ab.$') - m = p.findall('abc abd abe abf') #['abf'] - - p = re.compile(r'[ab]c$', re.M) #Add flag re.M to match multiple text - m = p.findall('ac\nbc') #['ac', 'bc'] - ``` - - `\b` **word boundary**: Match based on whether a position is a word boundary - ```Python - p = re.compile(r'\b\d\d\b') - m = p.findall('1 2 3 11 12 13 111 112 113') #['11', '12', '13'] - - p = re.compile(r'\b\w\w\b') - m = p.findall('aa,ab;ac(AA)AB AC') #['aa', 'ab', 'ac', 'AA', 'AB', 'AC'] - ``` - -- *Type 4*: Quantifiers: - - `*`: zero or more - - `?`: zero or one +- _Type 3_: Anchors: `^` beginning of text, `$` end of text, `\b` word boundary + + - `^` **beginning of text**: We have seen a caret used in a character class. Here the caret is used without a character class. + + - It matches the starting position in the text. + - In the case of Multiline text, we can add flag `re.MULTILINE` or `re.M` in `re.compile` + + ```Python + p = re.compile(r'^a[ab]c') + m = p.findall('''aac\nabc''') #['aac'] + + p = re.compile(r'^a[ab]c', re.M) #Add flag re.M to match multiple text + m = p.findall('''aac\nabc''') #['aac', 'abc'] + ``` + + - `$` **end of text**: + + - It matches the ending position in the text + - Similar to caret, dollar sign matches the ending position but not in each line in multiline text, but this behavior can also be changed with `re.MULTILINE` or `re.M` + + ```Python + p = re.compile(r'ab.$') + m = p.findall('abc abd abe abf') #['abf'] + + p = re.compile(r'[ab]c$', re.M) #Add flag re.M to match multiple text + m = p.findall('ac\nbc') #['ac', 'bc'] + ``` + + - `\b` **word boundary**: Match based on whether a position is a word boundary + + ```Python + p = re.compile(r'\b\d\d\b') + m = p.findall('1 2 3 11 12 13 111 112 113') #['11', '12', '13'] + + p = re.compile(r'\b\w\w\b') + m = p.findall('aa,ab;ac(AA)AB AC') #['aa', 'ab', 'ac', 'AA', 'AB', 'AC'] + ``` + +- _Type 4_: Quantifiers: + + - `*`: zero or more + - `?`: zero or one - `+`: one or more - `{m}`: m repetitions - `{m, n}`: any number of repetitions from m to n, inclusive. - + ```Python p = re.compile(r'a[ab]*c') m = p.findall('a ab ac abc aac aabc aaac ababc') #['ac', 'abc', 'aac', 'aabc', 'aaac', 'ababc'] @@ -537,36 +620,43 @@ The metacharacters can be categorized into several types as below: p = re.compile(r'\d{2,3}') m = p.findall('1 2 3 11 12 13 111 112 113') #['11', '12', '13', '111', '112', '113'] ``` - - + ## 6.4. Grouping Constructs +

Screenshot 2021-09-23 at 11 08 51

### 6.4.1. Grouped Pattern -- We can group pattern using `()` into sub-patterns - ```Python - p = re.compile(r'(\w+): (\d+)') #Sub-patterns are 2 group - m = p.findall('Course: Grade\nMath: 89\nPhysics: 92\n English: 78') #[('Math', '89'), ('Physics', '92'), ('English', '78')] - - chapters = 'Chapter 12: Numpy\n\ - Chapter 13: Pandas\n\ - Chapter 14: Data Visualzation' - p = re.compile(r'^Chapter (\d+: .+)', re.M) #['12: Numpy', '13: Pandas', '14: Data Visualzation'] - m = p.findall(chapters) - ``` + +- We can group pattern using `()` into sub-patterns + + ```Python + p = re.compile(r'(\w+): (\d+)') #Sub-patterns are 2 group + m = p.findall('Course: Grade\nMath: 89\nPhysics: 92\n English: 78') #[('Math', '89'), ('Physics', '92'), ('English', '78')] + + chapters = 'Chapter 12: Numpy\n\ + Chapter 13: Pandas\n\ + Chapter 14: Data Visualzation' + p = re.compile(r'^Chapter (\d+: .+)', re.M) #['12: Numpy', '13: Pandas', '14: Data Visualzation'] + m = p.findall(chapters) + ``` + ### 6.4.2. Alternation + - Match the sub-pattern before or the one after - - ```Python - p = re.compile(r'(\w+)\.(bat|zip|exe)') - m = p.findall('game.exe auto.bat text.zip') #[('game', 'exe'), ('auto', 'bat'), ('text', 'zip')] - ``` + ```Python + p = re.compile(r'(\w+)\.(bat|zip|exe)') + m = p.findall('game.exe auto.bat text.zip') #[('game', 'exe'), ('auto', 'bat'), ('text', 'zip')] + ``` + ### 6.4.3. re.Match.groups() vs re.Match.group() + - `.groups()`: return all matched groups - `.group()`: allows users to choose different groups by giving the indices of the groups. + - group(0) returns the whole match. - group(1) returns the 1st captured group. - group(2, 3, 4) returns the 2nd, 3rd and 4th groups. + ```Python #Ex 1: re.Match.groups() vs re.Match.group() p = re.compile(r'(\w+\.\w+)\s(\w+\.\w+)') @@ -574,35 +664,40 @@ The metacharacters can be categorized into several types as below: print(m.groups()) #('game.exe', 'auto.bat') print(m.group(1)) # game.exe - + #Ex 2: re.Match.group() pattern = r'(\w+)\W+(\w+)\W+(\w+)\W+(\w)+' p = re.compile(pattern) m = p.search('one,,,two:three++++++4') print(m.group(0)) #one,,,two:three++++++4 (i.e: the whole match) print(m.group(1)) #one (i.e: match only group 1) - print(m.group(2, 3, 4)) #('two', 'three', '4') + print(m.group(2, 3, 4)) #('two', 'three', '4') ``` -### 6.4.4. Back Reference (\1, \2, \3, ...) + +### 6.4.4. Back Reference (\1, \2, \3, ...) + - `'(\w+)-\1'` is different from `'(\w+)-\w+'` - `'(\w+)-\1'` : when the first group is matched, `\1` match the same literal string in group1 -- For example: two patterns both match ‘one-one’, but the one with backreference, `'(\w+)-\1'`, won’t match ‘one-two’. +- For example: two patterns both match ‘one-one’, but the one with backreference, `'(\w+)-\1'`, won’t match ‘one-two’. ```Python - # pattern tries to match the type of number that starts with a few digits followed by one digit + # pattern tries to match the type of number that starts with a few digits followed by one digit # and then repeats the first few digits. p = re.compile(r'((\d+)\d\2)') m = p.finditer('1234123, 11311, 123, 54345') for string in m: - print(string.group(1, 2)) + print(string.group(1, 2)) #('1234123', '123') (i.e: 123 - 4 - same as group 2, in this case is 123) #('11311', '11') #('434', '4') ``` + ## 6.5. Flags + Three common flags that are very useful are: -- `re.MULTILINE` or `re.M` : make “^”/“$” match starting/ending position of each line. + +- `re.MULTILINE` or `re.M` : make “^”/“$” match starting/ending position of each line. - `re.IGNORECASE` or `re.I`: match letters in a case-insensitive way. -- `re.DOTALL` or `re.S` : make “.” match any character, including newlines \n. +- `re.DOTALL` or `re.S` : make “.” match any character, including newlines \n. ```Python p1 = re.compile(r'abc') @@ -613,7 +708,9 @@ m2 = p2.findall('abc ABC aBC Abc') #['abc', 'ABC', 'aBC', 'Abc'] because re.I me ``` ## 6.6. Module-Level re Methods + ### 6.6.1. re.match, re.search, re.findall, re.finditer + - Using the module-level methods can skip the step compiling the pattern. ```Python @@ -629,9 +726,12 @@ print(f'finditer: {finditer}') # ``` ### 6.6.2. String-modifying methods + #### Split() + - By default, the `split()` method returns a list of strings broken down, **excluding the matched strings**. - It is also possible to make split() return the matched strings, simply by using a group to capture the whole pattern. + ```Python p = re.compile(r'\W+') split = p.split('The~split*method-is%powerful') #['The', 'split', 'method', 'is', 'powerful'], by default @@ -640,7 +740,9 @@ split = p.split('The~split*method-is%powerful') #['The', 'split', 'method', 'is' p = re.compile(r'(\W+)') split = p.split('The~split*method-is%powerful') #'The', '~', 'split', '*', 'method', '-', 'is', '%', 'powerful'] ``` + #### Sub(replacement string, text to match the pattern) & Subn() + - `sub()` returns a new string after replacement. - `subn()` returns a tuple containing the new string and the number of replacements. @@ -651,9 +753,13 @@ subn = p.subn('Tokyo', 'Toko is Toko') #('Tokyo is Tokyo', 2) ``` ## 6.7. Look ahead and Look behind + ### 6.7.1. Look ahead (Look Forward) + #### Look ahead positive `(?=)` + - Find expression A where expression B is matching: `A(?=B)` + ```Python p = re.compile(r"\s(\w+(-\w+){1,3}(?=[\s.]))") #(?=[\s.]) match A if B=[\s.] is matching either space or dot. m = p.findall(''' @@ -665,15 +771,17 @@ There is a five-and-one-half-foot-long sign at the outskirt of the town.''') ``` #### Look ahead negative `(?!)` + - Find expression A where expression B does not follow:`A(?!B)` ### 6.7.2. Look behind (Look Backward) + #### Look behind positive `(?<=)` + - Find expression A where expression B precedes: `(?<=B)A` -#### Look behind negative `(?\n", - "True\n" - ] - } - ], - "source": [ - "a = True\n", - "print(type(a))\n", - "print(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "20\n" - ] - } - ], - "source": [ - "a = 20\n", - "print(type(a))\n", - "print(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "20.21\n" - ] - } - ], - "source": [ - "a = 20.21\n", - "print(type(a))\n", - "print(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "the \"art\" of programming\n" - ] - } - ], - "source": [ - "a = 'the \"art\" of programming'\n", - "print(type(a))\n", - "print(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'0b1'" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bin(True)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'0b0'" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bin(False)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Type casting" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-1" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "int(-1.99)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2420279590275804445606588463955072096420804747701564608" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "int('thequickbrownfoxjumpsoverthelazydog', 36)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1.0" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "float('0.999999999999999999999999999999999999')" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-inf" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "float('-inf')" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'170141183460469231731687303715884105727'" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "str(170141183460469231731687303715884105727) # the 12th Mersenne prime" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'0.9876543210987654'" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "str(0.987654321098765432109876543210)" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bool(-1)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "bool(0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Binary representations" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'10000000000000000000000000000001'" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import bitstring\n", - "#i1 = bitstring.BitArray(int = 2147483649, length = 32) # this line gives you error because largest integer for signed 32 bits is 2147483647 = 2^31 - 1\n", - "i1 = bitstring.BitArray(uint = 2147483649, length = 32)\n", - "i1.bin" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'11111111'" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "i2 = bitstring.BitArray(int = -1, length = 8)\n", - "i2.bin" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'00111111100000000000000000000000'" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "f1 = bitstring.BitArray(float = 1.0, length = 32)\n", - "f1.bin" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'11000001100101000110000011001101'" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "f2 = bitstring.BitArray(float = -18.547265383, length = 32)\n", - "f2.bin" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'00000000000000000000000000000000'" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "f3 = bitstring.BitArray(float = 0.0, length = 32)\n", - "f3.bin" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'01111111100000000000000000000000'" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "f4 = bitstring.BitArray(float = float('inf'), length = 32)\n", - "f4.bin" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "@©®§ǖΣДЖ१२३€£¥円元圆圓\n", - "b'@\\xc2\\xa9\\xc2\\xae\\xc2\\xa7\\xc7\\x96\\xce\\xa3\\xd0\\x94\\xd0\\x96\\xe0\\xa5\\xa7\\xe0\\xa5\\xa8\\xe0\\xa5\\xa9\\xe2\\x82\\xac\\xc2\\xa3\\xc2\\xa5\\xe5\\x86\\x86\\xe5\\x85\\x83\\xe5\\x9c\\x86\\xe5\\x9c\\x93'\n" - ] - } - ], - "source": [ - "a = '@©®§ǖΣДЖ१२३€£¥円元圆圓'\n", - "print(a)\n", - "print(a.encode('utf-8'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "@ : b'@'
\n", - "© : b'\\xc2\\xa9'
\n", - "® : b'\\xc2\\xae'
\n", - "§ : b'\\xc2\\xa7'
\n", - "ǖ : b'\\xc7\\x96'
\n", - "Σ : b'\\xce\\xa3'
\n", - "Д : b'\\xd0\\x94'
\n", - "Ж : b'\\xd0\\x96'
\n", - "१ : b'\\xe0\\xa5\\xa7'
\n", - "२ : b'\\xe0\\xa5\\xa8'
\n", - "३ : b'\\xe0\\xa5\\xa9'
\n", - "€ : b'\\xe2\\x82\\xac'
\n", - "£ : b'\\xc2\\xa3'
\n", - "¥ : b'\\xc2\\xa5'
\n", - "円 : b'\\xe5\\x86\\x86'
\n", - "元 : b'\\xe5\\x85\\x83'
\n", - "圆 : b'\\xe5\\x9c\\x86'
\n", - "圓 : b'\\xe5\\x9c\\x93'" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "@©®§ǖΣДЖ१२३€£¥円元圆圓\n", - "b'@\\xc2\\xa9\\xc2\\xae\\xc2\\xa7\\xc7\\x96\\xce\\xa3\\xd0\\x94\\xd0\\x96\\xe0\\xa5\\xa7\\xe0\\xa5\\xa8\\xe0\\xa5\\xa9\\xe2\\x82\\xac\\xc2\\xa3\\xc2\\xa5\\xe5\\x86\\x86\\xe5\\x85\\x83\\xe5\\x9c\\x86\\xe5\\x9c\\x93'\n", - "@©®§ǖΣДЖ१२३€£¥円元圆圓\n", - "@©®§ǖΣДЖ१२३€£¥円å…", - "ƒåœ†åœ“\n" - ] - } - ], - "source": [ - "a1 = a.encode('utf-8')\n", - "a2 = a1.decode('utf-8')\n", - "a3 = a1.decode('iso-8859-1')\n", - "print(a)\n", - "print(a1)\n", - "print(a2)\n", - "print(a3)" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'01000000110000101010100111000010101011101100001010100111110001111001011011001110101000111101000010010100110100001001011011100000101001011010011111100000101001011010100011100000101001011010100111100010100000101010110011000010101000111100001010100101111001011000011010000110111001011000010110000011111001011001110010000110111001011001110010010011'" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s1 = bitstring.BitArray(bytes = a.encode('utf-8'))\n", - "s1.bin" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Python operators" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Logical operators" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "not False" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "True and False" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "False or True" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Arithmetic operators" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "355 // 113" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "355 % 113" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "2" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "-7 % 3" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "120390229192789671200196730675808906407818580678535565853604471040981468330576609422256057752381687848600439581729091776513008621150593910720527739772380453052486767498034969314002237284144953291103458547532810152608127216408475325114421897897408047581395677670971695493487923933346069636224032935216763561673143257907287561970520670661943292226106584203713841952673366886865445199267790891789863232017223226748196794533959989836805876911810211481167739679043319937687835412885323948134322098370385629943305785136881090458653857068542385988740344220360507575957485047851613181253218943644136742478444626968576" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 ** 2020" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Assignment operators" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n" - ] - } - ], - "source": [ - "i = 0\n", - "i += 1\n", - "print(i)" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "-9\n" - ] - } - ], - "source": [ - "#print(i := int(-9.99)) ## warlus operator not recognized, to update anaconda soon.\n", - "i = int(-9.99)\n", - "print(i)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Comparison operators" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 33, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = True\n", - "b = False\n", - "a > b" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a = 'ab'\n", - "b = 'Ab'\n", - "a < b" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "c = 'a b'\n", - "a < c" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### String Concatenation & repetition" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'newspaperman'" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "'news' + 'paper' + 'man'" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'eigenvalue'" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s = 'eigen'\n", - "s += 'value'\n", - "s" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'----------'" - ] - }, - "execution_count": 38, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "'-' * 10" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### String length & indices" - ] - }, - { - "cell_type": "code", - "execution_count": 39, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "16" - ] - }, - "execution_count": 39, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s = 'machine learning'\n", - "len(s)" - ] - }, - { - "cell_type": "code", - "execution_count": 40, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'c'" - ] - }, - "execution_count": 40, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s[2]" - ] - }, - { - "cell_type": "code", - "execution_count": 41, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ne le\n", - "learning\n", - "machine\n" - ] - } - ], - "source": [ - "print(s[5:10])\n", - "print(s[8:])\n", - "print(s[:7])" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "e\n", - "earn\n" - ] - } - ], - "source": [ - "print(s[-7])\n", - "print(s[-7:-3])" - ] - }, - { - "cell_type": "code", - "execution_count": 43, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "5" - ] - }, - "execution_count": 43, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s.find('n')" - ] - }, - { - "cell_type": "code", - "execution_count": 44, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "12" - ] - }, - "execution_count": 44, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s.find('n', 6)" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "-1" - ] - }, - "execution_count": 45, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s.find('n', 6, 10)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### print" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1234-567.89#" - ] - } - ], - "source": [ - "print(1234, 567.89, sep = '-', end = '#')" - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pi is approximately 022/7 = 3.14\n" - ] - } - ], - "source": [ - "print('{0:s} is approximately {1:03d}/{2:<2d} = {3:.2f}'.format('pi', 22, 7, 3.1415926))" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "pi is approximately 355 / 113 = 3.141593\n" - ] - } - ], - "source": [ - "print('{0:s} is approximately {1:^5d}/{2:^5d} = {3:.6f}'.format('pi', 355, 113, 3.1415926))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Python containers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Range and for loops" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1 3 5 7 9 " - ] - } - ], - "source": [ - "for i in range(1, 11, 2):\n", - " print(i, end = ' ')" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1 2 4 8 16 32 64 128 256 " - ] - } - ], - "source": [ - "for i in range(9):\n", - " print(2**i, end = ' ')" - ] - }, - { - "cell_type": "code", - "execution_count": 51, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "m-a-c-h-i-n-e- -l-e-a-r-n-i-n-g-" - ] - } - ], - "source": [ - "for i in range(len(s)):\n", - " print(s[i], end = '-')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Lists and Tuples" - ] - }, - { - "cell_type": "code", - "execution_count": 52, - "metadata": {}, - "outputs": [], - "source": [ - "orange_peel = (1.0, 0.625, 0.0)" - ] - }, - { - "cell_type": "code", - "execution_count": 53, - "metadata": {}, - "outputs": [], - "source": [ - "l = [1, 2, 3, 4, 5, 6, 7]" - ] - }, - { - "cell_type": "code", - "execution_count": 54, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "4" - ] - }, - "execution_count": 54, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[3]" - ] - }, - { - "cell_type": "code", - "execution_count": 55, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[3, 4, 5, 6]" - ] - }, - "execution_count": 55, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[2:6]" - ] - }, - { - "cell_type": "code", - "execution_count": 56, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "7" - ] - }, - "execution_count": 56, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[-1]" - ] - }, - { - "cell_type": "code", - "execution_count": 57, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "0.625" - ] - }, - "execution_count": 57, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "orange_peel[1]" - ] - }, - { - "cell_type": "code", - "execution_count": 58, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]" - ] - }, - "execution_count": 58, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "list(range(10))" - ] - }, - { - "cell_type": "code", - "execution_count": 59, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 3, 5, 7, 9, 11, 13, 15, 17]\n" - ] - } - ], - "source": [ - "# print(l := list(range(1, 19, 2))) ## walrus operator again\n", - "l = list(range(1, 19, 2))\n", - "print(l)" - ] - }, - { - "cell_type": "code", - "execution_count": 60, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[5, 9, 13]" - ] - }, - "execution_count": 60, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[2:7:2]" - ] - }, - { - "cell_type": "code", - "execution_count": 61, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[15, 13, 11]" - ] - }, - "execution_count": 61, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[7:4:-1]" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[15, 11]" - ] - }, - "execution_count": 62, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[-2:-5:-2]" - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[17, 15, 13, 11, 9, 7, 5, 3, 1]" - ] - }, - "execution_count": 63, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l[::-1]" - ] - }, - { - "cell_type": "code", - "execution_count": 64, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 64, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l.index(7)" - ] - }, - { - "cell_type": "code", - "execution_count": 65, - "metadata": {}, - "outputs": [], - "source": [ - "# l.index(8) gives an error as 8 is not in the list" - ] - }, - { - "cell_type": "code", - "execution_count": 66, - "metadata": {}, - "outputs": [], - "source": [ - "l.append(19)" - ] - }, - { - "cell_type": "code", - "execution_count": 67, - "metadata": {}, - "outputs": [], - "source": [ - "l.insert(1, 2)" - ] - }, - { - "cell_type": "code", - "execution_count": 68, - "metadata": {}, - "outputs": [], - "source": [ - "l.extend((23, 29, 31)) # extend by a tuple" - ] - }, - { - "cell_type": "code", - "execution_count": 69, - "metadata": {}, - "outputs": [], - "source": [ - "l.extend([37, 41, 43, 47, 49]) # extend by a list" - ] - }, - { - "cell_type": "code", - "execution_count": 70, - "metadata": {}, - "outputs": [], - "source": [ - "# l.remove(4) # error if remove 4\n", - "l.remove(9)" - ] - }, - { - "cell_type": "code", - "execution_count": 71, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "49" - ] - }, - "execution_count": 71, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l.pop()" - ] - }, - { - "cell_type": "code", - "execution_count": 72, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "15" - ] - }, - "execution_count": 72, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l.pop(7)" - ] - }, - { - "cell_type": "code", - "execution_count": 73, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 73, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "l.pop(0)" - ] - }, - { - "cell_type": "code", - "execution_count": 74, - "metadata": {}, - "outputs": [], - "source": [ - "l.sort(reverse = True)" - ] - }, - { - "cell_type": "code", - "execution_count": 75, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[47, 43, 41, 37, 31, 29, 23, 19, 17, 13, 11, 7, 5, 3, 2]\n" - ] - } - ], - "source": [ - "print(l)" - ] - }, - { - "cell_type": "code", - "execution_count": 76, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['mitb', 'smu', 'edu', 'sg']\n" - ] - } - ], - "source": [ - "s = 'mitb.smu.edu.sg'\n", - "print(s.split('.'))" - ] - }, - { - "cell_type": "code", - "execution_count": 77, - "metadata": {}, - "outputs": [], - "source": [ - "s = 'machine learning'\n", - "tokens = s.split()" - ] - }, - { - "cell_type": "code", - "execution_count": 78, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "machine\n", - "learning\n" - ] - } - ], - "source": [ - "print('\\n'.join(tokens))" - ] - }, - { - "cell_type": "code", - "execution_count": 79, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "machine\r", - "learning\n" - ] - } - ], - "source": [ - "print('\\r'.join(tokens))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Dictionaries" - ] - }, - { - "cell_type": "code", - "execution_count": 80, - "metadata": {}, - "outputs": [], - "source": [ - "d = {}\n", - "for i in range(97, 123):\n", - " d[chr(i)] = i - 96" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "19\n" - ] - } - ], - "source": [ - "print(d['s'])" - ] - }, - { - "cell_type": "code", - "execution_count": 82, - "metadata": {}, - "outputs": [], - "source": [ - "d['s'] *= 10" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "metadata": {}, - "outputs": [], - "source": [ - "d['s'] = 19" - ] - }, - { - "cell_type": "code", - "execution_count": 84, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 84, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 in l" - ] - }, - { - "cell_type": "code", - "execution_count": 85, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 85, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "'z' in d" - ] - }, - { - "cell_type": "code", - "execution_count": 86, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "False" - ] - }, - "execution_count": 86, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 in d" - ] - }, - { - "cell_type": "code", - "execution_count": 87, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 87, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "2 not in d" - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "20" - ] - }, - "execution_count": 88, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "d.pop('t')" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [], - "source": [ - "del d['s']" - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 'u', 'v', 'w', 'x', 'y', 'z']\n" - ] - } - ], - "source": [ - "print(list(d.keys()))" - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26]\n" - ] - } - ], - "source": [ - "print(list(d.values()))" - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5), ('f', 6), ('g', 7), ('h', 8), ('i', 9), ('j', 10), ('k', 11), ('l', 12), ('m', 13), ('n', 14), ('o', 15), ('p', 16), ('q', 17), ('r', 18), ('u', 21), ('v', 22), ('w', 23), ('x', 24), ('y', 25), ('z', 26)]\n" - ] - } - ], - "source": [ - "print(list(d.items()))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Sets" - ] - }, - { - "cell_type": "code", - "execution_count": 93, - "metadata": {}, - "outputs": [], - "source": [ - "s = {'deer', 'hawk', 'wolf', 'boar'}" - ] - }, - { - "cell_type": "code", - "execution_count": 94, - "metadata": {}, - "outputs": [], - "source": [ - "s.add('bear')" - ] - }, - { - "cell_type": "code", - "execution_count": 95, - "metadata": {}, - "outputs": [], - "source": [ - "s.add(('goat', 'pony', 'hare')) # do you know why you cannot change the tuple to a list?" - ] - }, - { - "cell_type": "code", - "execution_count": 96, - "metadata": {}, - "outputs": [], - "source": [ - "s.update(['lion', 'puma', 'tiger', 'leopard']) # cannot add a list" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'deer', 'tiger', 'bear', 'hawk', 'wolf', 'leopard', 'lion', ('goat', 'pony', 'hare'), 'boar', 'puma'}\n" - ] - } - ], - "source": [ - "print(s)" - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'deer'" - ] - }, - "execution_count": 98, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s.pop() # pop some element in the set" - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "metadata": {}, - "outputs": [], - "source": [ - "s.remove('leopard')" - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'tiger', 'bear', 'hawk', 'wolf', 'lion', ('goat', 'pony', 'hare'), 'boar', 'puma'}\n" - ] - } - ], - "source": [ - "print(s)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.11: count the frequence of each unique value in a given list\n", - "Hint: use .get(key, default_value)" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "metadata": {}, - "outputs": [], - "source": [ - "long_list = [11, 230, 127, 183, 142, 186, 256, 182, 184, 50, 266, 179, 22, 30, 59, 236, 155, 57, 262, 279, 107, 98, 271, 240, 276, 23, 170, 207, 123, 228, 231, 205, 30, 161, 125, 212, 224, 34, 272, 106, 164, 26, 263, 3, 234, 244, 3, 260, 135, 29, 116, 44, 206, 131, 218, 201, 140, 208, 130, 247, 256, 272, 208, 262, 227, 242, 112, 138, 192, 7, 268, 184, 168, 5, 246, 199, 6, 26, 300, 54, 260, 69, 64, 61, 15, 288, 190, 78, 165, 7, 178, 71, 62, 131, 26, 75, 2, 52, 164, 195, 75, 80, 212, 127, 201, 184, 78, 106, 90, 256, 33, 241, 208, 39, 32, 240, 160, 172, 108, 144, 116, 251, 106, 278, 120, 99, 22, 148, 6, 185, 136, 235, 208, 114, 22, 229, 88, 225, 112, 236, 250, 32, 152, 195, 0, 160, 252, 15, 173, 283, 72, 94, 76, 226, 4, 44, 28, 120, 175, 56, 262, 178, 249, 246, 19, 203, 196, 207, 33, 94, 216, 280, 102, 250, 74, 277, 159, 23, 80, 63, 124, 240, 166, 137, 14, 255, 252, 112, 41, 90, 187, 108, 2, 60, 147, 114, 266, 173, 183, 84, 10, 173, 35, 248, 124, 207, 163, 44, 2, 171, 142, 174, 219, 114, 30, 290, 239, 63, 42, 103, 61, 58, 181, 18, 111, 119, 99, 171, 210, 59, 142, 278, 213, 35, 286, 285, 227, 91, 232, 196, 11, 91, 192, 241, 1, 275, 76, 210, 160, 32, 272, 120, 176, 33, 65, 26, 2, 248, 262, 286, 199, 12, 107, 253, 150, 138, 157, 31, 250, 30, 95, 96, 105, 261, 276, 146, 195, 190, 217, 62, 138, 268, 134, 39, 164, 8, 46, 152, 93, 263, 232, 264, 272, 53, 283, 286, 218, 293, 238, 5, 122, 241, 76, 106, 85, 103, 221, 77, 74, 236, 1, 13, 144, 235, 27, 50, 7, 17, 157, 296, 111, 1, 176, 297, 286, 115, 187, 272, 66, 185, 145, 254, 20, 232, 49, 289, 285, 222, 199, 103, 65, 33, 3, 88, 157, 276, 29, 88, 226, 194, 219, 98, 58, 193, 2, 255, 126, 41, 112, 83, 104, 296, 219, 148, 274, 34, 2, 15, 267, 286, 252, 275, 126, 173, 225, 223, 121, 136, 257, 214, 7, 291, 84, 60, 93, 284, 112, 195, 162, 296, 277, 204, 297, 120, 62, 218, 247, 150, 274, 108, 78, 146, 180, 168, 231, 39, 79, 45, 139, 75, 0, 83, 158, 273, 258, 242, 36, 268, 287, 106, 284, 184, 64, 235, 14, 159, 57, 168, 4, 3, 185, 180, 132, 132, 270, 148, 39, 18, 178, 121, 250, 29, 96, 190, 234, 34, 225, 187, 57, 57, 260, 219, 126, 158, 72, 248, 47, 180, 219, 253, 10, 84, 86, 5, 210, 147, 122, 61, 143, 84, 164, 250, 233, 225, 73, 133, 123, 148, 124, 214, 5, 48, 172, 102, 133, 100, 57, 253, 13, 0, 31, 272, 2, 87, 292, 243, 53, 298, 35, 116, 282, 187, 287, 30, 108, 298, 63, 285, 289, 132, 204, 30, 230, 95, 117, 254, 128, 203, 55, 36, 147, 2, 285, 168, 214, 239, 93, 171, 288, 265, 202, 168, 161, 217, 189, 36, 101, 46, 100, 101, 50, 266, 263, 170, 19, 126, 35, 67, 122, 147, 109, 76, 147, 177, 183, 51, 124, 220, 263, 265, 3, 41, 188, 234, 187, 157, 287, 21, 99, 46, 214, 68, 8, 230, 284, 234, 258, 296, 192, 6, 281, 31, 238, 297, 34, 120, 20, 6, 230, 127, 242, 248, 147, 294, 165, 266, 268, 258, 82, 121, 221, 9, 80, 240, 67, 271, 35, 78, 253, 207, 161, 257, 38, 128, 281, 281, 170, 167, 40, 113, 12, 93, 126, 41, 258, 233, 71, 242, 209, 82, 97, 150, 90, 276, 264, 51, 222, 6, 204, 118, 263, 102, 177, 113, 106, 288, 58, 94, 299, 131, 95, 183, 184, 108, 190, 273, 279, 99, 227, 10, 274, 81, 272, 50, 65, 114, 52, 52, 10, 181, 36, 281, 6, 97, 214, 279, 143, 203, 244, 250, 151, 180, 185, 169, 66, 51, 21, 201, 275, 250, 58, 108, 1, 87, 127, 95, 81, 212, 250, 222, 171, 83, 145, 149, 185, 67, 275, 206, 242, 67, 229, 118, 124, 117, 179, 141, 65, 40, 111, 81, 152, 79, 104, 67, 119, 27, 107, 295, 43, 97, 193, 148, 255, 247, 284, 69, 84, 268, 234, 251, 169, 99, 233, 126, 103, 233, 24, 196, 70, 181, 150, 181, 110, 257, 31, 299, 195, 25, 289, 36, 75, 152, 37, 115, 116, 171, 218, 278, 198, 200, 204, 260, 211, 97, 220, 167, 261, 168, 281, 67, 161, 297, 202, 56, 53, 230, 27, 64, 171, 299, 179, 66, 276, 209, 204, 282, 71, 132, 64, 299, 158, 163, 111, 252, 14, 180, 202, 286, 250, 142, 48, 271, 148, 151, 282, 116, 232, 188, 5, 150, 242, 292, 48, 119, 158, 10, 89, 124, 211, 253, 182, 295, 81, 199, 126, 139, 59, 154, 212, 101, 89, 45, 289, 69, 120, 264, 217, 279, 163, 103, 153, 159, 183, 81, 282, 77, 77, 4, 229, 10, 292, 222, 235, 205, 283, 194, 166, 63, 56, 92, 57, 184, 48, 285, 146, 184, 233, 76, 164, 83, 74, 178, 263, 137, 272, 4, 102, 111, 83, 229, 7, 268, 26, 274, 100, 231, 80, 223, 226, 151, 219, 5, 144, 169, 68, 175, 257, 48, 243, 185, 145, 115, 239, 259, 36, 192, 256, 19, 252, 95, 284, 62, 192, 281, 299, 34, 290, 70, 166, 9, 102, 279, 225, 147, 175, 269, 16, 115, 181, 150, 200, 89, 1, 298, 132, 93, 24, 209, 231, 225, 67, 239, 47, 280, 101, 210, 164, 241, 115, 259, 261, 157, 224, 296, 223, 127, 22, 280, 28, 170, 15, 201, 102, 245, 266, 161, 20, 210, 251, 249, 53, 282, 76, 126, 243, 196, 220, 265, 110, 146, 242, 248, 17, 181, 23, 77, 106, 296, 290, 243, 93]" - ] - }, - { - "cell_type": "code", - "execution_count": 102, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Python Conditionals" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### if and elif" - ] - }, - { - "cell_type": "code", - "execution_count": 103, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an odd number\n", - "this is an even number\n" - ] - } - ], - "source": [ - "for i in l:\n", - " if i % 2 == 0:\n", - " print('this is an even number')\n", - " else:\n", - " print('this is an odd number')" - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a prime number\n", - "this is a multiple of 3\n", - "this is an even number\n" - ] - } - ], - "source": [ - "for i in l:\n", - " if i % 2 == 0:\n", - " print('this is an even number')\n", - " elif i % 3 == 0:\n", - " print('this is a multiple of 3')\n", - " else:\n", - " print('this is a prime number')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### for loops" - ] - }, - { - "cell_type": "code", - "execution_count": 105, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "1\n", - "2\n", - "3\n", - "4\n", - "5\n", - "6\n", - "7\n", - "8\n", - "9\n" - ] - } - ], - "source": [ - "for i in range(10):\n", - " print(i)" - ] - }, - { - "cell_type": "code", - "execution_count": 106, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "10\n", - "11\n", - "12\n", - "13\n", - "14\n", - "15\n", - "16\n", - "17\n", - "18\n", - "19\n" - ] - } - ], - "source": [ - "for i in range(10, 20):\n", - " print(i)" - ] - }, - { - "cell_type": "code", - "execution_count": 107, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n", - "3\n", - "5\n", - "7\n" - ] - } - ], - "source": [ - "for i in range(1, 9, 2):\n", - " print(i)" - ] - }, - { - "cell_type": "code", - "execution_count": 108, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "m\n", - "a\n", - "c\n", - "h\n", - "i\n", - "n\n", - "e\n", - " \n", - "l\n", - "e\n", - "a\n", - "r\n", - "n\n", - "i\n", - "n\n", - "g\n" - ] - } - ], - "source": [ - "s = 'machine learning'\n", - "for ch in s:\n", - " print(ch)" - ] - }, - { - "cell_type": "code", - "execution_count": 109, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n", - "2\n", - "3\n", - "4\n" - ] - } - ], - "source": [ - "l = [1, 2, 3, 4]\n", - "for v in l:\n", - " print(v)" - ] - }, - { - "cell_type": "code", - "execution_count": 110, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n", - "3\n" - ] - } - ], - "source": [ - "d = {1:2, 3:4}\n", - "for k in d:\n", - " print(k)" - ] - }, - { - "cell_type": "code", - "execution_count": 111, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2\n", - "4\n" - ] - } - ], - "source": [ - "for v in d.values():\n", - " print(v)" - ] - }, - { - "cell_type": "code", - "execution_count": 112, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(1, 2)\n", - "(3, 4)\n" - ] - } - ], - "source": [ - "for p in d.items():\n", - " print(p)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### while loops" - ] - }, - { - "cell_type": "code", - "execution_count": 113, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5050\n" - ] - } - ], - "source": [ - "summ, i = 0, 0\n", - "while i <= 100:\n", - " summ += i\n", - " i += 1\n", - "print(summ)" - ] - }, - { - "cell_type": "code", - "execution_count": 114, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "i\n", - "like\n", - "python\n" - ] - } - ], - "source": [ - "l = ['i', 'like', 'python']\n", - "while l:\n", - " print(l.pop(0))" - ] - }, - { - "cell_type": "code", - "execution_count": 115, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "' # comment this line to run the code below\\nsent = input(\\'What can I help you?\\n\\')\\nwhile sent.lower() != \\'i give up!\\' and sent.lower() != \"i\\'m frustrated!\":\\n sent = input(\\'Pardon?\\n\\')\\n#'" - ] - }, - "execution_count": 115, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "''' # comment this line to run the code below\n", - "sent = input('What can I help you?\\n')\n", - "while sent.lower() != 'i give up!' and sent.lower() != \"i'm frustrated!\":\n", - " sent = input('Pardon?\\n')\n", - "#'''" - ] - }, - { - "cell_type": "code", - "execution_count": 116, - "metadata": {}, - "outputs": [], - "source": [ - "while None:\n", - " print('this is evaluated as False')\n", - "while False:\n", - " print('this is evaluated as False')\n", - "while 0:\n", - " print('this is evaluated as False')\n", - "while '':\n", - " print('this is evaluated as False')\n", - "while []:\n", - " print('this is evaluated as False')\n", - "while {}:\n", - " print('this is evaluated as False')\n", - "while float('NaN') == float('NaN'):\n", - " print('this is evaluated as False')" - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "value of i is now 1\n", - "value of i is now 3\n", - "value of i is now 5\n" - ] - } - ], - "source": [ - "i = 0\n", - "while i < 8:\n", - " i += 1\n", - " print('value of i is now', i)\n", - " if i == 5:\n", - " break\n", - " i += 1" - ] - }, - { - "cell_type": "code", - "execution_count": 118, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "value of i is now 1\n", - "value of i is now 3\n", - "value of i is now 5\n", - "value of i is now 6\n", - "value of i is now 8\n" - ] - } - ], - "source": [ - "i = 0\n", - "while i < 8:\n", - " i += 1\n", - " print('value of i is now', i)\n", - " if i == 5:\n", - " continue\n", - " i += 1" - ] - }, - { - "cell_type": "code", - "execution_count": 119, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "no multiple of 37 found\n" - ] - } - ], - "source": [ - "j = 37\n", - "for i in range(80, 110):\n", - " if i % j == 0:\n", - " break\n", - "else:\n", - " print('no multiple of {:d} found'.format(j))" - ] - }, - { - "cell_type": "code", - "execution_count": 120, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "no multiple of 37 found\n" - ] - } - ], - "source": [ - "i, j = 80, 37\n", - "while i <= 110:\n", - " if i % j == 0:\n", - " break\n", - " i += 1\n", - "else:\n", - " print('no multiple of {:d} found'.format(j))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.12: find the first value appears 3 times in a list" - ] - }, - { - "cell_type": "code", - "execution_count": 121, - "metadata": {}, - "outputs": [], - "source": [ - "long_list = [11, 230, 127, 183, 142, 186, 256, 182, 184, 50, 266, 179, 22, 30, 59, 236, 155, 57, 262, 279, 107, 98, 271, 240, 276, 23, 170, 207, 123, 228, 231, 205, 30, 161, 125, 212, 224, 34, 272, 106, 164, 26, 263, 3, 234, 244, 3, 260, 135, 29, 116, 44, 206, 131, 218, 201, 140, 208, 130, 247, 256, 272, 208, 262, 227, 242, 112, 138, 192, 7, 268, 184, 168, 5, 246, 199, 6, 26, 300, 54, 260, 69, 64, 61, 15, 288, 190, 78, 165, 7, 178, 71, 62, 131, 26, 75, 2, 52, 164, 195, 75, 80, 212, 127, 201, 184, 78, 106, 90, 256, 33, 241, 208, 39, 32, 240, 160, 172, 108, 144, 116, 251, 106, 278, 120, 99, 22, 148, 6, 185, 136, 235, 208, 114, 22, 229, 88, 225, 112, 236, 250, 32, 152, 195, 0, 160, 252, 15, 173, 283, 72, 94, 76, 226, 4, 44, 28, 120, 175, 56, 262, 178, 249, 246, 19, 203, 196, 207, 33, 94, 216, 280, 102, 250, 74, 277, 159, 23, 80, 63, 124, 240, 166, 137, 14, 255, 252, 112, 41, 90, 187, 108, 2, 60, 147, 114, 266, 173, 183, 84, 10, 173, 35, 248, 124, 207, 163, 44, 2, 171, 142, 174, 219, 114, 30, 290, 239, 63, 42, 103, 61, 58, 181, 18, 111, 119, 99, 171, 210, 59, 142, 278, 213, 35, 286, 285, 227, 91, 232, 196, 11, 91, 192, 241, 1, 275, 76, 210, 160, 32, 272, 120, 176, 33, 65, 26, 2, 248, 262, 286, 199, 12, 107, 253, 150, 138, 157, 31, 250, 30, 95, 96, 105, 261, 276, 146, 195, 190, 217, 62, 138, 268, 134, 39, 164, 8, 46, 152, 93, 263, 232, 264, 272, 53, 283, 286, 218, 293, 238, 5, 122, 241, 76, 106, 85, 103, 221, 77, 74, 236, 1, 13, 144, 235, 27, 50, 7, 17, 157, 296, 111, 1, 176, 297, 286, 115, 187, 272, 66, 185, 145, 254, 20, 232, 49, 289, 285, 222, 199, 103, 65, 33, 3, 88, 157, 276, 29, 88, 226, 194, 219, 98, 58, 193, 2, 255, 126, 41, 112, 83, 104, 296, 219, 148, 274, 34, 2, 15, 267, 286, 252, 275, 126, 173, 225, 223, 121, 136, 257, 214, 7, 291, 84, 60, 93, 284, 112, 195, 162, 296, 277, 204, 297, 120, 62, 218, 247, 150, 274, 108, 78, 146, 180, 168, 231, 39, 79, 45, 139, 75, 0, 83, 158, 273, 258, 242, 36, 268, 287, 106, 284, 184, 64, 235, 14, 159, 57, 168, 4, 3, 185, 180, 132, 132, 270, 148, 39, 18, 178, 121, 250, 29, 96, 190, 234, 34, 225, 187, 57, 57, 260, 219, 126, 158, 72, 248, 47, 180, 219, 253, 10, 84, 86, 5, 210, 147, 122, 61, 143, 84, 164, 250, 233, 225, 73, 133, 123, 148, 124, 214, 5, 48, 172, 102, 133, 100, 57, 253, 13, 0, 31, 272, 2, 87, 292, 243, 53, 298, 35, 116, 282, 187, 287, 30, 108, 298, 63, 285, 289, 132, 204, 30, 230, 95, 117, 254, 128, 203, 55, 36, 147, 2, 285, 168, 214, 239, 93, 171, 288, 265, 202, 168, 161, 217, 189, 36, 101, 46, 100, 101, 50, 266, 263, 170, 19, 126, 35, 67, 122, 147, 109, 76, 147, 177, 183, 51, 124, 220, 263, 265, 3, 41, 188, 234, 187, 157, 287, 21, 99, 46, 214, 68, 8, 230, 284, 234, 258, 296, 192, 6, 281, 31, 238, 297, 34, 120, 20, 6, 230, 127, 242, 248, 147, 294, 165, 266, 268, 258, 82, 121, 221, 9, 80, 240, 67, 271, 35, 78, 253, 207, 161, 257, 38, 128, 281, 281, 170, 167, 40, 113, 12, 93, 126, 41, 258, 233, 71, 242, 209, 82, 97, 150, 90, 276, 264, 51, 222, 6, 204, 118, 263, 102, 177, 113, 106, 288, 58, 94, 299, 131, 95, 183, 184, 108, 190, 273, 279, 99, 227, 10, 274, 81, 272, 50, 65, 114, 52, 52, 10, 181, 36, 281, 6, 97, 214, 279, 143, 203, 244, 250, 151, 180, 185, 169, 66, 51, 21, 201, 275, 250, 58, 108, 1, 87, 127, 95, 81, 212, 250, 222, 171, 83, 145, 149, 185, 67, 275, 206, 242, 67, 229, 118, 124, 117, 179, 141, 65, 40, 111, 81, 152, 79, 104, 67, 119, 27, 107, 295, 43, 97, 193, 148, 255, 247, 284, 69, 84, 268, 234, 251, 169, 99, 233, 126, 103, 233, 24, 196, 70, 181, 150, 181, 110, 257, 31, 299, 195, 25, 289, 36, 75, 152, 37, 115, 116, 171, 218, 278, 198, 200, 204, 260, 211, 97, 220, 167, 261, 168, 281, 67, 161, 297, 202, 56, 53, 230, 27, 64, 171, 299, 179, 66, 276, 209, 204, 282, 71, 132, 64, 299, 158, 163, 111, 252, 14, 180, 202, 286, 250, 142, 48, 271, 148, 151, 282, 116, 232, 188, 5, 150, 242, 292, 48, 119, 158, 10, 89, 124, 211, 253, 182, 295, 81, 199, 126, 139, 59, 154, 212, 101, 89, 45, 289, 69, 120, 264, 217, 279, 163, 103, 153, 159, 183, 81, 282, 77, 77, 4, 229, 10, 292, 222, 235, 205, 283, 194, 166, 63, 56, 92, 57, 184, 48, 285, 146, 184, 233, 76, 164, 83, 74, 178, 263, 137, 272, 4, 102, 111, 83, 229, 7, 268, 26, 274, 100, 231, 80, 223, 226, 151, 219, 5, 144, 169, 68, 175, 257, 48, 243, 185, 145, 115, 239, 259, 36, 192, 256, 19, 252, 95, 284, 62, 192, 281, 299, 34, 290, 70, 166, 9, 102, 279, 225, 147, 175, 269, 16, 115, 181, 150, 200, 89, 1, 298, 132, 93, 24, 209, 231, 225, 67, 239, 47, 280, 101, 210, 164, 241, 115, 259, 261, 157, 224, 296, 223, 127, 22, 280, 28, 170, 15, 201, 102, 245, 266, 161, 20, 210, 251, 249, 53, 282, 76, 126, 243, 196, 220, 265, 110, 146, 242, 248, 17, 181, 23, 77, 106, 296, 290, 243, 93]" - ] - }, - { - "cell_type": "code", - "execution_count": 122, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.13: print the following pattern of 10 rows and 19 columns" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```\n", - "*******************\n", - "---------*---------\n", - "********---********\n", - "-------*****-------\n", - "******-------******\n", - "-----*********-----\n", - "****-----------****\n", - "---*************---\n", - "**---------------**\n", - "-*****************-\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 123, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### List & dictionary comprehension" - ] - }, - { - "cell_type": "code", - "execution_count": 124, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[9, 25, 49, 81, 121, 169, 225, 289, 361, 441, 529, 625, 729, 841, 961, 1089, 1225, 1369]\n" - ] - } - ], - "source": [ - "a = [i**2 for i in range(3, 39, 2)]\n", - "print(a)" - ] - }, - { - "cell_type": "code", - "execution_count": 125, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{9: 0, 25: 1, 49: 2, 81: 3, 121: 4, 169: 5, 225: 6, 289: 7, 361: 8, 441: 9, 529: 10, 625: 11, 729: 12, 841: 13, 961: 14, 1089: 15, 1225: 16, 1369: 17}\n" - ] - } - ], - "source": [ - "b = {a[i]:i for i in range(len(a))}\n", - "print(b)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 4: Construct a geometric progression\n", - "print first 20 terms, use list comprehension" - ] - }, - { - "cell_type": "code", - "execution_count": 126, - "metadata": {}, - "outputs": [], - "source": [ - "first_term, ratio = 512, 1.5" - ] - }, - { - "cell_type": "code", - "execution_count": 127, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your Python code" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 5: find the start time of Einstein’s presentation\n", - "\n", - "Suppose a presentation session at a conference starts at 8:20am, each speaker is given 20 minutes and they present in the ascending order of their surname, when does Einstein start to present? " - ] - }, - { - "cell_type": "code", - "execution_count": 128, - "metadata": {}, - "outputs": [], - "source": [ - "physicists = ['Erwin Schroedinger', 'Wolfgang Pauli', 'Max Born', 'Niels Bohr', 'Max Planck', 'Madame Curie', 'Hendrik Antoon Lorentz', 'Albert Einstein', 'Paul Langevin', 'Louis Victor de Broglie', 'Paul Dirac', 'Werner Heisenberg']" - ] - }, - { - "cell_type": "code", - "execution_count": 129, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Final exercise: list words that have appeared at least 3 times" - ] - }, - { - "cell_type": "code", - "execution_count": 130, - "metadata": {}, - "outputs": [], - "source": [ - "speech = ['the United States has conducted an operation that killed Osama bin Laden',\n", - " 'Abu Bakr al-Baghdadi is dead',\n", - " 'the United States launched a targeted operation against that compound',\n", - " 'they did a lot of shooting and they did a lot of blasting even not going through the front door You know you would think you go through the door If you are a normal person you say Knock knock May I come in',\n", - " 'After a firefight they killed Osama bin Laden and took custody of his body',\n", - " 'He died like a dog',\n", - " 'Yet his death does not mark the end of our effort',\n", - " 'a beautiful dog a talented dog',\n", - " 'We give thanks for the men who carried out this operation',\n", - " 'And I dont get any credit for this but thats okay I never do But here we are',\n", - " 'May God bless you And may God bless the United States of America',\n", - " 'And Im writing a book I think I wrote 12 books All did very well']" - ] - }, - { - "cell_type": "code", - "execution_count": 131, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - } - ], - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/W1_Python_Basics/class_exercise_1_submit.ipynb b/W1_Python_Basics/class_exercise_1_submit.ipynb deleted file mode 100644 index a4402ee..0000000 --- a/W1_Python_Basics/class_exercise_1_submit.ipynb +++ /dev/null @@ -1,788 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.11: count the frequence of each unique value in a given list" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "long_list = [11, 230, 127, 183, 142, 186, 256, 182, 184, 50, 266, 179, 22, 30, 59, 236, 155, 57, 262, 279, 107, 98, 271, 240, 276, 23, 170, 207, 123, 228, 231, 205, 30, 161, 125, 212, 224, 34, 272, 106, 164, 26, 263, 3, 234, 244, 3, 260, 135, 29, 116, 44, 206, 131, 218, 201, 140, 208, 130, 247, 256, 272, 208, 262, 227, 242, 112, 138, 192, 7, 268, 184, 168, 5, 246, 199, 6, 26, 300, 54, 260, 69, 64, 61, 15, 288, 190, 78, 165, 7, 178, 71, 62, 131, 26, 75, 2, 52, 164, 195, 75, 80, 212, 127, 201, 184, 78, 106, 90, 256, 33, 241, 208, 39, 32, 240, 160, 172, 108, 144, 116, 251, 106, 278, 120, 99, 22, 148, 6, 185, 136, 235, 208, 114, 22, 229, 88, 225, 112, 236, 250, 32, 152, 195, 0, 160, 252, 15, 173, 283, 72, 94, 76, 226, 4, 44, 28, 120, 175, 56, 262, 178, 249, 246, 19, 203, 196, 207, 33, 94, 216, 280, 102, 250, 74, 277, 159, 23, 80, 63, 124, 240, 166, 137, 14, 255, 252, 112, 41, 90, 187, 108, 2, 60, 147, 114, 266, 173, 183, 84, 10, 173, 35, 248, 124, 207, 163, 44, 2, 171, 142, 174, 219, 114, 30, 290, 239, 63, 42, 103, 61, 58, 181, 18, 111, 119, 99, 171, 210, 59, 142, 278, 213, 35, 286, 285, 227, 91, 232, 196, 11, 91, 192, 241, 1, 275, 76, 210, 160, 32, 272, 120, 176, 33, 65, 26, 2, 248, 262, 286, 199, 12, 107, 253, 150, 138, 157, 31, 250, 30, 95, 96, 105, 261, 276, 146, 195, 190, 217, 62, 138, 268, 134, 39, 164, 8, 46, 152, 93, 263, 232, 264, 272, 53, 283, 286, 218, 293, 238, 5, 122, 241, 76, 106, 85, 103, 221, 77, 74, 236, 1, 13, 144, 235, 27, 50, 7, 17, 157, 296, 111, 1, 176, 297, 286, 115, 187, 272, 66, 185, 145, 254, 20, 232, 49, 289, 285, 222, 199, 103, 65, 33, 3, 88, 157, 276, 29, 88, 226, 194, 219, 98, 58, 193, 2, 255, 126, 41, 112, 83, 104, 296, 219, 148, 274, 34, 2, 15, 267, 286, 252, 275, 126, 173, 225, 223, 121, 136, 257, 214, 7, 291, 84, 60, 93, 284, 112, 195, 162, 296, 277, 204, 297, 120, 62, 218, 247, 150, 274, 108, 78, 146, 180, 168, 231, 39, 79, 45, 139, 75, 0, 83, 158, 273, 258, 242, 36, 268, 287, 106, 284, 184, 64, 235, 14, 159, 57, 168, 4, 3, 185, 180, 132, 132, 270, 148, 39, 18, 178, 121, 250, 29, 96, 190, 234, 34, 225, 187, 57, 57, 260, 219, 126, 158, 72, 248, 47, 180, 219, 253, 10, 84, 86, 5, 210, 147, 122, 61, 143, 84, 164, 250, 233, 225, 73, 133, 123, 148, 124, 214, 5, 48, 172, 102, 133, 100, 57, 253, 13, 0, 31, 272, 2, 87, 292, 243, 53, 298, 35, 116, 282, 187, 287, 30, 108, 298, 63, 285, 289, 132, 204, 30, 230, 95, 117, 254, 128, 203, 55, 36, 147, 2, 285, 168, 214, 239, 93, 171, 288, 265, 202, 168, 161, 217, 189, 36, 101, 46, 100, 101, 50, 266, 263, 170, 19, 126, 35, 67, 122, 147, 109, 76, 147, 177, 183, 51, 124, 220, 263, 265, 3, 41, 188, 234, 187, 157, 287, 21, 99, 46, 214, 68, 8, 230, 284, 234, 258, 296, 192, 6, 281, 31, 238, 297, 34, 120, 20, 6, 230, 127, 242, 248, 147, 294, 165, 266, 268, 258, 82, 121, 221, 9, 80, 240, 67, 271, 35, 78, 253, 207, 161, 257, 38, 128, 281, 281, 170, 167, 40, 113, 12, 93, 126, 41, 258, 233, 71, 242, 209, 82, 97, 150, 90, 276, 264, 51, 222, 6, 204, 118, 263, 102, 177, 113, 106, 288, 58, 94, 299, 131, 95, 183, 184, 108, 190, 273, 279, 99, 227, 10, 274, 81, 272, 50, 65, 114, 52, 52, 10, 181, 36, 281, 6, 97, 214, 279, 143, 203, 244, 250, 151, 180, 185, 169, 66, 51, 21, 201, 275, 250, 58, 108, 1, 87, 127, 95, 81, 212, 250, 222, 171, 83, 145, 149, 185, 67, 275, 206, 242, 67, 229, 118, 124, 117, 179, 141, 65, 40, 111, 81, 152, 79, 104, 67, 119, 27, 107, 295, 43, 97, 193, 148, 255, 247, 284, 69, 84, 268, 234, 251, 169, 99, 233, 126, 103, 233, 24, 196, 70, 181, 150, 181, 110, 257, 31, 299, 195, 25, 289, 36, 75, 152, 37, 115, 116, 171, 218, 278, 198, 200, 204, 260, 211, 97, 220, 167, 261, 168, 281, 67, 161, 297, 202, 56, 53, 230, 27, 64, 171, 299, 179, 66, 276, 209, 204, 282, 71, 132, 64, 299, 158, 163, 111, 252, 14, 180, 202, 286, 250, 142, 48, 271, 148, 151, 282, 116, 232, 188, 5, 150, 242, 292, 48, 119, 158, 10, 89, 124, 211, 253, 182, 295, 81, 199, 126, 139, 59, 154, 212, 101, 89, 45, 289, 69, 120, 264, 217, 279, 163, 103, 153, 159, 183, 81, 282, 77, 77, 4, 229, 10, 292, 222, 235, 205, 283, 194, 166, 63, 56, 92, 57, 184, 48, 285, 146, 184, 233, 76, 164, 83, 74, 178, 263, 137, 272, 4, 102, 111, 83, 229, 7, 268, 26, 274, 100, 231, 80, 223, 226, 151, 219, 5, 144, 169, 68, 175, 257, 48, 243, 185, 145, 115, 239, 259, 36, 192, 256, 19, 252, 95, 284, 62, 192, 281, 299, 34, 290, 70, 166, 9, 102, 279, 225, 147, 175, 269, 16, 115, 181, 150, 200, 89, 1, 298, 132, 93, 24, 209, 231, 225, 67, 239, 47, 280, 101, 210, 164, 241, 115, 259, 261, 157, 224, 296, 223, 127, 22, 280, 28, 170, 15, 201, 102, 245, 266, 161, 20, 210, 251, 249, 53, 282, 76, 126, 243, 196, 220, 265, 110, 146, 242, 248, 17, 181, 23, 77, 106, 296, 290, 243, 93]" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[(0, 3),\n", - " (1, 5),\n", - " (2, 8),\n", - " (3, 5),\n", - " (4, 4),\n", - " (5, 6),\n", - " (6, 6),\n", - " (7, 5),\n", - " (8, 2),\n", - " (9, 2),\n", - " (10, 6),\n", - " (11, 2),\n", - " (12, 2),\n", - " (13, 2),\n", - " (14, 3),\n", - " (15, 4),\n", - " (16, 1),\n", - " (17, 2),\n", - " (18, 2),\n", - " (19, 3),\n", - " (20, 3),\n", - " (21, 2),\n", - " (22, 4),\n", - " (23, 3),\n", - " (24, 2),\n", - " (25, 1),\n", - " (26, 5),\n", - " (27, 3),\n", - " (28, 2),\n", - " (29, 3),\n", - " (30, 6),\n", - " (31, 4),\n", - " (32, 3),\n", - " (33, 4),\n", - " (34, 5),\n", - " (35, 5),\n", - " (36, 6),\n", - " (37, 1),\n", - " (38, 1),\n", - " (39, 4),\n", - " (40, 2),\n", - " (41, 4),\n", - " (42, 1),\n", - " (43, 1),\n", - " (44, 3),\n", - " (45, 2),\n", - " (46, 3),\n", - " (47, 2),\n", - " (48, 5),\n", - " (49, 1),\n", - " (50, 4),\n", - " (51, 3),\n", - " (52, 3),\n", - " (53, 4),\n", - " (54, 1),\n", - " (55, 1),\n", - " (56, 3),\n", - " (57, 6),\n", - " (58, 4),\n", - " (59, 3),\n", - " (60, 2),\n", - " (61, 3),\n", - " (62, 4),\n", - " (63, 4),\n", - " (64, 4),\n", - " (65, 4),\n", - " (66, 3),\n", - " (67, 7),\n", - " (68, 2),\n", - " (69, 3),\n", - " (70, 2),\n", - " (71, 3),\n", - " (72, 2),\n", - " (73, 1),\n", - " (74, 3),\n", - " (75, 4),\n", - " (76, 6),\n", - " (77, 4),\n", - " (78, 4),\n", - " (79, 2),\n", - " (80, 4),\n", - " (81, 5),\n", - " (82, 2),\n", - " (83, 5),\n", - " (84, 5),\n", - " (85, 1),\n", - " (86, 1),\n", - " (87, 2),\n", - " (88, 3),\n", - " (89, 3),\n", - " (90, 3),\n", - " (91, 2),\n", - " (92, 1),\n", - " (93, 6),\n", - " (94, 3),\n", - " (95, 5),\n", - " (96, 2),\n", - " (97, 4),\n", - " (98, 2),\n", - " (99, 5),\n", - " (100, 3),\n", - " (101, 4),\n", - " (102, 6),\n", - " (103, 5),\n", - " (104, 2),\n", - " (105, 1),\n", - " (106, 7),\n", - " (107, 3),\n", - " (108, 6),\n", - " (109, 1),\n", - " (110, 2),\n", - " (111, 5),\n", - " (112, 5),\n", - " (113, 2),\n", - " (114, 4),\n", - " (115, 5),\n", - " (116, 5),\n", - " (117, 2),\n", - " (118, 2),\n", - " (119, 3),\n", - " (120, 6),\n", - " (121, 3),\n", - " (122, 3),\n", - " (123, 2),\n", - " (124, 6),\n", - " (125, 1),\n", - " (126, 8),\n", - " (127, 5),\n", - " (128, 2),\n", - " (130, 1),\n", - " (131, 3),\n", - " (132, 5),\n", - " (133, 2),\n", - " (134, 1),\n", - " (135, 1),\n", - " (136, 2),\n", - " (137, 2),\n", - " (138, 3),\n", - " (139, 2),\n", - " (140, 1),\n", - " (141, 1),\n", - " (142, 4),\n", - " (143, 2),\n", - " (144, 3),\n", - " (145, 3),\n", - " (146, 4),\n", - " (147, 7),\n", - " (148, 6),\n", - " (149, 1),\n", - " (150, 6),\n", - " (151, 3),\n", - " (152, 4),\n", - " (153, 1),\n", - " (154, 1),\n", - " (155, 1),\n", - " (157, 5),\n", - " (158, 4),\n", - " (159, 3),\n", - " (160, 3),\n", - " (161, 5),\n", - " (162, 1),\n", - " (163, 3),\n", - " (164, 6),\n", - " (165, 2),\n", - " (166, 3),\n", - " (167, 2),\n", - " (168, 6),\n", - " (169, 3),\n", - " (170, 4),\n", - " (171, 6),\n", - " (172, 2),\n", - " (173, 4),\n", - " (174, 1),\n", - " (175, 3),\n", - " (176, 2),\n", - " (177, 2),\n", - " (178, 4),\n", - " (179, 3),\n", - " (180, 5),\n", - " (181, 6),\n", - " (182, 2),\n", - " (183, 5),\n", - " (184, 7),\n", - " (185, 6),\n", - " (186, 1),\n", - " (187, 5),\n", - " (188, 2),\n", - " (189, 1),\n", - " (190, 4),\n", - " (192, 5),\n", - " (193, 2),\n", - " (194, 2),\n", - " (195, 5),\n", - " (196, 4),\n", - " (198, 1),\n", - " (199, 4),\n", - " (200, 2),\n", - " (201, 4),\n", - " (202, 3),\n", - " (203, 3),\n", - " (204, 5),\n", - " (205, 2),\n", - " (206, 2),\n", - " (207, 4),\n", - " (208, 4),\n", - " (209, 3),\n", - " (210, 5),\n", - " (211, 2),\n", - " (212, 4),\n", - " (213, 1),\n", - " (214, 5),\n", - " (216, 1),\n", - " (217, 3),\n", - " (218, 4),\n", - " (219, 6),\n", - " (220, 3),\n", - " (221, 2),\n", - " (222, 4),\n", - " (223, 3),\n", - " (224, 2),\n", - " (225, 6),\n", - " (226, 3),\n", - " (227, 3),\n", - " (228, 1),\n", - " (229, 4),\n", - " (230, 5),\n", - " (231, 4),\n", - " (232, 4),\n", - " (233, 5),\n", - " (234, 5),\n", - " (235, 4),\n", - " (236, 3),\n", - " (238, 2),\n", - " (239, 4),\n", - " (240, 4),\n", - " (241, 4),\n", - " (242, 7),\n", - " (243, 4),\n", - " (244, 2),\n", - " (245, 1),\n", - " (246, 2),\n", - " (247, 3),\n", - " (248, 5),\n", - " (249, 2),\n", - " (250, 9),\n", - " (251, 3),\n", - " (252, 5),\n", - " (253, 5),\n", - " (254, 2),\n", - " (255, 3),\n", - " (256, 4),\n", - " (257, 4),\n", - " (258, 4),\n", - " (259, 2),\n", - " (260, 4),\n", - " (261, 3),\n", - " (262, 4),\n", - " (263, 6),\n", - " (264, 3),\n", - " (265, 3),\n", - " (266, 5),\n", - " (267, 1),\n", - " (268, 6),\n", - " (269, 1),\n", - " (270, 1),\n", - " (271, 3),\n", - " (272, 8),\n", - " (273, 2),\n", - " (274, 4),\n", - " (275, 4),\n", - " (276, 5),\n", - " (277, 2),\n", - " (278, 3),\n", - " (279, 5),\n", - " (280, 3),\n", - " (281, 6),\n", - " (282, 5),\n", - " (283, 3),\n", - " (284, 5),\n", - " (285, 5),\n", - " (286, 6),\n", - " (287, 3),\n", - " (288, 3),\n", - " (289, 4),\n", - " (290, 3),\n", - " (291, 1),\n", - " (292, 3),\n", - " (293, 1),\n", - " (294, 1),\n", - " (295, 2),\n", - " (296, 6),\n", - " (297, 4),\n", - " (298, 3),\n", - " (299, 5),\n", - " (300, 1)]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "freq_count = {}\n", - "for key in long_list:\n", - " if key not in freq_count:\n", - " freq_count[key]=1\n", - " else:\n", - " freq_count[key]+=1\n", - "\n", - "list(sorted(freq_count.items(), key=lambda x: x[0]))" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "value_freq = {}\n", - "for k in long_list:\n", - " if k in value_freq:\n", - " value_freq[k] += 1 #value_freq[k] + 1\n", - " else:\n", - " value_freq[k] = 1 # 0 + 1" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "dict_items([(11, 2), (230, 5), (127, 5), (183, 5), (142, 4), (186, 1), (256, 4), (182, 2), (184, 7), (50, 4), (266, 5), (179, 3), (22, 4), (30, 6), (59, 3), (236, 3), (155, 1), (57, 6), (262, 4), (279, 5), (107, 3), (98, 2), (271, 3), (240, 4), (276, 5), (23, 3), (170, 4), (207, 4), (123, 2), (228, 1), (231, 4), (205, 2), (161, 5), (125, 1), (212, 4), (224, 2), (34, 5), (272, 8), (106, 7), (164, 6), (26, 5), (263, 6), (3, 5), (234, 5), (244, 2), (260, 4), (135, 1), (29, 3), (116, 5), (44, 3), (206, 2), (131, 3), (218, 4), (201, 4), (140, 1), (208, 4), (130, 1), (247, 3), (227, 3), (242, 7), (112, 5), (138, 3), (192, 5), (7, 5), (268, 6), (168, 6), (5, 6), (246, 2), (199, 4), (6, 6), (300, 1), (54, 1), (69, 3), (64, 4), (61, 3), (15, 4), (288, 3), (190, 4), (78, 4), (165, 2), (178, 4), (71, 3), (62, 4), (75, 4), (2, 8), (52, 3), (195, 5), (80, 4), (90, 3), (33, 4), (241, 4), (39, 4), (32, 3), (160, 3), (172, 2), (108, 6), (144, 3), (251, 3), (278, 3), (120, 6), (99, 5), (148, 6), (185, 6), (136, 2), (235, 4), (114, 4), (229, 4), (88, 3), (225, 6), (250, 9), (152, 4), (0, 3), (252, 5), (173, 4), (283, 3), (72, 2), (94, 3), (76, 6), (226, 3), (4, 4), (28, 2), (175, 3), (56, 3), (249, 2), (19, 3), (203, 3), (196, 4), (216, 1), (280, 3), (102, 6), (74, 3), (277, 2), (159, 3), (63, 4), (124, 6), (166, 3), (137, 2), (14, 3), (255, 3), (41, 4), (187, 5), (60, 2), (147, 7), (84, 5), (10, 6), (35, 5), (248, 5), (163, 3), (171, 6), (174, 1), (219, 6), (290, 3), (239, 4), (42, 1), (103, 5), (58, 4), (181, 6), (18, 2), (111, 5), (119, 3), (210, 5), (213, 1), (286, 6), (285, 5), (91, 2), (232, 4), (1, 5), (275, 4), (176, 2), (65, 4), (12, 2), (253, 5), (150, 6), (157, 5), (31, 4), (95, 5), (96, 2), (105, 1), (261, 3), (146, 4), (217, 3), (134, 1), (8, 2), (46, 3), (93, 6), (264, 3), (53, 4), (293, 1), (238, 2), (122, 3), (85, 1), (221, 2), (77, 4), (13, 2), (27, 3), (17, 2), (296, 6), (297, 4), (115, 5), (66, 3), (145, 3), (254, 2), (20, 3), (49, 1), (289, 4), (222, 4), (194, 2), (193, 2), (126, 8), (83, 5), (104, 2), (274, 4), (267, 1), (223, 3), (121, 3), (257, 4), (214, 5), (291, 1), (284, 5), (162, 1), (204, 5), (180, 5), (79, 2), (45, 2), (139, 2), (158, 4), (273, 2), (258, 4), (36, 6), (287, 3), (132, 5), (270, 1), (47, 2), (86, 1), (143, 2), (233, 5), (73, 1), (133, 2), (48, 5), (100, 3), (87, 2), (292, 3), (243, 4), (298, 3), (282, 5), (117, 2), (128, 2), (55, 1), (265, 3), (202, 3), (189, 1), (101, 4), (67, 7), (109, 1), (177, 2), (51, 3), (220, 3), (188, 2), (21, 2), (68, 2), (281, 6), (294, 1), (82, 2), (9, 2), (38, 1), (167, 2), (40, 2), (113, 2), (209, 3), (97, 4), (118, 2), (299, 5), (81, 5), (151, 3), (169, 3), (149, 1), (141, 1), (295, 2), (43, 1), (24, 2), (70, 2), (110, 2), (25, 1), (37, 1), (198, 1), (200, 2), (211, 2), (89, 3), (154, 1), (153, 1), (92, 1), (259, 2), (269, 1), (16, 1), (245, 1)])\n" - ] - } - ], - "source": [ - "print(value_freq.items())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.12: find the first value appears 3 times in a list" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "26\n" - ] - } - ], - "source": [ - "freq_count = {}\n", - "for key in long_list:\n", - " if key not in freq_count:\n", - " freq_count[key]=1\n", - " else: \n", - " freq_count[key]+=1\n", - " if freq_count[key] == 3:\n", - " print(key)\n", - " break" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.13: print the following pattern of 10 rows and 19 columns" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "```\n", - "*******************\n", - "---------*---------\n", - "********---********\n", - "-------*****-------\n", - "******-------******\n", - "-----*********-----\n", - "****-----------****\n", - "---*************---\n", - "**---------------**\n", - "-*****************-\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "*******************\n", - "---------*---------\n", - "********---********\n", - "-------*****-------\n", - "******-------******\n", - "-----*********-----\n", - "****-----------****\n", - "---*************---\n", - "**---------------**\n", - "-*****************-\n" - ] - } - ], - "source": [ - "n_rows = 10\n", - "n_cols = 19\n", - "\n", - "for i in range(10):\n", - " if i == 0:\n", - " print(\"*\"*n_cols)\n", - " else:\n", - " if i % 2 == 1:\n", - " side, mid = \"-\", \"*\"\n", - " else:\n", - " side, mid = \"*\", \"-\"\n", - " print(side*(n_rows-i) + mid*(2*i -1) + side*(n_rows-i))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.14: Construct a geometric progression\n", - "- Xn = a* r^(n-1)" - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [], - "source": [ - "first_term, ratio = 512, 1.5\n", - "length = 20" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[512.0, 768.0, 1152.0, 1728.0, 2592.0, 3888.0, 5832.0, 8748.0, 13122.0, 19683.0, 29524.5, 44286.75, 66430.125, 99645.1875, 149467.7812, 224201.6719, 336302.5078, 504453.7617, 756680.6426, 1135020.9639]\n" - ] - } - ], - "source": [ - "gp_list = [round(first_term*(ratio**(n-1)), 4) for n in range(1,length+1)]\n", - "print(gp_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.15: find the start time of Einstein’s presentation\n", - "Suppose a presentation session at a conference starts at 8:05am, each speaker is given 25 minutes and they present in the ascending order of their surname, when does Einstein start to present?" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['Erwin Schroedinger', 'Wolfgang Pauli', 'Max Born', 'Niels Bohr', 'Max Planck', 'Madame Curie', 'Hendrik Antoon Lorentz', 'Albert Einstein', 'Paul Langevin', 'Louis Victor de Broglie', 'Paul Dirac', 'Werner Heisenberg']\n" - ] - } - ], - "source": [ - "physicists = ['Erwin Schroedinger', 'Wolfgang Pauli', 'Max Born', 'Niels Bohr', 'Max Planck', 'Madame Curie', 'Hendrik Antoon Lorentz', 'Albert Einstein', 'Paul Langevin', 'Louis Victor de Broglie', 'Paul Dirac', 'Werner Heisenberg']\n", - "print(physicists)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['Niels Bohr',\n", - " 'Max Born',\n", - " 'Louis Victor de Broglie',\n", - " 'Madame Curie',\n", - " 'Paul Dirac',\n", - " 'Albert Einstein',\n", - " 'Werner Heisenberg',\n", - " 'Paul Langevin',\n", - " 'Hendrik Antoon Lorentz',\n", - " 'Wolfgang Pauli',\n", - " 'Max Planck',\n", - " 'Erwin Schroedinger']" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sorted_physicists = sorted(physicists, key=lambda x: x.split()[-1])\n", - "sorted_physicists" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "125" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "present_time = {physicist: index*25 for index, physicist in enumerate(sorted_physicists)}\n", - "present_time['Albert Einstein']" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": { - "scrolled": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Einstein 's presentation time: 10:10 \n" - ] - } - ], - "source": [ - "from datetime import datetime, timedelta\n", - "time_str = '8:05'\n", - "time_format = '%H:%M'\n", - "# create datetime object from timestamp string\n", - "start_time = datetime.strptime(time_str, time_format)\n", - "#Add 125 mins to start_time, which will be Einstein's start time\n", - "final_time = start_time + timedelta(minutes=present_time['Albert Einstein'])\n", - "\n", - "# Convert datetime object to string in specific format \n", - "final_time_str = final_time.strftime(time_format)\n", - "print(f\"Einstein 's presentation time: {final_time_str} \")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Solution" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "10:10\n" - ] - } - ], - "source": [ - "surname = [i.split()[-1] for i in physicists] #Assume surname is the last word of each name\n", - "surname.sort()\n", - "start_time = (8*60 + 5) #start time convert to minutes\n", - "v = start_time + 25*surname.index(\"Einstein\")\n", - "print(f'{v//60:02d}:{v%60:02d}')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 1.16: list words that have appeared at least 3 times" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "speech = ['the United States has conducted an operation that killed Osama bin Laden',\n", - " 'Abu Bakr al-Baghdadi is dead',\n", - " 'the United States launched a targeted operation against that compound',\n", - " 'they did a lot of shooting and they did a lot of blasting even not going through the front door You know you would think you go through the door If you are a normal person you say Knock knock May I come in',\n", - " 'After a firefight they killed Osama bin Laden and took custody of his body',\n", - " 'He died like a dog',\n", - " 'Yet his death does not mark the end of our effort',\n", - " 'a beautiful dog a talented dog',\n", - " 'We give thanks for the men who carried out this operation',\n", - " 'And I dont get any credit for this but thats okay I never do But here we are',\n", - " 'May God bless you And may God bless the United States of America',\n", - " 'And Im writing a book I think I wrote 12 books All did very well']" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "word_count = dict()\n", - "for sentence in speech:\n", - " for word in sentence.split():\n", - " word = word.lower()\n", - " if word not in word_count:\n", - " word_count[word] = 1\n", - " else:\n", - " word_count[word] += 1" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "metadata": {}, - "outputs": [], - "source": [ - "freq_3 = [k for k,v in word_count.items() if v >= 3]" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "data": { - "text/plain": [ - "['the',\n", - " 'united',\n", - " 'states',\n", - " 'operation',\n", - " 'a',\n", - " 'they',\n", - " 'did',\n", - " 'of',\n", - " 'and',\n", - " 'you',\n", - " 'may',\n", - " 'i',\n", - " 'dog']" - ] - }, - "execution_count": 37, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "freq_3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Solution" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [], - "source": [ - "words = [word.lower() for sentence in speech for word in sentence.split()]" - ] - }, - { - "cell_type": "code", - "execution_count": 38, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "the united states operation a they did of and you may i dog\n" - ] - } - ], - "source": [ - "word_count = {}\n", - "for w in words:\n", - " word_count[w] = word_count.get(w, 0) + 1\n", - "print(\" \".join([w for w,c in word_count.items() if c >= 3]))" - ] - }, - { - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/W1_Python_Basics/tutorial_1.ipynb b/W1_Python_Basics/tutorial_1.ipynb deleted file mode 100644 index 9e79161..0000000 --- a/W1_Python_Basics/tutorial_1.ipynb +++ /dev/null @@ -1,725 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 1.21: Find the pair of nearest points in Euclidean distance\n", - "\n", - "Give a list of 200 2-dimensional points" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "points = [[1.6917766692855842, -5.755629277630385], [7.675827069862372, 7.301699114949773], [-3.2909129520196334, 9.613848011649935], [-9.085072103632527, -1.494685042518995], [-1.4697584875414886, -2.7246611030972367], [-2.976539234942413, -4.837062248394437], [-5.764304539098299, 2.993570134491293], [-7.315877529023922, -9.705105482173941], [1.707258575977411, 8.485934115270496], [-8.351619858350414, -5.223846451971372], [-5.828795444668502, 3.976366472397393], [8.720271552698694, -3.2124379846092825], [-0.4054482808742037, 9.317930145526955], [6.510986951874475, -2.1819354371980904], [-2.9962592160097756, -7.31509680893523], [9.083360339101048, 7.829967068419251], [-1.3331436878552552, 3.1603946549411432], [6.458132015006093, 8.822434340960669], [7.16827365354672, -3.4508012637846512], [-5.326845746838891, 9.040483027647156], [4.876441225663108, 5.232449738531539], [8.712743288792506, -3.7280349050848205], [7.466241207765329, 2.379265289757564], [-0.9978936202890551, 1.6449368506129112], [-2.6773431893653266, -0.40694827311359916], [-1.8106293810449987, 2.213838668872807], [4.947071131296752, 3.8097106485733008], [5.950466307087394, -7.2512068192895125], [-1.1945786627066717, -5.044692372482798], [2.8811835000735186, 8.851997733796221], [-0.2955365925438471, -9.53917142360364], [-2.011593976593165, -3.542159913868959], [-5.769156935219925, -5.5530087458111606], [9.295871879150603, -3.1240063531616125], [9.756200956431801, 6.479447636789221], [0.8652659943599339, 7.223803402253235], [-3.0332492431783713, -2.1682838845029355], [-0.46657573289961896, 6.8578688639078464], [-2.8117123795590304, -9.572150259865635], [7.203169784969749, 8.753192289873127], [5.224452974702636, 6.857696807277627], [-0.049900556065052726, -1.6942071762016973], [3.5917999402331073, 5.805997834258715], [-5.726479558318768, -7.825976148522635], [4.4719508762928974, -0.47119270370785493], [-8.51658927302788, 9.019684845294073], [9.998303580126834, 1.0909413091749443], [-7.490707783997972, -4.918960983306291], [-2.3814557996463215, 0.4179856971303444], [-4.74392775076129, -4.954224114510013], [-3.3798603785546284, 7.4349511827236405], [3.348941636633935, -4.119066801277675], [3.069597715313229, 8.095932206766918], [-9.977767715384749, 6.31860517880245], [-7.694480444296634, -2.2312884198209426], [7.009378799427232, -9.813278209833005], [-6.892764172568169, 0.4037318298032808], [1.934551861184664, 9.647259153474256], [-1.684970151131278, 6.715523798836713], [4.778791910872442, -6.302597588632741], [7.880213948051896, -6.87757837319777], [3.018764954167871, 9.55577737941606], [9.442098648513728, -1.7971299117298027], [4.294009056182848, 2.9257922144291086], [-7.488141519192402, 3.194146869954558], [4.4044943363257865, 3.47156887284239], [-5.265210866237737, 0.935707859404797], [1.0874401120301478, 4.769687266008177], [3.6677610968015735, 2.329559760946882], [1.3264496075559418, 6.8853295396453476], [2.5218992542292025, -5.3065171699363445], [-6.891179995601471, 1.4638922450737049], [-4.104604058398198, -0.3519967592988227], [-6.387767854843327, -4.577263623649737], [5.677380281111347, -7.529320047947541], [6.8499814135785435, 2.7651117469683975], [4.524713991980372, 7.031248939975825], [-6.219936466401483, 6.892438002621454], [7.118149238188241, -9.529551925292782], [4.114057119430395, -2.8804850370519564], [1.1264331754207308, 9.342444010097452], [-3.3387597997519496, -1.030669371597714], [2.754752556298641, -3.8303761593096564], [2.909388807772359, -5.627376431102753], [4.069630695597288, 4.094098821729082], [-0.22956514974007902, -4.58853096311544], [7.534625539128605, -4.639398935950235], [4.0975226435368235, 1.7820187555361073], [4.523097584062741, 1.049588730388077], [8.417023917682236, 0.1800789755507548], [0.7221429129456567, 6.043776101932181], [7.951069747757323, 3.5232376580146934], [4.436388479108524, 1.9518412860140444], [0.8948126626225257, 1.6870313023848187], [-8.572283501649252, 7.636418415404268], [-7.598099763010668, 9.74677805351963], [-5.474665381459111, -0.09997403697378004], [-9.62348607265123, 8.1817556106746], [4.832941301248653, -7.471586076153429], [0.05489249120935469, 4.427018862646381], [-0.7623078015360356, -4.907223326092369], [5.034440191453175, -7.262422368215999], [0.6749115867488484, 1.0617316506040897], [-5.1257522163309694, 3.0558877666004243], [7.989879083992175, 6.113310630467961], [-6.717271141351702, 6.257733867841495], [2.983926361240556, 3.042070100993019], [5.110723815722771, 9.969387392449438], [7.979605659313002, -3.119594793941558], [2.8722736848244175, -8.92267951192901], [1.4725245815339516, 7.7370401415203425], [5.418909068505318, -9.899664895856628], [-0.3293559589320534, -9.437455767069785], [-5.34092368773914, 0.9864061312783186], [-5.154479072122699, 6.40140805792705], [-0.9157534309671682, -3.9493086221799834], [6.995617487705161, 4.338249584691781], [-4.621252431635439, -5.671606152930753], [-7.925718226173945, 5.084347460461391], [-9.208656699649092, 2.2542831481077954], [2.677446578667597, -2.815260402542414], [1.5725772741199417, 5.984661070798369], [-8.214349445840588, 2.8719923126330187], [-5.250694847383057, 8.186106947277043], [-9.602658269493816, 9.444386484846465], [9.115835186422256, 5.871935528361178], [-2.5287196350232737, 2.887246469932851], [-2.1372641737135734, -1.8391371234033809], [-1.1082552861090988, -4.2077726793698496], [4.629226584152599, -1.8924358944589734], [-5.2525786527691665, -9.369867782433111], [9.689666432703984, 8.631856666441546], [-3.1058640538038906, -7.112691119818997], [3.8351850067247675, -7.816140083215879], [8.059420357182002, -3.9918994148213045], [8.987126313071869, 9.670169215984295], [-8.004125422134386, -7.1932295635881065], [-0.06738368787870286, 4.151225812072738], [-6.321804627995416, 6.465945820534664], [-6.272914208292708, -6.651387059839684], [-0.650918077356728, 1.1571804929060008], [9.900367553654284, -9.549655307552209], [-5.356214337566534, -1.5157332931067398], [-5.493398811827042, -5.103215154502985], [4.394427744530926, -6.258852539216266], [0.651214329260787, 8.205110848341754], [-2.887747978726665, 0.45437176710394667], [7.2358298248090875, -0.7626602653399406], [-1.6802984837606445, -1.521300620569285], [6.2871381561148745, 7.550379731999151], [8.828265968582258, -5.450358190359445], [-2.771419010097665, 4.965733736649366], [7.283791183364258, -9.330647069466309], [1.1503066518591716, -1.494280922589116], [5.430985505849231, 3.6506997889161177], [6.368883543730131, 2.5665925873045214], [8.27268807049646, -2.8108071086508613], [-8.761049538238906, -1.6668399813187218], [6.969563475322449, 4.870653532707438], [-3.8088639686044923, -8.04770050129066], [-6.588753626385426, -5.479445503860109], [0.3628758153674525, -7.375003116652234], [4.2110293083088735, -8.173588108962464], [9.109404060819152, 5.0945898294577425], [1.202164552896999, -6.704377860207917], [3.678524338607412, -6.480872921026548], [-9.2398934138698, 9.76162162677548], [5.014304634637492, -2.4366142669971076], [-0.7032174537587714, -8.412492474901585], [-7.914280615312719, -9.611747935706859], [8.375659961940777, 8.983443372571148], [-3.3398204611856848, -4.1187025796210825], [7.776476441020563, -2.147519947412942], [6.021515870950164, 9.586902937160275], [5.399893902345628, -4.2287458010492145], [1.1876175402532994, -1.6866656645274158], [9.74486427533984, 4.557794093707109], [-9.224676163399579, -2.700399005920211], [0.8443253817877387, 5.148506043849885], [3.8089155234248278, -0.08432848625492895], [8.657341530126452, 9.731798284743121], [5.54498708607046, -9.173588536034211], [-3.324039445073714, 9.816471573057132], [3.4925222371530076, -4.5624259495605095], [-9.58522266877101, -2.958387712219963], [-6.1029158407825275, 0.3190439014138118], [2.9081452608597242, 0.15094304627423938], [8.14261912316013, 0.14005581572142312], [-9.86297822478999, 9.9630163124958], [2.8257928317496344, -2.7283387054290165], [3.7547434905675114, -1.7952181505798883], [-5.749168201073395, 6.1766418276003705], [-4.680119791390682, 8.930237286122129], [-3.953594775616896, 6.842726263223426], [8.502438568323704, -0.7444855789600986], [-2.9955321537705615, 3.3497140964060073], [-2.1949766474129113, 2.0897368044250157], [8.72756539060871, 4.6607545572283104], [-4.153754350587191, 2.3678095388120113], [4.862091715463841, 2.1254725176755827]]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "200" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import math\n", - "len(points)" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Min = 0.0911 where points are [-5.265210866237737, 0.935707859404797], and [-5.34092368773914, 0.9864061312783186] \n" - ] - } - ], - "source": [ - "\n", - "dist_dict = dict()\n", - "for i in range(len(points)):\n", - " for j in range(i+1, len(points)):\n", - " dist_dict[(i,j)] = math.sqrt((points[i][0] - points[j][0])**2 + (points[i][1] - points[j][1])**2)\n", - "\n", - "pair, min_dist = min(dist_dict.items(), key=lambda x: x[1]) \n", - "print(f\"Min = {min_dist:.4f} where points are {points[pair[0]]}, and {points[pair[1]]} \")" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0.09111940578529276 [-5.265210866237737, 0.935707859404797] [-5.34092368773914, 0.9864061312783186]\n" - ] - } - ], - "source": [ - "n = len(points)\n", - "min_dist = float(\"inf\") \n", - "min_i, min_j = 0,0\n", - "for i in range(n):\n", - " for j in range(i+1, n):\n", - " d = math.sqrt((points[i][0] - points[j][0])**2 + (points[i][1] - points[j][1])**2)\n", - " if d < min_dist:\n", - " min_dist, min_i, min_j = d, i, j\n", - " \n", - "print(min_dist, points[min_i],points[min_j]) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 1.22: Find longest palindrome\n", - "\n", - "if two palindromes are of same length, return the one appears first
\n", - "optional part: if two palindromes are of same length, return the one appears first in alphabetical order" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "e.g. s = 'abbabcdefghijihgfedcbaaabbbbaaaabbaaaabbbbaaabc' => return 'cbaaabbbbaaaabbaaaabbbbaaabc'" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [], - "source": [ - "s = 'abbabcdefghijihgfedcbaaabbbbaaaabbaaaabbbbaaabc'" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'abcdefghijihgfedcba'" - ] - }, - "execution_count": 24, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "s[3:22]" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "28 cbaaabbbbaaaabbaaaabbbbaaabc\n" - ] - } - ], - "source": [ - "max_value = float(\"-inf\")\n", - "palindrome = \"\"\n", - "\n", - "for i in range(len(s)):\n", - " for j in range(i+1, len(s)):\n", - " if s[i:j+1] == s[i:j+1][::-1]: #j + 1 as s[i:j+1] as not including j+1\n", - " pal_len = len(s[i:j+1]) \n", - " if pal_len > max_value:\n", - " max_value = pal_len\n", - " palindrome = s[i:j+1]\n", - "\n", - "print(max_value, palindrome)" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{1: 'a', 3: 'aaa', 19: 'abcdefghijihgfedcba', 5: 'baaab', 4: 'abba', 2: 'aa', 10: 'aaabbbbaaa', 8: 'bbaaaabb', 28: 'cbaaabbbbaaaabbaaaabbbbaaabc'}\n" - ] - } - ], - "source": [ - "n = len(s)\n", - "palindrome = {}\n", - "\n", - "#Case 1 - Pal is Odd: aba - i is in the center\n", - "for i in range(n):\n", - " j = 1\n", - " while( j <= i and j < n - i): #i - j >=0 => i >= j; i+j < n => j < n - i\n", - " if s[i-j] != s[i+j]:\n", - " break\n", - " j+=1\n", - " #len_pal = 2*j - 1 as we double counts (2*j) the center, so need to minus 1 center\n", - " #s[i-j+1:i+j] < palindrome[2*j -1] to take care \"return the one appears first in alphabetical order\" \n", - " if 2*j -1 not in palindrome or s[i-j+1:i+j] < palindrome[2*j -1]: \n", - " palindrome[2*j -1] = s[i-j+1:i+j]\n", - "\n", - "#Case 2 - Pal is Even: abba i and i+1 in the center\n", - "for i in range(n-1):\n", - " if s[i] == s[i+1]:\n", - " j = 1\n", - " while( j <= i and j < n - i - 1): #i - j >=0 => i >= j; i+j < n-1 => j < n - i -1\n", - " if s[i-j] != s[i+1+j]:\n", - " break\n", - " j+=1\n", - " if 2*j not in palindrome or s[i-j+1:i+1+j] < palindrome[2*j]: \n", - " palindrome[2*j] = s[i-j+1:i+1+j]\n", - "\n", - "print(palindrome)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 1.23 : Largest number in a string matching -- in single scan\n", - "\n", - "e.g. string = 'abc123def789.456' => return 789.456" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [], - "source": [ - "s = 'abc123def789.456' " - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "['123', '789.456']\n", - "789.456\n" - ] - } - ], - "source": [ - "import re\n", - "\n", - "x = re.findall(r\"\\d+.\\d+\", string)\n", - "print(x)\n", - "print(max(x, key=lambda x: len(x)))" - ] - }, - { - "cell_type": "code", - "execution_count": 21, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "789.456\n" - ] - } - ], - "source": [ - "n = len(s)\n", - "max_float = 0.0\n", - "first, second = '0','0' #2 container\n", - "for i in range(n):\n", - " if s[i].isdigit():\n", - " first += s[i]\n", - " second += s[i]\n", - " elif s[i] == '.':\n", - " max_float = max(max_float, float(second))\n", - " second = first+'.' #use second container to continue after '.'\n", - " first = '0' #reset first container to zero\n", - " elif len(first) > 1 or len(second) > 1: #If we found a char not '.', we need to store the current value\n", - " max_float = max(max_float, max(float(first), float(second)))\n", - " first, second = '0', '0'\n", - " else:\n", - " pass\n", - "\n", - " #In case, it breaks the loop, but yet to compare the final first and second with max_float\n", - "max_float = max(max_float, max(float(first), float(second))) \n", - "print(max_float)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 1.24: Write the naive primality test algorithm" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Basic method : check one by one (the most naive version: check number by number, factor by factor)
\n", - "Example:\n", - "- check if 13 is a prime
\n", - "-- check from all numbers between 2 and 12 inclusive, none of them is a factor of 13
\n", - "-- then we know 13 is a prime
\n", - "- proceed to 14 to check if it is a prime" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Improvement 1: primality can be determined as long as one non-trivial factor is found
\n", - "Improvement 2: do you need to check even numbers? Can an odd number be divided by an even number?
\n", - "Improvement 3: can checking on non-trivial factors be terminated earlier?" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "num = 13\n", - "def check_primality(num):\n", - " if num % 2 == 0 and num != 2:\n", - " return False\n", - " else:\n", - " for i in range(3, num, 2):\n", - " if num%i == 0:\n", - " return False\n", - " else:\n", - " return True\n", - "\n", - "check_primality(2)" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 121, 127, 131, 137, 139, 143, 149, 151, 157, 163, 167, 169, 173, 179, 181, 191, 193, 197, 199]\n" - ] - } - ], - "source": [ - "prime = [2]\n", - "for i in range(3, 200, 2):\n", - " is_prime = True\n", - " for f in range(3, int(math.sqrt(i)), 2):\n", - " if i % f == 0:\n", - " is_prime = False\n", - " break\n", - " if is_prime:\n", - " prime.append(i)\n", - "print(prime)" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199]\n" - ] - } - ], - "source": [ - "prime = [2]\n", - "for i in range(3,200,2):\n", - " f = 3\n", - " while f*f <=i:\n", - " if i % f == 0:\n", - " break\n", - " f+=2 #Since we dont need to divide by even number\n", - " else:\n", - " prime.append(i)\n", - "print(prime)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 1.25: Sudoku checker (I) -- return the list of possible values for each cell" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "| | | | | | | | | |\n", - "|---|---|---|---|---|---|---|---|---|\n", - "| | |7| | | |1|?|&|\n", - "| |5|9| | | |2|3|%|\n", - "|8|2|3| | | |4|5|6|\n", - "|5|1| | | | | |7|8|\n", - "|9| | |1| |3| | |4|\n", - "| | |4|2| |8|9| | |\n", - "| |7|5|3| |6|8|9| |\n", - "| |8|6| | | |7|1| |\n", - "| |9| | | | | |4| |" - ] - }, - { - "cell_type": "code", - "execution_count": 35, - "metadata": {}, - "outputs": [], - "source": [ - "sudoku1 = [' 7 1 ', ' 59 23 ', '823 456', '51 78', '9 1 3 4', ' 42 89 ', ' 753 689 ', ' 86 71 ', ' 9 4 ']\n", - "sudoku2 = [' ', ' 528 614 ', ' 98 27 ', ' 12 39 ', '735 682', ' 695 741 ', ' 1 3 8 9 ', '42 7 1 65', ' ']\n", - "sudoku3 = [' 76 3 ', ' 13 8 92', ' 4 2 31 ', ' 86 5 9', '26 78', '4 9 82 ', ' 17 5 2 ', '95 3 41 ', ' 2 96 ']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Example:\n", - "Take the 3x3 square at the upper right corner for example, 1, 2, 3, 4, 5, 6 are already filled. We use '?', '&' and '%' to represent the remaining three positions.
\n", - "7 cannot be in the first row, as there is a 7 in the first row in the 3x3 square upper left corner. So 7 must be at the position '%', so 7 is the only possible value at the cell (row = 2, col = 9), and we write '(2, 9): 7' in one line.
\n", - "Likewise, 8 cannot be in the last column, as there is already a 8 in the last column. So 8 must be at the position '?', we write '(1, 8): 8' to state the only possible value at cell (row = 1, col = 8) is 8.
\n", - "After that, the only missing value in the 3x3 square upper right corner is 9, and it must be at the position '&'. Therefore, we write '(1, 9): 9'.
\n", - "In this exercise, your goal is to list possible values for each cell. When there is uncertainty, you are allowed to list multiple values for one cell, but try your best to keep this list as short as possible, i.e., remove as many impossible values as possible for each cell." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Hint:\n", - "1. Build the initial sudoku board with -1 being unfilled ==> the board is a 2-dimensional array\n", - "2. Build a list of possible values for each cell ==> this should be a 3-dimensional array\n", - "3. If a cell is marked with a value v
\n", - "3a) other cells in the same row should mark v as impossible
\n", - "3b) other cells in the same column should mark v as impossible
\n", - "3c) the 3x3 square where this cell is in should mark v as impossible
\n", - "4. Output the list of possible values for each empty cell" - ] - }, - { - "cell_type": "raw", - "metadata": {}, - "source": [ - "# for sudoku1, as shown above, the result should look like this:\n", - "(1, 1): 4 6\n", - "(1, 2): 4 6\n", - "(1, 4): 4 5 6 8 9\n", - "(1, 5): 2 3 4 5 6 8 9\n", - "(1, 6): 2 4 5 9\n", - "(1, 8): 8\n", - "(1, 9): 9\n", - "(2, 1): 1 4 6\n", - "(2, 4): 4 6 7 8\n", - "(2, 5): 1 4 6 7 8\n", - "(2, 6): 1 4 7\n", - "(2, 9): 7\n", - "(3, 4): 7 9\n", - "(3, 5): 1 7 9\n", - "(3, 6): 1 7 9\n", - "(4, 3): 2\n", - "(4, 4): 4 6 9\n", - "(4, 5): 4 6 9\n", - "(4, 6): 4 9\n", - "(4, 7): 3 6\n", - "(5, 2): 6\n", - "(5, 3): 2 8\n", - "(5, 5): 5 6 7\n", - "(5, 7): 5 6\n", - "(5, 8): 2 6\n", - "(6, 1): 3 6 7\n", - "(6, 2): 3 6\n", - "(6, 5): 5 6 7\n", - "(6, 8): 6\n", - "(6, 9): 1 3 5\n", - "(7, 1): 1 2 4\n", - "(7, 5): 1 2 4\n", - "(7, 9): 2\n", - "(8, 1): 2 3 4\n", - "(8, 4): 4 5 9\n", - "(8, 5): 2 4 5 9\n", - "(8, 6): 2 4 5 9\n", - "(8, 9): 2 3 5\n", - "(9, 1): 1 2 3\n", - "(9, 3): 1 2\n", - "(9, 4): 5 7 8\n", - "(9, 5): 1 2 5 7 8\n", - "(9, 6): 1 2 5 7\n", - "(9, 7): 3 5 6\n", - "(9, 9): 2 3 5" - ] - }, - { - "cell_type": "code", - "execution_count": 28, - "metadata": {}, - "outputs": [], - "source": [ - "def build_sudoku_board(board):\n", - " return [[int(item) if not item.isspace() else -1 for item in row] for row in board]\n", - "\n", - "board = build_sudoku_board(sudoku1)" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "metadata": {}, - "outputs": [], - "source": [ - "def find_next_empty(puzzle):\n", - " for r in range(9):\n", - " for c in range(9):\n", - " if puzzle[r][c] == -1:\n", - " return (r, c)\n", - " return None, None #if no spaces in the puzzle to make a guess\n", - "\n", - "def is_valid(puzzle, guess, row, col):\n", - " # figures out whether the guess at the row/col of the puzzle is a valid guess\n", - " # returns True or False\n", - " # Let s start with the row:\n", - " row_vals = puzzle[row]\n", - " #Column:\n", - " col_vals = [r[col] for r in puzzle]\n", - " if guess in row_vals:\n", - " return False\n", - " if guess in col_vals:\n", - " return False\n", - " #And then the square 3x3 matrix\n", - " #Find the start index of 3x3 matrix\n", - " row_start = (row//3)*3 #row//3 to identify if first, second or third matrix\n", - " col_start = (col//3)*3\n", - " for r in range(row_start, row_start+3):\n", - " for c in range(col_start, col_start+3):\n", - " if puzzle[r][c] == guess:\n", - " return False\n", - " return True\n", - " \n", - "def solve_sudoku(puzzle):\n", - " # Step 1: Choose somewhere on the puzzle to make a guess\n", - " row, col = find_next_empty(puzzle)\n", - " # Step 1.1: if row, col = None, we finished\n", - " if row is None:\n", - " return True\n", - " # step 2: if there is a place to put a number, then make a guess between 1 and 9\n", - " for guess in range(1,10):\n", - " # step 3: check if this is a valid guess\n", - " if is_valid(puzzle, guess, row, col):\n", - " # Step 3.1: \n", - " puzzle[row][col] = guess\n", - " if solve_sudoku(puzzle):\n", - " return True\n", - " # step 5: it not valid or if nothing gets returned true, then we need to backtrack and try a new number\n", - " puzzle[row][col] = -1\n", - " return False" - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 30, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "solve_sudoku(board)" - ] - }, - { - "cell_type": "code", - "execution_count": 31, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[[6, 4, 7, 5, 3, 2, 1, 8, 9],\n", - " [1, 5, 9, 6, 8, 4, 2, 3, 7],\n", - " [8, 2, 3, 7, 9, 1, 4, 5, 6],\n", - " [5, 1, 2, 4, 6, 9, 3, 7, 8],\n", - " [9, 6, 8, 1, 7, 3, 5, 2, 4],\n", - " [7, 3, 4, 2, 5, 8, 9, 6, 1],\n", - " [4, 7, 5, 3, 1, 6, 8, 9, 2],\n", - " [2, 8, 6, 9, 4, 5, 7, 1, 3],\n", - " [3, 9, 1, 8, 2, 7, 6, 4, 5]]" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "board" - ] - }, - { - "cell_type": "code", - "execution_count": 32, - "metadata": {}, - "outputs": [], - "source": [ - "value = [[-1]*9 for _ in range(9)]\n", - "possible = [[[True]*10 for _ in range(9)] for _ in range(9)] #10 we need to map possible[1] to possible[9], will ignore possible[0]" - ] - }, - { - "cell_type": "code", - "execution_count": 33, - "metadata": {}, - "outputs": [], - "source": [ - "value = []\n", - "for _ in range(9):\n", - " value.append([-1]*9)\n", - "possible = []\n", - "for _ in range(9):\n", - " for _ in range(9):\n", - " possible.append([True]*10)" - ] - }, - { - "cell_type": "code", - "execution_count": 37, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "'bool' object does not support item assignment", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mvv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m10\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mvv\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0mpossible\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mj\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mvv\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 12\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mjj\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m9\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mjj\u001b[0m \u001b[0;34m!=\u001b[0m \u001b[0mj\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mTypeError\u001b[0m: 'bool' object does not support item assignment" - ] - } - ], - "source": [ - "i = 0\n", - "for s in sudoku1:\n", - " if len(s) != 9:\n", - " print('Length sould be 9', s)\n", - " for j in range(9):\n", - " if s[j] != ' ':\n", - " v = int(s[j])\n", - " value[i][j] = v\n", - " for vv in range(1, 10):\n", - " if vv != v:\n", - " possible[i][j][vv] = False\n", - " for jj in range(9):\n", - " if jj != j:\n", - " possible[i][jj][v] = False\n", - " for ii in range(9):\n", - " if ii != i:\n", - " possible[ii][j][v] = False\n", - " gi, gj = (i // 3)*3, (j//3)*3\n", - " for ii in range(3):\n", - " for jj in range(3):\n", - " if gi + ii != i or gj + jj != j: #to ensure not the same row and col\n", - " possible[gi+ii][gj+jj][v] = False\n", - " i +=1\n", - "for i in range(9):\n", - " for j in range(9):\n", - " if value[i][j] == -1:\n", - " print(f\"({i+1, j+1}): {''.join([str(v) for v in range(1,10) if possible[i][j][v]])}\")" - ] - }, - { - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/W1_Python_Basics/tutorial_1_answer.pdf b/W1_Python_Basics/tutorial_1_answer.pdf deleted file mode 100644 index 168b05d..0000000 Binary files a/W1_Python_Basics/tutorial_1_answer.pdf and /dev/null differ diff --git a/W2_Function_Lambda/.DS_Store b/W2_Function_Lambda/.DS_Store deleted file mode 100644 index 5008ddf..0000000 Binary files a/W2_Function_Lambda/.DS_Store and /dev/null differ diff --git a/W2_Function_Lambda/.ipynb_checkpoints/class_exercise_2-checkpoint.ipynb b/W2_Function_Lambda/.ipynb_checkpoints/class_exercise_2-checkpoint.ipynb deleted file mode 100644 index b5fde6c..0000000 --- a/W2_Function_Lambda/.ipynb_checkpoints/class_exercise_2-checkpoint.ipynb +++ /dev/null @@ -1,1518 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Python programming and Data Analysis\n", - "\n", - "## Class Exercise 2 -- Python Intermediate" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Before function – Operators " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n", - "False\n", - "True\n" - ] - } - ], - "source": [ - "str1 = 'abc'\n", - "str2 = 'def'\n", - "print('a' in str1)\n", - "print('a' in str2)\n", - "print('a' not in str1)\n", - "print('a' not in str2)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n", - "False\n", - "True\n" - ] - } - ], - "source": [ - "x = 5\n", - "print(type(x) is int)\n", - "print(type(x) is str)\n", - "\n", - "print(type(x) is not int)\n", - "print(type(x) is not str)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Functions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Define & Call" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n" - ] - } - ], - "source": [ - "def add(a, b):\n", - " c = a + b\n", - " print(c)\n", - "\n", - "add(2, 3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Arguments" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike is 40 years old.\n" - ] - } - ], - "source": [ - "def info(name, age):\n", - " print(name, 'is', age, 'years old.')\n", - "\n", - "info('Mike', 40) " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "40 is Mike years old.\n" - ] - } - ], - "source": [ - "info(40, 'Mike')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "info() missing 1 required positional argument: 'age'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0minfo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m40\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m: info() missing 1 required positional argument: 'age'" - ] - } - ], - "source": [ - "info(40)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike is 40 years old.\n", - "Mike is 40 years old.\n" - ] - } - ], - "source": [ - "def info(name, age):\n", - " print(name, 'is', age, 'years old.')\n", - "\n", - "info(name = 'Mike', age = 40)\n", - "info(age = 40, name = 'Mike') " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike is 40 years old.\n", - "Mike is 35 years old.\n" - ] - } - ], - "source": [ - "def info(name, age = 35):\n", - " print(name, 'is', age, 'years old.')\n", - "\n", - "info('Mike', 40)\n", - "info('Mike')" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike's hobbies: \n", - "Mike's hobbies: hiking, reading\n" - ] - } - ], - "source": [ - "def info(name, *args):\n", - " hobby = []\n", - " for a in args:\n", - " hobby.append(a)\n", - " print(name +\"'s hobbies: \" + ', '.join(hobby))\n", - "\n", - "info('Mike')\n", - "info('Mike', 'hiking', 'reading') " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike's hobbies: first-hiking, second-reading\n" - ] - } - ], - "source": [ - "def info(name, **kwargs):\n", - " hobby = []\n", - " for k, v in kwargs.items():\n", - " hobby.append(k+'-'+v)\n", - " print(name +\"'s hobbies: \" + ', '.join(hobby))\n", - "\n", - "info('Mike', first='hiking', second='reading')" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Python Data Analysis\n", - "Python Data Analysis\n" - ] - } - ], - "source": [ - "def func(a1, a2, a3):\n", - " print(a1,a2,a3)\n", - " \n", - "args = ('Python', 'Data', 'Analysis')\n", - "func(*args)\n", - "\n", - "kwargs = {'a1' : 'Python', 'a2' : 'Data', 'a3' : 'Analysis'}\n", - "func(**kwargs)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "args: ('I', 'love')\n", - "kwargs: {'first': 'Python programming', 'mid': 'and', 'last': 'Data Analysis'}\n", - "I love Python programming and Data Analysis\n" - ] - } - ], - "source": [ - "def func(*args,**kwargs):\n", - " print('args: ', args)\n", - " print('kwargs: ', kwargs)\n", - " print(' '.join(args), ' '.join(kwargs.values()))\n", - " \n", - "func('I', 'love', first='Python programming', mid='and', last='Data Analysis')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Return" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n", - "(1, 3)\n" - ] - } - ], - "source": [ - "def func1(a,b):\n", - " return a\n", - "\n", - "def func2(a,b):\n", - " return a,b\n", - "\n", - "print(func1(1,3))\n", - "print(func2(1,3))" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 3]\n", - "{'a': 1, 'b': 3}\n" - ] - } - ], - "source": [ - "def func3(a,b):\n", - " return [a,b]\n", - "\n", - "def func4(a,b):\n", - " return {'a': a, 'b': b}\n", - "\n", - "print(func3(1,3))\n", - "print(func4(1,3))" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4\n", - "6\n" - ] - } - ], - "source": [ - "def by_factor(factor):\n", - " def multiply(number):\n", - " return factor * number\n", - " return multiply\n", - "\n", - "double = by_factor(2)\n", - "print(double(2))\n", - "print(double(3))" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n" - ] - } - ], - "source": [ - "def add(a, b):\n", - " c = a + b\n", - " return c\n", - "\n", - "result = add(2, 3)\n", - "print(result)" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n", - "None\n" - ] - } - ], - "source": [ - "def add2(a, b):\n", - " c = a + b\n", - " print(c)\n", - "\n", - "result2 = add2(2, 3)\n", - "print(result2)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3.7200759760208356e-44\n", - "0.5\n", - "1.0\n" - ] - } - ], - "source": [ - "def logistic(x):\n", - " return 1/(1+math.exp(-x))\n", - "\n", - "print(logistic(-100))\n", - "print(logistic(0))\n", - "print(logistic(100))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Variable Scope" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "local\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'y' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0mtest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mNameError\u001b[0m: name 'y' is not defined" - ] - } - ], - "source": [ - "def test():\n", - " y = 'local'\n", - " print(y)\n", - "\n", - "test()\n", - "print(y) " - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "global\n", - "global\n" - ] - } - ], - "source": [ - "y = 'global'\n", - "def test():\n", - " global y\n", - " print(y)\n", - "\n", - "test()\n", - "print(y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.11: find out all the prime numbers in a given list" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "num_list = [649, 778, 652, 653, 912, 402, 917, 536, 664, 922, 284, 158, 415, 672, 673, 33, 419, 414, 421, 811, 683, 48, 818, 566, 567, 310, 580, 838, 199, 586, 458, 460, 337, 728, 604, 94, 607, 865, 354, 230, 367, 752, 625, 371, 505, 635, 893, 382, 767]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Lambda Expressions" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "add=lambda x, y: x+y\n", - "add(1, 2) " - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sum = lambda x: 1\n", - "sum([2,3])" - ] - }, - { - "cell_type": "code", - "execution_count": 48, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[3, 2, 4, 1, 5]" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sorted([1, 2, 3, 4, 5], key = lambda x: abs(3 - x))" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 3, 5]" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "list(filter(lambda n: n % 2 == 1, [1, 2, 3, 4, 5]))" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[2, 3, 4]" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "list(map(lambda x: x + 1, [1, 2, 3]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.12: use the prime function you created in exercise 1 and lambda to find out all the prime numbers in a given list in one line" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Modules" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3.141592653589793\n", - "3.141592653589793\n", - "3.141592653589793\n" - ] - } - ], - "source": [ - "import math\n", - "print(math.pi)\n", - "\n", - "import math as mt\n", - "print(mt.pi)\n", - "\n", - "from math import pi\n", - "print(pi)\n", - "\n", - "from math import * " - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "7\n", - "0.187558625103874\n", - "3\n", - "b\n" - ] - } - ], - "source": [ - "import random as rnd\n", - "print(rnd.randint(0, 10))\n", - "print(rnd.random())\n", - "lst = list(range(10))\n", - "print(rnd.choice(lst))\n", - "print(random.choice('abc'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Classes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Class and Instance" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1469952256\n", - "\n" - ] - } - ], - "source": [ - "a = 2\n", - "print(id(a))\n", - "print(type(a)) " - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1469952256\n", - "\n" - ] - } - ], - "source": [ - "b = 2\n", - "print(id(b))\n", - "print(type(b)) " - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1469952288\n", - "\n" - ] - } - ], - "source": [ - "c = 3\n", - "print(id(c))\n", - "print(type(c)) " - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023259656\n", - "1531023259656\n", - "[1, 2, 3]\n", - "[1, 2, 3]\n", - "1531023259656\n", - "1531023259656\n" - ] - } - ], - "source": [ - "a = [1,2]\n", - "b = a\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "b.append(3)\n", - "print(a)\n", - "print(b)\n", - "print(id(a)) \n", - "print(id(b)) " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4426390664\n", - "4426391176\n", - "True\n", - "False\n" - ] - } - ], - "source": [ - "a = [1,2]\n", - "b = [1,2]\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "print(a == b)\n", - "print(a is b) " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4389863968\n", - "4389863968\n", - "True\n", - "True\n" - ] - } - ], - "source": [ - "a = 101\n", - "b = 101\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "print(a == b)\n", - "print(a is b) " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4426665552\n", - "4426665104\n", - "True\n", - "False\n" - ] - } - ], - "source": [ - "c = 1001\n", - "d = 1001\n", - "print(id(c)) \n", - "print(id(d)) \n", - "\n", - "print(c == d)\n", - "print(c is d) " - ] - }, - { - "cell_type": "code", - "execution_count": 96, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023200840\n", - "1531023200840\n", - "[[9, 1], 2, 3, 4]\n", - "[[9, 1], 2, 3, 4]\n", - "1531023200840\n", - "1531023200840\n" - ] - } - ], - "source": [ - "a = [[0, 1], 2, 3]\n", - "b = a\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "b.append(4)\n", - "b[0][0] = 9\n", - "print(a)\n", - "print(b)\n", - "print(id(a))\n", - "print(id(b))" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023204040\n", - "1531023260168\n", - "1531023201608\n", - "1531023201608\n", - "[[9, 1], 2, 3]\n", - "[[9, 1], 2, 3, 4]\n" - ] - } - ], - "source": [ - "import copy\n", - "a = [[0, 1], 2, 3]\n", - "b = copy.copy(a)\n", - "print(id(a))\n", - "print(id(b))\n", - "print(id(a[0]))\n", - "print(id(b[0]))\n", - "\n", - "b.append(4)\n", - "b[0][0] = 9\n", - "print(a)\n", - "print(b) " - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023203336\n", - "1531023203784\n", - "1531023200840\n", - "1531022909128\n", - "[[0, 1], 2, 3]\n", - "[[9, 1], 2, 3, 4]\n" - ] - } - ], - "source": [ - "import copy\n", - "a = [[0, 1], 2, 3]\n", - "b = copy.deepcopy(a)\n", - "print(id(a)) \n", - "print(id(b))\n", - "print(id(a[0]))\n", - "print(id(b[0]))\n", - "\n", - "b.append(4)\n", - "b[0][0] = 9\n", - "print(a)\n", - "print(b) " - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023380864\n", - "Hello!\n", - "1531023382824\n" - ] - } - ], - "source": [ - "string = 'Hello'\n", - "print(id(string))\n", - "string += '!'\n", - "print(string)\n", - "print(id(string)) " - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023201032\n", - "[1, 2, 3]\n", - "1531023201032\n" - ] - } - ], - "source": [ - "list1 = [1,2]\n", - "print(id(list1))\n", - "list1 += [3]\n", - "print(list1)\n", - "print(id(list1))" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n" - ] - } - ], - "source": [ - "class Student:\n", - " pass #skip this part for now\n", - "\n", - "stu_1 = Student()\n", - "stu_1.first = 'Jean'\n", - "stu_1.last = 'Chen'\n", - "stu_1.email = 'Jean.Chen@smu.edu.sg'\n", - "print(stu_1.email) " - ] - }, - { - "cell_type": "code", - "execution_count": 102, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n", - "Zian.Gong@smu.edu.sg\n" - ] - } - ], - "source": [ - "class Student:\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - "\n", - "stu_1 = Student('Jean', 'Chen')\n", - "stu_2 = Student('Zian', 'Gong')\n", - "print(stu_1.email) \n", - "print(stu_2.email) " - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean Chen\n", - "Jean Chen\n" - ] - } - ], - "source": [ - "class Student:\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - " \n", - " def fullname(self):\n", - " return self.first + ' ' + self.last\n", - "\n", - "stu_1 = Student('Jean', 'Chen')\n", - "print(stu_1.fullname())\n", - "print(Student.fullname(stu_1)) " - ] - }, - { - "cell_type": "code", - "execution_count": 103, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "1\n" - ] - } - ], - "source": [ - "class Student:\n", - " num_of_stu = 0\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - " Student.num_of_stu += 1\n", - "\n", - "print(Student.num_of_stu) \n", - "stu_1 = Student('Jean', 'Chen')\n", - "print(Student.num_of_stu) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Inheritance" - ] - }, - { - "cell_type": "code", - "execution_count": 84, - "metadata": {}, - "outputs": [], - "source": [ - "class Student:\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - " \n", - " def fullname(self):\n", - " return self.first + ' ' + self.last" - ] - }, - { - "cell_type": "code", - "execution_count": 85, - "metadata": {}, - "outputs": [], - "source": [ - "class Rep(Student):\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": 86, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n", - "Jean Chen\n" - ] - } - ], - "source": [ - "rep_1 = Rep('Jean', 'Chen') \n", - "print(rep_1.email)\n", - "print(rep_1.fullname())" - ] - }, - { - "cell_type": "code", - "execution_count": 87, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n", - "Jean Chen\n", - "academic\n" - ] - } - ], - "source": [ - "class Rep(Student):\n", - " def __init__(self, first, last, cat):\n", - " super().__init__(first, last)\n", - " self.cat = cat\n", - "\n", - "rep_1 = Rep('Jean', 'Chen', 'academic')\n", - "print(rep_1.email) \n", - "print(rep_1.fullname())\n", - "print(rep_1.cat) " - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'academic representative: Jean Chen'" - ] - }, - "execution_count": 88, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "class Rep(Student):\n", - " def __init__(self, first, last, cat):\n", - " super().__init__(first, last) \n", - " self.cat = cat\n", - "\n", - " def fullname(self):\n", - " return self.cat + ' representative: ' + self.first + ' ' + self.last\n", - " \n", - "rep_1 = Rep('Jean', 'Chen', 'academic')\n", - "rep_1.fullname()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Magic Method" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['__abs__',\n", - " '__add__',\n", - " '__and__',\n", - " '__bool__',\n", - " '__ceil__',\n", - " '__class__',\n", - " '__delattr__',\n", - " '__dir__',\n", - " '__divmod__',\n", - " '__doc__',\n", - " '__eq__',\n", - " '__float__',\n", - " '__floor__',\n", - " '__floordiv__',\n", - " '__format__',\n", - " '__ge__',\n", - " '__getattribute__',\n", - " '__getnewargs__',\n", - " '__gt__',\n", - " '__hash__',\n", - " '__index__',\n", - " '__init__',\n", - " '__init_subclass__',\n", - " '__int__',\n", - " '__invert__',\n", - " '__le__',\n", - " '__lshift__',\n", - " '__lt__',\n", - " '__mod__',\n", - " '__mul__',\n", - " '__ne__',\n", - " '__neg__',\n", - " '__new__',\n", - " '__or__',\n", - " '__pos__',\n", - " '__pow__',\n", - " '__radd__',\n", - " '__rand__',\n", - " '__rdivmod__',\n", - " '__reduce__',\n", - " '__reduce_ex__',\n", - " '__repr__',\n", - " '__rfloordiv__',\n", - " '__rlshift__',\n", - " '__rmod__',\n", - " '__rmul__',\n", - " '__ror__',\n", - " '__round__',\n", - " '__rpow__',\n", - " '__rrshift__',\n", - " '__rshift__',\n", - " '__rsub__',\n", - " '__rtruediv__',\n", - " '__rxor__',\n", - " '__setattr__',\n", - " '__sizeof__',\n", - " '__str__',\n", - " '__sub__',\n", - " '__subclasshook__',\n", - " '__truediv__',\n", - " '__trunc__',\n", - " '__xor__',\n", - " 'bit_length',\n", - " 'conjugate',\n", - " 'denominator',\n", - " 'from_bytes',\n", - " 'imag',\n", - " 'numerator',\n", - " 'real',\n", - " 'to_bytes']" - ] - }, - "execution_count": 81, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dir(int)" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3\n", - "3\n" - ] - } - ], - "source": [ - "num = 1\n", - "print(num + 2)\n", - "print(num.__add__(2))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class iter_example(): \n", - " def __init__(self, data=1): \n", - " self.data = data \n", - "\n", - " def __iter__(self): \n", - " return self \n", - "\n", - " def __next__(self): \n", - " if self.data > 3:\n", - " raise StopIteration \n", - " else:\n", - " self.data += 1 \n", - " return self.data" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2\n", - "3\n", - "4\n" - ] - } - ], - "source": [ - "for i in iter_example():\n", - " print(i)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Final exercises 2.13, 2.14 and 2.15: class inheritance" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.13: Write a parallelogram class that takes length, width and angle between sides as arguments:\n", - "- it has two functions: perimeter and area\n", - "- create an instant paral with length 5, width 6 and angle 60, print out its perimeter and area\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.14: Write a rhombus class that inherits from parallelogram class:\n", - "- create an instant rh with length 5 and angle 60, print out its perimeter and area" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.15: Write a square class that inherits from rhombus class:\n", - "- create an instant sq with length 5, print out its perimeter and area\n", - "- write a new function area that will return \"The area of a square with length xxx is xxx\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your python code here" - ] - } - ], - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/W2_Function_Lambda/.ipynb_checkpoints/class_exercise_2_submit-checkpoint.ipynb b/W2_Function_Lambda/.ipynb_checkpoints/class_exercise_2_submit-checkpoint.ipynb deleted file mode 100644 index 790c3dd..0000000 --- a/W2_Function_Lambda/.ipynb_checkpoints/class_exercise_2_submit-checkpoint.ipynb +++ /dev/null @@ -1,244 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Python programming and Data Analysis\n", - "\n", - "## Class Exercise 2 -- Python Intermediate" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.11: find out all the prime numbers in a given list" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "num_list = [649, 778, 652, 653, 912, 402, 917, 536, 664, 922, 284, 158, 415, 672, 673, 33, 419, 414, 421, 811, 683, 48, 818, 566, 567, 310, 580, 838, 199, 586, 458, 460, 337, 728, 604, 94, 607, 865, 354, 230, 367, 752, 625, 371, 505, 635, 893, 382, 767]" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[649, 653, 917, 415, 673, 33, 419, 421, 811, 683, 567, 199, 337, 607, 865, 367, 625, 371, 505, 635, 893, 767]\n" - ] - } - ], - "source": [ - "import math\n", - "# write your Python code here\n", - "def is_prime(num):\n", - " for i in range(2, math.floor(math.sqrt(num))+1, 2):\n", - " if num%i == 0:\n", - " return False\n", - " return True\n", - "prime_list = [num for num in num_list if is_prime(num)]\n", - "print(prime_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.12: use the prime function you created in exercise 1 and lambda to find out all the prime numbers in a given list in one line" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[649, 653, 917, 415, 673, 33, 419, 421, 811, 683, 567, 199, 337, 607, 865, 367, 625, 371, 505, 635, 893, 767]\n" - ] - } - ], - "source": [ - "# write your Python code here\n", - "\n", - "print(list(filter(lambda num: is_prime(num), num_list)))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.13: Write a parallelogram class that takes length, width and angle between sides as arguments:\n", - "- it has two functions: perimeter and area\n", - "- create an instant paral with length 5, width 6 and angle 60, print out its perimeter and area\n" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "class parallel:\n", - " def __init__(self, length, width, angle):\n", - " self.length = length\n", - " self.width = width\n", - " self.angle = angle\n", - " def perimeter(self):\n", - " return (self.length + self.width)*2\n", - " def area(self):\n", - " return f\"{self.length*self.width*math.sin(math.radians(self.angle)):.2f}\"" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "22\n", - "25.98\n" - ] - } - ], - "source": [ - "paral = parallel(5, 6, 60)\n", - "print(paral.perimeter())\n", - "print(paral.area())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.14: Write a rhombus class that inherits from parallelogram class:\n", - "- create an instant rh with length 5 and angle 60, print out its perimeter and area" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here\n", - "class rhombus(parallel):\n", - " def __init__(self, length, angle):\n", - " self.length = length\n", - " self.angle = angle\n", - " def perimeter(self):\n", - " return 4*self.length\n", - " def area(self):\n", - " return f\"{pow(self.length,2)*math.sin(math.radians(self.angle)):.2f}\"\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "20\n", - "21.65\n" - ] - } - ], - "source": [ - "rh = rhombus(5, 60)\n", - "print(rh.perimeter())\n", - "print(rh.area())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.15: Write a square class that inherits from rhombus class:\n", - "- create an instant sq with length 5, print out its perimeter and area\n", - "- write a new function area that will return \"The area of a square with length xxx is xxx\"" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here\n", - "class square(rhombus):\n", - " def __init__(self, length):\n", - " self.length = length\n", - " def area(self):\n", - " return f\"The area of a square with length {self.length} is {self.length*self.length}\"" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "20\n", - "The area of a square with length 5 is 25\n" - ] - } - ], - "source": [ - "sq = square(5)\n", - "print(sq.perimeter())\n", - "print(sq.area())" - ] - }, - { - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/W2_Function_Lambda/class_exercise_2.ipynb b/W2_Function_Lambda/class_exercise_2.ipynb deleted file mode 100644 index 5efb696..0000000 --- a/W2_Function_Lambda/class_exercise_2.ipynb +++ /dev/null @@ -1,1545 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Python programming and Data Analysis\n", - "\n", - "## Class Exercise 2 -- Python Intermediate" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Before function – Operators " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n", - "False\n", - "True\n" - ] - } - ], - "source": [ - "str1 = 'abc'\n", - "str2 = 'def'\n", - "print('a' in str1)\n", - "print('a' in str2)\n", - "print('a' not in str1)\n", - "print('a' not in str2)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "True\n", - "False\n", - "False\n", - "True\n" - ] - } - ], - "source": [ - "x = 5\n", - "print(type(x) is int)\n", - "print(type(x) is str)\n", - "\n", - "print(type(x) is not int)\n", - "print(type(x) is not str)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Functions" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Define & Call" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n" - ] - } - ], - "source": [ - "def add(a, b):\n", - " c = a + b\n", - " print(c)\n", - "\n", - "add(2, 3)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Arguments" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike is 40 years old.\n" - ] - } - ], - "source": [ - "def info(name, age):\n", - " print(name, 'is', age, 'years old.')\n", - "\n", - "info('Mike', 40) " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "40 is Mike years old.\n" - ] - } - ], - "source": [ - "info(40, 'Mike')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "ename": "TypeError", - "evalue": "info() missing 1 required positional argument: 'age'", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0minfo\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m40\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mTypeError\u001b[0m: info() missing 1 required positional argument: 'age'" - ] - } - ], - "source": [ - "info(40)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike is 40 years old.\n", - "Mike is 40 years old.\n" - ] - } - ], - "source": [ - "def info(name, age):\n", - " print(name, 'is', age, 'years old.')\n", - "\n", - "info(name = 'Mike', age = 40)\n", - "info(age = 40, name = 'Mike') " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike is 40 years old.\n", - "Mike is 35 years old.\n" - ] - } - ], - "source": [ - "def info(name, age = 35):\n", - " print(name, 'is', age, 'years old.')\n", - "\n", - "info('Mike', 40)\n", - "info('Mike')" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike's hobbies: \n", - "Mike's hobbies: hiking, reading\n" - ] - } - ], - "source": [ - "def info(name, *args):\n", - " hobby = []\n", - " for a in args:\n", - " hobby.append(a)\n", - " print(name +\"'s hobbies: \" + ', '.join(hobby))\n", - "\n", - "info('Mike')\n", - "info('Mike', 'hiking', 'reading') " - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Mike's hobbies: first-hiking, second-reading\n" - ] - } - ], - "source": [ - "def info(name, **kwargs):\n", - " hobby = []\n", - " for k, v in kwargs.items():\n", - " hobby.append(k+'-'+v)\n", - " print(name +\"'s hobbies: \" + ', '.join(hobby))\n", - "\n", - "info('Mike', first='hiking', second='reading')" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Python Data Analysis\n", - "Python Data Analysis\n" - ] - } - ], - "source": [ - "def func(a1, a2, a3):\n", - " print(a1,a2,a3)\n", - " \n", - "args = ('Python', 'Data', 'Analysis')\n", - "func(*args)\n", - "\n", - "kwargs = {'a1' : 'Python', 'a2' : 'Data', 'a3' : 'Analysis'}\n", - "func(**kwargs)" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "args: ('I', 'love')\n", - "kwargs: {'first': 'Python programming', 'mid': 'and', 'last': 'Data Analysis'}\n", - "I love Python programming and Data Analysis\n" - ] - } - ], - "source": [ - "def func(*args,**kwargs):\n", - " print('args: ', args)\n", - " print('kwargs: ', kwargs)\n", - " print(' '.join(args), ' '.join(kwargs.values()))\n", - " \n", - "func('I', 'love', first='Python programming', mid='and', last='Data Analysis')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Return" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1\n", - "(1, 3)\n" - ] - } - ], - "source": [ - "def func1(a,b):\n", - " return a\n", - "\n", - "def func2(a,b):\n", - " return a,b\n", - "\n", - "print(func1(1,3))\n", - "print(func2(1,3))" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[1, 3]\n", - "{'a': 1, 'b': 3}\n" - ] - } - ], - "source": [ - "def func3(a,b):\n", - " return [a,b]\n", - "\n", - "def func4(a,b):\n", - " return {'a': a, 'b': b}\n", - "\n", - "print(func3(1,3))\n", - "print(func4(1,3))" - ] - }, - { - "cell_type": "code", - "execution_count": 24, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4\n", - "6\n" - ] - } - ], - "source": [ - "def by_factor(factor):\n", - " def multiply(number):\n", - " return factor * number\n", - " return multiply\n", - "\n", - "double = by_factor(2)\n", - "print(double(2))\n", - "print(double(3))" - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n" - ] - } - ], - "source": [ - "def add(a, b):\n", - " c = a + b\n", - " return c\n", - "\n", - "result = add(2, 3)\n", - "print(result)" - ] - }, - { - "cell_type": "code", - "execution_count": 26, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5\n", - "None\n" - ] - } - ], - "source": [ - "def add2(a, b):\n", - " c = a + b\n", - " print(c)\n", - "\n", - "result2 = add2(2, 3)\n", - "print(result2)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3.7200759760208356e-44\n", - "0.5\n", - "1.0\n" - ] - } - ], - "source": [ - "def logistic(x):\n", - " return 1/(1+math.exp(-x))\n", - "\n", - "print(logistic(-100))\n", - "print(logistic(0))\n", - "print(logistic(100))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Variable Scope" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "local\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'y' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mNameError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[0;32m 4\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 5\u001b[0m \u001b[0mtest\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 6\u001b[1;33m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0my\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mNameError\u001b[0m: name 'y' is not defined" - ] - } - ], - "source": [ - "def test():\n", - " y = 'local'\n", - " print(y)\n", - "\n", - "test()\n", - "print(y) " - ] - }, - { - "cell_type": "code", - "execution_count": 30, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "global\n", - "global\n" - ] - } - ], - "source": [ - "y = 'global'\n", - "def test():\n", - " global y\n", - " print(y)\n", - "\n", - "test()\n", - "print(y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.11: find out all the prime numbers in a given list" - ] - }, - { - "cell_type": "code", - "execution_count": 34, - "metadata": {}, - "outputs": [], - "source": [ - "num_list = [649, 778, 652, 653, 912, 402, 917, 536, 664, 922, 284, 158, 415, 672, 673, 33, 419, 414, 421, 811, 683, 48, 818, 566, 567, 310, 580, 838, 199, 586, 458, 460, 337, 728, 604, 94, 607, 865, 354, 230, 367, 752, 625, 371, 505, 635, 893, 382, 767]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Lambda Expressions" - ] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "3" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "add=lambda x, y: x+y\n", - "add(1, 2) " - ] - }, - { - "cell_type": "code", - "execution_count": 47, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sum = lambda x: 1\n", - "sum([2,3])" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[3, 2, 4, 1, 5]" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "sorted([1, 2, 3, 4, 5], key = lambda x: abs(3 - x))" - ] - }, - { - "cell_type": "code", - "execution_count": 49, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1, 3, 5]" - ] - }, - "execution_count": 49, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "list(filter(lambda n: n % 2 == 1, [1, 2, 3, 4, 5]))" - ] - }, - { - "cell_type": "code", - "execution_count": 50, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[2, 3, 4]" - ] - }, - "execution_count": 50, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "list(map(lambda x: x + 1, [1, 2, 3]))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.12: use the prime function you created in exercise 1 and lambda to find out all the prime numbers in a given list in one line" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Modules" - ] - }, - { - "cell_type": "code", - "execution_count": 62, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3.141592653589793\n", - "3.141592653589793\n", - "3.141592653589793\n" - ] - } - ], - "source": [ - "import math\n", - "print(math.pi)\n", - "\n", - "import math as mt\n", - "print(mt.pi)\n", - "\n", - "from math import pi\n", - "print(pi)\n", - "\n", - "from math import * " - ] - }, - { - "cell_type": "code", - "execution_count": 63, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "7\n", - "0.187558625103874\n", - "3\n", - "b\n" - ] - } - ], - "source": [ - "import random as rnd\n", - "print(rnd.randint(0, 10))\n", - "print(rnd.random())\n", - "lst = list(range(10))\n", - "print(rnd.choice(lst))\n", - "print(random.choice('abc'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Classes" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Class and Instance" - ] - }, - { - "cell_type": "code", - "execution_count": 89, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1469952256\n", - "\n" - ] - } - ], - "source": [ - "a = 2\n", - "print(id(a))\n", - "print(type(a)) " - ] - }, - { - "cell_type": "code", - "execution_count": 90, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1469952256\n", - "\n" - ] - } - ], - "source": [ - "b = 2\n", - "print(id(b))\n", - "print(type(b)) " - ] - }, - { - "cell_type": "code", - "execution_count": 91, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1469952288\n", - "\n" - ] - } - ], - "source": [ - "c = 3\n", - "print(id(c))\n", - "print(type(c)) " - ] - }, - { - "cell_type": "code", - "execution_count": 92, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023259656\n", - "1531023259656\n", - "[1, 2, 3]\n", - "[1, 2, 3]\n", - "1531023259656\n", - "1531023259656\n" - ] - } - ], - "source": [ - "a = [1,2]\n", - "b = a\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "b.append(3)\n", - "print(a)\n", - "print(b)\n", - "print(id(a)) \n", - "print(id(b)) " - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4426390664\n", - "4426391176\n", - "True\n", - "False\n" - ] - } - ], - "source": [ - "a = [1,2]\n", - "b = [1,2]\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "print(a == b)\n", - "print(a is b) " - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4389863968\n", - "4389863968\n", - "True\n", - "True\n" - ] - } - ], - "source": [ - "a = 101\n", - "b = 101\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "print(a == b)\n", - "print(a is b) " - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "4426665552\n", - "4426665104\n", - "True\n", - "False\n" - ] - } - ], - "source": [ - "c = 1001\n", - "d = 1001\n", - "print(id(c)) \n", - "print(id(d)) \n", - "\n", - "print(c == d)\n", - "print(c is d) " - ] - }, - { - "cell_type": "code", - "execution_count": 96, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023200840\n", - "1531023200840\n", - "[[9, 1], 2, 3, 4]\n", - "[[9, 1], 2, 3, 4]\n", - "1531023200840\n", - "1531023200840\n" - ] - } - ], - "source": [ - "a = [[0, 1], 2, 3]\n", - "b = a\n", - "print(id(a))\n", - "print(id(b))\n", - "\n", - "b.append(4)\n", - "b[0][0] = 9\n", - "print(a)\n", - "print(b)\n", - "print(id(a))\n", - "print(id(b))" - ] - }, - { - "cell_type": "code", - "execution_count": 97, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023204040\n", - "1531023260168\n", - "1531023201608\n", - "1531023201608\n", - "[[9, 1], 2, 3]\n", - "[[9, 1], 2, 3, 4]\n" - ] - } - ], - "source": [ - "import copy\n", - "a = [[0, 1], 2, 3]\n", - "b = copy.copy(a)\n", - "print(id(a))\n", - "print(id(b))\n", - "print(id(a[0]))\n", - "print(id(b[0]))\n", - "\n", - "b.append(4)\n", - "b[0][0] = 9\n", - "print(a)\n", - "print(b) " - ] - }, - { - "cell_type": "code", - "execution_count": 98, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023203336\n", - "1531023203784\n", - "1531023200840\n", - "1531022909128\n", - "[[0, 1], 2, 3]\n", - "[[9, 1], 2, 3, 4]\n" - ] - } - ], - "source": [ - "import copy\n", - "a = [[0, 1], 2, 3]\n", - "b = copy.deepcopy(a)\n", - "print(id(a)) \n", - "print(id(b))\n", - "print(id(a[0]))\n", - "print(id(b[0]))\n", - "\n", - "b.append(4)\n", - "b[0][0] = 9\n", - "print(a)\n", - "print(b) " - ] - }, - { - "cell_type": "code", - "execution_count": 99, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023380864\n", - "Hello!\n", - "1531023382824\n" - ] - } - ], - "source": [ - "string = 'Hello'\n", - "print(id(string))\n", - "string += '!'\n", - "print(string)\n", - "print(id(string)) " - ] - }, - { - "cell_type": "code", - "execution_count": 100, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1531023201032\n", - "[1, 2, 3]\n", - "1531023201032\n" - ] - } - ], - "source": [ - "list1 = [1,2]\n", - "print(id(list1))\n", - "list1 += [3]\n", - "print(list1)\n", - "print(id(list1))" - ] - }, - { - "cell_type": "code", - "execution_count": 101, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n" - ] - } - ], - "source": [ - "class Student:\n", - " pass #skip this part for now\n", - "\n", - "stu_1 = Student()\n", - "stu_1.first = 'Jean'\n", - "stu_1.last = 'Chen'\n", - "stu_1.email = 'Jean.Chen@smu.edu.sg'\n", - "print(stu_1.email) " - ] - }, - { - "cell_type": "code", - "execution_count": 102, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n", - "Zian.Gong@smu.edu.sg\n" - ] - } - ], - "source": [ - "class Student:\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - "\n", - "stu_1 = Student('Jean', 'Chen')\n", - "stu_2 = Student('Zian', 'Gong')\n", - "print(stu_1.email) \n", - "print(stu_2.email) " - ] - }, - { - "cell_type": "code", - "execution_count": 104, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean Chen\n", - "Jean Chen\n" - ] - } - ], - "source": [ - "class Student:\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - " \n", - " def fullname(self):\n", - " return self.first + ' ' + self.last\n", - "\n", - "stu_1 = Student('Jean', 'Chen')\n", - "print(stu_1.fullname())\n", - "print(Student.fullname(stu_1)) " - ] - }, - { - "cell_type": "code", - "execution_count": 103, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0\n", - "1\n" - ] - } - ], - "source": [ - "class Student:\n", - " num_of_stu = 0\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - " Student.num_of_stu += 1\n", - "\n", - "print(Student.num_of_stu) \n", - "stu_1 = Student('Jean', 'Chen')\n", - "print(Student.num_of_stu) " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Inheritance" - ] - }, - { - "cell_type": "code", - "execution_count": 84, - "metadata": {}, - "outputs": [], - "source": [ - "class Student:\n", - " def __init__(self, first, last):\n", - " self.first = first\n", - " self.last = last\n", - " self.email = first + '.' + last + '@smu.edu.sg'\n", - " \n", - " def fullname(self):\n", - " return self.first + ' ' + self.last" - ] - }, - { - "cell_type": "code", - "execution_count": 85, - "metadata": {}, - "outputs": [], - "source": [ - "class Rep(Student):\n", - " pass" - ] - }, - { - "cell_type": "code", - "execution_count": 86, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n", - "Jean Chen\n" - ] - } - ], - "source": [ - "rep_1 = Rep('Jean', 'Chen') \n", - "print(rep_1.email)\n", - "print(rep_1.fullname())" - ] - }, - { - "cell_type": "code", - "execution_count": 87, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Jean.Chen@smu.edu.sg\n", - "Jean Chen\n", - "academic\n" - ] - } - ], - "source": [ - "class Rep(Student):\n", - " def __init__(self, first, last, cat):\n", - " super().__init__(first, last)\n", - " self.cat = cat\n", - "\n", - "rep_1 = Rep('Jean', 'Chen', 'academic')\n", - "print(rep_1.email) \n", - "print(rep_1.fullname())\n", - "print(rep_1.cat) " - ] - }, - { - "cell_type": "code", - "execution_count": 88, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'academic representative: Jean Chen'" - ] - }, - "execution_count": 88, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "class Rep(Student):\n", - " def __init__(self, first, last, cat):\n", - " super().__init__(first, last) \n", - " self.cat = cat\n", - "\n", - " def fullname(self):\n", - " return self.cat + ' representative: ' + self.first + ' ' + self.last\n", - " \n", - "rep_1 = Rep('Jean', 'Chen', 'academic')\n", - "rep_1.fullname()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Magic Method" - ] - }, - { - "cell_type": "code", - "execution_count": 81, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['__abs__',\n", - " '__add__',\n", - " '__and__',\n", - " '__bool__',\n", - " '__ceil__',\n", - " '__class__',\n", - " '__delattr__',\n", - " '__dir__',\n", - " '__divmod__',\n", - " '__doc__',\n", - " '__eq__',\n", - " '__float__',\n", - " '__floor__',\n", - " '__floordiv__',\n", - " '__format__',\n", - " '__ge__',\n", - " '__getattribute__',\n", - " '__getnewargs__',\n", - " '__gt__',\n", - " '__hash__',\n", - " '__index__',\n", - " '__init__',\n", - " '__init_subclass__',\n", - " '__int__',\n", - " '__invert__',\n", - " '__le__',\n", - " '__lshift__',\n", - " '__lt__',\n", - " '__mod__',\n", - " '__mul__',\n", - " '__ne__',\n", - " '__neg__',\n", - " '__new__',\n", - " '__or__',\n", - " '__pos__',\n", - " '__pow__',\n", - " '__radd__',\n", - " '__rand__',\n", - " '__rdivmod__',\n", - " '__reduce__',\n", - " '__reduce_ex__',\n", - " '__repr__',\n", - " '__rfloordiv__',\n", - " '__rlshift__',\n", - " '__rmod__',\n", - " '__rmul__',\n", - " '__ror__',\n", - " '__round__',\n", - " '__rpow__',\n", - " '__rrshift__',\n", - " '__rshift__',\n", - " '__rsub__',\n", - " '__rtruediv__',\n", - " '__rxor__',\n", - " '__setattr__',\n", - " '__sizeof__',\n", - " '__str__',\n", - " '__sub__',\n", - " '__subclasshook__',\n", - " '__truediv__',\n", - " '__trunc__',\n", - " '__xor__',\n", - " 'bit_length',\n", - " 'conjugate',\n", - " 'denominator',\n", - " 'from_bytes',\n", - " 'imag',\n", - " 'numerator',\n", - " 'real',\n", - " 'to_bytes']" - ] - }, - "execution_count": 81, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "dir(int)" - ] - }, - { - "cell_type": "code", - "execution_count": 83, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "3\n", - "3\n" - ] - } - ], - "source": [ - "num = 1\n", - "print(num + 2)\n", - "print(num.__add__(2))" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "class iter_example(): \n", - " def __init__(self, data=1): \n", - " self.data = data \n", - "\n", - " def __iter__(self): \n", - " return self \n", - "\n", - " def __next__(self): \n", - " if self.data > 3:\n", - " raise StopIteration \n", - " else:\n", - " self.data += 1 \n", - " return self.data" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2\n", - "3\n", - "4\n" - ] - } - ], - "source": [ - "for i in iter_example():\n", - " print(i)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Id 1: Quan Nguyen\n" - ] - } - ], - "source": [ - "class Human:\n", - " def __init__(self, id, name, addresses=[], maps={}):\n", - " self.id = id\n", - " self.name = name\n", - " self.addresses = addresses\n", - " self.maps = maps\n", - " \n", - " def __str__(self):\n", - " return f'Id {self.id}: {self.name}'\n", - "human = Human(1, 'Quan Nguyen', ['Address1', 'Address1'], {'London':2, 'UK':3})\n", - "print(human)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Final exercises 2.13, 2.14 and 2.15: class inheritance" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.13: Write a parallelogram class that takes length, width and angle between sides as arguments:\n", - "- it has two functions: perimeter and area\n", - "- create an instant paral with length 5, width 6 and angle 60, print out its perimeter and area\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.14: Write a rhombus class that inherits from parallelogram class:\n", - "- create an instant rh with length 5 and angle 60, print out its perimeter and area" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your python code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.15: Write a square class that inherits from rhombus class:\n", - "- create an instant sq with length 5, print out its perimeter and area\n", - "- write a new function area that will return \"The area of a square with length xxx is xxx\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Write your python code here" - ] - } - ], - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/W2_Function_Lambda/class_exercise_2_submit.ipynb b/W2_Function_Lambda/class_exercise_2_submit.ipynb deleted file mode 100644 index 790c3dd..0000000 --- a/W2_Function_Lambda/class_exercise_2_submit.ipynb +++ /dev/null @@ -1,244 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Python programming and Data Analysis\n", - "\n", - "## Class Exercise 2 -- Python Intermediate" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.11: find out all the prime numbers in a given list" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "num_list = [649, 778, 652, 653, 912, 402, 917, 536, 664, 922, 284, 158, 415, 672, 673, 33, 419, 414, 421, 811, 683, 48, 818, 566, 567, 310, 580, 838, 199, 586, 458, 460, 337, 728, 604, 94, 607, 865, 354, 230, 367, 752, 625, 371, 505, 635, 893, 382, 767]" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[649, 653, 917, 415, 673, 33, 419, 421, 811, 683, 567, 199, 337, 607, 865, 367, 625, 371, 505, 635, 893, 767]\n" - ] - } - ], - "source": [ - "import math\n", - "# write your Python code here\n", - "def is_prime(num):\n", - " for i in range(2, math.floor(math.sqrt(num))+1, 2):\n", - " if num%i == 0:\n", - " return False\n", - " return True\n", - "prime_list = [num for num in num_list if is_prime(num)]\n", - "print(prime_list)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.12: use the prime function you created in exercise 1 and lambda to find out all the prime numbers in a given list in one line" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[649, 653, 917, 415, 673, 33, 419, 421, 811, 683, 567, 199, 337, 607, 865, 367, 625, 371, 505, 635, 893, 767]\n" - ] - } - ], - "source": [ - "# write your Python code here\n", - "\n", - "print(list(filter(lambda num: is_prime(num), num_list)))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.13: Write a parallelogram class that takes length, width and angle between sides as arguments:\n", - "- it has two functions: perimeter and area\n", - "- create an instant paral with length 5, width 6 and angle 60, print out its perimeter and area\n" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "class parallel:\n", - " def __init__(self, length, width, angle):\n", - " self.length = length\n", - " self.width = width\n", - " self.angle = angle\n", - " def perimeter(self):\n", - " return (self.length + self.width)*2\n", - " def area(self):\n", - " return f\"{self.length*self.width*math.sin(math.radians(self.angle)):.2f}\"" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "22\n", - "25.98\n" - ] - } - ], - "source": [ - "paral = parallel(5, 6, 60)\n", - "print(paral.perimeter())\n", - "print(paral.area())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.14: Write a rhombus class that inherits from parallelogram class:\n", - "- create an instant rh with length 5 and angle 60, print out its perimeter and area" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here\n", - "class rhombus(parallel):\n", - " def __init__(self, length, angle):\n", - " self.length = length\n", - " self.angle = angle\n", - " def perimeter(self):\n", - " return 4*self.length\n", - " def area(self):\n", - " return f\"{pow(self.length,2)*math.sin(math.radians(self.angle)):.2f}\"\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "20\n", - "21.65\n" - ] - } - ], - "source": [ - "rh = rhombus(5, 60)\n", - "print(rh.perimeter())\n", - "print(rh.area())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 2.15: Write a square class that inherits from rhombus class:\n", - "- create an instant sq with length 5, print out its perimeter and area\n", - "- write a new function area that will return \"The area of a square with length xxx is xxx\"" - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "metadata": {}, - "outputs": [], - "source": [ - "# write your Python code here\n", - "class square(rhombus):\n", - " def __init__(self, length):\n", - " self.length = length\n", - " def area(self):\n", - " return f\"The area of a square with length {self.length} is {self.length*self.length}\"" - ] - }, - { - "cell_type": "code", - "execution_count": 18, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "20\n", - "The area of a square with length 5 is 25\n" - ] - } - ], - "source": [ - "sq = square(5)\n", - "print(sq.perimeter())\n", - "print(sq.area())" - ] - }, - { - "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.8.8" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/W2_Function_Lambda/tutorial_2.ipynb b/W2_Function_Lambda/tutorial_2.ipynb deleted file mode 100644 index 2ebc27f..0000000 --- a/W2_Function_Lambda/tutorial_2.ipynb +++ /dev/null @@ -1,730 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 2.21: Elevator -- return correct floor" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code below defines an *Elevator* class. In this class,
\n", - "* The elevator is associated with a current floor where it stands by.\n", - "* All floors are numbered by continuous integers except that *floor -1* is one level below *floor 1*.\n", - "* The first floor aboveground is *floor 1*, and the first floor undergound is *floor -1* if there is any underground floor.\n", - "* There is a pair of integers representing the top floor and the bottom floor the elevator can go to.\n", - "* The elevator only stops at floors numbered with an odd integer.\n", - "\n", - "Fill in the blanks to simulate the movement of the elevator between the requested floors." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class Elevator:\n", - " def __init__(self, bottom, top, current):\n", - " '''Initialize the Elevator instance.\n", - " If the current floor is not an odd number,\n", - " the current floor will be one level below the desired floor.'''\n", - "\n", - " def up(self):\n", - " '''Make the elevator go up to the next possible floor.'''\n", - "\n", - " def down(self):\n", - " '''Make the elevator go down to the next possible floor.'''\n", - "\n", - " def go_to(self, floor):\n", - " '''Make the elevator go to the specific floor.\n", - " If the number of specific floor is not an odd number, \n", - " the specific floor will be one level below the desired floor.'''\n", - "\n", - " def __str__(self):\n", - " return \"Current floor: \" + str(self.current)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "elevator = Elevator(-1, 11, 2)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To test whether your *Elevator* class is working correctly, run the code blocks below." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "elevator.up()\n", - "elevator.current #should output 3" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "elevator.down() \n", - "elevator.current #should output 1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "elevator.go_to(9) \n", - "elevator.current #should output 9" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Go to the top floor. Try to go up, it should stay. Then go down.\n", - "elevator.go_to(11)\n", - "elevator.up()\n", - "elevator.down()\n", - "print(elevator.current) # should be 9" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Try to go up, then go down.\n", - "elevator.go_to(10)\n", - "elevator.up()\n", - "elevator.down()\n", - "print(elevator.current) # should be 9, why?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Go to the bottom floor. Try to go down, it should stay. Then go up.\n", - "elevator.go_to(-1)\n", - "print(elevator.current) # should be -1\n", - "elevator.down()\n", - "elevator.down()\n", - "elevator.up()\n", - "elevator.up()\n", - "print(elevator.current) # should be 3" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now add the __str__ method to your *Elevator* class definition above so that when printing the elevator using the **print( )** method, we get the current floor together with a message. For example, in the 5th floor it should say \"Current floor: 5\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "elevator.go_to(5)\n", - "print(elevator)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 2.22: Netflix" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code below defines a *Netflix* class. A Netflix object stores its title and the year it was first published." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Write your class here\n", - "class Netflix:\n", - " def __init__(self, title, year):\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Test your code here\n", - "netflix = Netflix('The call', 2020)\n", - "print(netflix)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What if we want to search movie by actor/actress's name and year?\n", - "* We would like to define a more structured class
\n", - "\n", - "The code below defines a *StructuredNetflix* class.
\n", - "This class stores the movie's title, cast, length and year.
\n", - "Add the method __display__ to show all the information stored." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Write your class here\n", - "class StructuredNetflix:\n", - " def __init__(self, title, cast, length, year):\n", - "\n", - "\n", - " def display(self):\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Test your code here\n", - "netflix = StructuredNetflix('The call', ['Park Shine-hye', 'Jun Jong-seo', 'Kim Sung-ryoung'], '1h 52m', 2020)\n", - "netflix.display()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Expected output:
\n", - "Title: The call
\n", - "Year: 2020
\n", - "Cast: Park Shine-hye, Jun Jong-seo, Kim Sung-ryoung
\n", - "Movie length: 1h 52m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now, if we have a list of StructuredNetflix objects and we want to find all of the ones that Park Shine-hye acted and shows in 2020 except the movie we just watched ('The call')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "netList = [StructuredNetflix('The call', ['Park Shine-hye', 'Jun Jong-seo', 'Kim Sung-ryoung'], '1h 52m', 2020),\n", - " StructuredNetflix('Alive', ['Yoo Ah-in', 'Park Shine-hye'], '1h 38m', 2020),\n", - " StructuredNetflix('Miss Americana', ['Taloy Swift'], '1h 25m', 2020)]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Write your code here" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Expected output:
\n", - "Title: Alive
\n", - "Year: 2020
\n", - "Cast: Yoo Ah-in, Park Shine-hye
\n", - "Movie length: 1h 38m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "But now we have another problem. Our StructuredAddress works fine for movies, but not for TV series. We could improve the **display()** method to handle lengths for movies and seasons for TV series. Let's think about the details:\n", - "\n", - "- Create a *BaseNetflix* class instead to store common attributes (title, cast and year).\n", - "- *BaseNetflix* class has the method __display__ to show the information stored.\n", - "- Create a child class *Movie* that has one more attribute length.\n", - "- When call the method __display__ with movies, it should show the movie's title, cast, year and length.\n", - "- Create a child class *TVseries* that has attributes title, cast, year and season.\n", - "- When call the method __display__ with TV series, it should show title, cast, year and season.\n", - "- Add method __update_season__ for class *TVseries*, this method will update the no. of season. Check the sample output for tv.update_season()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Write your code here\n", - "class BaseNetflix:\n", - " def __init__(self, title, cast, year):\n", - "\n", - " \n", - " def display(self):\n", - "\n", - "\n", - "class Movie(BaseNetflix):\n", - " def __init__(self, title, cast, year, length):\n", - "\n", - "\n", - " def display(self):\n", - "\n", - "\n", - "class TVseries(BaseNetflix):\n", - " def __init__(self, title, cast, year, season):\n", - "\n", - "\n", - " def display(self):\n", - "\n", - "\n", - " def update_season(self):\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Test your code here\n", - "movie = Movie('The call', ['Park Shine-hye', 'Jun Jong-seo', 'Kim Sung-ryoung'], 2020, '1h 52m')\n", - "movie.display()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Expected output:
\n", - "Title: The call
\n", - "Year: 2020
\n", - "Cast: Park Shine-hye, Jun Jong-seo, Kim Sung-ryoung
\n", - "Movie length: 1h 52m" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "#Test your code here\n", - "tv = TVseries('The crown', ['Olivia Colman', 'Tobias Menzies'], 2020, 4)\n", - "tv.display()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Expected output:
\n", - "Title: The crown
\n", - "Year: 2020
\n", - "Cast: Olivia Colman, Tobias Menzies
\n", - "Seasons: 4" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tv.update_season()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Expected output:
\n", - "Title: The crown
\n", - "Year: 2020
\n", - "Cast: Olivia Colman, Tobias Menzies
\n", - "Seasons: 4
\n", - "After update
\n", - "Title: The crown
\n", - "Year: 2020
\n", - "Cast: Olivia Colman, Tobias Menzies
\n", - "Seasons: 5" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 2.23: Teaching load" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Let us first define a *Course* class.\n", - "Each course is associated with a course complexity, which is a random number between 10 and 15." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import random\n", - "\n", - "class Course:\n", - " def __init__(self, course_id):\n", - " '''Create a new instance of course.'''\n", - " self.course_id = course_id # attribute: course_id\n", - " self.complexity = 10 + random.random() * 5\n", - "\n", - " def __str__(self):\n", - " return 'The complexity of course {:s} is {:.2f}'.format(self.course_id, self.complexity)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "all_courses = {'cs6' + '%02d' % (i+1): Course('cs6' + '%02d' % (i+1)) for i in range(30)}" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for c in all_courses.values():\n", - " print(c)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code below defines a *Professor* class.\n", - "* Each instance of this class is associated to a professor.\n", - "* The instance records the active courses that the professor is currently teaching.\n", - "* A professor can teach multiple sections of the same course.\n", - "* The workload of a professor is the sum of the complexity of all sections she is currently teaching across all different courses." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class Professor:\n", - " def __init__(self):\n", - " '''Create a new instance, with no active courses.'''\n", - "\n", - " def add_section(self, course):\n", - " '''Add a new course to this professor.'''\n", - "\n", - " def deactive_course(self, course):\n", - " '''Remove all teaching sections of the same course from this professor'''\n", - "\n", - " def load(self):\n", - " '''Calculate the current load for all courses.'''\n", - "\n", - " def __str__(self):\n", - " '''Return a string with the current load of the professor'''\n", - " \n", - " def __lt__(self, other):\n", - " return self.load() < other.load()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "prof = Professor()\n", - "prof.add_section(all_courses['cs604'])\n", - "\n", - "print(prof.load())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "prof.deactive_course(all_courses['cs604'])\n", - "print(prof.load()) # should be 0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We now have a basic implementation of the *Professor* class. What if we wish to balance the load between all professors? Let's use the strategy below:\n", - "1. If there is a new section of a course, assign the new section to the professor has the lowest load
\n", - "2. If adding the new section makes the average load more than 50, hire a new professor.
\n", - "How would you define a new *LoadBalancing* class?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class LoadBalancing:\n", - " def __init__(self, courses = {}):\n", - " '''Initialize with one professor'''\n", - "\n", - " def add_course(self, course_id):\n", - " '''Add a new course into available courses'''\n", - "\n", - " def add_section(self, course_id):\n", - " '''Select a professor with the lowest load and add a section of that course to him/ her.\n", - " If it's a new course, add the course first'''\n", - "\n", - " def deactive_course(self, course_id):\n", - " '''Deactive the course from all teaching professors.'''\n", - "\n", - " def avg_load(self):\n", - " '''Calculate the average load of all professors'''\n", - "\n", - " def ensure_availability(self):\n", - " '''If the average load is higher than 50, hire a new professor'''\n", - "\n", - " def __str__(self):\n", - " '''Return a string with the load for each professor.'''" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "load = LoadBalancing(all_courses)\n", - "load.add_section('cs604')\n", - "print(load.avg_load())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "What if we hire a new professor?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "load.profs.append(Professor())\n", - "print(load.avg_load())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now what about deactivating the course?" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "load.deactive_course('cs604')\n", - "print(load.avg_load()) # should return 0.0" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We hired a new professor manually. But we want this to happen automatically when the average load is more than 50%. To make this possible, we add a method **ensure_availability** and call it from the method **add_course** after a new course has been added. You can test it with the following code:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "load = LoadBalancing()\n", - "for c in random.choices(list(all_courses.keys()), k = 50):\n", - " load.add_section(c)\n", - " print(load)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The code above adds 50 new sections and then prints the loads for each professor. Run the following code to verify that the average load is not more than 50." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(load.avg_load())" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "How would you change your code to make sure no professor has load more than 50?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Question 2.24: Sudoku checker (II) -- return cells which you are certain about its value" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "| | | | | | | | | |\n", - "|---|---|---|---|---|---|---|---|---|\n", - "| | |7| | | |1| | |\n", - "| |5|9| | | |2|3| |\n", - "|8|2|3| | | |4|5|6|\n", - "|5|1| | | | | |7|8|\n", - "|9| | |1| |3| | |4|\n", - "| | |4|2| |8|9| | |\n", - "| |7|5|3| |6|8|9| |\n", - "| |8|6| | | |7|1| |\n", - "| |9| | | | | |4| |" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "config1 = [' 7 1 ', ' 59 23 ', '823 456', '51 78', '9 1 3 4', ' 42 89 ', ' 753 689 ', ' 86 71 ', ' 9 4 ']\n", - "config2 = [' ', ' 528 614 ', ' 98 27 ', ' 12 39 ', '735 682', ' 695 741 ', ' 1 3 8 9 ', '42 7 1 65', ' ']\n", - "config3 = [' 76 3 ', ' 13 8 92', ' 4 2 31 ', ' 86 5 9', '26 78', '4 9 82 ', ' 17 5 2 ', '95 3 41 ', ' 2 96 ']" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "class SudokuChecker:\n", - " def __init__(self, config):\n", - " \n", - " def process(self):\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sudoku1 = SudokuChecker(config1)\n", - "sudoku1.process()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sudoku2 = SudokuChecker(config2)\n", - "sudoku2.process()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sudoku3 = SudokuChecker(config3)\n", - "sudoku3.process()" - ] - } - ], - "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.6.9" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/advanced/README.md b/advanced/README.md new file mode 100644 index 0000000..f1de9cb --- /dev/null +++ b/advanced/README.md @@ -0,0 +1,76 @@ +# Advanced Python + +## Topics +- [Type Hints](./type_hints.md) + +## Class + +### Encapsulation + +**Encapsulation** describes the idea of wrapping data and the methods that work on data within one unit. This puts restrictions on accessing variables and methods directly and can prevent the accidental modification of data + +- The goal of information hiding is to ensure that an object’s state is always valid by controlling access to attributes that are hidden from the outside world. + +#### Access Modifiers + +**Access modifiers**: Python doesn't have any mechanism that effectively restricts access to any instance variable or method. Python prescribes a convention of prefixing the name of the variable/method with a single (`_`) or double underscore (`__`) to emulate the behavior of protected and private access specifiers. + +1. **Public** +2. **Protected**: to add a prefix `_` (single underscore) to it + - Protected members of a class are accessible from within the class and are also available to its sub-classes. No other environment is permitted access to it. + - Although the protected variable can be accessed out of the class as well as in the derived class (modified too in derived class), it is customary(convention not a rule) to not access the protected out the class body. +3. **Private**: + - The double underscore `__` prefixed to a variable makes it private. It gives a strong suggestion not to touch it from outside the class. Any attempt to do so will result in an `AttributeError` + - **Name mangling**: Every member with a double underscore will be changed to `_object.___`. So, it can still be accessed from outside the class, but the practice should be refrained. + +## Data Modeling & Validation +- Common Package: Attrs, Pydantic, or Python Data Classes + - `Pydantic` is a Python library for data modeling/parsing that has efficient error handling and a custom validation mechanism. +### Python Data Classes + +Dataclasses, as the name clearly suggests, are classes that are meant to hold data. The motivation behind this module is that we sometimes define classes that only act as data containers and when we do that, we spend a consequent amount of time writing boilerplate code with tons of arguments, an ugly `__init__` method and many overridden functions. + +- Type annotation for each attribute. Although this doesn’t enforce type validation, it helps your text editor provide better linting +- dataclass decorator is actually a code generator that automatically adds other methods under the hood: `__init__` , `__eq__` and `__repr__` methods: these methods are responsible for setting the attribute values, testing for equality and representing objects in a nice string format. + +```Python +class Person(): + def __init__(self, first_name, last_name, age, job): + self.first_name = first_name + self.last_name = last_name + self.age = age + self.job = job + +# dataclass help to remove ugly __init__ method +from dataclasses import dataclass +@dataclass +class Person: + first_name: str + last_name: str + age: int + job: str +``` + +## Test-driven development + +- The basic idea is that we write tests even before we write code. The tests define what it means to say that our program works “correctly.” +- Test templates: + - The first test in every exercise checks whether the expected program exists. + - The second test checks that the program will print a help message if we ask for help. + - After that, your program will be run with various inputs and options. + +## Virtual Environment +### Virtual Env Creation & Activation + +- Step 1: `python3 -m venv venv` for initialising the virtual environment +- Step 2: Activating the virtual environment + - Linux or MacOS `source venv/bin/activate` + - Window `venv/venv\Scripts\activate.bat` + +### Dependency Installation + +The following commands shall be ran **after activating the virtual environment**. + +- `pip install --upgrade pip` for upgrading the pip +- `pip install -r requirements.txt` for the functional dependencies +- `pip install -r requirements-dev.txt` for the development dependencies. (should include `pre-commit` module) diff --git a/advanced/class_0_basics_tutorial.py b/advanced/class_0_basics_tutorial.py new file mode 100644 index 0000000..3ad95a9 --- /dev/null +++ b/advanced/class_0_basics_tutorial.py @@ -0,0 +1,3 @@ +""" +- Class/Static Variable in Python: https://www.geeksforgeeks.org/g-fact-34-class-or-static-variables-in-python/?ref=lbp +""" diff --git a/advanced/class_1_inheritance_polymorphism_tutorial.py b/advanced/class_1_inheritance_polymorphism_tutorial.py new file mode 100644 index 0000000..338d33b --- /dev/null +++ b/advanced/class_1_inheritance_polymorphism_tutorial.py @@ -0,0 +1,3 @@ +""" +https://www.geeksforgeeks.org/polymorphism-in-python/ +""" diff --git a/advanced/class_2_encapsulation_tutorial.py b/advanced/class_2_encapsulation_tutorial.py new file mode 100644 index 0000000..027a3ba --- /dev/null +++ b/advanced/class_2_encapsulation_tutorial.py @@ -0,0 +1,47 @@ +""" +Encapsulation: hiding the change + +Access modifiers +1. Public +2. Protected: '_' +3. Private +""" + + +# --- Public --- +class Person: + def __init__(self, id): + self._id = id + + +class Student(Person): + """Student is a derived class from person""" + + school_name = "NTU" # public class attribute + + def __init__(self, name, id, class_no, age): + super(Student, self).__init__(id) + self.name = name + self._class_no = class_no + self.__age = age # protected instance attribute + + def __private_method(self): + print("This is private method") + + def __str__(self): + return f"Student {self.name}, ID: {self._id}, Age: {self.__age} y.o, is at class {self._class_no}" + + +if __name__ == "__main__": + s1 = Student("Bob", "GM18999M", "10A1", "16") + print(s1) + # print(dir(s1)) + # print(help(s1)) + + # protected member can be accessed but should not be done due to convention + print(s1._class_no) + # private attribute/method still can access outside the class + # via _object.___ + print(s1._Student__age) + s1._Student__private_method() + print(s1.__age) diff --git a/advanced/class_3_inheritance_composition.py b/advanced/class_3_inheritance_composition.py new file mode 100644 index 0000000..90c6a3b --- /dev/null +++ b/advanced/class_3_inheritance_composition.py @@ -0,0 +1,3 @@ +""" +https://realpython.com/inheritance-composition-python/ +""" diff --git a/advanced/class_41_property_decorator_tutorial.md b/advanced/class_41_property_decorator_tutorial.md new file mode 100644 index 0000000..0897560 --- /dev/null +++ b/advanced/class_41_property_decorator_tutorial.md @@ -0,0 +1,39 @@ +# `property()` Add Managed Attributes to Your Classes +- **Data Validation**: One of the most common use cases of `property()` is building managed attributes that validate the input data before storing or even accepting it as a secure input. +```Python + # point.py + +class Point: + def __init__(self, x): + self.x = x + @property + def x(self): + return self._x + + @x.setter + def x(self, value): + try: + self._x = float(value) + print("Validated!") + except ValueError: + raise ValueError('"x" must be a number') from None + +pt = Point("none", 2) # -> ValueError: "x" must be a number +pt = Point(12) +# Validated! +pt.x = 4 +# Validated! +point.x = "one" # -> ValueError: "x" must be a number + +``` +- **Providing Computed Attributes** +```Python +class Rectangle: + def __init__(self, width, height): + self.width = width + self.height = height + + @property + def area(self): + return self.width * self.height +``` diff --git a/advanced/class_4_decorator_tutorial.py b/advanced/class_4_decorator_tutorial.py new file mode 100644 index 0000000..9775e7c --- /dev/null +++ b/advanced/class_4_decorator_tutorial.py @@ -0,0 +1,5 @@ +""" +@property decorator: https://www.tutorialsteacher.com/python/property-decorator +@classmethod +@staticmethod +""" diff --git a/advanced/dataclass_tutorial.py b/advanced/dataclass_tutorial.py new file mode 100644 index 0000000..44d256d --- /dev/null +++ b/advanced/dataclass_tutorial.py @@ -0,0 +1,144 @@ +# dataclass +from dataclasses import asdict, dataclass, field +from datetime import date +from typing import List + +# frozen=True create objects that are read-only, +# prevent anyone from modifying the values of +# @dataclass(frozen=True) +# class Person: +# first_name: str +# last_name: str +# age: int +# job: str + + +@dataclass +class Person: + """Data Class with default value""" + + first_name: str = "Code" + last_name: str = "Xplore" + age: int = 30 + job: str = "Data Scientist" + # field(init=False): create attribute that is only defined internally, + # not when the class is instantiated. + # If we try to access it, an AttributeError is thrown. + full_name: str = field(init=False, repr=False) + + def __post_init__(self): + """__post_init__ to perform initialization of attributes that depend on others""" + self.full_name = self.first_name + " " + self.last_name + + def __repr__(self): + return f"{self.first_name} {self.last_name}: {self.age}" + + def __eq__(self, other): + if isinstance(other, self.__class__): + return self.age == other.age + return NotImplemented + + def __lt__(self, other): + if isinstance(other, self.__class__): + return self.age < other.age + return NotImplemented + + +@dataclass +class Product: + name: str = field(compare=True) # use for comparison Product's instance + category: str = field(compare=True) + shipping_weight: float = field(compare=False) + unit_price: int = field(compare=False) + tax_percent: float = field(compare=False) + + def __post_init__(self) -> None: + if self.unit_price < 0: + raise ValueError("unit_price attribute must greater then zero.") + + if self.shipping_weight < 0: + raise ValueError("shipping_weight attribute must greater then zero.") + + if not 0 < self.tax_percent < 1: + raise ValueError("tax_percent attribute must be between zero and one.") + + +@dataclass +class Order: + creation_date: date = date.today() + products: List[Product] = field(default_factory=list) # default value is a List + + def add_product(self, product: Product) -> None: + self.products.append(product) + + @property + def sub_total(self) -> int: + return sum((p.unit_price for p in self.products)) + + @property + def tax(self) -> float: + return sum( + (product.unit_price * product.tax_percent for product in self.products) + ) + + @property + def total_price(self) -> float: + return self.sub_total + self.tax + + @property + def total_shipping_weight(self) -> float: + return sum((product.shipping_weight for product in self.products)) + + +def test_product_order_dataclasses() -> None: + banana = Product( + name="banana", + category="fruit", + shipping_weight=0.5, + unit_price=215, + tax_percent=0.07, + ) + + mango = Product( + name="mango", + category="fruit", + shipping_weight=2, + unit_price=319, + tax_percent=0.11, + ) + mango_large = Product( + name="mango", + category="fruit", + shipping_weight=10, + unit_price=319, + tax_percent=0.11, + ) + + expensive_mango = Product( + name="Mango", + category="Fruit", + shipping_weight=4.0, + unit_price=800, + tax_percent=0.20, + ) + + order = Order() + for product in [banana, mango, mango_large, expensive_mango]: + order.add_product(product) + + print(f"Comparison between mango and expensive mango: {mango == expensive_mango}") + print(f"Comparison between mango and mango large: {mango == mango_large}") + print(f"Total order price: ${order.total_price/100:.2f}") + print(f"Subtotal order price: ${order.sub_total/100:.2f}") + print(f"Value paid in taxes: ${order.tax/100:.2f}") + print(f"Total weight order: {order.total_shipping_weight} kg") + + +if __name__ == "__main__": + student = Person("Quan", "Nguyen", 28, "student") + doctor = Person("WY", "Peh", 30) + print(student) + # print(student < 5) + print(asdict(student)) # convert to dictionary + + test_product_order_dataclasses() diff --git a/advanced/decorators_tutorial.ipynb b/advanced/decorators_tutorial.ipynb new file mode 100644 index 0000000..3073998 --- /dev/null +++ b/advanced/decorators_tutorial.ipynb @@ -0,0 +1,537 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Python Decorators Tutorials" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. What is Python Wrappers\n", + "- Python wrappers are functions that are added to another function which then can add additional functionality or modifies its behavior without directly changing its source code. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Example 1: Without `functools.wraps()`\n", + " - We can observe that both the `first_function` and `second_function` after applying the `a_decorator` have the same `__name__` and `__doc__` string which is `name='wrapper', doc='A wrapper function'`\n", + "- Ideally, it should show the name and docstring of wrapped function (`func`) instead of wrapping function `wrapper`." + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First Function : name='wrapper', doc='A wrapper function'\n", + "Second Function: name='wrapper', doc='A wrapper function'\n" + ] + } + ], + "source": [ + "def a_decorator(func):\n", + " def wrapper(*args, **kwargs):\n", + " \"\"\"A wrapper function\"\"\"\n", + " # Extend some capabilities of func\n", + " func()\n", + " return wrapper\n", + " \n", + "@a_decorator\n", + "def first_function():\n", + " \"\"\"This is docstring for first function\"\"\"\n", + " print(\"first function\")\n", + " \n", + "@a_decorator\n", + "def second_function(a):\n", + " \"\"\"This is docstring for second function\"\"\"\n", + " print(\"second function\")\n", + " \n", + "print(f\"First Function : name='{first_function.__name__}', doc='{first_function.__doc__}'\")\n", + "print(f\"Second Function: name='{second_function.__name__}', doc='{second_function.__doc__}'\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- `functools.wraps()` as decorator to wrapper function\n", + " - Now, the function names and docstrings of wrapped function have been display correctly" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "First Function : name='first_function', doc='This is docstring for first function'\n", + "Second Function: name='second_function', doc='This is docstring for second function'\n" + ] + } + ], + "source": [ + "import functools\n", + "def a_decorator(func):\n", + " @functools.wraps(func)\n", + " def wrapper(*args, **kwargs):\n", + " \"\"\"A wrapper function\"\"\"\n", + " func()\n", + " return wrapper\n", + " \n", + "@a_decorator\n", + "def first_function():\n", + " \"\"\"This is docstring for first function\"\"\"\n", + " print(\"first function\")\n", + " \n", + "@a_decorator\n", + "def second_function(a):\n", + " \"\"\"This is docstring for second function\"\"\"\n", + " print(\"second function\")\n", + " \n", + "print(f\"First Function : name='{first_function.__name__}', doc='{first_function.__doc__}'\")\n", + "print(f\"Second Function: name='{second_function.__name__}', doc='{second_function.__doc__}'\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. Examples of Wrapper Function" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.1 Timer\n", + "- To create the **decorator** in Python, we need to define a function called `timer` that takes a parameter called `func` = *a decorator function*. \n", + "- Inside the `timer` function, we define another function called `wrapper` that takes the **arguments** typically *passed to the function we want to decorate*.\n", + "- Within the `wrapper` function, we invoke the desired function using the provided arguments. \n", + " - We can do this with the line: `result = func(*args, **kwargs)`.\n", + " - Finally, the `wrapper` function returns the **result of the decorated function’s execution**. \n", + "- To utilize the decorator, you can apply it to the desired function using the @ symbol." + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "import functools\n", + "import time\n", + "\n", + "# Timeit decorators\n", + "def timer(func):\n", + " @functools.wraps(func)\n", + " def wrapper(*args, **kwargs):\n", + " \"\"\"This is timeit's wrapper func\"\"\"\n", + " start = time.perf_counter()\n", + " # call the decorated function\n", + " result = func(*args, **kwargs)\n", + " end = time.perf_counter()\n", + " print(f\"Function '{func.__name__}' took {end - start:.6f} seconds to complete\")\n", + " return result\n", + "\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "10000\n", + "Function 'train_model' took 2.001211 seconds to complete\n" + ] + } + ], + "source": [ + "@timer\n", + "def train_model(a, b):\n", + " # simulate a function execution by pausing the program for 2 seconds\n", + " time.sleep(2) \n", + " print(a*b)\n", + "\n", + "\n", + "train_model(1000, b=10) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.2. Debugger\n", + "- An additional useful wrapper function can be created to facilitate debugging by printing the inputs and outputs of each function. \n", + "- This approach allows us to gain insight into the execution flow of various functions without cluttering our applications with multiple print statements." + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "def debug(func):\n", + " @functools.wraps(func)\n", + " def wrapper(*args, **kwargs):\n", + " # print the fucntion name and arguments\n", + " print(f\"Calling '{func.__name__}' with args: {args} kwargs: {kwargs}\")\n", + " # call the function\n", + " result = func(*args, **kwargs)\n", + " # print the results\n", + " print(f\"'{func.__name__}' returned: {result}\")\n", + " return result\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Calling 'add_numbers' with args: (7,) kwargs: {'y': 5}\n", + "'add_numbers' returned: 12\n" + ] + }, + { + "data": { + "text/plain": [ + "12" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "@debug\n", + "def add_numbers(x, y):\n", + " return x + y\n", + "add_numbers(7, y=5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.3. Exception Handler\n", + "- The exception_handler the wrapper will catch any exceptions raised within the decorator function" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "def exception_handler(func):\n", + " @functools.wraps(func)\n", + " def wrapper(*args, **kwargs):\n", + " try: \n", + " return func(*args, **kwargs)\n", + " except Exception as e:\n", + " # Handle the exception\n", + " print(f\"An exception occurred: {str(e)}\")\n", + " # Optionally, perform additional error handling or logging\n", + " # Reraise the exception if needed\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "An exception occurred: division by zero\n" + ] + } + ], + "source": [ + "@exception_handler\n", + "def divide(x, y):\n", + " return x / y\n", + "divide(10, 0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.4. Call Count" + ] + }, + { + "cell_type": "code", + "execution_count": 44, + "metadata": {}, + "outputs": [], + "source": [ + "# Call Count\n", + "def count_call(func):\n", + " @functools.wraps(func)\n", + " def wrapper(*args, **kwargs):\n", + " wrapper.count += 1\n", + " result = func(*args, **kwargs)\n", + " print(f\"{func.__name__} has been called {wrapper.count} times\")\n", + " return result\n", + "\n", + " wrapper.count = 0 # initialise to 0 before you ran any of them.\n", + " return wrapper" + ] + }, + { + "cell_type": "code", + "execution_count": 53, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "add_numbers has been called 1 times\n", + "1999\n", + "add_numbers has been called 2 times\n", + "3\n" + ] + } + ], + "source": [ + "@count_call\n", + "def add_numbers(a, b):\n", + " \"\"\"This is plus_two_number function\"\"\"\n", + " return a + b\n", + "\n", + "print(add_numbers(1000, 999))\n", + "print(add_numbers(1, 2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.5. Built-in `lru_cache`\n", + "\n", + "- `@fucntools.lru_cache`: When calling the input function,\n", + " - It first checks if its arguments are present in the cache.\n", + " - If it’s the case, return the result.\n", + " - Otherwise, compute it and put it in the cache" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function 'multiply_numbers' took 0.000002 seconds to complete\n", + "987644223459\n", + "Function 'multiply_numbers' took 0.000002 seconds to complete\n", + "2\n", + "Function 'multiply_numbers' took 0.000001 seconds to complete\n", + "987644223459\n" + ] + } + ], + "source": [ + "@timer\n", + "@functools.lru_cache\n", + "def multiply_numbers(a, b):\n", + " \"\"\"This is plus_two_number function\"\"\"\n", + " return a * b\n", + "\n", + "print(multiply_numbers(99999, 9876541))\n", + "print(multiply_numbers(1, 2))\n", + "print(multiply_numbers(99999, 9876541))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- As you can see that `multiply_numbers` with input` a=99999, b=9876541` called 2 times\n", + " - For the first time, it took 0.000002 to complete\n", + " - For the second time, it only took 0.000001 to complete this is because the result from the second time is retrieved from the cache thanks to the `@functools.lru_cache`\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### 1.6. Retry\n", + "- This wrapper retries the execution of a function a specified number of times with a delay between retries." + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "import traceback\n", + "\n", + "LOG_FORMAT = \"%(asctime)s - %(levelname)s - %(pathname)s - %(funcName)s - %(lineno)d -msg: %(message)s\"\n", + "logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)\n", + "\n", + "def retry(max_attempts, delay):\n", + " \"\"\"\n", + " retry help decorator.\n", + " :param max_attempts: the retry num; retry sleep sec\n", + " :return: decorator\n", + " \"\"\"\n", + " def decorator(func):\n", + " \"\"\"decorator\"\"\"\n", + " @functools.wraps(func) # preserve information about the original function, or else the wrapped func name will be \"wrapper\" not \"func\"\n", + " def wrapper(*args, **kwargs):\n", + " \"\"\"wrapper\"\"\"\n", + " for attempt in range(max_attempts):\n", + " try:\n", + " return func(*args, **kwargs) \n", + " except Exception as err: \n", + " logging.error(err)\n", + " logging.error(traceback.format_exc())\n", + " time.sleep(delay)\n", + " logging.error(f\"Trying attempt {attempt+1} of {max_attempts}\")\n", + " logging.error(f\"func {func.__name__}retry failed\")\n", + " raise Exception(f'Exceed max retry num: {max_attempts} failed')\n", + "\n", + " return wrapper\n", + "\n", + " return decorator" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-10-18 00:08:52,201 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 22 -msg: Server is not responding.\n", + "2023-10-18 00:08:52,212 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 23 -msg: Traceback (most recent call last):\n", + " File \"/var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py\", line 20, in wrapper\n", + " return func(*args, **kwargs)\n", + " ^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/579690303.py\", line 5, in fetch_data\n", + " raise TimeoutError(\"Server is not responding.\")\n", + "TimeoutError: Server is not responding.\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fetching the data..\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-10-18 00:08:54,218 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 25 -msg: Trying attempt 1 of 2\n", + "2023-10-18 00:08:54,219 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 22 -msg: Server is not responding.\n", + "2023-10-18 00:08:54,221 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 23 -msg: Traceback (most recent call last):\n", + " File \"/var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py\", line 20, in wrapper\n", + " return func(*args, **kwargs)\n", + " ^^^^^^^^^^^^^^^^^^^^^\n", + " File \"/var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/579690303.py\", line 5, in fetch_data\n", + " raise TimeoutError(\"Server is not responding.\")\n", + "TimeoutError: Server is not responding.\n", + "\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Fetching the data..\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-10-18 00:08:56,222 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 25 -msg: Trying attempt 2 of 2\n", + "2023-10-18 00:08:56,223 - ERROR - /var/folders/ww/280v33ws1pdd58c895ntxf4w0000gn/T/ipykernel_48486/3869183515.py - wrapper - 26 -msg: func fetch_dataretry failed\n" + ] + }, + { + "ename": "Exception", + "evalue": "Exceed max retry num: 2 failed", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m/Users/quannguyen/repos/python/advanced/decorators_tutorial.ipynb Cell 19\u001b[0m line \u001b[0;36m7\n\u001b[1;32m 4\u001b[0m \u001b[39m# raise timeout error to simulate a server not responding..\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mTimeoutError\u001b[39;00m(\u001b[39m\"\u001b[39m\u001b[39mServer is not responding.\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m----> 7\u001b[0m fetch_data(\u001b[39m\"\u001b[39;49m\u001b[39mhttps://example.com/data\u001b[39;49m\u001b[39m\"\u001b[39;49m)\n", + "\u001b[1;32m/Users/quannguyen/repos/python/advanced/decorators_tutorial.ipynb Cell 19\u001b[0m line \u001b[0;36m2\n\u001b[1;32m 25\u001b[0m logging\u001b[39m.\u001b[39merror(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mTrying attempt \u001b[39m\u001b[39m{\u001b[39;00mattempt\u001b[39m+\u001b[39m\u001b[39m1\u001b[39m\u001b[39m}\u001b[39;00m\u001b[39m of \u001b[39m\u001b[39m{\u001b[39;00mmax_attempts\u001b[39m}\u001b[39;00m\u001b[39m\"\u001b[39m)\n\u001b[1;32m 26\u001b[0m logging\u001b[39m.\u001b[39merror(\u001b[39mf\u001b[39m\u001b[39m\"\u001b[39m\u001b[39mfunc \u001b[39m\u001b[39m{\u001b[39;00mfunc\u001b[39m.\u001b[39m\u001b[39m__name__\u001b[39m\u001b[39m}\u001b[39;00m\u001b[39mretry failed\u001b[39m\u001b[39m\"\u001b[39m)\n\u001b[0;32m---> 27\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mException\u001b[39;00m(\u001b[39mf\u001b[39m\u001b[39m'\u001b[39m\u001b[39mExceed max retry num: \u001b[39m\u001b[39m{\u001b[39;00mmax_attempts\u001b[39m}\u001b[39;00m\u001b[39m failed\u001b[39m\u001b[39m'\u001b[39m)\n", + "\u001b[0;31mException\u001b[0m: Exceed max retry num: 2 failed" + ] + } + ], + "source": [ + "@retry(max_attempts=2, delay=2)\n", + "def fetch_data(url):\n", + " print(\"Fetching the data..\")\n", + " # raise timeout error to simulate a server not responding..\n", + " raise TimeoutError(\"Server is not responding.\")\n", + "\n", + "fetch_data(\"https://example.com/data\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "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.11.3" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/advanced/geo-hashing/README.md b/advanced/geo-hashing/README.md new file mode 100644 index 0000000..4fbab63 --- /dev/null +++ b/advanced/geo-hashing/README.md @@ -0,0 +1,29 @@ +# Geo Hashing + +## What is GeoHash ? + +- A Geohash is a **unique identifier** of a specific region on the Earth. +- The basic idea is the Earth gets divided into rectangular regions of user-defined size, and each region is assigned a unique id which is called its **Geohash**. +- For a given location on earth, the algorithm converts an arbitrary precision latitude and longitude into a string, and the regions with a **similar string prefix** will be **closer together**. + - Conceptually, GeoHashing **reduces proximity search** to _string prefix matching_. As each character encodes additional precision, shared prefixes denote geographic proximity. +


The demo of GeoHash "w3gvk1" corresponding to the longitude & latitude of the HCMC Opera House (Red dot) and the neighbors with precision=6 such as "w3gv7f", "w3gv7b", etc. with the same prefix in geohashes

+- Geohashes also provide a degree of **anonymity** since it isn’t necessary to expose exact GPS coordinates. The location of an entity up to a bounding box cell at a given precision is all that is known. + +## Algorithm + +- The user specifies a level of precision, usually between 1 and 12, and a GeoHash of that length is returned. +- The GeoHash symbol map consists of 32 characters: consists of digits 0 thru 9 plus all lowercase letters excluding a, i, l, o. + - `base32 = "0123456789bcdefghjkmnpqrstuvwxyz"` +- Generate the geohash using `pygeohash` package + +```Python +import pygeohash +lat, lon, precision = 10.776775578390142, 106.7031296241205, 6 +gh_center = pygeohash.encode(latitude=lat, longitude=lon, precision=precision) +print(gh_center) # 'w3gvk1' +``` + +- As you can see, with `precision=6`, the geohash returned is also with the `length=6` +- The table below gives the dimensions of GeoHash cells at each level of precision (taken from [here](https://www.movable-type.co.uk/scripts/geohash.html)): + +


The cell sizes of geohashes of different lengths

diff --git a/advanced/geo-hashing/geo-hashing.ipynb b/advanced/geo-hashing/geo-hashing.ipynb new file mode 100644 index 0000000..120ec52 --- /dev/null +++ b/advanced/geo-hashing/geo-hashing.ipynb @@ -0,0 +1,449 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Geo Hashing\n", + "- [GeoHashing from Scratch in Python](https://www.jtrive.com/posts/geohash-python/index.html)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# !pip install pygeohash\n", + "# !pip install folium" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import pygeohash\n", + "\n", + "# visualise geohash with folium\n", + "import folium \n", + "from folium.features import DivIcon" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def get_bbox_geohash(lat, lon, precision=12):\n", + " min_lat, max_lat = -90, 90\n", + " min_lon, max_lon = -180, 180\n", + " for ii in range(5 * precision):\n", + " if ii % 2 == 0:\n", + " # Bisect longitude (E-W).\n", + " mid_lon = (min_lon + max_lon) / 2\n", + " if lon >= mid_lon: \n", + " min_lon = mid_lon\n", + " else:\n", + " max_lon = mid_lon\n", + " else:\n", + " # Bisect latitude (N-S).\n", + " mid_lat = (min_lat + max_lat) / 2\n", + " if lat >= mid_lat:\n", + " min_lat = mid_lat\n", + " else:\n", + " max_lat = mid_lat\n", + " return [min_lat, min_lon, max_lat, max_lon]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "lat, lon, precision = 10.776775578390142, 106.7031296241205, 6\n", + "gh_center = pygeohash.encode(latitude=lat, longitude=lon, precision=precision)\n", + "min_lat, min_lon, max_lat, max_lon = get_bbox_geohash(lat, lon, precision=precision)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'w3gvk1'" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "gh_center" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [], + "source": [ + "# Get mid_lat and mid_lon for GeoHash id placement. \n", + "mid_lat = (min_lat + max_lat) / 2\n", + "mid_lon = (min_lon + max_lon) / 2" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m = folium.Map(\n", + " location=[lat, lon], \n", + " #width=900, \n", + " #height=600, \n", + " zoom_start=16, \n", + " zoom_control=True, \n", + " no_touch=True,\n", + " tiles=\"OpenStreetMap\"\n", + " )\n", + "\n", + "# precision = 6 GeoHash bounding box. \n", + "folium.Rectangle(\n", + " [(min_lat, min_lon), (max_lat, max_lon)], \n", + " fill_color=\"red\", fill_opacity=.15\n", + " ).add_to(m)\n", + "\n", + "# Red dot at Merchandise Mart. \n", + "folium.CircleMarker(\n", + " location=[lat, lon], radius=5, color=\"red\", fill_color=\"red\", \n", + " fill_opacity=1\n", + " ).add_to(m)\n", + "\n", + "# precision = 6 GeoHash id.\n", + "folium.map.Marker(\n", + " [mid_lat, mid_lon],\n", + " icon=DivIcon(\n", + " icon_size=(250,36),\n", + " icon_anchor=(100,50),\n", + " html=f'
{gh_center}
',\n", + " )\n", + " ).add_to(m)\n", + "# m" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "def get_bbox_and_geohash(lat, lon, precision):\n", + " geohash = pygeohash.encode(latitude=lat, longitude=lon, precision=precision)\n", + " min_lat, min_lon, max_lat, max_lon = get_bbox_geohash(lat, lon, precision=precision)\n", + " bbox = [min_lat, min_lon, max_lat, max_lon]\n", + " return geohash, bbox" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Identify GeoHash Neighboring Cells: once the bounding box for the target GeoHash is known we simply increment those coordinates by a small amount, then lookup the GeoHash and bounding box associated with the new coordinate" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [], + "source": [ + "eps = 1e-10\n", + "gh_center, bb_center = get_bbox_and_geohash(lat, lon, precision=precision)\n", + "min_lat, min_lon, max_lat, max_lon = bb_center\n", + "# Get GeoHash id and bounding box for Northwest cell.\n", + "gh_nw, bb_nw = get_bbox_and_geohash(max_lat + eps, min_lon - eps, precision=precision)\n", + "\n", + "# Get GeoHash id and bounding box for Northeast cell.\n", + "gh_ne, bb_ne = get_bbox_and_geohash(max_lat + eps, max_lon + eps, precision=precision)\n", + "\n", + "# Get GeoHash id and bounding box for Southeast cell.\n", + "gh_se, bb_se = get_bbox_and_geohash(min_lat - eps, max_lon + eps, precision=precision)\n", + "\n", + "# Get GeoHash id and bounding box for Southwest cell.\n", + "gh_sw, bb_sw = get_bbox_and_geohash(min_lat - eps, min_lon - eps, precision=precision)" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [], + "source": [ + "coord_list = zip([gh_center, gh_nw, gh_ne, gh_se, gh_sw],[bb_center, bb_nw, bb_ne, bb_se, bb_sw])" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
Make this Notebook Trusted to load map: File -> Trust Notebook
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m = folium.Map(\n", + " location=[lat, lon], \n", + " #width=900, \n", + " #height=600, \n", + " zoom_start=16, \n", + " zoom_control=True, \n", + " no_touch=True,\n", + " tiles=\"OpenStreetMap\"\n", + ")\n", + "# Red dot at Merchandise Mart. \n", + "folium.CircleMarker(\n", + " location=[lat, lon], radius=5, color=\"red\", fill_color=\"red\", \n", + " fill_opacity=1\n", + ").add_to(m)\n", + "\n", + "for gh, bb in coord_list:\n", + " min_lat, min_lon, max_lat, max_lon = bb\n", + " # Get mid_lat and mid_lon for GeoHash id placement. \n", + " mid_lat = (min_lat + max_lat) / 2\n", + " mid_lon = (min_lon + max_lon) / 2\n", + " # precision = 6 GeoHash bounding box. \n", + " folium.Rectangle(\n", + " [(min_lat, min_lon), (max_lat, max_lon)], \n", + " fill_color=\"red\", fill_opacity=.15\n", + " ).add_to(m)\n", + "\n", + " # precision = 6 GeoHash id.\n", + " folium.map.Marker(\n", + " [mid_lat, mid_lon],\n", + " icon=DivIcon(\n", + " icon_size=(250,36),\n", + " icon_anchor=(100,50),\n", + " html=f'
{gh}
',\n", + " )\n", + " ).add_to(m)\n", + "m" + ] + }, + { + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/advanced/logging_tutorial.py b/advanced/logging_tutorial.py new file mode 100644 index 0000000..fb13e16 --- /dev/null +++ b/advanced/logging_tutorial.py @@ -0,0 +1,31 @@ +import logging + + +def basic_logging() -> None: + logging.basicConfig(level=logging.ERROR) + + logging.debug("This is a debug message.") + logging.info("This is an info message.") + logging.warning("This is a warning message.") + logging.error("This is an error message.") + logging.critical("This is a critical message.") + + +def format_logging() -> None: + logging.basicConfig( + level=logging.DEBUG, + format="%(asctime)s %(levelname)s %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", + # filename="basic.log", log to file + ) + + logging.debug("This is a debug message.") + logging.info("This is an info message.") + logging.warning("This is a warning message.") + logging.error("This is an error message.") + logging.critical("This is a critical message.") + + +if __name__ == "__main__": + basic_logging() + # format_logging() diff --git a/advanced/others/fuzzy-name-matching.ipynb b/advanced/others/fuzzy-name-matching.ipynb new file mode 100644 index 0000000..dd93a3e --- /dev/null +++ b/advanced/others/fuzzy-name-matching.ipynb @@ -0,0 +1,283 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# The Fuzz\n", + "- `theFuzz` uses the Levenshtein edit distance to calculate the degree of closeness between two strings. \n", + " - It also provides features for determining string similarity in various situations\n", + "- [Reference](https://www.datacamp.com/tutorial/fuzzy-string-python)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# !conda install thefuzz" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from thefuzz import fuzz" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## String Matching Methods\n", + "|Technique|\tDescription|\tCode Example|\n", + "|:------:|:------|:------|\n", + "|Simple Ratio|\tCalculates similarity considering the order of input strings.\t|`fuzz.ratio(name, full_name)`|\n", + "|Partial Ratio|\tFinds partial similarity by comparing the shortest string with sub-strings.|\t`fuzz.partial_ratio(name, full_name)`\n", + "|Token Sort Ratio|\tIgnores order of words in strings.|\t`fuzz.token_sort_ratio(full_name_reordered, full_name)`|\n", + "|Token Set Ratio|\tRemoves common tokens before calculating similarity.|\t`fuzz.token_set_ratio(name, full_name)`|" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Simple Ratio \n", + "- `ratio()` calculates the edit distance based on the ordering of both input strings\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Similarity score: 86\n" + ] + } + ], + "source": [ + "# Check the similarity score\n", + "name = \"Kurtis Pykes\"\n", + "full_name = \"Kurtis K D Pykes\"\n", + "\n", + "print(f\"Similarity score: {fuzz.ratio(name, full_name)}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Partial Ratio\n", + "- `partial_ratio()` seeks to find how partially similar two strings are.\n", + " - it calculates the similarity by taking the **shortest** string, which in this scenario is stored in the variable `name`, then compares it against the **sub-strings** of the same length in the longer string, which is stored in `full_name`. " + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Similarity score: 67\n" + ] + } + ], + "source": [ + "print(f\"Similarity score: {fuzz.partial_ratio(name, full_name)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- Since order matters in partial ratio, our score dropped to 67 in this instance. \n", + "- Therefore, to get a 100% similarity match, you would have to move the \"K D\" part to the end of the string" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Partial ratio similarity score: 100\n", + "Simple ratio similarity score: 86\n" + ] + } + ], + "source": [ + "# Order matters with partial ratio\n", + "# Check the similarity score\n", + "name = \"Kurtis Pykes\"\n", + "full_name = \"Kurtis Pykes K D\" # move K D to the end \n", + "\n", + "print(f\"Partial ratio similarity score: {fuzz.partial_ratio(name, full_name)}\")\n", + "\n", + "# But order will not effect simple ratio if strings do not match\n", + "print(f\"Simple ratio similarity score: {fuzz.ratio(name, full_name)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Token Sort Ratio\n", + "- Token sort doesn’t care about what order words occur in. It accounts for similar strings that aren’t in order as expressed above" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Token sort ratio similarity score: 100\n", + "Partial ratio similarity score: 75\n", + "Simple ratio similarity score: 86\n" + ] + } + ], + "source": [ + "# Check the similarity score\n", + "full_name = \"Kurtis K D Pykes\"\n", + "full_name_reordered = \"Kurtis Pykes K D\"\n", + "\n", + "# Order does not matter for token sort ratio\n", + "print(f\"Token sort ratio similarity score: {fuzz.token_sort_ratio(full_name_reordered, full_name)}\")\n", + "\n", + "# Order matters for partial ratio\n", + "print(f\"Partial ratio similarity score: {fuzz.partial_ratio(full_name, full_name_reordered)}\")\n", + "\n", + "# Order will not effect simple ratio if strings do not match\n", + "print(f\"Simple ratio similarity score: {fuzz.ratio(name, full_name)}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- If there are words that are dissimilar words in the strings, it will negatively impact the similarity ratio" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Token sort ratio similarity score: 86\n" + ] + } + ], + "source": [ + "# Check the similarity score\n", + "name = \"Kurtis Pykes\"\n", + "full_name = \"Kurtis K D Pykes\" # \"Kurtis Pykes K D\"\n", + "\n", + "print(f\"Token sort ratio similarity score: {fuzz.token_sort_ratio(name, full_name)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Token set ratio\n", + "- The `token_set_ratio()` method is pretty similar to the token_sort_ratio(), except it takes out common tokens before calculating how similar the strings are: this is extremely helpful when the strings are significantly different in length. " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Token sort ratio similarity score: 100\n" + ] + } + ], + "source": [ + "# Check the similarity score\n", + "name = \"Kurtis Pykes\"\n", + "full_name = \"Kurtis K D Pykes\"\n", + "\n", + "print(f\"Token sort ratio similarity score: {fuzz.token_set_ratio(name, full_name)}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Process\n", + "- The process module enables users to extract text from a collection using fuzzy string matching. Calling the extract() method on the process module returns the strings with a similarity score in a vector. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[('barcelona fc', 86), ('AFC Barcelona', 82)]\n" + ] + } + ], + "source": [ + "from thefuzz import process\n", + "\n", + "collection = [\"AFC Barcelona\", \"Barcelona AFC\", \"barcelona fc\", \"afc barcalona\"]\n", + "print(process.extract(\"barcelona\", collection, scorer=fuzz.ratio, limit=2))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python_tutorial", + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/advanced/pytest/README.md b/advanced/pytest/README.md new file mode 100644 index 0000000..5c25e10 --- /dev/null +++ b/advanced/pytest/README.md @@ -0,0 +1,9 @@ +# PyTest + +## Execution Flag +- `-x` to stop on the first failing test. No more tests are run after that. +- `-v` to print verbose output. + +```Shell +pytest -xv test.py +``` \ No newline at end of file diff --git a/advanced/type_hints.md b/advanced/type_hints.md new file mode 100644 index 0000000..2fb6f60 --- /dev/null +++ b/advanced/type_hints.md @@ -0,0 +1,51 @@ +# Type Hints +## Common Types +```Python +from typing import List, Dict, Tuple +def square_func(arr: List[float]) -> List[float]: + return [x ** 2 for x in arr] +print(square_func([1, 2, 3])) # 1, 4, 9 +``` +### `Union` +```Python +from typing import Union +# cache_dir variable either type str or Path +def filename_to_url(filename: str, cache_dir: Union[str, Path] = None) -> Tuple[str, str]: + pass + +``` +### `Optional` +```Python +from typing import Optional + +Params = dict[str, dict[str, float]] +Descriptions = dict[str, str] + +def foo(x: Params) -> Optional[Descriptions]: + pass +``` +### `Callable` +- `Callable` represents something that can be called (e.g. a function) that takes input arguments and returns an output type: +```Python +from typing import Callable +# func varibale is Callable that takes two integer arguments and returns an float +def apply_func(a: int, b: int, func: Callable[[int, int], float]) -> int: + return func(a, b) + +def divide_func(a: int, b: int) -> float: + return a/b + +apply_func(1,2, divide_func) +``` +## `mypy` Static Type Checker +- `mypy` is a static type checker for Python. It allows us to check our code for common type errors before we actually run anything. + - Installation: `pip install mypy` +```Python +def main(name: str) -> str: + return 'Hello ' + name +if __name__=='__main__': + main('John') +# ------- +# mypy program.py +# >> Success: no issues found in 1 source file +``` diff --git a/assets/img/conda_miniconda_anaconda.webp b/assets/img/conda_miniconda_anaconda.webp new file mode 100644 index 0000000..591f121 Binary files /dev/null and b/assets/img/conda_miniconda_anaconda.webp differ diff --git a/assets/img/geo-hash-cell-size-with-different-length.png b/assets/img/geo-hash-cell-size-with-different-length.png new file mode 100644 index 0000000..e0513a9 Binary files /dev/null and b/assets/img/geo-hash-cell-size-with-different-length.png differ diff --git a/assets/img/geo-hash.png b/assets/img/geo-hash.png new file mode 100644 index 0000000..28ed28d Binary files /dev/null and b/assets/img/geo-hash.png differ diff --git a/assets/img/lru_cache_example.png b/assets/img/lru_cache_example.png new file mode 100644 index 0000000..e09c4e2 Binary files /dev/null and b/assets/img/lru_cache_example.png differ diff --git a/assets/img/plotly_subplots_example.png b/assets/img/plotly_subplots_example.png new file mode 100644 index 0000000..88b1031 Binary files /dev/null and b/assets/img/plotly_subplots_example.png differ diff --git a/basics/README.md b/basics/README.md new file mode 100644 index 0000000..71b0037 --- /dev/null +++ b/basics/README.md @@ -0,0 +1,108 @@ +# Basics Python + +## Topics + +- [`*args` and `**kwargs`](./args_kwargs_tutorial.py) +- [Google Colab](./notebooks/google_colab_tutorial.ipynb) +- [Pathlib](./pathlib_tutorial.py) +- [Subprocess](./notebooks/subprocess.ipynb) +- [YAML](./yaml/README.md) + +## Argument Parser + +- The `argparse` module will “parse” the “arguments” to the program. + - Make the `name` optional by changing the name of the argument to `--name` + - `-n` for the “short” and and `--name` for “long” option names. + - `metavar` value of “name” to describe what the value should be. + +```Python +import argparse + +parser = argparse.ArgumentParser(description='Say hello') +# parser.add_argument('name', help='user_name to greet') # positional argument 'name' +parser.add_argument('-n', '--name', metavar='user_name', + default='World', help='user_name to greet') +args = parser.parse_args() + +print('Hello, ' + args.name + '!') + +# use vars() to make args as the dict +args = vars(parser.parse_args()) +print('Hello, ' + args['name'] + '!') + +``` + +| Type | Example | Required | Default | +| ---------- | ------------------------------ | -------- | ------- | +| Positional | `name` | Yes | No | +| Optinal | `-n` (short), `--name` (long)) | No | Yes | + +- `-h` and `--help` to get the documentation + +```Python +optional arguments: + -h, --help show this help message and exit + -n user_name, --name user_name user_name to greet +``` + +## Code Formater + +- The [PEP 8 (Python Enhancement Proposal)](www.python.org/dev/peps/pep-0008/) describes best practices for formatting code, and most IDEs and text editors will have tools to help you format your code so that it’s easier to read and find problems. + +## Code Linter + +- A code linter is a tool that will report problems in your code, such as declaring a variable but never using it. +- Two most popular code linter: [Pylint](www.pylint.org/) and [Flake8](http://flake8.pycqa.org/en/latest/), and both can find errors in your code that the Python interpreter itself will not complain about. +- [Mypy](http://mypy-lang.org/) can use to find problems along with type hints, such as using text when you should be using a number. + +## Makefile + +- If there is something you need to do literally hundreds of times, say run pytest, so you can creat a **Makefile** that looks like this: + +```Python +.PHONY: test + +test: + pytest -xv test.py +``` + +- If you have the program `make` installed on your computer, you can run you can run `make test` to execute `pytest -xv test.py` + - The `make` program will look for a Makefile in your current working directory and then look for a recipe called “test.” + +## Pip + +- Show package information: `pip show -f ` +- Upgrade package: `pip install --upgrade ` +- Uninstall & install again: `pip install --ignore-installed ` + +## Python IDLE + +- Python can run into 2 modes: Interactive (**Python IDLE**, **IPython**) & Script mode +- The _IDLE_ application (REPL because it’s a Read-Evaluate-Print-Loop) allows you to interact directly with the Python language. Each statement you type is evaluated when you press Enter, and the results are shown in the window. +- The _IPython_ program is yet another “interactive Python” REPL that has many enhancements over IDLE and python3 + +## Shebang `#!` + +- Python programs live in plain text files +- It’s common to put a special comment line in programs like `#!/usr/bin/env python3` these to indicate which language needs to be used to execute the commands in the file. +- Python will ignore the shebang, but the operating systems (like macOS or Windows) will use it to decide which program to use to run the rest of the file. +- Below is the shebang you should add at the beginning of the file + +``` +#!/usr/bin/env python3 +``` + +- The shebang line tells the operating system to use the `env` program (located at `/usr/bin/env`) to find the **python3** that is specific to the machine on which it’s running. + +### Executable Python Program + +- So far we’ve been explicitly telling python3 to run our program (`python3 hello.py`), but since we added the shebang, we can execute the program directly and let the OS figure out that it should use python3. +- The first step in doing this is to make our program “executable” using the command `chmod` + +```bash +chmod +x hello.py # +x will add an “executable” attribute to the file + +# Now can run the program like +# The . / is the current directory, and it’s necessary to run a program when you are in the same directory as the program. +./hello.py +``` diff --git a/basics/args_kwargs_tutorial.py b/basics/args_kwargs_tutorial.py new file mode 100644 index 0000000..233951a --- /dev/null +++ b/basics/args_kwargs_tutorial.py @@ -0,0 +1,33 @@ +a_list = [1, 2, 3] +b_list = [2, 10] +print(a_list) +print(*a_list) + + +def product_list(*args): + result = 1 + for arg in args: + result *= arg + return result + + +print(product_list(*a_list, *b_list)) + + +# merging_dicts.py +my_first_dict = {"A": 1, "B": 2, "C": 3, "D": 4} +my_second_dict = { + "country_capital": {"Vietnam": "Ha Noi", "England": "London", "Japan": "Tokyo"}, + "colors": ["red", "white", "blue"], +} +config_dict = {**my_first_dict, **my_second_dict} +print(config_dict) + + +def demo_func(colors, country_capital, A, B, C, D): + print("\n") + print(colors) + print(country_capital) + + +demo_func(**config_dict) diff --git a/basics/dotvenv.md b/basics/dotvenv.md new file mode 100644 index 0000000..1a47edf --- /dev/null +++ b/basics/dotvenv.md @@ -0,0 +1,15 @@ +# `.env` +- Installation: `pip install python-dotenv==1.0.0` +- Config file stores in `.env` file +```shell +HUGGINGFACEHUB_API_TOKEN="" +``` +- Load environmental variables +```Python +import os +from dotenv import load_dotenv, find_dotenv + +load_dotenv("../config/.env") +# load_dotenv(find_dotenv()) # find_dotenv() is to find the .env +os.environ["HUGGINGFACEHUB_API_TOKEN"] = ... # insert your API_TOKEN here +``` diff --git a/basics/notebooks/google_colab_tutorial.ipynb b/basics/notebooks/google_colab_tutorial.ipynb new file mode 100644 index 0000000..6f5da0a --- /dev/null +++ b/basics/notebooks/google_colab_tutorial.ipynb @@ -0,0 +1,516 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [], + "toc_visible": true + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + } + }, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Introduction to Google Colab\n", + "\n", + "## Jupyter Notebook\n", + "\n", + "- a browser-based environment that integrates code and its output into a single document that combines texts, images, visualizations, mathematical equations.\n", + "- displays outputs, results and data visualization without leaving the environment \n", + "- handy for end to end data science workflows - data cleaning, statistical modeling, building and training machine learning models, visualizing data etc.\n", + "- code is written in independent cells which are executed individually \n", + "- allows the user to test a specific block of code in a project without having to execute the code from the start of the script\n", + "- hosted and run on local machine\n", + "\n", + "## Google Colab\n", + "\n", + "- similar to Jupyter Notebook, but runs entirely in the cloud\n", + "- provides the use of free GPU \n", + "- runs on Google servers using virtual machines – do not need to install any packages\n", + "- allows easy sharing of notebook (just like Google Docs) or to GitHub repository\n", + "- Jupyter Notebook can be uploaded to and run in Google Colab \n", + "\n", + "All the lab materials will be prepared and run on Colab. If you need to access data that are not provided on cloud, you will have to use your Google drive to store the data so that you can access the data in Colab environment. To do so, you must mount your Google Drive on Colab." + ], + "metadata": { + "id": "cN87HBJM6j1R" + } + }, + { + "cell_type": "code", + "source": [ + "print(\"Hello World\")" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KXK8GEoX3obD", + "outputId": "4450b11b-8668-4f65-c380-fb79b19ce2c2" + }, + "execution_count": 1, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Hello World\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Linux Commands & Pip Install" + ], + "metadata": { + "id": "PuUGb5hpJCJh" + } + }, + { + "cell_type": "code", + "source": [ + "!ls" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rvM23hQc6hD-", + "outputId": "8bff903e-b308-47f0-de21-0a8c16fe6e18" + }, + "execution_count": 2, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "sample_data\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "!pwd" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "FZgGHnhTJMnf", + "outputId": "bcb31dc8-142e-42e3-8839-e139ec5923b3" + }, + "execution_count": 3, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "/content\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "!pip freeze | grep tensorflow" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "h2OdrL5xJTLG", + "outputId": "126b5da6-d5b9-4893-dc5e-a903188b758c" + }, + "execution_count": 7, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "tensorflow==2.11.0\n", + "tensorflow-datasets==4.8.3\n", + "tensorflow-estimator==2.11.0\n", + "tensorflow-gcs-config==2.11.0\n", + "tensorflow-hub==0.12.0\n", + "tensorflow-io-gcs-filesystem==0.31.0\n", + "tensorflow-metadata==1.12.0\n", + "tensorflow-probability==0.19.0\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "!pip show tensorflow" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "TqzXNt0rJeKB", + "outputId": "99c5c86e-38ba-4470-bf6e-8c7043d7a36b" + }, + "execution_count": 8, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Name: tensorflow\n", + "Version: 2.11.0\n", + "Summary: TensorFlow is an open source machine learning framework for everyone.\n", + "Home-page: https://www.tensorflow.org/\n", + "Author: Google Inc.\n", + "Author-email: packages@tensorflow.org\n", + "License: Apache 2.0\n", + "Location: /usr/local/lib/python3.8/dist-packages\n", + "Requires: absl-py, astunparse, flatbuffers, gast, google-pasta, grpcio, h5py, keras, libclang, numpy, opt-einsum, packaging, protobuf, setuptools, six, tensorboard, tensorflow-estimator, tensorflow-io-gcs-filesystem, termcolor, typing-extensions, wrapt\n", + "Required-by: \n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "!pip install tensorflow==2.12.0" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "yTl_4aCZKsA0", + "outputId": "b1784fdb-2e46-44da-c2c7-137787e95a29" + }, + "execution_count": 12, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n", + "\u001b[31mERROR: Could not find a version that satisfies the requirement tensorflow==2.12.0 (from versions: 2.2.0, 2.2.1, 2.2.2, 2.2.3, 2.3.0, 2.3.1, 2.3.2, 2.3.3, 2.3.4, 2.4.0, 2.4.1, 2.4.2, 2.4.3, 2.4.4, 2.5.0, 2.5.1, 2.5.2, 2.5.3, 2.6.0rc0, 2.6.0rc1, 2.6.0rc2, 2.6.0, 2.6.1, 2.6.2, 2.6.3, 2.6.4, 2.6.5, 2.7.0rc0, 2.7.0rc1, 2.7.0, 2.7.1, 2.7.2, 2.7.3, 2.7.4, 2.8.0rc0, 2.8.0rc1, 2.8.0, 2.8.1, 2.8.2, 2.8.3, 2.8.4, 2.9.0rc0, 2.9.0rc1, 2.9.0rc2, 2.9.0, 2.9.1, 2.9.2, 2.9.3, 2.10.0rc0, 2.10.0rc1, 2.10.0rc2, 2.10.0rc3, 2.10.0, 2.10.1, 2.11.0rc0, 2.11.0rc1, 2.11.0rc2, 2.11.0, 2.12.0rc0)\u001b[0m\u001b[31m\n", + "\u001b[0m\u001b[31mERROR: No matching distribution found for tensorflow==2.12.0\u001b[0m\u001b[31m\n", + "\u001b[0m" + ] + } + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Mount Google Drive" + ], + "metadata": { + "id": "eULiCOinLmFI" + } + }, + { + "cell_type": "code", + "source": [ + "from google.colab import drive\n", + "drive.mount('/content/drive/')" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "aR0WVsK6LXpb", + "outputId": "e4def66b-cea2-4471-e267-3944320a1a61" + }, + "execution_count": 15, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Mounted at /content/drive/\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "!ls \"/content/drive/MyDrive\"" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "a25i6fFKL4yR", + "outputId": "32bf0556-2242-4e64-8f0f-67398f5e54a2" + }, + "execution_count": 16, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "'Colab Notebooks'\t ML_Algo\n", + " CS608-Recommender-Systems NLP_Transformers-for-NLP-2nd-Edition\n", + " Drift_Detection\t SMU_MITB_NLP\n", + " FSDL_2021\t\t Table_Extraction\n", + " FSDL_2022\t\t YOLO\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd" + ], + "metadata": { + "id": "Kz1x6Wg3MKtX" + }, + "execution_count": 17, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "df = pd.read_csv('/content/drive/MyDrive/ML_Algo/Boosting/data/diamonds.csv', index_col='Unnamed: 0')" + ], + "metadata": { + "id": "_gpj7L9PMdkv" + }, + "execution_count": 20, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "df.head()" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 206 + }, + "id": "iWWnsaG8MjaR", + "outputId": "2b1dcdcb-dc9e-4f4d-c257-82f197800ac2" + }, + "execution_count": 21, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " carat cut color clarity depth table price x y z\n", + "1 0.23 Ideal E SI2 61.5 55.0 326 3.95 3.98 2.43\n", + "2 0.21 Premium E SI1 59.8 61.0 326 3.89 3.84 2.31\n", + "3 0.23 Good E VS1 56.9 65.0 327 4.05 4.07 2.31\n", + "4 0.29 Premium I VS2 62.4 58.0 334 4.20 4.23 2.63\n", + "5 0.31 Good J SI2 63.3 58.0 335 4.34 4.35 2.75" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
caratcutcolorclaritydepthtablepricexyz
10.23IdealESI261.555.03263.953.982.43
20.21PremiumESI159.861.03263.893.842.31
30.23GoodEVS156.965.03274.054.072.31
40.29PremiumIVS262.458.03344.204.232.63
50.31GoodJSI263.358.03354.344.352.75
\n", + "
\n", + " \n", + " \n", + " \n", + "\n", + " \n", + "
\n", + "
\n", + " " + ] + }, + "metadata": {}, + "execution_count": 21 + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "J8KeUpLCMkj9" + }, + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/basics/notebooks/pandas-pivot-melt-crosstab.ipynb b/basics/notebooks/pandas-pivot-melt-crosstab.ipynb new file mode 100644 index 0000000..8c91038 --- /dev/null +++ b/basics/notebooks/pandas-pivot-melt-crosstab.ipynb @@ -0,0 +1,941 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Reshaping Dataframes" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pivot\n", + "- In pandas, there are two methods `.pivot()` and `.pivot_table()` (RECOMMENDED)\n", + "- However, `.pivot()` unable to handle duplicate values in the index column, in this case, the index column is `cusid` which contains multiple rows of `cusid=1`, and `cusid=2`" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cusidpayment_methodmerchanttotal_txn
01DEBITSHOPEE1
11DEBITGRAB2
21CREDITSHOPEE3
32CREDITSHOPEE4
42CREDITLAZADA5
52DEBITGSM6
\n", + "
" + ], + "text/plain": [ + " cusid payment_method merchant total_txn\n", + "0 1 DEBIT SHOPEE 1\n", + "1 1 DEBIT GRAB 2\n", + "2 1 CREDIT SHOPEE 3\n", + "3 2 CREDIT SHOPEE 4\n", + "4 2 CREDIT LAZADA 5\n", + "5 2 DEBIT GSM 6" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame({'cusid': [1,1,1,2,2,2],\n", + " 'payment_method': ['DEBIT', 'DEBIT', 'CREDIT', 'CREDIT', 'CREDIT', 'DEBIT'],\n", + " 'merchant': ['SHOPEE', 'GRAB', 'SHOPEE', 'SHOPEE', 'LAZADA', 'GSM'],\n", + " 'total_txn': [1, 2, 3, 4, 5, 6],\n", + "})\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
payment_methodCREDITDEBIT
merchantLAZADASHOPEEGRABGSMSHOPEE
cusid
1NaN3.02.0NaN1.0
25.04.0NaN6.0NaN
\n", + "
" + ], + "text/plain": [ + "payment_method CREDIT DEBIT \n", + "merchant LAZADA SHOPEE GRAB GSM SHOPEE\n", + "cusid \n", + "1 NaN 3.0 2.0 NaN 1.0\n", + "2 5.0 4.0 NaN 6.0 NaN" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pivot_df = df.pivot_table(index=[\"cusid\"], columns=[\"payment_method\", \"merchant\"], values=[\"total_txn\"])\n", + "pivot_df" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "MultiIndex([('CREDIT', 'LAZADA'),\n", + " ('CREDIT', 'SHOPEE'),\n", + " ( 'DEBIT', 'GRAB'),\n", + " ( 'DEBIT', 'GSM'),\n", + " ( 'DEBIT', 'SHOPEE')],\n", + " names=['payment_method', 'merchant'])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# MultiIndex\n", + "pivot_df.columns" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
CREDIT_LAZADACREDIT_SHOPEEDEBIT_GRABDEBIT_GSMDEBIT_SHOPEE
cusid
1NaN3.02.0NaN1.0
25.04.0NaN6.0NaN
\n", + "
" + ], + "text/plain": [ + " CREDIT_LAZADA CREDIT_SHOPEE DEBIT_GRAB DEBIT_GSM DEBIT_SHOPEE\n", + "cusid \n", + "1 NaN 3.0 2.0 NaN 1.0\n", + "2 5.0 4.0 NaN 6.0 NaN" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "flatten_name_df = pivot_df.copy()\n", + "flatten_name_df.columns = list(map(\"_\".join, pivot_df.columns))\n", + "flatten_name_df" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Melt (Unpivot)\n", + "- Unpivot a DataFrame from **wide** to **long** format, optionally leaving identifiers set.\n", + "- For example, we want to melt the dataframe `df` below into `subjects` and `grades` for each student instead of having multiple subjects columns" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
NameMathEnglishAge
0BobA+C13
1JohnBB16
2FooAB16
3BarFA+15
4AlexDF15
5TomCA13
\n", + "
" + ], + "text/plain": [ + " Name Math English Age\n", + "0 Bob A+ C 13\n", + "1 John B B 16\n", + "2 Foo A B 16\n", + "3 Bar F A+ 15\n", + "4 Alex D F 15\n", + "5 Tom C A 13" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame({'Name': ['Bob', 'John', 'Foo', 'Bar', 'Alex', 'Tom'],\n", + " 'Math': ['A+', 'B', 'A', 'F', 'D', 'C'],\n", + " 'English': ['C', 'B', 'B', 'A+', 'F', 'A'],\n", + " 'Age': [13, 16, 16, 15, 15, 13]})\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
NameAgeSubjectGrades
4Alex15MathD
10Alex15EnglishF
3Bar15MathF
9Bar15EnglishA+
0Bob13MathA+
6Bob13EnglishC
2Foo16MathA
8Foo16EnglishB
1John16MathB
7John16EnglishB
5Tom13MathC
11Tom13EnglishA
\n", + "
" + ], + "text/plain": [ + " Name Age Subject Grades\n", + "4 Alex 15 Math D\n", + "10 Alex 15 English F\n", + "3 Bar 15 Math F\n", + "9 Bar 15 English A+\n", + "0 Bob 13 Math A+\n", + "6 Bob 13 English C\n", + "2 Foo 16 Math A\n", + "8 Foo 16 English B\n", + "1 John 16 Math B\n", + "7 John 16 English B\n", + "5 Tom 13 Math C\n", + "11 Tom 13 English A" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df.melt(\n", + " id_vars=[\"Name\", \"Age\"],\n", + " value_vars=[\"Math\", \"English\"],\n", + " var_name=\"Subject\",\n", + " value_name=\"Grades\",\n", + ").sort_values(by=[\"Name\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Crosstab\n", + "- Crosstab: displays the relationship between two or more categorical variables by showing the frequency of different combinations of those variables" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
GenderEducationAge
0MaleGraduate27
1FemaleUndergraduate18
2FemaleUndergraduate19
3MaleGraduate24
4MaleGraduate29
5FemaleGraduate23
6MaleUndergraduate18
\n", + "
" + ], + "text/plain": [ + " Gender Education Age\n", + "0 Male Graduate 27\n", + "1 Female Undergraduate 18\n", + "2 Female Undergraduate 19\n", + "3 Male Graduate 24\n", + "4 Male Graduate 29\n", + "5 Female Graduate 23\n", + "6 Male Undergraduate 18" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame({'Gender': ['Male', 'Female', 'Female', 'Male', 'Male','Female', 'Male'],\n", + " 'Education': ['Graduate', 'Undergraduate', 'Undergraduate', 'Graduate', 'Graduate', 'Graduate', 'Undergraduate'],\n", + " 'Age': [27, 18, 19, 24, 29, 23,18]})\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
EducationGraduateUndergraduate
Gender
Female02
Male30
\n", + "
" + ], + "text/plain": [ + "Education Graduate Undergraduate\n", + "Gender \n", + "Female 0 2\n", + "Male 3 0" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Basic crosstab\n", + "cross_tab = pd.crosstab(df['Gender'], df['Education'])\n", + "cross_tab" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
EducationGraduateUndergraduate
Gender
Female0.1428570.285714
Male0.4285710.142857
\n", + "
" + ], + "text/plain": [ + "Education Graduate Undergraduate\n", + "Gender \n", + "Female 0.142857 0.285714\n", + "Male 0.428571 0.142857" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Crosstab with normalization: shows the proportion of each combination relative to the total.\n", + "cross_tab_normalized = pd.crosstab(df['Gender'], df['Education'], normalize='all')\n", + "cross_tab_normalized" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
EducationGraduateUndergraduate
Gender
Female23.00000018.5
Male26.66666718.0
\n", + "
" + ], + "text/plain": [ + "Education Graduate Undergraduate\n", + "Gender \n", + "Female 23.000000 18.5\n", + "Male 26.666667 18.0" + ] + }, + "execution_count": 32, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Crosstab with aggregation for each combination\n", + "cross_tab_agg = pd.crosstab(df['Gender'], df['Education'], values=df['Age'], aggfunc='mean')\n", + "cross_tab_agg" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "\n", + "# Crosstab with margins\n", + "cross_tab_margins = pd.crosstab(df['Gender'], df['Education'], margins=True, margins_name=\"Total\")\n", + "print(\"\\nCrosstab with Margins:\")\n", + "print(cross_tab_margins)\n", + "\n", + "\n", + "print(\"\\nCrosstab with Normalization:\")\n", + "print(cross_tab_normalized)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "ml_env", + "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.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/basics/notebooks/subprocess.ipynb b/basics/notebooks/subprocess.ipynb new file mode 100644 index 0000000..1461054 --- /dev/null +++ b/basics/notebooks/subprocess.ipynb @@ -0,0 +1,270 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Subprocess\n", + "- `subprocess.run` is a higher-level wrapper around Popen that is intended to be more convenient to use.\n", + " - Usage: to run a command and capture its output\n", + "- `subprocess.call` \n", + " - Usage: to run a command and check the return code, but do not need to capture the output.\n", + "- `subprocess.Popen` is a lower-level interface to running subprocesses\n", + " - Usage: if you need more control over the process, such as interacting with its input and output streams." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## subprocess.run()\n", + "- `subprocess.run()` method is a convenient way to run a subprocess and wait for it to complete.\n", + " - Once the subprocess is started, the `run()` method blocks until the subprocess completes and returns a `CompletedProcess` object\n", + "- `subprocess.run()`'s input arguments:\n", + " - `args`: The command to run and its arguments, passed as a **list of strings**.\n", + " - `capture_output`: When set to True, will capture the standard output and standard error.\n", + " - `text`: when set to True, will return the stdout and stderr as string, otherwise as bytes `b'/Users/codexplore/Developer/repos/`.\n", + " - `check`: \n", + " - when check is set to True, the function will check the return code of the command and raise a `CalledProcessError` exception if the return code is non-zero. \n", + " - when check is set to False (default), the function will not check the return code and will not raise an exception, even if the command fails.\n", + " - `timeout`: A value in seconds that specifies how long to wait for the subprocess to complete before timing out.\n", + "- `subprocess.run()`` method also returns a `CompletedProcess` object, which contains the following attributes:\n", + " - `args`: The command and arguments that were run.\n", + " - `returncode`: The return code of the subprocess.\n", + " - `stdout`: The standard output of the subprocess, as a bytes object.\n", + " - `stderr`: The standard error of the subprocess, as a bytes object.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import subprocess" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "total 40\n", + "drwxr-xr-x 4 codexplore staff 128 Feb 6 17:32 \u001b[1m\u001b[36m.\u001b[m\u001b[m\n", + "drwxr-xr-x@ 8 codexplore staff 256 Feb 6 17:32 \u001b[1m\u001b[36m..\u001b[m\u001b[m\n", + "-rw-r--r--@ 1 codexplore staff 18414 Oct 22 10:29 google_colab_tutorial.ipynb\n", + "-rw-r--r-- 1 codexplore staff 0 Feb 6 17:32 subprocess.ipynb\n" + ] + }, + { + "data": { + "text/plain": [ + "CompletedProcess(args=['ls', '-la'], returncode=0)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "subprocess.run([\"ls\", \"-la\"])" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [], + "source": [ + "result = subprocess.run([\"pwd\"], capture_output=True, text=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('/Users/codexplore/Developer/repos/python/basics/notebooks\\n', '')" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.stdout, result.stderr" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.returncode" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## subprocess.call()" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.9.6\n", + "Command executed successfully.\n" + ] + } + ], + "source": [ + "return_code = subprocess.call([\"python3\", \"--version\"])\n", + "\n", + "if return_code == 0:\n", + " print(\"Command executed successfully.\")\n", + "else:\n", + " print(\"Command failed with return code\", return_code)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## subprocess.Popen()\n", + "- `Popen` allows you to start a new process and interact with its standard input, output, and error streams. It returns a handle to the running process that can be used to wait for the process to complete, check its return code, or terminate it.\n", + "- The Popen class has several methods that allow you to interact with the process, such as `communicate(`), `poll()`, `wait()`, `terminate()`, and `kill()`." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Python 3.9.6\n", + "\n" + ] + } + ], + "source": [ + "import subprocess\n", + "\n", + "p = subprocess.Popen([\"python3\", \"--version\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)\n", + "\n", + "output, errors = p.communicate()\n", + "\n", + "print(output)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Subprocess `PIPE`\n", + "- A `PIPE` is a unidirectional communication channel that connects one process's standard output to another's standard input. " + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ouptut:\n", + "google_colab_tutorial.ipynb\n", + "subprocess.ipynb\n", + "\n", + "Error : None\n" + ] + } + ], + "source": [ + "# creates a pipe that connects the output of the `ls` command to the input of the `grep` command,\n", + "ls_process = subprocess.Popen([\"ls\"], stdout=subprocess.PIPE, text=True)\n", + "\n", + "grep_process = subprocess.Popen([\"grep\", \".ipynb\"], stdin=ls_process.stdout, stdout=subprocess.PIPE, text=True)\n", + "\n", + "output, error = grep_process.communicate()\n", + "\n", + "print(f\"Ouptut:\\n{output}\")\n", + "print(f\"Error : {error}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "google_colab_tutorial.ipynb\n", + "subprocess.ipynb\n", + "\n" + ] + } + ], + "source": [ + "result = subprocess.run([\"ls\"], stdout=subprocess.PIPE)\n", + "\n", + "print(result.stdout.decode()) # decode() to convert from bytes to strings\n" + ] + } + ], + "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.9.6" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/basics/pathlib_tutorial.py b/basics/pathlib_tutorial.py new file mode 100644 index 0000000..befc817 --- /dev/null +++ b/basics/pathlib_tutorial.py @@ -0,0 +1,30 @@ +# Get current director +from pathlib import Path + +# need to provide .resolve() before calling parents to go up certain level +data_path = Path("__file__").resolve().parents[1] + +# convert Pathlib to String +data_path_str = data_path.as_posix() + +# to create a folder if it is not exist +folder_path = Path("/this/is/the/new/folder") +# parents=True -> will create if parent folder is not existed +# exist_ok=True -> to ignore the warning if the parent folder is already existed +folder_path.mkdir(parents=True, exist_ok=True) + +# glob +""" +data +└── ml-class + └── cnn-audio + ├── bed: *.wav + ├── cat: *.wav + └── happy: *.wav +""" + +data_path = ( + Path("__file__").resolve().parents[1] / "data" / "ml-class" / "cnn-audio" +) +# to loop through all the folder inside "cnn-audio" +audio_files = data_path.glob("*/*.wav") diff --git a/basics/yaml/README.md b/basics/yaml/README.md new file mode 100644 index 0000000..dbc91f5 --- /dev/null +++ b/basics/yaml/README.md @@ -0,0 +1,50 @@ +# YAML + +## Read YAML file +### PyYAML +- Install: `pip install pyyaml` +- `yaml.load_all(file, Loader=yaml.FullLoader)` load multiple yaml docs +- `yaml.safe_load(file)` load the yaml in a safe manner +### `ruamel.yaml` +- Install: `pip install ruamel.yaml` +- `typ='safe'` to achieve `safe_load()` +```Python +from ruamel.yaml import YAML + +yaml=YAML(typ='safe') # default, if not specfied, is 'rt' (round-trip) +yaml.load(doc) + +# set identation +yaml = YAML() +yaml.indent(mapping=4, sequence=6, offset=3) +yaml.load(doc) +``` + +## Define YAML + +- List: + +```yaml +item: + - apple + - oragnge + - banana +# {'item': ['apple', 'oragnge', 'banana']} +``` + +### Anchor & Alias + +```yaml +age: &age 22 +# Anchors (&) & Alias (*) +person_a: &person_a + name: Harry Potter + age: *age_anchor + occupation: Software Engineer +person_a_copy: *person_a +person_b: + <<: *person_a # <<: create merging of mapping (put whatever mapping on &person_a) + name: Stacy # overwrite the mapping of &person_a + age: 12 # overwrite the mapping of &person_a + +``` diff --git a/basics/yaml/data/config.yaml b/basics/yaml/data/config.yaml new file mode 100644 index 0000000..573e67d --- /dev/null +++ b/basics/yaml/data/config.yaml @@ -0,0 +1,25 @@ +job_server: + job_name: yaml_tutorial + job_version: "1.0.0" +data_type: + - string_value: "Hello, World" + - int_value: &age_anchor 22 + - float_value: 3.14 + - bool_value: false # true, false, yes, no + - null_value: null +routes: + - path: /api/posts + methods: [GET] + - path: /api/new_post + method: [POST, PUT] +# Anchors (&) & Alias (*) +person_a: &person_a + name: Harry Potter + age: *age_anchor + occupation: Software Engineer +person_a_copy: *person_a +person_b: + <<: *person_a # <<: create merging of mapping (put whatever mapping on &person_a) + name: Stacy # overwrite the mapping of &person_a + age: 12 # overwrite the mapping of &person_a + diff --git a/basics/yaml/data/multiple_docs.yaml b/basics/yaml/data/multiple_docs.yaml new file mode 100644 index 0000000..f614a17 --- /dev/null +++ b/basics/yaml/data/multiple_docs.yaml @@ -0,0 +1,12 @@ +cities: + - Bratislava + - Kosice + - Trnava + - Moldava + - Trencin +--- +companies: + - Eset + - Slovnaft + - Duslo Sala + - Matador Puchov diff --git a/basics/yaml/pyaml_tutorial.py b/basics/yaml/pyaml_tutorial.py new file mode 100644 index 0000000..742b97e --- /dev/null +++ b/basics/yaml/pyaml_tutorial.py @@ -0,0 +1,21 @@ +# !pip install pyaml +from pathlib import Path +from pprint import pprint + +import yaml + +curr_dir = Path(__file__).resolve().parent + +with open(curr_dir / "data/config.yaml", "r") as f: + # load_all: is to load multiple document in a single YAML + # safe_load: is to load the config in safe manner + """ + docs = yaml.load_all(f, Loader=yaml.FullLoader) # multiple_docs.yaml + + for doc in docs: + for k, v in doc.items(): + print(k, v) + """ + + config = yaml.safe_load(f) + pprint(config, sort_dicts=False) diff --git a/daily_knowledge.md b/daily_knowledge.md new file mode 100644 index 0000000..0a5d01b --- /dev/null +++ b/daily_knowledge.md @@ -0,0 +1,1079 @@ +# 2024 + +## Day 2 + +- Notebook: make changes to your module's code and see the effects immediately without needing to manually reload or restart the notebook's kernel. + +```Python +%load_ext autoreload # enable the autoreload feature in your notebook session. +%autoreload 2 # sets the auto-reload mode to "2", which means that modules will be automatically re-loaded before executing any code that depends on them. +``` + +- How to express $10^{n}$: `2.944297e+10` is equivalent to `2.944297*(10**10)` + +## Day 1 + +### Matplotlib + +- Modify the x-axis with highlighted values (only), instead of listing down all the dates + - In the below example, instead of putting in x-axis all the months, we just highlight data points with marks a year from 1949 to 1962 + +```Python +fig, ax = plt.subplots() + +ax.plot(df['Month'], df['Passengers']) +ax.set_xlabel('Date') +ax.set_ylabel('Number of air passengers') + +plt.xticks(np.arange(0, 145, 12), # only provide each 12 months + np.arange(1949, 1962, 1) # a list of a year corresponding to +) +``` + +### Pandas + +#### `.loc` vs `.iloc` + +- `loc` gets rows (and/or columns) with particular **labels**. +- `iloc` gets rows (and/or columns) at **integer locations**. +- Example: given the following dataframe that has the index starting from 80 to 84 + +```Python +df = pd.DataFrame(np.arange(25).reshape(5, 5), + index=[80, 81, 82, 83, 84], + columns=['col_A','col_B','col_C', 'col_D', 'col_E']) +``` + +| | col_A | col_B | col_C | col_D | col_E | +| --: | ----: | ----: | ----: | ----: | ----: | +| 80 | 0 | 1 | 2 | 3 | 4 | +| 81 | 5 | 6 | 7 | 8 | 9 | +| 82 | 10 | 11 | 12 | 13 | 14 | +| 83 | 15 | 16 | 17 | 18 | 19 | +| 84 | 20 | 21 | 22 | 23 | 24 | + +- Return the first row of the df with two columns `col_A` and `col_D` + - `.loc`: since the first row in the dataframe corresponding to the `index=80`, so we need to specify it in the `.loc` + - `df.loc[80, ["col_A", "col_D"]]` + - `.iloc`: as iloc will be based on the integer location, so the first row in the df is corresponding to the location 0 + - `df.iloc[0, [df.columns.get_loc(c) for c in ["col_A", "col_D"]]]` + +```Python +# example of .loc and .iloc to return the first row of the df with two columns A and D +df.loc[80, ["col_A", "col_D"]] +# col_A 0 +# col_D 3 +df.iloc[0, [df.columns.get_loc(c) for c in ["col_A", "col_D"]]] +# col_A 0 +# col_D 3 +``` + +- Select last 2 row in the `df` → `.iloc` will have the advantages as it is based on the integer location rather then the labels. + +```Python +df.iloc[-2:, :] +``` + +| | col_A | col_B | col_C | col_D | col_E | +| --: | ----: | ----: | ----: | ----: | ----: | +| 83 | 15 | 16 | 17 | 18 | 19 | +| 84 | 20 | 21 | 22 | 23 | 24 | + +- Select first 3 columns of the row after index=82 + +```Python +df.iloc[df.index.get_loc(82):, :3] +``` + +| | col_A | col_B | col_C | +| --: | ----: | ----: | ----: | +| 82 | 10 | 11 | 12 | +| 83 | 15 | 16 | 17 | +| 84 | 20 | 21 | 22 | + +# 2023 + +## Day 11 + +### Python + +- `1e-4` is equal to `0.0001` with total 4 zeros +- Validate the input string variable, say `split` belongs to certain options: `assert split in ['train', 'test', 'both']` + - We can add the handling path if the assertion error paused the program + ```Python + try: + assert 'value' not in numerical_vars + except AssertionError: + # do something + ``` + +### Pandas + +#### `pd.melt` vs contingency table (`pd.crosstab`) + +- The `melt` function in pandas is used to unpivot a DataFrame, meaning that it **converts columns of data into rows**. + - This is useful when you want to combine the data for plotting + - For example: the melt function has converted the `Math` and `Physics` columns into rows, and created two new columns: `subject` and `score`. + +```Python +# Create a sample DataFrame +df = pd.DataFrame({'student_id': [1, 2, 3], 'Math': [4, 5, 6], 'Physics': [7, 8, 9]}) + +# Melt the DataFrame +df_melted = df.melt(id_vars=['student_id'], value_vars=['Math', 'Physics'], var_name='Ssubject', value_name='score') + +# Print the melted DataFrame +print(df_melted) + +# student_id subject score +# 0 1 Math 4 +# 1 2 Math 5 +# 2 3 Math 6 +# 3 1 Physics 7 +# 4 2 Physics 8 +# 5 3 Physics 9 + +# plotting the melted dataframe by subject using hue of seaborn + +sns.barplot(df_melted, x='student_id', y='score', hue='subject') +``` + +- The `crosstab` function: produces a DataFrame where the rows represent the levels of one factor and the columns represent the levels of another factor. +- Usage: to create frequency table for each category in a feature vs another feature +- The crosstab function takes the following arguments: + - `index`: The name of the column to use for the row labels. + - `columns`: The name of the column to use for the column labels. + - `values`: The name of the column to use for the cell values. If not specified, the counts of observations are used. + - `margins`: If True, the DataFrame will include a row and column for the totals. + +```Python +# Create a sample DataFrame +df = pd.DataFrame({'gender': ['M', 'F', 'M', 'F', 'F'], 'favorite_color': ['blue', 'red', 'green', 'blue', 'purple']}) + +# gender favorite_color +# 0 M blue +# 1 F red +# 2 M green +# 3 F blue +# 4 F purple +# Create a crosstabulation of gender and favorite color +crosstab = pd.crosstab(df['gender'], # rows + df['favorite_color'], # columns + margins=True # True to calculate the total + ) + +# re-name columns "All" to 'row_totals' & 'col_totals' +# note: columns "All" are only avail if margins=True +crosstab.columns = [*crosstab.columns.to_list()[:-1], 'row_totals'] +crosstab.index = [*crosstab.index.to_list()[:-1], 'col_totals'] +# blue green purple red row_totals +# F 1 0 1 1 3 +# M 1 1 0 0 2 +# col_totals 2 1 1 1 5 +``` + +### Matplotlib + +- Subplots: + +```Python +# Annual, weekly and daily seasonality +# ============================================================================== +fig, axs = plt.subplots(2, 2, figsize=(8.5, 5.5), sharex=False, sharey=True) + +# Before: +ax1 = axs[0,0] +ax2 = axs[0,1] +# After with axs.ravel() +axs = axs.ravel() +ax1 = axs[0] +#... +ax4 = axs[3] + +``` + +### Conda vs Pip: Package Availability + +- Pip installs packages from the Python Package Index (`PyPI`), which hosts a vast array of Python libraries. Almost any Python library can be installed using pip. +- conda installs packages from the Anaconda distribution and other channels (`conda-forge`). While the number of packages available through conda is smaller than pip, conda can install packages for multiple languages and not just Python. +- Example: `skforecast` is not avail in the `conda-forge` but it is avail in `PyPI`, so you cannot `conda install skforecast`, but it can be install via `pip install` command + +## Day 10 + +### Pandas + +- Find the row with the column is equal to value: `index_choice = df.index.get_loc(CustomerId=15674932)` + +#### `pd.cut` vs `pd.qcut` + +| | Space between 2 bins | Frequency of Samples in each bin | +| --------- | -------------------- | -------------------------------- | +| `pd.cut` | Equal Spacing | Difference | +| `pd.qcut` | Un-equal Spacing | Same | + +- `pd.cut` will choose the bins to be **evenly spaced** according to the values themselves and not the frequency of those values. + - You also can define the bounds for each binning with `pd.cut()` + - You can use the Fisher-Jenks algorithm to determine the natural bounds and then pass those values into `pd.cut()` +- `pd.qcut` the bin interval will be chosen so based on the percentiles that you have the same number of records in each bin. + +```Python +factors = np.random.randn(30) + +pd.cut(factors, 5).value_counts() # bin size has equal interval of ~1 + +# (-2.583, -1.539] 5 +# (-1.539, -0.5] 5 +# (-0.5, 0.539] 9 +# (0.539, 1.578] 9 +# (1.578, 2.617] 2 + +pd.qcut(factors, 5).value_counts() # each bin has equal size of 6 + +# [-2.578, -0.829] 6 +# (-0.829, -0.36] 6 +# (-0.36, 0.366] 6 +# (0.366, 0.868] 6 +# (0.868, 2.617] 6 + + + + +``` + +#### `.read_csv()` by chunk + +- If the csv file is large, can consider to read by chunk + +```Python +df_iter = pd.read_csv(file_path, iterator=True, chunksize=100000) +df = next(df_iter) +``` + +### Python + +#### `lru_cache` from `functools` + +- `@lru_cache` modifies the function it decorates to return the same value that was returned the first time, instead of computing it again, executing the code of the function every time. + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +

+ +#### typing `Annotated` + +- `Annotated` in python allows developers to declare the type of a reference and provide additional information related to it. + +```Python +from typing_extensions import Annotated +# This tells that "name" is of type "str" and that "name[0]" is a capital letter. +name = Annotated[str, "first letter is capital"] +``` + +- Fast API examples: + ```Python + from fastapi import Query + def read_items(q: Annotated[str, Query(max_length=50)]) + ``` + - The parameter `q` is of type `str` with a maximum length of 50. + +#### Float to Decimal conversion + +- Convert `float` directly to `Decimal` constructor introduces a rounding error. + +```Python +from decimal import Decimal +x = 0.1234 +Decimal(x) +# Decimal('0.12339999999999999580335696691690827719867229461669921875') +``` + +- **Solution**: to convert a float to a string before passing it to the constructor. + - You also can round the float before converting it to string + +```Python +Decimal(str(x)) +# Decimal('0.1234') +Decimal(str(round(x,2))) +# Decimal('0.12') +``` + +- + +## Day 9 + +### `subprocess` module + +- `subprocess.run` is a higher-level wrapper around Popen that is intended to be more convenient to use. + - Usage: to run a command and capture its output +- `subprocess.call` + - Usage: to run a command and check the return code, but do not need to capture the output. +- `subprocess.Popen` is a lower-level interface to running subprocesses + + - Usage: if you need more control over the process, such as interacting with its input and output streams. + +- A `PIPE` is a unidirectional communication channel that connects one process's standard output to another's standard input. + +```Python +# creates a pipe that connects the output of the `ls` command to the input of the `grep` command, +ls_process = subprocess.Popen(["ls"], stdout=subprocess.PIPE, text=True) + +grep_process = subprocess.Popen(["grep", ".ipynb"], stdin=ls_process.stdout, stdout=subprocess.PIPE, text=True) + +output, error = grep_process.communicate() + +print(f"Ouptut:\n{output}") +print(f"Error : {error}") + +# Ouptut: +# google_colab_tutorial.ipynb +# subprocess.ipynb +# +# Error : None +result = subprocess.run(["ls"], stdout=subprocess.PIPE) + +print(result.stdout.decode()) # decode() to convert from bytes to strings +# google_colab_tutorial.ipynb +# subprocess.ipynb +``` + +#### `subprocess` vs `os.system` + +- `subprocess.run` is generally more flexible than `os.system` (you can get the stdout, stderr, the "real" status code, better error handling, etc.) +- Even the [documentation for `os.system`](https://docs.python.org/3/library/os.html#os.system) recommends using subprocess instead. + +### `sys` module + +- The kernel knows to execute this script with a **python** interpreter with the shebang `#!/usr/bin/env python` +- `sys.argv[0]` return name of the script +- `sys.argv[1:]` return the arguments parsed to the script + +```Python +############################# +# in the python_script.py # +############################# +#!/usr/bin/env python +import sys +for arg in reversed(sys.argv[1:]): + print(arg) + +############################# +# in the interactive shell # +############################# +bash-5.2$ chmod +x python_script.py +bash-5.2$ ./python_script.py a b c +# Running: ./python_script.py +# c +# b +# a +``` + +## Day 8 + +- `bytes("yes", "utf-8")` convert string to binary objects: + +### Matplotlib + +- Color Map + +```Python +cmap = plt.get_cmap("viridis") +fig = plt.figure(figsize=(8, 6)) +m1 = plt.scatter(X_train, y_train, color=cmap(0.9), s=10) +m2 = plt.scatter(X_test, y_test, color=cmap(0.5), s=10) +``` + +- Plot 2 charts on the same figure with share x-axis + +```Python +fig, ax1 = plt.subplots() + +ax1.hist(housing["housing_median_age"], bins=50) + +ax2 = ax1.twinx() # key: create a twin axis that shares the same x-axis +color = "blue" +ax2.plot(ages, rbf1, color=color, label="gamma = 0.10") +ax2.tick_params(axis='y', labelcolor=color) +ax2.set_ylabel("Age similarity", color=color) # second y-axis's measurement + +plt.show() +``` + +### Relative import + +``` +# example.py +from .abstract import ExampleClass +# if we run this script directly like python src/abc/example.py, we will encounter the issue +``` + +- Soluton: `python -m src.abc.example` or call the `example.py` script outside the `src` + +### `subprocess.Popen` to send Linux command + +```Python +from subprocess import Popen, Pipe + +execute = Popen("scp -i /location_in_machine_A/to/private/key -v -P 64022 file_path machineB@ip_address:/path/to/store/inB/".split(), stdout=PIPE, stdin=PIPE, stderr=PIPE) +execute.stdin.write(bytes("yes", "utf-8")) # to send the "yes" command +execute.communicate()[0] + +``` + +### `os.path` + +- To read the path separator of the env `os.path.sep # return '/' if using Linux` + +### List + +- Copy a list: `copied_list = a_list[:]` + - Leverage on `copy` module + ```Python + import copy + copied_list = copy.deepcopy(a_list) + ``` + +## Day 7 + +### Conda + +- Conda is an open source **package** + **environment** manager +- Conda vs (Miniconda & Anaconda): + - _Conda_ is a **package manager** & _Conda_ is tightly coupled to two software distributions: _Anaconda_ and _Miniconda_. + - _Anaconda_ is a full distribution of the central software in the PyData ecosystem, and includes Python itself along with binaries for several hundred third-party open-source projects. + - _Miniconda_ is essentially an installer for an empty conda environment, containing only Conda and its dependencies, so that you can install what you need from scratch. +- Recommended conda installation in PC: Miniconda +- Miniconda and Miniforge: + - **Miniforge**-installed conda is the same as Miniconda-installed conda, except that it uses the conda-forge channel (and only the conda-forge channel) as the default channel. + - **Miniconda**-installed conda is the Anaconda (company) driven minimalistic conda installer, where pacakages installed from the anaconda channels +- Conda channel: A **channel** is the location where packages are stored remotely. + - Example of channels: Anaconda channel, `conda-forge`, Apple + - Install TensorFlow dependencies from Apple Conda channel: `conda install -c apple tensorflow-deps` +- Understanding `environment.yml` in `conda create --prefix ./venv python=3.8 --file environment.yml` + - `tensorflow-deps` will need to be installed by `conda` via `apple` channel + - `scikit-learn` will be installed by `conda` via `conda-forge` channel + - `tensorflow-macos` will need `pip` install via **PyPI** + +```yaml +name: tensorflow +channels: + - apple + - conda-forge +dependencies: + - tensorflow-deps + - scikit-learn + - pip: + - tensorflow-macos + - tensorflow-metal +``` + +#### Conda env creation: + +```shell +# create env +conda create --prefix ./venv python=3.8 --file requirements.txt +conda activate ./venv +conda deactivate + +# install package from requirements.txt +conda install --file requirements.txt +# export to requirements.txt so that can install via pip in virtualenv/venv environment + +pip list --format=freeze > requirements.txt +``` + +#### `conda create --file requirements.txt` vs `conda env create --file environment.yml` + +- `conda create --file` expects a `requirements.txt`, not an `environment.yml`, each line in the given file is treated as a package-reference +- `conda env create` to create an environment from a given `environment.yml` + - Command: `conda env create --name tensorflow --file environment.yml` + +#### Other common conda commands + +- `conda env list` to list down conda envs +- `du -h -s $(conda info --base)/envs/*` list down the size of each env +- `conda config --show channels` to show available channels in the config + +## Day 6 + +- Number: `1000000` can be written as `1_000_000` for the ease of visualisation + ```Python + state['Population'] / 1_000_000 + ``` + +### Matplotlib + +- Plot horizontal line: `{plt, ax}.axhline(y=0.5, color='r', linestyle='-')` + +### Numpy + +- Stacking columns/rows + - `np.column_stack` & `np.row_stack` + - `np.hstack` & `np.vstack` + +```Python +a = np.array((1,2,3)) +b = np.array((2,3,4)) +# column stack +np.column_stack((a,b)) +# array([[1, 2], +# [2, 3], +# [3, 4]]) + +# row_stack or vstack +np.row_stack((a,b)) +np.vstack((a,b)) +# array([[1, 2, 3], +# [2, 3, 4]]) + +# hstack +np.hstack((a,b)) +# array([1, 2, 3, 2, 3, 4]) +``` + +### Holidays package + +- Pandas's holiday package: `pandas.tseries.holiday` +- `holidays` package + +### Code Refactor + +- Instead of `if '.yml' in file_path or '.yaml' in file_path` we can do as follows: + - Solution: `if any(ext in file_path for ext in ['.yml', '.yaml']` + +## Day 5 + +### Seaborn + +- To get color palatte `color_pal = sns.color_palette()` + +#### Histogram (Displot) + +- Since the `sns.displot` is deprecated, so we will use `sns.histplot` as follow to plot the histogram + kde distribution by specifying `kde=True` +- Also can `set_xlim()` to the zone that containing the data in case the distribution is skewed + +```Python +sns.histplot(df['col_name'], kde=True, bins=50).set_xlim(0,8); +``` + +#### Pairplot + +- Pairplot is to use `scatterplot()` for each pairing of the variables and `histplot()` for the marginal plots along the diagonal +- Customise with `x_var` and `y_var` and `hue` + +```Python +sns.pairplot(df.dropna(), + hue='hour', + x_vars=['hour','dayofweek', + 'year','weekofyear'], + y_vars='PJME_MW', + height=5, + plot_kws={'alpha':0.15, 'linewidth':1.5} + ) +plt.suptitle('Power Use MW by Hour, Day of Week, Year and Week of Year') +plt.show() +``` + +

+ +### Python + +- `yield` keyword is used in the context of defining generator functions. + - When a generator function is called, it doesn't execute the function immediately. + - Instead, it returns a generator object that can be used to control the execution of the function. + - The code inside the generator function is executed only when an item is requested from the generator using the `next()` function or a `for` loop. + +```Python +def simple_generator(): + yield 1 + yield 2 + yield 3 + +# Create a generator object +gen = simple_generator() + +# using next() to access the code inside +print(next(gen)) # 1 +print(next(gen)) # 2 +print(next(gen)) # 3 +print(next(gen)) # StopIteration raised + +# using for-loop to iterate through the generator +for value in simple_generator(): + print(value) + +``` + +### Pandas + +### Select columns based on Dtype + +- Numerical columns: `num_cols = df.select_dtypes(include=np.number).columns.tolist()` +- Categorical columns: `cat_cols = df.select_dtypes(exclude=np.number).columns.tolist()` + +### Time-series + +- Convert the datetime index to a datetime col: `df['date'] = df.index.date` +- Slicing using 1 date by including `23:59:59` + +```Python +end_train = '1980-01-01 23:59:59' +# including 23:59:59 means +data_train = df.loc[:end_train] # ends at 1980-01-01 +data_test = df.loc[end_train:] # start at 1980-01-02 +``` + +#### `df.query` + +- Can set multiple condition: `df.query("make == 'bmw' and model == '1_series')` +- Can query using a list + +```Python +holiday_list = ['2021-01-01', '2022-09-02'] +df.query('datetime_col in @holiday_list') +``` + +#### Check & Remove Duplicates + +- `df.duplicated()` to check if there are any row duplicate. This will return `True` for the 2nd occurence of the duplicate + - `df.duplicated(subset=['col_A','col_B','col_C'])` in case there is no entire row duplciate, we can check duplicates for only subsets of columns +- `df.query("make == 'bmw' and model == '1_series' and year == 2013 and price == 31500")` using query to identify & view the duplicated rows +- Remove the duplicates + - `.reset_index(drop=True)` to reset the index after dropping the duplicates + - `.copy()` to make the deep copy of the dataframe + +```Python +df = df.loc[~df.duplicated(subset=['Coaster_Name','Location','Opening_Date'])] \ + .reset_index(drop=True).copy() +``` + +### Matplotlib + +- You can set matplotlib object to `ax` variable + - You also can continue to plot on the same graph with `ax` variable + +```Python +# case 1: get ax from the plot via pandas dataframe +ax = df['year'].value_counts() \ + .head(10) \ + .plot(kind='bar', title='Top 10 Years Coasters Introduced') + +# case 1.1: also can continue to plot on the same graph with ax variable +df.query('year < 2023').plot(style='.', ax=ax) + +ax.set_xlabel('year') +ax.set_ylabel('count') + +# case 2: get ax from the plot via seaborn +ax = sns.countplot(data=df, x='year') +ax.set_xticks(ax.get_xticks(), ax.get_xticklabels(), rotation=90, ha='center') +``` + +- Rotate the xticks label + +```Python +# rotate via plt +plt.xticks(rotation=90) + +# rotate via ax +ax.set_xticks(ax.get_xticks(), ax.get_xticklabels(), rotation=45, ha='right') +``` + +## Day 4 + +### Numpy + +- Numpy 's `np.nan` vs Python 's `None` object + - In Numpy, a `np.nan` value is a native floating-point type array. + - When you try to do some arithmetic operations will `np.nan`, the result will always be `np.nan`. + - Fortunately, Numpy provides some special aggregation methods that can ignore the existence of `np.nan` value such as `np.nansum(arr)` + - `None` is a Python Object called **NoneType** + - Pandas automatically converts the `None` to a `np.nan` value. + - If you try to aggregate over this array, you will get an error because of the NoneType. + +### Pandas + +- `df.loc[:, "col"] = df["col"].map(mapping)` re-assign the updated value to originial column without any error +- `pd.options.display.max_columns` to view all the columns in the df when `df.head()` + +#### `groupby` + +- Use the `.agg` function to get multiple statistics on the other columns + +```Python +## Example 1: +df.groupby('A').agg(['min', 'max']) # apply same operations on other columns +## Example 2: +df.groupby('A').agg({'B': ['min', 'max'], 'C': 'sum'}) # apply different operations on other columns +## Example 3: +# group by Team & Position, get mean, min, and max value of Age for each value of Team. +grouped_single = df.groupby(['Team', 'Position']).agg({'Age': ['mean', 'min', 'max']}) +grouped_single.columns = ['age_mean', 'age_min', 'age_max'] # rename columns +# reset index to get grouped columns back +grouped_single = grouped_single.reset_index() + +## Example 4: +df_customers.groupby('rfm_score').agg( # groupby 'rfm_score' col + customers=('customer_id', 'count'), # create new 'customers' col by count('customer_id' col) + mean_recency=('recency', 'mean'), # create new 'mean_recency' col by mean('recency' col) + mean_frequency=('frequency', 'mean'), + mean_monetary=('monetary', 'mean'), +).sort_values(by='rfm_score') +``` + +- Group by the first column and get second column as lists in rows using `.apply(list)` + +```Python +In [1]: df = pd.DataFrame( {'a':['A','A','B','B','B','C'], 'b':[1,2,5,5,4,6]}) + df + +Out[1]: + a b +0 A 1 +1 A 2 +2 B 5 +3 B 5 +4 B 4 +5 C 6 + +In [2]: df.groupby('a')['b'].apply(list) +Out[2]: +a +A [1, 2] +B [5, 5, 4] +C [6] +Name: b, dtype: object +``` + +### Python + +- `IPython` debug: when executing `main.py` script in the terminal, we still can insert **ipython** checkpoint at the line we want to debug + - `from IPython import embed; embed()` +- Avoid circular imports + + ``` + # __init__.py of utils folder + from .base_logger import * + from .data_loader import * + + def load_yaml() + + # data_loader.py + from utils import load_yaml # this will cause circular import + ``` + + - Solution: DO NOT `from .data_loader import *` if a data_loader refer to any functions in `utils.__init__.py` + +### `.env` + +- Installation: `pip install python-dotenv==1.0.0` +- Config file stores in `.env` file + +```shell +HUGGINGFACEHUB_API_TOKEN="" +``` + +- Load environmental variables + +```Python +import os +from dotenv import load_dotenv, find_dotenv + +load_dotenv("../config/.env") +# load_dotenv(find_dotenv()) # find_dotenv() is to find the .env +os.environ["HUGGINGFACEHUB_API_TOKEN"] = ... # insert your API_TOKEN here +``` + +## Day 3 + +### Notebook + +- Surpass the warning + +```Python +import warnings +warnings.filterwarnings('ignore') + +# [Optional] If you do not want to supress all the warnings, you also can explicitly specify which warning needs ignore +import warnings +warnings.filterwarnings('ignore', category=FutureWarning) +warnings.filterwarnings('ignore', category=DeprecationWarning) +``` + +- Both `!` and `%` allow you to run shell commands from a Jupyter notebook + - Difference: `!` calls out to a shell (in a new process), while `%` affects the process associated with the notebook + - `!cd foo`, by itself, has **no lasting effect**, since the process with the changed directory immediately terminates. + - `%cd foo` changes the current directory of the notebook process, which is a **lasting effect**. + - Example + ```Bash + # in a notebook cell + !git clone https://github.com/full-stack-deep-learning/fsdl-text-recognizer-2021-labs # ! can use for git clone, pip install + %cd fsdl-text-recognizer-2021-labs # % use for cd + ``` + +### VScode + +- Multiline editing in Visual Studio Code: + - Mac: `⌥ Opt`+`⌘ Cmd`+`↑/↓` + - Windows: `Shift`+`Alt`+`↑/↓` + +### Matplotlib + +#### Figure + +- Figure object is the overall window where everything is drawn. + +```Python +def draw_smtg(): + fig = plt.figure(figsize=(10,10)) + plt.plot(...) + + return fig #whatever the graphs in fig will be returned +``` + +### Python + +- Logging level: `DEBUG > INFO > WARNING > ERROR > CRITICAL` + - If set `logging.basicConfig(level=logging.ERROR)` means that only log `ERROR` & `CRITICAL` +- `reload` a module in Jupyter notebook + +```Python +from importlib import reload +from abc import module_a +# By doing this, whatever code change in class_xyz will be reflected in the notebook +reload(module_a) +from abc.module_a import class_xyz +``` + +- `python -m pip install ` + - [`-m` flag](https://stackoverflow.com/a/69527909/7973510) makes sure that you are using the pip that's tied to the active Python executable. +- Load pickle file using `joblib` + +```Python +model = joblib.load('lgbm_mode.pkl') +``` + +## Day 2 + +### Pandas + +- `df = pd.read_csv('example.csv',index_col=[0], parse_dates=[0])` to set the col loc=0 as the index, and parsed as date time type +- `to_csv` to prevent `nnamed: 0` column to be appended along with your original df by set `df.to_csv('result.csv', index=False)` +- `.apply` based on the condition of certain columns + +```Python +df.loc[:,'C'] = df.apply(lambda row: 'Hi' if row['A'] > 10 and row['B'] < 5 else '') +``` + +- `df.insert()` Avoid error `Try using .loc[row_indexer,col_indexer] ` when creating the new column in df from an existing df + +```Python +# insert(position of the newly_inserted_col in the df, newly_inserted_col's name, newly_inserted_col's value) +data.insert(len(data.columns), 'rolling', data['open'].rolling(5).mean().values) +``` + +#### Joining Pandas DataFrame with Numpy array + +- Concat `df` with `numpy_array` and assign the name for the `numpy_array` as `new_col` + - Syntax: `df = df.assign(new_col=numpy_array)` + +#### Joining Pandas DataFrame with Pandas Series + +```Python +# need to convert pd's Series into the Dataframe, and transpose it before concat with pd's DF +pd.concat([df, pd_series.to_frame().T], ignore_index=True) +``` + +#### Joining Pandas DataFrames + +- Experience: before joining (either `concat`, `merge`), need to careful about the _index_ of the dataframes (might need to `.reset_index()`) as apart from the joining condition, pandas also matching the index of each dataframe. + +


Column Concat
+
+Merge [Inner, Outter (Left, Right)] +

+ +- `concat()` for combining DataFrames across rows or columns + - **axis** represents the axis that you’ll concatenate along. + - The default value is **0**, which concatenates **along the index**, or row axis. + - Alternatively, a value of **1** will concatenate vertically, **along columns**. You can also use the string values "index" or "columns". + - `ignore_index` defaults to False. + - If True, then the new combined dataset won’t preserve the original index values in the axis specified in the axis parameter. This lets you have entirely new index values. +- `merge()` for combining data on common columns or indices + - **how** defaults to `inner`, but other possible options include `outer`, `left`, and `right` + - `on`; `left_on` and `right_on` specify a column or index that’s present only in the left or right object that you’re merging + +```Python +# ------------ pd.concat() examples ------------ +reindexed = pd.concat( + [df1, df2], ignore_index=True, axis=1 +) +# ------------ pd.merge() examples ------------- +pd.merge( + df1, df2, how="left", on=["col_A", "col_B"] +) +# if left & right DF has diff joining col names +pd.merge( + df1, df2, how="left", left_on=["col_A1"], right_on=["col_A2"] +) +``` + +### Numpy + +- Dense & Sparse Matrix Conversion: + - Sparse → Dense: `A.toarray()` +- Numpy vs Tensor: + - TensorFlow seems to look a lot like NumPy. But here’s something NumPy can’t do: retrieve the gradient of any differentiable expression with respect to any of its inputs. + - Open a `GradientTape` scope, apply some computation to one or several input tensors, and retrieve the gradient of the result with respect to the inputs. + - A significant difference between NumPy arrays and TensorFlow tensors is that TensorFlow tensors aren’t assignable: they’re constant + +```Python +import numpy as np +x = np.ones(shape=(2, 2)) +x[0, 0] = 0. + +x = tf.ones(shape=(2, 2)) +x[0, 0] = 0. # ERROR: fail, as a tensor isn’t assignable. +``` + +### `sys.path` + +- `sys.path` is a built-in variable within the sys module. It contains a list of directories that the interpreter will search in for the required module. When a module(a module is a python file) is imported within a Python file, the interpreter first searches for the specified module among its built-in modules. If not found it looks through the list of directories(a directory is a folder that contains related modules) defined by sys.path. +- To locate the installation path of the module: `print(module_name.__file__)` +- Python will locate the module based on the path appears first in `sys.path`, so in order to change prioritise the installation packages, we can do as follow: + +```Python +import sys +sys.path.insert(0, '/path/to/site-packages') # location of src +``` + +### Matplotlib + +- Set params: `plt.rcParams.update({'font.size': 14})` +- Set the style of the plot `plt.style.use('fivethirtyeight') # set at the front of the notebook` + - Other styles: `seaborn-v0_8-darkgrid` + +#### Ax + +- Set vertical axis range: `ax.set_ylim([0,1])` or `plt.gca().set_ylim(0,1) #set vertical range to [0-1]` +- Set horizontal axis range: + +#### Subplots + +- Enable subplots share the same axis with `sharex` or `sharey`: `plt.subplots(nrows=3, sharey=True)` +- `fig.tight_layout(pad=2)` function of matplotlib allows to adhust the gap between subplots + - `pad` parameter to specify gap size + +### Python + +- `assert`: to check if the data is expected (`assert len(x.shape) == 2`) and will raise Exception if not matching. +- `iter()`: return an iterator for the given a list, set, tuple or object with `__next__()` method. + +```Python +phones = ['apple', 'samsung', 'oneplus'] +phones_iter = iter(phones) +print(next(phones_iter)) +``` + +- `os.environ[variable]=value` a mapping object that represents the user’s environmental variables. +- `sys.path` is a built-in variable within the sys module. It contains a list of directories that the interpreter will search in for the required module. When a module(a module is a python file) is imported within a Python file, the interpreter first searches for the specified module among its built-in modules. If not found it looks through the list of directories(a directory is a folder that contains related modules) defined by sys.path. +- `random` module + - Randomly select an item in a list: `random.randint(0, len_x)` + - Randomly select subset of items in a list: + ```Python + # Method 1 + indices_permutation = random.permutation(len(x)) + dataset[indices_permutation][:10] + # Method 2: select 10 out of the dataset + indices_permutation = random.sample(range(len(trainset)), 10) + dataset[indices_permutation] + ``` + - Normal distribution with mean 0 and standard deviation 1: `np.random.normal(size=(3,1), loc=0., scale=1.)` + - Uniform distribution between 0 and 1: ` np.random.uniform(size=(3, 1), low=0., high=1.)` + +## Day 1 + +### VS Code + +#### VS Code Shortcuts + +- `CMD + Shift + P` Command Palette +- `CMD + P` Quickly open files + +#### Auto Venv Activation + +```json +# in .vscode settings.json +"python.terminal.activateEnvironment": true +``` + +## Code Formatter & Linting + +- The main coding standard for Python is PEP8 (Python Enhancement Proposal 8) + - **Linters** such as `flake8` and `pylint` highlight places where your code doesn’t conform with PEP8. + - **Automatic formatters** such as `black` that will update your code automatically to conform with coding standards. + - **Type Checker** `mypy` is a static type checker for Python. Type checkers help ensure that you're using variables and functions in your code correctly. With mypy, add type hints (PEP 484) to your Python programs, and mypy will warn you when you use those types incorrectly. + +### Setup inside VS Code + +- How to install `flack8`: + - Step 1: Install `black` in virtual environment: `pip install flake8` + - Step 2: Open the Command Palette (`CMD + Shift + P`) → Search the “Python: Select Linter” and press enter. Select the “flake8” +- How to install `black`: + - Step 1: Install `black` in virtual environment: `pip install black` + - Step 2: Open the Command Palette (`CMD + Shift + P`) → “Preferences → Settings” + - Search “format on save” and check the checkbox + - Search “python formatting provider” and select the `black`. + - NOTE: can run black seperately `black -l 80 --preview src/youtube_statistics.py` +- How to install `isort`: + - Open the Command Palette (`CMD + Shift + P`). Search the “Preferences: Open User Settings (JSON)” and press enter. It will open the “settings.json” and add the follow code into that: + ```json + "editor.codeActionsOnSave": { + "source.organizeImports": true + } + ``` + +### Setup pre-commit using `git hooks` + +This is to ensure the code formatter, linting is running before the commit + +- install requirements-dev dependencies + +```sh +# requirements-dev.txt +flake8 +black +mypy +coverage +``` + +- add `hooksPath` into git config core: `git config --local core.hooksPath .git/hooks/` +- `pre-commit` file inside `.git/hooks/` + ```sh + # content inside pre-commit file + echo "Running lint.sh before commit" + bash lint.sh + echo "Linting completed" + ``` + - make pre-commit file executable via `chmod +x .git/hooks//pre-commit` +- Define the content in `lint.sh` + + ```sh + # content inside lint.sh + linting_path="." + echo "-------------Formatter with black-----------------" + black $linting_path --line-length=88 + + echo "-------------Linting with flake8-----------------" + flake8 $linting_path --max-line-length=88 --ignore=E203,W503,E231,E266,E722 + + echo "-------------Type checking with mypy-----------------" + mypy $linting_path --ignore-missing-imports + ``` + +### Setup pre-commit using `pre-commit` package + +- [Reading](https://medium.com/@anton-k./how-to-set-up-pre-commit-hooks-with-python-2b512290436) diff --git a/Readings/common_syntax.md b/docs/common_syntax.md similarity index 100% rename from Readings/common_syntax.md rename to docs/common_syntax.md diff --git a/docs/conda.md b/docs/conda.md new file mode 100644 index 0000000..00473c3 --- /dev/null +++ b/docs/conda.md @@ -0,0 +1,226 @@ +# Conda + +## What is Conda ? + +- Conda is an open source **package** + **environment** management system that runs on Windows, Mac OS and Linux. + - Conda as a _package manager_ helps you find and install packages. + - If you need a package that requires a different version of Python, you do not need to switch to a different environment manager, because Conda is also an _environment manager_. +- Conda was created for Python programs, Conda can package and distribute software for any language such as R, Ruby, Lua, Scala, Java, JavaScript, C, C++, FORTRAN + +### Pip vs Conda + +- **Pip**, which stands for **P**ip **I**nstalls **P**ackages, is Python's officially-sanctioned package manager, and is most commonly used to install packages published on the Python Package Index (PyPI). + - Both **pip** and **PyPI** are governed and supported by the Python Packaging Authority (PyPA). + - Pip installs Python software packaged as _wheels_ or _source_ distributions. + +#### Difference between Conda and Pip + +- Pip installs Python packages whereas Conda installs packages which may contain software written in any language. +- Conda has the ability to create **isolated environments** that can contain different versions of Python and/or the packages installed in them. + - This can be extremely useful when working with data science tools as different tools may contain conflicting requirements which could prevent them all being installed into a single environment. +- Pip has no built in support for environments but rather depends on other tools like `virtualenv`, `venv` to create isolated environments. +- When installing packages, pip installs dependencies in a _recursive_, serial loop. + - In contrast, conda uses a _satisfiability (SAT)_ solver to verify that all requirements of all packages installed in an environment are met. This check can take extra time but helps prevent the creation of broken environments. + +| | Conda | Pip | +| ------------------- | ---------------------------------------------------- | ------------------------------ | +| Package | pre-built, binary (faster) | wheels or source distributions | +| Package Source | Anaconda Cloud (can use pip if package is not avail) | PyPI | +| Package Languages | Any | Python only | +| Require compiled | No | Yes | +| Create isolated env | built-in | `virtualenv`, `venv` | +| Dependency Check | Yes | No | + +### Conda vs Virtualenv + +- `virtualenv/venv` are utilites that allow users to create isolated Python environments that work with pip. +- **Conda** has its own built-in environment manager that works seamlessly with both conda and pip, and in fact has several advantages over virtualenv/venv: + - conda environments integrate management of different Python versions, including installation and updating of Python itself. Virtualenvs must be created upon an existing, externally managed Python executable. + - conda environments can track non-python dependencies; for example seamlessly managing dependencies and parallel versions of essential tools like LAPACK or OpenSSL + - Rather than environments built on symlinks – which break the isolation of the virtualenv and can be flimsy at times for non-Python dependencies – conda-envs are true isolated environments within a single executable path. + - While virtualenvs are not compatible with conda packages, conda environments are entirely compatible with pip packages. First conda install pip, and then you can pip install any available package within that environment. You can even explicitly list pip packages in conda environment files, meaning the full software stack is entirely reproducible from a single environment metadata file. + +### Conda vs (Miniconda & Anaconda) + +- _Conda_ is a **package manager** + - A package manager is a tool that automates the process of installing, updating, and removing packages. + - _Conda_ is tightly coupled to two software distributions: _Anaconda_ and _Miniconda_. +- _Anaconda_ is a **software distribution** created by by Continuum Analytics. Although Conda is packaged with Anaconda, the two are distinct entities with distinct goals. + - A software distribution is a pre-built and pre-configured collection of packages that can be installed and used on a system. + +#### Anaconda vs Miniconda + +- Anaconda is a full distribution of the central software in the PyData ecosystem, and includes Python itself along with binaries for several hundred third-party open-source projects. +- Miniconda is essentially an installer for an empty conda environment, containing only Conda and its dependencies, so that you can install what you need from scratch. + +

+ +- **Rule of thumbs**: installing Miniconda which combines Conda with Python 3 + - If needs a particular version of the full Anaconda distribution you can always create an new conda environment with following command + +```shell +conda create --name anaconda-env-202302 anaconda=2023.02 +``` + +### Miniconda and Miniforge + +- `miniforge` is the **community** (`conda-forge`) driven minimalistic conda installer. Subsequent package installations come thus from conda-forge channel. +- `miniconda` is the **Anaconda** (company) driven minimalistic conda installer. Subsequent package installations come from the **anaconda channels** (default or otherwise). +- Summary: Both Miniforge and Miniconda are minimalistic conda installers, except that Miniforge uses the conda-forge channel (and only the conda-forge channel) as the default channel. + +### Conda Channel + +- A **channel** is the location where packages are stored remotely. +- To Check the default channels: `conda config --show channels` +- To Install a Package in Conda Using a Channel Name: `conda install -c conda-forge matplotlib` + - This is to install `matplotlib` via `conda-forge` channel + +#### `conda-forge` channel + +- There is a **community-led** effort (Conda-Forge) to make conda packaging & distribution entirely open. +- `conda-forge` that contains tools for the creation of community-driven builds for any package. Packages are maintained in the open via github, with binaries automatically built using free CI tools like TravisCI for Mac OSX builds, AppVeyor for Windows builds, and CircleCI for Linux builds. All the metadata for each package lives in a Github repository, and package updates are accomplished through merging a Github pull request (here is an example of what a package update looks like in conda-forge). + +## Why should you use Conda ? + +- Conda provides **pre-built** packages or binaries (which generally avoids the need to deal with compiling packages from source). + - TensorFlow is an example of a tool which is difficult to install source (particularly with GPU support), but that can be installed using Conda in a single step. +- Conda is cross platform, with support for Windows, MacOS, GNU/Linux, and support for multiple hardware platforms, such as x86 and Power 8 and 9. +- Where a library or tools is not already packaged for install using conda, Conda allows for using other package management tools (such as pip) inside Conda environments. +- Conda can quickly install commonly used data science libraries and tools, such as R, NumPy, SciPy, Scikit-learn, Dask, TensorFlow, PyTorch, Fast.ai, NVIDIA RAPIDS, and more built using optimized, hardware specific libraries (such as Intel’s MKL or NVIDIA’s CUDA), which provides a speedup without having to change any of your code. + +## Setup Conda on Macbook M2 + +- Download [Miniforge3 (Conda installer)](https://github.com/conda-forge/miniforge), namely [Miniforge3-MacOSX-arm64.sh](https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-MacOSX-arm64.sh), for macOS arm64 chips (M1, M1 Pro, M1 Max) +- Install Miniforge3 into home directory + - Installation Path: `/users//miniforge3` + - Run `conda init` (conda init code will be added to .zshrc) + - Restart Terminal + +### Config + +- Conda config will be stored in `~/.condarc` +- Show env name, instead of the entire path to env: + - `conda config --set env_prompt '({name})'` + - This above command is equivalent to add `env_prompt: '({name})'` to `.condarc` +- **Bug 1**: [environment duplication](https://github.com/microsoft/vscode-python/issues/22233?fbclid=IwAR1RimJUIENwStVLCyxOQLSWXsXdCK3aO5PYgSD9-N9i9ewXMwIIMx-vTtY) when open VS code terminal, conda init will be auto init the base env, and then after that VS code will activate the specific env of the project causing the terminal will have two env, say `(venv) (base) folder` + - _Solution_: disable the auto_activate_base env in `.condarc` with the follow commands + - `conda config --set auto_activate_base False` + +```shell +chmod +x ~/Downloads/Miniforge3-MacOSX-arm64.sh +sh ~/Downloads/Miniforge3-MacOSX-arm64.sh +source ~/miniforge3/bin/activate +``` + +- Verify installation: `conda info` + +## Conda commands + +- List all existing environments: `conda env list` +- `conda list` gives you list of packages used for the environment + +### Create environments + +#### `conda create` + +- `--name` or `-n` name of the env. + - If not specify `--prefix`, the new environment will be created by Conda at `/users//miniforge3/envs/` + +```shell +conda create --name env-name --file requirements.txt +conda activate env-name +conda deactivate +``` + +- `--prefix` custom env location (preferred) + +```shell +conda create --prefix ./venv python=3.8 --file requirements.txt +conda activate ./venv +conda deactivate +``` + +#### `conda env create` + +- `conda create --file` expects a `requirements.txt`, not an `environment.yml`, each line in the given file is treated as a package-reference +- `conda env create` to create an environment from a given `environment.yml` + - Command: `conda env create --name tensorflow --file environment.yml` + +#### Install from `requirements.txt` + +- `conda install --file requirements.txt` + +#### Export enviroment to `requirements.txt` for `pip` + +```shell +conda activate +conda install pip # only install if pip in conda env is not avail, can check which pip +pip list --format=freeze > requirements.txt +``` + +- Then use the resulting `requirements.txt` to create a `pip` virtual environment: + +```shell +python3 -m venv env +source env/bin/activate +pip install -r requirements.txt +``` + +- `--file` to specify the `environment.yml` + +#### `environment.yml` + +- duplicate your environment using **YAML file** `conda env export > my_environment.yml` +- to recreate the environment now use `conda create -f environment.yml` + - `tensorflow-deps` will need to be installed by `conda` via `apple` channel + - `scikit-learn` will be installed by `conda` via `conda-forge` channel + - `tensorflow-macos` will need `pip` install via **PyPI** + +```yaml +name: tensorflow +channels: + - apple + - conda-forge +dependencies: + - tensorflow-deps + - scikit-learn + - pip: + - tensorflow-macos + - tensorflow-metal +``` + +#### Tensorflow Setup MacOS M2 + +- Create env: + +```shell +conda create --prefix ./venv python=3.10 +conda activate ./venv +``` + +- Install TensorFlow dependencies from Apple Conda channel + +```shell +conda install -c apple tensorflow-deps +``` + +- Install TensorFlow Base (Apple's fork of TensorFlow is called tensorflow-macos) + +```shell +python -m pip install tensorflow-macos +``` + +- Install Apple's `tensorflow-metal` to leverage Apple Metal (Apple's GPU framework) for M1, M1 Pro, M1 Max GPU acceleration. + +```shell +python -m pip install tensorflow-metal +``` + +### Remove environments + +- `conda remove -n ENV_NAME --all` +- `conda remove -p /path/to/venv` + +## References + +- [Conda: Myths and Misconceptions](https://jakevdp.github.io/blog/2016/08/25/conda-myths-and-misconceptions/) diff --git a/docs/linux_commands.md b/docs/linux_commands.md new file mode 100644 index 0000000..8048a1c --- /dev/null +++ b/docs/linux_commands.md @@ -0,0 +1,109 @@ +# Linux Command + +## Special Variables + +### `$PATH` variable + +- Windows, macOS, and Linux all have a `$PATH` variable, which is a list of directories the OS will look in to find a program (using the `env` program) + - The `$PATH` variable is a way of telling your computer to only look in places where executable programs can be found. + - The directories are separated by colons (`:`). Notice that the directory where **python3** lives is the first one in `$PATH` + - The `$PATH` is located at `~/.bashrc` user's file or or `~/.zshrc` + +```bash + echo $PATH +/Users/quannguyen/repos/tiny_python_projects/venv/bin:/usr/local/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Library/Apple/usr/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin:/Applications/Visual Studio Code.app/Contents/Resources/app/bin +``` + +#### Altering your `$PATH` + +- Simply add the path where your program (script) is located to $PATH, You should now be able to execute the script anywhere on your system by just typing in its name, without having to include the full path as you type it. + +```bash +$ mkdir ~/bin # Use the mkdir (“make directory”) command to create ~/bin. +$ cp 01_hello/hello.py ~/bin # Use the cp command to copy the 01_hello/hello.py program to the ~/bin directory. +$ PATH=~/bin:$PATH # Put the ~/bin directory first in $PATH. +$ PATH=$PATH:~/bin # Put the ~/bin directory last in $PATH. +$ which hello.py # /home/quannguyen/bin/hello.py + +``` + +## Common Linux Commands +### `chmod` +- `chmod` make our program “executable” + - `+x` add an “executable” attribute to the file + +```bash +chmod +x hello.py # +x will add an “executable” attribute to the file + +# Now can run the program like +./hello.py +``` +### `echo` +- `echo` to print + +```bash +echo $USER +# quannguyen +echo $HOME +# /Users/quannguyen +``` + +### `export` +- `export` command sets an environment variable named **key** to the **value** +```bash +# This command sets an environment variable named AWS_DEFAULT_PROFILE to the value quannguyen. +export AWS_DEFAULT_PROFILE=quannguyen +``` +- To persist the environment variable so that it remains available even after you close the terminal, you can add the `export` command to + - If using Bash terinmal, Bash profile file (`~/.bashrc` or `~/.bash_profile`) + - If using Zsh terminal, Zsh configuration file (`~/.zshrc`) +```bash +# Open & add the following line at the end of the ~/.bashrc or ~/.zshrc file +export AWS_DEFAULT_PROFILE=quannguyen + +# Save the file and exit the text editor. To apply the changes, either open a new terminal session or run the following command to reload the profile: +source ~/.bashrc +source ~/.zshrc +``` + +### `env` +- `env` is the env program will tell you about your “environment.” + + - If you run `env` on your computer, you should see your login name and your home directory. + - use the `env ` command to find and run programs, say if we type`env python3`, the env program is looking for python3 in the environment. If Python has not been installed, it won’t be able to find it, but it’s also possible that Python has been installed more than once. +```bash +➜ ~ env python3 +Python 3.11.3 (v3.11.3:f3909b8bc8, Apr 4 2023, 20:12:10) [Clang 13.0.0 (clang-1300.0.29.30)] on darwin +Type "help", "copyright", "credits" or "license" for more information. +>>> +``` + +### shebang `#!` + +- It’s common to put a special comment line in programs like `#!/usr/bin/env python3` these to indicate which language needs to be used to execute the commands in the file. +- Below is the shebang you should add at the beginning of the file + +``` +#!/usr/bin/env python3 +``` + +- The shebang line tells the operating system to use the `env` program (located at `/usr/bin/env`) to find the **python3** that is specific to the machine on which it’s running. + + +### `which` +- `which` to see where the program is installed + +```bash +which env +# /usr/bin/env +which python3 +# /usr/local/bin/python3 +``` +## Daily Knowledge +### Day 1 + +- `du -sh` to find the size of the current folder +- `/dev/null1 file` which is a special device file that discards all data written to it + - `tail -f /dev/null` to keep a terminal session open but don't need any active process running in the background. +- `top` provides real-time monitoring of system resources and processes, to list down PID of each process + - `kill -9 1234` command isforcefully terminates the process, with **PID=1234** immediately, without giving it a chance to clean up or save any unsaved data. diff --git a/Readings/matplotlib.md b/docs/matplotlib.md similarity index 100% rename from Readings/matplotlib.md rename to docs/matplotlib.md diff --git a/Readings/numpy.md b/docs/numpy.md similarity index 100% rename from Readings/numpy.md rename to docs/numpy.md diff --git a/Readings/pandas.md b/docs/pandas.md similarity index 100% rename from Readings/pandas.md rename to docs/pandas.md diff --git a/docs/plotly.md b/docs/plotly.md new file mode 100644 index 0000000..44cad66 --- /dev/null +++ b/docs/plotly.md @@ -0,0 +1,101 @@ +# Plotly + +## Installation + +```Python +pip install plotly +``` + +## Plotly Express + +- Plotly Express is a high-level interface for creating various types of plots easily. + +```Python +import plotly.express as px +fig = px.bar(x=["a", "b", "c"], y=[1, 3, 2]) +fig.show() +``` + +## Plotly Graph Objects + +### Single Plot + +```Python +import plotly.graph_objects as go + +# define the fig object +fig = go.Figure() +# add multiple line into the fig object +fig.add_trace(go.Scatter(x=data_train.index, y=data_train['users'], mode='lines', name='Train')) +fig.add_trace(go.Scatter(x=data_val.index, y=data_val['users'], mode='lines', name='Validation')) +fig.add_trace(go.Scatter(x=data_test.index, y=data_test['users'], mode='lines', name='Test')) +fig.update_layout( + title = 'Number of users', + xaxis_title="Time", + yaxis_title="Users", + legend_title="Partition:", + width=800, + height=350, + margin=dict(l=20, r=20, t=35, b=20), + legend=dict( + orientation="h", + yanchor="top", + y=1, + xanchor="left", + x=0.001 + ) +) +#fig.update_xaxes(rangeslider_visible=True) +fig.show() +``` + +### Subplots + +- `make_subplots` function from `plotly.subplots` is to create the subplots. +- In the below example, `make_subplots()` creates the figure `fig` with 2 rows and 1 column. + - `fig.add_trace()` function to add two traces to the figure, one for stock price data and one for volume data. + - `go.Ohlc()` function creates an interactive candlestick chart based on stock price data + - `go.Scatter()` function is used to plot the volume data + - By `setting layout_xaxis_rangeslider_visible` to `False`, the update() function modifies the layout of the plot to get rid of the range slider for the x-axis. + +```Python +import plotly.graph_objs as go +from plotly.subplots import make_subplots + +# Define the range for cropping the x-axis +start_date = '2021-01-10' +end_date = '2021-01-20' + +# Create subplots +# shared_xaxes=True to help crop both plots at the same time. +fig = make_subplots(rows=2, cols=1, shared_xaxes=True) + +# Add OHLC plot at row=1, col=1 +fig.add_trace( + go.Ohlc( + x=df["Date"], + open=df["Open"],high=df["High"],low=df["Low"],close=df["Close"], + name="Price" + ), + row=1, col=1 # specify the plot order row=1, col=1 +) + +# Add Volume scatter plot at row=2, col=1 +fig.add_trace( + go.Scatter( + x=df["Date"], y=df["Volume"], + name="Volume" + ), + row=2, col=1 # specify the plot order row=2, col=1 +) + +# Update x-axes range +fig.update_xaxes(range=[start_date, end_date]) + +# Hide the rangeslider +fig.update(layout_xaxis_rangeslider_visible=False) + +fig.show() +``` + +

diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f434a2a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,9 @@ +attrs +black +folium +pydantic +pygeohash +pyaml +tqdm +librosa +wandb