Mutex in C++ (Critical Section Problem Part-2)

So critical section is a block of code, where threads/processes access the shared resources/variables. So to avoid inconsistencies, at a time only one thread must be able to access the critical section. 

If one thread is executing in the critical section, another thread should wait until thread one completes its execution. 

The process where at a time only one thread executes in the critical section is called mutual exclusion. It is one of the conditions to avoid the deadlock. We will learn about deadlock at the later stage of this course. 

So let’s recap the previous tutorial. At lines number 9 and 10, both the threads t1 and t2 were accessing the shared variable x simultaneously. It is the reason we get different values as output. So we have to block thread t1 if t2 is accessing this code and vice versa. 

One of the solutions to handle this situation is a mutex. 

Mutex is a mutual exclusion object to synchronizes access to the resources. A mutex has two states, 

  1. acquire(thread acquires the mutex) 
  2. release(thread release the mutex)

Mutex acquired by one thread/process can only be released by the same thread/process.

Let’s understand it with the previous example:

#include<iostream>
#include<thread>
using namespace std;

int x = 0;
std::mutex m;

void function1()
{
	//acquire the lock
	m.lock();

	//critical section code
	x = 2;
	x = x+1;

	//release the lock
	m.unlock();

}
int main()
{
	std::thread t1(function1);
	std::thread t2(function1);
	
	if(t1.joinable())
	{
		t1.join();
	}

	if(t2.joinable())
	{
		t2.join();
	}

	cout<<"Values of x:\t"<<x<<endl;

	return 0;
}

You can run the code using below command:

g++ -std=c++14 -pthread multithreadingProblem.cpp
./a.out

Output of the code:

Values of x:	3

Let’s understand, how the code is working:

At line number 6, we are defining the mutex variable m. By default the mutex variable is unlock, means any thread can acquire it initially. So let suppose thread t1 calls the function1, and acquire the mutex m at line number 11. At the same time, context switch takes place and thread t2 starts executing, and reaches at line number 11. When it tries to acquire the mutex, it comes to know that it has already been acquired by thread t1. So it wait until thread t1 releases the lock at line number 18. As soon as mutex is released by thread t1, t2 starts executing in the critical section(Just reverse will take place when t2 calls the function1 first). Thus we ensure that at a time only single thread executes in the critical section and avoid the ambiguous output.

Properties of Mutex:

  1. At a time, only one thread can acquire the mutex.
  2. mutex will be released by same thread which has acquired it.
  3. It is a mechanism to ensure that at a time only one thread executes in the critical section.
  4. lock and unlock are the atomic operations i.e. no context switch will take place during either of the operations.
Posted in C++

Problem with Multithreading (Critical Section Problem Part-1):

Goal: In this article, we will see what are the problems associated with multithreading.

We will take a function with name functionWithCriticalSection, and two threads t1, t2 will call this function.

Let’s see the code:

#include<iostream>
#include<thread>
using namespace std;

int x = 0;

void functionWithCriticalSection()
{
//this is the critical section
	x = 2;
	x = x+1;
}

int main()
{

	std::thread t1(functionWithCriticalSection);
	std::thread t2(functionWithCriticalSection);
	
	if(t1.joinable())
	{
		t1.join();
	}

	if(t2.joinable())
	{
		t2.join();
	}

	cout<<"Values of x:\t"<<x<<endl;

	return 0;

}

To Run the Code:

g++ -std=c++14 -pthread multithreadingProblem.cpp
./a.out

Output of the Code:

Values of x:	3
Values of x:	4

When we run the code multiple times, we see this strange output i.e. in one run we get x = 3, and in the another run we get 4. So we can say for the different runs, we are getting different outputs.

Note: When we you will the above code many times(can be upto 1000 times), then you will get x = 4.

So think about why the code is showing this strange behaviour?

This problem is called critical section problem.

So critical section is a block of code, where two/more threads/processes access the shared variables, and it ends up creating inconsistencies in the code output.


In our code, variable x is the shared variable, and line number 10, 11 is the critical section because this is the part of code where threads are accessing shared variable.

In the next post, we will see how we can deal with the ambiguous output.

Posted in C++

joinable() in c++ Multithreading

We perform thread.join() operation to join the child thread to the main thread. But think about a scenario, you have a large project, and you don’t know whether you have already joined the child thread to the main thread or not. So before joining the child thread to the main thread, we check if thread has already been joined or not.

