diff --git a/exercises/numpy_broadcasting/broadcasting.ipynb b/exercises/numpy_broadcasting/broadcasting.ipynb
new file mode 100644
index 0000000..c89a8e9
--- /dev/null
+++ b/exercises/numpy_broadcasting/broadcasting.ipynb
@@ -0,0 +1,344 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "6cd0f8cf",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# Broadcasting exercises"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "282817dd",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T20:08:23.900532Z",
+ "start_time": "2023-06-27T20:08:22.963157Z"
+ },
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "acba732f",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Exercise 1\n",
+ "\n",
+ "```\n",
+ "What is the expected output shape for each operation?\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "a41d0f74",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.881059Z",
+ "start_time": "2023-06-27T19:58:57.830Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "a = np.arange(5)\n",
+ "b = 5\n",
+ "\n",
+ "np.shape(a - b)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "6f82a2fb",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.884966Z",
+ "start_time": "2023-06-27T19:58:57.833Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "a = np.ones((7, 1))\n",
+ "b = np.arange(7)\n",
+ "np.shape(a * b)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "808095ad",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.888119Z",
+ "start_time": "2023-06-27T19:58:57.836Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "a = np.random.randint(0, 50, (2, 3, 3))\n",
+ "b = np.random.randint(0, 10, (3, 1))\n",
+ "\n",
+ "np.shape(a - b)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "d9a12a90",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.891462Z",
+ "start_time": "2023-06-27T19:58:57.839Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "a = np.arange(100).reshape(10, 10)\n",
+ "b = np.arange(0, 10)\n",
+ "\n",
+ "np.shape(a + b)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "69632f95",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Exercise 2\n",
+ "\n",
+ "```\n",
+ "1. Create a random 2D array of dimension (5, 3)\n",
+ "2. Calculate the maximum value of each row\n",
+ "3. Divide each row by its maximum\n",
+ "```\n",
+ "\n",
+ "Remember to use broadcasting : NO FOR LOOPS!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "54e2a53e",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.894433Z",
+ "start_time": "2023-06-27T19:58:57.843Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "## Your code here"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b9facc0f",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Exercise 3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7e8156d0",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Task: Find the closest **cluster** to the **observation**. \n",
+ "\n",
+ "Again, use broadcasting: DO NOT iterate cluster by cluster"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "2969994e",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.899204Z",
+ "start_time": "2023-06-27T19:58:57.847Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "observation = np.array([30.0, 99.0]) #Observation\n",
+ "\n",
+ "#Clusters\n",
+ "clusters = np.array([\n",
+ " [102.0, 203.0],\n",
+ " [132.0, 193.0],\n",
+ " [45.0, 155.0], \n",
+ " [57.0, 173.0]\n",
+ "])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f13352ff",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Let's plot this data\n",
+ "\n",
+ "In the plot below, **+** is the observation and dots are the cluster coordinates"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "b9f6b5cf",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.906715Z",
+ "start_time": "2023-06-27T19:58:57.850Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import matplotlib.pyplot as plt \n",
+ "\n",
+ "plt.scatter(clusters[:, 0], clusters[:, 1]) #Scatter plot of clusters\n",
+ "for n, x in enumerate(clusters):\n",
+ " print('cluster %d' %n)\n",
+ " plt.annotate('cluster%d' %n, (x[0], x[1])) #Label each cluster\n",
+ "plt.plot(observation[0], observation[1], 'r+'); #Plot observation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4f9b84e2",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Closest cluster as seen in the plot is **2**. Your task is to write a function to calculate this"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8aea6781",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-26T19:25:08.202848Z",
+ "start_time": "2023-06-26T19:25:08.194923Z"
+ }
+ },
+ "source": [
+ "\n",
+ "**hint:** Find the distance between the observation and each row in the cluster. The cluster to which the observation belongs to is the row with the minimum distance.\n",
+ "\n",
+ "distance = $\\sqrt {\\left( {x_1 - x_2 } \\right)^2 + \\left( {y_1 - y_2 } \\right)^2 }$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "id": "ea8a7240",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.916610Z",
+ "start_time": "2023-06-27T19:58:57.854Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "## Your code here"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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"
+ },
+ "rise": {
+ "scroll": true
+ },
+ "toc": {
+ "base_numbering": 1,
+ "nav_menu": {},
+ "number_sections": true,
+ "sideBar": true,
+ "skip_h1_title": false,
+ "title_cell": "Table of Contents",
+ "title_sidebar": "Contents",
+ "toc_cell": false,
+ "toc_position": {},
+ "toc_section_display": true,
+ "toc_window_display": false
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}
diff --git a/exercises/numpy_broadcasting/broadcasting_solutions.ipynb b/exercises/numpy_broadcasting/broadcasting_solutions.ipynb
new file mode 100644
index 0000000..623fe7c
--- /dev/null
+++ b/exercises/numpy_broadcasting/broadcasting_solutions.ipynb
@@ -0,0 +1,510 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "id": "6cd0f8cf",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "# Broadcasting exercises"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "id": "282817dd",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T20:08:23.900532Z",
+ "start_time": "2023-06-27T20:08:22.963157Z"
+ },
+ "slideshow": {
+ "slide_type": "skip"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "import numpy as np"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "acba732f",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Exercise 1\n",
+ "\n",
+ "```\n",
+ "What is the expected output shape for each operation?\n",
+ "```"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "id": "a41d0f74",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.881059Z",
+ "start_time": "2023-06-27T19:58:57.830Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(5,)"
+ ]
+ },
+ "execution_count": 2,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a = np.arange(5)\n",
+ "b = 5\n",
+ "\n",
+ "np.shape(a - b)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "id": "6f82a2fb",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.884966Z",
+ "start_time": "2023-06-27T19:58:57.833Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(7, 7)"
+ ]
+ },
+ "execution_count": 3,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a = np.ones((7, 1))\n",
+ "b = np.arange(7)\n",
+ "np.shape(a * b)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "id": "808095ad",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.888119Z",
+ "start_time": "2023-06-27T19:58:57.836Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(2, 3, 3)"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a = np.random.randint(0, 50, (2, 3, 3))\n",
+ "b = np.random.randint(0, 10, (3, 1))\n",
+ "\n",
+ "np.shape(a - b)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "id": "d9a12a90",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.891462Z",
+ "start_time": "2023-06-27T19:58:57.839Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(10, 10)"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "a = np.arange(100).reshape(10, 10)\n",
+ "b = np.arange(0, 10)\n",
+ "\n",
+ "np.shape(a + b)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "69632f95",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Exercise 2\n",
+ "\n",
+ "```\n",
+ "1. Create a random 2D array of dimension (5, 3)\n",
+ "2. Calculate the maximum value of each row\n",
+ "3. Divide each row by its maximum\n",
+ "```\n",
+ "\n",
+ "Remember to use broadcasting : NO FOR LOOPS!"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "id": "ad362a83-4821-4146-b4bc-c781bb31c714",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.894433Z",
+ "start_time": "2023-06-27T19:58:57.843Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([[0.04512288, 0.29887872, 0.71583331],\n",
+ " [0.96876287, 0.89086747, 0.53374129],\n",
+ " [0.80630616, 0.05463225, 0.23587356],\n",
+ " [0.12837335, 0.29644576, 0.71527555],\n",
+ " [0.0672898 , 0.99300472, 0.49310665]])"
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "x = np.random.random((5,3))\n",
+ "x"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "id": "395a6807-e826-4301-9f13-f15c0e4e2e11",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([[0.06303546, 0.41752558, 1. ],\n",
+ " [1. , 0.91959291, 0.55095143],\n",
+ " [1. , 0.06775621, 0.29253598],\n",
+ " [0.17947398, 0.41444974, 1. ],\n",
+ " [0.06776383, 1. , 0.49658036]])"
+ ]
+ },
+ "execution_count": 7,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "m = x.max(axis=1)\n",
+ "y = x / m[:, None]\n",
+ "y"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "id": "a94ef9c2-4efc-4d03-be10-7e1e9681addd",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([[1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.],\n",
+ " [1.]])"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "# check\n",
+ "y.max(axis=1)[:, None]"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "b9facc0f",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "slide"
+ }
+ },
+ "source": [
+ "### Exercise 3"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "7e8156d0",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Task: Find the closest **cluster** to the **observation**. \n",
+ "\n",
+ "Again, use broadcasting: DO NOT iterate cluster by cluster"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "id": "2969994e",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.899204Z",
+ "start_time": "2023-06-27T19:58:57.847Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [],
+ "source": [
+ "observation = np.array([30.0, 99.0]) #Observation\n",
+ "\n",
+ "#Clusters\n",
+ "clusters = np.array([\n",
+ " [102.0, 203.0],\n",
+ " [132.0, 193.0],\n",
+ " [45.0, 155.0], \n",
+ " [57.0, 173.0]\n",
+ "])"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "f13352ff",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Let's plot this data\n",
+ "\n",
+ "In the plot below, **+** is the observation and dots are the cluster coordinates"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "id": "b9f6b5cf",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.906715Z",
+ "start_time": "2023-06-27T19:58:57.850Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "cluster 0\n",
+ "cluster 1\n",
+ "cluster 2\n",
+ "cluster 3\n"
+ ]
+ },
+ {
+ "data": {
+ "image/png": "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+N643Sv820tszCAB32rVTFJ+fr5uuukmhYeHq1evXrr77rt93905wzAMzZs3T06nU127dtWwYcO0d+9evzput1vTp09Xz549FRYWpszMTFVVVQXmiAAAF80aZNGP+0fprqF99OP+UQQk4CytCklbt27VE088oQ8++ECbNm3SN998o1GjRvm9TGzRokV6+eWXVVBQoJ07d8rhcOi2225TfX29r05OTo5KSkpUXFysbdu2qaGhQWPHjm3xYjEAAID2clmvAPj73/+uXr16aevWrbrllltkGIacTqdycnL01FNPSadnjWJiYrRw4UI9+uijcrlcio6O1ooVK5SVlSVJOnbsmGJjY7V+/XqNHj36O3+3oz1CCAAAOt75+7Ju3Ha5XNLpl4pJUmVlpWpqajRq1ChfHZvNpltvvVXbt2+XJJWVlcnj8fjVcTqdSkxM9NU5l9vtVl1dnd8CAADQli45JBmGoZkzZyojI0OJiYmS5Pu44LkfFIyJifFtq6mpUWhoqHr06HHeOufKz8+X3W73Ld/15lUAAIDLdckhadq0afrrX/+q1atXt9h27teZDcNoUXauC9XJy8uTy+XyLUeOHLnUbgMAAFyUSwpJ06dP1xtvvKEtW7aob9++vvIzX2k+d0aotrbWN7vkcDjU1NSk48ePn7fOuWw2myIiIvwWAACAttSqkGQYhqZNm6Y1a9bo3XffVXx8vN/2+Ph4ORwObdq0yVfW1NSkrVu3Kj09XZKUmpqqkJAQvzrV1dXas2ePrw4AAEB7a9XLJJ944gmtWrVKr7/+usLDw30zRna7XV27dpXFYlFOTo4WLFiggQMHauDAgVqwYIG6deumSZMm+eo+/PDDmjVrlqKiohQZGanZs2crKSlJI0eObJujBAAAaKVWhaRly5ZJkoYNG+ZXXlhYqH/913+VJM2ZM0eNjY16/PHHdfz4caWlpWnjxo0KDw/31V+8eLGCg4M1YcIENTY2asSIESoqKpLVag3MUQEAAFymy3pPUnvpaO9ZAAAAHe/8zQduAQAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAABAqx08eFAWi0UVFRXt3ZU2Q0gCAADtrqioSN27dw9Ye3v37tW9996rfv36yWKxaMmSJa1ug5AEAACuGM3NzfJ6vTp58qSuueYavfDCC75vy7YWIQkAAJyX1+vVwoUL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XlNTo9DQUPXo0cOvPCYmRjU1Nab75Ofny263+5bY2NhAdxsAAMBPQENSWVmZXnnlFRUVFclisbRqX8MwzrtPXl6eXC6Xbzly5EiAegwAAGAuoCHpz3/+s2praxUXF6fg4GAFBwfr0KFDmjVrlvr16ydJcjgcampq0vHjx/32ra2tVUxMjGm7NptNERERfgsAAEBbCmhIeuihh/TXv/5VFRUVvsXpdCo3N1d/+tOfJEmpqakKCQnRpk2bfPtVV1drz549Sk9PD2R3AAAALlmrn25raGjQgQMHfOuVlZWqqKhQZGSk4uLiFBUV5Vc/JCREDodD1157rSTJbrfr4Ycf1qxZsxQVFaXIyEjNnj1bSUlJvqfdAAAA2lurQ9JHH32k4cOH+9ZnzpwpSZoyZYqKioouqo3FixcrODhYEyZMUGNjo0aMGKGioiJZrdbWdgcAAKBNWAzDMNq7E61VV1cnu90ul8vF/UkAAHQQHe38zbfbAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATBCSAAAATLQ6JL333nsaN26cnE6nLBaL1q5d69vm8Xj01FNPKSkpSWFhYXI6ncrOztaxY8f82nC73Zo+fbp69uypsLAwZWZmqqqqKjBHBAAAEACtDkknTpxQcnKyCgoKWmw7efKkysvL9eyzz6q8vFxr1qzR/v37lZmZ6VcvJydHJSUlKi4u1rZt29TQ0KCxY8equbn58o4GAAAgQCyGYRiXvLPFopKSEt19993nrbNz507dfPPNOnTokOLi4uRyuRQdHa0VK1YoKytLknTs2DHFxsZq/fr1Gj169Hf+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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import matplotlib.pyplot as plt \n",
+ "\n",
+ "plt.scatter(clusters[:, 0], clusters[:, 1]) #Scatter plot of clusters\n",
+ "for n, x in enumerate(clusters):\n",
+ " print('cluster %d' %n)\n",
+ " plt.annotate('cluster%d' %n, (x[0], x[1])) #Label each cluster\n",
+ "plt.plot(observation[0], observation[1], 'r+'); #Plot observation"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "4f9b84e2",
+ "metadata": {
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "source": [
+ "Closest cluster as seen in the plot is **2**. Your task is to write a function to calculate this"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "id": "8aea6781",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-26T19:25:08.202848Z",
+ "start_time": "2023-06-26T19:25:08.194923Z"
+ }
+ },
+ "source": [
+ "\n",
+ "**hint:** Find the distance between the observation and each row in the cluster. The cluster to which the observation belongs to is the row with the minimum distance.\n",
+ "\n",
+ "distance = $\\sqrt {\\left( {x_1 - x_2 } \\right)^2 + \\left( {y_1 - y_2 } \\right)^2 }$"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 11,
+ "id": "fe168c3e-fa25-4196-8839-c2b7ffd52f7e",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "np.int64(2)"
+ ]
+ },
+ "execution_count": 11,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "np.argmin( np.sqrt( np.sum((clusters - observation)**2, axis=1) ) )"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 12,
+ "id": "ea8a7240",
+ "metadata": {
+ "ExecuteTime": {
+ "end_time": "2023-06-27T19:58:58.916610Z",
+ "start_time": "2023-06-27T19:58:57.854Z"
+ },
+ "slideshow": {
+ "slide_type": "fragment"
+ }
+ },
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "np.int64(2)"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "(clusters - observation).__pow__(2).sum(axis=1).__pow__(0.5).argmin()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "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.13.4"
+ },
+ "rise": {
+ "scroll": true
+ },
+ "toc": {
+ "base_numbering": 1,
+ "nav_menu": {},
+ "number_sections": true,
+ "sideBar": true,
+ "skip_h1_title": false,
+ "title_cell": "Table of Contents",
+ "title_sidebar": "Contents",
+ "toc_cell": false,
+ "toc_position": {},
+ "toc_section_display": true,
+ "toc_window_display": false
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 5
+}