├── Algorithms ├── Bubble_sort.py ├── Dselect.py ├── Insertion_sort.py ├── MergeSort.py ├── QuickSelect.py ├── Quicksort_InPlace.py ├── Quicksort_Recursion.py ├── Random_Select_InPlace.py ├── Readme.md └── Selection_sort.py ├── File_Manipulation ├── File_rename_containing_numeric.ipynb └── Readme.md ├── LICENSE ├── Maths ├── Amicable_number.py ├── Area_under_a_curve.py ├── BaseN_num_generator.py ├── Circular_prime.py ├── Coin_3_5.py ├── Collatz_Recursive.py ├── Collatz_seq.py ├── Fourier_Waveform_NumPy.py ├── Hanoi_Tower.py ├── Linear_equation_solve.py ├── Neumann_random_generator.py ├── Numpy practice.ipynb ├── Palindrome_product.py ├── Pandigital_prime.py ├── Quadratic_prime.py ├── Readme.md └── nth_prime.py ├── README.md └── Text_Analysis ├── Most_Frequent_Word_from_File.py ├── Readme.md ├── TaleOf2Cities.txt ├── Word_cloud.py ├── Word_count_from_web.py └── stopwords /Algorithms/Bubble_sort.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Dec 22 17:45:47 2017 4 | @author: Tirthajyoti Sarkar 5 | Simple Bubble sort with counter for number of swap operations 6 | Accepts user input on minimum and maximum bound of the array and the size of the array 7 | """ 8 | 9 | import random 10 | 11 | def bubble_sort(array): 12 | n = len(array) 13 | # Set a swap counter to a non-zero value 14 | swap_counter=-1 15 | swap_op=0 16 | # Unitll swap counter hits zero... 17 | while(swap_counter!=0): 18 | # Reset the swap counter at the beginnig of each iteration 19 | swap_counter=0 20 | # Iterate over the array examining the a pair of data 21 | for i in range(n-1): 22 | if(array[i]>array[i+1]): 23 | temp=array[i] 24 | array[i]=array[i+1] 25 | array[i+1]=temp 26 | # Print for troubleshooting 27 | #print(sorted_array) 28 | swap_counter+=1 29 | swap_op+=1 30 | else: 31 | pass 32 | return (array,swap_op) 33 | 34 | # User inputs for generating the random arrays 35 | mini = int(input("Please enter the minimum bound:")) 36 | maxi = int(input("Now enter the maximum bound:")) 37 | num = int(input("Finally enter the size:")) 38 | 39 | # Create random array based on user-specified minimum/maximum bounds and number of elements 40 | a= [] 41 | for i in range(num): 42 | a.append(random.randint(mini,maxi)) 43 | 44 | print("\nInitial array:",a) 45 | 46 | # Get the sorted array back along with the count of # of operations it took to sort 47 | sorted_array,n_op=bubble_sort(a) 48 | print("Sorted array: {}\nTook {} operations".format(sorted_array,n_op)) 49 | -------------------------------------------------------------------------------- /Algorithms/Dselect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jan 28 12:30:03 2018 4 | 5 | @author: Tirtha 6 | """ 7 | import random 8 | 9 | def partition(A,p_idx): 10 | p=A[p_idx] 11 | #print("Input list to partition with pivot {}: {}".format(p,A)) 12 | # Swap/move pivot to leftmost 13 | temp=A[0] 14 | A[0]=A[p_idx] 15 | A[p_idx]=temp 16 | 17 | l=0 18 | i=l+1 19 | r=len(A) 20 | for j in range(l+1,r): 21 | if A[j]<=p: 22 | temp=A[j] 23 | A[j]=A[i] 24 | A[i]=temp 25 | i+=1 26 | # Now swap the pivot from the 0-th index to its rightful index 27 | temp=A[i-1] 28 | A[i-1]=A[l] 29 | A[l]=temp 30 | # Print partitioned list and new pivot index for debugging 31 | #print("Partitioned list:",A) 32 | #print("New pivot",i-1) 33 | #print("") 34 | return (i-1) 35 | 36 | def median(A): 37 | if len(A)==1: 38 | return A[0] 39 | elif len(A)==2: 40 | return A[1] 41 | else: 42 | return A[int(len(A)/2)+1] 43 | 44 | def Dselect(my_list,n): 45 | length=len(my_list) 46 | # Base case 47 | if length==1: 48 | return my_list[0] 49 | # Recursive case 50 | else: 51 | chunk=5 52 | medians=[] 53 | A=[] 54 | for i in range(0, length, chunk): 55 | A.append(my_list[i:i + chunk]) 56 | #print("A:",A) 57 | for array in A: 58 | # Note this sort is happening on a small array of fixed size (5) i.e. in O(1) time 59 | array.sort() 60 | medians.append(median(array)) 61 | #print("Medians:",medians) 62 | # Sorts the medians and choose the 'median of the medians' as pivot 63 | # Note this sort is happening on a very small array i.e. O(1) time 64 | medians.sort() 65 | #print("Medians sorted:",medians) 66 | p = Dselect(medians,int(length/10)) 67 | p_idx=my_list.index(p) 68 | #print("Pivot index and pivots:{}, {}".format(p_idx,p)) 69 | # Partition based on the chosen median of median pivot 70 | new_pivot = partition(my_list,p_idx) 71 | # Case to check if the new pivot returned by partition is the n-th order 72 | # Disabled because it was giving error on some cases and preventing the code to reach the base case 73 | #if new_pivot==n: 74 | #print("New pivot equal to sought order") 75 | #return (my_list[new_pivot-1]) 76 | if new_pivot>=n: 77 | # Recurse on the left side of the array with unchanged order statistic 78 | left=my_list[0:new_pivot] 79 | #print("New pivot {} >= {}. Recursing on {} with order {}".format(new_pivot,n,left,n)) 80 | return Dselect(left,n) 81 | else: 82 | # Recurse on the right side of the array with order statistic shrinked 83 | right=my_list[new_pivot:] 84 | #print("New pivot {} < {}. Recursing on {} with order changed to {}".format(new_pivot,n,right,n-new_pivot)) 85 | return Dselect(right,n-new_pivot) 86 | 87 | """ 88 | # Test code for single case with fixed order statistic 89 | ##============= 90 | N_test=20 91 | test_lst=[] 92 | for i in range(N_test): 93 | test_lst.append(random.randint(0,100)) 94 | #n= random.randint(1,6) 95 | n=5 96 | print("Original list:",test_lst) 97 | print("Order statistic sought",n) 98 | print("") 99 | 100 | result = Dselect(test_lst,n) 101 | test_lst.sort() 102 | #element = test_lst[result-1] 103 | print("{}-th order statistic is {}".format(n,result)) 104 | 105 | print("Sorted list",test_lst) 106 | """ 107 | 108 | ## Test code with 100 cases with random order statistic 109 | N=10000 110 | check = [] 111 | # Create a test array of 20 integers 112 | for i in range(N): 113 | N_test=20 114 | test_lst=[] 115 | for i in range(N_test): 116 | test_lst.append(random.randint(0,100)) 117 | # Picking a random test input for order statistic 118 | n= random.randint(1,20) 119 | result = Dselect(test_lst,n) 120 | # Call Python's built-in sort method on the test array 121 | test_lst.sort() 122 | # Check if the sorted array's n-1-th element is the n-th order statistic returned by our program 123 | check.append(test_lst[n-1]==result) 124 | # Print the sum total of truth values in the check array 125 | print(sum(check)) 126 | 127 | -------------------------------------------------------------------------------- /Algorithms/Insertion_sort.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Dec 22 23:26:32 2017 4 | @author: Tirthajyoti Sarkar 5 | Simple Insertion sort with counter for total number of operations (shifting and iterating) 6 | Accepts user input on minimum and maximum bound of the array and the size of the array 7 | """ 8 | import random 9 | 10 | def insertion_sort(array): 11 | counter = 0 12 | # Iterate over the array starting from 2nd element i.e. index 1 13 | for index in range(1,len(array)): 14 | # Set current value and index 15 | currentvalue = array[index] 16 | position = index 17 | # Keep shifting the elements to insert the next unsorted element in the proper position 18 | while position>0 and array[position-1]>currentvalue: 19 | array[position]=array[position-1] 20 | position = position-1 21 | array[position]=currentvalue 22 | counter+=1 23 | # Print current state of array for troubleshooting 24 | #print(array) 25 | return (array,counter) 26 | 27 | # User inputs for generating the random arrays 28 | mini = int(input("Enter the minimum bound:")) 29 | maxi = int(input("Enter the maximum bound:")) 30 | num = int(input("Enter the size:")) 31 | 32 | # Create random array based on user-specified minimum/maximum bounds and number of elements 33 | a= [] 34 | for i in range(num): 35 | a.append(random.randint(mini,maxi)) 36 | 37 | print("\nInitial array:",a) 38 | 39 | # Get the sorted array back along with the count of # of operations it took to sort 40 | sorted_array,n_op=insertion_sort(a) 41 | print("Sorted array: {}\nTook {} operations".format(sorted_array,n_op)) -------------------------------------------------------------------------------- /Algorithms/MergeSort.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Jan 24 22:42:19 2018 4 | 5 | @author: Tirtha 6 | """ 7 | def merge(list1,list2): 8 | """ 9 | Takes two lists and merge them in a sorted list 10 | """ 11 | # Initialie the empty list 12 | result=[] 13 | i=0 14 | j=0 15 | # This loop runs till both input lists have non-zero elements in them 16 | # That means this loop stops when either of the input list runs out of element 17 | while (len(list1)>0 and len(list2)>0): 18 | if list1[0]<=list2[0]: 19 | # Append to the result list 20 | result.append(list1[0]) 21 | #print("Result:",result) 22 | # Pop the first element of the list 23 | list1.pop(0) 24 | i=i+1 25 | else: 26 | # Append to the result list 27 | result.append(list2[0]) 28 | #print("Result:",result) 29 | # Pop the first element of the list 30 | list2.pop(0) 31 | j+=1 32 | # Now checking which input list has run out of element. 33 | # Whichever list still has element left, append all of them to the result array 34 | # Note, only one of these if-loops will be executed 35 | if(len(list1)>0): 36 | result=result+list1 37 | if(len(list2)>0): 38 | result=result+list2 39 | 40 | #print(f"i:{i},j:{j}") 41 | return (result) 42 | 43 | def mergeSort(my_list): 44 | n = len(my_list) 45 | # Base case for 1-element array 46 | if n==1: 47 | return (my_list) 48 | # Recursive case: 49 | # Divide the array into two halves. 50 | # Mergesort on the left half 51 | # Mergesort on the right half 52 | # Merge two sorted arrays 53 | # Return the merged result 54 | else: 55 | left_half=my_list[0:int(n/2)] 56 | right_half=my_list[int(n/2):n] 57 | #print("Left half:",left_half) 58 | #print("Right half:",right_half) 59 | left=mergeSort(left_half) 60 | right=mergeSort(right_half) 61 | sorted_list=merge(left,right) 62 | return (sorted_list) -------------------------------------------------------------------------------- /Algorithms/QuickSelect.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jun 18 20:01:40 2017 4 | 5 | @author: Tirtha 6 | """ 7 | import random 8 | def SelectiSmallest (A,i): 9 | n = len(A) 10 | if (n==1): 11 | print ("By quickselect: {}".format(A[0])) 12 | return (A[0]) 13 | else: 14 | low = [] 15 | high = [] 16 | p=A[random.randint(0,n-1)] 17 | # If random pivot is the max element, just create a one-element list 'high' with it and put all other elements in 'low', don't recurse 18 | if p==max(A): 19 | high.append(p) 20 | A.remove(p) 21 | low=A 22 | else: 23 | for j in range(len(A)): 24 | if (A[j]<=p): 25 | low.append(A[j]) 26 | else: 27 | high.append(A[j]) 28 | if i<=len(low): 29 | SelectiSmallest(low,i) 30 | else: 31 | SelectiSmallest(high,i-len(low)) 32 | 33 | # Test list initialization 34 | l = [] 35 | # Number of elements in the list 36 | Nt = 10 37 | # i-th smallest element 38 | i = 8 39 | # List elements randomly generated by selecting integeres from 1 to 500 40 | for k in range(Nt): 41 | l.append(random.randint(1,500)) 42 | # Check for duplicate elements 43 | if (len(set(l))) != len(l): 44 | print("Duplicate elements found. This algorithm won't work. Exiting!") 45 | else: 46 | a = SelectiSmallest(l,i) 47 | 48 | # Verifying by the default list sort method 49 | sorted_list=sorted(l) 50 | print ("By sorting: {}".format(sorted_list[i-1])) 51 | -------------------------------------------------------------------------------- /Algorithms/Quicksort_InPlace.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Jan 26 18:32:13 2018 4 | 5 | @author: Tirtha 6 | """ 7 | 8 | import random 9 | 10 | def partition(A,l,r): 11 | p=A[l] 12 | i=l+1 13 | for j in range(l+1,r): 14 | if A[j]<=p: 15 | temp=A[j] 16 | A[j]=A[i] 17 | A[i]=temp 18 | i+=1 19 | temp=A[i-1] 20 | A[i-1]=A[l] 21 | A[l]=temp 22 | print("Modified list:",A) 23 | return (i) 24 | 25 | def QuickSortInPlace(lst,low,high): 26 | #count_op=0 27 | length=high-low 28 | # Base case: Nothing to do 29 | if length<=1: 30 | pass 31 | # Recursive case 32 | else: 33 | # Partition the array and get back the pivot position 34 | pivot_pos=partition(lst,low,high) 35 | # Quicksort on the left half of the pivot 36 | QuickSortInPlace(lst,low,pivot_pos-1) 37 | # Quicksort on the right half of the pivot 38 | QuickSortInPlace(lst,pivot_pos,high) 39 | 40 | # Test code 41 | ##============= 42 | N_test=15 43 | test_lst=[] 44 | for i in range(N_test): 45 | test_lst.append(random.randint(0,100)) 46 | 47 | print("Original list:",test_lst) 48 | QuickSortInPlace(test_lst,0,15) 49 | print("Sorted list: ",test_lst) -------------------------------------------------------------------------------- /Algorithms/Quicksort_Recursion.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Jan 22 20:28:05 2018 4 | 5 | @author: Tirtha 6 | """ 7 | 8 | def quicksort(lst): 9 | #count_op=0 10 | if lst==[]: 11 | return (lst) 12 | else: 13 | pivot=lst[0] 14 | smaller_lst = [n for n in lst if npivot] 17 | 18 | return (quicksort(smaller_lst)+pivot_lst+quicksort(greater_lst)) 19 | 20 | import random 21 | 22 | N_test=20 23 | test_lst=[] 24 | for i in range(N_test): 25 | test_lst.append(random.randint(0,100)) 26 | 27 | print("Original list:",test_lst) 28 | print("Sorted list:",quicksort(test_lst)) -------------------------------------------------------------------------------- /Algorithms/Random_Select_InPlace.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jan 28 12:30:03 2018 4 | 5 | @author: Tirtha 6 | """ 7 | import random 8 | 9 | def partition(A,p_idx): 10 | p=A[p_idx] 11 | #print("Input list to partition with pivot {}: {}".format(p,A)) 12 | # Swap/move pivot to leftmost 13 | temp=A[0] 14 | A[0]=A[p_idx] 15 | A[p_idx]=temp 16 | 17 | l=0 18 | i=l+1 19 | r=len(A) 20 | for j in range(l+1,r): 21 | if A[j]<=p: 22 | temp=A[j] 23 | A[j]=A[i] 24 | A[i]=temp 25 | i+=1 26 | # Now swap the pivot from the 0-th index to its rightful index 27 | temp=A[i-1] 28 | A[i-1]=A[l] 29 | A[l]=temp 30 | # Print partitioned list and new pivot index for debugging 31 | #print("Partitioned list:",A) 32 | #print("New pivot",i-1) 33 | #print("") 34 | return (i-1) 35 | 36 | 37 | def Rselect(my_list,n): 38 | length=len(my_list) 39 | # Base case 40 | if length==1: 41 | return my_list[0] 42 | # Recursive case 43 | else: 44 | # Randomly choose a pivot index from 1 to length-1 45 | p_idx = random.randint(1,length-1) 46 | #print("Pivot index chosen",p_idx) 47 | # Partition based on the randomly chosen index 48 | new_pivot = partition(my_list,p_idx) 49 | # Case to check if the new pivot returned by partition is the n-th order 50 | # Disabled because it was giving error on some cases and preventing the code to reach the base case 51 | #if new_pivot==n: 52 | #print("New pivot equal to sought order") 53 | #return (my_list[new_pivot-1]) 54 | if new_pivot>=n: 55 | # Recurse on the left side of the array with unchanged order statistic 56 | left=my_list[0:new_pivot] 57 | #print("New pivot {} >= {}. Recursing on {} with order {}".format(new_pivot,n,left,n)) 58 | return Rselect(left,n) 59 | else: 60 | # Recurse on the right side of the array with order statistic shrinked 61 | right=my_list[new_pivot:] 62 | #print("New pivot {} < {}. Recursing on {} with order changed to {}".format(new_pivot,n,right,n-new_pivot)) 63 | return Rselect(right,n-new_pivot) 64 | 65 | """ 66 | # Test code for single case with fixed order statistic 67 | ##============= 68 | N_test=7 69 | test_lst=[] 70 | for i in range(N_test): 71 | test_lst.append(random.randint(0,100)) 72 | #n= random.randint(1,6) 73 | n=3 74 | print("Original list:",test_lst) 75 | print("Order statistic sought",n) 76 | print("") 77 | 78 | result = Rselect(test_lst,n) 79 | test_lst.sort() 80 | #element = test_lst[result-1] 81 | print("{}-th order statistic is {}".format(n,result)) 82 | 83 | print("Sorted list",test_lst) 84 | """ 85 | 86 | ## Test code with 100 cases with random order statistic 87 | N=10000 88 | check = [] 89 | # Create a test array of 20 integers 90 | for i in range(N): 91 | N_test=20 92 | test_lst=[] 93 | for i in range(N_test): 94 | test_lst.append(random.randint(0,100)) 95 | # Picking a random test input for order statistic 96 | n= random.randint(1,20) 97 | result = Rselect(test_lst,n) 98 | # Call Python's built-in sort method on the test array 99 | test_lst.sort() 100 | # Check if the sorted array's n-1-th element is the n-th order statistic returned by our program 101 | check.append(test_lst[n-1]==result) 102 | # Print the sum total of truth values in the check array 103 | print(sum(check)) 104 | 105 | -------------------------------------------------------------------------------- /Algorithms/Readme.md: -------------------------------------------------------------------------------- 1 | # Various important algorithms 2 | ## Sorting and Selection 3 | * Bubble sort 4 | * Selection sort 5 | * Insertion sort 6 | * Merge sort (by recursion) 7 | * Quicksort (using additional arrays) 8 | * Quicksort (in-place by partioning and swapping, no additional memory required) 9 | * Selection of n-th order statistic using __randomized pivot algorithm__ (in-place, no additional memory required) 10 | * Selection of n-th order statistic using __randomized pivot algorithm__ using additional arrays (easier implementation) 11 | * Selection of n-th order statistic using __medians of medians technique (no randomization involved)__ 12 | -------------------------------------------------------------------------------- /Algorithms/Selection_sort.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Dec 22 18:44:02 2017 4 | @author: Tirthajyoti Sarkar 5 | Simple selection sort with counter for total number of operations (finding minimum and swapping) 6 | Accepts user input on minimum and maximum bound of the array and the size of the array. 7 | """ 8 | import random 9 | 10 | def find_min(array): 11 | n=len(array) 12 | r = array[0] 13 | count=0 14 | for i in range(1,n): 15 | count+=1 16 | if r>array[i]: 17 | r=array[i] 18 | return(r,count) 19 | 20 | def selection_sort(array): 21 | n=len(array) 22 | num_op=0 23 | # Iterate over the length of the array, pushing smaller values to the left 24 | for i in range(n): 25 | # Scan the array from i-th element (where the iterator is currently) to the end for minimum 26 | m,c_min=find_min(array[i:n]) 27 | # IMPORTANT: Get the index of the minimum element w.r.t. to the main array 28 | m_index=array[i:n].index(m)+i 29 | # If the first element of the unsorted portion i.e. i-th element> minimum, then SWAP 30 | if (array[i]>m): 31 | # Print statement for examining minimum and its index, Troubleshooting 32 | #print("Minimum found {} at position {}. Swapping positions {} and {}".format(m,m_index,i,m_index)) 33 | temp=array[i] 34 | array[i]=m 35 | array[m_index]=temp 36 | num_op+=(c_min+1) 37 | print(array) 38 | else: 39 | pass 40 | return (array,num_op) 41 | 42 | # User inputs for generating the random arrays 43 | mini = int(input("Enter the minimum bound:")) 44 | maxi = int(input("Enter the maximum bound:")) 45 | num = int(input("Enter the size:")) 46 | 47 | # Create random array based on user-specified minimum/maximum bounds and number of elements 48 | a= [] 49 | for i in range(num): 50 | a.append(random.randint(mini,maxi)) 51 | 52 | print("\nInitial array:",a) 53 | 54 | # Get the sorted array back along with the count of # of operations it took to sort 55 | sorted_array,n_op=selection_sort(a) 56 | print("Sorted array: {}\nTook {} operations".format(sorted_array,n_op)) 57 | -------------------------------------------------------------------------------- /File_Manipulation/File_rename_containing_numeric.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Renaming multiple files with numeric digits\n", 8 | "\n", 9 | "Sometime you find multiple files, particularly song files, with leading numeric digits. Here we try to rename those files by cutting off the digits and keeping the main text.\n", 10 | "\n", 11 | "** Advisable to do this on a test folder by copying all your files. You will still save plenty of time vs. if you would have to rename all those files by hand.**" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": null, 17 | "metadata": { 18 | "collapsed": true 19 | }, 20 | "outputs": [], 21 | "source": [ 22 | "import os" 23 | ] 24 | }, 25 | { 26 | "cell_type": "markdown", 27 | "metadata": {}, 28 | "source": [ 29 | "### Use the exact directory path name" 30 | ] 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": null, 35 | "metadata": { 36 | "collapsed": true 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "dirname = \"../../../../Music/Car Listening/test/\"" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "### Create a list and apend all the file names contained within the directory" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "collapsed": true 55 | }, 56 | "outputs": [], 57 | "source": [ 58 | "l =[]\n", 59 | "for filename in os.listdir(\"../../../../Music/Car Listening/test/\"):\n", 60 | " print(filename)\n", 61 | " l.append(filename)" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "### Function definition to extract numeric digits and the length of the string before the real file name starts" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": { 75 | "collapsed": true 76 | }, 77 | "outputs": [], 78 | "source": [ 79 | "def digit_extractor(word):\n", 80 | " for letter in word:\n", 81 | " if letter.isdigit():\n", 82 | " i = word.find(letter)\n", 83 | " j=i\n", 84 | " while (not w[i].isalpha()):\n", 85 | " i+=1\n", 86 | " #print(w[i])\n", 87 | " return (j,i-j,True)\n", 88 | " break\n", 89 | " else:\n", 90 | " return (-1,-1,False)" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "### Run the extractor function and print the result to check if it is identifying files with right number of leading digits and non-alphabatic characters" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "execution_count": null, 103 | "metadata": { 104 | "collapsed": true, 105 | "scrolled": true 106 | }, 107 | "outputs": [], 108 | "source": [ 109 | "count=0\n", 110 | "for w in l:\n", 111 | " idx, length, flag=digit_extractor(w)\n", 112 | " if flag:\n", 113 | " print(\"For {}, Digit found at {}. Actual name starts at {}!\".format(w,idx,length))\n", 114 | " count+=1\n", 115 | "print(\"\\n\")\n", 116 | "print(\"Total songs found with digits: \",count)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "markdown", 121 | "metadata": {}, 122 | "source": [ 123 | "### Rename all the files at one go!" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": { 130 | "collapsed": true 131 | }, 132 | "outputs": [], 133 | "source": [ 134 | "count=0\n", 135 | "for w in l:\n", 136 | " idx, length, flag=digit_extractor(w)\n", 137 | " if flag:\n", 138 | " print(\"{} processed\".format(w))\n", 139 | " os.rename(dirname+w, dirname+w[idx+length:])\n", 140 | " count+=1\n", 141 | "print(\"Total songs found with digits and processed: \",count)" 142 | ] 143 | } 144 | ], 145 | "metadata": { 146 | "kernelspec": { 147 | "display_name": "Python 3", 148 | "language": "python", 149 | "name": "python3" 150 | }, 151 | "language_info": { 152 | "codemirror_mode": { 153 | "name": "ipython", 154 | "version": 3 155 | }, 156 | "file_extension": ".py", 157 | "mimetype": "text/x-python", 158 | "name": "python", 159 | "nbconvert_exporter": "python", 160 | "pygments_lexer": "ipython3", 161 | "version": "3.6.2" 162 | } 163 | }, 164 | "nbformat": 4, 165 | "nbformat_minor": 2 166 | } 167 | -------------------------------------------------------------------------------- /File_Manipulation/Readme.md: -------------------------------------------------------------------------------- 1 | 2 | ### Basic file and OS related scripts 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | {one line to give the program's name and a brief idea of what it does.} 635 | Copyright (C) {year} {name of author} 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | {project} Copyright (C) {year} {fullname} 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /Maths/Amicable_number.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Apr 17 21:51:59 2017 4 | @author: Tirtha 5 | 6 | Search for all amicable number pairs up to 10,000 and finding their sum 7 | #Barebne code 8 | """ 9 | import math 10 | def divisor_sum(n): 11 | div_sum=1 12 | for i in range(2,int(math.sqrt(n)+1)): 13 | if n%i==0: 14 | div_sum+=i 15 | if (i*i!=n): 16 | div_sum+=int((n/i)) 17 | return div_sum 18 | 19 | def is_amicable(a,b): 20 | if (divisor_sum(a)==b and divisor_sum(b)==a): 21 | return True 22 | else: 23 | return False 24 | 25 | result = 0 26 | lsta =[] 27 | lstb= [] 28 | k=0 29 | while k<10: 30 | for i in range(1000*k,1000*(k+1)): 31 | for j in range (i+1,min([10000,2*i])): 32 | if is_amicable(i,j): 33 | lsta.append(i) 34 | lstb.append(j) 35 | result+=i+j 36 | print ("Finished loop for {}\n".format(k)) 37 | k+=1 38 | print (result) 39 | -------------------------------------------------------------------------------- /Maths/Area_under_a_curve.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jan 21 23:31:45 2018 4 | 5 | @author: Tirtha 6 | """ 7 | import math 8 | def area (func,low,high,stepsize=0.01): 9 | """ 10 | Accepts arbitrary function of single variable and calculates the area under the curve between 'low' 11 | and 'high' limits. Stepsize for numerical approximation can be chosen by user or set to 0.01 by default 12 | """ 13 | area=0 14 | iter_count=0 15 | while (low36: 44 | print("Base length exceeds 36.\ 45 | Cannot generate numbers with regular numerics and alphabets.") 46 | return None 47 | import string 48 | alpha=string.ascii_uppercase 49 | result = [] 50 | bases = [i for i in range(10)]+ [c for c in alpha] 51 | 52 | if length==0: 53 | result.append('') 54 | return result 55 | else: 56 | for i in bases[:N]: 57 | resultN = [str(i)+ bits for bits in baseN_gen(length-1,N)] 58 | result=result+resultN 59 | return result -------------------------------------------------------------------------------- /Maths/Circular_prime.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Apr 7 09:44:38 2017 4 | 5 | @author: Tirtha 6 | """ 7 | Nt = 10000 8 | def even_check(n): 9 | list_num = list(str(n)) 10 | if '0' in list_num or '2' in list_num or '4' in list_num or '5' in list_num or '6' in list_num or '8' in list_num: 11 | return True 12 | 13 | def rotateN(n): 14 | ln_num = len(str(n)) 15 | str_num = str(n) 16 | result = [n] 17 | 18 | for i in range(ln_num-1): 19 | rotated = str_num[1:]+str_num[0] 20 | result.append(rotated) 21 | str_num = rotated 22 | 23 | return result 24 | 25 | def is_prime(n): 26 | if n< 0: 27 | return False 28 | elif n == 0 or n==1: 29 | return False 30 | elif n==2: 31 | return True 32 | elif (str(n)[-1] == '2') or (str(n)[-1] == '4') or (str(n)[-1] == '6') or (str(n)[-1] == '8'): 33 | return False 34 | elif (str(n)[-1]=='5' and n!=5): 35 | return False 36 | elif (str(n)[-1]=='0'): 37 | return False 38 | else: 39 | for i in range(2,int(math.sqrt(n))+2): 40 | if (n%i == 0): 41 | #print ("Not a prime") 42 | return False 43 | else: 44 | #print ("Prime!") 45 | return True 46 | 47 | def is_circular_prime(n): 48 | if even_check(n): 49 | return False 50 | 51 | if (not is_prime(n)): 52 | return False 53 | 54 | rot = rotateN(n) 55 | flag = True 56 | 57 | for i in range(len(rot)): 58 | if not is_prime(int(rot[i])): 59 | flag = False 60 | 61 | return flag 62 | 63 | def primes_sieve(limit): 64 | limitn = limit+1 65 | not_prime = set() 66 | primes = [] 67 | 68 | for i in range(2, limitn): 69 | if i in not_prime: 70 | continue 71 | 72 | for f in range(i*2, limitn, i): 73 | not_prime.add(f) 74 | 75 | primes.append(i) 76 | 77 | return primes 78 | 79 | def circular_prime_count(N): 80 | result = [] 81 | primes = primes_sieve(N) 82 | for i in primes: 83 | if is_circular_prime(i): 84 | result.append(i) 85 | return len(result) 86 | n_result = circular_prime_count(Nt)+2 87 | 88 | print ("Number of circular primes up to {} is as following: {}".format(Nt, n_result)) 89 | -------------------------------------------------------------------------------- /Maths/Coin_3_5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Jan 30 19:59:36 2018 4 | 5 | @author: Tirtha 6 | """ 7 | 8 | """ 9 | Simple recursive program to generate the sequence of coins (of value 3 and 5) for any amount > 8. 10 | This can be used to show that any integer amount of money (> 8) can be paid using coins of 3 and 5. 11 | """ 12 | def coins2pay(amount): 13 | # Base cases 14 | if amount==8: 15 | return [3,5] 16 | elif amount==9: 17 | return [3,3,3] 18 | elif amount==10: 19 | return [5,5] 20 | # Recursive case 21 | else: 22 | coins=coins2pay(amount-3) 23 | coins.append(3) 24 | return coins -------------------------------------------------------------------------------- /Maths/Collatz_Recursive.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Jan 22 20:01:52 2018 4 | 5 | @author: Tirtha 6 | """ 7 | """ 8 | This function computes the length of a collatz sequence by recursion. It does not store the sequence. 9 | It also determines the longest Collatz sequence up to some given number. 10 | """ 11 | import time 12 | t1=time.time() 13 | def collatz_length(seed,count): 14 | # Base case 15 | n=seed 16 | if n==1: 17 | return count 18 | elif (n%2==0): 19 | return collatz_length(n/2,count+1) 20 | else: 21 | return collatz_length(3*n+1,count+1) 22 | 23 | Nt = 60000 24 | result = [] 25 | for i in range(2,Nt+1): 26 | result.append(collatz_length(i,0)) 27 | 28 | num = 2 + result.index(max(result)) 29 | 30 | print ("\nThe longest sequence has {rt} terms and it is produced by the number {num2}".format(rt = max(result), num2 = num)) 31 | 32 | t2=time.time() 33 | print("Time taken",t2-t1) 34 | -------------------------------------------------------------------------------- /Maths/Collatz_seq.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Spyder Editor 4 | 5 | Longest Collatz sequence 6 | """ 7 | import matplotlib.pyplot as plt 8 | # Upper limit up to which collatz sequence will be generated 9 | Nt = 30000 10 | # Returns main sequence 11 | def collatz(n): 12 | collatz_seq=[n] 13 | while n!=1: 14 | if (n%2==0): 15 | n/=2 16 | else: 17 | n=3*n+1 18 | collatz_seq.append(n) 19 | return collatz_seq 20 | 21 | # Returns length of the sequence if 'n' is passed 22 | def collatz_length(n): 23 | return len(collatz(n)) 24 | 25 | #n = int(input("Enter a number: ")) 26 | result = [] 27 | 28 | # Brute force check up to given number 29 | for i in range(2,Nt+1): 30 | result.append(collatz_length(i)) 31 | 32 | num = 2 + result.index(max(result)) 33 | print ("\nThe longest sequence has {rt} terms and it is produced by the number {num2}".format(rt = max(result), num2 = num)) 34 | 35 | #print ("And it looks like this...\n") 36 | #print(collatz(num)) 37 | 38 | print ("\n The evolution of the sequence looks like...\n") 39 | plt.plot(collatz(num)) 40 | plt.show() 41 | 42 | # The distribution of the number of terms in Collatz sequence is plotted 43 | print ("\n The distribution looks like following...\n") 44 | 45 | #Plotting the histogram 46 | plt.hist(result,50) 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Maths/Fourier_Waveform_NumPy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Fri Apr 7 17:41:53 2017 4 | 5 | @author: Tirtha 6 | """ 7 | 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | from pylab import rcParams 11 | 12 | rcParams['figure.figsize'] = 10, 6 13 | 14 | # Fourier series of Triangular Waveform 15 | #=============================================== 16 | x = np.linspace(-2*np.pi,2*np.pi, 200) 17 | #y = (8/(np.pi**2))*np.sin(x) 18 | #plt.plot(x,y) 19 | # Feel free to change the numbers '57' and '5' around to see what happens 20 | for j in range(4,57,5): 21 | y = (8/(np.pi**2))*np.sin(x) 22 | for i in range(3,j): 23 | if i%2!=0: 24 | y += (8/(np.pi**2))*((-1)**((i-1)/2))*(1/i**2)*np.sin(i*x) 25 | 26 | plt.plot(x,y) 27 | 28 | plt.title("Fourier approx. of triangular waveform", fontsize=20) 29 | plt.xlabel("Time-scale", fontsize=20) 30 | plt.ylabel("Magnitude", fontsize=20) 31 | plt.show() 32 | 33 | # Fourier series of Square Waveform 34 | #=============================================== 35 | x = np.linspace(-2*np.pi,2*np.pi, 200) 36 | y = (4/(np.pi))*np.sin(x) 37 | #plt.plot(x,y) 38 | 39 | # Feel free to change the numbers '57' and '5' around to see what happens 40 | for j in range(4,57,5): 41 | y = (4/(np.pi))*np.sin(x) 42 | for i in range(3,j): 43 | if i%2!=0: 44 | y += (4/(np.pi))*(1/i)*np.sin(i*x) 45 | 46 | plt.plot(x,y) 47 | 48 | plt.title("Fourier approx. of square waveform", fontsize=20) 49 | plt.xlabel("Time-scale", fontsize=20) 50 | plt.ylabel("Magnitude", fontsize=20) 51 | plt.show() -------------------------------------------------------------------------------- /Maths/Hanoi_Tower.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Jan 30 20:30:53 2018 4 | 5 | @author: Tirtha 6 | """ 7 | """ 8 | Recursive program to generate the sequence of moves to solve Tower of Hanoi problem for any number of disks 9 | """ 10 | def HanoiTower(n,source,dest,storage): 11 | if n==1: 12 | print("Move disk from {source} to {dest}") 13 | elif n==2: 14 | print(f"Move a disk from {source} to {storage}") 15 | print(f"Move a disk from {source} to {dest}") 16 | print(f"Move a disk from {storage} to {dest}") 17 | else: 18 | HanoiTower(n-1,source,storage,dest) 19 | print(f"Move disk from {source} to {dest}") 20 | HanoiTower(n-1,storage,dest,source) 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Maths/Linear_equation_solve.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Apr 8 15:27:51 2017 4 | 5 | @author: Tirtha 6 | """ 7 | import numpy as np 8 | import time 9 | 10 | n_var = int(input ("How many unknowns you want to solve for? ")) 11 | coeff =[] 12 | B = [] 13 | flag = True 14 | 15 | print ("\nOK. Your equation system looks like following...\n") 16 | 17 | # Printing the equation system for ease of user 18 | for j in range (1,n_var+1): 19 | 20 | for i in range (1, n_var): 21 | print ('a{}{}x{}+'.format(j,i,i), end='') 22 | print ('a{}{}x{} '.format(j,n_var,n_var), end='') 23 | print ('= b{} ..... (EQN. {})'.format(j,j)) 24 | 25 | print ("\nNow you will be asked to enter coefficient matrix first i.e. left-hand side of the above equation system. ", end='') 26 | print ("Please enter the exact number of coefficients as asked for") 27 | 28 | for i in range(n_var): 29 | if flag: 30 | eqcoeff = input("Please enter the {} coefficient(s) of the EQN. {}, separated by spaces only (i.e. no comma or any other punctuation): ".format(n_var, i+1)) 31 | eqcoeff = eqcoeff.split() 32 | if (len(eqcoeff)!=n_var): 33 | print ("\nWrong # of input, please check again.") 34 | flag = False 35 | else: 36 | for j in range(len(eqcoeff)): 37 | coeff.append(float(eqcoeff[j])) 38 | """ 39 | try: 40 | coeff.append(float(eqcoeff[j])) 41 | except ValueError: 42 | print ("\nNON-NUMERIC INPUT, PROGRAM TERMINATING!") 43 | flag = False 44 | break 45 | """ 46 | if flag: 47 | 48 | coeff = np.array(coeff) 49 | coeff = coeff.reshape(n_var, n_var) 50 | A = coeff 51 | 52 | if (np.linalg.det(A)==0): 53 | print ("\nLinearly dependent system, no unique solution possible!") 54 | else: 55 | rhs = input("Now please enter the {} right hand side values of the linear equation system, separated by spaces only (i.e. no comma or any other punctuation): ".format(n_var)) 56 | rhs = rhs.split() 57 | if (len(rhs)!=n_var): 58 | print ("Wrong # of input, please check again.") 59 | flag = False 60 | for j in range(len(rhs)): 61 | B.append(float(rhs[j])) 62 | """ 63 | try: 64 | B.append(float(rhs[j])) 65 | except ValueError: 66 | print ("\nNON-NUMERIC INPUT, PROGRAM TERMINATING!") 67 | flag = False 68 | break 69 | """ 70 | #A_inv = np.linalg.inv(A) 71 | if flag: 72 | x = np.linalg.solve(A,B) 73 | # Introducing a small delay before printing the result, just for fun :) 74 | print ("\nSolving the linear equation system, please wait...") 75 | time.sleep(3) 76 | print ("\nYour unknown(s) are as follows\n") 77 | for i in range(n_var): 78 | print ("x{} = {}".format(i+1,round(x[i],3))) 79 | -------------------------------------------------------------------------------- /Maths/Neumann_random_generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Apr 19 00:02:21 2017 4 | @author: Tirtha 5 | 6 | Generate 3- or 4-digit random numbers by Neumann Pseudo-Random generation process 7 | """ 8 | def Neumann_random_generator(seed): 9 | 10 | n = seed 11 | random = [] 12 | random.append(n) 13 | count = 1 14 | 15 | while count<50000: 16 | m = 7*n**2+13*n**3+19*n**4 17 | strm = str(m) 18 | if len(strm) < 8: 19 | strm = '0'*(8-len(strm))+strm 20 | randn = int(strm[2:6]) 21 | n = randn 22 | random.append(randn) 23 | #set_rnd = set(random) 24 | count +=1 25 | # if (len(set_rnd)!= len(random)) or (False): 26 | # random.pop() 27 | # break 28 | 29 | return (random) 30 | 31 | ask_seed = int(input ("Please enter the seed:")) 32 | r = Neumann_random_generator(ask_seed) 33 | 34 | #for i in r: 35 | #print (i, end=' ') 36 | 37 | # Plotting the histogram of the numbers to see distribution 38 | import matplotlib.pyplot as plt 39 | 40 | plt.hist(r,50, alpha=0.6) -------------------------------------------------------------------------------- /Maths/Numpy practice.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# NumPy Practice\n", 8 | "## Vectors, Matrices \n", 9 | "* object type\n", 10 | "* dimension\n", 11 | "* size \n", 12 | "* shape\n", 13 | "* data type" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 1, 19 | "metadata": { 20 | "collapsed": false 21 | }, 22 | "outputs": [ 23 | { 24 | "name": "stdout", 25 | "output_type": "stream", 26 | "text": [ 27 | "Type/Class of this object: \n", 28 | "Here is the vector\n", 29 | "--------------------\n", 30 | " [1 2 3]\n" 31 | ] 32 | } 33 | ], 34 | "source": [ 35 | "my_list = [1,2,3]\n", 36 | "import numpy as np\n", 37 | "arr = np.array(my_list)\n", 38 | "print(\"Type/Class of this object:\",type(arr))\n", 39 | "print(\"Here is the vector\\n--------------------\\n\",arr)" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": 2, 45 | "metadata": { 46 | "collapsed": false 47 | }, 48 | "outputs": [ 49 | { 50 | "name": "stdout", 51 | "output_type": "stream", 52 | "text": [ 53 | "Type/Class of this object: \n", 54 | "Here is the matrix\n", 55 | "----------\n", 56 | " [[1 2 3]\n", 57 | " [4 5 6]\n", 58 | " [7 8 9]] \n", 59 | "----------\n", 60 | "Dimension of this matrix: 2\n", 61 | "Size of this matrix: 9\n", 62 | "Shape of this matrix: (3, 3)\n", 63 | "Data type of this matrix: int32\n", 64 | "Data type of the modified matrix: float64\n", 65 | "\n", 66 | "\n", 67 | "Even tuples can be converted to ndarrays...\n", 68 | "We write b = np.array([(1.5,2,3), (4,5,6)])\n", 69 | "Matrix made from tuples, not lists\n", 70 | "---------------------------------------\n", 71 | "[[ 1.5 2. 3. ]\n", 72 | " [ 4. 5. 6. ]]\n" 73 | ] 74 | } 75 | ], 76 | "source": [ 77 | "my_mat = [[1,2,3],[4,5,6],[7,8,9]]\n", 78 | "mat = np.array(my_mat)\n", 79 | "print(\"Type/Class of this object:\",type(mat))\n", 80 | "print(\"Here is the matrix\\n----------\\n\",mat,\"\\n----------\")\n", 81 | "print(\"Dimension of this matrix: \",mat.ndim,sep='') #ndim gives the dimensison, 2 for a matrix, 1 for a vector\n", 82 | "print(\"Size of this matrix: \", mat.size,sep='') #size gives the total number of elements\n", 83 | "print(\"Shape of this matrix: \", mat.shape,sep='') #shape gives the number of elements along each axes (dimension)\n", 84 | "print(\"Data type of this matrix: \", mat.dtype,sep='') #dtype gives the data type contained in the array\n", 85 | "\n", 86 | "my_mat = [[1.1,2,3],[4,5.2,6],[7,8.3,9]]\n", 87 | "mat = np.array(my_mat)\n", 88 | "print(\"Data type of the modified matrix: \", mat.dtype,sep='') #dtype gives the data type contained in the array\n", 89 | "print(\"\\n\\nEven tuples can be converted to ndarrays...\")\n", 90 | "\n", 91 | "b = np.array([(1.5,2,3), (4,5,6)])\n", 92 | "print(\"We write b = np.array([(1.5,2,3), (4,5,6)])\")\n", 93 | "print(\"Matrix made from tuples, not lists\\n---------------------------------------\")\n", 94 | "print(b)" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "## 'arange' and 'linspace'" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": 3, 107 | "metadata": { 108 | "collapsed": false 109 | }, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | "A series of numbers: [ 5 6 7 8 9 10 11 12 13 14 15]\n" 116 | ] 117 | } 118 | ], 119 | "source": [ 120 | "print(\"A series of numbers:\",np.arange(5,16)) # A series of numbers from low to high" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 4, 126 | "metadata": { 127 | "collapsed": false 128 | }, 129 | "outputs": [ 130 | { 131 | "name": "stdout", 132 | "output_type": "stream", 133 | "text": [ 134 | "Numbers spaced apart by 2: [ 0 2 4 6 8 10]\n" 135 | ] 136 | } 137 | ], 138 | "source": [ 139 | "print(\"Numbers spaced apart by 2:\",np.arange(0,11,2)) # Numbers spaced apart by 2" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 5, 145 | "metadata": { 146 | "collapsed": false 147 | }, 148 | "outputs": [ 149 | { 150 | "name": "stdout", 151 | "output_type": "stream", 152 | "text": [ 153 | "Numbers spaced apart by float: [ 0. 2.5 5. 7.5 10. ]\n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "print(\"Numbers spaced apart by float:\",np.arange(0,11,2.5)) # Numbers spaced apart by 2.5" 159 | ] 160 | }, 161 | { 162 | "cell_type": "code", 163 | "execution_count": 6, 164 | "metadata": { 165 | "collapsed": false 166 | }, 167 | "outputs": [ 168 | { 169 | "name": "stdout", 170 | "output_type": "stream", 171 | "text": [ 172 | "Every 5th number from 50 in reverse order\n", 173 | " [50 45 40 35 30 25 20 15 10 5 0]\n" 174 | ] 175 | } 176 | ], 177 | "source": [ 178 | "print(\"Every 5th number from 50 in reverse order\\n\",np.arange(50,-1,-5))" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 7, 184 | "metadata": { 185 | "collapsed": false 186 | }, 187 | "outputs": [ 188 | { 189 | "name": "stdout", 190 | "output_type": "stream", 191 | "text": [ 192 | "21 linearly spaced numbers between 1 and 5\n", 193 | "--------------------------------------------\n", 194 | "[ 1. 1.2 1.4 1.6 1.8 2. 2.2 2.4 2.6 2.8 3. 3.2 3.4 3.6 3.8\n", 195 | " 4. 4.2 4.4 4.6 4.8 5. ]\n" 196 | ] 197 | } 198 | ], 199 | "source": [ 200 | "print(\"21 linearly spaced numbers between 1 and 5\\n--------------------------------------------\")\n", 201 | "print(np.linspace(1,5,21))" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": {}, 207 | "source": [ 208 | "## Zeroes, Ones, empty, and Identity matrix" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": 8, 214 | "metadata": { 215 | "collapsed": false 216 | }, 217 | "outputs": [ 218 | { 219 | "name": "stdout", 220 | "output_type": "stream", 221 | "text": [ 222 | "Vector of zeroes\n", 223 | "---------------------\n", 224 | "[ 0. 0. 0. 0. 0.]\n", 225 | "Matrix of zeroes\n", 226 | "--------------------\n", 227 | "[[ 0. 0. 0. 0.]\n", 228 | " [ 0. 0. 0. 0.]\n", 229 | " [ 0. 0. 0. 0.]]\n" 230 | ] 231 | } 232 | ], 233 | "source": [ 234 | "print(\"Vector of zeroes\\n---------------------\")\n", 235 | "print(np.zeros(5))\n", 236 | "print(\"Matrix of zeroes\\n--------------------\")\n", 237 | "print(np.zeros((3,4))) # Notice Tuples" 238 | ] 239 | }, 240 | { 241 | "cell_type": "code", 242 | "execution_count": 9, 243 | "metadata": { 244 | "collapsed": false 245 | }, 246 | "outputs": [ 247 | { 248 | "name": "stdout", 249 | "output_type": "stream", 250 | "text": [ 251 | "Vector of ones\n", 252 | "---------------------\n", 253 | "[ 1. 1. 1. 1. 1.]\n", 254 | "Matrix of ones\n", 255 | "---------------------\n", 256 | "[[ 1. 1.]\n", 257 | " [ 1. 1.]\n", 258 | " [ 1. 1.]\n", 259 | " [ 1. 1.]\n", 260 | " [ 1. 1.]]\n", 261 | "Matrix of 5's\n", 262 | "---------------------\n", 263 | "[[ 5. 5. 5. 5. 5.]\n", 264 | " [ 5. 5. 5. 5. 5.]\n", 265 | " [ 5. 5. 5. 5. 5.]]\n" 266 | ] 267 | } 268 | ], 269 | "source": [ 270 | "print(\"Vector of ones\\n---------------------\")\n", 271 | "print(np.ones(5))\n", 272 | "print(\"Matrix of ones\\n---------------------\")\n", 273 | "print(np.ones((5,2))) # Note matrix dimension specified by Tuples\n", 274 | "print(\"Matrix of 5's\\n---------------------\")\n", 275 | "print(5*np.ones((3,5)))" 276 | ] 277 | }, 278 | { 279 | "cell_type": "code", 280 | "execution_count": 3, 281 | "metadata": { 282 | "collapsed": false 283 | }, 284 | "outputs": [ 285 | { 286 | "name": "stdout", 287 | "output_type": "stream", 288 | "text": [ 289 | "Empty matrix\n", 290 | "-------------\n", 291 | " [[ 0. 0. 0. 0. 0.]\n", 292 | " [ 0. 0. 0. 0. 0.]\n", 293 | " [ 0. 0. 0. 0. 0.]]\n" 294 | ] 295 | } 296 | ], 297 | "source": [ 298 | "print(\"Empty matrix\\n-------------\\n\", np.empty((3,5)))" 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": 4, 304 | "metadata": { 305 | "collapsed": false 306 | }, 307 | "outputs": [ 308 | { 309 | "name": "stdout", 310 | "output_type": "stream", 311 | "text": [ 312 | "Identity matrix of dimension (4, 4)\n", 313 | "[[ 1. 0. 0. 0.]\n", 314 | " [ 0. 1. 0. 0.]\n", 315 | " [ 0. 0. 1. 0.]\n", 316 | " [ 0. 0. 0. 1.]]\n" 317 | ] 318 | } 319 | ], 320 | "source": [ 321 | "mat1 = np.eye(4) \n", 322 | "print(\"Identity matrix of dimension\", mat1.shape)\n", 323 | "print(mat1)" 324 | ] 325 | }, 326 | { 327 | "cell_type": "markdown", 328 | "metadata": {}, 329 | "source": [ 330 | "## Random number generation" 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": 12, 336 | "metadata": { 337 | "collapsed": false 338 | }, 339 | "outputs": [ 340 | { 341 | "name": "stdout", 342 | "output_type": "stream", 343 | "text": [ 344 | "Random number generation (from Uniform distribution)\n", 345 | "[[ 0.25506558 0.75756507 0.55128715]\n", 346 | " [ 0.04533328 0.7999211 0.81843587]]\n" 347 | ] 348 | } 349 | ], 350 | "source": [ 351 | "print(\"Random number generation (from Uniform distribution)\")\n", 352 | "print(np.random.rand(2,3)) # 2 by 3 matrix with random numbers ranging from 0 to 1, Note no Tuple is necessary " 353 | ] 354 | }, 355 | { 356 | "cell_type": "code", 357 | "execution_count": 13, 358 | "metadata": { 359 | "collapsed": false 360 | }, 361 | "outputs": [ 362 | { 363 | "name": "stdout", 364 | "output_type": "stream", 365 | "text": [ 366 | "Numbers from Normal distribution with zero mean and standard deviation 1 i.e. standard normal\n", 367 | "[[-1.01557146 -0.57295568 1.93753693]\n", 368 | " [ 1.24708078 -0.78489921 1.43625099]\n", 369 | " [ 0.90337139 -2.06767273 -2.17374497]\n", 370 | " [-0.04516691 -0.6602149 -0.03035842]]\n" 371 | ] 372 | } 373 | ], 374 | "source": [ 375 | "print(\"Numbers from Normal distribution with zero mean and standard deviation 1 i.e. standard normal\")\n", 376 | "print(np.random.randn(4,3))" 377 | ] 378 | }, 379 | { 380 | "cell_type": "code", 381 | "execution_count": 12, 382 | "metadata": { 383 | "collapsed": false 384 | }, 385 | "outputs": [ 386 | { 387 | "name": "stdout", 388 | "output_type": "stream", 389 | "text": [ 390 | "Random integer vector: [81 10 78 60 57 1 1 54 36 29]\n", 391 | "\n", 392 | "Random integer matrix\n", 393 | "[[72 81 22 86]\n", 394 | " [66 46 44 74]\n", 395 | " [53 15 2 11]\n", 396 | " [32 92 42 73]]\n", 397 | "\n", 398 | "20 samples drawn from a dice throw: [1 6 3 2 4 4 6 2 6 5 2 6 5 5 4 2 1 3 3 5]\n" 399 | ] 400 | } 401 | ], 402 | "source": [ 403 | "print(\"Random integer vector:\",np.random.randint(1,100,10)) #randint (low, high, # of samples to be drawn)\n", 404 | "print (\"\\nRandom integer matrix\")\n", 405 | "print(np.random.randint(1,100,(4,4))) #randint (low, high, # of samples to be drawn in a tuple to form a matrix)\n", 406 | "print(\"\\n20 samples drawn from a dice throw:\",np.random.randint(1,7,20)) # 20 samples drawn from a dice throw" 407 | ] 408 | }, 409 | { 410 | "cell_type": "markdown", 411 | "metadata": {}, 412 | "source": [ 413 | "## Reshaping, min, max, sort" 414 | ] 415 | }, 416 | { 417 | "cell_type": "code", 418 | "execution_count": 18, 419 | "metadata": { 420 | "collapsed": false 421 | }, 422 | "outputs": [ 423 | { 424 | "name": "stdout", 425 | "output_type": "stream", 426 | "text": [ 427 | "Shape of a: (30,)\n", 428 | "Shape of b: (2, 3, 5)\n", 429 | "Shape of c: (6, 5)\n", 430 | "\n", 431 | "a looks like\n", 432 | " -------------------- \n", 433 | " [87 73 64 71 61 10 15 25 88 56 53 7 67 36 13 60 41 22 70 72 67 82 27 11 90\n", 434 | " 36 44 23 50 76] \n", 435 | " --------------------\n", 436 | "\n", 437 | "b looks like\n", 438 | " -------------------- \n", 439 | " [[[87 73 64 71 61]\n", 440 | " [10 15 25 88 56]\n", 441 | " [53 7 67 36 13]]\n", 442 | "\n", 443 | " [[60 41 22 70 72]\n", 444 | " [67 82 27 11 90]\n", 445 | " [36 44 23 50 76]]] \n", 446 | " --------------------\n", 447 | "\n", 448 | "c looks like\n", 449 | " -------------------- \n", 450 | " [[87 73 64 71 61]\n", 451 | " [10 15 25 88 56]\n", 452 | " [53 7 67 36 13]\n", 453 | " [60 41 22 70 72]\n", 454 | " [67 82 27 11 90]\n", 455 | " [36 44 23 50 76]] \n", 456 | " --------------------\n", 457 | "\n", 458 | "Vector of random integers\n", 459 | " -------------------------------------------------- \n", 460 | " [62 21 24 40 54 41 28 38 89 63]\n", 461 | "\n", 462 | "Here is the sorted vector\n", 463 | " -------------------------------------------------- \n", 464 | " [21 24 28 38 40 41 54 62 63 89]\n", 465 | "\n", 466 | "5x5 Matrix of random integers\n", 467 | " -------------------------------------------------- \n", 468 | " [[84 76 60 34 65]\n", 469 | " [49 27 96 16 44]\n", 470 | " [19 1 49 32 77]\n", 471 | " [94 84 23 59 37]\n", 472 | " [58 46 89 79 57]]\n", 473 | "\n", 474 | "Here is the sorted matrix along each row\n", 475 | " -------------------------------------------------- \n", 476 | " [[34 60 65 76 84]\n", 477 | " [16 27 44 49 96]\n", 478 | " [ 1 19 32 49 77]\n", 479 | " [23 37 59 84 94]\n", 480 | " [46 57 58 79 89]]\n", 481 | "\n", 482 | "Here is the sorted matrix along each column\n", 483 | " -------------------------------------------------- \n", 484 | " [[19 1 23 16 37]\n", 485 | " [49 27 49 32 44]\n", 486 | " [58 46 60 34 57]\n", 487 | " [84 76 89 59 65]\n", 488 | " [94 84 96 79 77]]\n" 489 | ] 490 | } 491 | ], 492 | "source": [ 493 | "from numpy.random import randint as ri\n", 494 | "a = ri(1,100,30)\n", 495 | "b = a.reshape(2,3,5)\n", 496 | "c = a.reshape(6,5)\n", 497 | "print (\"Shape of a:\", a.shape)\n", 498 | "print (\"Shape of b:\", b.shape)\n", 499 | "print (\"Shape of c:\", c.shape)\n", 500 | "print(\"\\na looks like\\n\",'-'*20,\"\\n\",a,\"\\n\",'-'*20)\n", 501 | "print(\"\\nb looks like\\n\",'-'*20,\"\\n\",b,\"\\n\",'-'*20)\n", 502 | "print(\"\\nc looks like\\n\",'-'*20,\"\\n\",c,\"\\n\",'-'*20)\n", 503 | "\n", 504 | "A = ri(1,100,10) # Vector of random interegrs\n", 505 | "print(\"\\nVector of random integers\\n\",'-'*50,\"\\n\",A)\n", 506 | "print(\"\\nHere is the sorted vector\\n\",'-'*50,\"\\n\",np.sort(A, kind='mergesort'))\n", 507 | "\n", 508 | "M = ri(1,100,25).reshape(5,5) # Matrix of random interegrs\n", 509 | "print(\"\\n5x5 Matrix of random integers\\n\",'-'*50,\"\\n\",M)\n", 510 | "print(\"\\nHere is the sorted matrix along each row\\n\",'-'*50,\"\\n\",np.sort(M, kind='mergesort')) # Default axis =1\n", 511 | "print(\"\\nHere is the sorted matrix along each column\\n\",'-'*50,\"\\n\",np.sort(M, axis=0, kind='mergesort'))" 512 | ] 513 | }, 514 | { 515 | "cell_type": "code", 516 | "execution_count": 19, 517 | "metadata": { 518 | "collapsed": false 519 | }, 520 | "outputs": [ 521 | { 522 | "name": "stdout", 523 | "output_type": "stream", 524 | "text": [ 525 | "Max of a: 90\n", 526 | "Max of b: 90\n", 527 | "Max of a location: 24\n", 528 | "Max of b location: 24\n", 529 | "Max of c location: 24\n" 530 | ] 531 | } 532 | ], 533 | "source": [ 534 | "print(\"Max of a:\", a.max())\n", 535 | "print(\"Max of b:\", b.max())\n", 536 | "print(\"Max of a location:\", a.argmax())\n", 537 | "print(\"Max of b location:\", b.argmax())\n", 538 | "print(\"Max of c location:\", b.argmax())" 539 | ] 540 | }, 541 | { 542 | "cell_type": "markdown", 543 | "metadata": {}, 544 | "source": [ 545 | "## Indexing and slicing" 546 | ] 547 | }, 548 | { 549 | "cell_type": "code", 550 | "execution_count": 20, 551 | "metadata": { 552 | "collapsed": false 553 | }, 554 | "outputs": [ 555 | { 556 | "name": "stdout", 557 | "output_type": "stream", 558 | "text": [ 559 | "Array: [ 0 1 2 3 4 5 6 7 8 9 10]\n", 560 | "Element at 7th index is: 7\n", 561 | "Elements from 3rd to 5th index are: [3 4 5]\n", 562 | "Elements up to 4th index are: [0 1 2 3]\n", 563 | "Elements from last backwards are: [10 9 8 7 6 5 4 3 2 1 0]\n", 564 | "3 Elements from last backwards are: [10 8 6]\n", 565 | "New array: [ 0 2 4 6 8 10 12 14 16 18 20]\n", 566 | "Elements at 2nd, 4th, and 9th index are: [ 4 8 18]\n" 567 | ] 568 | } 569 | ], 570 | "source": [ 571 | "arr = np.arange(0,11)\n", 572 | "print(\"Array:\",arr)\n", 573 | "print(\"Element at 7th index is:\", arr[7])\n", 574 | "print(\"Elements from 3rd to 5th index are:\", arr[3:6])\n", 575 | "print(\"Elements up to 4th index are:\", arr[:4])\n", 576 | "print(\"Elements from last backwards are:\", arr[-1::-1])\n", 577 | "print(\"3 Elements from last backwards are:\", arr[-1:-6:-2])\n", 578 | "\n", 579 | "arr = np.arange(0,21,2)\n", 580 | "print(\"New array:\",arr)\n", 581 | "print(\"Elements at 2nd, 4th, and 9th index are:\", arr[[2,4,9]]) # Pass a list as a index to subset" 582 | ] 583 | }, 584 | { 585 | "cell_type": "code", 586 | "execution_count": 21, 587 | "metadata": { 588 | "collapsed": false 589 | }, 590 | "outputs": [ 591 | { 592 | "name": "stdout", 593 | "output_type": "stream", 594 | "text": [ 595 | "Matrix of random 2-digit numbers\n", 596 | "--------------------------------\n", 597 | " [[66 78 75 78 32]\n", 598 | " [53 42 94 92 99]\n", 599 | " [96 98 12 40 49]]\n", 600 | "\n", 601 | "Double bracket indexing\n", 602 | "------------------------\n", 603 | "Element in row index 1 and column index 2: 94\n", 604 | "\n", 605 | "Single bracket with comma indexing\n", 606 | "----------------------------------\n", 607 | "Element in row index 1 and column index 2: 94\n", 608 | "\n", 609 | "Row or column extract\n", 610 | "----------------------\n", 611 | "Entire row at index 2: [96 98 12 40 49]\n", 612 | "Entire column at index 3: [78 92 40]\n", 613 | "\n", 614 | "Subsetting sub-matrices\n", 615 | "--------------------------\n", 616 | "Matrix with row indices 1 and 2 and column indices 3 and 4\n", 617 | " [[92 99]\n", 618 | " [40 49]]\n", 619 | "Matrix with row indices 0 and 1 and column indices 1 and 3\n", 620 | " [[78 78]\n", 621 | " [42 92]]\n" 622 | ] 623 | } 624 | ], 625 | "source": [ 626 | "mat = np.array(ri(10,100,15)).reshape(3,5)\n", 627 | "print(\"Matrix of random 2-digit numbers\\n--------------------------------\\n\",mat)\n", 628 | "\n", 629 | "print(\"\\nDouble bracket indexing\\n------------------------\")\n", 630 | "print(\"Element in row index 1 and column index 2:\", mat[1][2])\n", 631 | "\n", 632 | "print(\"\\nSingle bracket with comma indexing\\n----------------------------------\")\n", 633 | "print(\"Element in row index 1 and column index 2:\", mat[1,2])\n", 634 | "print(\"\\nRow or column extract\\n----------------------\")\n", 635 | "\n", 636 | "print(\"Entire row at index 2:\", mat[2])\n", 637 | "print(\"Entire column at index 3:\", mat[:,3])\n", 638 | "\n", 639 | "print(\"\\nSubsetting sub-matrices\\n--------------------------\")\n", 640 | "print(\"Matrix with row indices 1 and 2 and column indices 3 and 4\\n\", mat[1:3,3:5])\n", 641 | "print(\"Matrix with row indices 0 and 1 and column indices 1 and 3\\n\", mat[0:2,[1,3]])" 642 | ] 643 | }, 644 | { 645 | "cell_type": "markdown", 646 | "metadata": {}, 647 | "source": [ 648 | "### Conditional subsetting" 649 | ] 650 | }, 651 | { 652 | "cell_type": "code", 653 | "execution_count": 22, 654 | "metadata": { 655 | "collapsed": false 656 | }, 657 | "outputs": [ 658 | { 659 | "name": "stdout", 660 | "output_type": "stream", 661 | "text": [ 662 | "Matrix of random 2-digit numbers\n", 663 | "--------------------------------\n", 664 | " [[27 13 20 56 86]\n", 665 | " [32 99 90 66 79]\n", 666 | " [66 44 22 57 87]]\n", 667 | "Elements greater than 50\n", 668 | " [56 86 99 90 66 79 66 57 87]\n" 669 | ] 670 | } 671 | ], 672 | "source": [ 673 | "mat = np.array(ri(10,100,15)).reshape(3,5)\n", 674 | "print(\"Matrix of random 2-digit numbers\\n--------------------------------\\n\",mat)\n", 675 | "print (\"Elements greater than 50\\n\", mat[mat>50])" 676 | ] 677 | }, 678 | { 679 | "cell_type": "markdown", 680 | "metadata": {}, 681 | "source": [ 682 | "### Slicing keeps the original reference, be aware of mutating the original array" 683 | ] 684 | }, 685 | { 686 | "cell_type": "code", 687 | "execution_count": 39, 688 | "metadata": { 689 | "collapsed": false 690 | }, 691 | "outputs": [ 692 | { 693 | "name": "stdout", 694 | "output_type": "stream", 695 | "text": [ 696 | "Original matrix\n", 697 | "[[11 12 13]\n", 698 | " [21 22 23]\n", 699 | " [31 32 33]]\n", 700 | "\n", 701 | "Sliced matrix\n", 702 | "[[11 12]\n", 703 | " [21 22]]\n", 704 | "\n", 705 | "Change the sliced matrix\n", 706 | "[[1000 12]\n", 707 | " [ 21 22]]\n", 708 | "\n", 709 | "But the original matrix? WHOA! It got changed too!\n", 710 | "[[1000 12 13]\n", 711 | " [ 21 22 23]\n", 712 | " [ 31 32 33]]\n", 713 | "\n", 714 | "Doing it again little differently now...\n", 715 | "\n", 716 | "Original matrix\n", 717 | "[[11 12 13]\n", 718 | " [21 22 23]\n", 719 | " [31 32 33]]\n", 720 | "\n", 721 | "Sliced matrix\n", 722 | "[[11 12]\n", 723 | " [21 22]]\n", 724 | "\n", 725 | "Change the sliced matrix\n", 726 | "[[1000 12]\n", 727 | " [ 21 22]]\n", 728 | "\n", 729 | "But the original matrix? NO CHANGE this time:)\n", 730 | "[[11 12 13]\n", 731 | " [21 22 23]\n", 732 | " [31 32 33]]\n" 733 | ] 734 | } 735 | ], 736 | "source": [ 737 | "mat = np.array([[11,12,13],[21,22,23],[31,32,33]])\n", 738 | "print(\"Original matrix\")\n", 739 | "print(mat)\n", 740 | "mat_slice = mat[:2,:2]\n", 741 | "print (\"\\nSliced matrix\")\n", 742 | "print(mat_slice)\n", 743 | "print (\"\\nChange the sliced matrix\")\n", 744 | "mat_slice[0,0] = 1000\n", 745 | "print (mat_slice)\n", 746 | "print(\"\\nBut the original matrix? WHOA! It got changed too!\")\n", 747 | "print(mat)\n", 748 | "\n", 749 | "# Little different way to create a copy of the slixed matrix\n", 750 | "print (\"\\nDoing it again little differently now...\\n\")\n", 751 | "mat = np.array([[11,12,13],[21,22,23],[31,32,33]])\n", 752 | "print(\"Original matrix\")\n", 753 | "print(mat)\n", 754 | "mat_slice = np.array(mat[:2,:2]) # Notice the np.array command to create a new array not just slicing\n", 755 | "print (\"\\nSliced matrix\")\n", 756 | "print(mat_slice)\n", 757 | "print (\"\\nChange the sliced matrix\")\n", 758 | "mat_slice[0,0] = 1000\n", 759 | "print (mat_slice)\n", 760 | "print(\"\\nBut the original matrix? NO CHANGE this time:)\")\n", 761 | "print(mat)" 762 | ] 763 | }, 764 | { 765 | "cell_type": "markdown", 766 | "metadata": {}, 767 | "source": [ 768 | "## Array operations (array-array, array-scalar, universal functions)" 769 | ] 770 | }, 771 | { 772 | "cell_type": "code", 773 | "execution_count": 40, 774 | "metadata": { 775 | "collapsed": false 776 | }, 777 | "outputs": [ 778 | { 779 | "name": "stdout", 780 | "output_type": "stream", 781 | "text": [ 782 | "\n", 783 | "1st Matrix of random single-digit numbers\n", 784 | "----------------------------------------\n", 785 | " [[3 7 1]\n", 786 | " [7 8 6]\n", 787 | " [3 6 9]]\n", 788 | "\n", 789 | "2nd Matrix of random single-digit numbers\n", 790 | "----------------------------------------\n", 791 | " [[8 2 7]\n", 792 | " [7 5 1]\n", 793 | " [9 5 6]]\n", 794 | "\n", 795 | "Addition\n", 796 | "------------------\n", 797 | " [[11 9 8]\n", 798 | " [14 13 7]\n", 799 | " [12 11 15]]\n", 800 | "\n", 801 | "Multiplication\n", 802 | "------------------\n", 803 | " [[24 14 7]\n", 804 | " [49 40 6]\n", 805 | " [27 30 54]]\n", 806 | "\n", 807 | "Division\n", 808 | "------------------\n", 809 | " [[ 0.375 3.5 0.14285714]\n", 810 | " [ 1. 1.6 6. ]\n", 811 | " [ 0.33333333 1.2 1.5 ]]\n", 812 | "\n", 813 | "Lineaer combination: 3*A - 2*B\n", 814 | "-----------------------------\n", 815 | " [[ -7 17 -11]\n", 816 | " [ 7 14 16]\n", 817 | " [ -9 8 15]]\n", 818 | "\n", 819 | "Addition of a scalar (100)\n", 820 | "-------------------------\n", 821 | " [[103 107 101]\n", 822 | " [107 108 106]\n", 823 | " [103 106 109]]\n", 824 | "\n", 825 | "Exponentiation, matrix cubed here\n", 826 | "----------------------------------------\n", 827 | " [[ 27 343 1]\n", 828 | " [343 512 216]\n", 829 | " [ 27 216 729]]\n", 830 | "\n", 831 | "Exponentiation, sq-root using pow function\n", 832 | "-------------------------------------------\n", 833 | " [[ 1.73205081 2.64575131 1. ]\n", 834 | " [ 2.64575131 2.82842712 2.44948974]\n", 835 | " [ 1.73205081 2.44948974 3. ]]\n" 836 | ] 837 | } 838 | ], 839 | "source": [ 840 | "mat1 = np.array(ri(1,10,9)).reshape(3,3)\n", 841 | "mat2 = np.array(ri(1,10,9)).reshape(3,3)\n", 842 | "print(\"\\n1st Matrix of random single-digit numbers\\n----------------------------------------\\n\",mat1)\n", 843 | "print(\"\\n2nd Matrix of random single-digit numbers\\n----------------------------------------\\n\",mat2)\n", 844 | "\n", 845 | "print(\"\\nAddition\\n------------------\\n\", mat1+mat2)\n", 846 | "print(\"\\nMultiplication\\n------------------\\n\", mat1*mat2)\n", 847 | "print(\"\\nDivision\\n------------------\\n\", mat1/mat2)\n", 848 | "print(\"\\nLineaer combination: 3*A - 2*B\\n-----------------------------\\n\", 3*mat1-2*mat2)\n", 849 | "\n", 850 | "print(\"\\nAddition of a scalar (100)\\n-------------------------\\n\", 100+mat1)\n", 851 | "\n", 852 | "print(\"\\nExponentiation, matrix cubed here\\n----------------------------------------\\n\", mat1**3)\n", 853 | "print(\"\\nExponentiation, sq-root using pow function\\n-------------------------------------------\\n\",pow(mat1,0.5))" 854 | ] 855 | }, 856 | { 857 | "cell_type": "markdown", 858 | "metadata": {}, 859 | "source": [ 860 | "### Broadcasting (super cool feature)" 861 | ] 862 | }, 863 | { 864 | "cell_type": "markdown", 865 | "metadata": {}, 866 | "source": [ 867 | "NumPy operations are usually done on pairs of arrays on an element-by-element basis. In the simplest case, the two arrays must have exactly the same shape.\n", 868 | "\n", 869 | "NumPy’s broadcasting rule relaxes this constraint when the arrays’ shapes meet certain constraints. When operating on two arrays, NumPy compares their shapes element-wise. It starts with the trailing dimensions, and works its way forward. Two dimensions are compatible when\n", 870 | "\n", 871 | "* **they are equal, or**\n", 872 | "* **one of them is 1**\n", 873 | "\n", 874 | "If these conditions are not met, a *ValueError: frames* are not aligned exception is thrown, indicating that the arrays have incompatible shapes. The size of the resulting array is the maximum size along each dimension of the input arrays.\n", 875 | "\n", 876 | "For more detail, please look up: https://docs.scipy.org/doc/numpy-1.10.1/user/basics.broadcasting.html\n" 877 | ] 878 | }, 879 | { 880 | "cell_type": "code", 881 | "execution_count": 47, 882 | "metadata": { 883 | "collapsed": false 884 | }, 885 | "outputs": [ 886 | { 887 | "name": "stdout", 888 | "output_type": "stream", 889 | "text": [ 890 | "[[ 0. 0. 0.]\n", 891 | " [ 0. 0. 0.]\n", 892 | " [ 0. 0. 0.]\n", 893 | " [ 0. 0. 0.]]\n" 894 | ] 895 | } 896 | ], 897 | "source": [ 898 | "start = np.zeros((4,3))\n", 899 | "print(start)" 900 | ] 901 | }, 902 | { 903 | "cell_type": "code", 904 | "execution_count": 48, 905 | "metadata": { 906 | "collapsed": false 907 | }, 908 | "outputs": [ 909 | { 910 | "name": "stdout", 911 | "output_type": "stream", 912 | "text": [ 913 | "[1 0 2]\n" 914 | ] 915 | } 916 | ], 917 | "source": [ 918 | "# create a rank 1 ndarray with 3 values\n", 919 | "add_rows = np.array([1, 0, 2])\n", 920 | "print(add_rows)" 921 | ] 922 | }, 923 | { 924 | "cell_type": "code", 925 | "execution_count": 49, 926 | "metadata": { 927 | "collapsed": false 928 | }, 929 | "outputs": [ 930 | { 931 | "name": "stdout", 932 | "output_type": "stream", 933 | "text": [ 934 | "[[ 1. 0. 2.]\n", 935 | " [ 1. 0. 2.]\n", 936 | " [ 1. 0. 2.]\n", 937 | " [ 1. 0. 2.]]\n" 938 | ] 939 | } 940 | ], 941 | "source": [ 942 | "y = start + add_rows # add to each row of 'start' using broadcasting\n", 943 | "print(y)" 944 | ] 945 | }, 946 | { 947 | "cell_type": "code", 948 | "execution_count": 50, 949 | "metadata": { 950 | "collapsed": false 951 | }, 952 | "outputs": [ 953 | { 954 | "name": "stdout", 955 | "output_type": "stream", 956 | "text": [ 957 | "[[0]\n", 958 | " [1]\n", 959 | " [2]\n", 960 | " [3]]\n" 961 | ] 962 | } 963 | ], 964 | "source": [ 965 | "# create an ndarray which is 4 x 1 to broadcast across columns\n", 966 | "add_cols = np.array([[0,1,2,3]])\n", 967 | "add_cols = add_cols.T\n", 968 | "print(add_cols)" 969 | ] 970 | }, 971 | { 972 | "cell_type": "code", 973 | "execution_count": 51, 974 | "metadata": { 975 | "collapsed": false 976 | }, 977 | "outputs": [ 978 | { 979 | "name": "stdout", 980 | "output_type": "stream", 981 | "text": [ 982 | "[[ 0. 0. 0.]\n", 983 | " [ 1. 1. 1.]\n", 984 | " [ 2. 2. 2.]\n", 985 | " [ 3. 3. 3.]]\n" 986 | ] 987 | } 988 | ], 989 | "source": [ 990 | "# add to each column of 'start' using broadcasting\n", 991 | "y = start + add_cols \n", 992 | "print(y)" 993 | ] 994 | }, 995 | { 996 | "cell_type": "code", 997 | "execution_count": 53, 998 | "metadata": { 999 | "collapsed": false 1000 | }, 1001 | "outputs": [ 1002 | { 1003 | "name": "stdout", 1004 | "output_type": "stream", 1005 | "text": [ 1006 | "[[ 100. 100. 100.]\n", 1007 | " [ 100. 100. 100.]\n", 1008 | " [ 100. 100. 100.]\n", 1009 | " [ 100. 100. 100.]]\n" 1010 | ] 1011 | } 1012 | ], 1013 | "source": [ 1014 | "# this will just broadcast in both dimensions\n", 1015 | "add_scalar = np.array([100]) \n", 1016 | "print(start+add_scalar)" 1017 | ] 1018 | }, 1019 | { 1020 | "cell_type": "markdown", 1021 | "metadata": {}, 1022 | "source": [ 1023 | "### NumPy mathematical functions on array" 1024 | ] 1025 | }, 1026 | { 1027 | "cell_type": "code", 1028 | "execution_count": 41, 1029 | "metadata": { 1030 | "collapsed": false, 1031 | "scrolled": false 1032 | }, 1033 | "outputs": [ 1034 | { 1035 | "name": "stdout", 1036 | "output_type": "stream", 1037 | "text": [ 1038 | "\n", 1039 | "1st Matrix of random single-digit numbers\n", 1040 | "----------------------------------------\n", 1041 | " [[2 6 4]\n", 1042 | " [3 7 3]\n", 1043 | " [2 4 2]]\n", 1044 | "\n", 1045 | "2nd Matrix of random single-digit numbers\n", 1046 | "----------------------------------------\n", 1047 | " [[8 2 8]\n", 1048 | " [3 9 6]\n", 1049 | " [1 5 4]]\n", 1050 | "\n", 1051 | "Sq-root of 1st matrix using np\n", 1052 | "------------------\n", 1053 | " [[ 1.41421356 2.44948974 2. ]\n", 1054 | " [ 1.73205081 2.64575131 1.73205081]\n", 1055 | " [ 1.41421356 2. 1.41421356]]\n", 1056 | "\n", 1057 | "Exponential power of 1st matrix using np\n", 1058 | " -------------------------------------------------- \n", 1059 | " [[ 7.3890561 403.42879349 54.59815003]\n", 1060 | " [ 20.08553692 1096.63315843 20.08553692]\n", 1061 | " [ 7.3890561 54.59815003 7.3890561 ]]\n", 1062 | "\n", 1063 | "10-base logarithm on 1st matrix using np\n", 1064 | " -------------------------------------------------- \n", 1065 | " [[ 0.30103 0.77815125 0.60205999]\n", 1066 | " [ 0.47712125 0.84509804 0.47712125]\n", 1067 | " [ 0.30103 0.60205999 0.30103 ]]\n", 1068 | "\n", 1069 | "Modulo reminder using np\n", 1070 | " -------------------------------------------------- \n", 1071 | " [[2 0 4]\n", 1072 | " [0 7 3]\n", 1073 | " [0 4 2]]\n", 1074 | "\n", 1075 | "Combination of functions by shwoing exponetial decay of a sine wave\n", 1076 | " ----------------------------------------------------------------------\n" 1077 | ] 1078 | }, 1079 | { 1080 | "data": { 1081 | "image/png": "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\njBHC/wIn0DE+pyPI4gAAAABJRU5ErkJggg==\n", 1082 | "text/plain": [ 1083 | "" 1084 | ] 1085 | }, 1086 | "metadata": {}, 1087 | "output_type": "display_data" 1088 | } 1089 | ], 1090 | "source": [ 1091 | "mat1 = np.array(ri(1,10,9)).reshape(3,3)\n", 1092 | "mat2 = np.array(ri(1,10,9)).reshape(3,3)\n", 1093 | "print(\"\\n1st Matrix of random single-digit numbers\\n----------------------------------------\\n\",mat1)\n", 1094 | "print(\"\\n2nd Matrix of random single-digit numbers\\n----------------------------------------\\n\",mat2)\n", 1095 | "\n", 1096 | "print(\"\\nSq-root of 1st matrix using np\\n------------------\\n\", np.sqrt(mat1))\n", 1097 | "print(\"\\nExponential power of 1st matrix using np\\n\",'-'*50,\"\\n\", np.exp(mat1))\n", 1098 | "print(\"\\n10-base logarithm on 1st matrix using np\\n\",'-'*50,\"\\n\", np.log10(mat1))\n", 1099 | "print(\"\\nModulo reminder using np\\n\",'-'*50,\"\\n\", np.fmod(mat1,mat2))\n", 1100 | "\n", 1101 | "print(\"\\nCombination of functions by shwoing exponetial decay of a sine wave\\n\",'-'*70)\n", 1102 | "A = np.linspace(0,12*np.pi,1001)\n", 1103 | "import matplotlib.pyplot as plt\n", 1104 | "plt.scatter(x=A,y=100*np.exp(-A/10)*(np.sin(A)))\n", 1105 | "plt.title(\"Exponential decay of sine wave: exp(-x)*sin(x)\")\n", 1106 | "plt.show()" 1107 | ] 1108 | }, 1109 | { 1110 | "cell_type": "markdown", 1111 | "metadata": {}, 1112 | "source": [ 1113 | "### NumPy basic statistics on array" 1114 | ] 1115 | }, 1116 | { 1117 | "cell_type": "code", 1118 | "execution_count": 57, 1119 | "metadata": { 1120 | "collapsed": false 1121 | }, 1122 | "outputs": [ 1123 | { 1124 | "name": "stdout", 1125 | "output_type": "stream", 1126 | "text": [ 1127 | "\n", 1128 | "1st Matrix of random single-digit numbers\n", 1129 | " -------------------------------------------------- \n", 1130 | " [[9 9 2]\n", 1131 | " [4 1 1]\n", 1132 | " [7 8 1]]\n", 1133 | "\n", 1134 | "2nd Matrix of random single-digit numbers\n", 1135 | " -------------------------------------------------- \n", 1136 | " [[9 3 6]\n", 1137 | " [5 3 7]\n", 1138 | " [5 8 2]]\n", 1139 | "\n", 1140 | "Sum of all numbers in 1st matrix\n", 1141 | " -------------------------------------------------- \n", 1142 | " 42\n", 1143 | "\n", 1144 | "Sum of all numbers in columns of 1st matrix\n", 1145 | " -------------------------------------------------- \n", 1146 | " [20 18 4]\n", 1147 | "\n", 1148 | "Sum of all numbers in rows of 1st matrix\n", 1149 | " -------------------------------------------------- \n", 1150 | " [20 6 16]\n", 1151 | "\n", 1152 | "Product of all numbers in rows of 1st matrix\n", 1153 | " -------------------------------------------------- \n", 1154 | " [162 4 56]\n", 1155 | "\n", 1156 | "Product of all numbers in columns of 2nd matrix\n", 1157 | " -------------------------------------------------- \n", 1158 | " [225 72 84]\n", 1159 | "\n", 1160 | "Mean of all numbers in 1st matrix\n", 1161 | " -------------------------------------------------- \n", 1162 | " 4.66666666667\n", 1163 | "\n", 1164 | "Standard deviation of all numbers in 1st matrix\n", 1165 | " -------------------------------------------------- \n", 1166 | " 3.36650164612\n", 1167 | "\n", 1168 | "Modified matrix of random numbers from 1 to 99\n", 1169 | " -------------------------------------------------- \n", 1170 | " [[17 50 33]\n", 1171 | " [50 74 81]\n", 1172 | " [16 7 55]]\n", 1173 | "\n", 1174 | "Standard deviation of all numbers in the modified matrix, a larger number\n", 1175 | " -------------------------------------------------------------------------------- \n", 1176 | " 24.5995081754\n", 1177 | "\n", 1178 | "Variance of all numbers in the modified matrix, a larger number\n", 1179 | " -------------------------------------------------------------------------------- \n", 1180 | " 605.135802469\n", 1181 | "\n", 1182 | "Median of all numbers in the modified matrix\n", 1183 | " ------------------------------------------------------------ \n", 1184 | " 50.0\n", 1185 | "\n", 1186 | "Modified matrix of 50 random numbers from 1 to 99\n", 1187 | " -------------------------------------------------- \n", 1188 | " [[38 85 87 90 26]\n", 1189 | " [21 24 45 19 35]\n", 1190 | " [81 41 93 78 28]\n", 1191 | " [83 63 63 7 84]\n", 1192 | " [19 50 59 19 89]\n", 1193 | " [55 93 77 68 20]\n", 1194 | " [53 38 91 81 97]\n", 1195 | " [16 75 75 82 15]\n", 1196 | " [40 28 73 95 95]\n", 1197 | " [74 78 24 49 15]]\n", 1198 | "\n", 1199 | "Standard deviation along the columns in the modified matrix\n", 1200 | " ------------------------------------------------------------ \n", 1201 | " [ 24.12882094 23.39764945 20.58178807 31.16985723 33.97705108]\n", 1202 | "\n", 1203 | "Modified matrix of random numbers from 1 to 49\n", 1204 | " -------------------------------------------------- \n", 1205 | " [[10 96 78 26 10]\n", 1206 | " [26 82 9 83 35]\n", 1207 | " [26 3 95 29 17]\n", 1208 | " [30 42 58 87 58]]\n", 1209 | "\n", 1210 | "Flattened and sorted matrix (as vector)\n", 1211 | " -------------------------------------------------- \n", 1212 | " [[ 3 9 10 10 17 26 26 26 29 30 35 42 58 58 78 82 83 87 95 96]]\n", 1213 | "\n", 1214 | "50th percentile of all numbers in the modified matrix\n", 1215 | " ------------------------------------------------------------ \n", 1216 | " 32.5\n", 1217 | "\n", 1218 | "90th percentile of all numbers in the modified matrix\n", 1219 | " ------------------------------------------------------------ \n", 1220 | " 87.8\n" 1221 | ] 1222 | } 1223 | ], 1224 | "source": [ 1225 | "mat1 = np.array(ri(1,10,9)).reshape(3,3)\n", 1226 | "mat2 = np.array(ri(1,10,9)).reshape(3,3)\n", 1227 | "print(\"\\n1st Matrix of random single-digit numbers\\n\",\"-\"*50,\"\\n\",mat1)\n", 1228 | "print(\"\\n2nd Matrix of random single-digit numbers\\n\",\"-\"*50,\"\\n\",mat2)\n", 1229 | "\n", 1230 | "print(\"\\nSum of all numbers in 1st matrix\\n\",\"-\"*50,\"\\n\",np.sum(mat1))\n", 1231 | "print(\"\\nSum of all numbers in columns of 1st matrix\\n\",\"-\"*50,\"\\n\",np.sum(mat1,axis=0))\n", 1232 | "print(\"\\nSum of all numbers in rows of 1st matrix\\n\",\"-\"*50,\"\\n\",np.sum(mat1,axis=1))\n", 1233 | "print(\"\\nProduct of all numbers in rows of 1st matrix\\n\",\"-\"*50,\"\\n\",np.prod(mat1,axis=1))\n", 1234 | "print(\"\\nProduct of all numbers in columns of 2nd matrix\\n\",\"-\"*50,\"\\n\",np.prod(mat2,axis=0))\n", 1235 | "print(\"\\nMean of all numbers in 1st matrix\\n\",\"-\"*50,\"\\n\",np.mean(mat1))\n", 1236 | "print(\"\\nStandard deviation of all numbers in 1st matrix\\n\",\"-\"*50,\"\\n\",np.std(mat1))\n", 1237 | "\n", 1238 | "mat1 = np.array(ri(1,100,9)).reshape(3,3)\n", 1239 | "print(\"\\nModified matrix of random numbers from 1 to 99\\n\",\"-\"*50,\"\\n\",mat1)\n", 1240 | "print(\"\\nStandard deviation of all numbers in the modified matrix, a larger number\\n\",\"-\"*80,\"\\n\",np.std(mat1))\n", 1241 | "print(\"\\nVariance of all numbers in the modified matrix, a larger number\\n\",\"-\"*80,\"\\n\",np.var(mat1))\n", 1242 | "print(\"\\nMedian of all numbers in the modified matrix\\n\",\"-\"*60,\"\\n\",np.median(mat1))\n", 1243 | "\n", 1244 | "mat2 = np.array(ri(1,100,50)).reshape(10,5)\n", 1245 | "print(\"\\nModified matrix of 50 random numbers from 1 to 99\\n\",\"-\"*50,\"\\n\",mat2)\n", 1246 | "print(\"\\nStandard deviation along the columns in the modified matrix\\n\",\"-\"*60,\"\\n\",np.std(mat2,axis=0))\n", 1247 | "\n", 1248 | "mat1 = np.array(ri(1,100,20)).reshape(4,5)\n", 1249 | "print(\"\\nModified matrix of random numbers from 1 to 49\\n\",\"-\"*50,\"\\n\",mat1)\n", 1250 | "print(\"\\nFlattened and sorted matrix (as vector)\\n\",\"-\"*50,\"\\n\",np.sort(mat1.reshape(1,20)))\n", 1251 | "print(\"\\n50th percentile of all numbers in the modified matrix\\n\",\"-\"*60,\"\\n\",np.percentile(mat1,50))\n", 1252 | "print(\"\\n90th percentile of all numbers in the modified matrix\\n\",\"-\"*60,\"\\n\",np.percentile(mat1,90))" 1253 | ] 1254 | }, 1255 | { 1256 | "cell_type": "markdown", 1257 | "metadata": {}, 1258 | "source": [ 1259 | "### Correlation and covariance" 1260 | ] 1261 | }, 1262 | { 1263 | "cell_type": "code", 1264 | "execution_count": 43, 1265 | "metadata": { 1266 | "collapsed": false, 1267 | "scrolled": false 1268 | }, 1269 | "outputs": [ 1270 | { 1271 | "name": "stdout", 1272 | "output_type": "stream", 1273 | "text": [ 1274 | "\n", 1275 | "B is twice that of A plus some random noise\n" 1276 | ] 1277 | }, 1278 | { 1279 | "data": { 1280 | "image/png": "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\nrW6Fi6YeLWPWuZzcrSFLFw85mZt1MHfLmJnlkM/czXLCPyyzYk7uZjngH5ZZKXfLmOWAf1hmpZzc\nzXLAPyyzUk0nd0k9kjZKur4VAZlZ/fzDMivVijP39wObW7AdM2uQf1hmpZpK7pLmAm8GLmlNOGbW\niKWLh1i1bBFD/X0IGOrvY9WyRb6Y+gLW7GiZi4APAbNbEIt1EQ+76zz+YZkVa/jMXdJpwGMRcUeV\n5ZZLGpU0Oj4+3ujurIMUht2NTUwS7B52N7JxrN2hmVnSTLfMicBbJD0AXAW8QdK60oUiYk1EDEfE\n8MDAQBO7s07hYXdmna/h5B4RKyNibkQsAM4AboqIt7UsMutYHnZn1vk8zt3q5mF3Zp2vJck9Im6J\niNNasS3rfB52Z9b5fG8Zq5vv527W+ZzcrSEedmfW2dznbmaWQ07uZmY55ORuZpZDTu5mZjnk5G5m\nlkNO7mZmOeTkbmaWQ07uZmY55ORuZpZDTu5mZjnk5G5mlkNO7mZmOeTkbmaWQ07uZmY55ORuZpZD\nTu5mZjnk5G5mlkMNP4lJ0jzgcuBQIIA1EfG5VgVWbGTjmB/pZmZWh2Yes/c8cF5E3ClpNnCHpBsi\n4r4WxQZkiX3l+k1M7tgJwNjEJCvXbwJwgjczq6DhbpmIeDgi7kyvnwY2Ay3Ptqs3bNmV2Asmd+xk\n9YYtrd6VmVlutKTPXdICYDFwe5l5yyWNShodHx+ve9vbJybrmm5mZi1I7pIOBK4F/iIiniqdHxFr\nImI4IoYHBgbq3n7//r11TTczsyaTu6RessR+RUSsb01Ie4qob7qZmTU3WkbAV4DNEfGZ1oW0pycn\nd9Q13WaGRzCZdbZmztxPBN4OvEHSXenv1BbFtctgf19d0236FUYwjU1MEuwewTSycazdoZlZ0sxo\nme9HhCLimIh4Zfr7diuDA1ixZCF9vT17TOvr7WHFkoWt3pXVyCOYzDpfM+PcZ0Thv/ruAugcHsFk\n1vk6PrlDluCdzDvHYH8fY2USubvKzDqH7y1jdXNXWWca2TjGiRfexBHnf4sTL7zJ10Be4LrizN06\ni7vKOo9v02GlnNytIe4q6yxTXeR2Pb0wuVvGLAd8kdtKObmb5YB/D2KlnNzNcsAXua2U+9zNcsAX\nua2Uk7tZTvgitxVzt4yZWQ45uZuZ5ZCTu5lZDrnP3SwnfI99K+bkbpYDvv2AlXK3jFkO+B77VsrJ\n3SwHfPsBK+XkbpYDvv2AlXJyN8sB337ASjWV3CWdImmLpPslnd+qoMysPksXD7Fq2SKG+vsQMNTf\nx6pli3wx9QWs4dEyknqA/wmcDGwDfiTpuoi4r1XBmVntfPsBK9bMmftxwP0R8fOIeA64Cji9NWGZ\nmVkzmhnnPgRsLXq/DTi+dCFJy4HlAPPnz29id9ZJ/IMZs8427RdUI2JNRAxHxPDAwMB0785mQOEH\nM2MTkwS7fzDjBzKbdY5mkvsYMK/o/dw0zXLOP5gx63zNJPcfAS+XdISkfYEzgOtaE5Z1Mv9gxqzz\nNZzcI+J54L3ABmAzcHVE3NuqwKxz+QczZp2vqT73iPh2RPz7iHhZRHy6VUFZZ/MPZsw6n+8KaXXz\n8zrNOp+TuzXEP5gx62y+t4yZWQ45uZuZ5ZCTu5lZDjm5m5nlkJO7mVkOKSJmbmfSOPBgE5uYAzze\nonDaKS/lgPyUJS/lgPyUJS/lgObLcnhE1HVzrhlN7s2SNBoRw+2Oo1l5KQfkpyx5KQfkpyx5KQe0\npyzuljEzyyEndzOzHOq25L6m3QG0SF7KAfkpS17KAfkpS17KAW0oS1f1uZuZWW267czdzMxq4ORu\nZpZDHZfcJV0q6TFJ91SYL0mfl3S/pB9LOnamY6xVDWU5SdKTku5Kfx+b6RhrIWmepJsl3SfpXknv\nL7NMx9dLjeXoljqZJemHku5OZflEmWW6oU5qKUdX1AmApB5JGyVdX2bezNZHRHTUH/A64Fjgngrz\nTwW+Awg4Abi93TE3UZaTgOvbHWcN5TgMODa9ng38FDiq2+qlxnJ0S50IODC97gVuB07owjqppRxd\nUScp1g8CXy8X70zXR8eduUfErcATUyxyOnB5ZG4D+iUdNjPR1aeGsnSFiHg4Iu5Mr58me6xi6c3c\nO75eaixHV0jH+Zn0tjf9lY6O6IY6qaUcXUHSXODNwCUVFpnR+ui45F6DIWBr0fttdOkHNHlN+i/a\ndyS9ot3BVCNpAbCY7AyrWFfVyxTlgC6pk9QFcBfwGHBDRHRlndRQDuiOOrkI+BDw2wrzZ7Q+ujG5\n58mdwPyIOAb4AjDS5nimJOlA4FrgLyLiqXbH06gq5eiaOomInRHxSmAucJyko9sdUyNqKEfH14mk\n04DHIuKOdsdS0I3JfQyYV/R+bprWdSLiqcJ/SSPi20CvpDltDqssSb1kCfGKiFhfZpGuqJdq5eim\nOimIiAngZuCUklldUScFlcrRJXVyIvAWSQ8AVwFvkLSuZJkZrY9uTO7XAe9IV55PAJ6MiIfbHVQj\nJP2OJKXXx5HVxy/bG9XeUoxfATZHxGcqLNbx9VJLObqoTgYk9afXfcDJwE9KFuuGOqlajm6ok4hY\nGRFzI2IBcAZwU0S8rWSxGa2PjntAtqQrya6Oz5G0Dfg42UUWIuJi4NtkV53vB34NvLM9kVZXQ1ne\nCvyppOeBSeCMSJfVO8yJwNuBTalvFOAjwHzoqnqppRzdUieHAZdJ6iFLdldHxPWSzoWuqpNaytEt\ndbKXdtaHbz9gZpZD3dgtY2ZmVTi5m5nlkJO7mVkOObmbmeWQk7uZWQ45uZuZ5ZCTu5lZDv1/2YdD\nlj9B6ooAAAAASUVORK5CYII=\n", 1281 | "text/plain": [ 1282 | "" 1283 | ] 1284 | }, 1285 | "metadata": {}, 1286 | "output_type": "display_data" 1287 | }, 1288 | { 1289 | "name": "stdout", 1290 | "output_type": "stream", 1291 | "text": [ 1292 | "[[ 1. 0.55638699]\n", 1293 | " [ 0.55638699 1. ]]\n", 1294 | "\n", 1295 | "B is 100 minus twice that of A plus some random noise\n" 1296 | ] 1297 | }, 1298 | { 1299 | "data": { 1300 | "image/png": "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\n", 1301 | "text/plain": [ 1302 | "" 1303 | ] 1304 | }, 1305 | "metadata": {}, 1306 | "output_type": "display_data" 1307 | }, 1308 | { 1309 | "name": "stdout", 1310 | "output_type": "stream", 1311 | "text": [ 1312 | "\n", 1313 | "[[ 1. -0.94973377]\n", 1314 | " [-0.94973377 1. ]]\n" 1315 | ] 1316 | } 1317 | ], 1318 | "source": [ 1319 | "A = ri(1,5,20) # 20 random integeres from a small range (1-10)\n", 1320 | "B = 2*A+5*np.random.randn(20) # B is twice that of A plus some random noise\n", 1321 | "print(\"\\nB is twice that of A plus some random noise\")\n", 1322 | "plt.scatter(A,B) # Scatter plot of B\n", 1323 | "plt.title(\"Scatter plot of A vs. B, expect a small positive correlation\")\n", 1324 | "plt.show()\n", 1325 | "print(np.corrcoef(A,B)) # Correleation coefficient matrix between A and B\n", 1326 | "\n", 1327 | "A = ri(1,50,20) # 20 random integeres from a larger range (1-50)\n", 1328 | "B = 100-2*A+10*np.random.randn(20) # B is 100 minus twice that of A plus some random noise\n", 1329 | "print(\"\\nB is 100 minus twice that of A plus some random noise\")\n", 1330 | "plt.scatter(A,B) # Scatter plot of B\n", 1331 | "plt.title(\"Scatter plot of A vs. B, expect a large negative correlation\")\n", 1332 | "plt.show()\n", 1333 | "print(\"\")\n", 1334 | "print(np.corrcoef(A,B)) # Correleation coefficient matrix between A and B" 1335 | ] 1336 | }, 1337 | { 1338 | "cell_type": "markdown", 1339 | "metadata": { 1340 | "collapsed": true 1341 | }, 1342 | "source": [ 1343 | "## Linear Algebra Operations" 1344 | ] 1345 | }, 1346 | { 1347 | "cell_type": "markdown", 1348 | "metadata": {}, 1349 | "source": [ 1350 | "### Dot/Inner/Outer products" 1351 | ] 1352 | }, 1353 | { 1354 | "cell_type": "code", 1355 | "execution_count": 90, 1356 | "metadata": { 1357 | "collapsed": false, 1358 | "scrolled": false 1359 | }, 1360 | "outputs": [ 1361 | { 1362 | "name": "stdout", 1363 | "output_type": "stream", 1364 | "text": [ 1365 | "\n", 1366 | "1st Matrix of 1-9 single-digit numbers (A)\n", 1367 | " -------------------------------------------------- \n", 1368 | " [[1 2 3]\n", 1369 | " [4 5 6]\n", 1370 | " [7 8 9]]\n", 1371 | "\n", 1372 | "2nd Matrix of random single-digit numbers (B)\n", 1373 | " -------------------------------------------------- \n", 1374 | " [[3 1 6]\n", 1375 | " [3 3 2]\n", 1376 | " [7 9 7]]\n", 1377 | "\n", 1378 | "Dot product of A and B (for 2D arrays it is equivalent to matrix multiplication) \n", 1379 | " -------------------------------------------------------------------------------- \n", 1380 | " [[ 30 34 31]\n", 1381 | " [ 69 73 76]\n", 1382 | " [108 112 121]]\n", 1383 | "\n", 1384 | "1st Vector of 1-5 numbers (A)\n", 1385 | " -------------------------------------------------- \n", 1386 | " [1 2 3 4 5]\n", 1387 | "\n", 1388 | "2nd Vector of 5 random single-digit numbers (B)\n", 1389 | " -------------------------------------------------- \n", 1390 | " [2 5 9 2 3]\n", 1391 | "\n", 1392 | "Inner product of vectors A and B \n", 1393 | " -------------------------------------------------- \n", 1394 | " 62 (sum of all pairwise elements)\n", 1395 | "\n", 1396 | "Outer product of vectors A and B \n", 1397 | " -------------------------------------------------- \n", 1398 | " [[ 2 5 9 2 3]\n", 1399 | " [ 4 10 18 4 6]\n", 1400 | " [ 6 15 27 6 9]\n", 1401 | " [ 8 20 36 8 12]\n", 1402 | " [10 25 45 10 15]]\n" 1403 | ] 1404 | } 1405 | ], 1406 | "source": [ 1407 | "A = np.arange(1,10).reshape(3,3)\n", 1408 | "B = ri(1,10,9).reshape(3,3)\n", 1409 | "print(\"\\n1st Matrix of 1-9 single-digit numbers (A)\\n\",\"-\"*50,\"\\n\",A)\n", 1410 | "print(\"\\n2nd Matrix of random single-digit numbers (B)\\n\",\"-\"*50,\"\\n\",B)\n", 1411 | "\n", 1412 | "print(\"\\nDot product of A and B (for 2D arrays it is equivalent to matrix multiplication) \\n\",\"-\"*80,\"\\n\",np.dot(A,B))\n", 1413 | "\n", 1414 | "A = np.arange(1,6)\n", 1415 | "B = ri(1,10,5)\n", 1416 | "print(\"\\n1st Vector of 1-5 numbers (A)\\n\",\"-\"*50,\"\\n\",A)\n", 1417 | "print(\"\\n2nd Vector of 5 random single-digit numbers (B)\\n\",\"-\"*50,\"\\n\",B)\n", 1418 | "\n", 1419 | "print(\"\\nInner product of vectors A and B \\n\",\"-\"*50,\"\\n\",np.inner(A,B), \"(sum of all pairwise elements)\")\n", 1420 | "print(\"\\nOuter product of vectors A and B \\n\",\"-\"*50,\"\\n\",np.outer(A,B))" 1421 | ] 1422 | }, 1423 | { 1424 | "cell_type": "markdown", 1425 | "metadata": {}, 1426 | "source": [ 1427 | "### Transpose" 1428 | ] 1429 | }, 1430 | { 1431 | "cell_type": "code", 1432 | "execution_count": 45, 1433 | "metadata": { 1434 | "collapsed": false, 1435 | "scrolled": false 1436 | }, 1437 | "outputs": [ 1438 | { 1439 | "name": "stdout", 1440 | "output_type": "stream", 1441 | "text": [ 1442 | "\n", 1443 | "3x3 Matrix of random single-digit numbers\n", 1444 | " -------------------------------------------------- \n", 1445 | " [[6 7 5]\n", 1446 | " [1 2 7]\n", 1447 | " [3 7 2]]\n", 1448 | "\n", 1449 | "Matrix transpose\n", 1450 | " -------------------------------------------------- \n", 1451 | " [[6 1 3]\n", 1452 | " [7 2 7]\n", 1453 | " [5 7 2]]\n", 1454 | "\n", 1455 | "3x2 Matrix of random single-digit numbers\n", 1456 | " -------------------------------------------------- \n", 1457 | " [[8 4]\n", 1458 | " [1 9]\n", 1459 | " [2 3]]\n", 1460 | "\n", 1461 | "2x3 Matrix transpose\n", 1462 | " -------------------------------------------------- \n", 1463 | " [[8 1 2]\n", 1464 | " [4 9 3]]\n", 1465 | "\n", 1466 | "Matrix multiplication of B and B-transpose\n", 1467 | " -------------------------------------------------- \n", 1468 | " [[80 44 28]\n", 1469 | " [44 82 29]\n", 1470 | " [28 29 13]]\n" 1471 | ] 1472 | } 1473 | ], 1474 | "source": [ 1475 | "A = ri(1,10,9).reshape(3,3)\n", 1476 | "print(\"\\n3x3 Matrix of random single-digit numbers\\n\",\"-\"*50,\"\\n\",A)\n", 1477 | "print(\"\\nMatrix transpose\\n\",\"-\"*50,\"\\n\",np.transpose(A))\n", 1478 | "\n", 1479 | "B = ri(1,10,6).reshape(3,2)\n", 1480 | "print(\"\\n3x2 Matrix of random single-digit numbers\\n\",\"-\"*50,\"\\n\",B)\n", 1481 | "print(\"\\n2x3 Matrix transpose\\n\",\"-\"*50,\"\\n\",np.transpose(B))\n", 1482 | "print(\"\\nMatrix multiplication of B and B-transpose\\n\",\"-\"*50,\"\\n\",np.dot(B, np.transpose(B)))" 1483 | ] 1484 | }, 1485 | { 1486 | "cell_type": "markdown", 1487 | "metadata": {}, 1488 | "source": [ 1489 | "### Trace" 1490 | ] 1491 | }, 1492 | { 1493 | "cell_type": "code", 1494 | "execution_count": 46, 1495 | "metadata": { 1496 | "collapsed": false, 1497 | "scrolled": true 1498 | }, 1499 | "outputs": [ 1500 | { 1501 | "name": "stdout", 1502 | "output_type": "stream", 1503 | "text": [ 1504 | "\n", 1505 | "4x4 Matrix of random single-digit numbers\n", 1506 | " -------------------------------------------------- \n", 1507 | " [[9 4 1 9]\n", 1508 | " [2 4 8 6]\n", 1509 | " [8 7 5 9]\n", 1510 | " [9 4 4 7]]\n", 1511 | "\n", 1512 | "Matrix trace\n", 1513 | " -------------------------------------------------- \n", 1514 | " 25\n", 1515 | "\n", 1516 | "Matrix trace with ofset +1 (upper triangle)\n", 1517 | " -------------------------------------------------- \n", 1518 | " 21\n", 1519 | "\n", 1520 | "Matrix trace with ofset -1 (lower triangle)\n", 1521 | " -------------------------------------------------- \n", 1522 | " 13\n" 1523 | ] 1524 | } 1525 | ], 1526 | "source": [ 1527 | "A = ri(1,10,16).reshape(4,4)\n", 1528 | "print(\"\\n4x4 Matrix of random single-digit numbers\\n\",\"-\"*50,\"\\n\",A)\n", 1529 | "print(\"\\nMatrix trace\\n\",\"-\"*50,\"\\n\",np.trace(A))\n", 1530 | "print(\"\\nMatrix trace with ofset +1 (upper triangle)\\n\",\"-\"*50,\"\\n\",np.trace(A,offset=1))\n", 1531 | "print(\"\\nMatrix trace with ofset -1 (lower triangle)\\n\",\"-\"*50,\"\\n\",np.trace(A,offset=-1))" 1532 | ] 1533 | }, 1534 | { 1535 | "cell_type": "markdown", 1536 | "metadata": {}, 1537 | "source": [ 1538 | "### Singular value decomposition (SVD)" 1539 | ] 1540 | }, 1541 | { 1542 | "cell_type": "code", 1543 | "execution_count": 87, 1544 | "metadata": { 1545 | "collapsed": false 1546 | }, 1547 | "outputs": [ 1548 | { 1549 | "name": "stdout", 1550 | "output_type": "stream", 1551 | "text": [ 1552 | "Original matrix\n", 1553 | " [[5 6 2]\n", 1554 | " [3 1 7]\n", 1555 | " [8 8 7]]\n", 1556 | "\n", 1557 | "\n", 1558 | "u: [[-0.45772212 0.52841166 -0.71503257]\n", 1559 | " [-0.37892562 -0.84346758 -0.38075953]\n", 1560 | " [-0.80430457 0.0966621 0.58630248]]\n", 1561 | "\n", 1562 | "\n", 1563 | "Singular values, s: [ 16.52900847 5.27168794 0.03442903]\n", 1564 | "\n", 1565 | "\n", 1566 | "v: [[-0.59651636 -0.57835864 -0.55647957]\n", 1567 | " [ 0.16786888 0.5881037 -0.7911726 ]\n", 1568 | " [-0.7848492 0.565363 0.25372506]]\n", 1569 | "\n", 1570 | "\n", 1571 | "Reconstruction of A, u*s*v\n", 1572 | " [[ 5. 6. 2.]\n", 1573 | " [ 3. 1. 7.]\n", 1574 | " [ 8. 8. 7.]]\n" 1575 | ] 1576 | } 1577 | ], 1578 | "source": [ 1579 | "A = np.random.randint(1,10,9).reshape(3,3)\n", 1580 | "print(\"Original matrix\\n\",A)\n", 1581 | "print(\"\\n\")\n", 1582 | "u,s,v=np.linalg.svd(A,compute_uv=1,full_matrices=True)\n", 1583 | "print(\"u:\",u)\n", 1584 | "print(\"\\n\")\n", 1585 | "print(\"Singular values, s:\",s)\n", 1586 | "print(\"\\n\")\n", 1587 | "print(\"v:\",v)\n", 1588 | "print(\"\\n\")\n", 1589 | "print (\"Reconstruction of A, u*s*v\\n\",np.dot(u,np.dot(np.diag(s),v)))" 1590 | ] 1591 | }, 1592 | { 1593 | "cell_type": "markdown", 1594 | "metadata": {}, 1595 | "source": [ 1596 | "### QR decomposition/factorization" 1597 | ] 1598 | }, 1599 | { 1600 | "cell_type": "code", 1601 | "execution_count": 91, 1602 | "metadata": { 1603 | "collapsed": false 1604 | }, 1605 | "outputs": [ 1606 | { 1607 | "name": "stdout", 1608 | "output_type": "stream", 1609 | "text": [ 1610 | "Original matrix\n", 1611 | " [[3 7 4]\n", 1612 | " [5 5 9]\n", 1613 | " [3 8 1]]\n", 1614 | "\n", 1615 | "\n", 1616 | "Q: [[-0.45749571 0.43156567 -0.77746302]\n", 1617 | " [-0.76249285 -0.64023479 0.09329556]\n", 1618 | " [-0.45749571 0.63549231 0.62197041]]\n", 1619 | "\n", 1620 | "\n", 1621 | "R: [[ -6.55743852 -10.67489992 -9.14991422]\n", 1622 | " [ 0. 4.90372426 -3.40035812]\n", 1623 | " [ 0. 0. -1.6482216 ]]\n", 1624 | "\n", 1625 | "\n", 1626 | "Reconstruction of A, Q*R\n", 1627 | " [[ 3. 7. 4.]\n", 1628 | " [ 5. 5. 9.]\n", 1629 | " [ 3. 8. 1.]]\n" 1630 | ] 1631 | } 1632 | ], 1633 | "source": [ 1634 | "A = np.random.randint(1,10,9).reshape(3,3)\n", 1635 | "print(\"Original matrix\\n\",A)\n", 1636 | "print(\"\\n\")\n", 1637 | "q,r=np.linalg.qr(A)\n", 1638 | "print(\"Q:\",q)\n", 1639 | "print(\"\\n\")\n", 1640 | "print(\"R:\",r)\n", 1641 | "print(\"\\n\")\n", 1642 | "print (\"Reconstruction of A, Q*R\\n\",np.dot(q,r))" 1643 | ] 1644 | }, 1645 | { 1646 | "cell_type": "markdown", 1647 | "metadata": {}, 1648 | "source": [ 1649 | "### Eigenvalues and eigenvectors" 1650 | ] 1651 | }, 1652 | { 1653 | "cell_type": "code", 1654 | "execution_count": 95, 1655 | "metadata": { 1656 | "collapsed": false 1657 | }, 1658 | "outputs": [ 1659 | { 1660 | "name": "stdout", 1661 | "output_type": "stream", 1662 | "text": [ 1663 | "Original matrix\n", 1664 | " [[ 0.05594554 1.02096149 0.94962784]\n", 1665 | " [-0.94312813 -0.13377838 -0.19325112]\n", 1666 | " [ 0.61866049 0.84990374 -0.45748733]]\n", 1667 | "\n", 1668 | "\n", 1669 | "Eigenvalues:\n", 1670 | " [ 0.26958701+1.03654742j 0.26958701-1.03654742j -1.07449419+0.j ]\n", 1671 | "\n", 1672 | "\n", 1673 | "Eigenvectors:\n", 1674 | " [[ 0.65609706+0.j 0.65609706-0.j -0.45466685+0.j ]\n", 1675 | " [-0.24271546+0.57868435j -0.24271546-0.57868435j -0.28229792+0.j ]\n", 1676 | " [ 0.40855234+0.09399606j 0.40855234-0.09399606j 0.84474016+0.j ]]\n" 1677 | ] 1678 | } 1679 | ], 1680 | "source": [ 1681 | "A = np.random.randn(9).reshape(3,3)\n", 1682 | "print(\"Original matrix\\n\",A)\n", 1683 | "print(\"\\n\")\n", 1684 | "w,v=np.linalg.eig(A)\n", 1685 | "print(\"Eigenvalues:\\n\",w)\n", 1686 | "print(\"\\n\")\n", 1687 | "print(\"Eigenvectors:\\n\",v)" 1688 | ] 1689 | }, 1690 | { 1691 | "cell_type": "markdown", 1692 | "metadata": {}, 1693 | "source": [ 1694 | "### Linear equation solving, matrix inverse, linear least suqare\n", 1695 | "\n", 1696 | "You can directly solve linear system of equations using NumPy writing only one line of code.\n", 1697 | "\n", 1698 | "Suppose you want to solve the following set of equations for (x,y,z). It is easy to see that (2,1,5) are the unique solutions.\n", 1699 | "\n", 1700 | "2*x* + 5*y* + *z* = 14;\n", 1701 | "\n", 1702 | "3*x* - 2*y* - *z* = -1;\n", 1703 | "\n", 1704 | "*x* - 3*y* + *z* = 4" 1705 | ] 1706 | }, 1707 | { 1708 | "cell_type": "code", 1709 | "execution_count": 100, 1710 | "metadata": { 1711 | "collapsed": false 1712 | }, 1713 | "outputs": [ 1714 | { 1715 | "name": "stdout", 1716 | "output_type": "stream", 1717 | "text": [ 1718 | "The solutions are: [ 2. 1. 5.]\n" 1719 | ] 1720 | } 1721 | ], 1722 | "source": [ 1723 | "A = np.array([[2,5,1],[3,-2,-1],[1,-3,1]])\n", 1724 | "B = np.array([14,-1,4])\n", 1725 | "x = np.linalg.solve(A,B)\n", 1726 | "\n", 1727 | "print(\"The solutions are:\",x)" 1728 | ] 1729 | }, 1730 | { 1731 | "cell_type": "markdown", 1732 | "metadata": {}, 1733 | "source": [ 1734 | "** Linear least squares can be calculated easily as a solution to a linear regression problem **" 1735 | ] 1736 | }, 1737 | { 1738 | "cell_type": "code", 1739 | "execution_count": 133, 1740 | "metadata": { 1741 | "collapsed": false 1742 | }, 1743 | "outputs": [ 1744 | { 1745 | "name": "stdout", 1746 | "output_type": "stream", 1747 | "text": [ 1748 | "[ 1 2 3 4 5 6 7 8 9 10]\n", 1749 | "[ 2.2186607 2.53379561 4.65245542 7.24311354 8.67462021\n", 1750 | " 10.25717262 13.6653078 15.34900931 16.59674539 18.72669168]\n" 1751 | ] 1752 | } 1753 | ], 1754 | "source": [ 1755 | "x = np.arange(1,11,1)\n", 1756 | "y = 2*x+np.random.randn(10)-1\n", 1757 | "print(x)\n", 1758 | "print(y)" 1759 | ] 1760 | }, 1761 | { 1762 | "cell_type": "code", 1763 | "execution_count": 135, 1764 | "metadata": { 1765 | "collapsed": false 1766 | }, 1767 | "outputs": [ 1768 | { 1769 | "name": "stdout", 1770 | "output_type": "stream", 1771 | "text": [ 1772 | "[[ 1. 1.]\n", 1773 | " [ 2. 1.]\n", 1774 | " [ 3. 1.]\n", 1775 | " [ 4. 1.]\n", 1776 | " [ 5. 1.]\n", 1777 | " [ 6. 1.]\n", 1778 | " [ 7. 1.]\n", 1779 | " [ 8. 1.]\n", 1780 | " [ 9. 1.]\n", 1781 | " [ 10. 1.]]\n" 1782 | ] 1783 | } 1784 | ], 1785 | "source": [ 1786 | "A = np.vstack([x, np.ones(len(x))]).T\n", 1787 | "print(A)" 1788 | ] 1789 | }, 1790 | { 1791 | "cell_type": "code", 1792 | "execution_count": 136, 1793 | "metadata": { 1794 | "collapsed": false 1795 | }, 1796 | "outputs": [ 1797 | { 1798 | "name": "stdout", 1799 | "output_type": "stream", 1800 | "text": [ 1801 | "Coefficient:1.94754443612\n", 1802 | "intercept:-0.719737172139\n" 1803 | ] 1804 | }, 1805 | { 1806 | "data": { 1807 | "image/png": "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\nzyrbhVjZx/O9HKBSytdVeDmnMWYncJmb428UuW2A+yp6DnWadetgyBBITobYWJg0CZo0ASA0JIis\n3NKTemgtvWZPKX+nLRuqg9xcePJJiIqCPXvsVogffHAy6QPERjYhKEBKfJqgAOGGSG3EppS/08Tv\n6775BiIj4dln4bbbYPNmuPlmkFOT/LDolgQHlvzfGRwYwNDoMG9Gq5SqBjTx+6qsLBg9Grp3tw3W\nPv0U3nkHGjRwO/yiBqFMHtSROsGBZ1T+QQFCneBAJg/qyEUNQqsieqWUD9PE74uWLYP27eHVV+2q\nnY0bISam1If1aN2IpaOjGdi5OXVDghCBuiFBDOzcnKWjo+nRulEVBK+U8nViP3/1LVFRUSYp6Yye\nbzXfr7/CQw/BW2/Bn/8M06dDdLTTUSmlqgERSTbGRJVlrFb8viI+HsLD7XTOo4/aFTya9JVSXqBr\n+5x24ACMHGlX6kREwCef2C0RlVLKS7Tid4oxMGsWtGljWyg/95zdFlGTvlLKy7Tid0JaGtxzD3z2\nGXTrZq++vfRSp6NSSvkJrfirUmGhvdq2XTv46it4/XVITNSkr5SqUlrxV5WtW2HoUJvwr70W3nwT\nWrRwOiqllB/Sit/b8vLg+efhsstg0yaYOROWLtWkr5RyjFb83pSaapuqpabaNguvvw5/+pPTUSml\n/JxW/N7w++/w2GNw+eWwbx8sXGiXa2rSV0r5AK34Pe3rr22Vv3Ur3HUXvPQSnHuu01EppdRJWvF7\nytGj9kKs6Ghb8X/2mW29oElfKeVjNPF7wmef2SWakybZ5L9xo125o5RSPkineirjl1/gn/+0/XUu\nvZSfP1nGxNxGLBr/Ndm5+YSGBBEb2YRh0S21HbJSymdoxV9RCxbYdgtz5sDjj7Pqvc/osTqPeWv2\nkJWbjwGycvOZt2YPMRMSSdh60OmIlVIKqETiF5ELRSRBRDaLyCYRGeVmzFUickRE1rq+nqpcuD5g\n/3646Sa45RZo1gy+/560B/7FvfM3k5NXQH7hqW2u8wsNOXkFxM1OIS0z26GglVLqD5Wp+POBB40x\n4cAVwH0iEu5mXKIxJsL19Z9KnM9ZxsDbb9vWyZ98Yi/K+u47iIhgWuJO8goKS3x4XkEh0xN3VVGw\nSilVvArP8Rtj9gP7XbePisgWoCmw2UOxlVlaZjbTEneyKHWfd+bWd++G4cPtzljR0XaDlD//+eTd\n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\n", 1808 | "text/plain": [ 1809 | "" 1810 | ] 1811 | }, 1812 | "metadata": {}, 1813 | "output_type": "display_data" 1814 | } 1815 | ], 1816 | "source": [ 1817 | "m, c = np.linalg.lstsq(A, y)[0]\n", 1818 | "print (\"Coefficient:\"+str(m)+ \"\\n\"+\"intercept:\"+str(c))\n", 1819 | "\n", 1820 | "# Plot the fitteed line\n", 1821 | "import matplotlib.pyplot as plt\n", 1822 | "%matplotlib inline\n", 1823 | "plt.plot(x, y, 'o', label='Original data', markersize=10)\n", 1824 | "plt.plot(x, m*x + c, 'r', label='Fitted line')\n", 1825 | "plt.legend()\n", 1826 | "plt.show()" 1827 | ] 1828 | }, 1829 | { 1830 | "cell_type": "markdown", 1831 | "metadata": {}, 1832 | "source": [ 1833 | "** Both normal multiplicative and *Moore-Penrose* pseudo-inverse matrix (for generalized *m* x *n* array) can be calculated **" 1834 | ] 1835 | }, 1836 | { 1837 | "cell_type": "code", 1838 | "execution_count": 137, 1839 | "metadata": { 1840 | "collapsed": false 1841 | }, 1842 | "outputs": [ 1843 | { 1844 | "name": "stdout", 1845 | "output_type": "stream", 1846 | "text": [ 1847 | "A:\n", 1848 | " [[ 1.3 0.1 1.8 1.6]\n", 1849 | " [ 1.5 1.4 0.1 1.2]\n", 1850 | " [ 0.4 1.6 1.1 0.7]\n", 1851 | " [ 1.4 1.6 1.5 1.2]]\n", 1852 | "Inverse of A:\n", 1853 | " [[-0.54152908 -0.1976124 -1.71094742 1.91770384]\n", 1854 | " [-0.34188468 0.12852426 0.49580899 0.03810008]\n", 1855 | " [ 0.01016002 -0.74676149 -0.19304039 0.84582169]\n", 1856 | " [ 1.07493015 0.99263399 1.57632715 -2.51206502]]\n" 1857 | ] 1858 | } 1859 | ], 1860 | "source": [ 1861 | "A = 0.1*np.random.randint(1,20,16).reshape(4,4)\n", 1862 | "print (\"A:\\n\",A)\n", 1863 | "print (\"Inverse of A:\\n\",np.linalg.inv(A))" 1864 | ] 1865 | }, 1866 | { 1867 | "cell_type": "code", 1868 | "execution_count": 138, 1869 | "metadata": { 1870 | "collapsed": false 1871 | }, 1872 | "outputs": [ 1873 | { 1874 | "name": "stdout", 1875 | "output_type": "stream", 1876 | "text": [ 1877 | "A:\n", 1878 | " [[ 1.3 1.9 0.7]\n", 1879 | " [ 0.5 0.3 1.5]\n", 1880 | " [ 0.5 1.8 1.3]\n", 1881 | " [ 1.6 1.9 0.3]\n", 1882 | " [ 0.9 0.3 1.2]]\n", 1883 | "Pseudo-inverse of A:\n", 1884 | " [[ 0.10887279 0.06388003 -0.68929921 0.45682289 0.48917593]\n", 1885 | " [ 0.14467469 -0.18830267 0.49458998 0.00372232 -0.38575162]\n", 1886 | " [-0.07582968 0.36975047 0.24662895 -0.24944669 0.21055954]]\n", 1887 | "Matrix product of A and pseudo inverse:\n", 1888 | " [[ 1.00000000e+00 -5.04407213e-17 2.42326325e-16]\n", 1889 | " [ -6.40765579e-17 1.00000000e+00 -1.30121024e-17]\n", 1890 | " [ -4.25091176e-17 1.78659733e-16 1.00000000e+00]]\n" 1891 | ] 1892 | } 1893 | ], 1894 | "source": [ 1895 | "A = 0.1*np.random.randint(1,20,15).reshape(5,3)\n", 1896 | "print (\"A:\\n\",A)\n", 1897 | "print (\"Pseudo-inverse of A:\\n\",np.linalg.pinv(A))\n", 1898 | "print (\"Matrix product of A and pseudo inverse:\\n\", np.dot(np.linalg.pinv(A),A))" 1899 | ] 1900 | } 1901 | ], 1902 | "metadata": { 1903 | "kernelspec": { 1904 | "display_name": "Python 3", 1905 | "language": "python", 1906 | "name": "python3" 1907 | }, 1908 | "language_info": { 1909 | "codemirror_mode": { 1910 | "name": "ipython", 1911 | "version": 3 1912 | }, 1913 | "file_extension": ".py", 1914 | "mimetype": "text/x-python", 1915 | "name": "python", 1916 | "nbconvert_exporter": "python", 1917 | "pygments_lexer": "ipython3", 1918 | "version": "3.6.0" 1919 | } 1920 | }, 1921 | "nbformat": 4, 1922 | "nbformat_minor": 2 1923 | } 1924 | -------------------------------------------------------------------------------- /Maths/Palindrome_product.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Apr 16 22:29:28 2017 4 | 5 | @author: Tirtha 6 | """ 7 | """ 8 | This program returns the largest palindrome from the product of two 3-digit number 9 | """ 10 | 11 | def is_palindrome(n): 12 | str_n = str(n) 13 | if str_n == str_n[-1:0:-1]+str_n[0]: 14 | return True 15 | else: 16 | return False 17 | 18 | max = 0 19 | max_i=0 20 | max_j=0 21 | 22 | #flag = False 23 | for i in range (999,99,-1): 24 | for j in range (999,99,-1): 25 | if is_palindrome(i*j) and i*j > max: 26 | max = i*j 27 | max_i=i 28 | max_j=j 29 | #flag = True 30 | break 31 | #break 32 | """ 33 | for item in lst: 34 | if is_palindrome(item) and item > max: 35 | max = item 36 | """ 37 | print ("Largest palindrome from the product of two 3-digit numbers is {}. It is product of {} and {}".format(max,max_i,max_j)) 38 | -------------------------------------------------------------------------------- /Maths/Pandigital_prime.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Apr 18 19:51:07 2017 4 | 5 | @author: Tirtha 6 | """ 7 | 8 | import math 9 | 10 | def is_prime(n): 11 | if n< 0: 12 | return False 13 | elif n == 0 or n==1: 14 | return False 15 | elif n==2: 16 | return True 17 | elif (str(n)[-1] == '2') or (str(n)[-1] == '4') or (str(n)[-1] == '6') or (str(n)[-1] == '8'): 18 | return False 19 | elif (str(n)[-1]=='5' and n!=5): 20 | return False 21 | elif (str(n)[-1]=='0'): 22 | return False 23 | else: 24 | for i in range(2,int(math.sqrt(n))+2): 25 | if (n%i == 0): 26 | #print ("Not a prime") 27 | return False 28 | else: 29 | #print ("Prime!") 30 | return True 31 | 32 | def is_pandigital(n,m): 33 | strn = str(n) 34 | #strl = len(strn) 35 | flag = True 36 | count=1 37 | for i in range(1,m+1): 38 | count = count*strn.count(str(i)) 39 | if count!=1: 40 | return False 41 | else: 42 | return True 43 | 44 | #return flag 45 | 46 | max = 0 47 | 48 | for i in range(9876543,1234567,-1): 49 | if is_pandigital(i,7): 50 | if is_prime(i): 51 | max = i 52 | break 53 | 54 | print (max) 55 | -------------------------------------------------------------------------------- /Maths/Quadratic_prime.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Apr 17 19:59:25 2017 4 | 5 | @author: Tirtha 6 | """ 7 | """ 8 | Considering quadratics of the form: 9 | n^2+a*n+b, where |a|<1000 and |b|≤1000, and |n| is the modulus/absolute value of n 10 | 11 | This program finds the product of the coefficients, a and b, for the quadratic 12 | expression that produces the maximum number of primes for consecutive values 13 | of n, starting with n=0. 14 | """ 15 | def is_prime(n): 16 | if n< 0: 17 | return False 18 | elif n == 0 or n==1: 19 | return False 20 | elif n==2: 21 | return True 22 | elif (str(n)[-1] == '2') or (str(n)[-1] == '4') or (str(n)[-1] == '6') or (str(n)[-1] == '8'): 23 | return False 24 | elif (str(n)[-1]=='5' and n!=5): 25 | return False 26 | elif (str(n)[-1]=='0'): 27 | return False 28 | else: 29 | for i in range(2,int(pow(n-1,0.5))+2): 30 | if (n%i == 0): 31 | #print ("Not a prime") 32 | return False 33 | else: 34 | #print ("Prime!") 35 | return True 36 | 37 | lst =[] 38 | lsta =[] 39 | lstb =[] 40 | maxn = 0 41 | for i in range(-100,100): 42 | for j in range (-100,100): 43 | n = 0 44 | while is_prime(n**2+i*n+j): 45 | n+=1 46 | lst.append(n-1) 47 | lsta.append(i) 48 | lstb.append(j) 49 | 50 | a = lsta[lst.index(max(lst))] 51 | b = lstb[lst.index(max(lst))] 52 | 53 | print ("Longest prime sequence is {} numbers".format(max(lst))) 54 | 55 | print ("Product of the coefficients of the quadratic prime producing longest sequence is {}".format(a*b)) 56 | -------------------------------------------------------------------------------- /Maths/Readme.md: -------------------------------------------------------------------------------- 1 | # Various maths operations 2 | 3 | * Various type of prime number generation 4 | * Various numerical sequence generation and counting 5 | * Fourier series calculations demo 6 | * Introduction to Numpy library and simple statistics 7 | * Area under curve of arbitrary function 8 | * Solving linear system of equation using linear algebra subroutines 9 | -------------------------------------------------------------------------------- /Maths/nth_prime.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Apr 16 23:53:34 2017 4 | 5 | @author: Tirtha 6 | """ 7 | 8 | def is_prime(n): 9 | if n< 0: 10 | return False 11 | elif n == 0 or n==1: 12 | return False 13 | elif n==2: 14 | return True 15 | elif (str(n)[-1] == '2') or (str(n)[-1] == '4') or (str(n)[-1] == '6') or (str(n)[-1] == '8'): 16 | return False 17 | elif (str(n)[-1]=='5' and n!=5): 18 | return False 19 | elif (str(n)[-1]=='0'): 20 | return False 21 | else: 22 | for i in range(2,int(pow(n-1,0.5))+2): 23 | if (n%i == 0): 24 | #print ("Not a prime") 25 | return False 26 | else: 27 | #print ("Prime!") 28 | return True 29 | i=0 30 | n=1 31 | final_n=2 32 | 33 | Nt = int(input("Enter n, where you want to determine nth prime: ")) 34 | 35 | while True: 36 | n+=1 37 | if is_prime(n): 38 | i+=1 39 | if i==Nt: 40 | final_n = n 41 | break 42 | 43 | print ("{}-th prime is {}".format(Nt,final_n)) 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Maths and Algorithms script in Python 3 -------------------------------------------------------------------------------- /Text_Analysis/Most_Frequent_Word_from_File.py: -------------------------------------------------------------------------------- 1 | name = input('Enter the name of file to be read: ') 2 | fhandle = open(name,'r') 3 | 4 | # Initialize a dictionary 5 | counts = dict() 6 | 7 | for line in fhandle: 8 | words = line.split() 9 | for word in words: 10 | counts[word.lower()]=counts.get(word.lower(),0)+1 11 | 12 | # Set initial counter variables 13 | bigcount = None 14 | bigword = None 15 | # Common words' list 16 | common_words = ['i','in','the','a','an','to','is','are','on','yes','no', 17 | 'not','he','she','you','I','my','me','at','of','so','but', 18 | 'it','as','if','for','oh','him','her','them','and','all', 19 | 'this','that','those','these','his','her','was','had','get', 20 | 'have','has','with','up','down','out','when','where','how', 21 | 'then','now'] 22 | 23 | """ 24 | Loop through the items of the dictionary with Tuple Unpacking. Ignore the common words (if you like) 25 | If the word count is higher than the running count, set it to the count and set the word to the 'bigword' variable 26 | """ 27 | for word,count in counts.items(): 28 | if word not in common_words : 29 | if bigcount is None or count > bigcount: 30 | bigword = word 31 | bigcount = count 32 | 33 | print(f"Most frequent word is '{bigword.upper()}', with frequency of {bigcount}") 34 | 35 | # Now prints the most frequenct N words 36 | 37 | top_N = int(input("How many most freqently used owrds do you want to display: ")) 38 | 39 | tmplst = [] 40 | for key,val in counts.items(): 41 | if key not in common_words: 42 | # Store the value first and then key (later used for sorting) 43 | newtup = (val,key) 44 | tmplst.append(newtup) 45 | 46 | # Sort the list by 'value' i.e. word count 47 | tmplst=sorted(tmplst,reverse=True) 48 | 49 | for val,key in tmplst[:top_N]: 50 | print(f"{key}:{val}") -------------------------------------------------------------------------------- /Text_Analysis/Readme.md: -------------------------------------------------------------------------------- 1 | Simple text analytics using Python 3 2 | -------------------------------------------------------------------------------- /Text_Analysis/Word_cloud.py: -------------------------------------------------------------------------------- 1 | 2 | import collections 3 | 4 | # Read input file, note the encoding is specified here, it may be different in your text file 5 | file = open('TaleOf2Cities.txt', encoding="utf8") 6 | a= file.read() 7 | 8 | # Stopwords 9 | stopwords = set(line.strip() for line in open('stopwords')) 10 | 11 | # Instantiate a dictionary, and for every word in the file, 12 | # Add to the dictionary if it doesn't exist. If it does, increase the count. 13 | wordcount = {} 14 | 15 | # To eliminate duplicates, remember to split by punctuation, and use case demiliters. 16 | for word in a.lower().split(): 17 | word = word.replace(".","") 18 | word = word.replace(",","") 19 | word = word.replace(":","") 20 | word = word.replace("\"","") 21 | word = word.replace("!","") 22 | word = word.replace("“","") 23 | if word not in stopwords: 24 | if word not in wordcount: 25 | wordcount[word] = 1 26 | else: 27 | wordcount[word] += 1 28 | 29 | # Print most common word 30 | n_print = int(input("How many most common words to print: ")) 31 | print("\nOK. The {} most common words are as follows\n".format(n_print)) 32 | word_counter = collections.Counter(wordcount) 33 | for word, count in word_counter.most_common(n_print): 34 | print(word, ": ", count) 35 | 36 | # Close the file 37 | file.close() 38 | 39 | 40 | -------------------------------------------------------------------------------- /Text_Analysis/Word_count_from_web.py: -------------------------------------------------------------------------------- 1 | import urllib.request, urllib.parse, urllib.error 2 | 3 | # Following example reads Project Gutenberg EBook of Adventures of Huckleberry Finn 4 | fhand = urllib.request.urlopen('http://www.gutenberg.org/files/76/76-0.txt') 5 | 6 | txt_dump = '' 7 | line_count=0 8 | word_count=0 9 | # Iterate over the lines in the file handler object and dump the data into the text string. Also increment line and word counts 10 | for line in fhand: 11 | # Use decode method to convert the UTF-8 to Unicode string 12 | txt_dump+=line.decode() 13 | line_count+=1 14 | # Count the length of words in the line and add to the running count 15 | word_count+=len(line.decode().split(' ')) 16 | 17 | # Prints basic information about the text data 18 | print("Printing some info on the text dump\n"+"-"*60) 19 | print("Total characters:",len(txt_dump)) 20 | print("Total words:",word_count) 21 | print(f"Total lines: {line_count}") 22 | 23 | 24 | # Function for counting top N words 25 | def print_top_N_words(text, top_N=10): 26 | """ 27 | This function accepts a text data (in the form of string) and extracts the top N words from it. 28 | N is supplied to the function. If not, default 10 is taken. 29 | """ 30 | # Initialize a dictionary 31 | counts = dict() 32 | txt_dump=text 33 | top_N=top_N 34 | words = txt_dump.split() 35 | for word in words: 36 | counts[word.lower()]=counts.get(word.lower(),0)+1 37 | 38 | common_words = set(line.strip() for line in open('stopwords.txt')) 39 | tmplst = [] 40 | for key,val in counts.items(): 41 | if key not in common_words: 42 | # Store the value first and then key (later used for sorting) 43 | newtup = (val,key) 44 | tmplst.append(newtup) 45 | 46 | # Sort the list by 'value' i.e. word count 47 | tmplst=sorted(tmplst,reverse=True) 48 | 49 | print(f"Top {top_N} words in this file are shown below\n"+"-"*55) 50 | for val,key in tmplst[:top_N]: 51 | print(f"{key}:{val}") 52 | 53 | # Common words' list 54 | 55 | common_words = ['i','in','the','a','an','to','is','are','on','yes','no', 56 | 'not','he','she','you','I','my','me','at','of','so','but', 57 | 'it','as','if','for','oh','him','her','them','and','all', 58 | 'this','that','those','these','his','her','was','had','get', 59 | 'have','has','with','up','down','out','when','where','how', 60 | 'then','now','we','they','got','there','by','or','by','would', 61 | 'will','shall','what','be','do','done','did'] 62 | 63 | 64 | # Now prints the most frequenct N words 65 | top_N = int(input("How many most freqently used owrds do you want to display: ")) 66 | print_top_N_words(txt_dump,top_N) 67 | 68 | -------------------------------------------------------------------------------- /Text_Analysis/stopwords: -------------------------------------------------------------------------------- 1 | a 2 | about 3 | above 4 | after 5 | again 6 | against 7 | all 8 | am 9 | an 10 | and 11 | any 12 | are 13 | aren't 14 | as 15 | at 16 | be 17 | because 18 | been 19 | before 20 | being 21 | below 22 | between 23 | both 24 | but 25 | by 26 | can 27 | can't 28 | cannot 29 | com 30 | could 31 | couldn't 32 | did 33 | didn't 34 | do 35 | does 36 | doesn't 37 | doing 38 | don't 39 | down 40 | during 41 | each 42 | else 43 | ever 44 | few 45 | for 46 | from 47 | further 48 | get 49 | had 50 | hadn't 51 | has 52 | hasn't 53 | have 54 | haven't 55 | having 56 | he 57 | he'd 58 | he'll 59 | he's 60 | her 61 | here 62 | here's 63 | hers 64 | herself 65 | him 66 | himself 67 | his 68 | how 69 | how's 70 | http 71 | i 72 | i'd 73 | i'll 74 | i'm 75 | i've 76 | if 77 | in 78 | into 79 | is 80 | isn't 81 | it 82 | it's 83 | its 84 | itself 85 | just 86 | k 87 | let's 88 | like 89 | me 90 | more 91 | most 92 | mustn't 93 | my 94 | myself 95 | no 96 | nor 97 | not 98 | of 99 | off 100 | on 101 | once 102 | only 103 | or 104 | other 105 | ought 106 | our 107 | ours 108 | ourselves 109 | out 110 | over 111 | own 112 | r 113 | same 114 | shall 115 | shan't 116 | she 117 | she'd 118 | she'll 119 | she's 120 | should 121 | shouldn't 122 | so 123 | some 124 | such 125 | than 126 | that 127 | that's 128 | the 129 | their 130 | theirs 131 | them 132 | themselves 133 | then 134 | there 135 | there's 136 | these 137 | they 138 | they'd 139 | they'll 140 | they're 141 | they've 142 | this 143 | those 144 | through 145 | to 146 | too 147 | under 148 | until 149 | up 150 | very 151 | was 152 | wasn't 153 | we 154 | we'd 155 | we'll 156 | we're 157 | we've 158 | were 159 | weren't 160 | what 161 | what's 162 | when 163 | when's 164 | where 165 | where's 166 | which 167 | while 168 | who 169 | who's 170 | whom 171 | why 172 | why's 173 | with 174 | won't 175 | would 176 | wouldn't 177 | www 178 | you 179 | you'd 180 | you'll 181 | you're 182 | you've 183 | your 184 | yours 185 | yourself 186 | yourselves --------------------------------------------------------------------------------