We can understand it with below example:

#include<iostream>
#include<thread>
using namespace std;

void function1()
{
	cout<<"This is function1 called by thread1"<<endl;
}

void function2()
{
	cout<<"This is function2 called by thread2"<<endl;
}

int main()
{
	std::thread t1(function1);
	std::thread t2(function2);

	t1.join();

	if(t1.joinable())
	{
		cout<<"Joining the Thread t1"<<endl;
		t1.join();
	}

	if(t2.joinable())
	{
		cout<<"Joining the Thread t2"<<endl;
		t2.join();
	}

	return 0;

}

To run the code:

g++ -std=c++14 -pthread joinable.cpp  
./a.out

Output of the Code:

This is function2 called by thread2
This is function1 called by thread1
Joining the Thread t2

Lets understand the output of the code:

At lines number 17 and 18, we call function1 and function2. At line number 20, we join thread t1 to the main thread. When we again check if t1 is joinable or not using t1.joinable(), it returns false, thus we do not see output from the first if block. But when we check if t2.joinable() is true or not, it returns true because till this point we have not joined t2 to the main thread. Thus we enter the if block and can see the output from the second if block.

When std::thread::joinable() returns false:

  • If the thread has already joined to the main thread or detached.
  • If the thread has been moved elsewhere.

Posted in C++

Latency in Multithreading Execution vs Sequential Execution:

Goal: In this post, we will understand the difference in execution time in case of multithreading execution vs sequential execution.

To understand which execution takes more time, we will take one simple assumption i.e. the program that we are going to execute does not have any IO operations.

We are going to write two functions:

  1. Function1 (it will calculate the sum of all the odd numbers from 1 to 100).
  2. Function2 (it will calculate the sum of all the even numbers from 1 to 100).

So following is the code for the above operations:

#include<iostream>
#include <pthread.h>
#include<thread>
using namespace std;
using namespace std::chrono;

int oddSum;
int evenSum;

void function1(int val)
{
	oddSum = 0;

	while(val>=0)  //iterate through all numbers from 100 to 0
	{
		if((val&1)==0) //check if number is divisible by 2 or not
		{
			oddSum = oddSum+val;
		}
		val--;
	}
}

void function2(int val)
{
	evenSum = 0;

	while(val>=0) //iterate through all numbers from 100 to 0
	{
		if((val&1)==1) //check if number is divisible by 2 or not
		{
			evenSum = evenSum+val;
		}
		val--;
	}
}

int main()
{
	//calling the function using multithreading
	cout<<"\n***********************************************************"<<endl;
	auto startTime1 = std::chrono::system_clock::now();
	std::thread t1(function1,100);
	std::thread t2(function2,100);

	t1.join();
	t2.join();
	
	cout<<"Sum of all even numbers from 1 to 100:\t"<<evenSum<<endl;
	cout<<"Sum of all odd numbers from 1 to 100:\t"<<oddSum<<endl;
	auto endTime1 = std::chrono::system_clock::now();

	auto duration1 = duration_cast<microseconds>(endTime1-startTime1);
	cout<<"Time taken using Multithreaded Execution:\t"<<duration1.count()<<endl;

	//calling the function using sequential execution

	cout<<"\n***********************************************************\n"<<endl;

	auto startTime2 = std::chrono::system_clock::now();
	function1(100);
	function2(100);

	cout<<"Sum of all even numbers from 1 to 100:\t"<<evenSum<<endl;
	cout<<"Sum of all odd numbers from 1 to 100:\t"<<oddSum<<endl;
	auto endTime2 = std::chrono::system_clock::now();

	auto duration2 = std::chrono::duration_cast<microseconds>(endTime2-startTime2);
	cout<<"Time taken using Sequential Execution:\t"<<duration2.count()<<endl; 

	return 0;
}

Let’s understand the above code:

At line number 42, we are recording the start time of the multithreaded execution. We call function1 and function2 at Line numbers 43 and 44 respectively. Once the execution of thread t1 and t2 completes, we join both the threads to the main thread and print the result. After the completion of all the steps, we again record the time and print it in microseconds.

Now, we perform the same operations again, but this time in the sequential fashion and, print the execution time and result.

Now, think about the scenario, the code is not having any I/O operations, which one (Multithreaded or Sequential Execution) will have more execution time. You can run the above code on your system using the below command:

