├── .gitignore ├── .idea ├── .gitignore ├── algorithm.iml ├── codeStyles │ └── codeStyleConfig.xml ├── dbnavigator.xml ├── encodings.xml ├── inspectionProfiles │ └── profiles_settings.xml ├── misc.xml └── vcs.xml ├── Bellman_Ford_matrix.py ├── FengSort.c ├── Horner_rule.py ├── Johnson.py ├── Queue.py ├── README.md ├── SeekSum.c ├── activity_selection.py ├── add.c ├── all_pairs_shortest_paths.py ├── any_disks_intersect.py ├── any_segments_intersect.py ├── automaton_string_match.py ├── b_tree_example.py ├── bh_tree.py ├── binary_add.py ├── binary_search.py ├── binarycounter.py ├── btree.py ├── bubble_sort.py ├── closest_points.py ├── closest_points_l1_distance.py ├── closest_points_l_infinite_distance.py ├── common-matrix-multiply-Strassen.py ├── common-matrix-multiply-recursive.py ├── comparable.py ├── constraints.py ├── contains.py ├── counting_sort.py ├── cut_rod.py ├── depth_tree.py ├── deque.py ├── disjoint_sets_forest.py ├── disjoint_sets_linked_list.py ├── dynamic_array.py ├── eight_queen.py ├── euclid.py ├── extended_bottom_up_cut_rod.py ├── fft.py ├── fibonacciheap.py ├── gcd.py ├── graph.py ├── hamiltonian_path.py ├── hash.py ├── heap.py ├── huffman.py ├── insertion_sort.py ├── interpolation.py ├── interval_graph_coloring.py ├── interval_tree.py ├── inversion.py ├── inversion_tree.py ├── k_way_merge.py ├── kleene_star.py ├── knapsack_0_1.py ├── kth-Quantiles.py ├── linkedlist.py ├── longest_common_subsequence.py ├── longest_monotonically_increasing_subsequence.py ├── longest_palindrome_subsequence.py ├── lowest_common_multiple.py ├── matrix_chain_order.py ├── matrix_pow.c ├── max_subsequence_sum.c ├── maximum-subarray-brute-force.c ├── maximum-subarray-inline.c ├── maximum-subarray-recursive.c ├── memoized_cut_rod.py ├── merge.py ├── merge_sort.py ├── min_gap_tree.py ├── min_heap_with_linked_list.py ├── min_heap_with_linked_list_test.py ├── min_priority_queue_using_rb_tree.py ├── mod_exp.c ├── most_reliable_path.py ├── optimal_binary_search_tree.py ├── os_tree.py ├── parallel_fib.c ├── parallel_mat_vec.c ├── parallel_merge_sort.c ├── parallel_square_matrix_multiply.c ├── partition.py ├── pointer_tree.py ├── polar_angle.py ├── polygon_area.py ├── polynomial_multiply.py ├── pow.py ├── priority_queue.py ├── quicksort.py ├── random_array.py ├── randomized_permute.py ├── randomized_select.py ├── rank_tree.py ├── rb_tree.py ├── right_horizontal_ray_intersect.py ├── segment_intersect.py ├── selection_sort.py ├── simplex.py ├── single_edge.py ├── square-matrix-multiply-brute-force.c ├── square-matrix-multiply-brute-force2.c ├── square-matrix-multiply-recursive.c ├── square_matrix_multiply_Strassen.py ├── stack.py ├── synthetic_division.py ├── tests ├── Bellman_Ford_matrix_test.py ├── Horner_rule_test.py ├── Johnson_test.py ├── __init__.py ├── all_pairs_shortest_paths_test.py ├── bh_tree_test.py ├── binary_search_test.py ├── bubble_sort_test.py ├── constraints_test.py ├── contains_test.py ├── counting_sort_test.py ├── cut_rod_test.py ├── depth_tree_test.py ├── disjoint_sets_forest_test.py ├── disjoint_sets_test.py ├── graph_test.py ├── hamiltonian_path_test.py ├── heap_test.py ├── insertion_sort_test.py ├── interval_tree_test.py ├── inversion_test.py ├── k_way_merge_test.py ├── linked_list_test.py ├── longest_common_subsequence_test.py ├── longest_monotonically_increasing_subsequence_test.py ├── merge_sort_test.py ├── min_gap_tree_test.py ├── min_heap_with_linked_list_test.py ├── min_priority_queue_using_rb_tree_test.py ├── most_reliable_path_test.py ├── os_tree_test.py ├── partition_test.py ├── pointer_tree_test.py ├── polygon_area_test.py ├── priority_queue_test.py ├── quicksort_test.py ├── randomized_select_test.py ├── rank_tree_test.py ├── rb_tree_test.py ├── selection_sort_test.py ├── test_binary_add.py ├── test_deque.py ├── test_dynamic_array.py ├── test_euclid.py ├── test_gcd.py ├── test_lowest_common_multiple.py ├── test_merge.py ├── test_pow.py ├── test_queue.py ├── two_sum_test.py ├── universal_sink_test.py ├── vEB_tree_test.py └── wrestlers_test.py ├── three_points_colinear.py ├── three_sum.py ├── tree.py ├── two_sum.py ├── universal_sink.py ├── vEB_tree.py └── wrestlers.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | a.out 9 | *.o 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .coverage 43 | .coverage.* 44 | .cache 45 | nosetests.xml 46 | coverage.xml 47 | *,cover 48 | .hypothesis/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | 57 | # Sphinx documentation 58 | docs/_build/ 59 | 60 | # PyBuilder 61 | target/ 62 | 63 | #Ipython Notebook 64 | .ipynb_checkpoints 65 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml 3 | -------------------------------------------------------------------------------- /.idea/algorithm.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Bellman_Ford_matrix.py: -------------------------------------------------------------------------------- 1 | 2 | def Bellman_Ford_matrix(W, s): 3 | n = W.shape[0] 4 | d = [float("Inf")] * n 5 | p = [None] * n 6 | d[s - 1] = 0 7 | for k in range(1, n): 8 | for i in range(1, n + 1): 9 | for j in range(1, n + 1): 10 | if d[j - 1] > d[i - 1] + W[i - 1, j - 1]: 11 | d[j - 1] = d[i - 1] + W[i - 1, j - 1] 12 | p[j - 1] = i 13 | print(d) 14 | print(p) 15 | return d, p 16 | 17 | 18 | def extend_shortest_paths(L, W): 19 | n = W.shape[0] 20 | LW = [float("Inf")] * n 21 | for j in range(n): 22 | for k in range(n): 23 | LW[j] = min(LW[j], L[k] + W[k, j]) 24 | return LW 25 | 26 | 27 | def slow_all_pairs_shortest_paths(W, s): 28 | n = W.shape[0] 29 | L = [0] * n 30 | for i in range(n): 31 | if i + 1 == s: 32 | L[i] = 0 33 | else: 34 | L[i] = float("Inf") 35 | print(L) 36 | for m in range(1, n): 37 | L = extend_shortest_paths(L, W) 38 | print(L) 39 | return L 40 | 41 | 42 | def extend_shortest_paths_with_predecessor_subgraph(s, L, P, W): 43 | n = W.shape[0] 44 | LW = [float("Inf")] * n 45 | PP = [None] * n 46 | for j in range(n): 47 | for k in range(n): 48 | if LW[j] > L[k] + W[k, j]: 49 | LW[j] = L[k] + W[k, j] 50 | PP[j] = k + 1 51 | if LW[j] == L[j]: 52 | PP[j] = P[j] 53 | return LW, PP 54 | 55 | 56 | def slow_all_pairs_shortest_paths_with_predecessor_subgraph(W, s): 57 | n = W.shape[0] 58 | L = [float("Inf")] * n 59 | L[s - 1] = 0 60 | P = [None] * n 61 | for m in range(1, n): 62 | L, P = extend_shortest_paths_with_predecessor_subgraph(s, L, P, W) 63 | print(L) 64 | print(P) 65 | return L, P 66 | 67 | 68 | def faster_all_pairs_shortest_paths(W): 69 | n = W.shape[0] 70 | L = W 71 | m = 1 72 | while m < n - 1: 73 | L = extend_shortest_paths(L, L) 74 | m = 2 * m 75 | print(m) 76 | print(L) 77 | return Ld, p 78 | -------------------------------------------------------------------------------- /FengSort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void FengSort(int A[], int first, int end) 6 | { 7 | int length = end - first + 1; 8 | int MAX = 100; 9 | int *B = (int *)calloc(MAX + 1, sizeof(int)); 10 | int i, j; 11 | int LIMIT = MAX + 1; 12 | 13 | for (i = 1; i <= MAX; i++) 14 | B[i] = LIMIT; 15 | for (i = 0; i < length; i++) 16 | B[A[i]] = A[i]; 17 | j = 0; 18 | for (i = 1; i <= MAX; i++) 19 | if (B[i] != LIMIT) 20 | A[j++] = B[i]; 21 | free(B); 22 | } 23 | 24 | int main() 25 | { 26 | int a[9] = { 3, 41, 52, 31, 31, 57, 9, 31, 100 }; 27 | int b[2] = {100, 2}; 28 | // int a[2] = {4,3}; 29 | // int a[3] = {4, 3, 1}; 30 | // Combine(a, 0, 3, 5); 31 | FengSort(a, 0, 8); 32 | printf("%d, %d, %d, %d, %d, %d, %d, %d, %d\n", a[0], a[1], a[2], a[3], 33 | a[4], a[5], a[6], a[7], a[8]); 34 | FengSort(b, 0, 1); 35 | printf("%d,%d\n", b[0], b[1]); 36 | exit(0); 37 | } 38 | -------------------------------------------------------------------------------- /Horner_rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | import functools 4 | 5 | 6 | def Horner_rule(x, coefficients): 7 | """ 8 | Implements Horner's rule 9 | :param x: 10 | :param coefficients: 11 | :return: 12 | """ 13 | return functools.reduce(lambda accumulate, coefficient: coefficient + accumulate * x, reversed(coefficients), 0) 14 | -------------------------------------------------------------------------------- /Johnson.py: -------------------------------------------------------------------------------- 1 | from graph import min_priority_queue, Vertex, Graph 2 | import numpy as np 3 | 4 | 5 | def Bellman_Ford(self, w, s): 6 | """ 7 | The Bellman-Ford algorithm solves the single-source 8 | shortest-paths problem in the general case in which edge 9 | weights may be negative. 10 | If there is a negative-weight cycle that is reachable from 11 | the source s, this function returns False and indicates that 12 | no solution exists. 13 | If there is no such cycle, this function returns True and produces 14 | the shortest paths and their weights. 15 | 16 | :param self: 17 | :param w: 18 | :param s: 19 | :return: 20 | """ 21 | initialize_single_source(self, s) 22 | for i in range(1, len(self.vertices)): 23 | for u, v in self.edges: 24 | relax(u, v, w) 25 | for u, v in self.edges: 26 | if v.d > u.d + w[(u, v)]: 27 | return False 28 | return True 29 | 30 | 31 | def initialize_single_source(self, s): 32 | for v in self.vertices: 33 | v.d = float("Inf") 34 | v.p = None 35 | s.d = 0 36 | 37 | 38 | def relax(u, v, w): 39 | if v.d > u.d + w[u, v]: 40 | v.d = u.d + w[u, v] 41 | v.p = u 42 | 43 | 44 | def Dijkstra(self, w, s): 45 | """ 46 | Dijkstra's algorithm solves the single-source shortest-paths problem 47 | on a weighted, directed graph G = (V, E) for the case in which all edge 48 | weights are nonnegative. 49 | """ 50 | initialize_single_source(self, s) 51 | S = set() 52 | Q = min_priority_queue(self.vertices, 'd') 53 | while Q.heap_size > 1: 54 | u = Q.heap_extract_min() 55 | S = S.union({u}) 56 | for v in self.adj[u]: 57 | if v.d > u.d + w[u, v]: 58 | v.d = u.d + w[u, v] 59 | v.p = u 60 | Q.heap_decrease_key(v.index, u.d + w[u, v]) 61 | 62 | 63 | def Johnson(self, w): 64 | G = self 65 | n = len(G.vertices) 66 | s = Vertex("s") 67 | GG = Graph(G.vertices.union({s}), G.edges | set((s, v) for v in G.vertices)) 68 | for v in G.vertices: 69 | w[(s, v)] = 0 70 | if not Bellman_Ford(GG, w, s): 71 | print("the input graph contains a negative-weight cycle") 72 | else: 73 | h = dict() 74 | for v in GG.vertices: 75 | h[v] = v.d 76 | # for key,value in h.iteritems(): 77 | # print(( "h({}) = {}".format(key, value))) 78 | ww = dict() 79 | for u, v in GG.edges: 80 | ww[(u, v)] = w[(u, v)] + h[u] - h[v] 81 | # for key,value in ww.iteritems(): 82 | # print(( "ww({}) = {}".format(key, value))) 83 | D = np.empty((n, n)) 84 | for u in G.vertices: 85 | Dijkstra(G, ww, u) 86 | for v in G.vertices: 87 | D[u.key - 1, v.key - 1] = v.d + h[v] - h[u] 88 | return D 89 | -------------------------------------------------------------------------------- /Queue.py: -------------------------------------------------------------------------------- 1 | class FullException(Exception): 2 | def __init__(self): 3 | Exception.__init__(self) 4 | 5 | 6 | class EmptyException(Exception): 7 | def __init__(self): 8 | Exception.__init__(self) 9 | 10 | 11 | class Queue: 12 | def __init__(self, size): 13 | self.data = [0] * size 14 | self.size = size 15 | self.head = 0 16 | self.tail = 0 17 | 18 | def enqueue(self, x): 19 | if self.full(): 20 | raise FullException() 21 | self.data[self.tail] = x 22 | if self.tail == self.size - 1: 23 | self.tail = 0 24 | else: 25 | self.tail = self.tail + 1 26 | 27 | def dequeue(self): 28 | if self.empty(): 29 | raise EmptyException() 30 | x = self.data[self.head] 31 | if self.head == self.size - 1: 32 | self.head = 0 33 | else: 34 | self.head = self.head + 1 35 | return x 36 | 37 | def empty(self): 38 | return self.tail == self.head 39 | 40 | def full(self): 41 | return (self.tail + 1) % self.size == self.head 42 | 43 | def capacity(self): 44 | return self.size - 1 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # algorithm 2 | implementation of algorithms in CLRS 3 | 4 | ## note 5 | Since python2 is outdated, the original python2.7 code is moved to python2.7 branch. 6 | The master branch support python3 only. 7 | 8 | ## test 9 | Run testcase in tests folder 10 | -------------------------------------------------------------------------------- /SeekSum.c: -------------------------------------------------------------------------------- 1 | #include 2 | //An algorithm that, given a set S of n integers and another integer x, 3 | //determines whether or not there exist two elements in S whose sum is 4 | //exactly x. The set S must be already sorted 5 | 6 | int BinSearch(int A[], int first, int end, int x) { 7 | int length = end - first; 8 | int inter; 9 | 10 | while (length >= 0) { 11 | inter = (first + end) / 2; 12 | if (x == A[inter] ) 13 | return inter + 1; 14 | else if (x < A[inter]) 15 | end = inter - 1; 16 | else 17 | first = inter + 1; 18 | length = end - first; 19 | } 20 | return -1; 21 | } 22 | 23 | void SeekSum(int A[], int first, int end, int x) { 24 | int i; 25 | int pos; 26 | 27 | for (i = first; i < end; i++) 28 | if ((pos = BinSearch(A, i + 1, end, x - A[i])) != -1) { 29 | printf("first = %d,end = %d\n",i + 1, pos); 30 | break; 31 | } 32 | } 33 | 34 | 35 | int main() { 36 | int A[10] = {2,3,4,6, 7, 8, 8, 10, 15 , 70}; 37 | 38 | SeekSum(A, 0, 9, 15); 39 | SeekSum(A, 0, 9, 25); 40 | SeekSum(A, 0, 9, 12); 41 | SeekSum(A, 0, 9, 13); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /activity_selection.py: -------------------------------------------------------------------------------- 1 | from numpy import zeros 2 | 3 | 4 | def activity_selection(s, f, n): 5 | c = zeros((n + 2, n + 2)) 6 | activities = zeros((n + 2, n + 2)) 7 | s = [float("-Inf")] + s[0:n] + [float("Inf")] 8 | f = [float("-Inf")] + f[0:n] + [float("Inf")] 9 | for l in range(3, n + 3): 10 | for i in range(n + 3 - l): 11 | j = i + l - 1 12 | print("i = {}, j = {}".format(i, j)) 13 | for k in range(i + 1, j): 14 | print("k = {}".format(k)) 15 | print("s[{}] = {}, f[{}] = {}".format(k, s[k], k, f[k])) 16 | print("s[{}] = {}, f[{}] = {}".format(j, s[j], i, f[i])) 17 | if f[i] <= s[k] and f[k] <= s[j]: 18 | t = c[i, k] + c[k, j] + 1 19 | print("t = {}, c[{}, {}] = {}".format(t, i, j, c[i, j])) 20 | if t > c[i, j]: 21 | c[i, j] = t 22 | activities[i, j] = k 23 | return c, activities 24 | 25 | 26 | def activity_selection_with_weight(s, f, v, n): 27 | """ 28 | This is a modification to the activity-selection problem in which each activity has, 29 | in addition to a start and finish time, a value v. Now the object is to maximize 30 | the total value of the activities scheduled. It can be solved by dynamic programming method 31 | """ 32 | c = zeros((n + 2, n + 2)) 33 | activities = zeros((n + 2, n + 2)) 34 | s = [float("-Inf")] + s[0:n] + [float("Inf")] 35 | f = [float("-Inf")] + f[0:n] + [float("Inf")] 36 | for l in range(3, n + 3): 37 | for i in range(n + 3 - l): 38 | j = i + l - 1 39 | for k in range(i + 1, j): 40 | if f[i] <= s[k] and f[k] <= s[j]: 41 | t = c[i, k] + c[k, j] + v[k - 1] 42 | if t > c[i, j]: 43 | c[i, j] = t 44 | activities[i, j] = k 45 | return c, activities 46 | 47 | 48 | def recursive_activity_selector(s, f, n): 49 | f = [float("-Inf")] + f 50 | return recursive_activity_selector_aux(s, f, 0, n) 51 | 52 | 53 | def recursive_activity_selector_aux(s, f, k, n): 54 | m = k + 1 55 | while m <= n and s[m - 1] < f[k]: 56 | m = m + 1 57 | if m <= n: 58 | return {m}.union(recursive_activity_selector_aux(s, f, m, n)) 59 | else: 60 | return {} 61 | 62 | 63 | def greedy_activity_selector(s, f): 64 | n = len(s) 65 | A = {1} 66 | k = 1 67 | for m in range(2, n + 1): 68 | if s[m - 1] >= f[k - 1]: 69 | A = A.union({m}) 70 | k = m 71 | return A 72 | 73 | 74 | def greedy_activity_selector_last(s, f): 75 | """Instead of always selecting the first activity to finish, 76 | select the last activity to start that is compatible with all 77 | previously selected activities 78 | """ 79 | n = len(s) 80 | A = {n} 81 | k = n 82 | for m in range(n - 1, 0, -1): 83 | if f[m - 1] <= s[k - 1]: 84 | A = A.union({m}) 85 | k = m 86 | return A 87 | 88 | 89 | def print_activity(activities): 90 | m = activities.shape[0] - 1 91 | n = activities.shape[1] - 1 92 | print_activity_aux(activities, 0, n) 93 | 94 | 95 | def print_activity_aux(activities, m, n): 96 | a = activities[m, n] 97 | if a == 0: 98 | return 99 | print_activity_aux(activities, m, a) 100 | print(int(a)) 101 | print_activity_aux(activities, a, n) 102 | -------------------------------------------------------------------------------- /add.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define N 2 4 | void submatrix_init(int *S, int S_row, int S_col, int *T, int T_row, int T_col, int row_start, int col_start); 5 | 6 | int main() { 7 | int A[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 8 | int B[4] = {1, 2, 3, 4}; 9 | int C[4] = {1, 0, 2, 1}; 10 | int D[4]; 11 | int E[4]; 12 | int i, j; 13 | 14 | 15 | //submatrix_init(A, 4, 4, B, 2, 2, 1, 1); 16 | //submatrix_init(A, 4, 4, C, 2, 2, 1, 3); 17 | //submatrix_init(A, 4, 4, D, 2, 2, 3, 1); 18 | //submatrix_init(A, 4, 4, E, 2, 2, 3, 3); 19 | //printf("Matrix A:\n"); 20 | //for (i = 0; i < 4; i++) { 21 | //for (j = 0; j < 4; j++) 22 | //printf("%d\t", *(A + 4 * i + j)); 23 | //printf("\n"); 24 | //} 25 | //printf("\n"); 26 | //printf("Matrix B:\n"); 27 | //for (i = 0; i < N; i++) { 28 | //for (j = 0; j < N; j++) 29 | //printf("%d\t", *(B + N * i + j)); 30 | //printf("\n"); 31 | //} 32 | //printf("\n"); 33 | //printf("Matrix C:\n"); 34 | //for (i = 0; i < N; i++) { 35 | //for (j = 0; j < N; j++) 36 | //printf("%d\t", *(C + N * i + j)); 37 | //printf("\n"); 38 | //} 39 | //printf("\n"); 40 | //printf("Matrix D:\n"); 41 | //for (i = 0; i < N; i++) { 42 | //for (j = 0; j < N; j++) 43 | //printf("%d\t", *(D + N * i + j)); 44 | //printf("\n"); 45 | //} 46 | //printf("\n"); 47 | //printf("Matrix E:\n"); 48 | //for (i = 0; i < N; i++) { 49 | //for (j = 0; j < N; j++) 50 | //printf("%d\t", *(E + N * i + j)); 51 | //printf("\n"); 52 | //} 53 | //printf("\n"); 54 | square_matrix_multiply(B, C, E, 2); 55 | printf("Matrix E:\n"); 56 | for (i = 0; i < N; i++) { 57 | for (j = 0; j < N; j++) 58 | printf("%d\t", *(E + N * i + j)); 59 | printf("\n"); 60 | } 61 | printf("\n"); 62 | } 63 | -------------------------------------------------------------------------------- /automaton_string_match.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def finite_automaton_matcher(T, s, m): 5 | n = len(T) 6 | q = 0 7 | for i in range(1, n + 1): 8 | q = s[(q, T[i - 1])] 9 | if q == m: 10 | print("Pattern occurs with shift {}".format(i - m)) 11 | 12 | 13 | def compute_transition_function(P, domain): 14 | m = len(P) 15 | s = dict() 16 | for a in domain: 17 | for q in range(m + 1): 18 | k = min(q + 1, m) 19 | while not (P[0:q] + a).endswith(P[0:k]): 20 | k = k - 1 21 | s[(q, a)] = k 22 | return s 23 | 24 | 25 | def automaton_string_match(P, T, domain): 26 | s = compute_transition_function(P, domain) 27 | m = len(P) 28 | finite_automaton_matcher(T, s, m) 29 | -------------------------------------------------------------------------------- /b_tree_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import btree as bt 4 | 5 | a = bt.BTreeNode(3, True, 2) 6 | a.key[0] = 'A' 7 | a.key[1] = 'B' 8 | b = bt.BTreeNode(3, True, 3) 9 | b.key[0] = 'D' 10 | b.key[1] = 'E' 11 | b.key[2] = 'F' 12 | c = bt.BTreeNode(3, True, 3) 13 | c.key[0] = 'J' 14 | c.key[1] = 'K' 15 | c.key[2] = 'L' 16 | d = bt.BTreeNode(3, True, 2) 17 | d.key[0] = 'N' 18 | d.key[1] = 'O' 19 | x = bt.BTreeNode(3, True, 3) 20 | x.key[0] = 'Q' 21 | x.key[1] = 'R' 22 | x.key[2] = 'S' 23 | y = bt.BTreeNode(3, True, 2) 24 | y.key[0] = 'U' 25 | y.key[1] = 'V' 26 | z = bt.BTreeNode(3, True, 2) 27 | z.key[0] = 'Y' 28 | z.key[1] = 'Z' 29 | e = bt.BTreeNode(3, False, 3) 30 | e.key[0] = 'C' 31 | e.key[1] = 'G' 32 | e.key[2] = 'M' 33 | e.c[0] = a 34 | e.c[1] = b 35 | e.c[2] = c 36 | e.c[3] = d 37 | v = bt.BTreeNode(3, False, 2) 38 | v.key[0] = 'T' 39 | v.key[1] = 'X' 40 | v.c[0] = x 41 | v.c[1] = y 42 | v.c[2] = z 43 | t = bt.BTree(3) 44 | t.root.key[0] = 'P' 45 | t.root.c[0] = e 46 | t.root.c[1] = v 47 | t.root.n = 1 48 | t.root.leaf = False 49 | t.root.delete(t, 'F') 50 | t.root.print_child_first() 51 | print() 52 | t.root.delete(t, 'M') 53 | t.root.print_child_first() 54 | print() 55 | t.root.delete(t, 'G') 56 | t.root.print_child_first() 57 | print() 58 | t.root.delete(t, 'D') 59 | t.root.print_child_first() 60 | print() 61 | t.root.delete(t, 'B') 62 | t.root.print_child_first() 63 | print() 64 | t.root.delete(t, 'C') 65 | t.root.print_child_first() 66 | print() 67 | t.root.delete(t, 'P') 68 | t.root.print_child_first() 69 | print() 70 | t.root.delete(t, 'V') 71 | t.root.print_child_first() 72 | print() 73 | -------------------------------------------------------------------------------- /bh_tree.py: -------------------------------------------------------------------------------- 1 | # A variant of red black tree that has black_height attribute 2 | # !/usr/bin/env python 3 | 4 | from rb_tree import RbNode, RbTree 5 | 6 | 7 | class bh_node(RbNode): 8 | def __init__(self, key, p, left, right, color, bh): 9 | RbNode.__init__(self, key, p, left, right, color) 10 | self.bh = bh 11 | 12 | 13 | class bh_tree(RbTree): 14 | nil = bh_node(None, None, None, None, 1, 0) 15 | root = nil 16 | 17 | def __init__(self, values): 18 | if isinstance(values, list): 19 | for i in values: 20 | self.insert(bh_node(i, None, None, None, 0, 1)) 21 | else: 22 | print("Not invalid argument") 23 | 24 | def insert_fixed(self, z): 25 | while z.p.color == 0: 26 | if z.p.p.left == z.p: 27 | y = z.p.p.right 28 | if y.color == 0: 29 | z.p.color = 1 30 | y.color = 1 31 | z.p.p.color = 0 32 | z = z.p.p 33 | z.bh = z.bh + 1 34 | else: 35 | if z.p.right == z: 36 | z = z.p 37 | self.left_rotate(z) 38 | z = z.p.p 39 | self.right_rotate(z) 40 | z.color = 0 41 | z.p.color = 1 42 | else: 43 | y = z.p.p.left 44 | if y.color == 0: 45 | z.p.color = 1 46 | y.color = 1 47 | z.p.p.color = 0 48 | z = z.p.p 49 | z.bh = z.bh + 1 50 | else: 51 | if z.p.left == z: 52 | z = z.p 53 | self.right_rotate(z) 54 | z = z.p.p 55 | self.left_rotate(z) 56 | z.color = 0 57 | z.p.color = 1 58 | self.root.color = 1 59 | 60 | def delete_fixup(self, x): 61 | while x != self.root and x.color == 1: 62 | if x == x.p.left: 63 | w = x.p.right 64 | if w.color == 0: 65 | w.color = 1 66 | x.p.color = 0 67 | self.left_rotate(x.p) 68 | w = x.p.right 69 | if w.left.color == 1 and w.right.color == 1: 70 | w.color = 0 71 | x = x.p 72 | x.bh = x.bh - 1 73 | else: 74 | if w.left.color == 0 and w.right.color == 1: 75 | w.left.color = 1 76 | w.color = 0 77 | self.right_rotate(w) 78 | w = x.p.right 79 | w.color = x.p.color 80 | x.p.color = 1 81 | w.right.color = 1 82 | self.left_rotate(x.p) 83 | w.bh = w.bh + 1 84 | x = self.root 85 | else: 86 | w = x.p.left 87 | if w.color == 0: 88 | w.color = 1 89 | x.p.color = 0 90 | self.right_rotate(x.p) 91 | w = x.p.left 92 | if w.left.color == 1 and w.right.color == 1: 93 | w.color = 0 94 | x = x.p 95 | else: 96 | if w.left.color == 1 and w.right.color == 0: 97 | w.right.color = 1 98 | w.color = 0 99 | self.left_rotate(w) 100 | w = x.p.left 101 | w.color = x.p.color 102 | w.left.color = 1 103 | x.p.color = 1 104 | self.right_rotate(x.p) 105 | w.bh = w.bh + 1 106 | x = self.root 107 | x.color = 1 108 | -------------------------------------------------------------------------------- /binary_add.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | def binary_add(array1, array2): 6 | """ 7 | Consider the problem of adding two n-bit binary integers, stored in two n-element arrays A and B, 8 | in big-endian order. 9 | The sum of the two integers should be stored in binary form in a (n + 1)-element array C. 10 | :param array1: n-element array A 11 | :param array2: n-element array B 12 | :return: (n + 1)-element array C 13 | """ 14 | assert len(array1) == len(array2) 15 | n = len(array1) 16 | promote = 0 17 | array3 = [0] * (n + 1) 18 | for i in range(n - 1, -1, -1): 19 | result = array1[i] + array2[i] + promote 20 | promote = result // 2 21 | array3[i + 1] = result % 2 22 | array3[0] = promote 23 | return array3 24 | -------------------------------------------------------------------------------- /binary_search.py: -------------------------------------------------------------------------------- 1 | def binary_search(target, array): 2 | """ 3 | find target in sorted array. 4 | If found, return the index, otherwise return -1. 5 | :param target: 6 | :param array: list 7 | :return: 8 | """ 9 | low = 0 10 | high = len(array) - 1 11 | while low <= high: 12 | mid = (low + high) // 2 13 | if target < array[mid]: 14 | high = mid - 1 15 | elif target > array[mid]: 16 | low = mid + 1 17 | else: 18 | return mid 19 | return -1 20 | 21 | 22 | def bisect_left(array, x, low=0, high=None): 23 | """ 24 | Locate the insertion point for x in a to maintain sorted order. 25 | If x is already present in a, 26 | the insertion point will be before (to the left of) any existing entries. 27 | The return value is suitable for use as the first parameter to list.insert() assuming that a is already sorted. 28 | Optional args lo (default 0) and hi (default len(a)) bound the 29 | slice of a to be searched. 30 | 31 | :param array: sorted list 32 | :param x: 33 | :param low: 34 | :param high: 35 | :return: 36 | """ 37 | if high is None: 38 | high = len(array) 39 | assert low <= high 40 | while low < high: 41 | mid = (low + high) // 2 42 | if array[mid] < x: 43 | low = mid + 1 44 | else: 45 | high = mid 46 | return low 47 | 48 | 49 | def bisect_right(array, x, low=0, high=None): 50 | """ 51 | Return the index where to insert item x in list a, assuming a is sorted. 52 | 53 | The return value i is such that all e in a[:i] have e <= x, and all e in 54 | a[i:] have e > x. So if x already appears in the list, a.insert(x) will 55 | insert just after the rightmost x already there. 56 | 57 | Optional args lo (default 0) and hi (default len(a)) bound the 58 | slice of a to be searched. 59 | :param array: 60 | :param x: 61 | :param low: 62 | :param high: 63 | :return: 64 | """ 65 | if high is None: 66 | high = len(array) 67 | assert low <= high 68 | while low < high: 69 | mid = (low + high) // 2 70 | if array[mid] <= x: 71 | low = mid + 1 72 | else: 73 | high = mid 74 | return low 75 | -------------------------------------------------------------------------------- /binarycounter.py: -------------------------------------------------------------------------------- 1 | class BinaryCounter(list): 2 | def __init__(self, size): 3 | self.leftmost_1 = -1 4 | super(BinaryCounter, self).__init__([0] * size) 5 | 6 | def increment(self): 7 | i = 0 8 | while i < len(self) and self[i] == 1: 9 | self[i] = 0 10 | i = i + 1 11 | if i < len(self): 12 | self[i] = 1 13 | if self.leftmost_1 < i: 14 | self.leftmost_1 = i 15 | else: 16 | self.leftmost_1 = -1 17 | 18 | def reset(self): 19 | for i in range(self.leftmost_1 + 1): 20 | self[i] = 0 21 | self.leftmost_1 = -1 22 | 23 | def print_bits(self): 24 | print(self[::-1]) 25 | -------------------------------------------------------------------------------- /bubble_sort.py: -------------------------------------------------------------------------------- 1 | def bubble_sort(array): 2 | """ 3 | O(n ^ 2) inplace sort 4 | :param array: list 5 | :return: 6 | """ 7 | n = len(array) 8 | for i in range(n): 9 | for j in range(n - 1, i, -1): 10 | if array[j] < array[j - 1]: 11 | array[j], array[j - 1] = array[j - 1], array[j] 12 | -------------------------------------------------------------------------------- /closest_points.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from math import ceil, sqrt 4 | from heap import MaxHeap 5 | 6 | 7 | def x_sort(S): 8 | X = MaxHeap(S) 9 | X.heapsort() 10 | return X 11 | 12 | 13 | def y_sort(S): 14 | Y = [] 15 | for p in S: 16 | Y.append((p[1], p[0])) 17 | YY = MaxHeap(Y) 18 | YY.heapsort() 19 | Y = [] 20 | for i in range(len(YY)): 21 | Y.append((YY[i][1], YY[i][0])) 22 | return Y 23 | 24 | 25 | def distance(p1, p2): 26 | return sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) 27 | 28 | 29 | def brute_force(P): 30 | P = list(P) 31 | d = float("Inf") 32 | for i in range(len(P)): 33 | for j in range(i + 1, len(P)): 34 | d = min(d, distance(P[i], P[j])) 35 | return d 36 | 37 | 38 | def closest_points(S): 39 | X = x_sort(S) 40 | Y = y_sort(S) 41 | return closest_points_aux(S, X, Y) 42 | 43 | 44 | def closest_points_aux(P, X, Y): 45 | length = len(P) 46 | half = int(ceil(length / 2)) 47 | if length <= 3: 48 | return brute_force(P) 49 | XL = X[:half] 50 | XR = X[half:] 51 | PL = set(XL) 52 | PR = set(XR) 53 | l = X[half - 1][0] 54 | YL = [] 55 | YR = [] 56 | for i in range(len(Y)): 57 | if Y[i] in PL: 58 | YL.append(Y[i]) 59 | else: 60 | YR.append(Y[i]) 61 | dl = closest_points_aux(PL, XL, YL) 62 | dr = closest_points_aux(PR, XR, YR) 63 | d1 = min(dl, dr) 64 | YY = [] 65 | for i in range(len(Y)): 66 | if abs(Y[i][0] - l) < d1: 67 | YY.append(Y[i]) 68 | d2 = float("Inf") 69 | for i in range(len(YY)): 70 | for j in range(1, 10): 71 | if i + j < len(YY): 72 | d2 = min(distance(YY[i], YY[i + j]), d2) 73 | return min(d1, d2) 74 | -------------------------------------------------------------------------------- /closest_points_l1_distance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from math import ceil, sqrt 4 | from heap import MaxHeap 5 | 6 | 7 | def x_sort(S): 8 | X = MaxHeap(S) 9 | X.heapsort() 10 | return X 11 | 12 | 13 | def y_sort(S): 14 | Y = [] 15 | for p in S: 16 | Y.append((p[1], p[0])) 17 | YY = MaxHeap(Y) 18 | YY.heapsort() 19 | Y = [] 20 | for i in range(len(YY)): 21 | Y.append((YY[i][1], YY[i][0])) 22 | return Y 23 | 24 | 25 | def distance(p1, p2): 26 | return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]) 27 | 28 | 29 | def brute_force(P): 30 | P = list(P) 31 | d = float("Inf") 32 | for i in range(len(P)): 33 | for j in range(i + 1, len(P)): 34 | d = min(d, distance(P[i], P[j])) 35 | return d 36 | 37 | 38 | def closest_points(S): 39 | X = x_sort(S) 40 | Y = y_sort(S) 41 | return closest_points_aux(S, X, Y) 42 | 43 | 44 | def closest_points_aux(P, X, Y): 45 | length = len(P) 46 | half = int(ceil(length / 2)) 47 | if length <= 3: 48 | return brute_force(P) 49 | XL = X[:half] 50 | XR = X[half:] 51 | PL = set(XL) 52 | PR = set(XR) 53 | l = X[half - 1][0] 54 | YL = [] 55 | YR = [] 56 | for i in range(len(Y)): 57 | if Y[i] in PL: 58 | YL.append(Y[i]) 59 | else: 60 | YR.append(Y[i]) 61 | dl = closest_points_aux(PL, XL, YL) 62 | dr = closest_points_aux(PR, XR, YR) 63 | d1 = min(dl, dr) 64 | YY = [] 65 | for i in range(len(Y)): 66 | if abs(Y[i][0] - l) < d1: 67 | YY.append(Y[i]) 68 | d2 = float("Inf") 69 | for i in range(len(YY)): 70 | for j in range(1, 10): 71 | if i + j < len(YY): 72 | d2 = min(distance(YY[i], YY[i + j]), d2) 73 | return min(d1, d2) 74 | -------------------------------------------------------------------------------- /closest_points_l_infinite_distance.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from math import ceil, sqrt 4 | from heap import MaxHeap 5 | 6 | 7 | def x_sort(S): 8 | X = MaxHeap(S) 9 | X.heapsort() 10 | return X 11 | 12 | 13 | def y_sort(S): 14 | Y = [] 15 | for p in S: 16 | Y.append((p[1], p[0])) 17 | YY = MaxHeap(Y) 18 | YY.heapsort() 19 | Y = [] 20 | for i in range(len(YY)): 21 | Y.append((YY[i][1], YY[i][0])) 22 | return Y 23 | 24 | 25 | def distance(p1, p2): 26 | return max(abs(p1[0] - p2[0]), abs(p1[1] - p2[1])) 27 | 28 | 29 | def brute_force(P): 30 | P = list(P) 31 | d = float("Inf") 32 | for i in range(len(P)): 33 | for j in range(i + 1, len(P)): 34 | d = min(d, distance(P[i], P[j])) 35 | return d 36 | 37 | 38 | def closest_points(S): 39 | X = x_sort(S) 40 | Y = y_sort(S) 41 | return closest_points_aux(S, X, Y) 42 | 43 | 44 | def closest_points_aux(P, X, Y): 45 | length = len(P) 46 | half = int(ceil(length / 2)) 47 | if length <= 3: 48 | return brute_force(P) 49 | XL = X[:half] 50 | XR = X[half:] 51 | PL = set(XL) 52 | PR = set(XR) 53 | l = X[half - 1][0] 54 | YL = [] 55 | YR = [] 56 | for i in range(len(Y)): 57 | if Y[i] in PL: 58 | YL.append(Y[i]) 59 | else: 60 | YR.append(Y[i]) 61 | dl = closest_points_aux(PL, XL, YL) 62 | dr = closest_points_aux(PR, XR, YR) 63 | d1 = min(dl, dr) 64 | YY = [] 65 | for i in range(len(Y)): 66 | if abs(Y[i][0] - l) < d1: 67 | YY.append(Y[i]) 68 | d2 = float("Inf") 69 | for i in range(len(YY)): 70 | for j in range(1, 7): 71 | if i + j < len(YY): 72 | d2 = min(distance(YY[i], YY[i + j]), d2) 73 | return min(d1, d2) 74 | -------------------------------------------------------------------------------- /common-matrix-multiply-Strassen.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python2.7 2 | 3 | # AUTHOR: WangQiang 4 | # CREATE DATE: 20140803 5 | # LAST UPDATE DATE: 20140803 6 | # EMAIL: cntqrxj@gmail.com 7 | 8 | from numpy import * 9 | from square_matrix_multiply_Strassen import square_matrix_multiply 10 | 11 | 12 | def common_matrix_multiply(A, B): 13 | if A.shape[1] != B.shape[0]: 14 | print("The width of matrix A not equal the height of matrix B.\nHence no matrix multiplication allowed") 15 | return 16 | shape = A.shape[0], B.shape[1] 17 | # shape = A.shape 18 | length = shape[0] 19 | half = length / 2 20 | A_width = A.shape[1] 21 | B_width = B.shape[1] 22 | A_height = A.shape[0] 23 | B_height = B.shape[0] 24 | half_A_width = A_width / 2 25 | half_A_height = A_height / 2 26 | half_B_width = B_width / 2 27 | half_B_height = B_height / 2 28 | 29 | C = zeros(shape, dtype=int64) 30 | if A_height == 1 or B_width == 1: 31 | C = dot(A, B) 32 | # if length == 1: 33 | # C[0, 0] = A[0, 0] * B[0, 0] 34 | # return C 35 | 36 | S1 = zeros((half, half), dtype=int64) 37 | S2 = zeros((half, half), dtype=int64) 38 | S3 = zeros((half, half), dtype=int64) 39 | S4 = zeros((half, half), dtype=int64) 40 | S5 = zeros((half, half), dtype=int64) 41 | S6 = zeros((half, half), dtype=int64) 42 | S7 = zeros((half, half), dtype=int64) 43 | S8 = zeros((half, half), dtype=int64) 44 | S9 = zeros((half, half), dtype=int64) 45 | S10 = zeros((half, half), dtype=int64) 46 | 47 | P1 = zeros((half, half), dtype=int64) 48 | P2 = zeros((half, half), dtype=int64) 49 | P3 = zeros((half, half), dtype=int64) 50 | P4 = zeros((half, half), dtype=int64) 51 | P5 = zeros((half, half), dtype=int64) 52 | P6 = zeros((half, half), dtype=int64) 53 | P7 = zeros((half, half), dtype=int64) 54 | 55 | S1 = B[0:half, half:length] - B[half:length, half:length] 56 | S2 = A[0:half, 0:half] + A[0:half, half:length] 57 | S3 = A[half:length, 0:half] + A[half:length, half:length] 58 | S4 = B[half:length, 0:half] - B[0:half, 0:half] 59 | S5 = A[0:half, 0:half] + A[half:length, half:length] 60 | S6 = B[0:half, 0:half] + B[half:length, half:length] 61 | S7 = A[0:half, half:length] - A[half:length, half:length] 62 | S8 = B[half:length, 0:half] + B[half:length, half:length] 63 | S9 = A[0:half, 0:half] - A[half:length, 0:half] 64 | S10 = B[0:half, 0:half] + B[0:half, half:length] 65 | 66 | P1 = square_matrix_multiply(A[0:half, 0:half], S1) 67 | P2 = square_matrix_multiply(S2, B[half:length, half:length]) 68 | P3 = square_matrix_multiply(S3, B[0:half, 0:half]) 69 | P4 = square_matrix_multiply(A[half:length, half:length], S4) 70 | P5 = square_matrix_multiply(S5, S6) 71 | P6 = square_matrix_multiply(S7, S8) 72 | P7 = square_matrix_multiply(S9, S10) 73 | 74 | C[0:half, 0:half] = P5 + P4 - P2 + P6 75 | C[0:half, half:length] = P1 + P2 76 | C[half:length, 0:half] = P3 + P4 77 | C[half:length, half:length] = P5 + P1 - P3 - P7 78 | 79 | return C 80 | 81 | 82 | # A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) 83 | # B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) 84 | # A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 85 | # B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 86 | A = array([[1, 3], [7, 5]]) 87 | B = array([[6, 8], [4, 2]]) 88 | # A = array([[1, 2, 3], [4, 5, 6]]) 89 | # B = array([[1, 2], [4, 5]]) 90 | print(square_matrix_multiply(A, B)) 91 | # print( dot(A, B)) 92 | -------------------------------------------------------------------------------- /common-matrix-multiply-recursive.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python2.7 2 | 3 | from numpy import * 4 | 5 | 6 | def common_matrix_multiply(A, B): 7 | if A.shape[1] != B.shape[0]: 8 | print("The width of matrix A not equal the height of matrix B.\nHence no matrix multiplication allowed") 9 | return 10 | shape = (A.shape[0], B.shape[1]) 11 | C = zeros(shape, dtype=int64) 12 | A_width = A.shape[1] 13 | B_width = B.shape[1] 14 | A_height = A.shape[0] 15 | B_height = B.shape[0] 16 | half_A_width = A_width / 2 17 | half_A_height = A_height / 2 18 | half_B_width = B_width / 2 19 | half_B_height = B_height / 2 20 | if A_height == 1 or B_width == 1: 21 | C = dot(A, B) 22 | # else if 23 | else: 24 | C[0:half_A_height, 0:half_B_width] = common_matrix_multiply(A[0:half_A_height, 0:half_A_width], 25 | B[0:half_B_height, 26 | 0:half_B_width]) + common_matrix_multiply( 27 | A[0:half_A_height, half_A_width:A_width], B[half_B_height:B_height, 0:half_B_width]) 28 | C[0:half_A_height, half_B_width:B_width] = common_matrix_multiply(A[0:half_A_height, 0:half_A_width], 29 | B[0:half_B_height, 30 | half_B_width:B_width]) + common_matrix_multiply( 31 | A[0:half_A_height, half_A_width:A_width], B[half_B_height:B_height, half_B_width:B_width]) 32 | C[half_A_height:A_height, 0:half_B_width] = common_matrix_multiply(A[half_A_height:A_height, 0:half_A_width], 33 | B[0:half_B_height, 34 | 0:half_B_width]) + common_matrix_multiply( 35 | A[half_A_height:A_height, half_A_width:A_width], B[half_B_height:B_height, 0:half_B_width]) 36 | C[half_A_height:A_height, half_B_width:B_width] = common_matrix_multiply( 37 | A[half_A_height:A_height, 0:half_A_width], 38 | B[0:half_B_height, half_B_width:B_width]) + common_matrix_multiply( 39 | A[half_A_height:A_height, half_A_width:A_width], B[half_B_height:B_height, half_B_width:B_width]) 40 | return C 41 | 42 | 43 | A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) 44 | B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) 45 | # A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 46 | # B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 47 | # A = array([[1, 2, 3], [4, 5, 6]]) 48 | # B = array([[1, 2], [4, 5]]) 49 | print(common_matrix_multiply(A, B)) 50 | # print( dot(A, B)) 51 | -------------------------------------------------------------------------------- /comparable.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def comparable(a, b, x): 4 | """ 5 | Given two segments a and b that are comparable at x, determine whether a is above b or not. Assume that neither segment is vertical 6 | """ 7 | 8 | p1 = a[0] 9 | p2 = a[1] 10 | p3 = b[0] 11 | p4 = b[1] 12 | x4 = p4[0] 13 | x3 = p3[0] 14 | v1 = (p2[0] - p1[0], p2[1] - p1[1]) 15 | v2 = ( 16 | (x4 - x3) * (p2[0] - p4[0]) + (x4 - x) * (p4[0] - p3[0]), 17 | (x4 - x3) * (p2[1] - p4[1]) + (x4 - x) * (p4[1] - p3[1])) 18 | result = v1[0] * v2[1] - v2[0] * v1[1] 19 | if result == 0: 20 | print("a intersects b at the vertical line") 21 | elif result > 0: 22 | print("a is above b") 23 | else: 24 | print("b is above a") 25 | -------------------------------------------------------------------------------- /contains.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | def contains(x, n): 4 | """ 5 | CLRS Exercise 16.2-5 6 | An algorithm that, given a set {x1, x2, ... ,xn} of points on the 7 | real line, determines the smallest set of unit-length closed intervals that contains 8 | all of the given points. 9 | :param x: 10 | :param n: 11 | :return: 12 | """ 13 | x.sort() 14 | print(x) 15 | i = 0 16 | a = float("-Inf") 17 | S = set() 18 | while i < n: 19 | if x[i] > a: 20 | S = S.union({(x[i], x[i] + 1)}) 21 | a = x[i] + 1 22 | i = i + 1 23 | print(S) 24 | return S 25 | -------------------------------------------------------------------------------- /counting_sort.py: -------------------------------------------------------------------------------- 1 | def counting_sort(A, B, k): 2 | C = [] 3 | for i in range(k + 1): 4 | C.append(0) 5 | for j in range(len(A)): 6 | C[A[j]] = C[A[j]] + 1 7 | for i in range(1, k + 1): 8 | C[i] = C[i] + C[i - 1] 9 | for j in range(len(A) - 1, -1, -1): 10 | B[C[A[j]] - 1] = A[j] 11 | C[A[j]] = C[A[j]] - 1 12 | -------------------------------------------------------------------------------- /cut_rod.py: -------------------------------------------------------------------------------- 1 | def bottom_up_cut_rod(p, n): 2 | r = [0] * (n + 1) 3 | for j in range(1, n + 1): 4 | q = float("-Inf") 5 | for i in range(1, j + 1): 6 | q = max(q, p[i - 1] + r[j - i]) 7 | r[j] = q 8 | return r[n] 9 | 10 | 11 | def bottom_up_cut_rod_two_subproblem(p, n): 12 | r = [0] * (n + 1) 13 | for i in range(1, n + 1): 14 | r[i] = p[i - 1] 15 | for j in range(1, n + 1): 16 | q = float("-Inf") 17 | for i in range(1, j + 1): 18 | q = max(q, r[i] + r[j - i]) 19 | r[j] = q 20 | return r[n] 21 | 22 | 23 | def memoized_cut_rod(p, n): 24 | r = [float("-Inf")] * n 25 | return memoized_cut_rod_aux(p, n, r) 26 | 27 | 28 | def memoized_cut_rod_aux(p, n, r): 29 | if n == 0: 30 | return 0 31 | if r[n - 1] >= 0: 32 | return r[n - 1] 33 | q = float("-Inf") 34 | for i in range(1, n + 1): 35 | q = max(q, p[i - 1] + memoized_cut_rod_aux(p, n - i, r)) 36 | r[n - 1] = q 37 | return q 38 | 39 | 40 | def extended_bottom_up_cut_rod(p, n): 41 | r = [0] * (n + 1) 42 | s = [0] * (n + 1) 43 | for j in range(1, n + 1): 44 | q = float("-Inf") 45 | for i in range(1, j + 1): 46 | if q < p[i - 1] + r[j - i]: 47 | q = p[i - 1] + r[j - i] 48 | s[j] = i 49 | r[j] = q 50 | return r, s 51 | 52 | 53 | def print_cut_rod_solution(p, n, cut): 54 | r, s = cut(p, n) 55 | while n != 0: 56 | print(s[n]) 57 | n = n - s[n] 58 | 59 | 60 | def bottom_up_cut_rod_with_fixed_cut_cost(p, n, c): 61 | r = [0] * (n + 1) 62 | for j in range(1, n + 1): 63 | q = float("-Inf") 64 | for i in range(1, j): 65 | q = max(q, r[i] + r[j - i] - c) 66 | q = max(q, p[j - 1]) 67 | r[j] = q 68 | return r[n] 69 | 70 | 71 | def extended_memoized_cut_rod(p, n): 72 | r = [float("-Inf")] * n 73 | s = [0] * (n + 1) 74 | extended_memoized_cut_rod_aux(p, n, r, s) 75 | return r, s 76 | 77 | 78 | def extended_memoized_cut_rod_aux(p, n, r, s): 79 | if n == 0: 80 | return 0 81 | if r[n - 1] >= 0: 82 | return r[n - 1] 83 | q = float("-Inf") 84 | for i in range(1, n + 1): 85 | value = p[i - 1] + extended_memoized_cut_rod_aux(p, n - i, r, s) 86 | if q < value: 87 | q = value 88 | s[n] = i 89 | r[n - 1] = q 90 | return q 91 | -------------------------------------------------------------------------------- /depth_tree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # A variant of red black tree that has depth attribute 4 | 5 | from rb_tree import RbNode, RbTree 6 | 7 | 8 | class depth_node(RbNode): 9 | def __init__(self, key, p, left, right, color, depth): 10 | RbNode.__init__(self, key, p, left, right, color) 11 | self.depth = depth 12 | 13 | def update_depth_whole_tree(self, amount): 14 | if self.depth != -1: 15 | self.left.update_depth_whole_tree(amount) 16 | self.depth = self.depth + amount 17 | self.right.update_depth_whole_tree(amount) 18 | 19 | 20 | class depth_tree(RbTree): 21 | nil = depth_node(None, None, None, None, 1, -1) 22 | root = nil 23 | 24 | def __init__(self, values): 25 | if isinstance(values, list): 26 | for i in values: 27 | self.insert(depth_node(i, None, None, None, 0, 0)) 28 | else: 29 | print("Not invalid argument") 30 | 31 | def left_rotate(self, x): 32 | y = x.right 33 | x.right = y.left 34 | if y.left != self.nil: 35 | y.left.p = x 36 | y.p = x.p 37 | if x.p == self.nil: 38 | self.root = y 39 | elif x.p.left == x: 40 | x.p.left = y 41 | else: 42 | x.p.right = y 43 | y.left = x 44 | x.p = y 45 | x.depth = x.depth + 1 46 | y.depth = y.depth - 1 47 | x.left.update_depth_whole_tree(1) 48 | y.right.update_depth_whole_tree(-1) 49 | 50 | def right_rotate(self, y): 51 | x = y.left 52 | y.left = x.right 53 | if x.right != self.nil: 54 | x.right.p = y 55 | x.p = y.p 56 | if y.p == self.nil: 57 | self.root = x 58 | elif y.p.right == y: 59 | y.p.right = x 60 | else: 61 | y.p.left = x 62 | x.right = y 63 | y.p = x 64 | x.depth = x.depth - 1 65 | y.depth = y.depth + 1 66 | x.left.update_depth_whole_tree(-1) 67 | y.right.update_depth_whole_tree(1) 68 | 69 | def insert(self, z): 70 | y = self.nil 71 | x = self.root 72 | depth = 0 73 | while x != self.nil: 74 | depth = depth + 1 75 | y = x 76 | if z.key <= x.key: 77 | x = x.left 78 | else: 79 | x = x.right 80 | z.depth = depth 81 | if y == self.nil: 82 | self.root = z 83 | elif z.key <= y.key: 84 | y.left = z 85 | else: 86 | y.right = z 87 | z.p = y 88 | z.left = self.nil 89 | z.right = self.nil 90 | z.color = 0 # red 91 | self.insert_fixed(z) 92 | 93 | def delete(self, z): 94 | y = z 95 | y_original_color = y.color 96 | if z.left == self.nil: 97 | x = z.right 98 | self.transplant(z, z.right) 99 | elif z.right == self.nil: 100 | x = z.left 101 | self.transplant(z, z.left) 102 | else: 103 | y = z.right.minimum() 104 | y_original_color = y.color 105 | x = y.right 106 | if y.p == z: 107 | x.p = y 108 | else: 109 | self.transplant(y, y.right) 110 | y.right = z.right 111 | y.right.p = y 112 | self.transplant(z, y) 113 | y.left = z.left 114 | y.left.p = y 115 | y.color = z.color 116 | y.depth = z.depth 117 | if x != self.nil: 118 | x.update_depth_whole_tree(-1) 119 | if y_original_color == 1: 120 | self.delete_fixup(x) 121 | -------------------------------------------------------------------------------- /deque.py: -------------------------------------------------------------------------------- 1 | from Queue import Queue, FullException, EmptyException 2 | 3 | 4 | class Deque(Queue): 5 | """ 6 | whereas a Queue allows insertion at one end and deletion at the other end, 7 | a Deque(double-ended Queue) allows insertion and deletion at both ends 8 | """ 9 | 10 | def __init__(self, size): 11 | super().__init__(size) 12 | 13 | def enqueue_tail(self, x): 14 | self.enqueue(x) 15 | 16 | def dequeue_head(self): 17 | return self.dequeue() 18 | 19 | def enqueue_head(self, x): 20 | if self.full(): 21 | raise FullException() 22 | else: 23 | if self.head == 0: 24 | self.head = self.size - 1 25 | else: 26 | self.head = self.head - 1 27 | self.data[self.head] = x 28 | 29 | def dequeue_tail(self): 30 | if self.empty(): 31 | raise EmptyException() 32 | else: 33 | if self.tail == 0: 34 | self.tail = self.size - 1 35 | else: 36 | self.tail = self.tail - 1 37 | 38 | return self.data[self.tail] 39 | -------------------------------------------------------------------------------- /disjoint_sets_forest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | class node: 5 | def __init__(self, key): 6 | self.key = key 7 | # key.index = self 8 | self.p = self 9 | self.rank = 0 10 | self.child = [] 11 | 12 | def union(self, y): 13 | self.find_set().link(y.find_set()) 14 | 15 | def link(self, y): 16 | x = self 17 | if x.rank > y.rank: 18 | x.child.append(y) 19 | y.p = x 20 | else: 21 | y.child.append(x) 22 | x.p = y 23 | if x.rank == y.rank: 24 | y.rank = y.rank + 1 25 | 26 | def find_set(self): 27 | y = self 28 | x = self 29 | while y != y.p: 30 | y = y.p 31 | while x != x.p: 32 | z = x 33 | x = x.p 34 | z.p = y 35 | # print( y.key) 36 | return y 37 | 38 | def print_set(self): 39 | x = self 40 | while x != x.p: 41 | x = x.p 42 | x.print_set_aux() 43 | 44 | def print_set_aux(self): 45 | print(self.key) 46 | if len(self.child) == 0: 47 | return 48 | for child in self.child: 49 | child.print_set_aux() 50 | -------------------------------------------------------------------------------- /disjoint_sets_linked_list.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | class node: 4 | def __init__(self, key): 5 | self.key = key 6 | self.set = None 7 | self.next = None 8 | 9 | def find_set(self): 10 | return self.set.head 11 | 12 | def union(self, y): 13 | if self.set.length < y.set.length: 14 | x = y 15 | y = self 16 | else: 17 | x = self 18 | xs = x.set 19 | ys = y.set 20 | xs.tail.next = ys.head 21 | element = ys.head 22 | for i in range(1, ys.length + 1): 23 | element.set = xs 24 | element = element.next 25 | xs.tail = ys.tail 26 | xs.length = xs.length + ys.length 27 | return x 28 | 29 | 30 | class header: 31 | def __init__(self, element): 32 | self.length = 1 33 | self.head = element 34 | element.set = self 35 | self.tail = self.head 36 | 37 | 38 | class node_notail(node): 39 | def union(self, y): 40 | if self.set.length < y.set.length: 41 | x = y 42 | y = self 43 | else: 44 | x = self 45 | xs = x.set 46 | ys = y.set 47 | element = ys.head 48 | for i in range(1, ys.length + 1): 49 | element.set = xs 50 | tail = element 51 | element = element.next 52 | tail.next = xs.head 53 | xs.head = ys.head 54 | xs.length = xs.length + ys.length 55 | return y 56 | 57 | 58 | class header_notail: 59 | def __init__(self, element): 60 | self.length = 1 61 | self.head = element 62 | element.set = self 63 | -------------------------------------------------------------------------------- /dynamic_array.py: -------------------------------------------------------------------------------- 1 | class DynamicArray: 2 | def __init__(self, capacity): 3 | assert capacity > 0 4 | self._capacity = capacity 5 | self._size = 0 6 | self._data = [None] * capacity 7 | 8 | def add(self, element): 9 | if self._size == self._capacity: 10 | temp = self._data 11 | self._data = [None] * (self._capacity * 2) 12 | self._data[:self._capacity] = temp[:] 13 | self._capacity *= 2 14 | self._data[self._size] = element 15 | self._size += 1 16 | 17 | def size(self): 18 | return self._size 19 | 20 | def get(self, index): 21 | return self._data[index] 22 | -------------------------------------------------------------------------------- /eight_queen.py: -------------------------------------------------------------------------------- 1 | N = 8 2 | counter = 0 3 | 4 | 5 | def print_solution(chess_board): 6 | for row in range(N): 7 | for col in range(N): 8 | if chess_board[row] != col: 9 | print('-', end=' ') 10 | else: 11 | print('X', end=' ') 12 | print('\n') 13 | print('\n') 14 | 15 | 16 | def isplaceok(chess_board, row, col): 17 | return not any( 18 | (chess_board[i] == col) or (chess_board[i] - col == row - i) or (chess_board[i] - col == i - row) for i in 19 | range(row)) 20 | 21 | 22 | def add_queen(chess_board, row): 23 | global counter 24 | if row >= N: 25 | print_solution(chess_board) 26 | counter += 1 27 | else: 28 | for col in range(N): 29 | if isplaceok(chess_board, row, col): 30 | chess_board[row] = col 31 | add_queen(chess_board, row + 1) 32 | 33 | 34 | if __name__ == "__main__": 35 | chess_board = [-1] * N 36 | add_queen(chess_board, 0) 37 | print(counter) 38 | -------------------------------------------------------------------------------- /euclid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | 5 | def euclid(a, b): 6 | if b == 0: 7 | return a 8 | else: 9 | return euclid(b, a % b) 10 | 11 | 12 | def extended_euclid(a, b): 13 | if b == 0: 14 | return a, 1, 0 15 | else: 16 | d, x, y = extended_euclid(b, a % b) 17 | return d, y, x - (a / b) * y 18 | -------------------------------------------------------------------------------- /extended_bottom_up_cut_rod.py: -------------------------------------------------------------------------------- 1 | def extended_bottom_up_cut_rod(p, n): 2 | r = [0] * (n + 1) 3 | s = [0] * (n + 1) 4 | for j in range(1, n + 1): 5 | q = float("-Inf") 6 | for i in range(1, j + 1): 7 | if q < p[i - 1] + r[j - i]: 8 | q = p[i - 1] + r[j - i] 9 | s[j] = i 10 | r[j] = q 11 | return r, s 12 | 13 | 14 | def print_cut_rod_solution(p, n): 15 | r, s = extended_bottom_up_cut_rod(p, n) 16 | while n > 0: 17 | print(s[n]) 18 | n = n - s[n] 19 | -------------------------------------------------------------------------------- /fft.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import math 4 | 5 | 6 | def recursive_fft(a): 7 | n = len(a) 8 | if n == 1: 9 | return a 10 | wn = complex(math.cos(2 * math.pi / n), math.sin(2 * math.pi / n)) 11 | w = 1.0 12 | a0 = [a[i] for i in range(0, n, 2)] 13 | a1 = [a[i] for i in range(1, n, 2)] 14 | y0 = recursive_fft(a0) 15 | y1 = recursive_fft(a1) 16 | y = [0.0] * n 17 | for k in range(n // 2): 18 | y[k] = y0[k] + w * y1[k] 19 | y[k + n // 2] = y0[k] - w * y1[k] 20 | w = w * wn 21 | return y 22 | 23 | 24 | def recursive_inverse_fft(y): 25 | n = len(y) 26 | result = recursive_inverse_fft_aux(y) 27 | return [result[i] / n for i in range(n)] 28 | 29 | 30 | def recursive_inverse_fft_aux(y): 31 | n = len(y) 32 | if n == 1: 33 | return y 34 | wn = 1.0 / complex(math.cos(2 * math.pi / n), math.sin(2 * math.pi / n)) 35 | w = 1.0 36 | y0 = [y[i] for i in range(0, n, 2)] 37 | y1 = [y[i] for i in range(1, n, 2)] 38 | a0 = recursive_inverse_fft_aux(y0) 39 | a1 = recursive_inverse_fft_aux(y1) 40 | a = [0.0] * n 41 | for k in range(n // 2): 42 | a[k] = (a0[k] + w * a1[k]) 43 | a[k + n // 2] = (a0[k] - w * a1[k]) 44 | w = w * wn 45 | return a 46 | -------------------------------------------------------------------------------- /gcd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | def gcd(m: int, n: int): 6 | """ 7 | compute the greatest common divisor of m and n; 8 | :param m: 9 | :param n: 10 | :return: 11 | """ 12 | while n > 0: 13 | rem = m % n 14 | m = n 15 | n = rem 16 | return m 17 | -------------------------------------------------------------------------------- /hamiltonian_path.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def hamiltonian_path(G, u, v): 5 | """ 6 | An algorithm to the hamiltonian-path problem on directed acyclic graphs 7 | """ 8 | we = dict() 9 | for i in G.edges: 10 | we[i] = -1 11 | 12 | def w(x, y): 13 | return we[(x, y)] 14 | 15 | G.dag_shortest_paths(w, u) 16 | return abs(v.d) == len(G.vertices) - 1 17 | -------------------------------------------------------------------------------- /hash.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def hash_insert(T, k, h): 5 | i = 0 6 | while i < len(T): 7 | j = h(k, i) 8 | if T[j] is None: 9 | T[j] = k 10 | return j 11 | else: 12 | i = i + 1 13 | 14 | 15 | def linear_probe(k, i): 16 | return (aux(k) + i) % len(T) 17 | 18 | 19 | def quad_probe(k, i): 20 | return (aux(k) + i + 3 * i * i) % len(T) 21 | 22 | 23 | def aux(k): 24 | return k 25 | 26 | 27 | def double_hashing(k, i): 28 | return (k + i * (1 + k % (len(T) - 1))) % len(T) 29 | 30 | 31 | T = [None] * 11 32 | print("length of T is ", len(T)) 33 | for i in 10, 22, 31, 4, 15, 28, 17, 88, 59: 34 | hash_insert(T, i, double_hashing) 35 | 36 | print(T) 37 | -------------------------------------------------------------------------------- /heap.py: -------------------------------------------------------------------------------- 1 | class MaxHeap(list): 2 | def __init__(self, data): 3 | super().__init__(data) 4 | self.length = len(self) 5 | self.heap_size = self.length 6 | self.build_max_heap() 7 | 8 | @staticmethod 9 | def left(i): 10 | return 2 * i + 1 11 | 12 | @staticmethod 13 | def right(i): 14 | return 2 * i + 2 15 | 16 | @staticmethod 17 | def parent(i): 18 | return (i - 1) // 2 19 | 20 | def max_heapify(self, i): 21 | left = self.left(i) 22 | right = self.right(i) 23 | if left < self.heap_size and self[left] > self[i]: 24 | largest = left 25 | else: 26 | largest = i 27 | if right < self.heap_size and self[right] > self[largest]: 28 | largest = right 29 | if largest != i: 30 | self[i], self[largest] = self[largest], self[i] 31 | self.max_heapify(largest) 32 | 33 | def build_max_heap(self): 34 | self.heap_size = self.length 35 | for i in range(self.length // 2 - 1, -1, -1): 36 | self.max_heapify(i) 37 | 38 | def heapsort(self): 39 | self.build_max_heap() 40 | for i in range(self.length - 1, 0, -1): 41 | self[0], self[i] = self[i], self[0] 42 | self.heap_size = self.heap_size - 1 43 | self.max_heapify(0) 44 | 45 | 46 | class MinHeap(list): 47 | def __init__(self, data): 48 | super().__init__(data) 49 | self.length = len(self) 50 | self.heap_size = self.length 51 | self.build_min_heap() 52 | 53 | def __contains__(self, y): 54 | return y in self[:self.heap_size] 55 | 56 | @staticmethod 57 | def left(i): 58 | return 2 * i + 1 59 | 60 | @staticmethod 61 | def right(i): 62 | return 2 * i + 2 63 | 64 | @staticmethod 65 | def parent(i): 66 | return (i - 1) // 2 67 | 68 | def min_heapify(self, i): 69 | l = self.left(i) 70 | r = self.right(i) 71 | if (l <= (self.heap_size - 1)) and (self[l] < self[i]): 72 | smallest = l 73 | else: 74 | smallest = i 75 | if (r <= (self.heap_size - 1)) and (self[r] < self[smallest]): 76 | smallest = r 77 | if smallest != i: 78 | self[i], self[smallest] = self[smallest], self[i] 79 | self.min_heapify(smallest) 80 | 81 | def build_min_heap(self): 82 | self.heap_size = self.length 83 | for i in range(self.length // 2 - 1, -1, -1): 84 | self.min_heapify(i) 85 | -------------------------------------------------------------------------------- /insertion_sort.py: -------------------------------------------------------------------------------- 1 | from binary_search import bisect_right 2 | 3 | 4 | def insert_with_linear_search(array, left_index, right_index): 5 | """ 6 | Use linear search to find a position in already sorted array[left_index...right_index-1] to insert array[right_index] into, 7 | making array[left_index...right_index] a sorted array. 8 | :param array: 9 | :param left_index: 10 | :param right_index: right_index > 0 11 | :return: 12 | """ 13 | key = array[right_index] 14 | i = right_index - 1 15 | while i >= left_index and key < array[i]: 16 | array[i + 1] = array[i] 17 | i = i - 1 18 | array[i + 1] = key 19 | 20 | 21 | def insert_with_binary_search(array, left_index, right_index): 22 | """ 23 | Use binary search to find a position in already sorted array[left_index...right_index-1] to insert array[right_index] into, 24 | making array[left_index...right_index] a sorted array. 25 | :param array: 26 | :param left_index: 27 | :param right_index: right_index > 0 28 | :return: 29 | """ 30 | x = array[right_index] 31 | index = bisect_right(array, x, left_index, right_index) 32 | array[index + 1: right_index + 1] = array[index: right_index] 33 | array[index] = x 34 | 35 | 36 | def insertion_sort(array, left=0, right=None, insert_method=insert_with_linear_search): 37 | """ 38 | inplace sort O(n ^ 2) sort 39 | :param array: 40 | :param left: 41 | :param right: 42 | :param insert_method: 43 | :return: 44 | """ 45 | if right is None: 46 | right = len(array) - 1 47 | for j in range(left, right + 1): 48 | insert_method(array, 0, j) 49 | 50 | 51 | def _insertion_sort_recursive(array, length, insert_method): 52 | if length > 1: 53 | _insertion_sort_recursive(array, length - 1, insert_method) 54 | insert_method(array, 0, length - 1) 55 | 56 | 57 | def insertion_sort_recursive(array, insert_method=insert_with_linear_search): 58 | """ 59 | recursive version of insertion sort 60 | :param array: 61 | :param insert_method: 62 | :return: 63 | """ 64 | _insertion_sort_recursive(array, len(array), insert_method) 65 | -------------------------------------------------------------------------------- /interpolation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import synthetic_division as di 4 | 5 | 6 | def roots_interpolation(roots, n): 7 | A = [0] * (n + 1) 8 | if n == 1: 9 | A[0] = -1 * roots[n - 1] 10 | A[1] = 1 11 | return A 12 | else: 13 | B = roots_interpolation(roots, n - 1) 14 | x = roots[n - 1] 15 | A[n] = B[n - 1] 16 | for i in range(n - 1, 0, -1): 17 | A[i] = B[i - 1] - x * B[i] 18 | A[0] = -1 * x * B[0] 19 | return A 20 | 21 | 22 | def Lagrange_interpolation(X, Y, n): 23 | R = roots_interpolation(X, n) 24 | # print( "length of R is {}".format(len(R))) 25 | A = [0] * n 26 | for k in range(n): 27 | q, re = di.synthetic_division(R, n + 1, X[k]) 28 | # print( q) 29 | # print( "length of q is {}".format(len(q))) 30 | m = 1.0 31 | for j in range(n): 32 | if j != k: 33 | m = m * (X[k] - X[j]) 34 | # print( "m = {}".format(m)) 35 | m = Y[k] / m 36 | # print( "m = {}".format(m)) 37 | for j in range(n): 38 | A[j] = A[j] + q[j] * m 39 | return A 40 | -------------------------------------------------------------------------------- /interval_graph_coloring.py: -------------------------------------------------------------------------------- 1 | def interval_graph_coloring(graph): 2 | """ 3 | The input graph is represented as an adjacency matrix since all we need is edge information about the graph 4 | """ 5 | m = graph.shape[0] 6 | color = [1] * m 7 | number = 1 8 | for i in range(m): 9 | for j in range(m): 10 | if graph[i, j] == 1 and color[i] == color[j]: 11 | color[j] = color[i] + 1 12 | if color[j] > number: 13 | number = color[j] 14 | return color,number 15 | -------------------------------------------------------------------------------- /inversion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | def inversion_with_insertion_sort(array): 6 | """ 7 | Count number of inversions of an array using insertion sort 8 | 9 | Let A[1...n] be an array of n numbers. If i < j and A[i] > A[j] , 10 | then the pair (i, j) is called an inversion_with_insertion_sort of A 11 | :param array: 12 | :return: 13 | """ 14 | array = array[:] 15 | return _inversion_with_insertion_sort(array) 16 | 17 | 18 | def _inversion_with_insertion_sort(array): 19 | """ 20 | :param array: 21 | :return: 22 | """ 23 | inverse = 0 24 | for j in range(1, len(array)): 25 | key = array[j] 26 | i = j - 1 27 | while i >= 0 and key < array[i]: 28 | inverse += 1 29 | array[i + 1] = array[i] 30 | i = i - 1 31 | array[i + 1] = key 32 | return inverse 33 | 34 | 35 | def inversion_with_merge_sort(array): 36 | """ 37 | Count number of inversions of an array using merge sort 38 | 39 | Let A[1...n] be an array of n numbers. If i < j and A[i] > A[j] , 40 | then the pair (i, j) is called an inversion_with_insertion_sort of A 41 | :param array: 42 | :return: 43 | """ 44 | array = array[:] 45 | return _inversion_with_merge_sort(array, 0, len(array) - 1) 46 | 47 | 48 | def _inversion_with_merge_sort(array, left, right): 49 | if left < right: 50 | mid = (left + right) // 2 51 | left_inverse = _inversion_with_merge_sort(array, left, mid) 52 | right_inverse = _inversion_with_merge_sort(array, mid + 1, right) 53 | inter_inverse = _merge(array, left, mid, right) 54 | return left_inverse + right_inverse + inter_inverse 55 | else: 56 | return 0 57 | 58 | 59 | def _merge(array, left, mid, right): 60 | """ 61 | 62 | :param array: 63 | :param left: 64 | :param mid: 65 | :param right: 66 | :return: 67 | """ 68 | left_part = array[left: mid + 1] 69 | left_part.append(float("Inf")) 70 | right_part = array[mid + 1: right + 1] 71 | right_part.append(float("Inf")) 72 | i = 0 73 | j = 0 74 | inverse = 0 75 | for k in range(left, right + 1): 76 | if left_part[i] <= right_part[j]: 77 | array[k] = left_part[i] 78 | i = i + 1 79 | else: 80 | array[k] = right_part[j] 81 | j = j + 1 82 | inverse += (mid - left + 1 - i) 83 | return inverse 84 | 85 | -------------------------------------------------------------------------------- /inversion_tree.py: -------------------------------------------------------------------------------- 1 | from rank_tree import rank_tree, rank_node 2 | 3 | 4 | def inversion(A): 5 | inversion = 0 6 | i = 0 7 | T = rank_tree([]) 8 | if isinstance(A, list): 9 | for key in A: 10 | i = i + 1 11 | x = rank_node(key, None, None, None, 0, 1) 12 | T.insert(x) 13 | # print( 'x.key = {}, x.rank = {}'.format(x.key, x.rank)) 14 | inversion = inversion + i - x.rank 15 | return inversion 16 | else: 17 | print("Not invalid argument") 18 | -------------------------------------------------------------------------------- /k_way_merge.py: -------------------------------------------------------------------------------- 1 | def merge(list1, list2): 2 | length1 = len(list1) 3 | length2 = len(list2) 4 | n = length1 + length2 5 | i = 0 6 | j = 0 7 | k = 0 8 | result = [0] * n 9 | while i < length1 and j < length2: 10 | if list1[i] <= list2[j]: 11 | result[k] = list1[i] 12 | i += 1 13 | else: 14 | result[k] = list2[j] 15 | j += 1 16 | k += 1 17 | if i == length1: 18 | while j < length2: 19 | result[k] = list2[j] 20 | k += 1 21 | j += 1 22 | elif j == length2: 23 | while i < length1: 24 | result[k] = list1[i] 25 | k += 1 26 | i += 1 27 | return result 28 | 29 | 30 | def k_way_merge(lists): 31 | """ 32 | Merge k sorted lists and return it as one sorted list 33 | :param lists: 34 | :return: 35 | """ 36 | length = len(lists) 37 | if length == 1: 38 | return lists[0] 39 | elif length == 2: 40 | return merge(lists[0], lists[1]) 41 | else: 42 | list1 = k_way_merge(lists[:length // 2]) 43 | list2 = k_way_merge(lists[length // 2:]) 44 | return merge(list1, list2) 45 | -------------------------------------------------------------------------------- /kleene_star.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from numpy import zeros 4 | 5 | 6 | def kleene_star(x, L, A): 7 | length = len(x) 8 | m = zeros((length, length)) 9 | for l in range(1, length + 1): 10 | for i in range(1, length - l + 2): 11 | j = i + l - 1 12 | for k in range(i, j): 13 | if m[i - 1, k - 1] == 1 and m[k, j - 1] == 1: 14 | m[i - 1, j - 1] = 1 15 | if m[i - 1, j - 1] != 1: 16 | m[i - 1, j - 1] = A(x[i - 1:j], L) 17 | return m[0, length - 1] != 0 18 | -------------------------------------------------------------------------------- /knapsack_0_1.py: -------------------------------------------------------------------------------- 1 | from numpy import zeros 2 | 3 | 4 | def knapsack_0_1(W, w, v): 5 | n = len(w) 6 | return knapsack_0_1_aux(W, w, v, 1, n) 7 | 8 | 9 | def knapsack_0_1_aux(W, w, v, m, n): 10 | """ 11 | m: the first item 12 | n: the last item 13 | W: total weight 14 | w: the list of weights of items 15 | v: the list of values of items 16 | """ 17 | 18 | # if m > n, then we have scanned all the items 19 | if m > n: 20 | return 0 21 | # if W <= 0, then we can't take any more items 22 | if W <= 0: 23 | return 0 24 | # We have two choices: take item m or not take item m 25 | if W < w[m - 1]: 26 | return knapsack_0_1_aux(W, w, v, m + 1, n) 27 | else: 28 | return max(knapsack_0_1_aux(W - w[m - 1], w, v, m + 1, n) + v[m - 1], knapsack_0_1_aux(W, w, v, m + 1, n)) 29 | 30 | 31 | def knapsack_0_1_memoized(W, w, v): 32 | m = 1 33 | n = len(w) 34 | value = zeros((W + 1, n + 1)) 35 | solution = zeros((W + 1, n + 1)) 36 | for i in range(W + 1): 37 | for j in range(n + 1): 38 | value[i, j] = float("-Inf") 39 | knapsack_0_1_memoized_aux(W, w, v, m, n, value, solution) 40 | return value, solution 41 | 42 | 43 | def knapsack_0_1_memoized_aux(W, w, v, m, n, value, solution): 44 | if m > n: 45 | return 0 46 | if value[W, m] >= 0: 47 | return value[W, m] 48 | if W < w[m - 1]: 49 | value[W, m] = knapsack_0_1_memoized_aux(W, w, v, m + 1, n, value, solution) 50 | solution[W, m] = 0 51 | else: 52 | s = knapsack_0_1_memoized_aux(W - w[m - 1], w, v, m + 1, n, value, solution) + v[m - 1] 53 | t = knapsack_0_1_memoized_aux(W, w, v, m + 1, n, value, solution) 54 | if s > t: 55 | solution[W, m] = 1 56 | value[W, m] = max(s, t) 57 | return value[W, m] 58 | 59 | 60 | def print_knapsack_solution(solution, w): 61 | W = solution.shape[0] - 1 62 | n = solution.shape[1] - 1 63 | i = 1 64 | while W != 0 and i <= n: 65 | if solution[W, i] == 1: 66 | print(i) 67 | W = W - w[i - 1] 68 | i = i + 1 69 | -------------------------------------------------------------------------------- /kth-Quantiles.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import math 4 | import random 5 | from randomized_select import randomized_select 6 | from quicksort import randomized_quicksort 7 | 8 | 9 | def kth_quantiles(A, B, k, p, r): 10 | if k > 0: 11 | n = r - p + 1 12 | location = math.floor(k / 2) * math.ceil(n / k) 13 | B[math.floor(k / 2)] = randomized_select(A, p, r, location) 14 | kth_quantiles(A, B, p, math.floor(k / 2) - 1, location - 1) 15 | kth_quantiles(A, B, math.floor(k / 2), location + 1, r) 16 | 17 | 18 | def median_of_two_arrays(X, x_start, x_end, Y, y_start, y_end, size): 19 | print(X[x_start:x_end + 1], '\t', Y[y_start:y_end + 1], '\t', size) 20 | if size == 1: 21 | return min(X[x_start], Y[y_start]) 22 | xc = X[x_start + int(math.floor(size / 2)) - 1] 23 | yc = Y[y_start + int(math.ceil(size / 2)) - 1] 24 | print(xc, yc) 25 | if xc == yc: 26 | return xc 27 | elif xc < yc: 28 | return median_of_two_arrays(X, x_start + int(math.floor(size / 2)), x_end, Y, y_start, y_end, 29 | math.ceil(size / 2)) 30 | else: 31 | return median_of_two_arrays(X, x_start, x_end, Y, y_start + int(math.ceil(size / 2)), y_end, 32 | math.floor(size / 2)) 33 | 34 | 35 | if __name__ == '__main__': 36 | A = [random.randint(1, 100) for i in range(15)] 37 | print(A) 38 | randomized_quicksort(A, 0, 14) 39 | print(A) 40 | B = [random.randint(1, 100) for i in range(15)] 41 | print(B) 42 | randomized_quicksort(B, 0, 14) 43 | print(B) 44 | print(median_of_two_arrays(A, 0, 14, B, 0, 14, 3.0)) 45 | # randomized_select(A, 0, 14, 7) 46 | # print( A) 47 | # for i in range(1, 16): 48 | # randomized_select(A, 0, 14, i) 49 | # print( i, '\t', A) 50 | # print( randomized_select(A, 0, 14, i)) 51 | -------------------------------------------------------------------------------- /linkedlist.py: -------------------------------------------------------------------------------- 1 | from typing import Any, Optional 2 | 3 | 4 | class LinkedListNode: 5 | def __init__(self, key: Any): 6 | self.key: Any = key 7 | self.prev: Optional[LinkedListNode] = None 8 | self.next: Optional[LinkedListNode] = None 9 | 10 | 11 | class LinkedList: 12 | def __init__(self, key=None): 13 | self.head: Optional[LinkedListNode] = None 14 | self.size: int = 0 15 | self.key = key 16 | 17 | def empty(self) -> bool: 18 | return self.size == 0 19 | 20 | def search(self, key: Any) -> Optional[LinkedListNode]: 21 | node = self.head 22 | while node and node.key != key: 23 | node = node.next 24 | return node 25 | 26 | def insert(self, node: LinkedListNode) -> None: 27 | self.size = self.size + 1 28 | node.next = self.head 29 | if self.head: 30 | self.head.prev = node 31 | self.head = node 32 | node.prev = None 33 | 34 | def delete(self, node: LinkedListNode) -> None: 35 | self.size = self.size - 1 36 | if node.prev: 37 | node.prev.next = node.next 38 | else: 39 | self.head = node.next 40 | if node.next: 41 | node.next.prev = node.prev 42 | 43 | def extract(self, node: LinkedListNode) -> LinkedListNode: 44 | self.delete(node) 45 | return node 46 | -------------------------------------------------------------------------------- /longest_common_subsequence.py: -------------------------------------------------------------------------------- 1 | from numpy import zeros 2 | 3 | 4 | def lcs_length(X, Y): 5 | m = len(X) 6 | n = len(Y) 7 | c = zeros((m + 1, n + 1)) 8 | b = zeros((m + 1, n + 1)) 9 | 10 | for i in range(1, m + 1): 11 | for j in range(1, n + 1): 12 | if X[i - 1] == Y[j - 1]: 13 | c[i, j] = c[i - 1, j - 1] + 1 14 | b[i, j] = 0 15 | elif c[i - 1, j] >= c[i, j - 1]: 16 | c[i, j] = c[i - 1, j] 17 | b[i, j] = 1 18 | else: 19 | c[i, j] = c[i, j - 1] 20 | b[i, j] = 2 21 | return c, b 22 | 23 | 24 | def lcs_length_one_row(X, Y): 25 | m = len(X) 26 | n = len(Y) 27 | c = [0] * (n + 1) 28 | 29 | for i in range(1, m + 1): 30 | a = 0 31 | for j in range(1, n + 1): 32 | if X[i - 1] == Y[j - 1]: 33 | value = a + 1 34 | elif c[j] >= c[j - 1]: 35 | value = c[j] 36 | else: 37 | value = c[j - 1] 38 | a = c[j] 39 | c[j] = value 40 | return c[n] 41 | 42 | 43 | def print_lcs(b, X, i, j): 44 | if i == 0 or j == 0: 45 | return 46 | if b[i, j] == 0: 47 | print_lcs(b, X, i - 1, j - 1) 48 | print(X[i - 1], ) 49 | elif b[i, j] == 1: 50 | print_lcs(b, X, i - 1, j) 51 | else: 52 | print_lcs(b, X, i, j - 1) 53 | -------------------------------------------------------------------------------- /longest_monotonically_increasing_subsequence.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from longest_common_subsequence import lcs_length_one_row 5 | 6 | def longest_monotonically_increasing_subsequence(A): 7 | C = sorted(set(A)) 8 | return lcs_length_one_row(A, C) 9 | -------------------------------------------------------------------------------- /longest_palindrome_subsequence.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from longest_common_subsequence import lcs_length, print_lcs 5 | 6 | 7 | def longest_palindrome_subsequence(s): 8 | # c, b = lcs_length(s, s[::-1]) 9 | # print(_lcs(b, s, len(s), len(s))) 10 | n = len(s) 11 | c = [[0] * n for _ in range(n)] 12 | for i in range(n): 13 | c[i][i] = 1 14 | for i in range(n - 1): 15 | if s[i] == s[i + 1]: 16 | c[i][i + 1] = 2 17 | else: 18 | c[i][i + 1] = 1 19 | for length in range(3, n + 1): 20 | for i in range(n - length + 1): 21 | j = i + length - 1 22 | if s[i] == s[j]: 23 | print(i, j, c[i + 1][j - 1]) 24 | c[i][j] = 2 + c[i + 1][j - 1] 25 | else: 26 | c[i][j] = max(c[i][j - 1], c[i + 1][j]) 27 | return c 28 | 29 | 30 | def print_lps(c, s): 31 | start = 0 32 | end = len(s) - 1 33 | l = [] 34 | idx = [] 35 | index = 0 36 | while start < end: 37 | if s[start] == s[end]: 38 | l.insert(index, s[end]) 39 | l.insert(index, s[start]) 40 | idx.insert(index, end) 41 | idx.insert(index, start) 42 | index += 1 43 | start += 1 44 | end -= 1 45 | elif c[start + 1][end] >= c[start][end - 1]: 46 | start += 1 47 | else: 48 | end -= 1 49 | if start == end: 50 | l.insert(index, s[start]) 51 | idx.insert(index, start) 52 | return ''.join(l), idx 53 | -------------------------------------------------------------------------------- /lowest_common_multiple.py: -------------------------------------------------------------------------------- 1 | from gcd import gcd 2 | 3 | 4 | def lcm(num1: int, num2: int): 5 | return num1 * num2 // gcd(num1, num2) 6 | -------------------------------------------------------------------------------- /matrix_chain_order.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from numpy import zeros 4 | 5 | 6 | def bottom_up_matrix_chain_order(p): 7 | n = len(p) - 1 8 | m = zeros((n + 1, n + 1)) 9 | s = zeros((n + 1, n + 1)) 10 | for l in range(2, n + 1): 11 | for i in range(1, n - l + 2): 12 | j = i + l - 1 13 | m[i, j] = float("Inf") 14 | for k in range(i, j): 15 | q = m[i, k] + m[k + 1, j] + p[i - 1] * p[k] * p[j] 16 | if q < m[i, j]: 17 | m[i, j] = q 18 | s[i, j] = k 19 | return m, s 20 | 21 | 22 | def memoized_matrix_chain_order(p): 23 | n = len(p) - 1 24 | m = zeros((n + 1, n + 1)) 25 | for i in range(1, n + 1): 26 | for j in range(1, n + 1): 27 | m[i, j] = float("Inf") 28 | return lookup_chain(m, p, 1, n) 29 | 30 | 31 | def lookup_chain(m, p, i, j): 32 | if m[i, j] < float("Inf"): 33 | return m[i, j] 34 | if i == j: 35 | m[i, j] = 0 36 | else: 37 | for k in range(i, j): 38 | q = lookup_chain(m, p, i, k) + lookup_chain(m, p, 39 | k + 1, j) + p[i - 1] * p[k] * p[j] 40 | if q < m[i, j]: 41 | m[i, j] = q 42 | return m[i, j] 43 | 44 | 45 | def print_optimal_parens(s, i, j): 46 | if i == j: 47 | print("A{}".format(int(i)), ) 48 | else: 49 | print("(", ) 50 | print_optimal_parens(s, i, s[i, j]) 51 | print_optimal_parens(s, s[i, j] + 1, j) 52 | print(")", ) 53 | 54 | 55 | # An incorrect greedy approach for matrix chain order problem 56 | def greedy_matrix_chain_order(p): 57 | n = len(p) - 1 58 | return greedy_matrix_chain_order_aux(p, 1, n) 59 | 60 | 61 | def greedy_matrix_chain_order_aux(p, i, j): 62 | if i == j: 63 | return 0 64 | q = float("Inf") 65 | for k in range(i, j): 66 | value = p[i - 1] * p[k] * p[j] 67 | if q > value: 68 | q = value 69 | pos = k 70 | return greedy_matrix_chain_order_aux(p, i, pos) + greedy_matrix_chain_order_aux(p, pos + 1, j) + q 71 | -------------------------------------------------------------------------------- /matrix_pow.c: -------------------------------------------------------------------------------- 1 | // AUTHOR: WangQiang 2 | // DATE: 20140524 3 | // LAST UPDATE DATE: 20140525 4 | // EMAIL: cntqrxj@gmail.com 5 | 6 | #include 7 | #include 8 | 9 | void matrix_exp(int *A, int *B, int n, int pow) { 10 | int length = n * n; 11 | int *C; 12 | int i; 13 | void square_matrix_multiply(int *, int *, int *, int); 14 | 15 | if (pow == 1) { 16 | for (i = 0; i < length; i++) 17 | B[i] = A[i]; 18 | return; 19 | } 20 | C = calloc(length, sizeof(int)); 21 | matrix_exp(A, C, n, pow / 2); 22 | square_matrix_multiply(C, C, B, n); 23 | if (pow % 2) { 24 | for (i = 0; i < length; i++) 25 | C[i] = B[i]; 26 | square_matrix_multiply(C, A, B, n); 27 | } 28 | free(C); 29 | return; 30 | } 31 | -------------------------------------------------------------------------------- /max_subsequence_sum.c: -------------------------------------------------------------------------------- 1 | /* max_subsequence_sum: compute max subsequence sum of a[n] 2 | on-lines algorithms; O(n) */ 3 | int max_subsequence_sum(int a[], unsigned n) { 4 | int this_sum, max_sum, best_i, best_j, i, j; 5 | 6 | i = this_sum = max_sum = 0; best_i = best_j = -1; 7 | for (j = 0; j < n; j++) { 8 | this_sum += a[j]; 9 | if (this_sum > max_sum) 10 | { /* update max_sum, best_i, best_j */ 11 | max_sum = this_sum; 12 | best_i = i; 13 | best_j = j; 14 | } else if (this_sum < 0) { 15 | i = j + 1; 16 | this_sum = 0; 17 | } 18 | } 19 | return max_sum; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /maximum-subarray-brute-force.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct value { 5 | int low; 6 | int high; 7 | int sum; 8 | }; 9 | 10 | //A brute-force solution to find maximum subarray: just try every possible pair 11 | struct value FIND_MAXIMUM_SUBARRAY(int A[], int low, int high) { 12 | int i, j; 13 | int left, right; 14 | int sum; 15 | int max_sum = INT_MIN; 16 | struct value max; 17 | 18 | for (i = low; i <= high; i++) { 19 | sum = 0; 20 | for (j = i; j <= high; j++) { 21 | sum = sum + A[j]; 22 | if (sum >= max_sum) { 23 | left = i; 24 | right = j; 25 | max_sum = sum; 26 | } 27 | } 28 | } 29 | max.low = left; 30 | max.high = right; 31 | max.sum = max_sum; 32 | return max; 33 | } 34 | 35 | int main() { 36 | int a[17] = { 13, -3, -25, 20, -3, -16, -23, 18, 20, -7, 12, -5, -22, 15, -4, 7, 0}; 37 | struct value max; 38 | int b[17] = {100,113,110,85,105,102,86,63,81,101,94,106,101,79,94,90,97}; 39 | int c[16]; 40 | int d[6] = {-6, -100, -8, -2, -5, -1}; 41 | int i; 42 | 43 | for (i = 0; i < 16; i++) 44 | c[i] = b[i + 1] - b[i]; 45 | max = FIND_MAXIMUM_SUBARRAY(a, 0, 16); 46 | printf("%d, %d, %d, %d, %d\n", max.low, max.high, max.sum, a[max.low], a[max.high]); 47 | max = FIND_MAXIMUM_SUBARRAY(c, 0, 15); 48 | printf("%d, %d, %d, %d, %d, %d, %d\n", max.low, max.high, max.sum, a[max.low], a[max.high], b[max.low], b[max.high + 1]); 49 | max = FIND_MAXIMUM_SUBARRAY(d, 0, 5); 50 | printf("%d, %d, %d\n", max.low, max.high, max.sum); 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /maximum-subarray-inline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct value { 5 | int low; 6 | int high; 7 | int sum; 8 | }; 9 | 10 | //An inline solution to find maximum subarray 11 | //FIND_MAXIMUM_SUBARRAY(A, low, high) 12 | // sum = A[low] 13 | // left = low 14 | // right = high 15 | // max-endpoint-sum = NEGATIVE INFINITE 16 | // for i = low to high 17 | // if max-endpoint-sum >= 0 18 | // max-endpoint-sum = max-endpoint-sum + A[i] 19 | // max-endpoint-high = i 20 | // else 21 | // max-endpoint-sum = A[i] 22 | // max-endpoint-low = max-endpoint-high = i 23 | // if max-endpoint-sum > sum 24 | // sum = max-endpoint-sum 25 | // left = max-endpoint-low 26 | // right = max-endpoint-high 27 | // return(left, right, sum) 28 | struct value FIND_MAXIMUM_SUBARRAY(int A[], int low, int high) { 29 | struct value max_endpoint, max; 30 | int i; 31 | 32 | max.sum = A[low]; 33 | max.low = low; 34 | max.high = high; 35 | max_endpoint.sum = INT_MIN; 36 | 37 | for (i = low; i <= high; i++) { 38 | if (max_endpoint.sum >= 0) { 39 | max_endpoint.sum = max_endpoint.sum + A[i]; 40 | max_endpoint.high = i; 41 | } 42 | else { 43 | max_endpoint.sum = A[i]; 44 | max_endpoint.low = max_endpoint.high = i; 45 | } 46 | if (max_endpoint.sum > max.sum) { 47 | max.sum = max_endpoint.sum; 48 | max.low = max_endpoint.low; 49 | max.high = max_endpoint.high; 50 | } 51 | } 52 | return max; 53 | } 54 | 55 | int main() { 56 | int a[17] = { 13, -3, -25, -20, -3, -16, 23, 18, 20, -7, 12, -5, 22, -15, -4, 7, 0}; 57 | int b[9] = {-2, 1, -3, 4, -1, 2, 1, -5, 4}; 58 | struct value max; 59 | 60 | max = FIND_MAXIMUM_SUBARRAY(a, 0, 16); 61 | printf("%d, %d, %d, %d, %d\n", max.low, max.high, max.sum, a[max.low], a[max.high]); 62 | max = FIND_MAXIMUM_SUBARRAY(b, 0, 8); 63 | printf("%d, %d, %d, %d, %d\n", max.low, max.high, max.sum, b[max.low], b[max.high]); 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /maximum-subarray-recursive.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct value { 5 | int low; 6 | int high; 7 | int sum; 8 | }; 9 | 10 | //FIND-MAX-CROSSING-SUBARRAY(A, low, mid, high) 11 | // left-sum = NEGATIVE INFINITE 12 | // sum = 0 13 | // for i = mid downto low 14 | // sum = sum + A[i] 15 | // if sum > left-sum 16 | // left-sum = sum 17 | // max-left = i 18 | // right-sum = NEGATIVE INFINITE 19 | // sum = 0 20 | // for j = mid + 1 to high 21 | // sum = sum + A[j] 22 | // if sum > right-sum 23 | // right-sum = sum 24 | // max-right = j 25 | // return(max-left,max-right,left-sum + right-sum) 26 | 27 | 28 | struct value FIND_MAX_CROSSING_SUBARRAY(int A[], int low, int mid, int high) { 29 | int left_sum = INT_MIN; 30 | int right_sum = INT_MIN; 31 | int max_left, max_right; 32 | int sum = 0; 33 | int i; 34 | struct value cross; 35 | for(i = mid; i >= low; i--) { 36 | sum = sum + A[i]; 37 | if (sum >= left_sum) 38 | { left_sum = sum; 39 | max_left = i; 40 | } 41 | } 42 | sum = 0; 43 | for (i = mid + 1; i <= high; i++) { 44 | sum = sum + A[i]; 45 | if (sum >= right_sum) { 46 | right_sum = sum; 47 | max_right = i; 48 | } 49 | } 50 | cross.low = max_left; 51 | cross.high = max_right; 52 | cross.sum = left_sum + right_sum; 53 | return cross; 54 | // printf("%d, %d, %d\n", max_left, max_right, left_sum + right_sum); 55 | } 56 | 57 | //FIND-MAXIMUM-SUBARRAY(A, low, high) 58 | // if high == low 59 | // return(low, high, A[low]) 60 | // else mid = floor of (low + high) / 2 61 | // (left-low, left-high, left-sum) = 62 | // FIND-MAXIMUM-SUBARRAY(A, low, mid) 63 | // (right-low, right-high, right-sum) = 64 | // FIND-MAXIMUM-SUBARRAY(A, mid + 1, high) 65 | // (cross-low, cross-high, cross-sum) = 66 | // FIND-MAXIMUM-SUBARRAY(A, low, mid, high) 67 | // if left-sum >= right-sum and left-sum >= cross-sum 68 | // return(left-low, left-high, left-sum) 69 | // elseif right-sum >= left-sum and right-sum >= cross-sum 70 | // return(right-low, right-high, right-sum) 71 | // else return(cross-low, cross-high, cross-sum) 72 | 73 | struct value FIND_MAXIMUM_SUBARRAY(int A[], int low, int high) { 74 | struct value left, right, cross; 75 | int mid; 76 | 77 | if (low == high) { 78 | left.low = low; 79 | left.high = high; 80 | left.sum = A[low]; 81 | return left; 82 | } 83 | else { 84 | mid = (low + high) / 2; 85 | left = FIND_MAXIMUM_SUBARRAY(A, low, mid); 86 | cross = FIND_MAX_CROSSING_SUBARRAY(A, low, mid, high); 87 | right = FIND_MAXIMUM_SUBARRAY(A, mid + 1, high); 88 | if (left.sum >= right.sum && left.sum >= cross.sum) 89 | return left; 90 | else if (right.sum >= left.sum && right.sum >= cross.sum) 91 | return right; 92 | else 93 | return cross; 94 | } 95 | } 96 | int main() { 97 | //int a[17] = { 13, -3, -25, -20, -3, -16, 23, 18, 20, -7, 12, -5, 22, -15, -4, 7, 0}; 98 | struct value max; 99 | int b[6] = {-6, -2, -2, -2, -10, -1}; 100 | // 101 | //max = FIND_MAXIMUM_SUBARRAY(a, 0, 16); 102 | max = FIND_MAXIMUM_SUBARRAY(b, 0, 5); 103 | //printf("%d, %d, %d, %d, %d\n", max.low, max.high, max.sum, a[max.low], a[max.high]); 104 | printf("%d, %d, %d\n", max.low, max.high, max.sum); 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /memoized_cut_rod.py: -------------------------------------------------------------------------------- 1 | def memoized_cut_rod(p, n): 2 | r = [float("-Inf")] * (n + 1) 3 | return memoized_cut_rod_aux(p, n, r) 4 | 5 | 6 | def memoized_cut_rod_aux(p, n, r): 7 | if r[n] >= 0: 8 | return r[n] 9 | if n == 0: 10 | q = 0 11 | else: 12 | q = float("-Inf") 13 | for i in range(1, n + 1): 14 | q = max(q, p[i - 1] + memoized_cut_rod_aux(p, n - i, r)) 15 | r[n] = q 16 | return q 17 | -------------------------------------------------------------------------------- /merge.py: -------------------------------------------------------------------------------- 1 | def merge_with_sentinel(array, left, mid, right): 2 | """ 3 | merge procedure with sentinels 4 | 5 | merge array[left...mid] and array[mid + 1...right] 6 | :param array: 7 | :param left: 8 | :param mid: 9 | :param right: 10 | :return: 11 | """ 12 | left_part = array[left: mid + 1] 13 | left_part.append(float("Inf")) 14 | right_part = array[mid + 1: right + 1] 15 | right_part.append(float("Inf")) 16 | i = 0 17 | j = 0 18 | for k in range(left, right + 1): 19 | if left_part[i] <= right_part[j]: 20 | array[k] = left_part[i] 21 | i += 1 22 | else: 23 | array[k] = right_part[j] 24 | j += 1 25 | 26 | 27 | def merge_without_sentinel(array, left, mid, right): 28 | """ 29 | merge procedure without sentinels 30 | 31 | A merge procedure without sentinels that stops once either array `left_part` or `right_part` has had all its elements 32 | copied back to `array` and then copying the remainder of another array back into `array` 33 | :param array: 34 | :param left: 35 | :param mid: 36 | :param right: 37 | :return: 38 | """ 39 | left_part = array[left: mid + 1] 40 | right_part = array[mid + 1: right + 1] 41 | i = 0 42 | j = 0 43 | k = left 44 | while i < len(left_part) and j < len(right_part): 45 | if left_part[i] <= right_part[j]: 46 | array[k] = left_part[i] 47 | k += 1 48 | i += 1 49 | else: 50 | array[k] = right_part[j] 51 | k += 1 52 | j += 1 53 | if i < len(left_part): 54 | array[k: right + 1] = left_part[i:] 55 | else: 56 | array[k: right + 1] = right_part[j:] -------------------------------------------------------------------------------- /merge_sort.py: -------------------------------------------------------------------------------- 1 | from insertion_sort import insertion_sort 2 | from merge import merge_with_sentinel 3 | 4 | 5 | def merge_sort(array, merge_method=merge_with_sentinel): 6 | """ 7 | inplace O(nlgn) sort 8 | :param array: 9 | :param merge_method: 10 | :return: 11 | """ 12 | _merge_sort(array, 0, len(array) - 1, merge_method) 13 | 14 | 15 | def _merge_sort(array, left, right, merge_method): 16 | if left < right: 17 | mid = (left + right) // 2 18 | _merge_sort(array, left, mid, merge_method) 19 | _merge_sort(array, mid + 1, right, merge_method) 20 | merge_method(array, left, mid, right) 21 | 22 | 23 | def merge_ins_sort_bottom_to_top(array, partition: int = 2): 24 | """ 25 | Although merge sort runs faster than insertion sort asymptotically, 26 | the constant factors in insertion sort can make it faster in practice for small problem sizes on many machines. 27 | Thus, it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when 28 | subproblems become sufficiently small. Consider a modification to merge sort in which n/k sublists of length k are 29 | sorted using insertion sort and then merged using the standard merging mechanism, where k is a value to be determined. 30 | 31 | bottom to top version with number of sublists specified 32 | :param array: 33 | :param partition: number of sublists 34 | :return: 35 | """ 36 | assert partition > 0 37 | n = len(array) 38 | sublist_length = n // partition 39 | sublist_number = partition 40 | for i in range(sublist_number): 41 | left = sublist_length * i 42 | right = min(sublist_length * (i + 1) - 1, n - 1) 43 | insertion_sort(array, left, right) 44 | while sublist_number > 1: 45 | for i in range(0, sublist_number - 1, 2): 46 | merge_with_sentinel(array, sublist_length * i, sublist_length * (i + 1) - 1, 47 | min(sublist_length * (i + 2) - 1, n - 1)) 48 | sublist_length *= 2 49 | sublist_number = sublist_number // 2 50 | 51 | 52 | def merge_ins_sort_top_to_bottom(array, sublist_length): 53 | """ 54 | Although merge sort runs faster than insertion sort asymptotically, the constant factors in insertion sort can make 55 | it faster in practice for small problem sizes on many machines. 56 | Thus, it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when 57 | subproblems become sufficiently small. Consider a modification to merge sort in which n/k sublists of length k are 58 | sorted using insertion sort and then merged using the standard merging mechanism, where k is a value to be determined. 59 | 60 | top to bottom version with sublist length specified 61 | :param array: 62 | :param sublist_length: 63 | :return: 64 | """ 65 | n = len(array) 66 | assert 0 < sublist_length < n 67 | _merge_ins_sort_top_to_bottom(array, 0, n - 1, sublist_length) 68 | 69 | 70 | def _merge_ins_sort_top_to_bottom(array, start, end, sublist_length): 71 | """ 72 | 73 | :param array: 74 | :param start: 75 | :param end: 76 | :param sublist_length: 77 | :return: 78 | """ 79 | length = end - start + 1 80 | if length > sublist_length: 81 | mid = (start + end) // 2 82 | _merge_ins_sort_top_to_bottom(array, start, mid, sublist_length) 83 | _merge_ins_sort_top_to_bottom(array, mid + 1, end, sublist_length) 84 | merge_with_sentinel(array, start, mid, end) 85 | else: 86 | insertion_sort(array, start, end) 87 | -------------------------------------------------------------------------------- /min_heap_with_linked_list.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | 4 | class MinHeap(list): 5 | def __init__(self, data): 6 | list.__init__(self, data) 7 | self.length = len(data) 8 | self.heap_size = self.length 9 | self.build_min_heap() 10 | 11 | def __contains__(self, y): 12 | return y in self[0:self.heap_size] 13 | 14 | def left(self, i): 15 | return 2 * i + 1 16 | 17 | def right(self, i): 18 | return 2 * i + 2 19 | 20 | def parent(self, i): 21 | return (i - 1) / 2 22 | 23 | def min_heapify(self, i): 24 | l = self.left(i) 25 | r = self.right(i) 26 | if (l <= (self.heap_size - 1)) and (self[l].key < self[i].key): 27 | smallest = l 28 | else: 29 | smallest = i 30 | if (r <= (self.heap_size - 1)) and (self[r].key < self[smallest].key): 31 | smallest = r 32 | if smallest != i: 33 | self[i], self[smallest] = self[smallest], self[i] 34 | self.min_heapify(smallest) 35 | 36 | def build_min_heap(self): 37 | self.heap_size = self.length 38 | for i in range(self.length // 2 - 1, -1, -1): 39 | self.min_heapify(i) 40 | 41 | 42 | class MinPriorityQueue(MinHeap): 43 | def heap_minimum(self): 44 | return self[0].head 45 | 46 | def heap_extract_min(self): 47 | if self.heap_size < 1: 48 | sys.exit("heap underflow") 49 | minimum = self[0].extract(self[0].head) 50 | if self[0].empty(): 51 | self[0] = self[self.heap_size - 1] 52 | self.heap_size = self.heap_size - 1 53 | self.min_heapify(0) 54 | return minimum 55 | 56 | def heap_decrease_key(self, i, element, key): 57 | if key > self[i]: 58 | sys.exit("new key is larger than current key") 59 | self[i] = key 60 | while i > 0 and self[self.parent(i)] > self[i]: 61 | tmp = self[self.parent(i)] 62 | self[self.parent(i)] = self[i] 63 | self[i] = tmp 64 | i = self.parent(i) 65 | 66 | def min_heap_insert(self, key): 67 | if self.heap_size >= self.length: 68 | sys.exit("heap overflow") 69 | self.heap_size = self.heap_size + 1 70 | self[self.heap_size - 1] = float("Inf") 71 | self.heap_decrease_key(self.heap_size - 1, key) 72 | -------------------------------------------------------------------------------- /min_heap_with_linked_list_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from min_heap_with_linked_list import min_heap, min_priority_queue 3 | from linkedlist import LinkedList, LinkedListNode 4 | 5 | 6 | class TestHeap(unittest.TestCase): 7 | def test_min_heapify(self): 8 | L1 = LinkedList(1) 9 | L2 = LinkedList(2) 10 | L2.insert(LinkedListNode(2)) 11 | L2.insert(LinkedListNode(2)) 12 | L3 = LinkedList(3) 13 | L3.insert(LinkedListNode(3)) 14 | L3.insert(LinkedListNode(3)) 15 | L4 = LinkedList(4) 16 | L4.insert(LinkedListNode(4)) 17 | L5 = LinkedList(5) 18 | L3.insert(LinkedListNode(5)) 19 | L3.insert(LinkedListNode(5)) 20 | L3.insert(LinkedListNode(5)) 21 | h = min_heap([L5, L1, L2, L3, L4]) 22 | h.min_heapify(0) 23 | self.assertEqual(h, [L1, L3, L2, L5, L4]) 24 | 25 | def test_build_min_heap(self): 26 | L1 = LinkedList(1) 27 | L2 = LinkedList(2) 28 | L2.insert(LinkedListNode(2)) 29 | L2.insert(LinkedListNode(2)) 30 | L3 = LinkedList(3) 31 | L3.insert(LinkedListNode(3)) 32 | L3.insert(LinkedListNode(3)) 33 | L4 = LinkedList(4) 34 | L4.insert(LinkedListNode(4)) 35 | L5 = LinkedList(5) 36 | L3.insert(LinkedListNode(5)) 37 | L3.insert(LinkedListNode(5)) 38 | L3.insert(LinkedListNode(5)) 39 | h = min_heap([L3, L4, L5, L2, L1]) 40 | h.build_min_heap() 41 | self.assertEqual(h, [L1, L2, L5, L3, L4]) 42 | 43 | def test_heap_minimum(self): 44 | L1 = LinkedList(1) 45 | L1.insert(LinkedListNode(1)) 46 | L1.insert(LinkedListNode(1)) 47 | L2 = LinkedList(2) 48 | L2.insert(LinkedListNode(2)) 49 | L2.insert(LinkedListNode(2)) 50 | L3 = LinkedList(3) 51 | L3.insert(LinkedListNode(3)) 52 | L3.insert(LinkedListNode(3)) 53 | L4 = LinkedList(4) 54 | L4.insert(LinkedListNode(4)) 55 | L5 = LinkedList(5) 56 | L3.insert(LinkedListNode(5)) 57 | L3.insert(LinkedListNode(5)) 58 | L3.insert(LinkedListNode(5)) 59 | q = min_priority_queue([L1, L2, L3, L4, L5]) 60 | self.assertEqual(q.heap_minimum().key, 1) 61 | 62 | def test_heap_extract_min(self): 63 | L1 = LinkedList(1) 64 | L1.insert(LinkedListNode(1)) 65 | L1.insert(LinkedListNode(1)) 66 | L2 = LinkedList(2) 67 | L2.insert(LinkedListNode(2)) 68 | L2.insert(LinkedListNode(2)) 69 | L3 = LinkedList(3) 70 | L3.insert(LinkedListNode(3)) 71 | L3.insert(LinkedListNode(3)) 72 | L4 = LinkedList(4) 73 | L4.insert(LinkedListNode(4)) 74 | L5 = LinkedList(5) 75 | L3.insert(LinkedListNode(5)) 76 | L3.insert(LinkedListNode(5)) 77 | L3.insert(LinkedListNode(5)) 78 | q = min_priority_queue([L1, L2, L3, L4, L5]) 79 | self.assertEqual(q.heap_extract_min().key, 1) 80 | self.assertEqual(q, [L1, L2, L3, L4, L5]) 81 | self.assertEqual(q.heap_extract_min().key, 1) 82 | self.assertEqual(q, [L2, L4, L3, L5, L5]) 83 | # def test_heap_decrease_key(self): 84 | # a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 85 | # q = MinPriorityQueue(a) 86 | # q.heap_decrease_key(8, 1) 87 | # self.assertEqual(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) 88 | # def test_heap_insert(self): 89 | # a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 90 | # q = MinPriorityQueue(a) 91 | # q.heap_extract_min() 92 | # q.min_heap_insert(0) 93 | # self.assertEqual(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) 94 | -------------------------------------------------------------------------------- /min_priority_queue_using_rb_tree.py: -------------------------------------------------------------------------------- 1 | from rb_tree import RbTree 2 | import sys 3 | 4 | 5 | class min_priority_queue(RbTree): 6 | def heap_minimum(self): 7 | return self.minimum() 8 | 9 | def heap_extract_min(self): 10 | x = self.minimum() 11 | self.delete(x) 12 | return x 13 | 14 | def heap_decrease_key(self, node, key): 15 | if key > node.key: 16 | sys.exit("new key is larger than current key") 17 | self.delete(node) 18 | node.key = key 19 | self.insert(node) 20 | 21 | def min_heap_insert(self, node): 22 | self.insert(node) 23 | -------------------------------------------------------------------------------- /mod_exp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned long modular_exponentiation(unsigned long a, unsigned long b, unsigned long n) { 4 | unsigned long c = 0; 5 | unsigned long d = 1; 6 | int k = sizeof(unsigned long) * 8 - 1; 7 | unsigned long mask = 1 << k; 8 | unsigned long shift = b; 9 | int i; 10 | for (i = k; i >= 0; i--) { 11 | c = 2 * c; 12 | d = (d * d) % n; 13 | if ((shift & mask) == mask) 14 | { 15 | c = c + 1; 16 | d = (d * a) % n; 17 | } 18 | shift = shift << 1; 19 | } 20 | return d; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /most_reliable_path.py: -------------------------------------------------------------------------------- 1 | from graph import max_priority_queue 2 | 3 | 4 | def most_reliable_path(G, r, s): 5 | """ 6 | We are given a directed graph G = (V, E) on which 7 | each edge (u, v) that belongs to E has an associated 8 | value r(u, v), which is a real number in the range 9 | 0 <= r(u, v) <= 1 that represents the reliability 10 | of a communication channel from vertex u to vertex v. 11 | We interpret r(u, v) as the probability that the channel 12 | from u to v will not fail, and we assume that these 13 | probabilities are independent. 14 | This is an algorithm to find the most reliable 15 | path from the source to other vertices. 16 | 17 | s: the source 18 | r: the function that returns the probability that the 19 | channel from u to v will not fail. 20 | """ 21 | initialize_single_source(G, s) 22 | S = set() 23 | Q = max_priority_queue(G.vertices, 'r') 24 | while Q.heap_size > 0: 25 | u = Q.heap_extract_max() 26 | S = S.union({u}) 27 | for v in G.adj[u]: 28 | if v.r < u.r * r(u, v): 29 | v.r = u.r * r(u, v) 30 | v.p = u 31 | Q.heap_increase_key(v.index, u.r * r(u, v)) 32 | 33 | 34 | def initialize_single_source(G, s): 35 | for v in G.vertices: 36 | v.r = 0 37 | v.p = None 38 | s.r = 1 39 | -------------------------------------------------------------------------------- /optimal_binary_search_tree.py: -------------------------------------------------------------------------------- 1 | from numpy import zeros 2 | 3 | 4 | def optimal_bst(p, q, n): 5 | e = zeros((n + 2, n + 1)) 6 | w = zeros((n + 2, n + 1)) 7 | root = zeros((1 + n, 1 + n)) 8 | for i in range(1, n + 2): 9 | print("i = {}".format(i)) 10 | e[i, i - 1] = q[i - 1] 11 | w[i, i - 1] = q[i - 1] 12 | for l in range(1, n + 1): 13 | for i in range(1, n - l + 2): 14 | j = i + l - 1 15 | e[i, j] = float("Inf") 16 | w[i, j] = w[i, j - 1] + p[j - 1] + q[j] 17 | for r in range(i, j + 1): 18 | t = e[i, r - 1] + e[r + 1, j] + w[i, j] 19 | if t < e[i, j]: 20 | e[i, j] = t 21 | root[i, j] = r 22 | return e, root 23 | 24 | 25 | def construct_optimal_bst(root): 26 | n = root.shape[1] - 1 27 | r = root[1, n] 28 | print("k{} is the root".format(int(r))) 29 | construct_optimal_bst_aux(root, r, 1, r - 1) 30 | construct_optimal_bst_aux(root, r, r + 1, n) 31 | 32 | 33 | def construct_optimal_bst_aux(root, p, i, j): 34 | if j < p: 35 | if i <= j: 36 | r = root[i, j] 37 | print("k{} is the left child of k{}".format(int(r), int(p))) 38 | construct_optimal_bst_aux(root, r, i, r - 1) 39 | construct_optimal_bst_aux(root, r, r + 1, j) 40 | else: 41 | print("d{} is the left child of k{}".format(int(j), int(p))) 42 | if i > p: 43 | if i <= j: 44 | r = root[i, j] 45 | print("k{} is the right child of k{}".format(int(r), int(p))) 46 | construct_optimal_bst_aux(root, r, i, r - 1) 47 | construct_optimal_bst_aux(root, r, r + 1, j) 48 | else: 49 | print("d{} is the right child of k{}".format(int(j), int(p))) 50 | -------------------------------------------------------------------------------- /parallel_fib.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int p_fib(int n) 6 | { 7 | int x, y; 8 | 9 | printf("%d\n", omp_get_nested()); 10 | if (n <= 1) 11 | return n; 12 | else 13 | { 14 | //The values of private data are undefined upon entry to and exit from the specific construct 15 | //So x and y should be declared shared 16 | #pragma omp parallel sections shared(n, x, y) 17 | { 18 | #pragma omp section 19 | x = p_fib(n - 1); 20 | #pragma omp section 21 | y = p_fib(n - 2); 22 | } 23 | return x + y; 24 | } 25 | } 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | printf("%d\n", omp_get_nested()); 30 | omp_set_nested(1); 31 | printf("%d\n", p_fib(atoi(argv[1]))); 32 | return 0; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /parallel_mat_vec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | //Multiply matrix A of size n * n by vector x of length n, return vector y of length n 6 | int *p_mat_vec(int *A, int *x, int n) 7 | { 8 | int *y = (int *) malloc(sizeof(int) * n); 9 | int i, j; 10 | #pragma omp parallel shared(A, x, n) private(i, j) 11 | { 12 | #pragma omp for 13 | for (i = 0; i < n; i++) 14 | y[i] = 0; 15 | #pragma omp for 16 | for (i = 0; i < n; i++) 17 | for (j = 0; j < n; j++) 18 | y[i] = y[i] + A[i * n + j] * x[j]; 19 | } 20 | return y; 21 | } 22 | 23 | int main(int argc, char *argv[]) 24 | { 25 | int * p_mat_vec(int *A, int *x, int n); 26 | int i, j, n; 27 | int *A, *x, *y; 28 | printf("Please give n: "); 29 | scanf("%d",&n); 30 | if ( (A=(int *)malloc(n * n *sizeof(int))) == NULL ) 31 | perror("memory allocation for a"); 32 | if ( (x=(int *)malloc(n*sizeof(int))) == NULL ) 33 | perror("memory allocation for b"); 34 | printf("Initializing matrix A and vector x\n"); 35 | for (j=0; j 2 | #include 3 | #include 4 | #include 5 | 6 | int binary_search(int x, int *T, int p, int r) 7 | { 8 | int low = p; 9 | int high = (p < (r + 1) ? (r + 1) : p); 10 | int mid; 11 | 12 | while (low < high) 13 | { 14 | mid = (low + high) / 2; 15 | if (x <= T[mid]) 16 | high = mid; 17 | else 18 | low = mid + 1; 19 | } 20 | return high; 21 | } 22 | 23 | void swap(int *p1, int *p2) 24 | { 25 | int tmp = *p1; 26 | 27 | *p1 = *p2; 28 | *p2 = tmp; 29 | return; 30 | } 31 | 32 | void parallel_merge(int *T, int p1, int r1, int p2, int r2, int *A, int p3) 33 | { 34 | int q1, q2, q3; 35 | int n1 = r1 - p1 + 1; 36 | int n2 = r2 - p2 + 1; 37 | 38 | if (n1 < n2) 39 | { 40 | swap(&p1, &p2); 41 | swap(&r1, &r2); 42 | swap(&n1, &n2); 43 | } 44 | if (n1 == 0) 45 | return; 46 | else 47 | { 48 | q1 = (p1 + r1) / 2; 49 | q2 = binary_search(T[q1], T, p2, r2); 50 | q3 = p3 + (q1 - p1) + (q2 - p2); 51 | A[q3] = T[q1]; 52 | #pragma omp parallel sections shared(T, p1, q1, p2, q2, A, p3, q3) 53 | { 54 | #pragma omp section 55 | parallel_merge(T, p1, q1 - 1, p2, q2 - 1, A, p3); 56 | #pragma omp section 57 | parallel_merge(T, q1 + 1, r1, q2, r2, A, q3 + 1); 58 | } 59 | return; 60 | } 61 | } 62 | void parallel_merge_sort(int *A, int p, int r, int *B, int s) 63 | { 64 | int n = r - p + 1; 65 | 66 | if (n == 1) 67 | { 68 | B[s] = A[p]; 69 | return; 70 | } 71 | else 72 | { 73 | int *T = (int *) malloc(sizeof(int) * n); 74 | int q1 = (p + r) / 2; 75 | int q2 = q1 - p + 1; 76 | 77 | #pragma omp parallel sections shared(A, p, q1, T, r, q2) 78 | { 79 | #pragma omp section 80 | parallel_merge_sort(A, p, q1, T, 0); 81 | #pragma omp section 82 | parallel_merge_sort(A, q1 + 1, r, T, q2); 83 | } 84 | parallel_merge(T, 0, q2 - 1, q2, n - 1, B, s); 85 | free(T); 86 | return; 87 | } 88 | } 89 | 90 | int main(int argc, char *argv[]) 91 | { 92 | int i; 93 | int n = atoi(argv[1]); 94 | int a[n]; 95 | int b[n]; 96 | 97 | omp_set_nested(1); 98 | srand(time(NULL)); 99 | for (i = 0; i < n; i++) 100 | { 101 | a[i] = rand(); 102 | } 103 | for (i = 0; i < n; i++) 104 | printf("%d\t", a[i]); 105 | printf("\n\n"); 106 | parallel_merge_sort(a, 0, n - 1, b, 0); 107 | for (i = 0; i < n; i++) 108 | printf("%d\t", b[i]); 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /parallel_square_matrix_multiply.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int *parallel_square_matrix_multiply(int *A, int *B, int n) 6 | { 7 | int *C = (int *) malloc(sizeof(int) * n * n); 8 | int i, j, k; 9 | 10 | #pragma omp parallel for shared(A, B, C, n) private(i, j, k) 11 | for (i = 0; i < n; i++) 12 | //If a thread in a team executing a parallel region encounters another parallel con- 13 | //struct, it creates a new team and becomes the master of that new team. 14 | //So the parallel construct is needed, insted of work-sharing region 15 | #pragma omp parallel for shared(i) 16 | for (j = 0; j < n; j++) 17 | { 18 | printf("%d\n", i); 19 | C[i * n + j] = 0; 20 | for (k = 0; k < n; k++) 21 | C[i * n + j] = C[i * n + j] + A[i * n + k] * B[k * n + j]; 22 | } 23 | return C; 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | int i, j, n; 29 | int *A, *B, *C; 30 | printf("Please give n: "); 31 | scanf("%d",&n); 32 | if ( (A=(int *)malloc(n * n *sizeof(int))) == NULL ) 33 | perror("memory allocation for matrix A"); 34 | if ( (B=(int *)malloc(n * n *sizeof(int))) == NULL ) 35 | perror("memory allocation for matrix B"); 36 | printf("Initializing matrix A and matrix B\n"); 37 | for (i=0; i x. The return value is the median of the second part. 18 | So the return value is (left + right) // 2 when all elements in the array A[left .. right] have the same value. Partition in place. 19 | """ 20 | x = array[right] 21 | i = left - 1 22 | k = i 23 | for j in range(left, right): 24 | if array[j] < x: 25 | i = i + 1 26 | array[i], array[j] = array[j], array[i] 27 | k = k + 1 28 | if i != k: 29 | array[j], array[k] = array[k], array[j] 30 | elif array[j] == x: 31 | k = k + 1 32 | array[k], array[j] = array[j], array[k] 33 | array[k + 1], array[right] = array[right], array[k + 1] 34 | return (k + 2 + i) // 2 35 | 36 | 37 | def partition3(array, left, right): 38 | """ 39 | Variant of partition. Requires O(n) extra space, but it is easier to implement. 40 | """ 41 | pivot = array[right] 42 | left_part = [array[i] for i in range(left, right) if array[i] <= pivot] 43 | right_part = [array[i] for i in range(left, right) if array[i] > pivot] 44 | pivot_index = left + len(left_part) 45 | array[left:pivot_index] = left_part[:] 46 | array[pivot_index + 1:right + 1] = right_part[:] 47 | array[pivot_index] = pivot 48 | return pivot_index 49 | 50 | 51 | def randomized_partition(array, left, right): 52 | i = random.randint(left, right) 53 | array[i], array[right] = array[right], array[i] 54 | return partition(array, left, right) 55 | -------------------------------------------------------------------------------- /polar_angle.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from heap import MaxHeap 4 | 5 | 6 | class Vector: 7 | def __init__(self, p2, p1=(0, 0)): 8 | self.x = p2[0] - p1[0] 9 | self.y = p2[1] - p1[0] 10 | 11 | def cross_product(self, v): 12 | return self.x * v.y - v.x * self.y 13 | 14 | def __lt__(self, v): 15 | return self.cross_product(v) > 0 16 | 17 | def __gt__(self, v): 18 | return self.cross_product(v) < 0 19 | 20 | def __eq__(self, v): 21 | return self.cross_product(v) == 0 22 | 23 | def __le__(self, v): 24 | return self.cross_product(v) >= 0 25 | 26 | def __ge__(self, v): 27 | return self.cross_product(v) <= 0 28 | 29 | 30 | def polar_angle(p0, point_list): 31 | """sort a sequence of n points according to 32 | their polar angles with respect to a given origin point p0. 33 | """ 34 | v0 = Vector((p0[0] + 1, p0[1]), p0) # The polar angle of v0 is 0 35 | vector_list = [Vector(p, p0) for p in point_list] 36 | angle_0 = [] # list of vectors whose polar angles are 0 37 | angle_pi = [] # list of vectors whose polar angles are pi 38 | angle_0_pi = [] # list of vectors whose polar angles are larger than 0 and smaller than pi 39 | angle_pi_2pi = [] # list of vectors whose polar angles are larger than pi and smaller than 2pi 40 | for v in vector_list: 41 | if v == v0: 42 | if v.x > 0: 43 | angle_0.append(v) 44 | elif v.x < 0: 45 | angle_pi.append(v) 46 | elif v < v0: 47 | angle_pi_2pi.append(v) 48 | elif v > v0: 49 | angle_0_pi.append(v) 50 | heap_0_pi = MaxHeap(angle_0_pi) 51 | heap_pi_2pi = MaxHeap(angle_pi_2pi) 52 | heap_0_pi.heapsort() 53 | heap_pi_2pi.heapsort() 54 | return [(v.x, v.y) for v in (angle_0 + heap_0_pi + angle_pi + heap_pi_2pi)] 55 | -------------------------------------------------------------------------------- /polygon_area.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from typing import Sequence, Tuple, Union 3 | 4 | Number = Union[int, float] 5 | 6 | 7 | def polygon_area(polygon: Sequence[Tuple[Number, Number]]) -> float: 8 | n = len(polygon) 9 | area = sum((polygon[i][0] + polygon[i + 1][0]) * (polygon[i + 1][1] - polygon[i][1]) for i in range(n - 1)) 10 | area += (polygon[0][0] + polygon[n - 1][0]) * (polygon[0][1] - polygon[n - 1][1]) 11 | return 0.5 * abs(area) 12 | -------------------------------------------------------------------------------- /polynomial_multiply.py: -------------------------------------------------------------------------------- 1 | import math 2 | import fft 3 | 4 | 5 | def polynominal_multiply(a, b, precision=0): 6 | a_len = len(a) 7 | b_len = len(b) 8 | length = int(2 ** (1 + math.ceil(math.log(max(a_len, b_len))))) 9 | print(length) 10 | extend_a = [0] * length 11 | extend_b = [0] * length 12 | for i in range(a_len): 13 | extend_a[i] = a[i] 14 | for i in range(a_len, length): 15 | extend_a[i] = 0 16 | for i in range(b_len): 17 | extend_b[i] = b[i] 18 | for i in range(b_len, length): 19 | extend_b[i] = 0 20 | a_fft = fft.recursive_fft(extend_a) 21 | b_fft = fft.recursive_fft(extend_b) 22 | m_fft = [a_fft[i] * b_fft[i] for i in range(len(a_fft))] 23 | ab = fft.recursive_inverse_fft(m_fft) 24 | return [round(ab[i].real, precision) for i in range(a_len + b_len - 1)] 25 | -------------------------------------------------------------------------------- /pow.py: -------------------------------------------------------------------------------- 1 | def pow1(x, n: int): 2 | """ 3 | compute x ^ n 4 | """ 5 | if n == 0: 6 | return 1 7 | square = x * x 8 | if n % 2: 9 | return pow1(square, n // 2) * x 10 | return pow1(square, n // 2) 11 | 12 | 13 | def pow2(x, n: int): 14 | """ 15 | compute x ^ n 16 | """ 17 | if n == 0: 18 | return 1 19 | tmp = pow2(x, n // 2) 20 | if n % 2: 21 | return tmp * tmp * x 22 | return tmp * tmp 23 | -------------------------------------------------------------------------------- /priority_queue.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from heap import MaxHeap, MinHeap 3 | 4 | 5 | class MaxPriorityQueue(MaxHeap): 6 | def heap_maximum(self): 7 | return self[0] 8 | 9 | def heap_extract_max(self): 10 | if self.heap_size < 1: 11 | sys.exit("heap underflow") 12 | maximum = self[0] 13 | self[0] = self[self.heap_size - 1] 14 | self.heap_size = self.heap_size - 1 15 | self.max_heapify(0) 16 | return maximum 17 | 18 | def heap_increase_key(self, i, key): 19 | if key < self[i]: 20 | sys.exit("new key is smaller than current key") 21 | self[i] = key 22 | while i > 0 and self[self.parent(i)] < self[i]: 23 | self[i], self[self.parent(i)] = self[self.parent(i)], self[i] 24 | i = self.parent(i) 25 | 26 | def max_heap_insert(self, key): 27 | if self.heap_size >= self.length: 28 | sys.exit("heap overflow") 29 | self.heap_size = self.heap_size + 1 30 | self[self.heap_size - 1] = float("-Inf") 31 | self.heap_increase_key(self.heap_size - 1, key) 32 | 33 | def heap_delete(self, i): 34 | self.heap_increase_key(i, float("Inf")) 35 | self[0], self[self.heap_size - 1] = self[self.heap_size - 1], self[0] 36 | self.heap_size = self.heap_size - 1 37 | self.max_heapify(0) 38 | 39 | 40 | class MinPriorityQueue(MinHeap): 41 | def heap_minimum(self): 42 | return self[0] 43 | 44 | def heap_extract_min(self): 45 | if self.heap_size < 1: 46 | sys.exit("heap underflow") 47 | minimum = self[0] 48 | self[0] = self[self.heap_size - 1] 49 | self.heap_size = self.heap_size - 1 50 | self.min_heapify(0) 51 | return minimum 52 | 53 | def heap_decrease_key(self, i, key): 54 | if key > self[i]: 55 | sys.exit("new key is larger than current key") 56 | self[i] = key 57 | while i > 0 and self[self.parent(i)] > self[i]: 58 | self[i], self[self.parent(i)] = self[self.parent(i)], self[i] 59 | i = self.parent(i) 60 | 61 | def min_heap_insert(self, key): 62 | if self.heap_size >= self.length: 63 | sys.exit("heap overflow") 64 | self.heap_size = self.heap_size + 1 65 | self[self.heap_size - 1] = float("Inf") 66 | self.heap_decrease_key(self.heap_size - 1, key) 67 | -------------------------------------------------------------------------------- /quicksort.py: -------------------------------------------------------------------------------- 1 | from partition import partition, randomized_partition 2 | 3 | 4 | def quicksort(array, left, right, partition_method=partition): 5 | if left < right: 6 | index = partition_method(array, left, right) 7 | quicksort(array, left, index - 1) 8 | quicksort(array, index + 1, right) 9 | 10 | 11 | def randomized_quicksort(array, left, right): 12 | if left < right: 13 | index = randomized_partition(array, left, right) 14 | randomized_quicksort(array, left, index - 1) 15 | randomized_quicksort(array, index + 1, right) 16 | -------------------------------------------------------------------------------- /random_array.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def random_arrays(array_num=100, array_size=100, array_lowerbound=0, array_upperbound=10000): 5 | for _ in range(array_num): 6 | yield [random.randint(array_lowerbound, array_upperbound) for _ in range(array_size)] 7 | -------------------------------------------------------------------------------- /randomized_permute.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | 4 | def randomize_in_place(A): 5 | """ 6 | An algorithm to permute the given array in place. 7 | It computes a uniform random permutation. 8 | """ 9 | n = len(A) 10 | for i in range(n): 11 | j = random.randint(i, n - 1) 12 | A[i], A[j] = A[j], A[i] 13 | 14 | # def permute_by_sorting(A): 15 | # n = len(A) 16 | # P = [0] * n 17 | # for i in 18 | -------------------------------------------------------------------------------- /randomized_select.py: -------------------------------------------------------------------------------- 1 | from partition import randomized_partition 2 | 3 | 4 | def randomized_select(A, p, r, i): 5 | if p == r: 6 | return A[p] 7 | q = randomized_partition(A, p, r) 8 | k = q - p + 1 9 | if i == k: 10 | return A[q] 11 | elif i < k: 12 | return randomized_select(A, p, q - 1, i) 13 | else: 14 | return randomized_select(A, q + 1, r, i - k) 15 | -------------------------------------------------------------------------------- /rank_tree.py: -------------------------------------------------------------------------------- 1 | # The variant of os_tree that use rank instead of size 2 | # !/usr/bin/env python 3 | 4 | from rb_tree import RbNode, RbTree 5 | 6 | 7 | class rank_node(RbNode): 8 | def __init__(self, key, p, left, right, color, rank): 9 | RbNode.__init__(self, key, p, left, right, color) 10 | self.rank = rank 11 | 12 | def update_rank_whole_tree(self, amount): 13 | if self.rank != 0: 14 | self.rank = self.rank + amount 15 | self.left.update_rank_whole_tree(amount) 16 | self.right.update_rank_whole_tree(amount) 17 | 18 | def decrease_all_successors(self, amount): 19 | self.rank = self.rank - amount 20 | self.right.update_rank_whole_tree(-1 * amount) 21 | y = self.p 22 | x = self 23 | while y.rank != 0 and y.right == x: 24 | x = y 25 | y = y.p 26 | if y.rank != 0: 27 | y.decrease_all_successors(amount) 28 | 29 | 30 | class rank_tree(RbTree): 31 | nil = rank_node(None, None, None, None, 1, 0) 32 | root = nil 33 | 34 | def __init__(self, values): 35 | if isinstance(values, list): 36 | for i in values: 37 | self.insert(rank_node(i, None, None, None, 0, 1)) 38 | else: 39 | print("Not invalid argument") 40 | 41 | def insert(self, z): 42 | y = self.nil 43 | x = self.root 44 | while x != self.nil: 45 | y = x 46 | if z.key <= x.key: 47 | x.rank = x.rank + 1 48 | x.right.update_rank_whole_tree(1) 49 | x = x.left 50 | else: 51 | x = x.right 52 | if y == self.nil: 53 | self.root = z 54 | z.rank = 1 55 | elif z.key <= y.key: 56 | y.left = z 57 | z.rank = y.rank - 1 58 | else: 59 | y.right = z 60 | z.rank = y.rank + 1 61 | z.p = y 62 | z.left = self.nil 63 | z.right = self.nil 64 | z.color = 0 # red 65 | self.insert_fixed(z) 66 | 67 | def delete(self, z): 68 | z.decrease_all_successors(1) # z is counted as a successor 69 | y = z 70 | y_original_color = y.color 71 | if z.left == self.nil: 72 | x = z.right 73 | self.transplant(z, z.right) 74 | elif z.right == self.nil: 75 | x = z.left 76 | self.transplant(z, z.left) 77 | else: 78 | y = z.right.minimum() 79 | y_original_color = y.color 80 | x = y.right 81 | if y.p == z: 82 | x.p = y 83 | else: 84 | self.transplant(y, y.right) 85 | y.right = z.right 86 | y.right.p = y 87 | self.transplant(z, y) 88 | y.left = z.left 89 | y.left.p = y 90 | y.color = z.color 91 | if y_original_color == 1: 92 | self.delete_fixup(x) 93 | -------------------------------------------------------------------------------- /right_horizontal_ray_intersect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | from segment_intersect import segments_intersect 4 | 5 | 6 | def right_horizontal_ray_intersect(p0, p1, p2): 7 | """An algorithm to determine whether a given right horizontal ray from p0 intersects a line segment p1p2""" 8 | max_x = max(p1[0], p2[0]) 9 | if max_x < p0[0]: 10 | return False 11 | # When max(x1, x2) = x0, if intersecting, the intersection point must be po, then po must be on the line segment p1p2 12 | elif max_x == p0[1]: 13 | if p1[0] == p2[0] and min(p1[1], p2[1]) <= p0[1] and max(p1[1], p2[1]) >= p0[1]: 14 | return True 15 | else: 16 | return equal(p0, p1) or equal(p0, p2) 17 | else: 18 | return segments_intersect(p1, p2, p0, (max_x, p0[1])) 19 | 20 | 21 | def equal(p1, p2): 22 | return p1[0] == p2[0] and p1[1] == p2[1] 23 | -------------------------------------------------------------------------------- /segment_intersect.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def segments_intersect(p1, p2, p3, p4): 5 | d1 = direction(p3, p4, p1) 6 | d2 = direction(p3, p4, p2) 7 | d3 = direction(p1, p2, p3) 8 | d4 = direction(p1, p2, p4) 9 | if ((d1 > 0 > d2) or (d1 < 0 < d2)) and ((d3 > 0 > d4) or (d3 < 0 < d4)): 10 | return True 11 | elif d1 == 0 and on_segment(p3, p4, p1): 12 | return True 13 | elif d2 == 0 and on_segment(p3, p4, p2): 14 | return True 15 | elif d3 == 0 and on_segment(p1, p2, p3): 16 | return True 17 | elif d4 == 0 and on_segment(p1, p2, p4): 18 | return True 19 | else: 20 | return False 21 | 22 | 23 | def direction(pi, pj, pk): 24 | v1 = (pk[0] - pi[0], pk[1] - pi[1]) 25 | v2 = (pj[0] - pi[0], pj[1] - pi[1]) 26 | return v1[0] * v2[1] - v2[0] * v1[1] 27 | 28 | 29 | def on_segment(pi, pj, pk): 30 | return min(pi[0], pj[0]) <= pk[0] <= max(pi[0], pj[0]) and min(pi[1], pj[1]) <= pk[1] <= max( 31 | pi[1], pj[1]) 32 | -------------------------------------------------------------------------------- /selection_sort.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | 5 | def selection_sort(array: list): 6 | """ 7 | Inplace sort 8 | Consider sorting n numbers stored in array A by first finding the smallest element of A 9 | and exchanging it with the element in A[0] . Then find the second smallest element of A, and exchange it with A[1]. 10 | Continue in this manner for the first n - 1 elements of A. 11 | :param array: 12 | :return: 13 | """ 14 | n = len(array) 15 | for i in range(n - 1): 16 | minimum = array[i] 17 | index = i 18 | for j in range(i + 1, n): 19 | if minimum > array[j]: 20 | minimum = array[j] 21 | index = j 22 | array[i], array[index] = array[index], array[i] 23 | -------------------------------------------------------------------------------- /square-matrix-multiply-brute-force.c: -------------------------------------------------------------------------------- 1 | // AUTHOR: WangQiang 2 | // DATE: 20140524 3 | // LAST UPDATE DATE: 20140524 4 | // EMAIL: cntqrxj@gmail.com 5 | 6 | #include 7 | 8 | //void square_matrix_multiply(int a[][2], int b[][2], int c[][2]) { 9 | //int i, j, k; 10 | // 11 | //for (i = 0; i < 2; i++) 12 | //for (j = 0; j < 2; j++) { 13 | //c[i][j] = 0; 14 | //for (k = 0; k < 2; k++) 15 | //c[i][j] = c[i][j] + a[i][k] * b[k][j]; 16 | //} 17 | //} 18 | 19 | void square_matrix_multiply(int *a, int *b, int *c, int n) { 20 | int i, j, k; 21 | 22 | for (i = 0; i < n; i++) 23 | for (j = 0; j < n; j++) { 24 | *(c + i * n + j) = 0; 25 | for (k = 0; k < n; k++) 26 | *(c + i * n + j) = *(c + i * n + j) + *(a + i * n + k) * *(b + k * n + j); 27 | } 28 | } 29 | 30 | int main() { 31 | //int d[4] = {1, 3, 7, 5}; 32 | //int e[4] = {6, 8, 4, 2}; 33 | //int f[4]; 34 | //int A[16] = {-1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1}; 35 | int A[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; 36 | int B[16], C[16]; 37 | int i, j; 38 | // 39 | //square_matrix_multiply(d, e, f, 2); 40 | //printf("Matrix d:\n"); 41 | //for (i = 0; i < 2; i++) { 42 | //for (j = 0; j < 2; j++) 43 | //printf("%d\t", *(d + 2 * i + j)); 44 | //printf("\n"); 45 | //} 46 | //printf("\n"); 47 | //printf("Matrix e:\n"); 48 | //for (i = 0; i < 2; i++) { 49 | //for (j = 0; j < 2; j++) 50 | //printf("%d\t", *(e + 2 * i + j)); 51 | //printf("\n"); 52 | //} 53 | //printf("\n"); 54 | //printf("The result of matrix multiply d * e:\n"); 55 | //for (i = 0; i < 2; i++) { 56 | //for (j = 0; j < 2; j++) 57 | //printf("%d\t", *(f + 2 * i + j)); 58 | //printf("\n"); 59 | //} 60 | square_matrix_multiply(A, A, B, 4); 61 | //square_matrix_multiply(A, B, C, 4); 62 | //square_matrix_multiply(C, C, B, 4); 63 | //printf("Matrix A:\n"); 64 | //for (i = 0; i < 4; i++) { 65 | //for (j = 0; j < 4; j++) 66 | //printf("%d\t", *(A + 4 * i + j)); 67 | //printf("\n"); 68 | //} 69 | //printf("\n"); 70 | //printf("The result is:\n"); 71 | for (i = 0; i < 4; i++) { 72 | for (j = 0; j < 4; j++) 73 | printf("%d\t", *(B + 4 * i + j)); 74 | printf("\n"); 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /square-matrix-multiply-brute-force2.c: -------------------------------------------------------------------------------- 1 | // AUTHOR: WangQiang 2 | // DATE: 20140527 3 | // LAST UPDATE DATE: 20140527 4 | // EMAIL: cntqrxj@gmail.com 5 | 6 | #include 7 | 8 | #define RANK 50 9 | 10 | void square_matrix_multiply(int a[][RANK], int b[][RANK], int c[][RANK]) { 11 | int i, j, k; 12 | 13 | for (i = 0; i < RANK; i++) 14 | for (j = 0; j < RANK; j++) { 15 | c[i][j] = 0; 16 | for (k = 0; k < RANK; k++) 17 | c[i][j] = c[i][j] + a[i][k] * b[k][j]; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /square-matrix-multiply-recursive.c: -------------------------------------------------------------------------------- 1 | // AUTHOR: WangQiang 2 | // CREATE DATE: 20140526 3 | // LAST UPDATE DATE: 20140528 4 | // EMAIL: cntqrxj@gmail.com 5 | 6 | #include 7 | #include 8 | 9 | static void submatrix_init(int *S, int S_row, int S_col, int *T, int T_row, int T_col, int row_start, int col_start) { 10 | int i, j; 11 | for (i = 0; i < T_row; i++) 12 | for (j = 0; j < T_col; j++) 13 | *(T + (i * T_row + j)) = *(S + (S_row * (row_start - 1) + col_start - 1) + i * S_row + j); 14 | } 15 | 16 | static void to_matrix(int *S, int S_row, int S_col, int *M, int M_row, int M_col, int row_start, int col_start) { 17 | int i, j; 18 | for (i = 0; i < S_row; i++) 19 | for (j = 0; j < S_col; j++) 20 | *(M + (M_row * (row_start - 1) + col_start - 1) + i * M_row + j) = *(S + (i * S_row + j)); 21 | } 22 | 23 | static void matrix_add(int *A, int *B, int *C, int row, int col) { 24 | int i, j; 25 | 26 | for (i = 0; i < row; i++) 27 | for (j = 0; j < col; j++) 28 | *(C + (i * row) + j) = *(A + (i * row) + j) + *(B + (i * row) + j); 29 | } 30 | 31 | void square_matrix_multiply(int *A, int *B, int *C, int n) { 32 | int half = n / 2; 33 | int num = half * half; 34 | 35 | if (n == 1) 36 | *C = *A * *B; 37 | else { 38 | int *A11 = (int *) calloc(num, sizeof(int)); 39 | int *A12 = (int *) calloc(num, sizeof(int)); 40 | int *A21 = (int *) calloc(num, sizeof(int)); 41 | int *A22 = (int *) calloc(num, sizeof(int)); 42 | int *B11 = (int *) calloc(num, sizeof(int)); 43 | int *B12 = (int *) calloc(num, sizeof(int)); 44 | int *B21 = (int *) calloc(num, sizeof(int)); 45 | int *B22 = (int *) calloc(num, sizeof(int)); 46 | int *C11 = (int *) calloc(num, sizeof(int)); 47 | int *C12 = (int *) calloc(num, sizeof(int)); 48 | int *C21 = (int *) calloc(num, sizeof(int)); 49 | int *C22 = (int *) calloc(num, sizeof(int)); 50 | int *D11 = (int *) calloc(num, sizeof(int)); 51 | int *D12 = (int *) calloc(num, sizeof(int)); 52 | int *D21 = (int *) calloc(num, sizeof(int)); 53 | int *D22 = (int *) calloc(num, sizeof(int)); 54 | 55 | submatrix_init(A, n, n, A11, half, half, 1, 1); 56 | submatrix_init(A, n, n, A12, half, half, 1, half + 1); 57 | submatrix_init(A, n, n, A21, half, half, half + 1, 1); 58 | submatrix_init(A, n, n, A22, half, half, half + 1, half + 1); 59 | submatrix_init(B, n, n, B11, half, half, 1, 1); 60 | submatrix_init(B, n, n, B12, half, half, 1, half + 1); 61 | submatrix_init(B, n, n, B21, half, half, half + 1, 1); 62 | submatrix_init(B, n, n, B22, half, half, half + 1, half + 1); 63 | square_matrix_multiply(A11, B11, C11, half); 64 | square_matrix_multiply(A12, B21, D11, half); 65 | square_matrix_multiply(A11, B12, C12, half); 66 | square_matrix_multiply(A12, B22, D12, half); 67 | square_matrix_multiply(A21, B11, C21, half); 68 | square_matrix_multiply(A22, B21, D21, half); 69 | square_matrix_multiply(A21, B12, C22, half); 70 | square_matrix_multiply(A22, B22, D22, half); 71 | matrix_add(C11, D11, C11, half, half); 72 | matrix_add(C12, D12, C12, half, half); 73 | matrix_add(C21, D21, C21, half, half); 74 | matrix_add(C22, D22, C22, half, half); 75 | to_matrix(C11, half, half, C, n, n, 1, 1); 76 | to_matrix(C12, half, half, C, n, n, 1, half + 1); 77 | to_matrix(C21, half, half, C, n, n, half + 1, 1); 78 | to_matrix(C22, half, half, C, n, n, half + 1, half + 1); 79 | free(A11); 80 | free(A12); 81 | free(A21); 82 | free(A22); 83 | free(B11); 84 | free(B12); 85 | free(B21); 86 | free(B22); 87 | free(C11); 88 | free(C12); 89 | free(C21); 90 | free(C22); 91 | free(D11); 92 | free(D12); 93 | free(D21); 94 | free(D22); 95 | } 96 | return; 97 | } 98 | -------------------------------------------------------------------------------- /square_matrix_multiply_Strassen.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/python2.7 2 | 3 | from numpy import * 4 | 5 | 6 | def square_matrix_multiply(A, B): 7 | shape = A.shape 8 | length = shape[0] 9 | half = length / 2 10 | 11 | C = zeros(shape, dtype=int64) 12 | if length == 1: 13 | C[0, 0] = A[0, 0] * B[0, 0] 14 | return C 15 | 16 | S1 = zeros((half, half), dtype=int64) 17 | S2 = zeros((half, half), dtype=int64) 18 | S3 = zeros((half, half), dtype=int64) 19 | S4 = zeros((half, half), dtype=int64) 20 | S5 = zeros((half, half), dtype=int64) 21 | S6 = zeros((half, half), dtype=int64) 22 | S7 = zeros((half, half), dtype=int64) 23 | S8 = zeros((half, half), dtype=int64) 24 | S9 = zeros((half, half), dtype=int64) 25 | S10 = zeros((half, half), dtype=int64) 26 | 27 | P1 = zeros((half, half), dtype=int64) 28 | P2 = zeros((half, half), dtype=int64) 29 | P3 = zeros((half, half), dtype=int64) 30 | P4 = zeros((half, half), dtype=int64) 31 | P5 = zeros((half, half), dtype=int64) 32 | P6 = zeros((half, half), dtype=int64) 33 | P7 = zeros((half, half), dtype=int64) 34 | 35 | S1 = B[0:half, half:length] - B[half:length, half:length] 36 | S2 = A[0:half, 0:half] + A[0:half, half:length] 37 | S3 = A[half:length, 0:half] + A[half:length, half:length] 38 | S4 = B[half:length, 0:half] - B[0:half, 0:half] 39 | S5 = A[0:half, 0:half] + A[half:length, half:length] 40 | S6 = B[0:half, 0:half] + B[half:length, half:length] 41 | S7 = A[0:half, half:length] - A[half:length, half:length] 42 | S8 = B[half:length, 0:half] + B[half:length, half:length] 43 | S9 = A[0:half, 0:half] - A[half:length, 0:half] 44 | S10 = B[0:half, 0:half] + B[0:half, half:length] 45 | 46 | P1 = square_matrix_multiply(A[0:half, 0:half], S1) 47 | P2 = square_matrix_multiply(S2, B[half:length, half:length]) 48 | P3 = square_matrix_multiply(S3, B[0:half, 0:half]) 49 | P4 = square_matrix_multiply(A[half:length, half:length], S4) 50 | P5 = square_matrix_multiply(S5, S6) 51 | P6 = square_matrix_multiply(S7, S8) 52 | P7 = square_matrix_multiply(S9, S10) 53 | 54 | C[0:half, 0:half] = P5 + P4 - P2 + P6 55 | C[0:half, half:length] = P1 + P2 56 | C[half:length, 0:half] = P3 + P4 57 | C[half:length, half:length] = P5 + P1 - P3 - P7 58 | 59 | return C 60 | 61 | 62 | # # A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) 63 | # # B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) 64 | # # A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 65 | # # B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) 66 | # A = array([[1, 3], [7, 5]]) 67 | # B = array([[6, 8], [4, 2]]) 68 | # # A = array([[1, 2, 3], [4, 5, 6]]) 69 | # # B = array([[1, 2], [4, 5]]) 70 | # print(square_matrix_multiply(A, B)) 71 | # # print( dot(A, B)) 72 | -------------------------------------------------------------------------------- /stack.py: -------------------------------------------------------------------------------- 1 | class FullException(Exception): 2 | pass 3 | 4 | 5 | class EmptyException(Exception): 6 | pass 7 | 8 | 9 | class Stack(list): 10 | def __init__(self, size): 11 | super(Stack, self).__init__([None] * size) 12 | self.top = -1 13 | self.size = len(size) 14 | 15 | def push(self, x): 16 | if self.full(): 17 | raise FullException("This stack is full") 18 | else: 19 | self.top = self.top + 1 20 | self[self.top] = x 21 | 22 | def pop(self, *args, **kwargs): 23 | if self.empty(): 24 | raise EmptyException('This stack is empty') 25 | else: 26 | self.top = self.top - 1 27 | return self[self.top + 1] 28 | 29 | def empty(self): 30 | return self.top == -1 31 | 32 | def full(self): 33 | return self.top == self.size - 1 34 | 35 | # def multipop(self, k): 36 | # l = [] 37 | # while not self.empty() and k > 0: 38 | # 39 | # l.append(self.pop()) 40 | # return l 41 | -------------------------------------------------------------------------------- /synthetic_division.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def synthetic_division(A, n, x): 5 | q = [0] * (n - 1) 6 | q[n - 2] = A[n - 1] 7 | for i in range(n - 3, -1, -1): 8 | q[i] = x * q[i + 1] + A[i + 1] 9 | r = x * q[0] + A[0] 10 | return q, r 11 | -------------------------------------------------------------------------------- /tests/Bellman_Ford_matrix_test.py: -------------------------------------------------------------------------------- 1 | from Bellman_Ford_matrix import Bellman_Ford_matrix, slow_all_pairs_shortest_paths 2 | import unittest 3 | import numpy 4 | 5 | 6 | class TestBellmanFordMatrix(unittest.TestCase): 7 | def test_Bellman_Ford_matrix(self): 8 | W = numpy.array([[float("Inf"), 6., 7., float("Inf"), float("Inf")], [float("Inf"), float("Inf"), 8., 5., -4.], 9 | [float("Inf"), float("Inf"), float("Inf"), -3., 9.], 10 | [float("Inf"), -2., float("Inf"), float("Inf"), float("Inf")], 11 | [2., float("Inf"), float("Inf"), 7., float("Inf")]]) 12 | d, p = Bellman_Ford_matrix(W, 1) 13 | self.assertEqual(d, [0, 2.0, 7.0, 4.0, -2.0]) 14 | self.assertEqual(p, [None, 4, 1, 3, 2]) 15 | 16 | def test_slow_all_pairs_shortest_paths(self): 17 | W = numpy.array([[0, 6., 7., float("Inf"), float("Inf")], [float("Inf"), 0, 8., 5., -4.], 18 | [float("Inf"), float("Inf"), 0, -3., 9.], [float("Inf"), -2., float("Inf"), 0, float("Inf")], 19 | [2., float("Inf"), float("Inf"), 7., 0]]) 20 | L = slow_all_pairs_shortest_paths(W, 1) 21 | # print(L) 22 | self.assertEqual(L, [0, 2.0, 7.0, 4.0, -2.0]) 23 | -------------------------------------------------------------------------------- /tests/Horner_rule_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import unittest 5 | import random 6 | from Horner_rule import Horner_rule 7 | 8 | 9 | class TestHornerRule(unittest.TestCase): 10 | def test_horner_rule(self): 11 | for _ in range(100): 12 | x = random.randint(1, 5) 13 | coefficients = [random.randint(0, 100) for _ in range(11)] 14 | expected_result = 0 15 | for index, coefficient in enumerate(coefficients): 16 | expected_result += coefficient * x ** index 17 | self.assertEqual(Horner_rule(x, coefficients), expected_result) 18 | -------------------------------------------------------------------------------- /tests/Johnson_test.py: -------------------------------------------------------------------------------- 1 | from Johnson import Johnson 2 | from graph import Vertex, Graph 3 | import unittest 4 | 5 | 6 | class TestJohnson(unittest.TestCase): 7 | def testJohnson(self): 8 | a1 = Vertex(1) 9 | a2 = Vertex(2) 10 | a3 = Vertex(3) 11 | a4 = Vertex(4) 12 | a5 = Vertex(5) 13 | vertices = [a1, a2, a3, a4, a5] 14 | edges = [(a1, a2), (a1, a3), (a1, a5), (a2, a4), (a2, a5), (a3, a2), (a4, a1), (a4, a3), (a5, a4)] 15 | g = Graph(vertices, edges) 16 | weight = [3, 8, -4, 1, 7, 4, 2, -5, 6] 17 | w = dict() 18 | for i, j in zip(edges, weight): 19 | w[i] = j 20 | D = Johnson(g, w) 21 | # print(D) 22 | a1 = Vertex(1) 23 | a2 = Vertex(2) 24 | a3 = Vertex(3) 25 | a4 = Vertex(4) 26 | a5 = Vertex(5) 27 | a6 = Vertex(6) 28 | vertices = [a1, a2, a3, a4, a5, a6] 29 | edges = [(a1, a5), (a2, a1), (a2, a4), (a3, a2), (a3, a6), (a4, a1), (a4, a5), (a5, a2), (a6, a2), (a6, a3)] 30 | g = Graph(vertices, edges) 31 | weight = [-1, 1, 2, 2, -8, -4, 3, 7, 5, 10] 32 | w = dict() 33 | for i, j in zip(edges, weight): 34 | w[i] = j 35 | D = Johnson(g, w) 36 | # print(D) 37 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Firkraag/algorithm/253f63e8c1e9cea2b90980d76973b37b347d70bb/tests/__init__.py -------------------------------------------------------------------------------- /tests/all_pairs_shortest_paths_test.py: -------------------------------------------------------------------------------- 1 | from all_pairs_shortest_paths import slow_all_pairs_shortest_paths, faster_all_pairs_shortest_paths 2 | import unittest 3 | import numpy as np 4 | 5 | 6 | class TestAllPairsShortestPaths(unittest.TestCase): 7 | def test_slow_all_pairs_shortest_paths(self): 8 | W = np.array([[0, 3, 8, float("Inf"), -4], [float("Inf"), 0, float("Inf"), 1, 7], 9 | [float("Inf"), 4, 0, float("Inf"), float("Inf")], [2, float("Inf"), -5, 0, float("Inf")], 10 | [float("Inf"), float("Inf"), float("Inf"), 6, 0]]) 11 | R = slow_all_pairs_shortest_paths(W) 12 | L = np.array([[0, 1, -3, 2, -4], [3, 0, -4, 1, -1], [7, 4, 0, 5, 3], [2, -1, -5, 0, -2], [8, 5, 1, 6, 0]]) 13 | self.assertEqual((R == L).all(), True) 14 | W = np.array([[0, float("Inf"), float("Inf"), float("Inf"), -1, float("Inf")], 15 | [1, 0, float("Inf"), 2, float("Inf"), float("Inf")], 16 | [float("Inf"), 2, 0, float("Inf"), float("Inf"), -8], 17 | [-4, float("Inf"), float("Inf"), 0, 3, float("Inf")], 18 | [float("Inf"), 7, float("Inf"), float("Inf"), 0, float("Inf")], 19 | [float("Inf"), 5, 10, float("Inf"), float("Inf"), 0]]) 20 | R = slow_all_pairs_shortest_paths(W) 21 | L = np.array([[0, 6, float("Inf"), 8, -1, float("Inf")], [-2, 0, float("Inf"), 2, -3, float("Inf")], 22 | [-5, -3, 0, -1, -6, -8], [-4, 2, float("Inf"), 0, -5, float("Inf")], 23 | [5, 7, float("Inf"), 9, 0, float("Inf")], [3, 5, 10, 7, 2, 0]]) 24 | self.assertEqual((R == L).all(), True) 25 | 26 | def test_faster_all_pairs_shortest_paths(self): 27 | W = np.array([[0, 3, 8, float("Inf"), -4], [float("Inf"), 0, float("Inf"), 1, 7], 28 | [float("Inf"), 4, 0, float("Inf"), float("Inf")], [2, float("Inf"), -5, 0, float("Inf")], 29 | [float("Inf"), float("Inf"), float("Inf"), 6, 0]]) 30 | R = faster_all_pairs_shortest_paths(W) 31 | L = np.array([[0, 1, -3, 2, -4], [3, 0, -4, 1, -1], [7, 4, 0, 5, 3], [2, -1, -5, 0, -2], [8, 5, 1, 6, 0]]) 32 | self.assertEqual((R == L).all(), True) 33 | W = np.array([[0, float("Inf"), float("Inf"), float("Inf"), -1, float("Inf")], 34 | [1, 0, float("Inf"), 2, float("Inf"), float("Inf")], 35 | [float("Inf"), 2, 0, float("Inf"), float("Inf"), -8], 36 | [-4, float("Inf"), float("Inf"), 0, 3, float("Inf")], 37 | [float("Inf"), 7, float("Inf"), float("Inf"), 0, float("Inf")], 38 | [float("Inf"), 5, 10, float("Inf"), float("Inf"), 0]]) 39 | R = faster_all_pairs_shortest_paths(W) 40 | L = np.array([[0, 6, float("Inf"), 8, -1, float("Inf")], [-2, 0, float("Inf"), 2, -3, float("Inf")], 41 | [-5, -3, 0, -1, -6, -8], [-4, 2, float("Inf"), 0, -5, float("Inf")], 42 | [5, 7, float("Inf"), 9, 0, float("Inf")], [3, 5, 10, 7, 2, 0]]) 43 | self.assertEqual((R == L).all(), True) 44 | -------------------------------------------------------------------------------- /tests/bh_tree_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from bh_tree import bh_tree, bh_node 4 | 5 | 6 | class TestRbTree(unittest.TestCase): 7 | def test_insert_one(self): 8 | T = bh_tree([41]) 9 | self.wrap(T, 41, 1) 10 | 11 | def test_insert_two(self): 12 | T = bh_tree([41, 38]) 13 | self.wrap(T, 41, 1) 14 | self.wrap(T, 38, 1) 15 | 16 | def test_insert_three(self): 17 | T = bh_tree([41, 38, 31]) 18 | self.wrap(T, 38, 1) 19 | self.wrap(T, 31, 1) 20 | self.wrap(T, 41, 1) 21 | 22 | def test_insert_four(self): 23 | T = bh_tree([41, 38, 31, 12]) 24 | self.wrap(T, 38, 2) 25 | self.wrap(T, 31, 1) 26 | self.wrap(T, 41, 1) 27 | self.wrap(T, 12, 1) 28 | 29 | def test_insert_five(self): 30 | T = bh_tree([41, 38, 31, 12, 19]) 31 | self.wrap(T, 38, 2) 32 | self.wrap(T, 19, 1) 33 | self.wrap(T, 41, 1) 34 | self.wrap(T, 12, 1) 35 | self.wrap(T, 31, 1) 36 | 37 | def test_insert_six(self): 38 | T = bh_tree([41, 38, 31, 12, 19, 9]) 39 | self.wrap(T, 38, 2) 40 | self.wrap(T, 19, 2) 41 | self.wrap(T, 41, 1) 42 | self.wrap(T, 12, 1) 43 | self.wrap(T, 31, 1) 44 | self.wrap(T, 9, 1) 45 | 46 | def test_delete_one(self): 47 | T = bh_tree([41, 38, 31, 12, 19, 9]) 48 | T.delete(T.iterative_tree_search(9)) 49 | self.wrap(T, 38, 2) 50 | self.wrap(T, 19, 2) 51 | self.wrap(T, 41, 1) 52 | self.wrap(T, 12, 1) 53 | self.wrap(T, 31, 1) 54 | 55 | def test_delete_two(self): 56 | T = bh_tree([41, 38, 31, 12, 19, 9]) 57 | T.delete(T.iterative_tree_search(9)) 58 | T.delete(T.iterative_tree_search(12)) 59 | self.wrap(T, 38, 2) 60 | self.wrap(T, 19, 1) 61 | self.wrap(T, 41, 1) 62 | self.wrap(T, 31, 1) 63 | 64 | def test_delete_three(self): 65 | T = bh_tree([41, 38, 31, 12, 19, 9]) 66 | T.delete(T.iterative_tree_search(9)) 67 | T.delete(T.iterative_tree_search(12)) 68 | T.delete(T.iterative_tree_search(19)) 69 | self.wrap(T, 38, 2) 70 | self.wrap(T, 31, 1) 71 | self.wrap(T, 41, 1) 72 | 73 | def test_delete_four(self): 74 | T = bh_tree([41, 38, 31, 12, 19, 9]) 75 | T.delete(T.iterative_tree_search(9)) 76 | T.delete(T.iterative_tree_search(12)) 77 | T.delete(T.iterative_tree_search(19)) 78 | T.delete(T.iterative_tree_search(31)) 79 | self.wrap(T, 38, 1) 80 | self.wrap(T, 41, 1) 81 | 82 | def test_delete_five(self): 83 | T = bh_tree([41, 38, 31, 12, 19, 9]) 84 | T.delete(T.iterative_tree_search(9)) 85 | T.delete(T.iterative_tree_search(12)) 86 | T.delete(T.iterative_tree_search(19)) 87 | T.delete(T.iterative_tree_search(31)) 88 | T.delete(T.iterative_tree_search(38)) 89 | self.wrap(T, 41, 1) 90 | 91 | def test_delete_six(self): 92 | T = bh_tree([41, 38, 31, 12, 19, 9]) 93 | T.delete(T.iterative_tree_search(9)) 94 | T.delete(T.iterative_tree_search(12)) 95 | T.delete(T.iterative_tree_search(19)) 96 | T.delete(T.iterative_tree_search(31)) 97 | T.delete(T.iterative_tree_search(38)) 98 | T.delete(T.iterative_tree_search(41)) 99 | self.assertEqual(T.root, T.nil) 100 | 101 | def wrap(self, tree, node, bh): 102 | self.assertEqual(tree.iterative_tree_search(node).bh, bh) 103 | 104 | 105 | if __name__ == '__main__': 106 | unittest.main() 107 | -------------------------------------------------------------------------------- /tests/binary_search_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | import random 4 | from binary_search import binary_search, bisect_left, bisect_right 5 | 6 | 7 | class TestBinarySearch(unittest.TestCase): 8 | def test_binary_search(self): 9 | for _ in range(100): 10 | array = sorted([random.randint(1, 10000) for _ in range(100)]) 11 | target = random.randint(1, 10000) 12 | index = binary_search(target, array) 13 | if index == -1: 14 | self.assertNotIn(target, array) 15 | else: 16 | self.assertEqual(target, array[index]) 17 | 18 | def test_bisect_left(self): 19 | for length in range(10): 20 | array = sorted([random.randint(1, 10) for _ in range(length)]) 21 | target = random.randint(0, 15) 22 | index = bisect_left(array, target) 23 | self.assertTrue(all(val < target for val in array[:index])) 24 | self.assertTrue(all(val >= target for val in array[index:])) 25 | 26 | def test_bisect_right(self): 27 | for length in range(10): 28 | array = sorted([random.randint(1, 10) for _ in range(length)]) 29 | target = random.randint(0, 15) 30 | index = bisect_right(array, target) 31 | self.assertTrue(all(val <= target for val in array[:index])) 32 | self.assertTrue(all(val > target for val in array[index:])) 33 | -------------------------------------------------------------------------------- /tests/bubble_sort_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | import random 4 | from bubble_sort import bubble_sort 5 | 6 | 7 | class TestBubbleSort(unittest.TestCase): 8 | def test_bubble_sort(self): 9 | for _ in range(100): 10 | array = [random.randint(1, 10000) for _ in range(100)] 11 | array_copy = array[:] 12 | bubble_sort(array) 13 | self.assertEqual(array, sorted(array_copy)) 14 | -------------------------------------------------------------------------------- /tests/contains_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import unittest 4 | from contains import contains 5 | 6 | 7 | class TestContains(unittest.TestCase): 8 | def test_contains(self): 9 | x = [1, 1.5, 3.5, 2.3, 10.01] 10 | self.assertEqual(contains(x, 5), { 11 | (1, 2), (2.3, 3.3), (3.5, 4.5), (10.01, 11.01)}) 12 | x = [3.5, 5.2, -1.1, -4, -12, -11.33] 13 | self.assertEqual(contains(x, 6), { 14 | (-12, -11), (-4, -3), (-1.1, -0.10000000000000009), (3.5, 4.5), (5.2, 6.2)}) 15 | -------------------------------------------------------------------------------- /tests/counting_sort_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from counting_sort import counting_sort 3 | 4 | 5 | class TestHeap(unittest.TestCase): 6 | def test_counting_sort(self): 7 | A = [2, 5, 3, 0, 2, 3, 0, 3] 8 | B = [] 9 | for i in range(len(A)): 10 | B.append(0) 11 | counting_sort(A, B, 5) 12 | self.assertEqual(B, [0, 0, 2, 2, 3, 3, 3, 5]) 13 | self.assertEqual(A, [2, 5, 3, 0, 2, 3, 0, 3]) 14 | -------------------------------------------------------------------------------- /tests/cut_rod_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | 4 | from cut_rod import bottom_up_cut_rod, bottom_up_cut_rod_two_subproblem, memoized_cut_rod, print_cut_rod_solution, \ 5 | bottom_up_cut_rod_with_fixed_cut_cost, extended_memoized_cut_rod 6 | 7 | 8 | class TestCutRod(unittest.TestCase): 9 | def test_bottom_up_cut_rod(self): 10 | p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] 11 | values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 12 | 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] 13 | for i in range(len(values), 2): 14 | self.assertEqual(bottom_up_cut_rod(p, values[i]), values[i + 1]) 15 | 16 | def test_bottom_up_cut_rod_two_subproblem(self): 17 | p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] 18 | values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 19 | 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] 20 | for i in range(len(values), 2): 21 | self.assertEqual(bottom_up_cut_rod_two_subproblem( 22 | p, values[i]), values[i + 1]) 23 | 24 | def test_memoized_cut_rod(self): 25 | p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] 26 | values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 27 | 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] 28 | for i in range(len(values), 2): 29 | self.assertEqual(memoized_cut_rod(p, values[i]), values[i + 1]) 30 | 31 | def test_bottom_up_cut_rod_with_fixed_cut_cost(self): 32 | p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] 33 | values = [1, 1, 2, 5, 3, 8, 4, 9, 5, 11, 34 | 6, 17, 7, 17, 8, 20, 9, 24, 10, 30] 35 | for i in range(len(values), 2): 36 | self.assertEqual(bottom_up_cut_rod_with_fixed_cut_cost( 37 | p, values[i], 2), values[i + 1]) 38 | values = [1, 1, 2, 5, 3, 8, 4, 9, 5, 11.5, 39 | 6, 17, 7, 17, 8, 20.5, 9, 24, 10, 30] 40 | for i in range(len(values), 2): 41 | self.assertEqual(bottom_up_cut_rod_with_fixed_cut_cost( 42 | p, values[i], 1.5), values[i + 1]) 43 | 44 | def test_print_rod_solution(self): 45 | p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] 46 | values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 47 | 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] 48 | print_cut_rod_solution(p, 9, extended_memoized_cut_rod) 49 | -------------------------------------------------------------------------------- /tests/depth_tree_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from depth_tree import depth_tree, depth_node 4 | 5 | 6 | class TestRbtree(unittest.TestCase): 7 | def test_insert_one(self): 8 | T = depth_tree([41]) 9 | self.wrap(T, 41, 0) 10 | 11 | def test_insert_two(self): 12 | T = depth_tree([41, 38]) 13 | self.wrap(T, 41, 0) 14 | self.wrap(T, 38, 1) 15 | 16 | def test_insert_three(self): 17 | T = depth_tree([41, 38, 31]) 18 | self.wrap(T, 38, 0) 19 | self.wrap(T, 31, 1) 20 | self.wrap(T, 41, 1) 21 | 22 | def test_insert_four(self): 23 | T = depth_tree([41, 38, 31, 12]) 24 | self.wrap(T, 38, 0) 25 | self.wrap(T, 31, 1) 26 | self.wrap(T, 41, 1) 27 | self.wrap(T, 12, 2) 28 | 29 | def test_insert_five(self): 30 | T = depth_tree([41, 38, 31, 12, 19]) 31 | self.wrap(T, 38, 0) 32 | self.wrap(T, 19, 1) 33 | self.wrap(T, 41, 1) 34 | self.wrap(T, 12, 2) 35 | self.wrap(T, 31, 2) 36 | 37 | def test_insert_six(self): 38 | T = depth_tree([41, 38, 31, 12, 19, 9]) 39 | self.wrap(T, 38, 0) 40 | self.wrap(T, 19, 1) 41 | self.wrap(T, 41, 1) 42 | self.wrap(T, 12, 2) 43 | self.wrap(T, 31, 2) 44 | self.wrap(T, 9, 3) 45 | 46 | def test_delete_one(self): 47 | T = depth_tree([41, 38, 31, 12, 19, 9]) 48 | T.delete(T.iterative_tree_search(9)) 49 | self.wrap(T, 38, 0) 50 | self.wrap(T, 19, 1) 51 | self.wrap(T, 41, 1) 52 | self.wrap(T, 12, 2) 53 | self.wrap(T, 31, 2) 54 | 55 | def test_delete_two(self): 56 | T = depth_tree([41, 38, 31, 12, 19, 9]) 57 | T.delete(T.iterative_tree_search(9)) 58 | T.delete(T.iterative_tree_search(12)) 59 | self.wrap(T, 38, 0) 60 | self.wrap(T, 19, 1) 61 | self.wrap(T, 41, 1) 62 | self.wrap(T, 31, 2) 63 | 64 | def test_delete_three(self): 65 | T = depth_tree([41, 38, 31, 12, 19, 9]) 66 | T.delete(T.iterative_tree_search(9)) 67 | T.delete(T.iterative_tree_search(12)) 68 | T.delete(T.iterative_tree_search(19)) 69 | self.wrap(T, 38, 0) 70 | self.wrap(T, 31, 1) 71 | self.wrap(T, 41, 1) 72 | 73 | def test_delete_four(self): 74 | T = depth_tree([41, 38, 31, 12, 19, 9]) 75 | T.delete(T.iterative_tree_search(9)) 76 | T.delete(T.iterative_tree_search(12)) 77 | T.delete(T.iterative_tree_search(19)) 78 | T.delete(T.iterative_tree_search(31)) 79 | self.wrap(T, 38, 0) 80 | self.wrap(T, 41, 1) 81 | 82 | def test_delete_five(self): 83 | T = depth_tree([41, 38, 31, 12, 19, 9]) 84 | T.delete(T.iterative_tree_search(9)) 85 | T.delete(T.iterative_tree_search(12)) 86 | T.delete(T.iterative_tree_search(19)) 87 | T.delete(T.iterative_tree_search(31)) 88 | T.delete(T.iterative_tree_search(38)) 89 | self.wrap(T, 41, 0) 90 | 91 | def test_delete_six(self): 92 | T = depth_tree([41, 38, 31, 12, 19, 9]) 93 | T.delete(T.iterative_tree_search(9)) 94 | T.delete(T.iterative_tree_search(12)) 95 | T.delete(T.iterative_tree_search(19)) 96 | T.delete(T.iterative_tree_search(31)) 97 | T.delete(T.iterative_tree_search(38)) 98 | T.delete(T.iterative_tree_search(41)) 99 | self.assertEqual(T.nil.depth, -1) 100 | 101 | def wrap(self, tree, node, depth): 102 | self.assertEqual(tree.iterative_tree_search(node).depth, depth) 103 | 104 | 105 | if __name__ == '__main__': 106 | unittest.main() 107 | -------------------------------------------------------------------------------- /tests/disjoint_sets_forest_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import unittest 4 | import disjoint_sets_forest as ds 5 | 6 | 7 | class TestDisjointSets(unittest.TestCase): 8 | def test_forest(self): 9 | pool = [0] * 17 10 | for i in range(1, 17): 11 | pool[i] = ds.node(i) 12 | for i in range(1, 17): 13 | self.assertEqual(pool[i].p, pool[i]) 14 | for i in range(1, 16, 2): 15 | pool[i].union(pool[i + 1]) 16 | parent_list = [2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16] 17 | for i in range(1, 17): 18 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 19 | for i in range(1, 14, 4): 20 | pool[i].union(pool[i + 2]) 21 | parent_list = [2, 4, 4, 4, 6, 8, 8, 8, 10, 12, 12, 12, 14, 16, 16, 16] 22 | for i in range(1, 17): 23 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 24 | pool[1].union(pool[5]) 25 | parent_list = [4, 4, 4, 8, 8, 8, 8, 8, 10, 12, 12, 12, 14, 16, 16, 16] 26 | for i in range(1, 17): 27 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 28 | pool[11].union(pool[13]) 29 | parent_list = [4, 4, 4, 8, 8, 8, 8, 8, 10, 12, 12, 16, 16, 16, 16, 16] 30 | for i in range(1, 17): 31 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 32 | pool[1].union(pool[10]) 33 | parent_list = [8, 4, 4, 8, 8, 8, 8, 16, 10, 16, 12, 16, 16, 16, 16, 16] 34 | for i in range(1, 17): 35 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 36 | self.assertTrue(pool[2].find_set() == pool[16]) 37 | parent_list = [8, 16, 4, 16, 8, 8, 8, 38 | 16, 10, 16, 12, 16, 16, 16, 16, 16] 39 | for i in range(1, 17): 40 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 41 | self.assertTrue(pool[9].find_set() == pool[16]) 42 | parent_list = [8, 16, 4, 16, 8, 8, 8, 43 | 16, 16, 16, 12, 16, 16, 16, 16, 16] 44 | for i in range(1, 17): 45 | self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) 46 | -------------------------------------------------------------------------------- /tests/disjoint_sets_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import unittest 4 | import disjoint_sets_linked_list as ds 5 | 6 | 7 | class TestDisjointSets(unittest.TestCase): 8 | def test_linked_lists_with_head_and_tail(self): 9 | pool = [0] * 17 10 | for i in range(1, 17): 11 | pool[i] = ds.node(i) 12 | a = ds.header(pool[i]) 13 | self.assertEqual(a.head, pool[i]) 14 | self.assertEqual(a.tail, pool[i]) 15 | for i in range(1, 16, 2): 16 | pool[i].union(pool[i + 1]) 17 | for i in range(1, 14, 4): 18 | pool[i].union(pool[i + 2]) 19 | pool[1].union(pool[5]) 20 | pool[11].union(pool[13]) 21 | pool[1].union(pool[10]) 22 | self.assertTrue(pool[2].find_set() == pool[1]) 23 | self.assertTrue(pool[9].find_set() == pool[1]) 24 | 25 | def test_linked_lists_no_tail(self): 26 | pool = [0] * 17 27 | for i in range(1, 17): 28 | pool[i] = ds.node_notail(i) 29 | ds.header_notail(pool[i]) 30 | for i in range(1, 16, 2): 31 | pool[i].union(pool[i + 1]) 32 | for i in range(1, 14, 4): 33 | pool[i].union(pool[i + 2]) 34 | pool[1].union(pool[5]) 35 | pool[11].union(pool[13]) 36 | pool[1].union(pool[10]) 37 | self.assertTrue(pool[2].find_set() == pool[16]) 38 | self.assertTrue(pool[9].find_set() == pool[16]) 39 | -------------------------------------------------------------------------------- /tests/hamiltonian_path_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from graph import Vertex, Graph 4 | from hamiltonian_path import hamiltonian_path 5 | 6 | 7 | class TestHamiltonianPath(unittest.TestCase): 8 | def testHamPath(self): 9 | r = Vertex('r') 10 | s = Vertex('s') 11 | t = Vertex('t') 12 | x = Vertex('x') 13 | y = Vertex('y') 14 | z = Vertex('z') 15 | vertices = [r, s, t, x, y, z] 16 | edges = [(r, s), (s, t), (t, x), (x, y), (y, z)] 17 | G = Graph(vertices, edges) 18 | self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False, True]) 19 | edges = [(r, s), (r, t), (s, x), (s, y), (t, z)] 20 | G = Graph(vertices, edges) 21 | self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False, False]) 22 | edges = [(r, s), (s, t), (s, x), (t, x)] 23 | vertices = [r, s, t, x] 24 | G = Graph(vertices, edges) 25 | self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, True]) 26 | edges = [(r, s), (s, t), (s, x), (t, x), (r, y), (y, s)] 27 | vertices = [r, s, t, x, y] 28 | G = Graph(vertices, edges) 29 | self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, True, False]) 30 | edges = [(r, s), (s, t), (s, x), (t, x), (r, y)] 31 | vertices = [r, s, t, x, y] 32 | G = Graph(vertices, edges) 33 | self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False]) 34 | -------------------------------------------------------------------------------- /tests/heap_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from heap import MaxHeap, MinHeap 3 | 4 | 5 | class TestHeap(unittest.TestCase): 6 | # def test_init(self): 7 | # a = heap([4, 1, 3, 2, 16, 9, 10, 14, 8, 7]) 8 | # self.assertEqual(a.__heap, a) 9 | # self.assertEqual(a.__length, 10) 10 | # self.assertEqual(a.__heap_size, 10) 11 | def test_max_heapify(self): 12 | a = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1] 13 | h = MaxHeap(a) 14 | h.max_heapify(1) 15 | self.assertEqual(h, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) 16 | 17 | def test_build_max_heap(self): 18 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 19 | h = MaxHeap(a) 20 | h.build_max_heap() 21 | self.assertEqual(h, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) 22 | 23 | def test_heapsort(self): 24 | a = [4, 1, 3, 3, 16, 9, 10, 14, 8, 7] 25 | h = MaxHeap(a) 26 | h.heapsort() 27 | self.assertEqual(h, [1, 3, 3, 4, 7, 8, 9, 10, 14, 16]) 28 | 29 | def test_min_heapify(self): 30 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 31 | h = MinHeap(a) 32 | h.min_heapify(1) 33 | self.assertEqual(h, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) 34 | 35 | def test_build_min_heap(self): 36 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 37 | h = MinHeap(a) 38 | h.build_min_heap() 39 | self.assertEqual(h, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) 40 | -------------------------------------------------------------------------------- /tests/insertion_sort_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | import random 4 | from insertion_sort import insertion_sort, insertion_sort_recursive, insert_with_linear_search, \ 5 | insert_with_binary_search 6 | 7 | 8 | class TestInsertionSort(unittest.TestCase): 9 | def test_insertion_sort_with_linear_search(self): 10 | for _ in range(100): 11 | array = [random.randint(1, 10000) for _ in range(100)] 12 | array_copy = array[:] 13 | insertion_sort(array, insert_method=insert_with_linear_search) 14 | self.assertEqual(array, sorted(array_copy)) 15 | 16 | def test_insertion_sort_with_binary_search(self): 17 | for _ in range(100): 18 | array = [random.randint(1, 10000) for _ in range(100)] 19 | array_copy = array[:] 20 | insertion_sort(array, insert_method=insert_with_binary_search) 21 | self.assertEqual(array, sorted(array_copy)) 22 | 23 | def test_insertion_sort_recursive(self): 24 | for _ in range(100): 25 | array = [random.randint(1, 10000) for _ in range(100)] 26 | array_copy = array[:] 27 | insertion_sort_recursive(array) 28 | self.assertEqual(array, sorted(array_copy)) 29 | for _ in range(100): 30 | array = [random.randint(1, 10000) for _ in range(100)] 31 | array_copy = array[:] 32 | insertion_sort_recursive( 33 | array, insert_method=insert_with_binary_search) 34 | self.assertEqual(array, sorted(array_copy)) 35 | -------------------------------------------------------------------------------- /tests/inversion_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | import unittest 4 | import random 5 | from inversion import inversion_with_insertion_sort, inversion_with_merge_sort 6 | 7 | 8 | class TestInversion(unittest.TestCase): 9 | def test_inversion_with_insertion_sort(self): 10 | for _ in range(100): 11 | array = [random.randint(0, 100) for _ in range(100)] 12 | expected_result = 0 13 | for i in range(len(array)): 14 | for j in range(i + 1, len(array)): 15 | if array[i] > array[j]: 16 | expected_result += 1 17 | self.assertEqual(inversion_with_insertion_sort(array), expected_result) 18 | 19 | def test_inversion_with_merge_sort(self): 20 | for _ in range(100): 21 | array = [random.randint(0, 100) for _ in range(100)] 22 | expected_result = 0 23 | for i in range(len(array)): 24 | for j in range(i + 1, len(array)): 25 | if array[i] > array[j]: 26 | expected_result += 1 27 | self.assertEqual(inversion_with_merge_sort(array), expected_result) 28 | -------------------------------------------------------------------------------- /tests/k_way_merge_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from k_way_merge import k_way_merge 4 | from random_array import random_arrays 5 | 6 | 7 | class TestKWayMerge(unittest.TestCase): 8 | def test_k_way_merge(self): 9 | for array in random_arrays(): 10 | lists = [] 11 | for i in range(10): 12 | lists.append(array[10 * i: (i + 1) * 10]) 13 | lists[-1].sort() 14 | self.assertEqual(k_way_merge(lists), sorted(array)) 15 | -------------------------------------------------------------------------------- /tests/linked_list_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from linkedlist import LinkedList, LinkedListNode 3 | 4 | 5 | class TestLinkedList(unittest.TestCase): 6 | def test_insert(self): 7 | L = LinkedList() 8 | a = LinkedListNode(1) 9 | b = LinkedListNode(4) 10 | c = LinkedListNode(16) 11 | d = LinkedListNode(9) 12 | e = LinkedListNode(25) 13 | L.insert(a) 14 | L.insert(b) 15 | L.insert(c) 16 | L.insert(d) 17 | L.insert(e) 18 | l = [] 19 | x = L.head 20 | while x: 21 | l.append(x) 22 | x = x.next 23 | self.assertEqual(l, [e, d, c, b, a]) 24 | 25 | def test_search(self): 26 | L = LinkedList() 27 | a = LinkedListNode(1) 28 | b = LinkedListNode(4) 29 | c = LinkedListNode(16) 30 | d = LinkedListNode(9) 31 | e = LinkedListNode(25) 32 | L.insert(a) 33 | L.insert(b) 34 | L.insert(c) 35 | L.insert(d) 36 | L.insert(e) 37 | self.assertEqual(L.search(4), b) 38 | 39 | def test_delete(self): 40 | L = LinkedList() 41 | a = LinkedListNode(1) 42 | b = LinkedListNode(4) 43 | c = LinkedListNode(16) 44 | d = LinkedListNode(9) 45 | e = LinkedListNode(25) 46 | L.insert(a) 47 | L.insert(b) 48 | L.insert(c) 49 | L.insert(d) 50 | L.insert(e) 51 | L.delete(b) 52 | l = [] 53 | x = L.head 54 | while x: 55 | l.append(x) 56 | x = x.next 57 | self.assertEqual(l, [e, d, c, a]) 58 | -------------------------------------------------------------------------------- /tests/longest_common_subsequence_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from longest_common_subsequence import lcs_length_one_row, lcs_length 4 | 5 | 6 | class TestLCS(unittest.TestCase): 7 | def test_lcs_length(self): 8 | X = "ABCBDAB" 9 | Y = "BDCABA" 10 | c, b = lcs_length(X, Y) 11 | self.assertEqual(c[len(X), len(Y)], 4) 12 | X = [1, 0, 0, 1, 0, 1, 0, 1] 13 | Y = [0, 1, 0, 1, 1, 0, 1, 1, 0] 14 | c, b = lcs_length(X, Y) 15 | self.assertEqual(c[len(X), len(Y)], 6) 16 | X = "ACCGGTCGAGTGCGCGGAAGCCGGCCGAA" 17 | Y = "GTCGTTCGGAATGCCGTTGCTCTGTAAA" 18 | c, b = lcs_length(X, Y) 19 | self.assertEqual(c[len(X), len(Y)], 20) 20 | 21 | def test_lcs_length_one_row(self): 22 | X = "ABCBDAB" 23 | Y = "BDCABA" 24 | self.assertEqual(lcs_length_one_row(X, Y), 4) 25 | X = [1, 0, 0, 1, 0, 1, 0, 1] 26 | Y = [0, 1, 0, 1, 1, 0, 1, 1, 0] 27 | self.assertEqual(lcs_length_one_row(X, Y), 6) 28 | X = "ACCGGTCGAGTGCGCGGAAGCCGGCCGAA" 29 | Y = "GTCGTTCGGAATGCCGTTGCTCTGTAAA" 30 | self.assertEqual(lcs_length_one_row(X, Y), 20) 31 | -------------------------------------------------------------------------------- /tests/longest_monotonically_increasing_subsequence_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | import unittest 4 | from longest_monotonically_increasing_subsequence import longest_monotonically_increasing_subsequence 5 | 6 | 7 | class TestLMIS(unittest.TestCase): 8 | def test_longest_monotonically_increasing_subsequence(self): 9 | X = [5, 4, 1, 3, 2] 10 | self.assertEqual(longest_monotonically_increasing_subsequence(X), 2) 11 | X = [1, 3, 4, 2, 5] 12 | self.assertEqual(longest_monotonically_increasing_subsequence(X), 4) 13 | X = [1, 3, 10, 5, 3, 4] 14 | self.assertEqual(longest_monotonically_increasing_subsequence(X), 3) 15 | -------------------------------------------------------------------------------- /tests/merge_sort_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | import random 4 | from merge_sort import merge_sort, merge_with_sentinel, merge_without_sentinel, merge_ins_sort_bottom_to_top, \ 5 | merge_ins_sort_top_to_bottom 6 | 7 | 8 | class TestMergeSort(unittest.TestCase): 9 | def test_merge_sort_with_sentinel(self): 10 | for _ in range(100): 11 | array = [random.randint(1, 10000) for _ in range(100)] 12 | array_copy = array[:] 13 | merge_sort(array, merge_with_sentinel) 14 | self.assertEqual(array, sorted(array_copy)) 15 | 16 | def test_merge_sort_without_sentinel(self): 17 | for _ in range(100): 18 | array = [random.randint(1, 10000) for _ in range(100)] 19 | array_copy = array[:] 20 | merge_sort(array, merge_without_sentinel) 21 | self.assertEqual(array, sorted(array_copy)) 22 | 23 | def test_merge_ins_sort(self): 24 | for length in range(100, 200): 25 | array = [random.randint(1, 10000) for _ in range(length)] 26 | array_copy = array[:] 27 | merge_ins_sort_bottom_to_top(array, partition=1) 28 | self.assertEqual(array, sorted(array_copy)) 29 | for length in range(100, 200): 30 | array = [random.randint(1, 10000) for _ in range(length)] 31 | array_copy = array[:] 32 | merge_ins_sort_top_to_bottom(array, sublist_length=15) 33 | self.assertEqual(array, sorted(array_copy)) 34 | -------------------------------------------------------------------------------- /tests/min_gap_tree_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from min_gap_tree import MinGapTree, MinGapNode 4 | 5 | 6 | class TestMinGapTree(unittest.TestCase): 7 | def test_insert_one(self): 8 | T = MinGapTree([50]) 9 | self.wrap(T, 50, float("Inf")) 10 | 11 | def test_insert_two(self): 12 | T = MinGapTree([50, 38]) 13 | self.wrap(T, 50, 12) 14 | self.wrap(T, 38, 12) 15 | 16 | def test_insert_three(self): 17 | T = MinGapTree([50, 38, 31]) 18 | self.wrap(T, 38, 7) 19 | self.wrap(T, 31, 7) 20 | self.wrap(T, 50, float("Inf")) 21 | 22 | def test_insert_four(self): 23 | T = MinGapTree([50, 38, 31, 12]) 24 | self.wrap(T, 38, 7) 25 | self.wrap(T, 31, 7) 26 | self.wrap(T, 50, float("Inf")) 27 | self.wrap(T, 12, 19) 28 | 29 | def test_insert_five(self): 30 | T = MinGapTree([50, 38, 31, 12, 19]) 31 | self.wrap(T, 38, 7) 32 | self.wrap(T, 19, 7) 33 | self.wrap(T, 50, float("Inf")) 34 | self.wrap(T, 12, 7) 35 | self.wrap(T, 31, 7) 36 | 37 | def test_insert_six(self): 38 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 39 | self.wrap(T, 38, 3) 40 | self.wrap(T, 19, 3) 41 | self.wrap(T, 50, float("Inf")) 42 | self.wrap(T, 12, 3) 43 | self.wrap(T, 31, 7) 44 | self.wrap(T, 9, 3) 45 | 46 | def test_delete_one(self): 47 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 48 | T.delete(T.iterative_tree_search(9)) 49 | self.wrap(T, 38, 7) 50 | self.wrap(T, 19, 7) 51 | self.wrap(T, 50, float("Inf")) 52 | self.wrap(T, 12, 7) 53 | self.wrap(T, 31, 7) 54 | 55 | def test_delete_two(self): 56 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 57 | T.delete(T.iterative_tree_search(9)) 58 | T.delete(T.iterative_tree_search(12)) 59 | self.wrap(T, 38, 7) 60 | self.wrap(T, 19, 7) 61 | self.wrap(T, 50, float("Inf")) 62 | self.wrap(T, 31, 7) 63 | 64 | def test_delete_three(self): 65 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 66 | T.delete(T.iterative_tree_search(9)) 67 | T.delete(T.iterative_tree_search(12)) 68 | T.delete(T.iterative_tree_search(19)) 69 | self.wrap(T, 38, 7) 70 | self.wrap(T, 31, 7) 71 | self.wrap(T, 50, float("Inf")) 72 | 73 | def test_delete_four(self): 74 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 75 | T.delete(T.iterative_tree_search(9)) 76 | T.delete(T.iterative_tree_search(12)) 77 | T.delete(T.iterative_tree_search(19)) 78 | T.delete(T.iterative_tree_search(31)) 79 | self.wrap(T, 38, 12) 80 | self.wrap(T, 50, float("Inf")) 81 | 82 | def test_delete_five(self): 83 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 84 | T.delete(T.iterative_tree_search(9)) 85 | T.delete(T.iterative_tree_search(12)) 86 | T.delete(T.iterative_tree_search(19)) 87 | T.delete(T.iterative_tree_search(31)) 88 | T.delete(T.iterative_tree_search(38)) 89 | self.wrap(T, 50, float("Inf")) 90 | 91 | def test_delete_six(self): 92 | T = MinGapTree([50, 38, 31, 12, 19, 9]) 93 | T.delete(T.iterative_tree_search(9)) 94 | T.delete(T.iterative_tree_search(12)) 95 | T.delete(T.iterative_tree_search(19)) 96 | T.delete(T.iterative_tree_search(31)) 97 | T.delete(T.iterative_tree_search(38)) 98 | T.delete(T.iterative_tree_search(50)) 99 | self.assertEqual(T.root, T.nil) 100 | 101 | def wrap(self, tree, node, min_gap): 102 | self.assertEqual(tree.iterative_tree_search(node).min_gap, min_gap) 103 | 104 | 105 | if __name__ == '__main__': 106 | unittest.main() 107 | -------------------------------------------------------------------------------- /tests/min_heap_with_linked_list_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from linkedlist import LinkedList, LinkedListNode 4 | from min_heap_with_linked_list import MinHeap, MinPriorityQueue 5 | 6 | 7 | class TestHeap(unittest.TestCase): 8 | def test_min_heapify(self): 9 | L1 = LinkedList(1) 10 | L2 = LinkedList(2) 11 | L2.insert(LinkedListNode(2)) 12 | L2.insert(LinkedListNode(2)) 13 | L3 = LinkedList(3) 14 | L3.insert(LinkedListNode(3)) 15 | L3.insert(LinkedListNode(3)) 16 | L4 = LinkedList(4) 17 | L4.insert(LinkedListNode(4)) 18 | L5 = LinkedList(5) 19 | L3.insert(LinkedListNode(5)) 20 | L3.insert(LinkedListNode(5)) 21 | L3.insert(LinkedListNode(5)) 22 | h = MinHeap([L5, L1, L2, L3, L4]) 23 | h.min_heapify(0) 24 | self.assertEqual(h, [L1, L3, L2, L5, L4]) 25 | 26 | def test_build_min_heap(self): 27 | L1 = LinkedList(1) 28 | L2 = LinkedList(2) 29 | L2.insert(LinkedListNode(2)) 30 | L2.insert(LinkedListNode(2)) 31 | L3 = LinkedList(3) 32 | L3.insert(LinkedListNode(3)) 33 | L3.insert(LinkedListNode(3)) 34 | L4 = LinkedList(4) 35 | L4.insert(LinkedListNode(4)) 36 | L5 = LinkedList(5) 37 | L3.insert(LinkedListNode(5)) 38 | L3.insert(LinkedListNode(5)) 39 | L3.insert(LinkedListNode(5)) 40 | h = MinHeap([L3, L4, L5, L2, L1]) 41 | h.build_min_heap() 42 | self.assertEqual(h, [L1, L2, L5, L3, L4]) 43 | 44 | def test_heap_minimum(self): 45 | L1 = LinkedList(1) 46 | L1.insert(LinkedListNode(1)) 47 | L1.insert(LinkedListNode(1)) 48 | L2 = LinkedList(2) 49 | L2.insert(LinkedListNode(2)) 50 | L2.insert(LinkedListNode(2)) 51 | L3 = LinkedList(3) 52 | L3.insert(LinkedListNode(3)) 53 | L3.insert(LinkedListNode(3)) 54 | L4 = LinkedList(4) 55 | L4.insert(LinkedListNode(4)) 56 | L5 = LinkedList(5) 57 | L3.insert(LinkedListNode(5)) 58 | L3.insert(LinkedListNode(5)) 59 | L3.insert(LinkedListNode(5)) 60 | q = MinPriorityQueue([L1, L2, L3, L4, L5]) 61 | self.assertEqual(q.heap_minimum().key, 1) 62 | 63 | def test_heap_extract_min(self): 64 | L1 = LinkedList(1) 65 | L1.insert(LinkedListNode(1)) 66 | L1.insert(LinkedListNode(1)) 67 | L2 = LinkedList(2) 68 | L2.insert(LinkedListNode(2)) 69 | L2.insert(LinkedListNode(2)) 70 | L3 = LinkedList(3) 71 | L3.insert(LinkedListNode(3)) 72 | L3.insert(LinkedListNode(3)) 73 | L4 = LinkedList(4) 74 | L4.insert(LinkedListNode(4)) 75 | L5 = LinkedList(5) 76 | L3.insert(LinkedListNode(5)) 77 | L3.insert(LinkedListNode(5)) 78 | L3.insert(LinkedListNode(5)) 79 | q = MinPriorityQueue([L1, L2, L3, L4, L5]) 80 | self.assertEqual(q.heap_extract_min().key, 1) 81 | self.assertEqual(q, [L1, L2, L3, L4, L5]) 82 | self.assertEqual(q.heap_extract_min().key, 1) 83 | self.assertEqual(q, [L2, L4, L3, L5, L5]) 84 | # def test_heap_decrease_key(self): 85 | # a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 86 | # q = MinPriorityQueue(a) 87 | # q.heap_decrease_key(8, 1) 88 | # self.assertEqual(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) 89 | # def test_heap_insert(self): 90 | # a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 91 | # q = MinPriorityQueue(a) 92 | # q.heap_extract_min() 93 | # q.min_heap_insert(0) 94 | # self.assertEqual(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) 95 | -------------------------------------------------------------------------------- /tests/min_priority_queue_using_rb_tree_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from min_priority_queue_using_rb_tree import min_priority_queue 4 | from rb_tree import RbNode 5 | 6 | 7 | class TestMinPriorityQueue(unittest.TestCase): 8 | def test_extract_min(self): 9 | q = min_priority_queue([41, 38, 31, 12, 19, 9]) 10 | self.assertEqual(q.heap_extract_min().key, 9) 11 | self.assertEqual(q.heap_extract_min().key, 12) 12 | self.assertEqual(q.heap_extract_min().key, 19) 13 | self.assertEqual(q.heap_extract_min().key, 31) 14 | self.assertEqual(q.heap_extract_min().key, 38) 15 | self.assertEqual(q.heap_extract_min().key, 41) 16 | 17 | def test_heap_decrease_key(self): 18 | q = min_priority_queue([41, 38, 31, 12, 19, 9]) 19 | q.heap_decrease_key(q.iterative_tree_search(9), 5) 20 | q.heap_decrease_key(q.iterative_tree_search(38), 5) 21 | self.assertEqual(q.heap_extract_min().key, 5) 22 | self.assertEqual(q.heap_extract_min().key, 5) 23 | self.assertEqual(q.heap_extract_min().key, 12) 24 | self.assertEqual(q.heap_extract_min().key, 19) 25 | self.assertEqual(q.heap_extract_min().key, 31) 26 | self.assertEqual(q.heap_extract_min().key, 41) 27 | 28 | def test_heap_insert(self): 29 | q = min_priority_queue([41, 38, 31, 12, 19, 9]) 30 | q.min_heap_insert(RbNode(5, None, None, None, 0)) 31 | q.min_heap_insert(RbNode(38, None, None, None, 0)) 32 | q.min_heap_insert(RbNode(50, None, None, None, 0)) 33 | self.assertEqual(q.heap_extract_min().key, 5) 34 | self.assertEqual(q.heap_extract_min().key, 9) 35 | self.assertEqual(q.heap_extract_min().key, 12) 36 | self.assertEqual(q.heap_extract_min().key, 19) 37 | self.assertEqual(q.heap_extract_min().key, 31) 38 | self.assertEqual(q.heap_extract_min().key, 38) 39 | self.assertEqual(q.heap_extract_min().key, 38) 40 | self.assertEqual(q.heap_extract_min().key, 41) 41 | self.assertEqual(q.heap_extract_min().key, 50) 42 | 43 | 44 | if __name__ == '__main__': 45 | unittest.main() 46 | -------------------------------------------------------------------------------- /tests/most_reliable_path_test.py: -------------------------------------------------------------------------------- 1 | from most_reliable_path import most_reliable_path 2 | import unittest 3 | from graph import Vertex, Graph 4 | 5 | 6 | class TestMostReliablePath(unittest.TestCase): 7 | def test_most_reliable_path(self): 8 | s = Vertex('s') 9 | u = Vertex('u') 10 | v = Vertex('v') 11 | w = Vertex('w') 12 | vertices = [s, u, v, w] 13 | edges = [(s, u), (s, v), (s, w), (u, v), (u, w), (w, u)] 14 | G = Graph(vertices, edges) 15 | probabilities = [0.2, 0.1, 0.15, 0.7, 0.6, 0.9] 16 | re = dict() 17 | for i, j in zip(edges, probabilities): 18 | re[i] = j 19 | 20 | def r(x, y): 21 | return re[(x, y)] 22 | 23 | most_reliable_path(G, r, s) 24 | self.assertEqual([i.p for i in vertices], [None, s, u, s]) 25 | self.assertEqual([round(i.r, 2) for i in vertices], [1, 0.2, 0.14, 0.15]) 26 | most_reliable_path(G, r, u) 27 | self.assertEqual([i.p for i in vertices], [None, None, u, u]) 28 | self.assertEqual([round(i.r, 2) for i in vertices], [0, 1, 0.7, 0.6]) 29 | -------------------------------------------------------------------------------- /tests/partition_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from partition import partition, partition2, partition3 3 | from random_array import random_arrays 4 | 5 | 6 | class TestPartition(unittest.TestCase): 7 | def test_partition(self): 8 | for array in random_arrays(): 9 | pivot_index = partition(array, 0, len(array) - 1) 10 | pivot = array[pivot_index] 11 | self.assertTrue(all(array[i] <= pivot for i in range(pivot_index)) and all( 12 | array[i] > pivot for i in range(pivot_index + 1, len(array)))) 13 | 14 | def test_partition2(self): 15 | a = [2, 8, 7, 1, 4, 5, 6, 4] 16 | partition2(a, 0, 7) 17 | self.assertEqual(a, [2, 1, 4, 4, 7, 5, 6, 8]) 18 | 19 | def test_partition3(self): 20 | for array in random_arrays(): 21 | pivot_index = partition3(array, 0, len(array) - 1) 22 | pivot = array[pivot_index] 23 | self.assertTrue(all(array[i] <= pivot for i in range(pivot_index)) and all( 24 | array[i] > pivot for i in range(pivot_index + 1, len(array)))) 25 | -------------------------------------------------------------------------------- /tests/pointer_tree_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from pointer_tree import pointer_tree, pointer_node 4 | 5 | 6 | class TestOstree(unittest.TestCase): 7 | def test_insert_one(self): 8 | T = pointer_tree([41]) 9 | self.wrap(T, 41, 41, 41, float("-Inf"), float("Inf")) 10 | 11 | def test_insert_two(self): 12 | T = pointer_tree([41, 38]) 13 | self.wrap(T, 41, 38, 41, 38, float("Inf")) 14 | self.wrap(T, 38, 38, 38, float("-Inf"), 41) 15 | 16 | def test_insert_three(self): 17 | T = pointer_tree([41, 38, 31]) 18 | self.wrap(T, 38, 31, 41, 31, 41) 19 | self.wrap(T, 31, 31, 31, float("-Inf"), 38) 20 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 21 | 22 | def test_insert_four(self): 23 | T = pointer_tree([41, 38, 31, 12]) 24 | self.wrap(T, 38, 12, 41, 31, 41) 25 | self.wrap(T, 31, 12, 31, 12, 38) 26 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 27 | self.wrap(T, 12, 12, 12, float("-Inf"), 31) 28 | 29 | def test_insert_five(self): 30 | T = pointer_tree([41, 38, 31, 12, 19]) 31 | self.wrap(T, 38, 12, 41, 31, 41) 32 | self.wrap(T, 19, 12, 31, 12, 31) 33 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 34 | self.wrap(T, 12, 12, 12, float("-Inf"), 19) 35 | self.wrap(T, 31, 31, 31, 19, 38) 36 | 37 | def test_insert_six(self): 38 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 39 | self.wrap(T, 38, 9, 41, 31, 41) 40 | self.wrap(T, 19, 9, 31, 12, 31) 41 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 42 | self.wrap(T, 12, 9, 12, 9, 19) 43 | self.wrap(T, 31, 31, 31, 19, 38) 44 | self.wrap(T, 9, 9, 9, float("-Inf"), 12) 45 | 46 | def test_delete_one(self): 47 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 48 | T.delete(T.iterative_tree_search(9)) 49 | self.wrap(T, 38, 12, 41, 31, 41) 50 | self.wrap(T, 19, 12, 31, 12, 31) 51 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 52 | self.wrap(T, 12, 12, 12, float("-Inf"), 19) 53 | self.wrap(T, 31, 31, 31, 19, 38) 54 | 55 | def test_delete_two(self): 56 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 57 | T.delete(T.iterative_tree_search(9)) 58 | T.delete(T.iterative_tree_search(12)) 59 | self.wrap(T, 38, 19, 41, 31, 41) 60 | self.wrap(T, 19, 19, 31, float("-Inf"), 31) 61 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 62 | self.wrap(T, 31, 31, 31, 19, 38) 63 | 64 | def test_delete_three(self): 65 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 66 | T.delete(T.iterative_tree_search(9)) 67 | T.delete(T.iterative_tree_search(12)) 68 | T.delete(T.iterative_tree_search(19)) 69 | self.wrap(T, 38, 31, 41, 31, 41) 70 | self.wrap(T, 31, 31, 31, float("-Inf"), 38) 71 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 72 | 73 | def test_delete_four(self): 74 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 75 | T.delete(T.iterative_tree_search(9)) 76 | T.delete(T.iterative_tree_search(12)) 77 | T.delete(T.iterative_tree_search(19)) 78 | T.delete(T.iterative_tree_search(31)) 79 | self.wrap(T, 38, 38, 41, float("-Inf"), 41) 80 | self.wrap(T, 41, 41, 41, 38, float("Inf")) 81 | 82 | def test_delete_five(self): 83 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 84 | T.delete(T.iterative_tree_search(9)) 85 | T.delete(T.iterative_tree_search(12)) 86 | T.delete(T.iterative_tree_search(19)) 87 | T.delete(T.iterative_tree_search(31)) 88 | T.delete(T.iterative_tree_search(38)) 89 | self.wrap(T, 41, 41, 41, float("-Inf"), float("Inf")) 90 | 91 | def test_delete_six(self): 92 | T = pointer_tree([41, 38, 31, 12, 19, 9]) 93 | T.delete(T.iterative_tree_search(9)) 94 | T.delete(T.iterative_tree_search(12)) 95 | T.delete(T.iterative_tree_search(19)) 96 | T.delete(T.iterative_tree_search(31)) 97 | T.delete(T.iterative_tree_search(38)) 98 | T.delete(T.iterative_tree_search(41)) 99 | self.assertEqual(T.root, T.nil) 100 | 101 | def wrap(self, tree, node, minimum, maximum, predecessor, successor): 102 | self.assertEqual(tree.iterative_tree_search(node).minimum.key, minimum) 103 | self.assertEqual(tree.iterative_tree_search(node).maximum.key, maximum) 104 | self.assertEqual(tree.iterative_tree_search( 105 | node).predecessor.key, predecessor) 106 | self.assertEqual(tree.iterative_tree_search( 107 | node).successor.key, successor) 108 | 109 | 110 | if __name__ == '__main__': 111 | unittest.main() 112 | -------------------------------------------------------------------------------- /tests/polygon_area_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from polygon_area import polygon_area 3 | 4 | 5 | class TestPolygonArea(unittest.TestCase): 6 | def test_rectangle_area(self): 7 | rectangle = ((0, 0), (0, 2), (2, 2), (2, 0)) 8 | self.assertEqual(polygon_area(rectangle), 4) 9 | 10 | def test_triangle_area(self): 11 | triangle = ((0, 0), (5, 0), (2.5, 5)) 12 | self.assertEqual(polygon_area(triangle), 12.5) 13 | -------------------------------------------------------------------------------- /tests/priority_queue_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from priority_queue import MaxPriorityQueue, MinPriorityQueue 3 | 4 | 5 | class TestMaxPriorityQueue(unittest.TestCase): 6 | def test_init(self): 7 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 8 | q = MaxPriorityQueue(a) 9 | self.assertEqual(q, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) 10 | 11 | def test_heap_maximum(self): 12 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 13 | self.assertEqual(MaxPriorityQueue(a).heap_maximum(), 16) 14 | 15 | def test_heap_extract_max(self): 16 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 17 | h = MaxPriorityQueue(a) 18 | self.assertEqual(h.heap_extract_max(), 16) 19 | self.assertEqual(h, [14, 8, 10, 4, 7, 9, 3, 2, 1, 1]) 20 | 21 | def test_heap_increase_key(self): 22 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 23 | h = MaxPriorityQueue(a) 24 | h.heap_increase_key(8, 15) 25 | self.assertEqual(h, [16, 15, 10, 14, 7, 9, 3, 2, 8, 1]) 26 | 27 | def test_heap_insert(self): 28 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 29 | queue = MaxPriorityQueue(a) 30 | queue.heap_extract_max() 31 | queue.max_heap_insert(100) 32 | self.assertEqual(queue, [100, 14, 10, 4, 8, 9, 3, 2, 1, 7]) 33 | 34 | def test_heap_delete(self): 35 | a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 36 | h = MaxPriorityQueue(a) 37 | h.heap_delete(4) 38 | self.assertEqual(h[0:h.heap_size], [16, 14, 10, 8, 1, 9, 3, 2, 4]) 39 | h.heap_delete(2) 40 | self.assertEqual(h[0:h.heap_size], [16, 14, 9, 8, 1, 4, 3, 2]) 41 | h.heap_delete(0) 42 | self.assertEqual(h[0:h.heap_size], [14, 8, 9, 2, 1, 4, 3]) 43 | h.heap_delete(5) 44 | self.assertEqual(h[0:h.heap_size], [14, 8, 9, 2, 1, 3]) 45 | h.heap_delete(3) 46 | self.assertEqual(h[0:h.heap_size], [14, 8, 9, 3, 1]) 47 | h.heap_delete(1) 48 | self.assertEqual(h[0:h.heap_size], [14, 3, 9, 1]) 49 | h.heap_delete(3) 50 | self.assertEqual(h[0:h.heap_size], [14, 3, 9]) 51 | h.heap_delete(2) 52 | self.assertEqual(h[0:h.heap_size], [14, 3]) 53 | h.heap_delete(1) 54 | self.assertEqual(h[0:h.heap_size], [14]) 55 | h.heap_delete(0) 56 | self.assertEqual(h[0:h.heap_size], []) 57 | 58 | 59 | class TestMinPriorityQueue(unittest.TestCase): 60 | def test_init(self): 61 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 62 | q = MinPriorityQueue(a) 63 | self.assertEqual(q, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) 64 | 65 | def test_heap_minimum(self): 66 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 67 | self.assertEqual(MinPriorityQueue(a).heap_minimum(), 1) 68 | 69 | def test_heap_extract_min(self): 70 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 71 | q = MinPriorityQueue(a) 72 | self.assertEqual(q.heap_extract_min(), 1) 73 | self.assertEqual(q, [2, 4, 3, 10, 7, 8, 9, 16, 14, 16]) 74 | 75 | def test_heap_decrease_key(self): 76 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 77 | q = MinPriorityQueue(a) 78 | q.heap_decrease_key(8, 1) 79 | self.assertEqual(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) 80 | 81 | def test_heap_insert(self): 82 | a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] 83 | q = MinPriorityQueue(a) 84 | q.heap_extract_min() 85 | q.min_heap_insert(0) 86 | self.assertEqual(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) 87 | -------------------------------------------------------------------------------- /tests/quicksort_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from partition import partition, partition2, partition3 3 | import random 4 | from quicksort import quicksort, randomized_quicksort 5 | 6 | 7 | class TestQuickSort(unittest.TestCase): 8 | def test_quicksort(self): 9 | for _ in range(100): 10 | array = [random.randint(1, 10000) for _ in range(100)] 11 | array_copy = array[:] 12 | quicksort(array, 0, len(array) - 1, partition) 13 | array_copy.sort() 14 | self.assertEqual(array, array_copy) 15 | for _ in range(100): 16 | array = [random.randint(1, 10000) for _ in range(100)] 17 | array_copy = array[:] 18 | quicksort(array, 0, len(array) - 1, partition2) 19 | array_copy.sort() 20 | self.assertEqual(array, array_copy) 21 | for _ in range(100): 22 | array = [random.randint(1, 10000) for _ in range(100)] 23 | array_copy = array[:] 24 | quicksort(array, 0, len(array) - 1, partition3) 25 | array_copy.sort() 26 | self.assertEqual(array, array_copy) 27 | 28 | def test_randomized_quicksort(self): 29 | for _ in range(100): 30 | array = [random.randint(1, 10000) for _ in range(100)] 31 | array_copy = array[:] 32 | randomized_quicksort(array, 0, len(array) - 1) 33 | array_copy.sort() 34 | self.assertEqual(array, array_copy) 35 | -------------------------------------------------------------------------------- /tests/randomized_select_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from randomized_select import randomized_select 3 | 4 | 5 | class TestRandSelect(unittest.TestCase): 6 | def test_randomize_select_distinct(self): 7 | a = [10, 11, 5, 3, 2, 6, 0, 8, 100, 50] 8 | self.assertEqual(randomized_select(a, 0, 9, 5), 6) 9 | 10 | def test_randomize_select_duplicate(self): 11 | a = [10, 11, 5, 8, 2, 6, 8, 8, 100, 50] 12 | self.assertEqual(randomized_select(a, 0, 9, 4), 8) 13 | self.assertEqual(randomized_select(a, 0, 9, 5), 8) 14 | self.assertEqual(randomized_select(a, 0, 9, 6), 8) 15 | -------------------------------------------------------------------------------- /tests/selection_sort_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | import unittest 5 | from random_array import random_arrays 6 | from selection_sort import selection_sort 7 | 8 | 9 | class TestSelectionSort(unittest.TestCase): 10 | def test_selection_sort(self): 11 | for array in random_arrays(): 12 | sorted_array = sorted(array) 13 | selection_sort(array) 14 | self.assertEqual(array, sorted_array) 15 | -------------------------------------------------------------------------------- /tests/test_binary_add.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from binary_add import binary_add 3 | 4 | 5 | class Test(TestCase): 6 | def test_binary_add(self): 7 | array1 = [1, 0, 1, 0] 8 | array2 = [0, 1, 1, 0] 9 | self.assertEqual(binary_add(array1, array2), [1, 0, 0, 0, 0]) 10 | -------------------------------------------------------------------------------- /tests/test_deque.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | 3 | from Queue import FullException, EmptyException 4 | from deque import Deque 5 | 6 | 7 | class TestDeque(TestCase): 8 | def test_enqueue_tail_and_dequeue_head(self): 9 | deque = Deque(3) 10 | deque.enqueue_tail(1) 11 | deque.enqueue_tail(2) 12 | with self.assertRaises(FullException): 13 | deque.enqueue_tail(3) 14 | self.assertEqual(1, deque.dequeue_head()) 15 | self.assertEqual(2, deque.dequeue_head()) 16 | with self.assertRaises(EmptyException): 17 | deque.dequeue_head() 18 | 19 | def test_enqueue_head_and_dequeue_tail(self): 20 | deque = Deque(3) 21 | deque.enqueue_head(1) 22 | deque.enqueue_head(2) 23 | with self.assertRaises(FullException): 24 | deque.enqueue_head(3) 25 | self.assertEqual(1, deque.dequeue_tail()) 26 | self.assertEqual(2, deque.dequeue_tail()) 27 | with self.assertRaises(EmptyException): 28 | deque.dequeue_tail() 29 | 30 | def test_enqueue_tail_and_dequeue_tail(self): 31 | deque = Deque(3) 32 | deque.enqueue_tail(1) 33 | deque.enqueue_tail(2) 34 | self.assertEqual(2, deque.dequeue_tail()) 35 | self.assertEqual(1, deque.dequeue_tail()) 36 | with self.assertRaises(EmptyException): 37 | deque.dequeue_tail() 38 | with self.assertRaises(EmptyException): 39 | deque.dequeue_head() 40 | 41 | def test_enqueue_head_and_dequeue_head(self): 42 | deque = Deque(3) 43 | deque.enqueue_head(1) 44 | deque.enqueue_head(2) 45 | self.assertEqual(2, deque.dequeue_head()) 46 | self.assertEqual(1, deque.dequeue_head()) 47 | with self.assertRaises(EmptyException): 48 | deque.dequeue_tail() 49 | with self.assertRaises(EmptyException): 50 | deque.dequeue_head() 51 | -------------------------------------------------------------------------------- /tests/test_dynamic_array.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from dynamic_array import DynamicArray 3 | 4 | 5 | class TestDynamicArray(TestCase): 6 | def test_add_and_get_and_size(self): 7 | dynamic_array = DynamicArray(2) 8 | self.assertEqual(0, dynamic_array.size()) 9 | dynamic_array.add(1) 10 | dynamic_array.add(2) 11 | dynamic_array.add(3) 12 | self.assertEqual(3, dynamic_array.size()) 13 | self.assertEqual(1, dynamic_array.get(0)) 14 | self.assertEqual(2, dynamic_array.get(1)) 15 | self.assertEqual(3, dynamic_array.get(2)) 16 | -------------------------------------------------------------------------------- /tests/test_euclid.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | from unittest import TestCase 4 | 5 | from euclid import euclid 6 | 7 | 8 | class TestEuclid(TestCase): 9 | def test_gcd(self): 10 | self.assertEqual(euclid(10, 3), 1) 11 | self.assertEqual(euclid(10, 4), 2) 12 | self.assertEqual(euclid(10, 1), 1) 13 | self.assertEqual(euclid(10, 5), 5) 14 | -------------------------------------------------------------------------------- /tests/test_gcd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | from unittest import TestCase 4 | 5 | from gcd import gcd 6 | 7 | 8 | class TestGcd(TestCase): 9 | def test_gcd(self): 10 | self.assertEqual(gcd(10, 3), 1) 11 | self.assertEqual(gcd(10, 4), 2) 12 | self.assertEqual(gcd(10, 1), 1) 13 | self.assertEqual(gcd(10, 5), 5) 14 | -------------------------------------------------------------------------------- /tests/test_lowest_common_multiple.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from lowest_common_multiple import lcm 3 | 4 | 5 | class LcmTest(TestCase): 6 | def test_lcm(self): 7 | self.assertEqual(lcm(10, 1), 10) 8 | self.assertEqual(lcm(10, 8), 40) 9 | self.assertEqual(lcm(15, 9), 45) 10 | -------------------------------------------------------------------------------- /tests/test_merge.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from merge import merge_without_sentinel, merge_with_sentinel 3 | from random_array import random_arrays 4 | 5 | 6 | class MergeTest(TestCase): 7 | def test_merge_with_sentinel(self): 8 | for array in random_arrays(): 9 | left_array = array[:len(array) // 2] 10 | right_array = array[len(array) // 2:] 11 | left_array.sort() 12 | right_array.sort() 13 | result_array = left_array + right_array 14 | merge_with_sentinel(result_array, 0, len(array) // 2 - 1, len(array) - 1) 15 | self.assertEqual(result_array, sorted(array)) 16 | 17 | def test_merge_without_sentinel(self): 18 | for array in random_arrays(): 19 | left_array = array[:len(array) // 2] 20 | right_array = array[len(array) // 2:] 21 | left_array.sort() 22 | right_array.sort() 23 | result_array = left_array + right_array 24 | merge_without_sentinel(result_array, 0, len(array) // 2 - 1, len(array) - 1) 25 | self.assertEqual(result_array, sorted(array)) 26 | -------------------------------------------------------------------------------- /tests/test_pow.py: -------------------------------------------------------------------------------- 1 | import math 2 | import random 3 | from unittest import TestCase 4 | from pow import pow1, pow2 5 | 6 | 7 | class Test(TestCase): 8 | def test_pow1(self): 9 | x = random.randint(1, 10) 10 | for n in range(10): 11 | self.assertEqual(pow1(x, n), math.pow(x, n)) 12 | 13 | def test_pow2(self): 14 | x = random.randint(1, 10) 15 | for n in range(10): 16 | self.assertEqual(pow2(x, n), math.pow(x, n)) 17 | -------------------------------------------------------------------------------- /tests/test_queue.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from Queue import Queue, EmptyException, FullException 3 | 4 | 5 | class TestQueue(TestCase): 6 | def test_enqueue_and_dequeue(self): 7 | queue = Queue(3) 8 | queue.enqueue(1) 9 | queue.enqueue(2) 10 | with self.assertRaises(FullException): 11 | queue.enqueue(3) 12 | self.assertEqual(1, queue.dequeue()) 13 | self.assertEqual(2, queue.dequeue()) 14 | with self.assertRaises(EmptyException): 15 | queue.dequeue() 16 | 17 | def test_empty(self): 18 | queue = Queue(2) 19 | self.assertTrue(queue.empty()) 20 | 21 | def test_full(self): 22 | queue = Queue(2) 23 | queue.enqueue(1) 24 | self.assertTrue(queue.full()) 25 | queue = Queue(1) 26 | self.assertTrue(queue.full()) 27 | 28 | def test_capacity(self): 29 | queue = Queue(5) 30 | self.assertEqual(4, queue.capacity()) 31 | -------------------------------------------------------------------------------- /tests/two_sum_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | from random_array import random_arrays 3 | import random 4 | from two_sum import two_sum 5 | 6 | 7 | class TestInsertionSort(unittest.TestCase): 8 | def test_two_sum(self): 9 | for array in random_arrays(array_num=1000, array_size=10, array_lowerbound=1, array_upperbound=20): 10 | x = random.randint(1, 100) 11 | n = len(array) 12 | result = False 13 | for i in range(n): 14 | for j in range(i + 1, n): 15 | if array[i] + array[j] == x: 16 | result = True 17 | self.assertEqual(two_sum(x, array), result) 18 | -------------------------------------------------------------------------------- /tests/universal_sink_test.py: -------------------------------------------------------------------------------- 1 | import universal_sink as us 2 | import unittest 3 | import numpy 4 | 5 | 6 | class TestRbtree(unittest.TestCase): 7 | def test_universal_sink(self): 8 | data = numpy.array( 9 | [[0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0], [1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 0], [1, 0, 0, 1, 0, 0], 10 | [1, 0, 0, 0, 0, 1]]) 11 | self.assertEqual(us.universal_sink(data), 1) 12 | data = numpy.array( 13 | [[0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [1, 1, 0, 0, 1, 1], [1, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 0], 14 | [1, 1, 0, 0, 0, 1]]) 15 | self.assertEqual(us.universal_sink(data), 2) 16 | data = numpy.array( 17 | [[0, 1, 1, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0], [1, 1, 1, 0, 0, 0], [1, 1, 1, 1, 0, 0], 18 | [1, 1, 1, 0, 0, 1]]) 19 | self.assertEqual(us.universal_sink(data), 3) 20 | data = numpy.array( 21 | [[0, 1, 0, 1, 0, 0], [0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1], [0, 0, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], 22 | [0, 0, 0, 1, 0, 1]]) 23 | self.assertEqual(us.universal_sink(data), 4) 24 | data = numpy.array( 25 | [[0, 1, 1, 0, 1, 0], [0, 0, 1, 0, 1, 0], [0, 0, 0, 0, 1, 0], [1, 1, 1, 0, 1, 0], [0, 0, 0, 0, 0, 0], 26 | [1, 1, 1, 0, 1, 1]]) 27 | self.assertEqual(us.universal_sink(data), 5) 28 | data = numpy.array( 29 | [[0, 1, 1, 0, 1, 1], [0, 0, 1, 0, 1, 1], [0, 0, 0, 0, 1, 1], [1, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1], 30 | [0, 0, 0, 0, 0, 0]]) 31 | self.assertEqual(us.universal_sink(data), 6) 32 | -------------------------------------------------------------------------------- /tests/vEB_tree_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import unittest 4 | from vEB_tree import vEB_node 5 | 6 | 7 | class testVEB(unittest.TestCase): 8 | def test_vEB(self): 9 | v = vEB_node(2 ** 8) 10 | l = [1, 4, 50, 30, 100, 201] 11 | for i in l: 12 | v.insert(i) 13 | for i in l: 14 | self.assertEqual(v.member(i), True) 15 | self.assertEqual(v.member(2), False) 16 | self.assertEqual(v.member(3), False) 17 | v.delete(1) 18 | self.assertEqual(v.member(1), False) 19 | v.delete(100) 20 | self.assertEqual(v.member(100), False) 21 | -------------------------------------------------------------------------------- /tests/wrestlers_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import unittest 3 | from wrestlers import wrestlers 4 | 5 | 6 | class TestWrestler(unittest.TestCase): 7 | def testBfs(self): 8 | wrestlersList = [1, 2, 3, 4, 5, 6, 7, 8] 9 | rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), (3, 6), 10 | (5, 6), (5, 7), (5, 8), (6, 8), (7, 8)] 11 | self.assertEqual(wrestlers(wrestlersList, rivalriesList), False) 12 | rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), 13 | (3, 6), (5, 7), (5, 8), (6, 8), (7, 8)] 14 | self.assertEqual(wrestlers(wrestlersList, rivalriesList), False) 15 | rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), 16 | (3, 6), (5, 7), (5, 8), (6, 8)] 17 | self.assertEqual(wrestlers(wrestlersList, rivalriesList), True) 18 | -------------------------------------------------------------------------------- /three_points_colinear.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from heap import MaxHeap 4 | 5 | 6 | class vector: 7 | def __init__(self, p1, p2, p1_index=0, p2_index=0): 8 | # gurantee that the polar angle of this Vector with respect to the origin point is in the range [0, pi) 9 | if p1[1] > p2[1]: 10 | self.x = p1[0] - p2[0] 11 | self.y = p1[1] - p2[1] 12 | elif p1[1] == p2[1]: 13 | self.y = 0 14 | self.x = abs(p1[0] - p2[0]) 15 | else: 16 | self.x = p2[0] - p1[0] 17 | self.y = p2[1] - p1[1] 18 | self.p1 = p1 19 | self.p2 = p2 20 | self.p1_index = p1_index 21 | self.p2_index = p2_index 22 | 23 | def cross_product(self, v): 24 | return self.x * v.y - v.x * self.y 25 | 26 | def __lt__(self, v): 27 | return self.cross_product(v) > 0 28 | 29 | def __gt__(self, v): 30 | return self.cross_product(v) < 0 31 | 32 | def __eq__(self, v): 33 | return self.cross_product(v) == 0 34 | 35 | def __le__(self, v): 36 | return self.cross_product(v) >= 0 37 | 38 | def __ge__(self, v): 39 | return self.cross_product(v) <= 0 40 | 41 | 42 | def three_points_colinear(points_list): 43 | """ to determine whether any three points in a set of n points are colinear""" 44 | n = len(points_list) 45 | vectors_list = [] 46 | for i in range(n): 47 | for j in range(i + 1, n): 48 | vectors_list.append(vector(points_list[i], points_list[j], i, j)) 49 | v0 = vector((1, 0), (0, 0)) 50 | heap_vectors = MaxHeap(vectors_list) 51 | heap_vectors.heapsort() 52 | status = [False] * n 53 | v = heap_vectors[0] 54 | status[v.p1_index] = True 55 | status[v.p2_index] = True 56 | stack = [] 57 | stack.append(v.p1_index) 58 | stack.append(v.p2_index) 59 | for i in range(1, len(heap_vectors)): 60 | v = heap_vectors[i] 61 | if v == heap_vectors[i - 1]: 62 | if status[v.p1_index]: 63 | return True 64 | elif status[v.p2_index]: 65 | return True 66 | else: 67 | status[v.p1_index] = True 68 | status[v.p2_index] = True 69 | stack.append(v.p1_index) 70 | stack.append(v.p2_index) 71 | else: 72 | print(len(stack)) 73 | print(stack) 74 | for i in range(len(stack)): 75 | status[stack.pop()] = False 76 | stack.append(v.p1_index) 77 | stack.append(v.p2_index) 78 | return False 79 | -------------------------------------------------------------------------------- /three_sum.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | 5 | def three_sum(array): 6 | """ 7 | Given an array `array` of n integers, find one triplet 8 | in the array which gives the sum of zero. 9 | 10 | `array` must be in increasing order 11 | """ 12 | n = len(array) 13 | for i in range(n - 2): 14 | j = i + 1 15 | k = n - 1 16 | 17 | while k >= j: 18 | if array[i] + array[j] + array[k] == 0: 19 | return array[i], array[j], array[k] 20 | elif array[i] + array[j] + array[k] > 0: 21 | k = k - 1 22 | else: 23 | j = j + 1 24 | -------------------------------------------------------------------------------- /two_sum.py: -------------------------------------------------------------------------------- 1 | def two_sum(x: int, array: list): 2 | """ 3 | an algorithm that, given a set S of n integers and another integer x, 4 | determines whether or not there exist two elements in S whose sum is exactly x. 5 | :param x: 6 | :param array: 7 | :return: 8 | """ 9 | sorted_array = sorted(array) 10 | i = 0 11 | j = len(array) - 1 12 | while i < j: 13 | sum = sorted_array[i] + sorted_array[j] 14 | if sum == x: 15 | return True 16 | elif sum < x: 17 | i = i + 1 18 | else: 19 | j = j - 1 20 | return False 21 | -------------------------------------------------------------------------------- /universal_sink.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | def universal_sink(M): 5 | """ 6 | An algorithm to determine whether a directed graph G contains 7 | a universal sink---a vertex with in-degree |V| - 1 and 8 | out-degree 0---in time O(V), given an adjacency matrix for G 9 | 10 | M: numpy matrix, the adjacency matrix for the graph 11 | rtype: vertex index if G contains a universal sink, otherwise, return None 12 | """ 13 | 14 | return universal_sink_aux(M, 1) 15 | 16 | 17 | def universal_sink_aux(M, i): 18 | """ 19 | M: numpy matrix 20 | i: vertex index 21 | """ 22 | size = M.shape[0] 23 | j = i 24 | while True: 25 | if j > size or M[i - 1][j - 1] != 0: 26 | break 27 | j = j + 1 28 | if j > size: 29 | for j in range(1, i): 30 | if M[i - 1][j - 1] != 0: 31 | return None 32 | for j in range(1, size + 1): 33 | if M[j - 1][i - 1] == 0 and j != i: 34 | return None 35 | return i 36 | else: 37 | return universal_sink_aux(M, j) 38 | -------------------------------------------------------------------------------- /vEB_tree.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import math 4 | 5 | 6 | class vEB_node: 7 | def __init__(self, u): 8 | """u must be exact power of 2, as required by CLRS; otherwise, the behavior is undefined""" 9 | self.u = u 10 | self.min = None 11 | self.max = None 12 | if u > 2: 13 | self.root = int(math.sqrt(u)) 14 | self.cluster = [0] * self.root 15 | self.summary = vEB_node(self.root) 16 | for i in range(self.root): 17 | self.cluster[i] = vEB_node(self.root) 18 | 19 | def high(self, x): 20 | return x // self.root 21 | 22 | def low(self, x): 23 | return x % self.root 24 | 25 | def index(self, x, y): 26 | return x * self.root + y 27 | 28 | def member(self, x): 29 | if self.min == x or self.max == x: 30 | return True 31 | elif self.u == 2: 32 | return False 33 | else: 34 | return self.cluster[self.high(x)].member(self.low(x)) 35 | 36 | def successor(self, x): 37 | if self.u == 2: 38 | if x == 0 and self.max == 1: 39 | return 1 40 | else: 41 | return None 42 | elif self.min is not None and x < self.min: 43 | return self.min 44 | else: 45 | max_low = self.cluster[self.high(x)].max 46 | if max_low is not None and self.low(x) < max_low: 47 | offset = self.cluster[self.high(x)].successor(self.low(x)) 48 | return self.index(self.high(x), offset) 49 | else: 50 | succ_cluster = self.summary.successor(self.high(x)) 51 | if succ_cluster is None: 52 | return None 53 | else: 54 | offset = self.cluster[succ_cluster].min 55 | return self.index(succ_cluster, offset) 56 | 57 | def empty_tree_insert(self, x): 58 | self.min = x 59 | self.max = x 60 | 61 | def insert(self, x): 62 | if self.min is None: 63 | self.empty_tree_insert(x) 64 | elif (x == self.min) or (x == self.max): 65 | return 66 | else: 67 | if x < self.min: 68 | x, self.min = self.min, x 69 | if self.u > 2: 70 | if self.cluster[self.high(x)].min is None: 71 | self.summary.insert(self.high(x)) 72 | self.cluster[self.high(x)].empty_tree_insert(self.low(x)) 73 | else: 74 | self.cluster[self.high(x)].insert(self.low(x)) 75 | if x > self.max: 76 | self.max = x 77 | 78 | def delete(self, x): 79 | # print( "u = {}, x = {}".format(self.u, x)) 80 | if self.min == self.max: 81 | # print( "min = {}, max = {}".format(self.min, self.max)) 82 | if x == self.min: 83 | self.min = None 84 | self.max = None 85 | elif self.u == 2: 86 | if x == 0: 87 | self.min = 1 88 | else: 89 | self.max = 0 90 | elif x < self.min: 91 | return 92 | else: 93 | if x == self.min: 94 | first_cluster = self.summary.min 95 | x = self.index(first_cluster, self.cluster[first_cluster].min) 96 | self.min = x 97 | self.cluster[self.high(x)].delete(self.low(x)) 98 | if self.cluster[self.high(x)].min is None: 99 | self.summary.delete(self.high(x)) 100 | if x == self.max: 101 | summary_max = self.summary.max 102 | if summary_max is None: 103 | self.max = self.min 104 | else: 105 | self.max = self.index( 106 | summary_max, self.cluster[summary_max].max) 107 | elif x == self.max: 108 | self.max = self.index( 109 | self.high(x), self.cluster[self.high(x)].max) 110 | 111 | def print_veb(self): 112 | if self.u == 2: 113 | print("u = {}, min = {}, max = {}".format( 114 | self.u, self.min, self.max)) 115 | else: 116 | print("u = {}, min = {}, max = {}".format( 117 | self.u, self.min, self.max)) 118 | print("Summary: \t", ) 119 | self.summary.print_veb() 120 | print() 121 | for i in range(self.root): 122 | self.cluster[i].print_veb() 123 | print() 124 | -------------------------------------------------------------------------------- /wrestlers.py: -------------------------------------------------------------------------------- 1 | from queue import Queue 2 | from graph import Graph, Vertex 3 | 4 | 5 | def wrestlers(wrestlersList, rivalriesList): 6 | """ 7 | There are two types of professional wrestlers: "babyfaces" 8 | ("good guys") and "heels" ("bad guys"). Between any pair of 9 | professional wrestlers, there may or may not be a rivalry. 10 | Given a list of professional wrestlers and a list of pairs of 11 | wrestlers for which there are rivalries, determine whether it is 12 | possible to designate some of the wrestlers as babyfaces and There 13 | remainder as heels such that each rivalry is between a babyfaces 14 | and a heel. 15 | """ 16 | d = dict() 17 | vertices = [None] * len(wrestlersList) 18 | edges = [None] * len(rivalriesList) 19 | for i in range(len(wrestlersList)): 20 | vertices[i] = Vertex(wrestlersList[i]) 21 | d[wrestlersList[i]] = vertices[i] 22 | 23 | for i in range(len(rivalriesList)): 24 | w1, w2 = rivalriesList[i] 25 | edges[i] = (d[w1], d[w2]) 26 | g = Graph(vertices, edges, False) 27 | 28 | for u in g.vertices: 29 | u.type = 0 30 | for u in g.vertices: 31 | if u.type == 0: 32 | if not _bfs(g, u): 33 | return False 34 | return True 35 | 36 | 37 | def _bfs(g, s): 38 | s.type = 1 39 | q = Queue(2 * len(g.vertices)) 40 | q.put(s) 41 | while not q.empty(): 42 | u = q.get() 43 | for v in g.adj[u]: 44 | if u.type == v.type: 45 | return False 46 | elif v.type == 0: 47 | if u.type == 1: 48 | v.type = 2 49 | else: 50 | v.type = 1 51 | q.put(v) 52 | return True 53 | --------------------------------------------------------------------------------