Skip to content

Commit 340b2c2

Browse files
authored
Create solution1.ipynb
1 parent 92d0558 commit 340b2c2

File tree

1 file changed

+392
-0
lines changed

1 file changed

+392
-0
lines changed

notebook/solution1.ipynb

Lines changed: 392 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,392 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "27b09e13",
6+
"metadata": {},
7+
"source": [
8+
"# Algorithm Optimization Solutions"
9+
]
10+
},
11+
{
12+
"cell_type": "markdown",
13+
"id": "ed05e9bf",
14+
"metadata": {},
15+
"source": [
16+
"## Exercise 1\n",
17+
"\n",
18+
"Suppose a manager gives a task to two of his employees to design an algorithm in Python that efficiently compute sums of diagonals of a matrix.\n",
19+
"\n",
20+
"For example:\n",
21+
"\n",
22+
"```py\n",
23+
"Input : \n",
24+
"\n",
25+
"\n",
26+
"1 2 3 4\n",
27+
"4 3 2 1\n",
28+
"7 8 9 6\n",
29+
"6 5 4 3\n",
30+
"\n",
31+
"Output :\n",
32+
"\n",
33+
"Principal Diagonal: 16\n",
34+
"Secondary Diagonal: 20\n",
35+
"```\n",
36+
"\n",
37+
"The primary diagonal is formed by the elements 1,3,9,3. \n",
38+
" \n",
39+
"\n",
40+
"Condition for Principal Diagonal: The row-column condition is row = column. \n",
41+
"\n",
42+
"The secondary diagonal is formed by the elements 4,2,8,6.\n",
43+
"\n",
44+
"Condition for Secondary Diagonal: The row-column condition is row = number Of Rows – column -1.\n",
45+
"\n",
46+
"The algorithm developed by the first employee looks like this:"
47+
]
48+
},
49+
{
50+
"cell_type": "markdown",
51+
"id": "8f18cb2f",
52+
"metadata": {},
53+
"source": [
54+
"**Method 1:**\n",
55+
"\n",
56+
"In this method, he used two loops. A loop for columns and a loop for rows and in the inner loop we check for the condition stated above."
57+
]
58+
},
59+
{
60+
"cell_type": "code",
61+
"execution_count": 2,
62+
"id": "c592f03c",
63+
"metadata": {},
64+
"outputs": [
65+
{
66+
"name": "stdout",
67+
"output_type": "stream",
68+
"text": [
69+
"Principal Diagonal: 18\n",
70+
"Secondary Diagonal: 18\n"
71+
]
72+
}
73+
],
74+
"source": [
75+
"# A simple Python program to\n",
76+
"# find sum of diagonals\n",
77+
"MAX = 100\n",
78+
" \n",
79+
"def DiagonalSums_emp1(mat, n):\n",
80+
" \n",
81+
" principal = 0\n",
82+
" secondary = 0;\n",
83+
" for i in range(0, n):\n",
84+
" for j in range(0, n):\n",
85+
" \n",
86+
" # Condition for principal diagonal\n",
87+
" if (i == j):\n",
88+
" principal += mat[i][j]\n",
89+
" \n",
90+
" # Condition for secondary diagonal\n",
91+
" if ((i + j) == (n - 1)):\n",
92+
" secondary += mat[i][j]\n",
93+
" \n",
94+
" print(\"Principal Diagonal:\", principal)\n",
95+
" print(\"Secondary Diagonal:\", secondary)\n",
96+
" \n",
97+
" \n",
98+
"a = [[ 1, 2, 3, 4 ],\n",
99+
" [ 5, 6, 7, 8 ],\n",
100+
" [ 1, 2, 3, 4 ],\n",
101+
" [ 5, 6, 7, 8 ]]\n",
102+
"\n",
103+
"DiagonalSums_emp1(a, 4)\n",
104+
" \n",
105+
"# This code is contributed\n",
106+
"# by ihritik"
107+
]
108+
},
109+
{
110+
"cell_type": "markdown",
111+
"id": "4f0567be",
112+
"metadata": {},
113+
"source": [
114+
"The algorithm developed by the second employee looks like this:\n",
115+
"\n",
116+
"**Method 2:**\n",
117+
"\n",
118+
"In this method we use one loop. A loop for calculating sum of both the principal and secondary diagonals: "
119+
]
120+
},
121+
{
122+
"cell_type": "code",
123+
"execution_count": 3,
124+
"id": "0ca5e0a5",
125+
"metadata": {},
126+
"outputs": [
127+
{
128+
"name": "stdout",
129+
"output_type": "stream",
130+
"text": [
131+
"Principal Diagonal: 18\n",
132+
"Secondary Diagonal: 18\n"
133+
]
134+
}
135+
],
136+
"source": [
137+
"# A simple Python3 program to find\n",
138+
"# sum of diagonals\n",
139+
"\n",
140+
"MAX = 100\n",
141+
" \n",
142+
"def DiagonalSums_emp2(mat, n):\n",
143+
" \n",
144+
" principal = 0\n",
145+
" secondary = 0\n",
146+
" for i in range(0, n):\n",
147+
" principal += mat[i][i]\n",
148+
" secondary += mat[i][n - i - 1]\n",
149+
" \n",
150+
" print(\"Principal Diagonal:\", principal)\n",
151+
" print(\"Secondary Diagonal:\", secondary)\n",
152+
" \n",
153+
"\n",
154+
"a = [[ 1, 2, 3, 4 ],\n",
155+
" [ 5, 6, 7, 8 ],\n",
156+
" [ 1, 2, 3, 4 ],\n",
157+
" [ 5, 6, 7, 8 ]]\n",
158+
"\n",
159+
"DiagonalSums_emp2(a, 4)\n",
160+
" \n",
161+
"# This code is contributed\n",
162+
"# by ihritik"
163+
]
164+
},
165+
{
166+
"cell_type": "markdown",
167+
"id": "afbd2b33",
168+
"metadata": {},
169+
"source": [
170+
"\n",
171+
"The manager has to decide which algorithm to use. To do so, he has to find the complexity of the algorithm. A good algorithm doesn't only find an answer, it finds it quickly and efficiently. But how do we evaluate how fast an algorithm is? One way to do so is by finding the time required to execute the algorithms. We can measure\n",
172+
"\n",
173+
"The %time command times a single run of a function. Here is an example on how it is used:\n",
174+
"\n",
175+
"```py\n",
176+
"In [3]: %time sum(range(100000))\n",
177+
"CPU times: user 2.68 ms, sys: 3 µs, total: 2.68 ms\n",
178+
"Wall time: 2.69 ms\n",
179+
"Out[3]: 4999950000\n",
180+
"```\n",
181+
"\n",
182+
"We can also use the time library:\n",
183+
"\n",
184+
"```py\n",
185+
"import time\n",
186+
"\n",
187+
"start = time.time()\n",
188+
"# your code\n",
189+
"# end\n",
190+
"print(f'Time: {time.time() - start}')\n",
191+
"```\n",
192+
"\n",
193+
"**Find the time required to execute each of the algorithms**"
194+
]
195+
},
196+
{
197+
"cell_type": "code",
198+
"execution_count": 11,
199+
"id": "929cef16",
200+
"metadata": {},
201+
"outputs": [
202+
{
203+
"name": "stdout",
204+
"output_type": "stream",
205+
"text": [
206+
"Principal Diagonal: 18\n",
207+
"Secondary Diagonal: 18\n",
208+
"CPU times: total: 0 ns\n",
209+
"Wall time: 0 ns\n"
210+
]
211+
}
212+
],
213+
"source": [
214+
"#TIME REQUIRED TO EXECUTE ALGORITHM BUILT BY THE FIRST EMPLOYEE\n",
215+
"#USING %time\n",
216+
"\n",
217+
"a = [[ 1, 2, 3, 4 ],\n",
218+
" [ 5, 6, 7, 8 ],\n",
219+
" [ 1, 2, 3, 4 ],\n",
220+
" [ 5, 6, 7, 8 ]]\n",
221+
"\n",
222+
"%time DiagonalSums_emp1(a, 4)"
223+
]
224+
},
225+
{
226+
"cell_type": "code",
227+
"execution_count": 16,
228+
"id": "82a7f066",
229+
"metadata": {},
230+
"outputs": [
231+
{
232+
"name": "stdout",
233+
"output_type": "stream",
234+
"text": [
235+
"Principal Diagonal: 18\n",
236+
"Secondary Diagonal: 18\n",
237+
"Time: 0.0\n"
238+
]
239+
}
240+
],
241+
"source": [
242+
"#USING TIME LIBRARY\n",
243+
"\n",
244+
"import time\n",
245+
"\n",
246+
"start = time.time()\n",
247+
"\n",
248+
"DiagonalSums_emp1(a, 4)\n",
249+
"\n",
250+
"print(f'Time: {time.time() - start}')"
251+
]
252+
},
253+
{
254+
"cell_type": "code",
255+
"execution_count": 17,
256+
"id": "8c8185a8",
257+
"metadata": {},
258+
"outputs": [
259+
{
260+
"name": "stdout",
261+
"output_type": "stream",
262+
"text": [
263+
"Principal Diagonal: 18\n",
264+
"Secondary Diagonal: 18\n",
265+
"CPU times: total: 0 ns\n",
266+
"Wall time: 0 ns\n"
267+
]
268+
}
269+
],
270+
"source": [
271+
"#TIME REQUIRED TO EXECUTE ALGORITHM BUILT BY THE SECOND EMPLOYEE\n",
272+
"#Using %time\n",
273+
"\n",
274+
"a = [[ 1, 2, 3, 4 ],\n",
275+
" [ 5, 6, 7, 8 ],\n",
276+
" [ 1, 2, 3, 4 ],\n",
277+
" [ 5, 6, 7, 8 ]]\n",
278+
"\n",
279+
"%time DiagonalSums_emp2(a, 4)"
280+
]
281+
},
282+
{
283+
"cell_type": "code",
284+
"execution_count": 18,
285+
"id": "c9141778",
286+
"metadata": {},
287+
"outputs": [
288+
{
289+
"name": "stdout",
290+
"output_type": "stream",
291+
"text": [
292+
"Principal Diagonal: 18\n",
293+
"Secondary Diagonal: 18\n",
294+
"Time: 0.0\n"
295+
]
296+
}
297+
],
298+
"source": [
299+
"#USING TIME LIBRARY\n",
300+
"\n",
301+
"import time\n",
302+
"\n",
303+
"start = time.time()\n",
304+
"\n",
305+
"DiagonalSums_emp2(a, 4)\n",
306+
"\n",
307+
"print(f'Time: {time.time() - start}')"
308+
]
309+
},
310+
{
311+
"cell_type": "markdown",
312+
"id": "d66bad41",
313+
"metadata": {},
314+
"source": [
315+
"However, execution time is not a good metric to measure the complexity of an algorithm since it depends upon the hardware. A more objective complexity analysis metrics for the algorithms is needed. This is where Big O notation comes to play.\n",
316+
"\n",
317+
"As we already know, the complexity of an algorithm is said to :\n",
318+
"\n",
319+
"Constant if:\n",
320+
"\n",
321+
"The steps required to complete the execution of an algorithm remain constant, irrespective of the number of inputs. The constant complexity is denoted by O(c) where c can be any constant number.\n",
322+
"\n",
323+
"Linear if:\n",
324+
"\n",
325+
"The steps required to complete the execution of an algorithm increase or decrease linearly with the number of inputs. Linear complexity is denoted by O(n). For instance, if there are 4 inputs in the inputs list, the for-loop will be executed 4 times, and so on.\n",
326+
"\n",
327+
"Quadratic if:\n",
328+
"\n",
329+
"The steps required to execute an algorithm are a quadratic function of the number of items in the input. Quadratic complexity is denoted as O(n^2). The total number of steps performed is n * n, where n is the number of items in the input array.\n",
330+
"\n",
331+
"Find out the complexity of each algorithm in Big O Notation and draw a line plot with the varying size of the items input on the x-axis and the number of steps on the y-axis."
332+
]
333+
},
334+
{
335+
"cell_type": "markdown",
336+
"id": "415eab09",
337+
"metadata": {},
338+
"source": [
339+
"**Answer:**\n",
340+
"\n",
341+
"The first employee implemented an algorithm with a time complexity of O(n^2) \n",
342+
"\n",
343+
"The second employee implemented an algorithm with a time complexity of O(n)"
344+
]
345+
},
346+
{
347+
"cell_type": "markdown",
348+
"id": "b281af6e",
349+
"metadata": {},
350+
"source": [
351+
"Source:\n",
352+
"\n",
353+
"https://www.geeksforgeeks.org/\n",
354+
"\n",
355+
"https://stackabuse.com/big-o-notation-and-algorithm-analysis-with-python-examples/\n",
356+
"\n",
357+
"https://stackabuse.com/quicksort-in-python/\n",
358+
"\n",
359+
"https://stackabuse.com/k-nearest-neighbors-algorithm-in-python-and-scikit-learn/"
360+
]
361+
}
362+
],
363+
"metadata": {
364+
"interpreter": {
365+
"hash": "9248718ffe6ce6938b217e69dbcc175ea21f4c6b28a317e96c05334edae734bb"
366+
},
367+
"kernelspec": {
368+
"display_name": "Python 3.9.12 ('ML-BOOTCAMP')",
369+
"language": "python",
370+
"name": "python3"
371+
},
372+
"language_info": {
373+
"codemirror_mode": {
374+
"name": "ipython",
375+
"version": 3
376+
},
377+
"file_extension": ".py",
378+
"mimetype": "text/x-python",
379+
"name": "python",
380+
"nbconvert_exporter": "python",
381+
"pygments_lexer": "ipython3",
382+
"version": "3.9.12"
383+
},
384+
"vscode": {
385+
"interpreter": {
386+
"hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6"
387+
}
388+
}
389+
},
390+
"nbformat": 4,
391+
"nbformat_minor": 5
392+
}

0 commit comments

Comments
 (0)