g++ -std=c++14 -pthread multithreadingVsSequentialExe.cpp
./a.out

Below are the results when we execute the code on our system(results might be different on different machines due to the hardware change):

***********************************************************
Sum of all even numbers from 1 to 100:	2500
Sum of all odd numbers from 1 to 100:	2550
Time taken using Multithreaded Execution:	255

***********************************************************

Sum of all even numbers from 1 to 100:	2500
Sum of all odd numbers from 1 to 100:	2550
Time taken using Sequential Execution:	6

When you will look at the results, you will wonder that multithreaded execution is taking more time as compared to sequential execution. Why is that the case?

Let’s understand it.

So when we are calling function1 and function2 using thread t1 and t2. Many context switches take place between thread t1 and t2 i.e. for x microseconds t1 runs and y microseconds t2 runs and so on. But when a context switch takes place, there is some latency associated with the context switch. It results in increasing the execution time for multithreaded execution.

So let suppose k numbers of context switches take place during the multithreaded execution then total execution time can be calculated using the below formula:

Execution time using Multithreading = function1 exe. time + function2 execution time + Number of context Switches * Latency in One Context Switch

Time Taken In Multithreaded Execution

But in case of sequential execution, function1 executes first and then function2. There is no context switch associated with the sequential execution. So time taken in sequential execution can be calculated using the below formula:

Execution time using Sequential Execution= function1 execution time + function2 execution time

Time in Sequential Execution

This blog might be an interesting read: Multithreading and MultiProcessing using Python

Posted in C++

Call the function with parameters

Goal: In this tutorial, we will see how we can pass the parameters to the function called using thread.

We will create two threads t1 and t2. One thread will call function1 (this function will perform the addition of two numbers), and another thread will call function2 (this function will perform the multiplication of two numbers).

Below is the code for this exercise:

#include<iostream>
#include<thread>
using namespace std;

int multi;//variable to store the multiplication of two numbers
int sum; //variable to store the sum of two numbers

void function1(int x, int y)
{
	sum = x+y;
}

void function2(int x, int y)
{
	multi = x*y;
}

int main()
{
	int a = 10, b = 20;

	std::thread t1(function1,a,b);
	std::thread t2(function2,a,b);

	t1.join();
	t2.join();

	cout<<"Sum of given numbers: "<<sum<<endl;
	cout<<"Multiplication of given numbers: "<<multi<<endl;

	return 0;
}

std::thread object takes two types of parameter,

  1. Function name 
  2. Values that we want to pass to the called function. 

So std::thread t1(function1,a,b) creates the thread t1 and calls the function1 with parameter a and b.

Once the execution of t1 and t2 completes, both the threads are joined to the main thread using join() function/method and we print the output of function1 and function2 using global variables sum and multi.

Posted in C++

Join in C++ Multithreading

From the line number 20 and 21 in the below code, if we remove t1.join() and t2.join(), our main thread will not wait for t1 and t2 to gets complete. So even before the execution of t1 and t2, main thread will terminate, and program execution will complete, so we will not be able to see the output of thread t1 and thread t2.

#include<iostream>
#include<thread>
using namespace std;

void function1()
{
	cout<<"This is function1 called by thread1"<<endl;
}

void function2()
{
	cout<<"This is function2 called by thread2"<<endl;
}

int main()
{
	std::thread t1(function1); //creation of thread1 and calling the function1
	std::thread t2(function2); //creation of thread2 and calling the function2

	t1.join(); //waiting for thread1 to execute
	t2.join(); //waiting for thread2 to execute

	return 0;
}
Command to Execute the code:
g++ -std=c++14 -pthread threadCreation.cpp
./a.out

You can try executing the above code by removing line number 20 and 21. You will not see the output from function1 and function2.

So why are we not able to see the output of function1 and function2? Let’s try to understand this.

At line number 18, we are having three threads in our system, one is the main thread, and the other two are t1 and t2. Main thread is the parent thread and t1, t2 are child threads. Child threads will be there in the system till the time parent thread is there in the system. So when t1 and t2 go for the function execution, parent thread i.e. main thread completes its execution and terminates. Now in the system, we are having only two threads t1, t2 and their parent thread i.e. main thread is not there in the system(it has completed its execution). So t1 and t2 also terminate without generating their output.


So if we use t1.join() and t2.join(), it means main thread is waiting for t1 and t2 to complete their execution and we see the output from function1 and function2.

Posted in C++

Thread Creation in C++

Goal:

At the end of this tutorial, you will learn creating threads and how we can call the different functions using them.


So for a better understanding of the topic, we are going to take a simple example. We will create two threads t1, and t2. These two threads will call two functions, function1 and function2. Once the execution of both the threads is complete, they will be joined to the main thread. So below is the code for this scenario:

#include<iostream>
#include<thread>
using namespace std;

void function1()
{
	cout<<"This is function1 called by thread1"<<endl;
}

void function2()
{
	cout<<"This is function2 called by thread2"<<endl;
}

int main()
{
	std::thread t1(function1); //creation of thread1 and calling the function1
	std::thread t2(function2); //creation of thread2 and calling the function2

	t1.join(); //waiting for thread1 to execute
	t2.join(); //waiting for thread2 to execute

	return 0;
}
Command to Execute the code:
g++ -std=c++14 -pthread threadCreation.cpp
./a.out


In main, at lines number 17 and 18, we are creating the two threads t1 and t2. Thread t1 is calling function1 and thread t2 is calling function2.
Once the execution of threads t1 and t2 are complete, both the threads are joined to the main thread.

When we run this code multiple times, we get different outputs. The reason for this is, both the threads t1 and t2 are created simultaneously. But due to the slight time difference in thread creation/execution, sometimes we see output from thread t2 first and then t1 and vice versa.

Note: Before moving ahead to the next tutorial, think about why are we using t1.join() and t2.join()?

Posted in C++

Programming Assignment for Beginner ( Programming + Theoretical Problems)

Instructions for the Assignment:

  1. Don’t copy the code from anywhere.
  2. Try to solve one problem in multiple ways.
  3. Don’t try to solve the problem just for the sake of completion but try to understand the logic behind the solution.
  4. Create the GitHub account and share the code in one of the Git Repository.
  5. You can use any language of your choice to solve the problems.

If you solve all the problems by following the above steps, you are good to go to the next level.

Programming Problems:

  1. Write a program to add and subtract the two numbers and print the output.
  2. Write a program that will take a number as input and based on the value of that number either it will print the addition or subtraction of these two numbers (Ex. if the initially entered number is 0 then perform addition else perform subtraction and print the output).
  3. Write a program to calculate the simple interest given the amount, interest rate, and time.
  4. Write a program to check whether a number is even or odd.
  5. Write a program to find out the maximum and minimum of three numbers.
  6. Write a program to check if a character is a vowel or consonant.
  7. Write a program that will perform the basic operations of a calculator(+, -, *, /) (User will provide the input to perform a particular action).
  8. Write a program to print the count from 1 to n (n can be any integer number).
  9. Write a program to print the table of any given integer number x.
  10. Write a program to calculate the binary representation of an integer and float.
  11. Write a program to calculate the integer value representation of an
  12. Write a program to print the patterns given in the below google doc: Different Pattern Problems for Beginner
  13. Write a program to find the LCM and HCF of two integer numbers.
  14. Write a program to check if a character is there in a string or not.
  15. Write a program to count the occurrence of every character in a string.
  16. Extract vowel and consonant in a separate string and print both.
  17. Write a program to check if a given number is prime or not.
  18. Write a program to print the elements of an array.
  19. Write a program to find out the sum of an array.
  20. Write a program to check if a string is a palindrome or not.
  21. Write a program to convert the string from lower case to upper case and vice versa (Suggestion: use the concept of ASCII values).
  22. Check if the given string is a permutation of another given string.
  23. Print the word and its position of the second most repeated word in a sequence.
  24. Write a program to check if a number is a power of 2 without using a loop (Hint: use the concept of bit).
  25. Write a program to check if a number is divisible by 2 (Suggestion: don’t use loop but try to solve using bit).
  26. Search an element in an unsorted array.
  27. Write a program to sort the elements of an integer array.
  28. Write a program to sort an array of 0’s, 1’s, and 2’s only.
  29. Search an element in a sorted array and return (Use Binary Search for searching).
  30. Write a program to find out the Union and Intersection of two arrays (array might be sorted or unsorted).
  31. Write a program to find out the two elements a and b in an array such that a+b = k.
  32. Write a program to sort the elements of an array using merge sort and quick sort (Don’t use the library implementation).
  33. Create a 2-d metric of integer elements and print its elements (row-wise and column-wise).
  34. Add two 2-d metrics and print the sum.
  35. Multiply two 2-d metrics and print the multiplication.
  36. Search an element in a 2-d metric, and print the position of the element.
  37. Rotate the 2-d metric by 90 degrees or find out the transpose of a metric.
  38. Access the elements of a 1-d and 2-d array using the reference of the first element of the array(For a better understanding, use C/C++).
  39. How do malloc, realloc, and calloc works, write a program to dynamically allocate the memory (For better understanding, use C/C++).
  40. Use malloc to declare a 1-d array of size n and reverse the elements of this array.
  41. Create a structure to store the student details in an array and print the details of all the students.
  42. Write a program to create a file. Once you create the file, write something to this file, and print whatever you have written to the file.
  43. Find the sum of all the integer elements written in a file (integers are separated by “,”, there might be multiple lines in the file).

Theoretical problems:

  1. What is an operating system?
  2. What is the difference between low-level language and high-level language?
  3. Why do we need to learn c/c++ in 2021?
  4. What is a compiler?
  5. What are the header files in any language, why do we need them?
  6. What is a switch statement?
  7. What is the size of int, char, float, etc?
  8. What are the if-else statements?
  9. What is the difference between for, while, and do-while loop?
  10. How does operator precedence work in any language?
  11. What is a string?
  12. What is the difference between mutable and immutable strings?
  13. What is an array? Why do we need an array?
  14. What is a pointer?
  15. How can we access the elements of an array using a pointer?
  16. What is the difference between pointer and reference?
  17. What is the difference between call by value and call by reference?
  18. What are malloc, alloc, and realloc?
  19. What is free and how does it work?
  20. What is the meaning of dynamic memory allocation?
  21. Why do we need to free the dynamically allocated memory?
  22. What is structure and why do we need structure?
  23. How can we access the elements of a structure?
  24. How does file handling work in c/c++?
  25. Can you provide some examples of unsafe operations on a file?

Roadmap to Excel in Computer Science and Get a Package of 20+ LPA

Almost all the students are concerned about their future. In this post we are going to discuss, how a normal student can excel in his college life.

If you follow this post for 1-2 years, I can bet, you will get something your friends can not think of. This post is mainly for the students studying in computer science and engineering.

1st Year:

If you are a first year student, just focus on your CGPA. Because in the upcoming years you will not get much time to work on your grades/CGPA. In first year, we generally have basic programming courses such as C, C++, Python, Java, etc. I will suggest, you learn two programming languages. One of them must be either C/C++ and the another one should be anyone of your choice.

Think about your Neha and the ways to get your Neha. One of the way is to get 20+ LPA job and propose Neha.

In the first year summer, we will start the advance topics of these languages such as OOPs concepts, Collection, Hash Map, etc. If you are good with these concepts at the end of your first year you are good to go for the second year.

2nd Year:

Now you have come to 2nd year, so you will start learning your core subjects. Whatever core subjects you are having in your current semester, try to complete at-least one project related to that particular subject in that semester itself. If you are in a tier1 college, you will have to complete the project by default, because projects will be the part of your syllabus.

Always remember you Neha, your package/success is the only thing that can help you in getting Neha in your arms.

At the same time, you also have to dig deep into competitive programming. For this, you can choose any of the platform i.e. codechef, hackerank, hackerearth, codeforces, etc. At any platform try to solve 300+ problems at the end of your second year.

At the end of 2nd Year, What you will have in your resume:

As you have completed 3-4 projects related to your core subjects (operating system, DBMS, Data Structure and Algorithms, Computer Systems, etc), you can put them in your resume along with github repository link. At the same time you can also mention that you have solve 300+ problems on some particular platform.

3rd Year

In the 3rd year, you have to continue the journey of your competitive coding. At the end of the 3rd year, the total number of problems solved should be 600-700+(if you can do this, you are ready to crack any company). At the same time, now you can work on some of the real world projects (take some of the softwares in the market and try to implement some of their functionalities). You can also work with some of the faculties in your college on some research projects.

In your 3rd year itself, I will highly suggest you to explore the open source projects and try to crack the Google Summer of Code. You can learn some of the framework such as Django, Flask, etc. In this entire learning process, don’t forgot about your core subjects.

If till this point you are following the post, you are gona rock in life man. You are going to get your Neha.

How will your resume look like at the end of your 3rd year:

You will have some of the cool projects in your resume along with a good grab on the competitive programming skills. If you work hard, you might have a publication or GSOC or both in your resume.

4th Year

Now this is the time to rock with all the skills you have. If you are in tier one engineering colleges, don’t worry you are going to get a really good placements. But if your college is not that good, try LinkedIn, and participate in off-campus placements, I can bet you will do wonders.

How to use LinkedIn to get Machine Learning or Data Science jobs?

What you can learn in 4th year:

Now you can learn some of the research topics in computer science and work on some cool projects around these topics. I will suggest you to learn machine learning, natural language processing, computer vision, and read as many recent research papers as possible. After reading some paper try to implement it on your own, it will provide you a really good exposer to research.

In most of the colleges, core subjects are over by 3rd year itself. So you need not to worry about core subjects. As you are good with core computer science, competitive coding, and open source, you can start writing blogs or you can start creating you tube videos or even you can work on some of the start up idea, if you have one. Try to read as many articles as possible related to your favourite field whether it is machine learning or software engineering or anything else. You can also explore some competitive exam such as gate or cat as well, if your are interested.

My suggestions:

If you are someone, studying in tier3 engineering college, go and crack gate. Try to enter into one of the IITs, it will help you in getting a pay package of 20+ LPA. Believe me, IITs are haven for computer science students, it will provide you a good recognition along with a really handsome package.

Don’t forgot about your Neha, she will come only when you will get 20+ LPA, Best wishes.

Benefits of using Numpy

Why is Numpy Better than Lists?

 

As a python programmer, one must be aware of why Numpy is better than Lists and how can we prove it. 

See, as a beginner, you can avoid this question, but if you have to work with big data sets; 

you should be aware of the benefits Numpy arrays have over lists.

In this article, we will discuss in what ways Numpy arrays are better and more suitable than lists.
Numpy Data Structure performs better in:

 

1) FUNCTIONALITY  :

 

Numpy array have inbuilt functions like linear algebra operations built-in; 

which makes them better than lists.  

 

2) SIZE :

 

Numpy array takes up less space or size.

Let us understand with the help of an example;

  • First, we will import the numpy library, time and getsizeof from the system library.

  • Then, we will create an empty list and get its size.

  • We will fill the list with the n range of elements; i.e. 3000000  and will again get the size. 

 >> we see that the size has considerably increased.

  • Now, let’s convert the list to NumPy and take its size:

  • To prove our point we print out the difference between both the sizes:

Hence, our point is being proved by the above example;

that NumPy takes up less space as compared to the list data structure.

 

 

3) PERFORMANCE :

They have a need for speed and are faster than lists.

Let’s understand with the help of an example:

  • First of all, create a list of n elements and then print first and last 5 items:

  • Modifying lists and multiplying each item by 10 and printing some of them:   

                                           

>> we see here that all elements are now multiplied by 10.

  • Now, let’s calculate the processing time taken for this procedure: 

   

  • Now, we will convert the list into numpy : 

  • Modifying the array and then printing the elements: 

   

  • And, then calculate the time for the process:    

  • To prove our point we will find the difference between the two times:

                 

>> Numpy is faster than a list by 0.53125s;

this is a small amount of time, but when you work with a large dataset, there will be a huge difference.

                                           


Numpy is designed to be efficient with matrix operations, more specifically; more processing in
NumPy is vectorized.
Vectorization involves, expressing mathematical operations; such as multiplication, that we are
using as occurring on the entire element, rather than a single statement.
With Vectorization, the underline code is parallelized, such that the operations we are performing
on NumPy array can run on multiple array elements at once, rather than looping through them
one at a time.
As long as the operations you are applying does not rely on any other array element,
as in the case of matrix multiplication; then vectorization will give you awesome speedups.
Looping over Python arrays, lists and dictionaries can be slow.
As, Vectorized operations in NumPy are mapped to highly optimized C code, making them much faster than their standard python counterparts. 

Hence, I will recommend you to use Numpy rather than lists in python.

Thank you for reading!            

This is the link to the code being used in the blog-  https://github.com/HARITIKAPANDIT/NOTEBOOK/blob/master/Numpy%20over%20list.ipynb