diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..e7e9d11 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,2 @@ +# Default ignored files +/workspace.xml diff --git a/.idea/algorithm.iml b/.idea/algorithm.iml new file mode 100644 index 0000000..8b8c395 --- /dev/null +++ b/.idea/algorithm.iml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dbnavigator.xml b/.idea/dbnavigator.xml new file mode 100644 index 0000000..51e620f --- /dev/null +++ b/.idea/dbnavigator.xml @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..15a15b2 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d56657a --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Bellman_Ford_matrix.py b/Bellman_Ford_matrix.py index 76739f2..21d547d 100644 --- a/Bellman_Ford_matrix.py +++ b/Bellman_Ford_matrix.py @@ -1,4 +1,3 @@ -import numpy as np def Bellman_Ford_matrix(W, s): n = W.shape[0] @@ -11,38 +10,41 @@ def Bellman_Ford_matrix(W, s): if d[j - 1] > d[i - 1] + W[i - 1, j - 1]: d[j - 1] = d[i - 1] + W[i - 1, j - 1] p[j - 1] = i - print d - print p + print(d) + print(p) return d, p + def extend_shortest_paths(L, W): n = W.shape[0] LW = [float("Inf")] * n - for j in range(0, n): - for k in range(0, n): + for j in range(n): + for k in range(n): LW[j] = min(LW[j], L[k] + W[k, j]) return LW + def slow_all_pairs_shortest_paths(W, s): n = W.shape[0] L = [0] * n - for i in range(0, n): + for i in range(n): if i + 1 == s: L[i] = 0 else: L[i] = float("Inf") - print L + print(L) for m in range(1, n): L = extend_shortest_paths(L, W) - print L + print(L) return L + def extend_shortest_paths_with_predecessor_subgraph(s, L, P, W): n = W.shape[0] LW = [float("Inf")] * n - PP = [None] * n - for j in range(0, n): - for k in range(0, n): + PP = [None] * n + for j in range(n): + for k in range(n): if LW[j] > L[k] + W[k, j]: LW[j] = L[k] + W[k, j] PP[j] = k + 1 @@ -50,6 +52,7 @@ def extend_shortest_paths_with_predecessor_subgraph(s, L, P, W): PP[j] = P[j] return LW, PP + def slow_all_pairs_shortest_paths_with_predecessor_subgraph(W, s): n = W.shape[0] L = [float("Inf")] * n @@ -57,10 +60,11 @@ def slow_all_pairs_shortest_paths_with_predecessor_subgraph(W, s): P = [None] * n for m in range(1, n): L, P = extend_shortest_paths_with_predecessor_subgraph(s, L, P, W) - print L - print P + print(L) + print(P) return L, P + def faster_all_pairs_shortest_paths(W): n = W.shape[0] L = W @@ -68,8 +72,6 @@ def faster_all_pairs_shortest_paths(W): while m < n - 1: L = extend_shortest_paths(L, L) m = 2 * m - print m - print L + print(m) + print(L) return Ld, p - - diff --git a/Bellman_Ford_matrix_test.py b/Bellman_Ford_matrix_test.py deleted file mode 100644 index 3e4dbdd..0000000 --- a/Bellman_Ford_matrix_test.py +++ /dev/null @@ -1,14 +0,0 @@ -from Bellman_Ford_matrix import Bellman_Ford_matrix, slow_all_pairs_shortest_paths -import unittest -import numpy -class TestBellmanFordMatrix(unittest.TestCase): - def test_Bellman_Ford_matrix(self): - W = numpy.array([[ float("Inf"), 6., 7., float("Inf"), float("Inf")], [ float("Inf"), float("Inf"), 8., 5., -4.], [ float("Inf"), float("Inf"), float("Inf"), -3., 9.], [ float("Inf"), -2., float("Inf"), float("Inf"), float("Inf")], [ 2., float("Inf"), float("Inf"), 7., float("Inf")]]) - d, p = Bellman_Ford_matrix(W, 1) - self.assertEquals(d, [0, 2.0, 7.0, 4.0, -2.0]) - self.assertEquals(p, [None, 4, 1, 3, 2]) - def test_slow_all_pairs_shortest_paths(self): - W = numpy.array([[ 0, 6., 7., float("Inf"), float("Inf")], [ float("Inf"), 0, 8., 5., -4.], [ float("Inf"), float("Inf"), 0, -3., 9.], [ float("Inf"), -2., float("Inf"), 0, float("Inf")], [ 2., float("Inf"), float("Inf"), 7., 0]]) - L = slow_all_pairs_shortest_paths(W, 1) - print L - self.assertEquals(L, [0, 2.0, 7.0, 4.0, -2.0]) diff --git a/BinSearch.c b/BinSearch.c deleted file mode 100644 index e096370..0000000 --- a/BinSearch.c +++ /dev/null @@ -1,34 +0,0 @@ -//BinSearch(A, first, end, x) -// while length >= 0 -// inter = (first + end) / 2 -// if x == A[inter] -// return inter + 1 -// else if x < A[inter] -// end = inter - 1 -// else -// first = inter + 1 -// length = end - first -// return -1 - -int BinSearch(int A[], int first, int end, int x) { - int length = end - first; - int inter; - - while (length >= 0) { - inter = (first + end) / 2; - if (x == A[inter] ) - return inter + 1; - else if (x < A[inter]) - end = inter - 1; - else - first = inter + 1; - length = end - first; - } - return -1; -} - -void main() { - int A[10] = {0,1,2,3,4,5,6,7,8,9}; - - printf("%d\n", BinSearch(A, 0, 9, 9)); -} diff --git a/BinaryAdd.c b/BinaryAdd.c deleted file mode 100644 index b2b7fa1..0000000 --- a/BinaryAdd.c +++ /dev/null @@ -1,29 +0,0 @@ -#include - -void BinaryAdd(int a[], int b[], int n,int c[]) { - int promote = 0; - int i; - int result; - - for (i = n - 1; i >= 0; i--) { - result = a[i] + b[i] + promote; - if (result >= 2) { - result = result - 2; - promote = 1; - } - else - promote = 0; - c[i + 1] = result; - } - c[0] = promote; -} - -int main() { - int a[4] = {1,0,1,1}; - int b[4] = {1,1,1,1}; - int c[5]; - - BinaryAdd(a, b, 4, c); - printf("%d%d%d%d + %d%d%d%d = %d%d%d%d%d\n", a[0], a[1], a[2], a[3], b[0], b[1], b[2], b[3], c[0], c[1], c[2], c[3], c[4]); - return 0; -} diff --git a/BubbleSort.c b/BubbleSort.c deleted file mode 100644 index 7ab898a..0000000 --- a/BubbleSort.c +++ /dev/null @@ -1,33 +0,0 @@ -//BubbleSort(A) -//for i = 1 to A.length - 1 -// for j = A.length downto i + 1 -// if A[j] < A[j - 1] -// swap(A[j], A[j - 1]) - -#include - -void BubbleSort(int A[], int n) { - int i, j; - - for (i = 0; i < n - 1; i++) - for (j = n - 1; j > i; j--) - if (A[j] < A[j - 1]) { - int tmp = A[j]; - - A[j] = A[j - 1]; - A[j - 1] = tmp; - } -} - -int main() { - int a[1000]; - int i; - - for (i = 0; i < 1000; i++) - a[i] = 1000 - i; - BubbleSort(a, 1000); - for (i = 0; i < 1000; i++) - printf("%d\t", a[i]); - printf("\n"); - return 0; -} diff --git a/FengSort.c b/FengSort.c index 124cb26..c9befcc 100644 --- a/FengSort.c +++ b/FengSort.c @@ -31,7 +31,7 @@ int main() FengSort(a, 0, 8); printf("%d, %d, %d, %d, %d, %d, %d, %d, %d\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8]); - FengSort(b, 0, 1); - printf("%d,%d\n", b[0], b[1]); - exit(0); + FengSort(b, 0, 1); + printf("%d,%d\n", b[0], b[1]); + exit(0); } diff --git a/Fibonacci.c b/Fibonacci.c deleted file mode 100644 index 181a626..0000000 --- a/Fibonacci.c +++ /dev/null @@ -1,22 +0,0 @@ -void swap(int *x, int *y) { - int temp; - - temp = *x; - *x = *y; - *y = temp; -} - -/* Compute Fibonacci number fib(n); fib(0) = 1, fib(1); fib(n) = fib(n-1) + fib(n-2); return fib(n) of int type */ - -int fib(int n) { - int fib1 = 1, fib2 = 1; - int i; - - for (i = 2; i <= n; i++) { - fib1 = fib1 + fib2; - swap(&fib1, &fib2); - } - return fib2; - -} - diff --git a/Horner.c b/Horner.c deleted file mode 100644 index d814262..0000000 --- a/Horner.c +++ /dev/null @@ -1,34 +0,0 @@ -//This procedure implements Horner's rule for evaluating -//a polynomial -#include -#include - -void Horner(int A[], int n, int x) { - int sum = 0; - int i; - - for (i = n; i >= 0; i--) - sum = A[i] + x * sum; - printf("%d\n", sum); -} - -//void Horner2(int A[], int n, int x) { - //int sum = 0; - //int i; -// - //for (i = n; i >= 0; i--) - //sum = A[i] * pow(x, i) + sum; - //printf("%d\n", sum); -//} - -int main() { - int a[10] = {1,2,30,4,5,6,7,8,9,0}; - - Horner(a, 9, 2); - //Horner2(a, 9, 2); - return 0; -} - - - - diff --git a/Horner_rule.py b/Horner_rule.py new file mode 100644 index 0000000..445940a --- /dev/null +++ b/Horner_rule.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# encoding: utf-8 +import functools + + +def Horner_rule(x, coefficients): + """ + Implements Horner's rule + :param x: + :param coefficients: + :return: + """ + return functools.reduce(lambda accumulate, coefficient: coefficient + accumulate * x, reversed(coefficients), 0) diff --git a/Ins-Merge.c b/Ins-Merge.c deleted file mode 100644 index 9710910..0000000 --- a/Ins-Merge.c +++ /dev/null @@ -1,98 +0,0 @@ -//* This program uses insertion sort within merge sort when subproblems -//* become sufficiently small - // MERGE(A, p, q, r) - // n1 = q - p + 1 - // n2 = r - q - // L[1...n1] = A[p...q] - // R[1...n2] = A[q+1...r] - // L[n1+1] = ∞ - // R[n2+1] = ∞ - // i = 1 - // j = 1 - // for k = p to r - // if L[i] <= R[j] - // A[k] = L[i] - // i = i + 1 - // else - // A[k] = R[j] - // j = j + 1 -#include -#include -#include - -void InsSort(int a[], int n) -{ - int i, j; - int key; - for (i = 1; i < n; i++) - { - key = a[i]; - for (j = i - 1; j >= 0 && a[j] > key; j--) - { - a[j + 1] = a[j]; - a[j] = key; - } - } -} - -void MERGE(int A[], int first, int inter, int end) -{ - int len1 = inter - first + 1; - int len2 = end - inter; - int i; - int j; - int k; - int *L; - int *R; - - L = (int *)calloc(len1 + 1, sizeof(int)); - R = (int *)calloc(len2 + 1, sizeof(int)); - for (i = 0; i < len1; i++) - L[i] = A[first + i]; - for (j = 0; j < len2; j++) - R[j] = A[inter + j + 1]; - L[len1] = INT_MAX; - R[len2] = INT_MAX; - - i = 0; - j = 0; - for (k = first; k <= end; k++) - { - if (L[i] <= R[j]) - A[k] = L[i++]; - else - A[k] = R[j++]; - } - free(L); - free(R); -} - -void MergeSort(int A[], int n, int length) -{ - int num = n / length; - int last_length = n - (num - 1) * length; - int i; - - for (i = 1; i < num; i++) - { - InsSort(A + (i - 1) * length, length); - if (i > 1) - MERGE(A, 0 , (i - 1) * length - 1, i * length - 1); - } - InsSort(A + (i - 1) * length, last_length); - MERGE(A, 0, (i - 1) * length - 1, n - 1); -} - -int main() -{ - int a[77]; - int i; - - for (i = 0; i < 77; i++) - a[i] = 77 - i; - MergeSort(a, 77, 9); - for (i = 0; i < 77; i++) - printf("%d\t", a[i]); - printf("\n"); - return 0; -} diff --git a/Ins-Merge2.c b/Ins-Merge2.c deleted file mode 100644 index d0ce4bc..0000000 --- a/Ins-Merge2.c +++ /dev/null @@ -1,94 +0,0 @@ -//* Divide and conquer version of Ins-Merge - // MERGE(A, p, q, r) - // n1 = q - p + 1 - // n2 = r - q - // L[1...n1] = A[p...q] - // R[1...n2] = A[q+1...r] - // L[n1+1] = ∞ - // R[n2+1] = ∞ - // i = 1 - // j = 1 - // for k = p to r - // if L[i] <= R[j] - // A[k] = L[i] - // i = i + 1 - // else - // A[k] = R[j] - // j = j + 1 -#include -#include -#include - -void InsSort(int a[], int n) -{ - int i, j; - int key; - for (i = 1; i < n; i++) - { - key = a[i]; - for (j = i - 1; j >= 0 && a[j] > key; j--) - { - a[j + 1] = a[j]; - a[j] = key; - } - } -} - -void MERGE(int A[], int first, int inter, int end) -{ - int len1 = inter - first + 1; - int len2 = end - inter; - int i; - int j; - int k; - int *L; - int *R; - - L = (int *)calloc(len1 + 1, sizeof(int)); - R = (int *)calloc(len2 + 1, sizeof(int)); - for (i = 0; i < len1; i++) - L[i] = A[first + i]; - for (j = 0; j < len2; j++) - R[j] = A[inter + j + 1]; - L[len1] = INT_MAX; - R[len2] = INT_MAX; - - i = 0; - j = 0; - for (k = first; k <= end; k++) - { - if (L[i] <= R[j]) - A[k] = L[i++]; - else - A[k] = R[j++]; - } - free(L); - free(R); -} - -void MergeSort(int A[], int start, int end, int length) -{ - if ((end - start + 1) > length) { - int middle = (start + end) / 2; - - MergeSort(A, start, middle, length); - MergeSort(A, middle + 1, end, length); - MERGE(A, start, middle, end); - } - else - InsSort(A + start, end - start + 1); -} - -int main() -{ - int a[77]; - int i; - - for (i = 0; i < 77; i++) - a[i] = 77 - i; - MergeSort(a, 1, 8, 9); - for (i = 0; i < 77; i++) - printf("%d\t", a[i]); - printf("\n"); - return 0; -} diff --git a/InsSort-BinSearch.c b/InsSort-BinSearch.c deleted file mode 100644 index a85159a..0000000 --- a/InsSort-BinSearch.c +++ /dev/null @@ -1,51 +0,0 @@ -#include - -void swap(int *a, int *b) -{ - int tmp = *a; - - *a = *b; - *b = tmp; -} -//Determine where x should be placed in array A -int BinSearch(int A[], int first, int end, int x) -{ - int length = end - first; - int inter; - - while (length >= 0) - { - inter = (first + end) / 2; - if (x == A[inter]) - return inter; - else if (x < A[inter]) - end = inter - 1; - else - first = inter + 1; - length = end - first; - } -// printf("%d, %d\n", first, end); - return first; -} - -void InsSort(int a[], int n) -{ - int i, j; - int pos; - - for (i = 1; i < n; i++) - { - pos = BinSearch(a, 0, i - 1, a[i]); - for (j = i; j > pos; j--) - swap(a + j, a + j - 1); - } -} - -int main() -{ - int a[7] = { 31, 101, 59, 26, 0, 61, 58 }; - - InsSort(a, 7); - printf("%d,%d,%d,%d,%d,%d,%d\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6]); - return 0; -} diff --git a/InsSort.c b/InsSort.c deleted file mode 100644 index fee77ba..0000000 --- a/InsSort.c +++ /dev/null @@ -1,24 +0,0 @@ -#include - -void InsSort(int a[], int n) -{ - int i, j; - int key; - for (i = 1; i < n; i++) - { - key = a[i]; - for (j = i - 1; j >= 0 && a[j] > key; j--) - { - a[j + 1] = a[j]; - a[j] = key; - } - } -} - -void main() -{ - int a[6] = { 31, 41, 59, 26, 61, 58 }; - - InsSort(a, 6); - printf("%d,%d,%d,%d,%d,%d", a[0], a[1], a[2], a[3], a[4], a[5]); -} \ No newline at end of file diff --git a/Johnson.py b/Johnson.py index c4fa24b..7dfe37f 100644 --- a/Johnson.py +++ b/Johnson.py @@ -1,41 +1,53 @@ from graph import min_priority_queue, Vertex, Graph import numpy as np + def Bellman_Ford(self, w, s): - ''' + """ The Bellman-Ford algorithm solves the single-source shortest-paths problem in the general case in which edge weights may be negative. - If there is a negative-weight cycle that is reachable from + If there is a negative-weight cycle that is reachable from the source s, this function returns False and indicates that no solution exists. If there is no such cycle, this function returns True and produces the shortest paths and their weights. - ''' - initialize_signle_source(self, s) + + :param self: + :param w: + :param s: + :return: + """ + initialize_single_source(self, s) for i in range(1, len(self.vertices)): - for u,v in self.edges: - relax(self, u, v, w) - for u,v in self.edges: + for u, v in self.edges: + relax(u, v, w) + for u, v in self.edges: if v.d > u.d + w[(u, v)]: return False return True -def initialize_signle_source(self, s): - for v in self.vertices: - v.d = float("Inf") - v.p = None - s.d = 0 -def relax(self, u, v, w): + + +def initialize_single_source(self, s): + for v in self.vertices: + v.d = float("Inf") + v.p = None + s.d = 0 + + +def relax(u, v, w): if v.d > u.d + w[u, v]: v.d = u.d + w[u, v] v.p = u + + def Dijkstra(self, w, s): - ''' + """ Dijkstra's algorithm solves the single-source shortest-paths problem on a weighted, directed graph G = (V, E) for the case in which all edge weights are nonnegative. - ''' - initialize_signle_source(self, s) + """ + initialize_single_source(self, s) S = set() Q = min_priority_queue(self.vertices, 'd') while Q.heap_size > 1: @@ -46,26 +58,28 @@ def Dijkstra(self, w, s): v.d = u.d + w[u, v] v.p = u Q.heap_decrease_key(v.index, u.d + w[u, v]) + + def Johnson(self, w): G = self n = len(G.vertices) s = Vertex("s") - GG = Graph(G.vertices.union({s}), G.edges + [(s, v) for v in G.vertices]) + GG = Graph(G.vertices.union({s}), G.edges | set((s, v) for v in G.vertices)) for v in G.vertices: w[(s, v)] = 0 - if Bellman_Ford(GG, w, s) == False: - print "the input graph contains a negative-weight cycle" + if not Bellman_Ford(GG, w, s): + print("the input graph contains a negative-weight cycle") else: h = dict() for v in GG.vertices: h[v] = v.d - #for key,value in h.iteritems(): - # print "h({}) = {}".format(key, value) + # for key,value in h.iteritems(): + # print(( "h({}) = {}".format(key, value))) ww = dict() for u, v in GG.edges: ww[(u, v)] = w[(u, v)] + h[u] - h[v] - #for key,value in ww.iteritems(): - # print "ww({}) = {}".format(key, value) + # for key,value in ww.iteritems(): + # print(( "ww({}) = {}".format(key, value))) D = np.empty((n, n)) for u in G.vertices: Dijkstra(G, ww, u) diff --git a/MergeSort.c b/MergeSort.c deleted file mode 100644 index 03ea825..0000000 --- a/MergeSort.c +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include - -//A version of merge procedure that stops once either array L or R has had //all its elements copied back to A -void Combine(int A[], int first, int inter, int end) { - int len1 = inter - first + 1; - int len2 = end - inter; - int i; - int j; - int k; - int *L; - int *R; - - L = (int *) calloc(len1, sizeof(int)); - R = (int *) calloc(len2, sizeof(int)); - for (i = 0; i < len1; i++) - L[i] = A[first + i]; - for (j = 0; j < len2; j++) - R[j] = A[inter + j + 1]; - - i = 0; - j = 0; - k = first; - while (i < len1 && j < len2) - if (L[i] <= R[j]) - A[k++] = L[i++]; - else - A[k++] = R[j++]; - if (i == len1) - while (j < len2) - A[k++] = R[j++]; - else if (j = len2) - while (i < len1) - A[k++] = L[i++]; - free(L); - free(R); -} - -void MergeSort(int A[], int first, int end) { - int middle = (first + end) / 2; - - if (end == first) - return; - MergeSort(A, first, middle); - MergeSort(A, middle + 1, end); - Combine(A, first, middle, end); - return; -} - -void main() { - int a[8] = {1,3,4,5,2,6,0,10}; - MergeSort(a, 0, 7); - printf("%d, %d, %d, %d, %d, %d, %d, %d\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); -} diff --git a/queue.py b/Queue.py similarity index 66% rename from queue.py rename to Queue.py index fbbc0f1..41aa7b4 100644 --- a/queue.py +++ b/Queue.py @@ -1,34 +1,44 @@ class FullException(Exception): def __init__(self): Exception.__init__(self) + + class EmptyException(Exception): def __init__(self): Exception.__init__(self) -class queue(object): + + +class Queue: def __init__(self, size): self.data = [0] * size - self.length = size + self.size = size self.head = 0 self.tail = 0 + def enqueue(self, x): if self.full(): - raise FullException() + raise FullException() self.data[self.tail] = x - if self.tail == self.length - 1: + if self.tail == self.size - 1: self.tail = 0 else: self.tail = self.tail + 1 + def dequeue(self): if self.empty(): - raise EmptyException() + raise EmptyException() x = self.data[self.head] - if self.head == self.length - 1: + if self.head == self.size - 1: self.head = 0 else: self.head = self.head + 1 return x + def empty(self): return self.tail == self.head + def full(self): - #print "tail: {}, head: {}, size: {}".format(self.tail, self.head, self.length) - return (self.tail + 1) % self.length == self.head + return (self.tail + 1) % self.size == self.head + + def capacity(self): + return self.size - 1 diff --git a/README.md b/README.md index c4adc91..784d417 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,9 @@ # algorithm implementation of algorithms in CLRS -test.sh is the shell script to run all the testcases +## note +Since python2 is outdated, the original python2.7 code is moved to python2.7 branch. +The master branch support python3 only. + +## test +Run testcase in tests folder diff --git a/activity_selection.py b/activity_selection.py index 95c248a..3369a04 100644 --- a/activity_selection.py +++ b/activity_selection.py @@ -1,35 +1,40 @@ from numpy import zeros + def activity_selection(s, f, n): c = zeros((n + 2, n + 2)) activities = zeros((n + 2, n + 2)) s = [float("-Inf")] + s[0:n] + [float("Inf")] f = [float("-Inf")] + f[0:n] + [float("Inf")] for l in range(3, n + 3): - for i in range(0, n + 3 - l): + for i in range(n + 3 - l): j = i + l - 1 - print "i = {}, j = {}".format(i, j) + print("i = {}, j = {}".format(i, j)) for k in range(i + 1, j): - print "k = {}".format(k) - print "s[{}] = {}, f[{}] = {}".format(k, s[k], k, f[k]) - print "s[{}] = {}, f[{}] = {}".format(j, s[j], i, f[i]) + print("k = {}".format(k)) + print("s[{}] = {}, f[{}] = {}".format(k, s[k], k, f[k])) + print("s[{}] = {}, f[{}] = {}".format(j, s[j], i, f[i])) if f[i] <= s[k] and f[k] <= s[j]: t = c[i, k] + c[k, j] + 1 - print "t = {}, c[{}, {}] = {}".format(t, i, j, c[i, j]) + print("t = {}, c[{}, {}] = {}".format(t, i, j, c[i, j])) if t > c[i, j]: c[i, j] = t activities[i, j] = k - return c,activities + return c, activities + + def activity_selection_with_weight(s, f, v, n): - '''This is a modification to the activity-selection problem in which each activity has, + """ + This is a modification to the activity-selection problem in which each activity has, in addition to a start and finish time, a value v. Now the object is to maximize - the total value of the activies scheduled. It can be solved by dynamic programming method''' + the total value of the activities scheduled. It can be solved by dynamic programming method + """ c = zeros((n + 2, n + 2)) activities = zeros((n + 2, n + 2)) s = [float("-Inf")] + s[0:n] + [float("Inf")] f = [float("-Inf")] + f[0:n] + [float("Inf")] for l in range(3, n + 3): - for i in range(0, n + 3 - l): + for i in range(n + 3 - l): j = i + l - 1 for k in range(i + 1, j): if f[i] <= s[k] and f[k] <= s[j]: @@ -37,10 +42,14 @@ def activity_selection_with_weight(s, f, v, n): if t > c[i, j]: c[i, j] = t activities[i, j] = k - return c,activities + return c, activities + + def recursive_activity_selector(s, f, n): f = [float("-Inf")] + f return recursive_activity_selector_aux(s, f, 0, n) + + def recursive_activity_selector_aux(s, f, k, n): m = k + 1 while m <= n and s[m - 1] < f[k]: @@ -49,6 +58,8 @@ def recursive_activity_selector_aux(s, f, k, n): return {m}.union(recursive_activity_selector_aux(s, f, m, n)) else: return {} + + def greedy_activity_selector(s, f): n = len(s) A = {1} @@ -58,10 +69,13 @@ def greedy_activity_selector(s, f): A = A.union({m}) k = m return A + + def greedy_activity_selector_last(s, f): - '''Instead of always selecting the first activity to finish, + """Instead of always selecting the first activity to finish, select the last activity to start that is compatible with all - previously selected activities''' + previously selected activities + """ n = len(s) A = {n} k = n @@ -70,14 +84,18 @@ def greedy_activity_selector_last(s, f): A = A.union({m}) k = m return A + + def print_activity(activities): m = activities.shape[0] - 1 n = activities.shape[1] - 1 print_activity_aux(activities, 0, n) + + def print_activity_aux(activities, m, n): a = activities[m, n] if a == 0: return print_activity_aux(activities, m, a) - print int(a) + print(int(a)) print_activity_aux(activities, a, n) diff --git a/all_pairs_shortest_paths.py b/all_pairs_shortest_paths.py index 323a572..d6115b3 100644 --- a/all_pairs_shortest_paths.py +++ b/all_pairs_shortest_paths.py @@ -1,21 +1,23 @@ import numpy as np + def extend_shortest_paths(L, W): n = L.shape[0] - LW = np.empty((n, n)) - for i in range(0, n): - for j in range(0, n): + LW = np.empty((n, n)) + for i in range(n): + for j in range(n): LW[i, j] = float("Inf") - for k in range(0, n): + for k in range(n): LW[i, j] = min(LW[i, j], L[i, k] + W[k, j]) return LW + def slow_all_pairs_shortest_paths(W): n = W.shape[0] L = [None] * n L[0] = np.empty((n, n)) - for i in range(0, n): - for j in range(0, n): + for i in range(n): + for j in range(n): if i == j: L[0][i, j] = 0 else: @@ -25,34 +27,36 @@ def slow_all_pairs_shortest_paths(W): L[m] = extend_shortest_paths(L[m - 1], W) return L[m] + def extend_shortest_paths_with_predecessor_subgraph(L, P, W): n = W.shape[0] LW = np.empty((n, n)) PP = np.empty((n, n)) - for i in range(0, n): - for j in range(0, n): + for i in range(n): + for j in range(n): LW[i, j] = float("Inf") PP[i, j] = None - for k in range(0, n): + for k in range(n): if LW[i, j] > L[i, k] + W[k, j]: LW[i, j] = L[i, k] + W[k, j] PP[i, j] = k + 1 if LW[i, j] == L[i, j]: PP[i, j] = P[i, j] -# if j == i: -# PP[i, j] = None -# elif j != k: -# PP[i, j] = k + 1 -# else: -# PP[i, j] = P[i, j] + # if j == i: + # PP[i, j] = None + # elif j != k: + # PP[i, j] = k + 1 + # else: + # PP[i, j] = P[i, j] return LW, PP + def slow_all_pairs_shortest_paths_with_predecessor_subgraph(W): n = W.shape[0] L = np.empty((n, n)) P = np.empty((n, n)) - for i in range(0, n): - for j in range(0, n): + for i in range(n): + for j in range(n): if j == i: L[i, j] = 0 else: @@ -60,40 +64,43 @@ def slow_all_pairs_shortest_paths_with_predecessor_subgraph(W): P[i, j] = None for m in range(1, n): L, P = extend_shortest_paths_with_predecessor_subgraph(L, P, W) - print L - print P + print(L) + print(P) return L, P + def predecessor(W, L): n = W.shape[0] P = np.empty((n, n)) - COMPLETED = np.empty((n, n), dtype = bool) + COMPLETED = np.empty((n, n), dtype=bool) DEPTH = np.empty((n, n)) - for i in range(0, n): - for j in range(0, n): + for i in range(n): + for j in range(n): COMPLETED[i, j] = False DEPTH[i, j] = None P[i, j] = None - for i in range(0, n): + for i in range(n): P[i, i] = None COMPLETED[i, i] = True DEPTH[i, i] = 0 for m in range(1, n): - for i in range(0, n): - for j in range(0, n): + for i in range(n): + for j in range(n): if i == 0: - print m - print COMPLETED[i, j] - print L[m][i] - print L[n - 1][j] + print(m) + print(COMPLETED[i, j]) + print(L[m][i]) + print(L[n - 1][j]) if COMPLETED[i, j] == False and L[m][i, j] == L[n - 1][i, j]: - for k in range(0, n): - if DEPTH[i, k] == m - 1 and L[m][i, j] == L[m -1][i, k] + W[k, j]: + for k in range(n): + if DEPTH[i, k] == m - 1 and L[m][i, j] == L[m - 1][i, k] + W[k, j]: DEPTH[i, j] = m P[i, j] = k + 1 COMPLETED[i, j] = True break return P + + def faster_all_pairs_shortest_paths(W): n = W.shape[0] L = W @@ -101,42 +108,48 @@ def faster_all_pairs_shortest_paths(W): while m < n - 1: L = extend_shortest_paths(L, L) m = 2 * m - print m - print L + print(m) + print(L) return L + def negative_weight_cycle(W): L = faster_all_pairs_shortest_paths(W) n = W.shape[0] status = True - for i in range(0, n): - for j in range(0, n): - for k in range(0, n): + for i in range(n): + for j in range(n): + for k in range(n): if L[i, j] > L[i, k] + W[k, j]: - print "source {} contains a negative-weight cycle".format(i + 1) + print("source {} contains a negative-weight cycle".format(i + 1)) status = False return status + + def negative_weight_cycle_another(W): L = faster_all_pairs_shortest_paths(W) L = extend_shortest_paths(L, W) - print L + print(L) status = True n = W.shape[0] - for i in range(0, n): + for i in range(n): if L[i, i] < 0: status = False return status + + def minimum_negative_weight_cycle_edges_number(W): n = W.shape[0] L = W for m in range(2, n + 1): L = extend_shortest_paths(L, W) - for i in range(0, n): + for i in range(n): if L[i, i] < 0: - print "minimum negative weight cycle edges number is {}".format(m) + print("minimum negative weight cycle edges number is {}".format(m)) return False return True + def Floyd_Warshall(W): n = W.shape[0] D = [None] * (n + 1) @@ -154,52 +167,57 @@ def Floyd_Warshall(W): P[k] = np.empty((n, n)) for i in range(n): for j in range(n): - D[k][i,j] = min(D[k - 1][i, j], D[k - 1][i, k - 1] + D[k - 1][k - 1, j]) + D[k][i, j] = min(D[k - 1][i, j], D[k - 1][i, k - 1] + D[k - 1][k - 1, j]) if D[k - 1][i, j] > D[k - 1][i, k - 1] + D[k - 1][k - 1, j]: P[k][i, j] = P[k - 1][k - 1, j] else: P[k][i, j] = P[k - 1][i, j] return D[n], P[n] + + def Floyd_Warshall_WITH_LI(W): n = W.shape[0] D = [None] * (n + 1) D[0] = W LI = [None] * (n + 1) - LI[0] = np.empty((n, n), dtype = np.int32) + LI[0] = np.empty((n, n), dtype=np.int32) for i in range(1, n + 1): for j in range(1, n + 1): - LI[0][i - 1, j - 1] = 0 + LI[0][i - 1, j - 1] = 0 for k in range(1, n + 1): D[k] = np.empty((n, n)) - LI[k] = np.empty((n, n), dtype = np.int32) + LI[k] = np.empty((n, n), dtype=np.int32) for i in range(n): for j in range(n): - D[k][i,j] = min(D[k - 1][i, j], D[k - 1][i, k - 1] + D[k - 1][k - 1, j]) + D[k][i, j] = min(D[k - 1][i, j], D[k - 1][i, k - 1] + D[k - 1][k - 1, j]) if D[k - 1][i, j] > D[k - 1][i, k - 1] + D[k - 1][k - 1, j]: LI[k][i, j] = k else: LI[k][i, j] = LI[k - 1][i, j] - print LI[k] - print D[k] + print(LI[k]) + print(D[k]) return D[n], LI[n] + def print_all_pairs_shortest_path(LI, i, j): global status status = [False] * LI.shape[0] print_all_pairs_shortest_path_aux(LI, i, j) + + def print_all_pairs_shortest_path_aux(LI, i, j): global status - # print "www: {}, {}, status: {}".format(i, j, status) + # print( "www: {}, {}, status: {}".format(i, j, status)) if LI[i - 1, j - 1] == 0: - if status[i - 1] == False: + if not status[i - 1]: status[i - 1] = True - print i - if status[j - 1] == False: + print(i) + if not status[j - 1]: status[j - 1] = True - print j + print(j) else: print_all_pairs_shortest_path_aux(LI, i, LI[i - 1, j - 1]) - if status[LI[i - 1, j - 1] - 1] == False: - print LI[i - 1, j - 1] - status[LI[i - 1, j - 1] - 1] = True + if not status[LI[i - 1, j - 1] - 1]: + print(LI[i - 1, j - 1]) + status[LI[i - 1, j - 1] - 1] = True print_all_pairs_shortest_path_aux(LI, LI[i - 1, j - 1], j) diff --git a/all_pairs_shortest_paths_test.py b/all_pairs_shortest_paths_test.py deleted file mode 100644 index 6819906..0000000 --- a/all_pairs_shortest_paths_test.py +++ /dev/null @@ -1,23 +0,0 @@ -from all_pairs_shortest_paths import extend_shortest_paths, slow_all_pairs_shortest_paths, faster_all_pairs_shortest_paths -import unittest -import numpy as np - -class TestAllPairsShortestPaths(unittest.TestCase): - def test_slow_all_pairs_shortest_paths(self): - W = np.array([[0, 3, 8, float("Inf"), -4], [float("Inf"), 0, float("Inf"), 1, 7], [float("Inf"), 4, 0, float("Inf"), float("Inf")], [2, float("Inf"), -5, 0, float("Inf")], [float("Inf"), float("Inf"), float("Inf"), 6, 0]]) - R = slow_all_pairs_shortest_paths(W) - 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]]) - self.assertEquals((R == L).all(), True) - W = np.array([[0, float("Inf"), float("Inf"), float("Inf"), -1, float("Inf")], [1, 0, float("Inf"), 2, float("Inf"), float("Inf")], [float("Inf"), 2, 0, float("Inf"), float("Inf"), -8], [-4, float("Inf"), float("Inf"), 0, 3, float("Inf")], [float("Inf"), 7, float("Inf"), float("Inf"), 0, float("Inf")], [float("Inf"), 5, 10, float("Inf"), float("Inf"), 0]]) - R = slow_all_pairs_shortest_paths(W) - L = np.array([[0, 6, float("Inf"), 8, -1, float("Inf")], [-2, 0, float("Inf"), 2, -3, float("Inf")], [-5, -3, 0, -1, -6, -8], [-4, 2, float("Inf"), 0, -5, float("Inf")], [5, 7, float("Inf"), 9, 0, float("Inf")], [3, 5, 10, 7, 2, 0]]) - self.assertEquals((R == L).all(), True) - def test_faster_all_pairs_shortest_paths(self): - W = np.array([[0, 3, 8, float("Inf"), -4], [float("Inf"), 0, float("Inf"), 1, 7], [float("Inf"), 4, 0, float("Inf"), float("Inf")], [2, float("Inf"), -5, 0, float("Inf")], [float("Inf"), float("Inf"), float("Inf"), 6, 0]]) - R = faster_all_pairs_shortest_paths(W) - 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]]) - self.assertEquals((R == L).all(), True) - W = np.array([[0, float("Inf"), float("Inf"), float("Inf"), -1, float("Inf")], [1, 0, float("Inf"), 2, float("Inf"), float("Inf")], [float("Inf"), 2, 0, float("Inf"), float("Inf"), -8], [-4, float("Inf"), float("Inf"), 0, 3, float("Inf")], [float("Inf"), 7, float("Inf"), float("Inf"), 0, float("Inf")], [float("Inf"), 5, 10, float("Inf"), float("Inf"), 0]]) - R = faster_all_pairs_shortest_paths(W) - L = np.array([[0, 6, float("Inf"), 8, -1, float("Inf")], [-2, 0, float("Inf"), 2, -3, float("Inf")], [-5, -3, 0, -1, -6, -8], [-4, 2, float("Inf"), 0, -5, float("Inf")], [5, 7, float("Inf"), 9, 0, float("Inf")], [3, 5, 10, 7, 2, 0]]) - self.assertEquals((R == L).all(), True) diff --git a/any_disks_intersect.py b/any_disks_intersect.py index 1bbd33d..29a139f 100644 --- a/any_disks_intersect.py +++ b/any_disks_intersect.py @@ -1,32 +1,37 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python # we use 0 to mean red, 1 to mean black from tree import Node, Tree -from heap import max_heap +from heap import MaxHeap + def comparable(a, b): - '''Given two disks a and b that are comparable at x, determine whether a is above b or not.''' + """Given two disks a and b that are comparable at x, determine whether a is above b or not.""" a_y = a[0][1] b_y = b[0][1] - if a_y >= b_y: - return True - else: - return False + return a_y >= b_y + + class disk(tuple): def __init__(self, d): super(disk, self).__init__(d) self.pointer = None + + class point(list): def __init__(self, info, disk): super(point, self).__init__(info) self.disk = disk + + class rb_node(Node): def __init__(self, key, p, left, right, color): Node.__init__(self, key, p, left, right) self.color = color - if key != None: + if key is not None: key.pointer = self + def minimum(self, nil): x = self y = x @@ -34,16 +39,21 @@ def minimum(self, nil): y = x x = x.left return y + def maximum(self, nil): x = self while x.right != nil: x = x.right return x + + class rb_tree(Tree): nil = rb_node(None, None, None, None, 1) root = nil + def __init__(self): pass + def above(self, s): x = s.pointer if x.right != self.nil: @@ -52,6 +62,7 @@ def above(self, s): while x.p != self.nil and x.p.right == x: x = x.p return x.p.key + def below(self, s): x = s.pointer if x.left != self.nil: @@ -60,10 +71,13 @@ def below(self, s): while x.p != self.nil and x.p.left == x: x = x.p return x.p.key + def minimum(self): return self.root.minimum(self.nil) + def __getitem__(self, key): return self.iterative_tree_search(key) + def left_rotate(self, x): y = x.right x.right = y.left @@ -78,6 +92,7 @@ def left_rotate(self, x): x.p.right = y y.left = x x.p = y + def right_rotate(self, y): x = y.left y.left = x.right @@ -92,8 +107,9 @@ def right_rotate(self, y): y.p.left = x x.right = y y.p = x + def insert(self, z): - ''' the disk z will only be inserted when the left endpoint of z is being processed''' + """ the disk z will only be inserted when the left endpoint of z is being processed""" # this is the x_coordinate of the left endpoint of z x_coordinate = z[0][0] z = rb_node(z, None, None, None, 0) @@ -114,8 +130,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def insert_fixed(self, z): while z.p.color == 0: if z.p.p.left == z.p: @@ -149,6 +166,7 @@ def insert_fixed(self, z): z.color = 0 z.p.color = 1 self.root.color = 1 + def transplant(self, u, v): if u.p == self.nil: self.root = v @@ -157,6 +175,7 @@ def transplant(self, u, v): else: u.p.right = v v.p = u.p + def delete(self, z): z = z.pointer y = z @@ -183,6 +202,7 @@ def delete(self, z): y.color = z.color if y_original_color == 1: self.delete_fixup(x) + def delete_fixup(self, x): while x != self.root and x.color == 1: if x == x.p.left: @@ -228,8 +248,14 @@ def delete_fixup(self, x): self.right_rotate(x.p) x = self.root x.color = 1 + + def any_disks_intersect(S): - '''This algorithm takes as input a set S of n disks represented by its center point and radius, returning the boolean value TRUE if any pair of disks in S intersects, and FALSE otherwise.''' + """ + This algorithm takes as input a set S of n disks represented by its center point and radius, returning the boolean value TRUE if any pair of disks in S intersects, and FALSE otherwise. + :param S: + :return: + """ T = rb_tree() point_list = [] disk_list = [] @@ -242,38 +268,37 @@ def any_disks_intersect(S): y = center_point[1] point_list.append(point([x - radius, 0, y], s)) point_list.append(point([x + radius, 1, y], s)) - heap_point = max_heap(point_list) + heap_point = MaxHeap(point_list) heap_point.heapsort() - print heap_point + print(heap_point) for p in heap_point: if p[1] == 0: s = p.disk T.insert(s) a = T.above(s) b = T.below(s) - print "insert: ", a, b - if (a != None and disks_intersect(a, s)) or (b != None and disks_intersect(b, s)): + print("insert: ", a, b) + if (a is not None and disks_intersect(a, s)) or (b is not None and disks_intersect(b, s)): return True if p[1] == 1: s = p.disk a = T.above(s) b = T.below(s) - if a != None and b != None and disks_intersect(a, b): + if a is not None and b is not None and disks_intersect(a, b): return True T.delete(s) return False + + def disks_intersect(a, b): - print a - print b + print(a) + print(b) a_x = a[0][0] a_y = a[0][1] a_r = a[1] b_x = b[0][0] b_y = b[0][1] b_r = b[1] - print (a_x - b_x) ** 2 + (a_y - b_y) ** 2 - print (a_r + b_r) ** 2 - if ((a_x - b_x) ** 2 + (a_y - b_y) ** 2) <= ((a_r + b_r) ** 2): - return True - else: - return False + print((a_x - b_x) ** 2 + (a_y - b_y) ** 2) + print((a_r + b_r) ** 2) + return ((a_x - b_x) ** 2 + (a_y - b_y) ** 2) <= ((a_r + b_r) ** 2) diff --git a/any_segments_intersect.py b/any_segments_intersect.py index 4fc0d57..38762d4 100644 --- a/any_segments_intersect.py +++ b/any_segments_intersect.py @@ -1,15 +1,20 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python # we use 0 to mean red, 1 to mean black from tree import Node, Tree -from heap import max_heap +from heap import MaxHeap from segment_intersect import segments_intersect + def vertical(a): return a[0][0] == a[1][0] + + def comparable(a, b, x): - '''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 ''' + """ + 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 + """ p1 = a[0] p2 = a[1] p3 = b[0] @@ -17,54 +22,44 @@ def comparable(a, b, x): x4 = p4[0] x3 = p3[0] if vertical(a) and vertical(b): - if p1[1] >= p3[1]: - return True - else: - return False + return p1[1] >= p3[1] elif vertical(a) and not vertical(b): v1 = (p4[0] - p3[0], p4[1] - p3[1]) v2 = (p4[0] - p1[0], p4[1] - p1[1]) result = v1[0] * v2[1] - v2[0] * v1[1] - # a is below b - if result >= 0: - return False - # a is above b - else: - return True + return result < 0 elif not vertical(a) and vertical(b): v1 = (p2[0] - p1[0], p2[1] - p1[1]) v2 = (p2[0] - p3[0], p2[1] - p3[1]) result = v1[0] * v2[1] - v2[0] * v1[1] - # a is above b - if result >= 0: - return True - # a is above b - else: - return False + return result >= 0 else: v1 = (p2[0] - p1[0], p2[1] - p1[1]) - v2 = ((x4 - x3) * (p2[0] - p4[0]) + (x4 - x) * (p4[0] - p3[0]), (x4 - x3) * (p2[1] - p4[1]) + (x4 - x) * (p4[1] - p3[1])) + v2 = ((x4 - x3) * (p2[0] - p4[0]) + (x4 - x) * (p4[0] - p3[0]), + (x4 - x3) * (p2[1] - p4[1]) + (x4 - x) * (p4[1] - p3[1])) result = v1[0] * v2[1] - v2[0] * v1[1] - # a is above b - if result >= 0: - return True - # a is below b - else: - return False + return result >= 0 + + class segment(tuple): def __init__(self, seg): super(segment, self).__init__(seg) self.pointer = None + + class point(list): def __init__(self, info, segment): super(point, self).__init__(info) self.segment = segment + + class rb_node(Node): def __init__(self, key, p, left, right, color): Node.__init__(self, key, p, left, right) self.color = color - if key != None: + if key is not None: key.pointer = self + def minimum(self, nil): x = self y = x @@ -72,16 +67,21 @@ def minimum(self, nil): y = x x = x.left return y + def maximum(self, nil): x = self while x.right != nil: x = x.right return x + + class rb_tree(Tree): nil = rb_node(None, None, None, None, 1) root = nil + def __init__(self): pass + def above(self, s): x = s.pointer if x.right != self.nil: @@ -90,6 +90,7 @@ def above(self, s): while x.p != self.nil and x.p.right == x: x = x.p return x.p.key + def below(self, s): x = s.pointer if x.left != self.nil: @@ -98,10 +99,13 @@ def below(self, s): while x.p != self.nil and x.p.left == x: x = x.p return x.p.key + def minimum(self): return self.root.minimum(self.nil) + def __getitem__(self, key): return self.iterative_tree_search(key) + def left_rotate(self, x): y = x.right x.right = y.left @@ -116,6 +120,7 @@ def left_rotate(self, x): x.p.right = y y.left = x x.p = y + def right_rotate(self, y): x = y.left y.left = x.right @@ -130,8 +135,11 @@ def right_rotate(self, y): y.p.left = x x.right = y y.p = x + def insert(self, z): - ''' the segment z will only be inserted when the left endpoint of z is being processed''' + """ + the segment z will only be inserted when the left endpoint of z is being processed + """ # this is the x_coordinate of the left endpoint of z x_coordinate = z[0][0] z = rb_node(z, None, None, None, 0) @@ -152,8 +160,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def insert_fixed(self, z): while z.p.color == 0: if z.p.p.left == z.p: @@ -187,6 +196,7 @@ def insert_fixed(self, z): z.color = 0 z.p.color = 1 self.root.color = 1 + def transplant(self, u, v): if u.p == self.nil: self.root = v @@ -195,6 +205,7 @@ def transplant(self, u, v): else: u.p.right = v v.p = u.p + def delete(self, z): z = z.pointer y = z @@ -221,6 +232,7 @@ def delete(self, z): y.color = z.color if y_original_color == 1: self.delete_fixup(x) + def delete_fixup(self, x): while x != self.root and x.color == 1: if x == x.p.left: @@ -266,17 +278,21 @@ def delete_fixup(self, x): self.right_rotate(x.p) x = self.root x.color = 1 + + def any_segments_intersect(S): - '''This algorithm takes as input a set S of n line segments, returning the boolean value TRUE if any pair of segments in S intersects, and FALSE otherwise.''' + """ + This algorithm takes as input a set S of n line segments, returning the boolean value TRUE if any pair of segments in S intersects, and FALSE otherwise. + """ T = rb_tree() segment_list = [] point_list = [] for s in S: segment_list.append(segment(s)) for s in segment_list: - point_list.append(point([s[0][0], 0, s[0][1]], s)) - point_list.append(point([s[1][0], 1, s[1][1]], s)) - heap_point = max_heap(point_list) + point_list.append(point([s[0][0], 0, s[0][1]], s)) + point_list.append(point([s[1][0], 1, s[1][1]], s)) + heap_point = MaxHeap(point_list) heap_point.heapsort() for p in heap_point: if p[1] == 0: @@ -284,17 +300,18 @@ def any_segments_intersect(S): T.insert(s) a = T.above(s) b = T.below(s) - if (a != None and segments_intersect(a[0], a[1], s[0], s[1])) or (b != None and segments_intersect(b[0], b[1], s[0], s[1])): + if (a is not None and segments_intersect(a[0], a[1], s[0], s[1])) or ( + b is not None and segments_intersect(b[0], b[1], s[0], s[1])): return True if p[1] == 1: s = p.segment a = T.above(s) b = T.below(s) -# print a -# print b -# print type(a) -# print type(b) - if a != None and b != None and segments_intersect(a[0], a[1], b[0], b[1]): + # print( a) + # print( b) + # print( type(a)) + # print( type(b)) + if a is not None and b is not None and segments_intersect(a[0], a[1], b[0], b[1]): return True T.delete(s) return False diff --git a/automaton_string_match.py b/automaton_string_match.py index 08c0d38..7de7ac1 100644 --- a/automaton_string_match.py +++ b/automaton_string_match.py @@ -1,4 +1,5 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + def finite_automaton_matcher(T, s, m): n = len(T) @@ -6,17 +7,21 @@ def finite_automaton_matcher(T, s, m): for i in range(1, n + 1): q = s[(q, T[i - 1])] if q == m: - print "Pattern occurs with shift {}".format(i - m) + print("Pattern occurs with shift {}".format(i - m)) + + def compute_transition_function(P, domain): m = len(P) s = dict() for a in domain: - for q in range(0, m + 1): + for q in range(m + 1): k = min(q + 1, m) while not (P[0:q] + a).endswith(P[0:k]): k = k - 1 s[(q, a)] = k return s + + def automaton_string_match(P, T, domain): s = compute_transition_function(P, domain) m = len(P) diff --git a/b_tree_test.py b/b_tree_example.py similarity index 69% rename from b_tree_test.py rename to b_tree_example.py index 92f321a..96c3644 100755 --- a/b_tree_test.py +++ b/b_tree_example.py @@ -1,32 +1,32 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -import b_tree as bt +import btree as bt -a = bt.b_tree_node(3, True, 2) +a = bt.BTreeNode(3, True, 2) a.key[0] = 'A' a.key[1] = 'B' -b = bt.b_tree_node(3, True, 3) +b = bt.BTreeNode(3, True, 3) b.key[0] = 'D' b.key[1] = 'E' b.key[2] = 'F' -c = bt.b_tree_node(3, True, 3) +c = bt.BTreeNode(3, True, 3) c.key[0] = 'J' c.key[1] = 'K' c.key[2] = 'L' -d = bt.b_tree_node(3, True, 2) +d = bt.BTreeNode(3, True, 2) d.key[0] = 'N' d.key[1] = 'O' -x = bt.b_tree_node(3, True, 3) +x = bt.BTreeNode(3, True, 3) x.key[0] = 'Q' x.key[1] = 'R' x.key[2] = 'S' -y = bt.b_tree_node(3, True, 2) +y = bt.BTreeNode(3, True, 2) y.key[0] = 'U' y.key[1] = 'V' -z = bt.b_tree_node(3, True, 2) +z = bt.BTreeNode(3, True, 2) z.key[0] = 'Y' z.key[1] = 'Z' -e = bt.b_tree_node(3, False, 3) +e = bt.BTreeNode(3, False, 3) e.key[0] = 'C' e.key[1] = 'G' e.key[2] = 'M' @@ -34,13 +34,13 @@ e.c[1] = b e.c[2] = c e.c[3] = d -v = bt.b_tree_node(3, False, 2) +v = bt.BTreeNode(3, False, 2) v.key[0] = 'T' v.key[1] = 'X' v.c[0] = x v.c[1] = y v.c[2] = z -t = bt.b_tree(3) +t = bt.BTree(3) t.root.key[0] = 'P' t.root.c[0] = e t.root.c[1] = v @@ -48,25 +48,25 @@ t.root.leaf = False t.root.delete(t, 'F') t.root.print_child_first() -print +print() t.root.delete(t, 'M') t.root.print_child_first() -print +print() t.root.delete(t, 'G') t.root.print_child_first() -print +print() t.root.delete(t, 'D') t.root.print_child_first() -print +print() t.root.delete(t, 'B') t.root.print_child_first() -print +print() t.root.delete(t, 'C') t.root.print_child_first() -print +print() t.root.delete(t, 'P') t.root.print_child_first() -print +print() t.root.delete(t, 'V') t.root.print_child_first() -print +print() diff --git a/bh_tree.py b/bh_tree.py index 75f5ac2..6bbf5f6 100644 --- a/bh_tree.py +++ b/bh_tree.py @@ -1,21 +1,26 @@ # A variant of red black tree that has black_height attribute -#!/usr/bin/env ipython +# !/usr/bin/env python -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class bh_node(rb_node): + +class bh_node(RbNode): def __init__(self, key, p, left, right, color, bh): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.bh = bh -class bh_tree(rb_tree): + + +class bh_tree(RbTree): nil = bh_node(None, None, None, None, 1, 0) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: self.insert(bh_node(i, None, None, None, 0, 1)) else: - print "Not invalid argument" + print("Not invalid argument") + def insert_fixed(self, z): while z.p.color == 0: if z.p.p.left == z.p: @@ -51,6 +56,7 @@ def insert_fixed(self, z): z.color = 0 z.p.color = 1 self.root.color = 1 + def delete_fixup(self, x): while x != self.root and x.color == 1: if x == x.p.left: diff --git a/binary_add.py b/binary_add.py new file mode 100644 index 0000000..92aabdd --- /dev/null +++ b/binary_add.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +def binary_add(array1, array2): + """ + Consider the problem of adding two n-bit binary integers, stored in two n-element arrays A and B, + in big-endian order. + The sum of the two integers should be stored in binary form in a (n + 1)-element array C. + :param array1: n-element array A + :param array2: n-element array B + :return: (n + 1)-element array C + """ + assert len(array1) == len(array2) + n = len(array1) + promote = 0 + array3 = [0] * (n + 1) + for i in range(n - 1, -1, -1): + result = array1[i] + array2[i] + promote + promote = result // 2 + array3[i + 1] = result % 2 + array3[0] = promote + return array3 diff --git a/binary_search.py b/binary_search.py new file mode 100644 index 0000000..f61f7b2 --- /dev/null +++ b/binary_search.py @@ -0,0 +1,74 @@ +def binary_search(target, array): + """ + find target in sorted array. + If found, return the index, otherwise return -1. + :param target: + :param array: list + :return: + """ + low = 0 + high = len(array) - 1 + while low <= high: + mid = (low + high) // 2 + if target < array[mid]: + high = mid - 1 + elif target > array[mid]: + low = mid + 1 + else: + return mid + return -1 + + +def bisect_left(array, x, low=0, high=None): + """ + Locate the insertion point for x in a to maintain sorted order. + If x is already present in a, + the insertion point will be before (to the left of) any existing entries. + The return value is suitable for use as the first parameter to list.insert() assuming that a is already sorted. + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + + :param array: sorted list + :param x: + :param low: + :param high: + :return: + """ + if high is None: + high = len(array) + assert low <= high + while low < high: + mid = (low + high) // 2 + if array[mid] < x: + low = mid + 1 + else: + high = mid + return low + + +def bisect_right(array, x, low=0, high=None): + """ + Return the index where to insert item x in list a, assuming a is sorted. + + The return value i is such that all e in a[:i] have e <= x, and all e in + a[i:] have e > x. So if x already appears in the list, a.insert(x) will + insert just after the rightmost x already there. + + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + :param array: + :param x: + :param low: + :param high: + :return: + """ + if high is None: + high = len(array) + assert low <= high + while low < high: + mid = (low + high) // 2 + if array[mid] <= x: + low = mid + 1 + else: + high = mid + return low diff --git a/binary_counter.py b/binarycounter.py similarity index 74% rename from binary_counter.py rename to binarycounter.py index b729ccf..e95701a 100644 --- a/binary_counter.py +++ b/binarycounter.py @@ -1,7 +1,8 @@ -class binary_counter(list): +class BinaryCounter(list): def __init__(self, size): self.leftmost_1 = -1 - list.__init__(self, [0] * size) + super(BinaryCounter, self).__init__([0] * size) + def increment(self): i = 0 while i < len(self) and self[i] == 1: @@ -13,9 +14,11 @@ def increment(self): self.leftmost_1 = i else: self.leftmost_1 = -1 + def reset(self): - for i in range(0, self.leftmost_1 + 1): + for i in range(self.leftmost_1 + 1): self[i] = 0 self.leftmost_1 = -1 + def print_bits(self): - print self[::-1] + print(self[::-1]) diff --git a/binsearch.c b/binsearch.c deleted file mode 100644 index 8f9c9f8..0000000 --- a/binsearch.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ -int binsearch(int x, int v[], int n) { - int low, high, mid; - - low = 0; - high = n - 1; - while (low <= high) { - mid = (high + low)/2; - if (x < v[mid]) - high = mid - 1; - else if (x > v[mid]) - low = mid + 1; - else /* found match */ - return mid; - } - return -1; /* no match */ -} - -void main() { - int A[10] = {0,1,2,3,4,5,6,7,8,9}; - - printf("%d\n", binsearch(9, A, 10)); -} - diff --git a/b_tree.py b/btree.py similarity index 81% rename from b_tree.py rename to btree.py index e181b40..7bd91a1 100644 --- a/b_tree.py +++ b/btree.py @@ -1,16 +1,18 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -class b_tree_node(object): + +class BTreeNode: def __init__(self, t, leaf, n): self.leaf = leaf self.n = n self.t = t self.key = [0] * (2 * t - 1) self.c = [0] * (2 * t) + def split_child(self, i): y = self.c[i - 1] t = y.t - z = b_tree_node(t, y.leaf, t - 1) + z = BTreeNode(t, y.leaf, t - 1) for j in range(1, t): z.key[j - 1] = y.key[j + t - 1] if not y.leaf: @@ -21,9 +23,10 @@ def split_child(self, i): self.c[j] = self.c[j - 1] self.c[i] = z for j in range(self.n, i - 1, -1): - self.key[j] = self.key[j -1] + self.key[j] = self.key[j - 1] self.key[i - 1] = y.key[t - 1] self.n = self.n + 1 + def insert_nonfull(self, k): i = self.n t = self.t @@ -42,31 +45,35 @@ def insert_nonfull(self, k): if k > self.key[i - 1]: i = i + 1 self.c[i - 1].insert_nonfull(k) + def search(self, k): i = 1 while i <= self.n and k > self.key[i - 1]: i = i + 1 if i <= self.n and k == self.key[i - 1]: - return (self, i) + return self, i elif self.leaf: return None else: return self.c[i - 1].search(k) + def print_inorder(self): if self.leaf: for i in range(1, self.n + 1): - print self.key[i - 1], + print(self.key[i - 1], ) else: for i in range(1, self.n + 1): self.c[i - 1].print_inorder() - print self.key[i - 1], + print(self.key[i - 1], ) self.c[self.n].print_inorder() + def print_child_first(self): if not self.leaf: for i in range(1, self.n + 2): self.c[i - 1].print_child_first() for i in range(1, self.n + 1): - print self.key[i - 1], + print(self.key[i - 1], ) + def delete(self, tree, k): t = self.t i = 1 @@ -133,7 +140,8 @@ def delete(self, tree, k): self.merge(tree, i - 1) self.c[i - 2].delete(tree, k) else: - self.c[i - 1].delete(tree, k) + self.c[i - 1].delete(tree, k) + def merge(self, tree, i): y = self.c[i - 1] z = self.c[i] @@ -154,49 +162,54 @@ def merge(self, tree, i): self.n = self.n - 1 if tree.root == self and self.n == 0: tree.root = y -class b_tree(object): + + +class BTree: def __init__(self, t): self.t = t - self.root = b_tree_node(t, True, 0) + self.root = BTreeNode(t, True, 0) + def insert(self, k): r = self.root t = self.t if r.n == 2 * t - 1: - s = b_tree_node(t, False, 0) + s = BTreeNode(t, False, 0) self.root = s s.c[0] = r s.split_child(1) s.insert_nonfull(k) else: r.insert_nonfull(k) + def print_b_tree(self): r = self.root r.print_inorder() -# def predecessor(self, k): -# m = [] -# x = self.root -# while not x.leaf: -# i = 1 -# while i <= x.n and k > x.key[i - 1]: -# i = i + 1 -# if i <= x.n and k == x.key[i - 1]: -# x = x.c[i - 1] -# while not x.leaf: -# x = x.c[x.n] -# return x.key[x.n - 1] -# else: -# x = x.c[i - 1] -# if i > 1: -# m.append(x.key[i - 1]) -# i = 1 -# while i <= x.n and k != x.key[i - 1]: -# i = i + 1 -# if i > x.n or len(m) == 0: -# return None -# elif i > 1: -# return x.key[i - 2] -# else: -# return max(m) + + # def predecessor(self, k): + # m = [] + # x = self.root + # while not x.leaf: + # i = 1 + # while i <= x.n and k > x.key[i - 1]: + # i = i + 1 + # if i <= x.n and k == x.key[i - 1]: + # x = x.c[i - 1] + # while not x.leaf: + # x = x.c[x.n] + # return x.key[x.n - 1] + # else: + # x = x.c[i - 1] + # if i > 1: + # m.append(x.key[i - 1]) + # i = 1 + # while i <= x.n and k != x.key[i - 1]: + # i = i + 1 + # if i > x.n or len(m) == 0: + # return None + # elif i > 1: + # return x.key[i - 2] + # else: + # return max(m) def predecessor(self, k): s = [] x = self.root diff --git a/bubble_sort.py b/bubble_sort.py new file mode 100644 index 0000000..f9d6ae6 --- /dev/null +++ b/bubble_sort.py @@ -0,0 +1,11 @@ +def bubble_sort(array): + """ + O(n ^ 2) inplace sort + :param array: list + :return: + """ + n = len(array) + for i in range(n): + for j in range(n - 1, i, -1): + if array[j] < array[j - 1]: + array[j], array[j - 1] = array[j - 1], array[j] diff --git a/closest_points.py b/closest_points.py index e61bccb..2ad5163 100644 --- a/closest_points.py +++ b/closest_points.py @@ -1,35 +1,46 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python from math import ceil, sqrt -from heap import max_heap +from heap import MaxHeap + def x_sort(S): - X = max_heap(S) + X = MaxHeap(S) X.heapsort() return X + + def y_sort(S): Y = [] for p in S: Y.append((p[1], p[0])) - YY = max_heap(Y) + YY = MaxHeap(Y) YY.heapsort() Y = [] - for i in range(0, len(YY)): + for i in range(len(YY)): Y.append((YY[i][1], YY[i][0])) return Y + + def distance(p1, p2): return sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) + + def brute_force(P): P = list(P) d = float("Inf") - for i in range(0, len(P)): + for i in range(len(P)): for j in range(i + 1, len(P)): d = min(d, distance(P[i], P[j])) return d + + def closest_points(S): X = x_sort(S) Y = y_sort(S) return closest_points_aux(S, X, Y) + + def closest_points_aux(P, X, Y): length = len(P) half = int(ceil(length / 2)) @@ -42,7 +53,7 @@ def closest_points_aux(P, X, Y): l = X[half - 1][0] YL = [] YR = [] - for i in range(0, len(Y)): + for i in range(len(Y)): if Y[i] in PL: YL.append(Y[i]) else: @@ -51,11 +62,11 @@ def closest_points_aux(P, X, Y): dr = closest_points_aux(PR, XR, YR) d1 = min(dl, dr) YY = [] - for i in range(0, len(Y)): + for i in range(len(Y)): if abs(Y[i][0] - l) < d1: YY.append(Y[i]) d2 = float("Inf") - for i in range(0, len(YY)): + for i in range(len(YY)): for j in range(1, 10): if i + j < len(YY): d2 = min(distance(YY[i], YY[i + j]), d2) diff --git a/closest_points_l1_distance.py b/closest_points_l1_distance.py index 25361d5..35b8817 100644 --- a/closest_points_l1_distance.py +++ b/closest_points_l1_distance.py @@ -1,35 +1,46 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python from math import ceil, sqrt -from heap import max_heap +from heap import MaxHeap + def x_sort(S): - X = max_heap(S) + X = MaxHeap(S) X.heapsort() return X + + def y_sort(S): Y = [] for p in S: Y.append((p[1], p[0])) - YY = max_heap(Y) + YY = MaxHeap(Y) YY.heapsort() Y = [] - for i in range(0, len(YY)): + for i in range(len(YY)): Y.append((YY[i][1], YY[i][0])) return Y + + def distance(p1, p2): return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]) + + def brute_force(P): P = list(P) d = float("Inf") - for i in range(0, len(P)): + for i in range(len(P)): for j in range(i + 1, len(P)): d = min(d, distance(P[i], P[j])) return d + + def closest_points(S): X = x_sort(S) Y = y_sort(S) return closest_points_aux(S, X, Y) + + def closest_points_aux(P, X, Y): length = len(P) half = int(ceil(length / 2)) @@ -42,7 +53,7 @@ def closest_points_aux(P, X, Y): l = X[half - 1][0] YL = [] YR = [] - for i in range(0, len(Y)): + for i in range(len(Y)): if Y[i] in PL: YL.append(Y[i]) else: @@ -51,11 +62,11 @@ def closest_points_aux(P, X, Y): dr = closest_points_aux(PR, XR, YR) d1 = min(dl, dr) YY = [] - for i in range(0, len(Y)): + for i in range(len(Y)): if abs(Y[i][0] - l) < d1: YY.append(Y[i]) d2 = float("Inf") - for i in range(0, len(YY)): + for i in range(len(YY)): for j in range(1, 10): if i + j < len(YY): d2 = min(distance(YY[i], YY[i + j]), d2) diff --git a/closest_points_l_infinite_distance.py b/closest_points_l_infinite_distance.py index 0b1e1fc..a99b692 100644 --- a/closest_points_l_infinite_distance.py +++ b/closest_points_l_infinite_distance.py @@ -1,35 +1,46 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python from math import ceil, sqrt -from heap import max_heap +from heap import MaxHeap + def x_sort(S): - X = max_heap(S) + X = MaxHeap(S) X.heapsort() return X + + def y_sort(S): Y = [] for p in S: Y.append((p[1], p[0])) - YY = max_heap(Y) + YY = MaxHeap(Y) YY.heapsort() Y = [] - for i in range(0, len(YY)): + for i in range(len(YY)): Y.append((YY[i][1], YY[i][0])) return Y + + def distance(p1, p2): return max(abs(p1[0] - p2[0]), abs(p1[1] - p2[1])) + + def brute_force(P): P = list(P) d = float("Inf") - for i in range(0, len(P)): + for i in range(len(P)): for j in range(i + 1, len(P)): d = min(d, distance(P[i], P[j])) return d + + def closest_points(S): X = x_sort(S) Y = y_sort(S) return closest_points_aux(S, X, Y) + + def closest_points_aux(P, X, Y): length = len(P) half = int(ceil(length / 2)) @@ -42,7 +53,7 @@ def closest_points_aux(P, X, Y): l = X[half - 1][0] YL = [] YR = [] - for i in range(0, len(Y)): + for i in range(len(Y)): if Y[i] in PL: YL.append(Y[i]) else: @@ -51,11 +62,11 @@ def closest_points_aux(P, X, Y): dr = closest_points_aux(PR, XR, YR) d1 = min(dl, dr) YY = [] - for i in range(0, len(Y)): + for i in range(len(Y)): if abs(Y[i][0] - l) < d1: YY.append(Y[i]) d2 = float("Inf") - for i in range(0, len(YY)): + for i in range(len(YY)): for j in range(1, 7): if i + j < len(YY): d2 = min(distance(YY[i], YY[i + j]), d2) diff --git a/common-matrix-multiply-Strassen.py b/common-matrix-multiply-Strassen.py index 74effb5..61a0424 100644 --- a/common-matrix-multiply-Strassen.py +++ b/common-matrix-multiply-Strassen.py @@ -6,15 +6,17 @@ # EMAIL: cntqrxj@gmail.com from numpy import * +from square_matrix_multiply_Strassen import square_matrix_multiply + def common_matrix_multiply(A, B): - if (A.shape[1] != B.shape[0]): - print "The width of matrix A not equal the height of matrix B.\nHence no matrix multiplication allowed" + if A.shape[1] != B.shape[0]: + print("The width of matrix A not equal the height of matrix B.\nHence no matrix multiplication allowed") return - shape = (A.shape[0], B.shape[1]) - #shape = A.shape - #length = shape[0] - #half = length / 2 + shape = A.shape[0], B.shape[1] + # shape = A.shape + length = shape[0] + half = length / 2 A_width = A.shape[1] B_width = B.shape[1] A_height = A.shape[0] @@ -23,32 +25,32 @@ def common_matrix_multiply(A, B): half_A_height = A_height / 2 half_B_width = B_width / 2 half_B_height = B_height / 2 - - C = zeros(shape, dtype = int64) + + C = zeros(shape, dtype=int64) if A_height == 1 or B_width == 1: - C = dot(A, B) - #if length == 1: + C = dot(A, B) + # if length == 1: # C[0, 0] = A[0, 0] * B[0, 0] # return C - - S1 = zeros((half, half), dtype = int64) - S2 = zeros((half, half), dtype = int64) - S3 = zeros((half, half), dtype = int64) - S4 = zeros((half, half), dtype = int64) - S5 = zeros((half, half), dtype = int64) - S6 = zeros((half, half), dtype = int64) - S7 = zeros((half, half), dtype = int64) - S8 = zeros((half, half), dtype = int64) - S9 = zeros((half, half), dtype = int64) - S10 = zeros((half, half), dtype = int64) - P1 = zeros((half, half), dtype = int64) - P2 = zeros((half, half), dtype = int64) - P3 = zeros((half, half), dtype = int64) - P4 = zeros((half, half), dtype = int64) - P5 = zeros((half, half), dtype = int64) - P6 = zeros((half, half), dtype = int64) - P7 = zeros((half, half), dtype = int64) + S1 = zeros((half, half), dtype=int64) + S2 = zeros((half, half), dtype=int64) + S3 = zeros((half, half), dtype=int64) + S4 = zeros((half, half), dtype=int64) + S5 = zeros((half, half), dtype=int64) + S6 = zeros((half, half), dtype=int64) + S7 = zeros((half, half), dtype=int64) + S8 = zeros((half, half), dtype=int64) + S9 = zeros((half, half), dtype=int64) + S10 = zeros((half, half), dtype=int64) + + P1 = zeros((half, half), dtype=int64) + P2 = zeros((half, half), dtype=int64) + P3 = zeros((half, half), dtype=int64) + P4 = zeros((half, half), dtype=int64) + P5 = zeros((half, half), dtype=int64) + P6 = zeros((half, half), dtype=int64) + P7 = zeros((half, half), dtype=int64) S1 = B[0:half, half:length] - B[half:length, half:length] S2 = A[0:half, 0:half] + A[0:half, half:length] @@ -68,22 +70,22 @@ def common_matrix_multiply(A, B): P5 = square_matrix_multiply(S5, S6) P6 = square_matrix_multiply(S7, S8) P7 = square_matrix_multiply(S9, S10) - + C[0:half, 0:half] = P5 + P4 - P2 + P6 C[0:half, half:length] = P1 + P2 C[half:length, 0:half] = P3 + P4 C[half:length, half:length] = P5 + P1 - P3 - P7 - - return C -#A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) -#B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) -#A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) -#B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + return C + + +# A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) +# B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) +# A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +# B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) A = array([[1, 3], [7, 5]]) B = array([[6, 8], [4, 2]]) -#A = array([[1, 2, 3], [4, 5, 6]]) -#B = array([[1, 2], [4, 5]]) -print square_matrix_multiply(A, B) -#print dot(A, B) - +# A = array([[1, 2, 3], [4, 5, 6]]) +# B = array([[1, 2], [4, 5]]) +print(square_matrix_multiply(A, B)) +# print( dot(A, B)) diff --git a/common-matrix-multiply-recursive.py b/common-matrix-multiply-recursive.py index 11ea7f6..534e534 100755 --- a/common-matrix-multiply-recursive.py +++ b/common-matrix-multiply-recursive.py @@ -1,18 +1,14 @@ #! /usr/bin/python2.7 -# AUTHOR: WangQiang -# CREATE DATE: 20140528 -# LAST UPDATE DATE: 20140603 -# EMAIL: cntqrxj@gmail.com - from numpy import * + def common_matrix_multiply(A, B): - if (A.shape[1] != B.shape[0]): - print "The width of matrix A not equal the height of matrix B.\nHence no matrix multiplication allowed" + if A.shape[1] != B.shape[0]: + print("The width of matrix A not equal the height of matrix B.\nHence no matrix multiplication allowed") return shape = (A.shape[0], B.shape[1]) - C = zeros(shape, dtype = int64) + C = zeros(shape, dtype=int64) A_width = A.shape[1] B_width = B.shape[1] A_height = A.shape[0] @@ -22,20 +18,33 @@ def common_matrix_multiply(A, B): half_B_width = B_width / 2 half_B_height = B_height / 2 if A_height == 1 or B_width == 1: - C = dot(A, B) -# else if + C = dot(A, B) + # else if else: - C[0:half_A_height, 0:half_B_width] = common_matrix_multiply(A[0:half_A_height, 0:half_A_width], B[0:half_B_height, 0:half_B_width]) + common_matrix_multiply(A[0:half_A_height, half_A_width:A_width], B[half_B_height:B_height, 0:half_B_width]) - C[0:half_A_height, half_B_width:B_width] = common_matrix_multiply(A[0:half_A_height, 0:half_A_width], B[0:half_B_height, half_B_width:B_width]) + common_matrix_multiply(A[0:half_A_height, half_A_width:A_width], B[half_B_height:B_height, half_B_width:B_width]) - C[half_A_height:A_height, 0:half_B_width] = common_matrix_multiply(A[half_A_height:A_height, 0:half_A_width], B[0:half_B_height, 0:half_B_width]) + common_matrix_multiply(A[half_A_height:A_height, half_A_width:A_width], B[half_B_height:B_height, 0:half_B_width]) - C[half_A_height:A_height, half_B_width:B_width] = common_matrix_multiply(A[half_A_height:A_height, 0:half_A_width], B[0:half_B_height,half_B_width:B_width]) + common_matrix_multiply(A[half_A_height:A_height, half_A_width:A_width], B[half_B_height:B_height, half_B_width:B_width]) + C[0:half_A_height, 0:half_B_width] = common_matrix_multiply(A[0:half_A_height, 0:half_A_width], + B[0:half_B_height, + 0:half_B_width]) + common_matrix_multiply( + A[0:half_A_height, half_A_width:A_width], B[half_B_height:B_height, 0:half_B_width]) + C[0:half_A_height, half_B_width:B_width] = common_matrix_multiply(A[0:half_A_height, 0:half_A_width], + B[0:half_B_height, + half_B_width:B_width]) + common_matrix_multiply( + A[0:half_A_height, half_A_width:A_width], B[half_B_height:B_height, half_B_width:B_width]) + C[half_A_height:A_height, 0:half_B_width] = common_matrix_multiply(A[half_A_height:A_height, 0:half_A_width], + B[0:half_B_height, + 0:half_B_width]) + common_matrix_multiply( + A[half_A_height:A_height, half_A_width:A_width], B[half_B_height:B_height, 0:half_B_width]) + C[half_A_height:A_height, half_B_width:B_width] = common_matrix_multiply( + A[half_A_height:A_height, 0:half_A_width], + B[0:half_B_height, half_B_width:B_width]) + common_matrix_multiply( + A[half_A_height:A_height, half_A_width:A_width], B[half_B_height:B_height, half_B_width:B_width]) return C - + + A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) -#A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) -#B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) -#A = array([[1, 2, 3], [4, 5, 6]]) -#B = array([[1, 2], [4, 5]]) -print common_matrix_multiply(A, B) -#print dot(A, B) +# A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +# B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +# A = array([[1, 2, 3], [4, 5, 6]]) +# B = array([[1, 2], [4, 5]]) +print(common_matrix_multiply(A, B)) +# print( dot(A, B)) diff --git a/comparable.py b/comparable.py index 85998b8..87307e1 100644 --- a/comparable.py +++ b/comparable.py @@ -1,7 +1,9 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python def comparable(a, b, x): - '''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 ''' + """ + 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 + """ p1 = a[0] p2 = a[1] @@ -10,11 +12,13 @@ def comparable(a, b, x): x4 = p4[0] x3 = p3[0] v1 = (p2[0] - p1[0], p2[1] - p1[1]) - v2 = ((x4 - x3) * (p2[0] - p4[0]) + (x4 - x) * (p4[0] - p3[0]), (x4 - x3) * (p2[1] - p4[1]) + (x4 - x) * (p4[1] - p3[1])) + v2 = ( + (x4 - x3) * (p2[0] - p4[0]) + (x4 - x) * (p4[0] - p3[0]), + (x4 - x3) * (p2[1] - p4[1]) + (x4 - x) * (p4[1] - p3[1])) result = v1[0] * v2[1] - v2[0] * v1[1] if result == 0: - print "a intersects b at the vertical line" + print("a intersects b at the vertical line") elif result > 0: - print "a is above b" + print("a is above b") else: - print "b is above a" + print("b is above a") diff --git a/constraints.py b/constraints.py index 631dd6e..3bd6d6c 100644 --- a/constraints.py +++ b/constraints.py @@ -1,35 +1,40 @@ from graph import Vertex, Graph from random import sample + def Bellman_Ford(G, w, s): - '''A variant to the original Bellman_Ford algorithm + """A variant to the original Bellman_Ford algorithm that we use to solve a system of difference constraints with m inequalities on n unknowns. The running time is O(nm), faster than O(n * n + nm) of the original Bellman-Ford algorithm. - ''' + """ edges = G.edges - set([(s, v) for v in G.adj[s]]) G.initialize_signle_source(s) j = 1 for i in range(1, len(G.vertices)): if j == 1: - for u,v in G.edges: + for u, v in G.edges: G.relax(u, v, w) else: - for u,v in edges: + for u, v in edges: G.relax(u, v, w) j = j + 1 - for u,v in G.edges: + for u, v in G.edges: if v.d > u.d + w(u, v): return False return True + + def initialize_signle_source(self, s): for v in self.vertices: v.d = float("Inf") v.p = None s.d = 0 + + def difference_constraints(A, b): - '''A algorithm to solve a system of difference constraints Ax <= b + """A algorithm to solve a system of difference constraints Ax <= b by solving a single-source shortest-paths problem using Bellman-Ford algorithm. Each row of the linear-programming matrix A contains one 1 and one 1, and all other entries of A are 0. @@ -37,7 +42,7 @@ def difference_constraints(A, b): Calling convention: A is a two-dimensional list, b is a list. Return value: This function returns a list representing x if there exists feasible solution; otherwise, this function returns None. - ''' + """ row = len(A) col = len(A[0]) @@ -45,14 +50,14 @@ def difference_constraints(A, b): vertices = [] edges = [] weights = dict() - for i in range(0, vertices_num + 1): + for i in range(vertices_num + 1): vertices.append(Vertex(i)) for i in range(1, vertices_num + 1): edges.append((vertices[0], vertices[i])) weights[(vertices[0], vertices[i])] = 0 - for i in range(0, row): - u = A[i].index(-1) + 1 - v = A[i].index(1) + 1 + for i in range(row): + u = A[i].index(-1) + 1 + v = A[i].index(1) + 1 edges.append((vertices[u], vertices[v])) weights[(vertices[u], vertices[v])] = b[i] G = Graph(vertices, edges) @@ -60,26 +65,28 @@ def difference_constraints(A, b): return [v.d for v in vertices[1:]] else: return None + + def difference_constraints_with_arbitrary_weight(A, b): - ''' An variant to the above difference constraints function + """ An variant to the above difference constraints function that the weight of the edge from the auxiliary vertex to any other vertex can be arbitrary value. - ''' + """ row = len(A) col = len(A[0]) vertices_num = col vertices = [] edges = [] weights = dict() - distribute = sample(xrange(-10, 10), vertices_num) - for i in range(0, vertices_num + 1): + distribute = sample(range(-10, 10), vertices_num) + for i in range(vertices_num + 1): vertices.append(Vertex(i)) for i in range(1, vertices_num + 1): edges.append((vertices[0], vertices[i])) weights[(vertices[0], vertices[i])] = distribute[i - 1] - for i in range(0, row): - u = A[i].index(-1) + 1 - v = A[i].index(1) + 1 + for i in range(row): + u = A[i].index(-1) + 1 + v = A[i].index(1) + 1 edges.append((vertices[u], vertices[v])) weights[(vertices[u], vertices[v])] = b[i] G = Graph(vertices, edges) @@ -87,6 +94,8 @@ def difference_constraints_with_arbitrary_weight(A, b): return [v.d for v in vertices[1:]] else: return None + + def equality_constraints(A, b): row = len(A) col = len(A[0]) @@ -94,14 +103,14 @@ def equality_constraints(A, b): vertices = [] edges = [] weights = dict() - for i in range(0, vertices_num + 1): + for i in range(vertices_num + 1): vertices.append(Vertex(i)) for i in range(1, vertices_num + 1): edges.append((vertices[0], vertices[i])) weights[(vertices[0], vertices[i])] = 0 - for i in range(0, row): - u = A[i].index(-1) + 1 - v = A[i].index(1) + 1 + for i in range(row): + u = A[i].index(-1) + 1 + v = A[i].index(1) + 1 edges.append((vertices[u], vertices[v])) weights[(vertices[u], vertices[v])] = b[i] edges.append((vertices[v], vertices[u])) @@ -111,6 +120,8 @@ def equality_constraints(A, b): return [v.d for v in vertices[1:]] else: return None + + def difference_constraints_without_aux_vertex(A, b): row = len(A) col = len(A[0]) @@ -120,9 +131,9 @@ def difference_constraints_without_aux_vertex(A, b): weights = dict() for i in range(vertices_num): vertices.append(Vertex(i + 1)) - for i in range(0, row): - u = A[i].index(-1) - v = A[i].index(1) + for i in range(row): + u = A[i].index(-1) + v = A[i].index(1) edges.append((vertices[u], vertices[v])) weights[(vertices[u], vertices[v])] = b[i] G = Graph(vertices, edges) @@ -130,19 +141,25 @@ def difference_constraints_without_aux_vertex(A, b): return [v.d for v in vertices] else: return None + + def Bellman_Ford_without_aux_vertex(G, w): initialize_signle_source_without_aux_vertex(G) for i in range(1, len(G.vertices)): - for u,v in G.edges: + for u, v in G.edges: G.relax(u, v, w) - for u,v in G.edges: + for u, v in G.edges: if v.d > u.d + w(u, v): return False return True + + def initialize_signle_source_without_aux_vertex(G): for v in G.vertices: v.d = 0 v.p = None + + def single_variable_constraints(A, b): row = len(A) col = len(A[0]) @@ -150,10 +167,10 @@ def single_variable_constraints(A, b): vertices = [] edges = [] weights = dict() - for i in range(0, vertices_num + 1): + for i in range(vertices_num + 1): vertices.append(Vertex(i)) - for i in range(0, row): - for j in range(0, len(A[i])): + for i in range(row): + for j in range(len(A[i])): if A[i][j] == 1: edges.append((vertices[0], vertices[j + 1])) weights[(vertices[0], vertices[j + 1])] = b[i] diff --git a/constraints_test.py b/constraints_test.py deleted file mode 100644 index 7a129a2..0000000 --- a/constraints_test.py +++ /dev/null @@ -1,61 +0,0 @@ -from constraints import difference_constraints, equality_constraints, difference_constraints_without_aux_vertex, single_variable_constraints, difference_constraints_with_arbitrary_weight -import unittest -from math import floor - -class TestConstraints(unittest.TestCase): - def test_difference_constraints(self): - A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] - b = [0, -1, 1, 5, 4, -1, -3, -3] - self.assertEquals(difference_constraints(A, b), [-5, -3, 0, -1, -4]) - A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] - b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] - self.assertEquals(difference_constraints(A, b), [-5, -3, 0, -1, -6, -8]) - A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] - b = [4, 5, -6, 1, 3, 5, 10, -4, 8] - self.assertEquals(difference_constraints(A, b), None) - A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] - b = [1, -4, 2, 7.3, 5, 10.1, 2.9, -1.11, 3, -8.6] - c = [int(floor(i)) for i in b] - print difference_constraints(A, c) - - def test_equality_constraints(self): - A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] - b = [0, -1, 1, 5, 4, -1, -3, -3] - self.assertEquals(equality_constraints(A, b), None) - A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] - b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] - self.assertEquals(equality_constraints(A, b), None) - A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] - b = [4, 5, -6, 1, 3, 5, 10, -4, 8] - self.assertEquals(equality_constraints(A, b), None) - A = [[-1, 1, 0], [0, -1, 1], [-1, 0, 1]] - b = [1, 1, 2] - self.assertEquals(equality_constraints(A, b), [-2, -1, 0]) - def test_difference_constraints_without_aux_vertex(self): - A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] - b = [0, -1, 1, 5, 4, -1, -3, -3] - self.assertEquals(difference_constraints_without_aux_vertex(A, b), [-5, -3, 0, -1, -4]) - A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] - b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] - self.assertEquals(difference_constraints_without_aux_vertex(A, b), [-5, -3, 0, -1, -6, -8]) - A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] - b = [4, 5, -6, 1, 3, 5, 10, -4, 8] - self.assertEquals(difference_constraints_without_aux_vertex(A, b), None) - def test_single_variable_constraints(self): - A = [[1, 0], [0, 1], [-1, 0], [0, -1], [1, 0]] - b = [3, 1, 5, -1, 2] - self.assertEquals(single_variable_constraints(A, b), [2, 1]) - A = [[1, 0], [0, 1], [-1, 0], [0, -1], [1, 0]] - b = [3, -1, 5, -1, 2] - self.assertEquals(single_variable_constraints(A, b), None) -# def test_difference_constraints_with_arbitrary_weight(self): -# A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] -# b = [0, -1, 1, 5, 4, -1, -3, -3] -# self.assertEquals(difference_constraints_with_arbitrary_weight(A, b), [-5, -3, 0, -1, -4]) -# A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] -# b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] -# self.assertEquals(difference_constraints_with_arbitrary_weight(A, b), [-5, -3, 0, -1, -6, -8]) -# A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] -# b = [4, 5, -6, 1, 3, 5, 10, -4, 8] -# self.assertEquals(difference_constraints_with_arbitrary_weight(A, b), None) - diff --git a/contains.py b/contains.py index 816e910..87b3fa4 100644 --- a/contains.py +++ b/contains.py @@ -1,12 +1,17 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python def contains(x, n): - '''CLRS Exercise 16.2-5 + """ + CLRS Exercise 16.2-5 An algorithm that, given a set {x1, x2, ... ,xn} of points on the real line, determines the smallest set of unit-length closed intervals that contains - all of the given points.''' + all of the given points. + :param x: + :param n: + :return: + """ x.sort() - print x + print(x) i = 0 a = float("-Inf") S = set() @@ -15,5 +20,5 @@ def contains(x, n): S = S.union({(x[i], x[i] + 1)}) a = x[i] + 1 i = i + 1 - print S + print(S) return S diff --git a/contains_test.py b/contains_test.py deleted file mode 100644 index 55d405f..0000000 --- a/contains_test.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ipython - -import unittest -from contains import contains - -class TestContains(unittest.TestCase): - def test_contains(self): - x = [1, 1.5, 3.5, 2.3, 10.01] - self.assertEquals(contains(x, 5), {(1, 2), (2.3, 3.3), (3.5, 4.5), (10.01, 11.01)}) - x = [3.5, 5.2, -1.1, -4, -12, -11.33] - self.assertEquals(contains(x, 6), {(-12, -11), (-4, -3), (-1.1, -0.10000000000000009), (3.5, 4.5), (5.2, 6.2)}) - diff --git a/counting_sort.py b/counting_sort.py index 922ab3d..1d71762 100644 --- a/counting_sort.py +++ b/counting_sort.py @@ -1,8 +1,8 @@ def counting_sort(A, B, k): C = [] - for i in range(0, k + 1): + for i in range(k + 1): C.append(0) - for j in range(0, len(A)): + for j in range(len(A)): C[A[j]] = C[A[j]] + 1 for i in range(1, k + 1): C[i] = C[i] + C[i - 1] diff --git a/cut_rod.py b/cut_rod.py index 1c7473f..2689136 100644 --- a/cut_rod.py +++ b/cut_rod.py @@ -5,7 +5,9 @@ def bottom_up_cut_rod(p, n): for i in range(1, j + 1): q = max(q, p[i - 1] + r[j - i]) r[j] = q - return r[n] + return r[n] + + def bottom_up_cut_rod_two_subproblem(p, n): r = [0] * (n + 1) for i in range(1, n + 1): @@ -15,10 +17,14 @@ def bottom_up_cut_rod_two_subproblem(p, n): for i in range(1, j + 1): q = max(q, r[i] + r[j - i]) r[j] = q - return r[n] + return r[n] + + def memoized_cut_rod(p, n): r = [float("-Inf")] * n return memoized_cut_rod_aux(p, n, r) + + def memoized_cut_rod_aux(p, n, r): if n == 0: return 0 @@ -29,6 +35,8 @@ def memoized_cut_rod_aux(p, n, r): q = max(q, p[i - 1] + memoized_cut_rod_aux(p, n - i, r)) r[n - 1] = q return q + + def extended_bottom_up_cut_rod(p, n): r = [0] * (n + 1) s = [0] * (n + 1) @@ -39,12 +47,16 @@ def extended_bottom_up_cut_rod(p, n): q = p[i - 1] + r[j - i] s[j] = i r[j] = q - return r,s + return r, s + + def print_cut_rod_solution(p, n, cut): - r,s = cut(p, n) + r, s = cut(p, n) while n != 0: - print s[n] + print(s[n]) n = n - s[n] + + def bottom_up_cut_rod_with_fixed_cut_cost(p, n, c): r = [0] * (n + 1) for j in range(1, n + 1): @@ -53,12 +65,16 @@ def bottom_up_cut_rod_with_fixed_cut_cost(p, n, c): q = max(q, r[i] + r[j - i] - c) q = max(q, p[j - 1]) r[j] = q - return r[n] + return r[n] + + def extended_memoized_cut_rod(p, n): r = [float("-Inf")] * n s = [0] * (n + 1) extended_memoized_cut_rod_aux(p, n, r, s) - return r,s + return r, s + + def extended_memoized_cut_rod_aux(p, n, r, s): if n == 0: return 0 @@ -66,7 +82,7 @@ def extended_memoized_cut_rod_aux(p, n, r, s): return r[n - 1] q = float("-Inf") for i in range(1, n + 1): - value = p[i - 1] + extended_memoized_cut_rod_aux(p, n -i, r, s) + value = p[i - 1] + extended_memoized_cut_rod_aux(p, n - i, r, s) if q < value: q = value s[n] = i diff --git a/cut_rod_test.py b/cut_rod_test.py deleted file mode 100755 index 13a9d6a..0000000 --- a/cut_rod_test.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env ipython -import unittest - -from cut_rod import bottom_up_cut_rod, bottom_up_cut_rod_two_subproblem, memoized_cut_rod, print_cut_rod_solution, bottom_up_cut_rod_with_fixed_cut_cost, extended_memoized_cut_rod - -class TestCutRod(unittest.TestCase): - def test_bottom_up_cut_rod(self): - p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] - values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] - for i in range(0, len(values), 2): - self.assertEquals(bottom_up_cut_rod(p, values[i]), values[i + 1]) - def test_bottom_up_cut_rod_two_subproblem(self): - p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] - values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] - for i in range(0, len(values), 2): - self.assertEquals(bottom_up_cut_rod_two_subproblem(p, values[i]), values[i + 1]) - def test_memoized_cut_rod(self): - p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] - values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] - for i in range(0, len(values), 2): - self.assertEquals(memoized_cut_rod(p, values[i]), values[i + 1]) - def test_bottom_up_cut_rod_with_fixed_cut_cost(self): - p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] - values = [1, 1, 2, 5, 3, 8, 4, 9, 5, 11, 6, 17, 7, 17, 8, 20, 9, 24, 10, 30] - for i in range(0, len(values), 2): - self.assertEquals(bottom_up_cut_rod_with_fixed_cut_cost(p, values[i], 2), values[i + 1]) - values = [1, 1, 2, 5, 3, 8, 4, 9, 5, 11.5, 6, 17, 7, 17, 8, 20.5, 9, 24, 10, 30] - for i in range(0, len(values), 2): - self.assertEquals(bottom_up_cut_rod_with_fixed_cut_cost(p, values[i], 1.5), values[i + 1]) - def test_print_rod_solution(self): - p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] - values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] - print_cut_rod_solution(p, 9, extended_memoized_cut_rod) diff --git a/depth_tree.py b/depth_tree.py index 4440928..72e2107 100644 --- a/depth_tree.py +++ b/depth_tree.py @@ -1,27 +1,33 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python # A variant of red black tree that has depth attribute -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class depth_node(rb_node): + +class depth_node(RbNode): def __init__(self, key, p, left, right, color, depth): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.depth = depth + def update_depth_whole_tree(self, amount): if self.depth != -1: self.left.update_depth_whole_tree(amount) self.depth = self.depth + amount self.right.update_depth_whole_tree(amount) -class depth_tree(rb_tree): + + +class depth_tree(RbTree): nil = depth_node(None, None, None, None, 1, -1) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: self.insert(depth_node(i, None, None, None, 0, 0)) else: - print "Not invalid argument" + print("Not invalid argument") + def left_rotate(self, x): y = x.right x.right = y.left @@ -40,6 +46,7 @@ def left_rotate(self, x): y.depth = y.depth - 1 x.left.update_depth_whole_tree(1) y.right.update_depth_whole_tree(-1) + def right_rotate(self, y): x = y.left y.left = x.right @@ -58,6 +65,7 @@ def right_rotate(self, y): y.depth = y.depth + 1 x.left.update_depth_whole_tree(-1) y.right.update_depth_whole_tree(1) + def insert(self, z): y = self.nil x = self.root @@ -79,8 +87,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def delete(self, z): y = z y_original_color = y.color diff --git a/deque.py b/deque.py index 61509a4..0391352 100644 --- a/deque.py +++ b/deque.py @@ -1,32 +1,38 @@ -from queue import queue, FullException, EmptyException - -def deque(queue): - ''' - whereas a queue allows insertion at one end and deletion at the other end, a deque(double-ended queue allows insertion and deletion at both ends - ''' - def __init__(self, size): - super(deque, self).__init__(size) - def enqueue_tail(self, x): - self.enqueue(x) - def dequeue_head(self): - return self.dequeue() - def enqueue_head(self, x): - if self.full(): - raise FullException("This double-ended queue is full") - else: - if self.head == 0: - self.head = self.length - 1 - else: - self.head = self.head - 1 - self[self.head] = x - def dequeue_tail(self): - if self.emtpy(): - raise EmptyException("This double-ended queue is empty") - else: - if self.tail == 0: - self.tail = self.length - 1 - else: - self.tail = self.tail - 1 - - return self[self.tail] +from Queue import Queue, FullException, EmptyException + +class Deque(Queue): + """ + whereas a Queue allows insertion at one end and deletion at the other end, + a Deque(double-ended Queue) allows insertion and deletion at both ends + """ + + def __init__(self, size): + super().__init__(size) + + def enqueue_tail(self, x): + self.enqueue(x) + + def dequeue_head(self): + return self.dequeue() + + def enqueue_head(self, x): + if self.full(): + raise FullException() + else: + if self.head == 0: + self.head = self.size - 1 + else: + self.head = self.head - 1 + self.data[self.head] = x + + def dequeue_tail(self): + if self.empty(): + raise EmptyException() + else: + if self.tail == 0: + self.tail = self.size - 1 + else: + self.tail = self.tail - 1 + + return self.data[self.tail] diff --git a/disjoint_sets_forest.py b/disjoint_sets_forest.py index 09ff777..20f20a6 100644 --- a/disjoint_sets_forest.py +++ b/disjoint_sets_forest.py @@ -1,24 +1,28 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -class node(object): + +class node: def __init__(self, key): self.key = key - #key.index = self + # key.index = self self.p = self self.rank = 0 self.child = [] + def union(self, y): self.find_set().link(y.find_set()) + def link(self, y): x = self if x.rank > y.rank: - x.child.append(y) + x.child.append(y) y.p = x else: - y.child.append(x) + y.child.append(x) x.p = y if x.rank == y.rank: y.rank = y.rank + 1 + def find_set(self): y = self x = self @@ -28,15 +32,17 @@ def find_set(self): z = x x = x.p z.p = y -# print y.key + # print( y.key) return y + def print_set(self): x = self while x != x.p: x = x.p x.print_set_aux() + def print_set_aux(self): - print self.key + print(self.key) if len(self.child) == 0: return for child in self.child: diff --git a/disjoint_sets_linked_list.py b/disjoint_sets_linked_list.py index af279c0..ea1895b 100644 --- a/disjoint_sets_linked_list.py +++ b/disjoint_sets_linked_list.py @@ -1,12 +1,14 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -class node(object): +class node: def __init__(self, key): self.key = key self.set = None self.next = None + def find_set(self): return self.set.head + def union(self, y): if self.set.length < y.set.length: x = y @@ -23,12 +25,16 @@ def union(self, y): xs.tail = ys.tail xs.length = xs.length + ys.length return x -class header(object): + + +class header: def __init__(self, element): self.length = 1 self.head = element element.set = self self.tail = self.head + + class node_notail(node): def union(self, y): if self.set.length < y.set.length: @@ -47,7 +53,9 @@ def union(self, y): xs.head = ys.head xs.length = xs.length + ys.length return y -class header_notail(object): + + +class header_notail: def __init__(self, element): self.length = 1 self.head = element diff --git a/dynamic_array.py b/dynamic_array.py new file mode 100644 index 0000000..2defc73 --- /dev/null +++ b/dynamic_array.py @@ -0,0 +1,21 @@ +class DynamicArray: + def __init__(self, capacity): + assert capacity > 0 + self._capacity = capacity + self._size = 0 + self._data = [None] * capacity + + def add(self, element): + if self._size == self._capacity: + temp = self._data + self._data = [None] * (self._capacity * 2) + self._data[:self._capacity] = temp[:] + self._capacity *= 2 + self._data[self._size] = element + self._size += 1 + + def size(self): + return self._size + + def get(self, index): + return self._data[index] diff --git a/eight_queen.py b/eight_queen.py new file mode 100644 index 0000000..6c4f155 --- /dev/null +++ b/eight_queen.py @@ -0,0 +1,37 @@ +N = 8 +counter = 0 + + +def print_solution(chess_board): + for row in range(N): + for col in range(N): + if chess_board[row] != col: + print('-', end=' ') + else: + print('X', end=' ') + print('\n') + print('\n') + + +def isplaceok(chess_board, row, col): + return not any( + (chess_board[i] == col) or (chess_board[i] - col == row - i) or (chess_board[i] - col == i - row) for i in + range(row)) + + +def add_queen(chess_board, row): + global counter + if row >= N: + print_solution(chess_board) + counter += 1 + else: + for col in range(N): + if isplaceok(chess_board, row, col): + chess_board[row] = col + add_queen(chess_board, row + 1) + + +if __name__ == "__main__": + chess_board = [-1] * N + add_queen(chess_board, 0) + print(counter) diff --git a/euclid.py b/euclid.py index e5f97bc..3d81b24 100644 --- a/euclid.py +++ b/euclid.py @@ -1,15 +1,17 @@ #!/usr/bin/env python # coding=utf-8 + def euclid(a, b): if b == 0: return a else: return euclid(b, a % b) + def extended_euclid(a, b): if b == 0: - return (a, 1, 0) + return a, 1, 0 else: d, x, y = extended_euclid(b, a % b) return d, y, x - (a / b) * y diff --git a/extended_bottom_up_cut_rod.py b/extended_bottom_up_cut_rod.py index ff4bdb2..316e42a 100644 --- a/extended_bottom_up_cut_rod.py +++ b/extended_bottom_up_cut_rod.py @@ -8,10 +8,11 @@ def extended_bottom_up_cut_rod(p, n): q = p[i - 1] + r[j - i] s[j] = i r[j] = q - return r, s + return r, s + def print_cut_rod_solution(p, n): - r,s = extended_bottom_up_cut_rod(p, n) + r, s = extended_bottom_up_cut_rod(p, n) while n > 0: - print s[n] + print(s[n]) n = n - s[n] diff --git a/fft.py b/fft.py index dd5ee18..e90b743 100644 --- a/fft.py +++ b/fft.py @@ -1,7 +1,8 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import math + def recursive_fft(a): n = len(a) if n == 1: @@ -13,16 +14,19 @@ def recursive_fft(a): y0 = recursive_fft(a0) y1 = recursive_fft(a1) y = [0.0] * n - for k in range(0, n / 2): + for k in range(n // 2): y[k] = y0[k] + w * y1[k] - y[k + n / 2] = y0[k] - w * y1[k] + y[k + n // 2] = y0[k] - w * y1[k] w = w * wn return y + def recursive_inverse_fft(y): n = len(y) result = recursive_inverse_fft_aux(y) - return [result[i] / n for i in range(0, n)] + return [result[i] / n for i in range(n)] + + def recursive_inverse_fft_aux(y): n = len(y) if n == 1: @@ -34,8 +38,8 @@ def recursive_inverse_fft_aux(y): a0 = recursive_inverse_fft_aux(y0) a1 = recursive_inverse_fft_aux(y1) a = [0.0] * n - for k in range(0, n / 2): + for k in range(n // 2): a[k] = (a0[k] + w * a1[k]) - a[k + n / 2] = (a0[k] - w * a1[k]) + a[k + n // 2] = (a0[k] - w * a1[k]) w = w * wn return a diff --git a/fibonacci_heap.py b/fibonacciheap.py similarity index 73% rename from fibonacci_heap.py rename to fibonacciheap.py index 53739b8..778ddcc 100644 --- a/fibonacci_heap.py +++ b/fibonacciheap.py @@ -1,17 +1,21 @@ -class fibonacci_node(object): +class FibonacciNode: degree = 0 p = None child = None mark = False left = None right = None + def __init__(self, k): self.key = k + def __iter__(self): - '''generate a list of children of the node for iteration''' + """ + generate a list of children of the node for iteration + """ self.children = [] self.index = 0 - if self.child != None: + if self.child is not None: child = self.child while True: self.children.append(child) @@ -20,39 +24,53 @@ def __iter__(self): else: break return self + def next(self): if self.index < len(self.children): self.index = self.index + 1 return self.children[self.index - 1] else: raise StopIteration + def insert(self, x): - '''insert x to the left of node''' + """ + insert x to the left of node + :param x: + :return: + """ x.left = self.left x.right = self self.left.right = x - self.left = x + self.left = x + def concatenate(self, x): - '''concatenate two lists represented by the node and x, - x mustn't be None''' + """ + concatenate two lists represented by the node and x, + x mustn't be None + :param x: + :return: + """ self.left.right = x.right x.right.left = self.left self.left = x x.right = self + def remove(self): - self.left.right = self.right + self.left.right = self.right self.right.left = self.left + def add_child(self, y): self.degree = self.degree + 1 y.mark = False y.p = self - if self.child == None: + if self.child is None: self.child = y y.left = y y.right = y else: - self.child.insert(y) - print "y.left.key = {}, y.right.key = {}".format(y.left.key, y.right.key) + self.child.insert(y) + print("y.left.key = {}, y.right.key = {}".format(y.left.key, y.right.key)) + def remove_child(self, y): self.degree = self.degree - 1 if y.right == y: @@ -62,15 +80,21 @@ def remove_child(self, y): y.remove() else: y.remove() -class fibonacci_heap(object): + + +class FibonacciHeap: def __init__(self): self.n = 0 self.minimum = None + def __iter__(self): - '''generate a list of children of the node for iteration''' + """ + generate a list of children of the node for iteration + :return: + """ self.root_list = [] self.index = 0 - if self.minimum != None: + if self.minimum is not None: root = self.minimum while True: self.root_list.append(root) @@ -79,18 +103,20 @@ def __iter__(self): else: break return self + def next(self): if self.index < len(self.root_list): self.index = self.index + 1 return self.root_list[self.index - 1] else: raise StopIteration + def __repr__(self): s = '' x = self.minimum - if x != None: + if x is not None: while True: - s = s + '\t' + str(x.key) + s = s + '\t' + str(x.key) if x == self.minimum.left: break else: @@ -98,10 +124,15 @@ def __repr__(self): return s else: return '' + def insert(self, x): - '''insert the node x into the root list of fibonacci heap''' + """ + insert the node x into the root list of fibonacci heap + :param x: + :return: + """ x.p = None - if self.minimum == None: + if self.minimum is None: self.minimum = x x.left = x x.right = x @@ -110,13 +141,15 @@ def insert(self, x): if x.key < self.minimum.key: self.minimum = x self.n = self.n + 1 + def minimum(self): return self.minimum + def union(self, h): - cat = fibonacci_heap() - if self.minimum == None: + cat = FibonacciHeap() + if self.minimum is None: return h - elif h.minimum == None: + elif h.minimum is None: return self else: self.minimum.concatenate(h.minimum) @@ -126,9 +159,10 @@ def union(self, h): cat.minimum = h.minimum cat.n = self.n + h.n return cat + def extract_min(self): z = self.minimum - if z != None: + if z is not None: for child in z: self.insert(child) z.remove() @@ -139,54 +173,61 @@ def extract_min(self): self.consolidate() self.n = self.n - 1 return z + def consolidate(self): - D = self.n / 2 + D = self.n // 2 A = [None] * (D + 1) left = self.minimum.left w = self.minimum for w in self: x = w d = x.degree - print 'w.key = {}'.format(w.key) - print 'w.degree = {}'.format(w.degree) - while A[d] != None: + print('w.key = {}'.format(w.key)) + print('w.degree = {}'.format(w.degree)) + while A[d] is not None: y = A[d] if x.key > y.key: - x,y = y,x + x, y = y, x self.link(y, x) A[d] = None d = d + 1 A[d] = x self.minimum = None for i in A: - if i != None: + if i is not None: self.insert(i) - def link(self, y, x): + + @staticmethod + def link(y, x): y.remove() x.add_child(y) + def decrease_key(self, x, k): if k > x.key: - print "new key is greater than current key" + print("new key is greater than current key") return x.key = k y = x.p - if y != None and x.key < y.key: + if y is not None and x.key < y.key: self.cut(x, y) self.cascading_cut(y) if x.key < self.minimum.key: self.minimum = x + def cut(self, x, y): y.remove_child(x) x.mark = False self.insert(x) + def cascading_cut(self, y): z = y.p - if z != None: - if y.mark == False: + if z is not None: + if y.mark is False: y.mark = True else: self.cut(y, z) self.cascading_cut(z) + def delete(self, x): self.decrease_key(x, float("-Inf")) self.extract_min() diff --git a/gcd.c b/gcd.c deleted file mode 100644 index 8dd5f52..0000000 --- a/gcd.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -/* gcd: compute the greatest common divisor of m and n; - return value: gcd */ - unsigned gcd(unsigned m, unsigned n) { - unsigned rem; - - while (n > 0) - { - rem = m % n; - m = n; - n = rem; - } - return m; -} - -int main() { - printf("%u\n", gcd(63 - 1194 + 1387, 1387)); - printf("%u\n", gcd(1273, 1387)); - return 0; -} diff --git a/gcd.py b/gcd.py new file mode 100644 index 0000000..ca4e42e --- /dev/null +++ b/gcd.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +def gcd(m: int, n: int): + """ + compute the greatest common divisor of m and n; + :param m: + :param n: + :return: + """ + while n > 0: + rem = m % n + m = n + n = rem + return m diff --git a/graph.py b/graph.py index d1a019d..004e05a 100644 --- a/graph.py +++ b/graph.py @@ -1,150 +1,150 @@ -from queue import queue +from queue import Queue import disjoint_sets_forest as dsf import sys +from typing import Iterable, Optional, Tuple, Set, Dict +from enum import Enum -class Vertex(object): +Color = Enum('Color', ('WHITE', 'GREY', 'BLACK')) + + +class Vertex: def __init__(self, key): self.key = key def __repr__(self): - return str(self.key) + return f"Vertex({self.key})" def print_path(self, v): - '''print out the vertices on a shortest path from s to - v, assuming that BFS has already computed a breadth-first tree''' + """ + print out the vertices on a shortest path from s to + v, assuming that BFS has already computed a breadth-first tree + """ if self == v: - print self, - elif v.p == None: - print "No path from {} to {} exists".format(self.key, v.key) + print(self) + elif v.p is None: + print("No path from {} to {} exists".format(self.key, v.key)) else: self.print_path(v.p) - print v, - -class Graph(object): - def __init__(self, vertices = tuple(), edges = tuple(), directed = True): - self.directed = directed - self.vertices = set(vertices) - self.edges = set() - self.adj = dict() - for u in vertices: + print(v) + + +Vertices = Optional[Iterable[Vertex]] +Edge = Tuple[Vertex, Vertex] +Edges = Optional[Iterable[Edge]] + + +class Graph: + def __init__(self, vertices: Optional[Vertices] = None, + edges: Optional[Edges] = None, directed: bool = True): + self.directed: bool = directed + self.vertices: Set[Vertex] = set() if vertices is None else set(vertices) + self.edges: Set[Edge] = set() + self.adj: Dict[Vertex, Set[Vertex]] = dict() + self._time: int = 0 + for u in self.vertices: self.adj[u] = set() - for u, v in edges: - self._addEdge(u, v) - - def __eq__(self, G2): - G1 = self - if G1.directed != G2.directed: - return False - elif G1.vertices != G2.vertices: - return False - elif G1.edges != G2.edges: - return False - else: - for u in G1.vertices: - if G1.adj[u] != G2.adj[u]: - return False - return True + if edges is not None: + for u, v in edges: + self._add_edge(u, v) + + def __eq__(self, graph2: 'Graph'): + graph1 = self + return (graph1.directed == graph2.directed) and (graph1.vertices == graph2.vertices) and ( + graph1.edges == graph2.edges) - def _addEdge(self, u, v): + def _add_edge(self, u: Vertex, v: Vertex): if self.directed: self.adj[u].add(v) self.edges.add((u, v)) - elif u != v: # undirected graph does not allow self loop + elif u != v: # undirected graph does not allow self loop self.adj[u].add(v) self.edges.add((u, v)) self.adj[v].add(u) self.edges.add((v, u)) - def _addVertex(self, u, edges = tuple()): - self.vertices.add(u) - for u, v in edges: - self._addEdge(u, v) + def _add_vertex(self, u: Vertex, edges: Optional[Edges] = None): + self.vertices.add(u) + if edges is not None: + for u, v in edges: + self._add_edge(u, v) def copy(self): return Graph(self.vertices, self.edges, self.directed) def transpose(self): - t = Graph(self.vertices) - for u in self.vertices: - for v in self.adj[u]: - t._addEdge(v, u) - return t + return Graph(self.vertices, [(v, u) for u, v in self.edges], self.directed) - def bfs(self, s): + def bfs(self, s: Vertex): for u in self.vertices: - u.d = float("Inf") - u.color = 0 - u.p = None - s.color = 1 - s.d = 0 - s.p = None - q = queue(2 * len(self.vertices)) - q.enqueue(s) - while not q.empty(): - u = q.dequeue() + u.distance = float("Inf") + u.color = Color.WHITE + u.parent = None + s.color = Color.GREY + s.distance = 0 + s.parent = None + queue = Queue() + queue.put(s) + while not queue.empty(): + u = queue.get() for v in self.adj[u]: - if v.color == 0: - v.color = 1 - v.d = u.d + 1 - v.p = u - q.enqueue(v) - u.color = 2 + if v.color == Color.WHITE: + v.color = Color.GREY + v.distance = u.distance + 1 + v.parent = u + queue.put(v) + u.color = Color.BLACK def dfs(self): - global time + self._time = 0 for u in self.vertices: - u.color = 0 + u.color = Color.WHITE u.p = None - time = 0 for u in self.vertices: - if u.color == 0: + if u.color == Color.WHITE: self._dfs_visit(u) - def _dfs_visit(self, u): - global time - time = time + 1 - u.d = time - u.color = 1 + def _dfs_visit(self, u: Vertex): + self._time += 1 + u.d = self._time + u.color = Color.GREY for v in self.adj[u]: - if v.color == 0: + if v.color == Color.WHITE: v.p = u self._dfs_visit(v) - u.color = 2 - time = time + 1 - u.f = time + u.color = Color.BLACK + self._time += 1 + u.f = self._time - def isCyclic(self): - global time + def is_cyclic(self): for u in self.vertices: - u.color = 0 - u.p = None - time = 0 + u.color = Color.WHITE for u in self.vertices: - if u.color == 0: + if u.color == Color.WHITE: if self._is_cyclic_aux(u): return True return False def _is_cyclic_aux(self, u): - global time - time = time + 1 - u.d = time - u.color = 1 + u.color = Color.GREY for v in self.adj[u]: - if v.color == 0: - v.p = u + if v.color == Color.WHITE: if self._is_cyclic_aux(v): return True - elif v.color == 1: + elif v.color == Color.GREY: return True - u.color = 2 - time = time + 1 - u.f = time + u.color = Color.BLACK return False def topological_sort(self): + """ + Perform topological sort for dag + + A topological sort of a dag(directed acyclic graph) G = (V, E) is a linear ordering of all the vertices + such that if G contains an edge (u, v), then u appears before v in the ordering. + """ + assert (not self.is_cyclic()) and self.directed self.dfs() - return sorted(self.vertices, key = lambda x: x.f, reverse = True) + return sorted(self.vertices, key=lambda x: x.f, reverse=True) def print_all_edges(self): s = next(iter(self.vertices)) @@ -154,15 +154,16 @@ def print_all_edges(self): def _print_all_edges_aux(self, u): for v in self.adj[u]: if u == v.p: - print (u, v) + print((u, v)) self._print_all_edges_aux(v) - print (v, u) + print((v, u)) else: pass + def printAllEdges(self): self.status = dict() s = next(iter(self.vertices)) - print "key of s is {}".format(s.key) + print("key of s is {}".format(s.key)) self.printAllEdges_aux(s) def printAllEdges_aux(self, u): @@ -172,16 +173,16 @@ def printAllEdges_aux(self, u): except KeyError: self.status[(u, v)] = 1 self.status[(v, u)] = 1 - print (u, v) + print((u, v)) self.printAllEdges_aux(v) - print (v, u) + print((v, u)) def path_num(self, s, t): - ''' + """ A linear-time algorithm that takes as input a directed acyclic graph G = (V, E) and two vertices s and t, and returns the number of simple paths from s to t in G. - ''' + """ for u in self.vertices: u.color = 0 u.num = 0 @@ -208,7 +209,7 @@ def strongly_connected_components(self): u.p = None time = 0 cc = 0 - for u in sorted(self.vertices, key = lambda u: u.f, reverse = True): + for u in sorted(self.vertices, key=lambda u: u.f, reverse=True): if u.color == 0: cc = cc + 1 t.strongly_connected_components_dfs_visit(u) @@ -226,13 +227,17 @@ def strongly_connected_components_dfs_visit(self, u): u.color = 2 time = time + 1 u.f = time + def simplified(self): - '''create a simplified graph that has the same strong + """ + create a simplified graph that has the same strong connected components and component graph as G and that is as small - as possible''' + as possible + """ self.dfs() t = self.transpose() return t.simplified_dfs() + def simplified_dfs(self): global time, cc, status status = dict() @@ -242,16 +247,17 @@ def simplified_dfs(self): u.p = None time = 0 cc = 0 - for u in sorted(self.vertices, key = lambda u: u.f, reverse = True): + for u in sorted(self.vertices, key=lambda u: u.f, reverse=True): if u.color == 0: stack = [] cc = cc + 1 self.simplified_dfs_visit(u, stack, s) - for i in range(0, len(stack) - 1): - s._addEdge(stack[i], stack[i + 1]) + for i in range(len(stack) - 1): + s._add_edge(stack[i], stack[i + 1]) if len(stack) > 1: - s._addEdge(stack[len(stack) - 1], stack[0]) + s._add_edge(stack[len(stack) - 1], stack[0]) return s + def simplified_dfs_visit(self, u, stack, s): global time, cc, status stack.append(u) @@ -267,18 +273,22 @@ def simplified_dfs_visit(self, u, stack, s): try: st = status[(v.cc, u.cc)] except KeyError: - status[(v.cc, u.cc)] = 1 - s._addEdge(v, u) + status[(v.cc, u.cc)] = 1 + s._add_edge(v, u) u.color = 2 time = time + 1 u.f = time + def component_graph(self): - '''compute the component graph of a directed graph - there is at most one edge between two vertices in the component graph''' - global time, cc, cg, status, vertices_list + """ + compute the component graph of a directed graph + there is at most one edge between two vertices in the component graph + :return: + """ + global time, cc, cg, status, vertices_list self.dfs() - t = self.transpose() - for u in t.vertices: + t = self.transpose() + for u in t.vertices: u.color = 0 u.p = None time = 0 @@ -286,13 +296,14 @@ def component_graph(self): status = dict() vertices_list = list() cg = Graph() - for u in sorted(self.vertices, key = lambda u: u.f, reverse = True): + for u in sorted(self.vertices, key=lambda u: u.f, reverse=True): if u.color == 0: cc = cc + 1 vertices_list.append(Vertex(cc)) - cg._addVertex(vertices_list[cc - 1]) + cg._add_vertex(vertices_list[cc - 1]) t.component_graph_dfs_visit(u) return cg + def component_graph_dfs_visit(self, u): global time, cc, cg, vertices_list u.cc = cc @@ -307,23 +318,29 @@ def component_graph_dfs_visit(self, u): try: st = status[(v.cc, u.cc)] except KeyError: - status[(v.cc, u.cc)] = 1 - cg._addEdge(vertices_list[v.cc - 1], vertices_list[u.cc - 1]) + status[(v.cc, u.cc)] = 1 + cg._add_edge( + vertices_list[v.cc - 1], + vertices_list[u.cc - 1]) u.color = 2 time = time + 1 u.f = time + def semiconnected(self): cg = self.component_graph() - vertices_list = sorted(cg.vertices, key = lambda u: u.key, reverse = False) - for i in range(0, len(vertices_list) - 1): + vertices_list = sorted(cg.vertices, key=lambda u: u.key, reverse=False) + for i in range(len(vertices_list) - 1): if vertices_list[i + 1] not in cg.adj[vertices_list[i]]: return False return True + def cut(self, x, y, w): - '''For a given edge (x, y) contained in some minimum spanning tree, + """ + For a given edge (x, y) contained in some minimum spanning tree, form a minimum spanning tree that contains (x, y) using a method like Prim's algorithm, and construct a cut (S, V - S) such that (x, y) is the light edge crossing - the cut, S = {u: u.root = x}''' + the cut, S = {u: u.root = x} + """ for v in self.vertices: v.weight = float("Inf") v.p = None @@ -340,6 +357,7 @@ def cut(self, x, y, w): v.root = u.root q.heap_decrease_key(v.index, w(u, v)) v.p = u + def alledges_undirected_dfs(self): global time, l for u in self.vertices: @@ -351,6 +369,7 @@ def alledges_undirected_dfs(self): if u.color == 0: self.alledges_undirected_dfs_visit(u) return l + def alledges_undirected_dfs_visit(self, u): global time, l time = time + 1 @@ -362,24 +381,28 @@ def alledges_undirected_dfs_visit(self, u): v.p = u self.alledges_undirected_dfs_visit(v) elif v.color == 1 and u.p != v: - l.append((u, v)) + l.append((u, v)) u.color = 2 time = time + 1 u.f = time + def Kruskal(self, w): A = set() for v in self.vertices: - dsf_node(v) -# ls = self.alledges_undirected_dfs() - for u,v in sorted(self.edges, key=lambda x: w(x[0], x[1]), reverse = False): + DfsNode(v) + # ls = self.alledges_undirected_dfs() + for u, v in sorted(self.edges, key=lambda x: w(x[0], x[1]), reverse=False): if u.index.find_set() != v.index.find_set(): - A = A.union({(u,v)}) + A = A.union({(u, v)}) u.index.union(v.index) return A + def Prim(self, w, r): - '''G.Prim(weight, root) -- Given weight function + """ + G.Prim(weight, root) -- Given weight function and an arbitrary vertex root of the graph G, - compute minimum spanning tree using Prim's algorithm''' + compute minimum spanning tree using Prim's algorithm + """ for v in self.vertices: v.weight = float("Inf") v.p = None @@ -391,28 +414,29 @@ def Prim(self, w, r): if v in q and w(u, v) < v.weight: v.p = u q.heap_decrease_key(v.index, w(u, v)) -# def Prim_vEB(self, w, r, bound): -# '''G.Prim(weight, root) -- Given weight function -# and an arbitrary vertex root of the graph G, -# compute minimum spanning tree using Prim's algorithm''' -# for v in self.vertices: -# v.weight = bound - 1 -# v.p = None -# r.weight = 0 -# t = vEB_node(bound) -# for u in self.vertices: -# t.insert(u) -# while t.size > 0: -# u = t.minimum() -# t.delete(u) -# for v in self.adj[u]: -# if t.member(v) and w(u, v) < v.weight: -# v.p = u -# t.delete(v) -# v.weight = w(u, v) -# t.insert(v) + + # def Prim_vEB(self, w, r, bound): + # """G.Prim(weight, root) -- Given weight function + # and an arbitrary vertex root of the graph G, + # compute minimum spanning tree using Prim's algorithm""" + # for v in self.vertices: + # v.weight = bound - 1 + # v.p = None + # r.weight = 0 + # t = vEB_node(bound) + # for u in self.vertices: + # t.insert(u) + # while t.size > 0: + # u = t.minimum() + # t.delete(u) + # for v in self.adj[u]: + # if t.member(v) and w(u, v) < v.weight: + # v.p = u + # t.delete(v) + # v.weight = w(u, v) + # t.insert(v) def Bellman_Ford(self, w, s): - ''' + """ The Bellman-Ford algorithm solves the single-source shortest-paths problem in the general case in which edge weights may be negative. @@ -421,49 +445,53 @@ def Bellman_Ford(self, w, s): no solution exists. If there is no such cycle, this function returns True and produces the shortest paths and their weights. - ''' + """ self.initialize_signle_source(s) for i in range(1, len(self.vertices)): - for u,v in self.edges: + for u, v in self.edges: self.relax(u, v, w) - for u,v in self.edges: + for u, v in self.edges: if v.d > u.d + w(u, v): return False return True + def initialize_signle_source(self, s): for v in self.vertices: v.d = float("Inf") v.p = None s.d = 0 + def relax(self, u, v, w): if v.d > u.d + w(u, v): v.d = u.d + w(u, v) v.p = u + def Bellman_Ford_modified(self, w, s): - ''' + """ Given a weighted, directed graph G = (V, E) with no negative-weight cycles, let m be the maximum over all vertices v of the minimum number of edges in a shortest path from the source s to v. This variant to the Bellman-Ford algorithm terminates in m + 1 passes, even if m is not known in advance. - ''' + """ modified = True number = 0 self.initialize_signle_source(s) for i in range(1, len(self.vertices)): if modified: - for u,v in self.edges: + for u, v in self.edges: number = self.relax_modified(u, v, w) + number if number == 0: modified = False number = 0 else: break - for u,v in self.edges: + for u, v in self.edges: if v.d > u.d + w(u, v): return False return True + def relax_modified(self, u, v, w): if v.d > u.d + w(u, v): v.d = u.d + w(u, v) @@ -471,18 +499,20 @@ def relax_modified(self, u, v, w): return 1 else: return 0 + def dag_shortest_paths(self, w, s): - ''' + """ compute shortest paths from a single source s for a directed acyclic graph with a weight function w - ''' + """ l = self.topological_sort() self.initialize_signle_source(s) for u in l: for v in self.adj[u]: self.relax(u, v, w) + def dag_shortest_paths_modified(self, s): - ''' + """ In the PERT chart analysis, vertices repre sent jobs and edges represent sequencing contraints; that is, edge (u, v) would @@ -496,28 +526,30 @@ def dag_shortest_paths_modified(self, s): vertices in linear time. This function return a list of vertices in a longest path - ''' + """ sink = Vertex("sink") vertices = self.vertices.union({sink}) edges = self.edges.union(set([(v, sink) for v in G.vertices])) Ga = Graph(vertices, edges) Ga.dag_shortest_paths(lambda u, v: -u.weight, s) u = sink - l = [] - while u.p != None: - l.append(u.p) + l = [] + while u.p is not None: + l.append(u.p) u = u.p return l[::-1] + def total_path_number(self): - ''' + """ A algorithm to count the total number of paths in a directed acyclic graph - ''' + """ number = 0 self._total_path_number_dfs() for v in self.vertices: number = number + v.num return number + def _total_path_number_dfs(self): global time for u in self.vertices: @@ -528,6 +560,7 @@ def _total_path_number_dfs(self): for u in self.vertices: if u.color == 0: self._total_path_number_dfs_visit(u) + def _total_path_number_dfs_visit(self, u): global time time = time + 1 @@ -541,12 +574,13 @@ def _total_path_number_dfs_visit(self, u): u.color = 2 time = time + 1 u.f = time + def Dijkstra(self, w, s): - ''' + """ Dijkstra's algorithm solves the single-source shortest-paths problem on a weighted, directed graph G = (V, E) for the case in which all edge weights are nonnegative. - ''' + """ self.initialize_signle_source(s) S = set() Q = min_priority_queue(self.vertices, 'd') @@ -558,15 +592,16 @@ def Dijkstra(self, w, s): v.d = u.d + w(u, v) v.p = u Q.heap_decrease_key(v.index, u.d + w(u, v)) + def Dijkstra_modified(self, w, s, W): - ''' + """ A algorithm to the the case when the values of the weight function w is in the range {0, 1, ..., W} for some nonnegative integer W. - ''' + """ self.initialize_signle_source(s) A = [] - for i in range(0, W * len(self.vertices) + 1): + for i in range(W * len(self.vertices) + 1): A.append(set()) A[0].add(s) i = 0 @@ -576,10 +611,10 @@ def Dijkstra_modified(self, w, s, W): i = i + 1 if i > W * len(self.vertices): break - print "i = {}".format(i) + print("i = {}".format(i)) u = A[i].pop() - print u - print A[i] + print(u) + print(A[i]) S.add(u) for v in self.adj[u]: if v.d > u.d + w(u, v): @@ -590,63 +625,64 @@ def Dijkstra_modified(self, w, s, W): v.p = u def single_edge(self): - ''' + """ An algorithm that given an adjacency-list representation of a multigraph G = (V, E), compute the adjacency-list representation of the "equivalent" undirected graph G2 = (V, E2), where E2 consists of the edges in E with all multiple edges between two vertices replaced by a single edge and with all self-loops removed - ''' - return Graph(self.vertices, self.edges, directed = False) + """ + return Graph(self.vertices, self.edges, directed=False) def union(self, G2): if self.directed != G2.directed: - print "The two graphs must be either both directed graphs or both undirected graphs" + print("The two graphs must be either both directed graphs or both undirected graphs") return None vertices = self.vertices | G2.vertices edges = self.edges | G2.edges - return Graph(vertices, edges, directed = self.directed) + return Graph(vertices, edges, directed=self.directed) def square(self): - ''' + """ The square of a directed graph G = (V, E) is the graph G^2 = (V, E^2) such that (u, v) belongs to E^2 if and only if G contains a path with at most two edges between u and v. - ''' + """ sqrt = self.copy() for u in self.vertices: for v in self.adj[u]: for w in self.adj[v]: - sqrt._addEdge(u, w) + sqrt._add_edge(u, w) return sqrt def height(self, u): maximum = 0 - print u.key + print(u.key) for v in self.adj[u]: if v.p == u: maximum = max(maximum, self.height(v) + 1) u.h = maximum - print u.key, u.h + print(u.key, u.h) return u.h + def mht(self): s = next(iter(self.vertices)) self.bfs(s) self.height(s) s.mh = s.h for u in self.adj[s]: - self.mhtAux(u) - - def mhtAux(self, u): + self._mht_aux(u) + + def _mht_aux(self, u): u.mh = max(u.h, u.p.mh + 1) for v in self.adj[u]: if v.p == u: - self.mhtAux(v) - + self._mht_aux(v) + -class dsf_node(dsf.node): +class DfsNode(dsf.node): def __init__(self, key): self.key = key key.index = self @@ -654,23 +690,29 @@ def __init__(self, key): self.rank = 0 self.child = [] + class max_heap(list): def __init__(self, data, attr): list.__init__(self, data) - for i in range(0, len(data)): + for i in range(len(data)): self[i].index = i self.length = len(data) self.attr = attr self.heap_size = self.length self.build_max_heap() + def __contains__(self, y): return y in self[0:self.heap_size] + def left(self, i): return 2 * i + 1 + def right(self, i): return 2 * i + 2 + def parent(self, i): - return (i - 1) / 2 + return (i - 1) // 2 + def max_heapify(self, i): l = self.left(i) r = self.right(i) @@ -680,19 +722,22 @@ def max_heapify(self, i): largest = i if (r <= (self.heap_size - 1)) and (self[r].__dict__[self.attr] > self[largest].__dict__[self.attr]): largest = r - if largest != i: - self[i],self[largest] = self[largest],self[i] + if largest != i: + self[i], self[largest] = self[largest], self[i] self[i].index = i self[largest].index = largest self.max_heapify(largest) + def build_max_heap(self): self.heap_size = self.length - for i in range(self.length / 2 - 1, -1, -1): + for i in range(self.length // 2 - 1, -1, -1): self.max_heapify(i) + class max_priority_queue(max_heap): def heap_maximum(self): return self[0] + def heap_extract_max(self): if self.heap_size < 1: sys.exit("heap underflow") @@ -702,46 +747,54 @@ def heap_extract_max(self): self.heap_size = self.heap_size - 1 self.max_heapify(0) return maximum + def heap_increase_key(self, i, key): if key < self[i].__dict__[self.attr]: sys.exit("new key is smaller than current key") self[i].__dict__[self.attr] = key while i > 0 and self[self.parent(i)].__dict__[self.attr] < self[i].__dict__[self.attr]: - self[i],self[self.parent(i)] = self[self.parent(i)], self[i] + self[i], self[self.parent(i)] = self[self.parent(i)], self[i] self[i].index = i self[self.parent(i)].index = self.parent(i) i = self.parent(i) + def max_heap_insert(self, element): if self.heap_size >= self.length: sys.exit("heap overflow") self.heap_size = self.heap_size + 1 self[self.heap_size - 1] = element element.index = self.heap_size - 1 - key = element.__dict__[self.attr] + key = element.__dict__[self.attr] element.__dict__[self.attr] = float("-Inf") self.heap_increase_key(self.heap_size - 1, key) + class min_heap(list): def __init__(self, data, attr): - ''' + """ data: input data for heap attr: the attribute of input date used as compare key - ''' + """ list.__init__(self, data) - for i in range(0, len(data)): + for i in range(len(data)): self[i].index = i self.attr = attr self.length = len(data) self.heap_size = self.length self.build_min_heap() + def __contains__(self, y): return y in self[0:self.heap_size] + def left(self, i): return 2 * i + 1 + def right(self, i): return 2 * i + 2 + def parent(self, i): - return (i - 1) / 2 + return (i - 1) // 2 + def min_heapify(self, i): l = self.left(i) r = self.right(i) @@ -751,19 +804,22 @@ def min_heapify(self, i): smallest = i if (r <= (self.heap_size - 1)) and (self[r].__dict__[self.attr] < self[smallest].__dict__[self.attr]): smallest = r - if smallest != i: - self[i],self[smallest] = self[smallest],self[i] + if smallest != i: + self[i], self[smallest] = self[smallest], self[i] self[i].index = i self[smallest].index = smallest self.min_heapify(smallest) + def build_min_heap(self): self.heap_size = self.length - for i in range(self.length / 2 - 1, -1, -1): + for i in range(self.length // 2 - 1, -1, -1): self.min_heapify(i) + class min_priority_queue(min_heap): def heap_minimum(self): return self[0] + def heap_extract_min(self): if self.heap_size < 1: sys.exit("heap underflow") @@ -773,15 +829,17 @@ def heap_extract_min(self): self.heap_size = self.heap_size - 1 self.min_heapify(0) return minimum + def heap_decrease_key(self, i, key): if key > self[i].__dict__[self.attr]: sys.exit("new key is larger than current key") self[i].__dict__[self.attr] = key while i > 0 and self[self.parent(i)].__dict__[self.attr] > self[i].__dict__[self.attr]: - self[i],self[self.parent(i)] = self[self.parent(i)], self[i] + self[i], self[self.parent(i)] = self[self.parent(i)], self[i] self[i].index = i self[self.parent(i)].index = self.parent(i) i = self.parent(i) + def min_heap_insert(self, element): if self.heap_size >= self.length: sys.exit("heap overflow") @@ -791,4 +849,3 @@ def min_heap_insert(self, element): key = element.__dict__[self.attr] element.__dict__[self.attr] = float("Inf") self.heap_decrease_key(self.heap_size - 1, key) - diff --git a/graph_test.py b/graph_test.py deleted file mode 100644 index 215e941..0000000 --- a/graph_test.py +++ /dev/null @@ -1,651 +0,0 @@ -#!/usr/bin/env ipython -import unittest -from graph import Vertex, Graph - -class TestGraph(unittest.TestCase): - def setUp(self): - self.graphs = [] - v1 = Vertex(1) - v2 = Vertex(2) - v3 = Vertex(3) - v4 = Vertex(4) - v5 = Vertex(5) - v6 = Vertex(6) - self.v1 = v1 - self.v2 = v2 - self.v3 = v3 - self.v4 = v4 - self.v5 = v5 - self.v6 = v6 - vertices = [v1,v2,v3,v4,v5,v6] - edges = [(v1, v2), (v1, v3), (v2, v3), (v2, v4), (v2, v5), (v3, v4), (v3, v6), (v4, v5), (v5, v6)] - self.graphs.append(Graph(vertices, edges)) - edges = [(v1, v2), (v2, v3), (v3, v4), (v4, v2), (v3, v5), (v2, v4), (v4, v3)] - self.graphs.append(Graph([v1, v2, v3, v4, v5], edges)) - - def tearDown(self): - pass - - def _buildGraph(self, keys, pairs, directed): - d = dict() - vertices = [None] * len(keys) - edges = [None] * len(pairs) - for i in range(len(vertices)): - vertices[i] = Vertex(keys[i]) - d[keys[i]] = vertices[i] - - for i in range(len(edges)): - w1, w2 = pairs[i] - edges[i] = (d[w1], d[w2]) - return Graph(vertices, edges, directed) - - def testBfs(self): - s = Vertex('s') - r = Vertex('r') - v = Vertex('v') - w = Vertex('w') - t = Vertex('t') - x = Vertex('x') - u = Vertex('u') - y = Vertex('y') - z = Vertex('z') - vertices = [v,r,s,w,t,x,u,y,z] - edges = [(s, r), (s, w), (r, v), (r, s), (v, r), (w, s), (w, t), (w, x), (t, w), (t, x), (t, u), (u, t), (u, x), (u, y), (x, w), (x, t), (x, u), (x, y), (y, x), (y, u)] - g = Graph(vertices, edges) - #g.printAllEdges() - #for i in g.vertices: - # i.printEdge() - # print - g.bfs(s) - # g.printVertices() - self.assertEquals(s.d, 0) - self.assertEquals(r.d, 1) - self.assertEquals(v.d, 2) - self.assertEquals(w.d, 1) - self.assertEquals(t.d, 2) - self.assertEquals(x.d, 2) - self.assertEquals(u.d, 3) - self.assertEquals(y.d, 3) - def testDfs(self): - s = Vertex('s') - v = Vertex('v') - z = Vertex('z') - w = Vertex('w') - y = Vertex('y') - x = Vertex('x') - t = Vertex('t') - u = Vertex('u') - #edges_list = [(z, w), (s, w), (y, w), (x, ), (x, ), (z, ), (v, u), (v, t)] - #vertices = (s, v, z, w, y, x, t, u) - #map(lambda vertex, edges: map(lambda vertex, edge: vertex.addEdge(edge), zip([vertex] * len(edges) , edges)), zip(vertices, edges_list)) - vertices = [s, v, z, w, y, x, t, u] - edges = [(y, x), (x, z), (z, y), (z, w), (w, x), (s, z), (s, w), (v, w), (v, s), (t, v), (t, u), (u, v), (u, t)] - g = Graph(vertices, edges) - g.dfs() - vertices = (s, v, z, w, y, x, t, u) -# for u in vertices: -# print u, u.d, u.f - #df = [(1, 10), (12, 13), (2, 9), (7, 8), (3, 6), (4, 5), (11, 16), (14, 15)] - #edges_list = [(z, w), (s, w), (y, w), (x, ), (x, ), (z, ), (v, u), (v, t)] - def testPathNum(self): - m = Vertex('m') - n = Vertex('n') - o = Vertex('o') - p = Vertex('p') - q = Vertex('q') - r = Vertex('r') - s = Vertex('s') - t = Vertex('t') - u = Vertex('u') - v = Vertex('v') - w = Vertex('w') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [m, n, o, p, q, r, s, t, u, v, w, x, y, z] - edges = [(m, q), (m, r), (m, x), (n, q), (n, o), (n, u), (o, r), (o, s), (o, v), (p, o), (p, s), (p, z), (q, t), (r, u), (r, y), (s, r), (u, t), (v, w), (v, x), (w, z), (y, v)] - g = Graph(vertices, edges) - self.assertEquals(g.path_num(m, v), 1) - self.assertEquals(g.path_num(n, v), 3) - self.assertEquals(g.path_num(o, v), 3) - self.assertEquals(g.path_num(p, v), 4) - self.assertEquals(g.path_num(q, v), 0) - self.assertEquals(g.path_num(r, v), 1) - self.assertEquals(g.path_num(s, v), 1) - self.assertEquals(g.path_num(t, v), 0) - self.assertEquals(g.path_num(u, v), 0) - self.assertEquals(g.path_num(v, v), 1) - self.assertEquals(g.path_num(w, v), 0) - self.assertEquals(g.path_num(x, v), 0) - self.assertEquals(g.path_num(y, v), 1) - self.assertEquals(g.path_num(z, v), 0) - - g = self.graphs[0] - self.assertEquals(g.path_num(self.v1, self.v2), 1) - self.assertEquals(g.path_num(self.v1, self.v3), 2) - self.assertEquals(g.path_num(self.v1, self.v4), 3) - self.assertEquals(g.path_num(self.v1, self.v5), 4) - self.assertEquals(g.path_num(self.v1, self.v6), 6) - self.assertEquals(g.path_num(self.v2, self.v1), 0) - self.assertEquals(g.path_num(self.v2, self.v3), 1) - self.assertEquals(g.path_num(self.v2, self.v4), 2) - self.assertEquals(g.path_num(self.v2, self.v5), 3) - self.assertEquals(g.path_num(self.v2, self.v6), 4) - g = self.graphs[1] - self.assertEquals(g.path_num(self.v1, self.v5), 1) - - def testSCC(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - vertices = [a, b, c, d, e, f, g, h] - edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (b, e), (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] - G = Graph(vertices, edges) - G.strongly_connected_components() - self.assertEquals(a.cc, 1) - self.assertEquals(b.cc, 1) - self.assertEquals(c.cc, 2) - self.assertEquals(d.cc, 2) - self.assertEquals(e.cc, 1) - self.assertEquals(f.cc, 3) - self.assertEquals(g.cc, 3) - self.assertEquals(h.cc, 4) - def testSimplified(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - vertices = [a, b, c, d, e, f, g, h] - #edges = [(a, c), (b, a), (d, h), (d, f), (e, a), (a, b), (b, c), (d, c), (c, d), (b, e), (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] - edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (b, e), (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] - G = Graph(vertices, edges) - s = G.simplified() -# for u in s.vertices: -# print "u.key: {}, u.cc: {}".format(u.key, u.cc) -# s.printEdge(u) - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - vertices = [a, b, c, d, e, f] - edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), (c, e), (b, e), (d, f), (e, f), (f, e)] - G = Graph(vertices, edges) - s = G.simplified() - #for u in s.vertices: - # print "u.key: {}, u.cc: {}".format(u.key, u.cc) - # s.printEdge(u) - def testComponentGraph(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - vertices = [a, b, c, d, e, f, g, h] - edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (d, h), (b, e), (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] - G = Graph(vertices, edges) - cg = G.component_graph() -# print -# for u in cg.vertices: -# print "u.key: {}".format(u.key) -# cg.printEdge(u) - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - vertices = [a, b, c, d, e, f] - edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), (c, e), (b, e), (d, f), (e, f), (f, e)] - G = Graph(vertices, edges) - cg = G.component_graph() -# print "www" -# print -# for u in cg.vertices: -# print "u.key: {}".format(u.key) -# cg.printEdge(u) - def testSemiconnected(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - vertices = [a, b, c, d, e, f, g, h] - edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (d, h), (b, e), (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), True) - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - vertices = [a, b, c, d, e, f] - edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), (c, e), (b, e), (d, f), (e, f), (f, e)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), True) - edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), (e, f)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), False) - abe = Vertex('abe') - cd = Vertex('cd') - fg = Vertex('fg') - h = Vertex('h') - vertices = [abe, cd, fg, h] - edges = [(abe, fg), (abe, cd), (fg, h), (cd, h), (cd, fg)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), True) - edges = [(abe, fg), (abe, cd), (fg, h), (cd, h)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), False) - edges = [(abe, fg), (abe, cd), (cd, h), (cd, fg)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), False) - edges = [(abe, fg), (abe, cd), (fg, h), (cd, fg)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), True) - edges = [(abe, cd), (fg, h), (cd, fg)] - G = Graph(vertices, edges) - self.assertEquals(G.semiconnected(), True) - def testCut(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - i = Vertex('i') - vertices = [a, b, c, d, e, f, g, h, i] - edges = [(a, b), (b, c), (b, h), (c, i), (d, c), (e, d), (f, d), (f, e), (f, c), (g, f), (g, h), (g, i), (h, a), (h, i)] - G = Graph(vertices, edges, directed = False) - #weight = [4, 8, 11, 2, 7, 9, 14, 10, 4, 2, 2, 1, 8, 7] - weight = [4, 8, 11, 2, 7, 9, 14, 10, 4, 2, 1, 6, 8, 7] - z = dict() - for x,y in zip(edges, weight): - z[x] = y - z[(x[1], x[0])] = y - def w(x, y): - return z[(x, y)] - G.cut(a, h, w) - r1 = set() - r2 = set() - for u in G.vertices: - if u.root == a: - r1.add(u) - else: - r2.add(u) - self.assertEquals(r1, set([a, b])) - self.assertEquals(r2, set([h, i, g, c, f, d, e])) -# for u in G.vertices: -# print "u.key: {}, u.root = {}".format(u.key, u.root) - def testKruskal(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - i = Vertex('i') - vertices = [a, b, c, d, e, f, g, h, i] - edges = [(a, b), (a, h), (b, a), (b, c), (b, h), (c, b), (c, i), (c, f), (c, d), (d, c), (d, e), (d, f), (e, d), (e, f), (f, d), (f, e), (f, c), (f, g), (g, f), (g, h), (g, i), (h, a), (h, b), (h, i), (h, g), (i, c), (i, h), (i, g)] - G = Graph(vertices, edges) - weight = [4, 8, 4, 8, 11, 8, 2, 4, 7, 7, 9, 14, 9, 10, 14, 10, 4, 2, 2, 1, 6, 8, 11, 7, 1, 2, 7, 6] - z = dict() - for x,y in zip(edges, weight): - z[x] = y - print "{}: {}".format(x, y) - def w(x, y): - return z[(x, y)] - ls = G.Kruskal(w) - print ls - def testPrim(self): - a = Vertex('a') - b = Vertex('b') - c = Vertex('c') - d = Vertex('d') - e = Vertex('e') - f = Vertex('f') - g = Vertex('g') - h = Vertex('h') - i = Vertex('i') - vertices = [a, b, c, d, e, f, g, h, i] - #edges = [(a, b), (a, h), (b, a), (b, c), (b, h), (c, b), (c, i), (c, f), (c, d), (d, c), (d, e), (d, f), (e, d), (e, f), (f, d), (f, e), (f, c), (f, g), (g, f), (g, h), (g, i), (h, a), (h, b), (h, i), (h, g), (i, c), (i, h), (i, g)] - #weight = [4, 8, 4, 8, 11, 8, 2, 4, 7, 7, 9, 14, 9, 10, 14, 10, 4, 2, 2, 1, 6, 8, 11, 7, 1, 2, 7, 6] - edges = [(a, b), (b, c), (b, h), (c, i), (d, c), (e, d), (f, d), (f, e), (f, c), (g, f), (g, h), (g, i), (h, a), (h, i)] - weight = [4, 8, 11, 2, 7, 9, 14, 10, 4, 2, 1, 6, 8, 7] - G = Graph(vertices, edges, False) - z = dict() - for x,y in zip(edges, weight): - z[x] = y - z[(x[1], x[0])] = y - #print "Prim edges: {}, weight: {}".format(x, y) - def w(x, y): - return z[(x, y)] - G.Prim(w, i) - s = set() - for u in G.vertices: - s.add((u.p, u)) -# self.assertEquals(s, set([(g, h), (f, g), (None, i), (c, d), (c, f), (i, c), (h, a), (d, e), (a, b)])) - def testBellmanFord(self): - s = Vertex('s') - t = Vertex('t') - y = Vertex('y') - x = Vertex('x') - z = Vertex('z') - vertices = [s, t, y, x, z] - edges = [(s, t), (s, y), (t, y), (t, x), (t, z), (y, x), (y, z), (x, t), (z, s), (z, x)] - weight = [6, 7, 8, 5, -4, -3, 9, -2, 2, 7] - G = Graph(vertices, edges) - we = dict() - for x,y in zip(edges, weight): - we[x] = y - def w(x, y): - return we[(x, y)] - G.Bellman_Ford(w, z) - def testBellmanFordModified(self): - s = Vertex('s') - t = Vertex('t') - u = Vertex('u') - v = Vertex('v') - x = Vertex('x') - y = Vertex('y') - vertices = [s, t, u, v, x, y] - edges = [(s, t), (s, v), (s, x), (s, y), (t, u), (v, u)] - weight = [1, 0, 3, 4, 2, 6] - G = Graph(vertices, edges) - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] -# G.Bellman_Ford(w, s) - G.Bellman_Ford_modified(w, s) - self.assertEquals([i.p for i in vertices], [None, s, t, s, s, s]) - self.assertEquals([i.d for i in vertices], [0, 1, 3, 0, 3, 4]) - r = Vertex('r') - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [r, s, t, x, y, z] - edges = [(r, s), (r, t), (s, t), (s, x), (t, x), (t, y), (t, z), (x, y), (x, z), (y, z)] - weight = [5, 3, 2, 6, 7, 4, 2, -1, 1, -2] - G = Graph(vertices, edges) - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] - G.Bellman_Ford_modified(w, s) - self.assertEquals([i.p for i in vertices], [None, None, s, s, x, y]) - self.assertEquals([i.d for i in vertices], [float("Inf"), 0, 2, 6, 5, 3]) - def testTopologicalSort(self): - r = Vertex('r') - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [r, s, t, x, y, z] - edges = [(r, s), (r, t), (s, t), (s, x), (t, x), (t, y), (t, z), (x, y), (x, z), (y, z)] - G = Graph(vertices, edges) - l = G.topological_sort() - self.assertEquals(l, [r, s, t, x, y, z]) - - result = [] - l = [self.v1, self.v2, self.v3, self.v4, self.v5, self.v6] - result.append(l) - for i in range(len(self.graphs)): - self.assertEquals(self.graphs[i].topological_sort(), result[i]) - - def testDagShortestPaths(self): - r = Vertex('r') - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [r, s, t, x, y, z] - edges = [(r, s), (r, t), (s, t), (s, x), (t, x), (t, y), (t, z), (x, y), (x, z), (y, z)] - weight = [5, 3, 2, 6, 7, 4, 2, -1, 1, -2] - G = Graph(vertices, edges) - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] - G.dag_shortest_paths(w, s) - self.assertEquals([i.p for i in vertices], [None, None, s, s, x, y]) - self.assertEquals([i.d for i in vertices], [float("Inf"), 0, 2, 6, 5, 3]) - G.dag_shortest_paths(w, r) - self.assertEquals([i.p for i in vertices], [None, r, r, t, t, t]) - self.assertEquals([i.d for i in vertices], [0, 5, 3, 10, 7, 5]) - def TestDagShortestPathsModified(self): - u = Vertex('u') - v = Vertex('v') - w = Vertex('w') - z = Vertex('z') - u.weight = 1 - v.weight = 2 - w.weight = 3 - z.weight = 4 - vertices = [u, v, w, z] - edges = [(u, v), (v, w), (v, z)] - G = Graph(vertices, edges) - self.assertEquals(dag_shortest_paths_modified(G, u), [u, v, z]) - def testTotalPathNumber(self): - r = Vertex('r') - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [r, s, t, x, y, z] - edges = [(r, s), (r, t), (s, t), (s, x), (t, x), (t, y), (t, z), (x, y), (x, z), (y, z)] - weight = [5, 3, 2, 6, 7, 4, 2, -1, 1, -2] - G = Graph(vertices, edges) - number = G.total_path_number() - self.assertEquals([i.num for i in vertices], [21, 12, 7, 3, 1, 0]) - self.assertEquals(number, 44) - def testDijkstra(self): - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [s, t, x, y, z] - edges = [(s, t), (s, y), (t, x), (t, y), (x, z), (y, t), (y, x), (y, z), (z, s), (z, x)] - g = Graph(vertices, edges) - weight = [10, 5, 1, 2, 4, 3, 9, 2, 7, 6] - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] - g.Dijkstra(w, s) - self.assertEquals([i.p for i in vertices], [None, y, t, s, y]) - self.assertEquals([i.d for i in vertices], [0, 8, 9, 5, 7]) - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [s, t, x, y, z] - edges = [(s, t), (s, y), (t, x), (t, y), (x, z), (y, t), (y, x), (y, z), (z, s), (z, x)] - g = Graph(vertices, edges) - weight = [3, 5, 6, 2, 2, 1, 4, 6, 3, 7] - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] - g.Dijkstra(w, s) - self.assertEquals([i.p for i in vertices], [None, s, t, s, y]) - self.assertEquals([i.d for i in vertices], [0, 3, 9, 5, 11]) - g.Dijkstra(w, z) - self.assertEquals([i.p for i in vertices], [z, s, z, s, None]) - self.assertEquals([i.d for i in vertices], [3, 6, 7, 8, 0]) - def testDijkstraModified(self): - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [s, t, x, y, z] - edges = [(s, t), (s, y), (t, x), (t, y), (x, z), (y, t), (y, x), (y, z), (z, s), (z, x)] - g = Graph(vertices, edges) - weight = [10, 5, 1, 2, 4, 3, 9, 2, 7, 6] - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] - g.Dijkstra_modified(w, s, 10) - self.assertEquals([i.p for i in vertices], [None, y, t, s, y]) - self.assertEquals([i.d for i in vertices], [0, 8, 9, 5, 7]) - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') - vertices = [s, t, x, y, z] - edges = [(s, t), (s, y), (t, x), (t, y), (x, z), (y, t), (y, x), (y, z), (z, s), (z, x)] - g = Graph(vertices, edges) - weight = [3, 5, 6, 2, 2, 1, 4, 6, 3, 7] - we = dict() - for i,j in zip(edges, weight): - we[i] = j - def w(x, y): - return we[(x, y)] - g.Dijkstra_modified(w, s, 7) - self.assertEquals([i.p for i in vertices], [None, s, t, s, y]) - self.assertEquals([i.d for i in vertices], [0, 3, 9, 5, 11]) - g.Dijkstra_modified(w, z, 7) - self.assertEquals([i.p for i in vertices], [z, s, z, s, None]) - self.assertEquals([i.d for i in vertices], [3, 6, 7, 8, 0]) - - def testSingleEdge(self): - a = Vertex(1) - b = Vertex(2) - c = Vertex(3) - d = Vertex(4) - vertices = [a, b, c, d] - edges = [(a, b), (b, a), (a, c), (d, d)] - G = Graph(vertices, edges) - G2 = G.single_edge() - edges = set([(a, b), (b, a), (a, c), (c, a)]) - vertices = set(vertices) - self.assertEquals(G2.vertices, vertices) - self.assertEquals(G2.edges, edges) - self.assertEquals(G2.adj[a], {b, c}) - self.assertEquals(G2.adj[b], {a}) - self.assertEquals(G2.adj[c], {a}) - self.assertEquals(G2.adj[d], set()) - - def testUnion(self): - a = Vertex(1) - b = Vertex(2) - c = Vertex(3) - d = Vertex(4) - G1 = Graph([a, b, c], [(a, b), (a, c)]) - G2 = Graph([c, d], [(c, d)]) - G3 = G1.union(G2) - self.assertEquals(G3.vertices, {a, b, c, d}) - self.assertEquals(G3.edges, {(a, b), (a, c), (c, d)}) - self.assertEquals(G3.adj[a], {b, c}) - self.assertEquals(G3.adj[b], set()) - self.assertEquals(G3.adj[c], {d}) - self.assertEquals(G3.adj[d], set()) - G1 = Graph([a, b, c], [(a, b), (a, c)], directed = False) - G2 = Graph([c, d], [(c, d)], directed = False) - G3 = G1.union(G2) - self.assertEquals(G3.vertices, {a, b, c, d}) - self.assertEquals(G3.edges, {(a, b), (b, a), (a, c), (c, a), (c, d), (d, c)}) - self.assertEquals(G3.adj[a], {b, c}) - self.assertEquals(G3.adj[b], {a}) - self.assertEquals(G3.adj[c], {d, a}) - self.assertEquals(G3.adj[d], {c}) - - def testCopy(self): - a = Vertex(1) - b = Vertex(2) - c = Vertex(3) - G1 = Graph([a, b, c], [(a, b), (a, c)]) - G2 = G1.copy() - self.assertEquals(G1, G2) - - def testSquareGraph(self): - a = Vertex(1) - b = Vertex(2) - c = Vertex(3) - d = Vertex(4) - G = Graph([a, b, c, d], [(a, b), (a, c), (c, d)]) - sqrt = G.square() - self.assertEquals(sqrt.vertices, {a, b, c, d}) - self.assertEquals(sqrt.edges, {(a, b), (a, c), (a, d), (c, d)}) - self.assertEquals(sqrt.adj[a], {b, c, d}) - self.assertEquals(sqrt.adj[b], set()) - self.assertEquals(sqrt.adj[c], {d}) - self.assertEquals(sqrt.adj[d], set()) - a = Vertex(1) - b = Vertex(2) - c = Vertex(3) - G = Graph([a, b, c], [(a, b), (b, c), (a, c)]) - sqrt = G.square() - self.assertEquals(G, sqrt) - - def testMht(self): - print "start mht" - g = self.graphs[0] - g.mht() - print "height" - print self.v1.h - print self.v2.h - print self.v3.h - print self.v4.h - print self.v5.h - print self.v6.h - print "height" - print self.v1.mh - print self.v2.mh - print self.v3.mh - print self.v4.mh - print self.v5.mh - print self.v6.mh -# def testJohnson(self): -# a1 = Vertex(1) -# a2 = Vertex(2) -# a3 = Vertex(3) -# a4 = Vertex(4) -# a5 = Vertex(5) -# vertices = [a1, a2, a3, a4, a5] -# edges = [(a1, a2), (a1, a3), (a1, a5), (a2, a4), (a2, a5), (a3, a2), (a4, a1), (a4, a3), (a5, a4)] -# g = Graph(vertices, edges) -# weight = [3, 8, -4, 1, 7, 4, 2, -5, 6] -# we = dict() -# for i,j in zip(edges, weight): -# we[i] = j -# def w(x, y): -# return we[(x, y)] -# g.Johnson(w) diff --git a/hamiltonian_path.py b/hamiltonian_path.py index 019db66..568c6a7 100644 --- a/hamiltonian_path.py +++ b/hamiltonian_path.py @@ -1,14 +1,16 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + def hamiltonian_path(G, u, v): - '''An algorithm to the hamiltonian-path problem on directed acyclic graphs''' + """ + An algorithm to the hamiltonian-path problem on directed acyclic graphs + """ we = dict() for i in G.edges: - we[i] = -1 + we[i] = -1 + def w(x, y): - return we[(x, y)] + return we[(x, y)] + G.dag_shortest_paths(w, u) - if abs(v.d) == len(G.vertices) - 1: - return True - else: - return False + return abs(v.d) == len(G.vertices) - 1 diff --git a/hash.py b/hash.py index 93f79a4..31a2505 100755 --- a/hash.py +++ b/hash.py @@ -1,26 +1,36 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + def hash_insert(T, k, h): i = 0 while i < len(T): j = h(k, i) - if T[j] == None: + if T[j] is None: T[j] = k return j else: i = i + 1 + + def linear_probe(k, i): return (aux(k) + i) % len(T) + + def quad_probe(k, i): return (aux(k) + i + 3 * i * i) % len(T) + + def aux(k): return k + + def double_hashing(k, i): return (k + i * (1 + k % (len(T) - 1))) % len(T) -T = [None for i in range(0, 11)] -print "length of T is ", len(T) + +T = [None] * 11 +print("length of T is ", len(T)) for i in 10, 22, 31, 4, 15, 28, 17, 88, 59: - hash_insert(T, i, double_hashing) + hash_insert(T, i, double_hashing) -print T +print(T) diff --git a/heap.py b/heap.py index 04f5db1..c69b0fc 100644 --- a/heap.py +++ b/heap.py @@ -1,52 +1,70 @@ -class max_heap(list): +class MaxHeap(list): def __init__(self, data): - list.__init__(self, data) - self.length = len(data) + super().__init__(data) + self.length = len(self) self.heap_size = self.length self.build_max_heap() - def left(self, i): + + @staticmethod + def left(i): return 2 * i + 1 - def right(self, i): + + @staticmethod + def right(i): return 2 * i + 2 - def parent(self, i): - return (i - 1) / 2 + + @staticmethod + def parent(i): + return (i - 1) // 2 + def max_heapify(self, i): - l = self.left(i) - r = self.right(i) - if (l <= (self.heap_size - 1)) and (self[l] > self[i]): - largest = l + left = self.left(i) + right = self.right(i) + if left < self.heap_size and self[left] > self[i]: + largest = left else: largest = i - if (r <= (self.heap_size - 1)) and (self[r] > self[largest]): - largest = r - if largest != i: - self[i],self[largest] = self[largest],self[i] + if right < self.heap_size and self[right] > self[largest]: + largest = right + if largest != i: + self[i], self[largest] = self[largest], self[i] self.max_heapify(largest) + def build_max_heap(self): self.heap_size = self.length - for i in range(self.length / 2 - 1, -1, -1): + for i in range(self.length // 2 - 1, -1, -1): self.max_heapify(i) + def heapsort(self): self.build_max_heap() for i in range(self.length - 1, 0, -1): - self[0],self[i] = self[i],self[0] + self[0], self[i] = self[i], self[0] self.heap_size = self.heap_size - 1 self.max_heapify(0) -# print self -class min_heap(list): + + +class MinHeap(list): def __init__(self, data): - list.__init__(self, data) - self.length = len(data) + super().__init__(data) + self.length = len(self) self.heap_size = self.length self.build_min_heap() + def __contains__(self, y): - return y in self[0:self.heap_size] - def left(self, i): + return y in self[:self.heap_size] + + @staticmethod + def left(i): return 2 * i + 1 - def right(self, i): + + @staticmethod + def right(i): return 2 * i + 2 - def parent(self, i): - return (i - 1) / 2 + + @staticmethod + def parent(i): + return (i - 1) // 2 + def min_heapify(self, i): l = self.left(i) r = self.right(i) @@ -56,10 +74,11 @@ def min_heapify(self, i): smallest = i if (r <= (self.heap_size - 1)) and (self[r] < self[smallest]): smallest = r - if smallest != i: - self[i],self[smallest] = self[smallest],self[i] + if smallest != i: + self[i], self[smallest] = self[smallest], self[i] self.min_heapify(smallest) + def build_min_heap(self): self.heap_size = self.length - for i in range(self.length / 2 - 1, -1, -1): + for i in range(self.length // 2 - 1, -1, -1): self.min_heapify(i) diff --git a/heap_test.py b/heap_test.py deleted file mode 100644 index 9c16baa..0000000 --- a/heap_test.py +++ /dev/null @@ -1,34 +0,0 @@ -import unittest -from heap import max_heap, min_heap - -class TestHeap(unittest.TestCase): -# def test_init(self): -# a = heap([4, 1, 3, 2, 16, 9, 10, 14, 8, 7]) -# self.assertEquals(a.__heap, a) -# self.assertEquals(a.__length, 10) -# self.assertEquals(a.__heap_size, 10) - def test_max_heapify(self): - a = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1] - h = max_heap(a) - h.max_heapify(1) - self.assertEquals(h, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) - def test_build_max_heap(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - h = max_heap(a) - h.build_max_heap() - self.assertEquals(h, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) - def test_heapsort(self): - a = [4, 1, 3, 3, 16, 9, 10, 14, 8, 7] - h = max_heap(a) - h.heapsort() - self.assertEquals(h, [1, 3, 3, 4, 7, 8, 9, 10, 14, 16]) - def test_min_heapify(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - h = min_heap(a) - h.min_heapify(1) - self.assertEquals(h, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) - def test_build_min_heap(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - h = min_heap(a) - h.build_min_heap() - self.assertEquals(h, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) diff --git a/huffman.py b/huffman.py index 90857b7..6b89cbb 100644 --- a/huffman.py +++ b/huffman.py @@ -1,104 +1,125 @@ -from priority_queue import min_priority_queue -class Min_priority_queue(min_priority_queue): +from priority_queue import MinPriorityQueue +import sys + + +class Min_priority_queue(MinPriorityQueue): def min_heap_insert(self, key): if self.heap_size >= self.length: sys.exit("heap overflow") self.heap_size = self.heap_size + 1 self.heap[self.heap_size - 1] = node(None, None, float("Inf")) self.heap_decrease_key(self.heap_size - 1, key) -class character(object): - def __init__(self, char, freq, sibling = None): + + +class character: + def __init__(self, char, freq, sibling=None): self.char = char self.freq = freq self.sibling = sibling + def __eq__(self, y): - if self.freq == y.freq: - return True + return self.freq == y.freq + def __gt__(self, y): - if self.freq > y.freq: - return True + return self.freq > y.freq + def __ge__(self, y): - if self.freq >= y.freq: - return True + return self.freq >= y.freq + def __le__(self, y): - if self.freq <= y.freq: - return True + return self.freq <= y.freq + def __lt__(self, y): - if self.freq < y.freq: - return True -class node(object): + return self.freq < y.freq + + +class node: def __init__(self, left, right, freq): self.left = left - self.right =right + self.right = right self.freq = freq + def __eq__(self, y): - if self.freq == y.freq: - return True + return self.freq == y.freq + def __gt__(self, y): - if self.freq > y.freq: - return True + return self.freq > y.freq + def __ge__(self, y): - if self.freq >= y.freq: - return True + return self.freq >= y.freq + def __le__(self, y): - if self.freq <= y.freq: - return True + return self.freq <= y.freq + def __lt__(self, y): - if self.freq < y.freq: - return True -class tenary_node(object): - def __init__(self, freq, child = None, sibling = None): + return self.freq < y.freq + + +class tenary_node: + def __init__(self, freq, child=None, sibling=None): self.freq = freq self.child = child self.sibling = sibling + def __eq__(self, y): - if self.freq == y.freq: - return True + return self.freq == y.freq + def __gt__(self, y): - if self.freq > y.freq: - return True + return self.freq > y.freq + def __ge__(self, y): - if self.freq >= y.freq: - return True + return self.freq >= y.freq + def __le__(self, y): - if self.freq <= y.freq: - return True + return self.freq <= y.freq + def __lt__(self, y): - if self.freq < y.freq: - return True + return self.freq < y.freq + + def huffman(chars, freqs): n = len(chars) c = [0] * n - for i in range(0, n): + for i in range(n): c[i] = character(chars[i], freqs[i]) q = Min_priority_queue(c) - for i in range(0, n - 1): + for i in range(n - 1): x = q.heap_extract_min() y = q.heap_extract_min() q.min_heap_insert(node(x, y, x.freq + y.freq)) return q.heap_extract_min() + + def print_code(root): print_code_aux(root, '') + + def print_code_aux(node, s): if hasattr(node, "left"): - print_code_aux(node.left, s + '0') print_code_aux(node.right, s + '1') + print_code_aux(node.left, s + '0') else: - print "character: {}\tfrequency: {}\tcode: {}".format(node.char, node.freq, s) + print("character: {}\tfrequency: {}\tcode: {}".format(node.char, node.freq, s)) + + def compact_store_prefix_code(root): store = [] compact_store_prefix_code_aux(root, store, '') return store + + def compact_store_prefix_code_aux(node, store, string): if hasattr(node, "left"): compact_store_prefix_code_aux(node.left, store, string + '0') compact_store_prefix_code_aux(node.right, store, '1') else: store.append((node.char, string)) + + def decode_compact_prefix_code(store): code = '' pos = 0 - for i in range(0, len(store)): + for i in range(len(store)): last_len = len(code) char = store[i][1][0] for pos in range(last_len - 1, -1, -1): @@ -108,14 +129,18 @@ def decode_compact_prefix_code(store): code = store[i][1] else: code = code[0:pos] + store[i][1] - print "char: {}, code: {}".format(store[i][0], code) + print("char: {}, code: {}".format(store[i][0], code)) + + def huffman_tenary(chars, freqs, m): - ''' generalize Huffman's algorithm to tenary codewords + """ + generalize Huffman's algorithm to tenary codewords the parameter m is the number of symbols we use, eg, in - original huffman algorithm, we use 0 and 1, so m = 2''' + original huffman algorithm, we use 0 and 1, so m = 2 + """ n = len(chars) c = [0] * n - for i in range(0, n): + for i in range(n): c[i] = character(chars[i], freqs[i]) q = Min_priority_queue(c) while q.heap_size >= m: @@ -131,19 +156,23 @@ def huffman_tenary(chars, freqs, m): return q.heap_extract_min() x = q.heap_extract_min() z = tenary_node(x.freq, x) - while q.heap_size > 0: + while q.heap_size > 0: y = q.heap_extract_min() x.sibling = y z.freq = z.freq + y.freq x = y q.min_heap_insert(z) return q.heap_extract_min() + + def print_huffman_tenary(root): print_huffman_tenary_aux(root, '', '') + + def print_huffman_tenary_aux(node, string, sibling): if hasattr(node, "child"): - print_huffman_tenary_aux(node.child, string + str(sibling), 0) + print_huffman_tenary_aux(node.child, string + str(sibling), 0) else: - print "character: {}\tfrequency: {}\tcode: {}".format(node.char, node.freq, string + str(sibling)) - if node.sibling != None: + print("character: {}\tfrequency: {}\tcode: {}".format(node.char, node.freq, string + str(sibling))) + if node.sibling: print_huffman_tenary_aux(node.sibling, string, sibling + 1) diff --git a/insertion-sort-noninc.c b/insertion-sort-noninc.c deleted file mode 100644 index 5056843..0000000 --- a/insertion-sort-noninc.c +++ /dev/null @@ -1,16 +0,0 @@ -#include -//Sort into nonincreasing order -void insertionsort(int s[], int length) { - int j, i; - int key; - - for (j = 1; j < length; j++) { - key = s[j]; - for (i = j - 1; i >= 0 && s[i] < key; i--) - s[i+1] = s[i]; - s[i+1] = key; - for (i = 0; i < length; i++) - printf("%d ", s[i]); - printf("\n"); - } -} diff --git a/insertion-sort-rec.c b/insertion-sort-rec.c deleted file mode 100644 index cd91cde..0000000 --- a/insertion-sort-rec.c +++ /dev/null @@ -1,48 +0,0 @@ -#include -// recursive version of insertion sort - -void swap(int *a, int *b) -{ - int tmp = *a; - - *a = *b; - *b = tmp; -} - -void Insert(int A[], int n) -{ - int i; - - for (i = n - 1; i >= 0; i--) - if (A[i] > A[i + 1]) - swap(A + i, A + i + 1); - else - return; -} - -void InsSort(int A[], int n) -{ - if (n > 1) - { - InsSort(A, n - 1); - Insert(A, n); - } - else if (n == 1) - { - if (A[0] > A[1]) - swap(A, A + 1); - return; - } - else if (n == 0) - return; -} - -int main() -{ - int a[8] = { 8, 8, 3, 65, 500, 3, -1, 3 }; - - InsSort(a, 7); - printf("%d,%d,%d,%d,%d,%d,%d, %d\n", a[0], a[1], a[2], a[3], a[4], a[5], - a[6], a[7]); - return 0; -} diff --git a/insertion-sort.c b/insertion-sort.c deleted file mode 100644 index 870d9ff..0000000 --- a/insertion-sort.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -//INSERTION-SORT(A) - //for j = 2 to A.length - //key = A[j] - ////Insert A[j] into the sorted sequence A[1..j - 1]. - //i = j - 1 - //while i > 0 and A[i] > key - //A[i + 1] = A[i] - //i = i - 1 - //A[i + 1] = key - -//Sort into nondecreasing order -void insertionsort(int s[], int length) { - int j, i; - int key; - - for (j = 1; j < length; j++) { - key = s[j]; - for (i = j - 1; i >= 0 && s[i] > key; i--) - s[i+1] = s[i]; - s[i+1] = key; -// for (i = 0; i < length; i++) -// printf("%d ", s[i]); -// printf("\n"); - } -} diff --git a/insertion_sort.py b/insertion_sort.py index 75b9716..25e1cf4 100644 --- a/insertion_sort.py +++ b/insertion_sort.py @@ -1,9 +1,64 @@ -def insertion_sort(A): - for j in range(1, len(A)): - key = A[j] - i = j - 1 - while i >= 0 and key < A[i]: - A[i + 1] = A[i] - i = i - 1 - A[i + 1] = key +from binary_search import bisect_right + +def insert_with_linear_search(array, left_index, right_index): + """ + Use linear search to find a position in already sorted array[left_index...right_index-1] to insert array[right_index] into, + making array[left_index...right_index] a sorted array. + :param array: + :param left_index: + :param right_index: right_index > 0 + :return: + """ + key = array[right_index] + i = right_index - 1 + while i >= left_index and key < array[i]: + array[i + 1] = array[i] + i = i - 1 + array[i + 1] = key + + +def insert_with_binary_search(array, left_index, right_index): + """ + Use binary search to find a position in already sorted array[left_index...right_index-1] to insert array[right_index] into, + making array[left_index...right_index] a sorted array. + :param array: + :param left_index: + :param right_index: right_index > 0 + :return: + """ + x = array[right_index] + index = bisect_right(array, x, left_index, right_index) + array[index + 1: right_index + 1] = array[index: right_index] + array[index] = x + + +def insertion_sort(array, left=0, right=None, insert_method=insert_with_linear_search): + """ + inplace sort O(n ^ 2) sort + :param array: + :param left: + :param right: + :param insert_method: + :return: + """ + if right is None: + right = len(array) - 1 + for j in range(left, right + 1): + insert_method(array, 0, j) + + +def _insertion_sort_recursive(array, length, insert_method): + if length > 1: + _insertion_sort_recursive(array, length - 1, insert_method) + insert_method(array, 0, length - 1) + + +def insertion_sort_recursive(array, insert_method=insert_with_linear_search): + """ + recursive version of insertion sort + :param array: + :param insert_method: + :return: + """ + _insertion_sort_recursive(array, len(array), insert_method) diff --git a/interpolation.py b/interpolation.py index 5c228bc..9003511 100644 --- a/interpolation.py +++ b/interpolation.py @@ -1,7 +1,8 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import synthetic_division as di + def roots_interpolation(roots, n): A = [0] * (n + 1) if n == 1: @@ -17,21 +18,22 @@ def roots_interpolation(roots, n): A[0] = -1 * x * B[0] return A + def Lagrange_interpolation(X, Y, n): R = roots_interpolation(X, n) -# print "length of R is {}".format(len(R)) + # print( "length of R is {}".format(len(R))) A = [0] * n - for k in range(0, n): + for k in range(n): q, re = di.synthetic_division(R, n + 1, X[k]) -# print q - # print "length of q is {}".format(len(q)) + # print( q) + # print( "length of q is {}".format(len(q))) m = 1.0 - for j in range(0, n): + for j in range(n): if j != k: m = m * (X[k] - X[j]) - # print "m = {}".format(m) + # print( "m = {}".format(m)) m = Y[k] / m - # print "m = {}".format(m) - for j in range(0, n): + # print( "m = {}".format(m)) + for j in range(n): A[j] = A[j] + q[j] * m return A diff --git a/interval_graph_coloring.py b/interval_graph_coloring.py index 2125273..0766480 100644 --- a/interval_graph_coloring.py +++ b/interval_graph_coloring.py @@ -1,10 +1,12 @@ def interval_graph_coloring(graph): - '''The input graph is represented as an adjacency matrix since all we need is edge information about the graph''' + """ + The input graph is represented as an adjacency matrix since all we need is edge information about the graph + """ m = graph.shape[0] color = [1] * m number = 1 - for i in range(0, m): - for j in range(0, m): + for i in range(m): + for j in range(m): if graph[i, j] == 1 and color[i] == color[j]: color[j] = color[i] + 1 if color[j] > number: diff --git a/interval_tree.py b/interval_tree.py index a4fcf41..6795419 100755 --- a/interval_tree.py +++ b/interval_tree.py @@ -1,21 +1,24 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class interval(object): + +class interval: def __init__(self, low, high): self.low = low self.high = high -class interval_node(rb_node): + + +class interval_node(RbNode): def __init__(self, key, p, left, right, color, interval, maximum): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.interval = interval self.maximum = maximum def list_all_overlapping_intervals(self, T, i): x = self if x.interval.high >= i.low and i.high >= x.interval.low: - print x.interval.low, x.interval.high + print(x.interval.low, x.interval.high) if x.left != T.nil and x.left.maximum >= i.low: self.left.list_all_overlapping_intervals(T, i) self.right.list_all_overlapping_intervals(T, i) @@ -23,7 +26,7 @@ def list_all_overlapping_intervals(self, T, i): self.right.list_all_overlapping_intervals(T, i) def interval_search_exactly(self, T, i): - if self.interval.low == i.low and self.interval.high == i.high: + if self.interval.low == i.low and self.interval.high == i.high: return self if self.interval.low > i.low: if self.left != T.nil: @@ -36,17 +39,19 @@ def interval_search_exactly(self, T, i): else: return T.nil - -class interval_tree(rb_tree): +class interval_tree(RbTree): nil = interval_node(None, None, None, None, 1, None, float("-Inf")) root = nil + def __init__(self, intervals): if isinstance(intervals, list): for i in intervals: - self.insert(interval_node(i.low, None, None, None, 0, i, i.high)) + self.insert(interval_node( + i.low, None, None, None, 0, i, i.high)) else: - print "Not invalid argument" + print("Not invalid argument") + def insert(self, z): y = self.nil x = self.root @@ -67,8 +72,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def left_rotate(self, x): y = x.right x.right = y.left @@ -85,6 +91,7 @@ def left_rotate(self, x): x.p = y y.maximum = x.maximum x.maximum = max(x.left.maximum, x.interval.high, x.right.maximum) + def right_rotate(self, y): x = y.left y.left = x.right @@ -101,6 +108,7 @@ def right_rotate(self, y): y.p = x x.maximum = y.maximum y.maximum = max(y.left.maximum, y.interval.high, y.right.maximum) + def delete(self, z): y = z y_original_color = y.color @@ -126,7 +134,8 @@ def delete(self, z): y.color = z.color traverse = x.p while traverse != self.nil: - traverse.maximum = max(traverse.left.maximum, traverse.interval.high, traverse.right.maximum) + traverse.maximum = max( + traverse.left.maximum, traverse.interval.high, traverse.right.maximum) traverse = traverse.p if y_original_color == 1: self.delete_fixup(x) @@ -141,8 +150,10 @@ def closed_interval_search(self, interval): return x def closed_interval_search_minimum_low_end(self, interval): - '''given an interval, returns an interval over- - lapping i that has the minimum low endpoint, or T.nil if no such interval exists''' + """ + given an interval, returns an interval over- + lapping i that has the minimum low endpoint, or T.nil if no such interval exists + """ x = self.root overlap = False i = self.nil @@ -168,11 +179,11 @@ def open_interval_search(self, interval): return x def list_all_overlapping_intervals(self, i): - if self.root == self.nil: + if self.root == self.nil: return else: self.root.list_all_overlapping_intervals(self, i) - print + print() def interval_search_exactly(self, i): if self.root == self.nil: diff --git a/inversion.c b/inversion.c deleted file mode 100644 index 0a96704..0000000 --- a/inversion.c +++ /dev/null @@ -1,81 +0,0 @@ -// This program determines the number of inversions in -// any permution on n elements using a global variable invs -#include -#include -#include - - // MERGE(A, p, q, r) - // n1 = q - p + 1 - // n2 = r - q - // L[1...n1] = A[p...q] - // R[1...n2] = A[q+1...r] - // L[n1+1] = ∞ - // R[n2+1] = ∞ - // i = 1 - // j = 1 - // for k = p to r - // if L[i] <= R[j] - // A[k] = L[i] - // i = i + 1 - // else - // A[k] = R[j] - // j = j + 1 -static int invs = 0; - -static void combine(int B[], int first, int inter, int end) -{ - int len1 = inter - first + 1; - int len2 = end - inter; - int i; - int j; - int k; - int *L; - int *R; - - L = (int *)calloc(len1 + 1, sizeof(int)); - R = (int *)calloc(len2 + 1, sizeof(int)); - for (i = 0; i < len1; i++) - L[i] = B[first + i]; - for (j = 0; j < len2; j++) - R[j] = B[inter + j + 1]; - L[len1] = INT_MAX; - R[len2] = INT_MAX; - - i = 0; - j = 0; - for (k = first; k <= end; k++) - { - if (L[i] <= R[j]) - B[k] = L[i++]; else { B[k] = R[j++]; - invs = invs + len1 - i; - } - - } - free(L); - free(R); -} - -static void divide(int B[], int first, int end) -{ - if (first < end) - { - int middle = (first + end) / 2; - - divide(B, first, middle); - divide(B, middle + 1, end); - combine(B, first, middle, end); - } -} - -int inversion(int A[], int first, int end) { - int i; - int *B = (int *) calloc(end - first + 1, sizeof(int)); - - for (i = first; i <= end; i++) - B[i] = A[i]; - divide(B, first, end); - free(B); - i = invs; - invs = 0; - return i; -} diff --git a/inversion.py b/inversion.py new file mode 100644 index 0000000..8ebff46 --- /dev/null +++ b/inversion.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +def inversion_with_insertion_sort(array): + """ + Count number of inversions of an array using insertion sort + + Let A[1...n] be an array of n numbers. If i < j and A[i] > A[j] , + then the pair (i, j) is called an inversion_with_insertion_sort of A + :param array: + :return: + """ + array = array[:] + return _inversion_with_insertion_sort(array) + + +def _inversion_with_insertion_sort(array): + """ + :param array: + :return: + """ + inverse = 0 + for j in range(1, len(array)): + key = array[j] + i = j - 1 + while i >= 0 and key < array[i]: + inverse += 1 + array[i + 1] = array[i] + i = i - 1 + array[i + 1] = key + return inverse + + +def inversion_with_merge_sort(array): + """ + Count number of inversions of an array using merge sort + + Let A[1...n] be an array of n numbers. If i < j and A[i] > A[j] , + then the pair (i, j) is called an inversion_with_insertion_sort of A + :param array: + :return: + """ + array = array[:] + return _inversion_with_merge_sort(array, 0, len(array) - 1) + + +def _inversion_with_merge_sort(array, left, right): + if left < right: + mid = (left + right) // 2 + left_inverse = _inversion_with_merge_sort(array, left, mid) + right_inverse = _inversion_with_merge_sort(array, mid + 1, right) + inter_inverse = _merge(array, left, mid, right) + return left_inverse + right_inverse + inter_inverse + else: + return 0 + + +def _merge(array, left, mid, right): + """ + + :param array: + :param left: + :param mid: + :param right: + :return: + """ + left_part = array[left: mid + 1] + left_part.append(float("Inf")) + right_part = array[mid + 1: right + 1] + right_part.append(float("Inf")) + i = 0 + j = 0 + inverse = 0 + for k in range(left, right + 1): + if left_part[i] <= right_part[j]: + array[k] = left_part[i] + i = i + 1 + else: + array[k] = right_part[j] + j = j + 1 + inverse += (mid - left + 1 - i) + return inverse + diff --git a/inversion2.c b/inversion2.c deleted file mode 100644 index a645192..0000000 --- a/inversion2.c +++ /dev/null @@ -1,87 +0,0 @@ -// This program determines the number of inversions in -// any permution on n elements -// This version no longer uses global variable. It is more 'divide and conquer' than inversion.c -#include -#include -#include - - // MERGE(A, p, q, r) - // n1 = q - p + 1 - // n2 = r - q - // L[1...n1] = A[p...q] - // R[1...n2] = A[q+1...r] - // L[n1+1] = ∞ - // R[n2+1] = ∞ - // i = 1 - // j = 1 - // for k = p to r - // if L[i] <= R[j] - // A[k] = L[i] - // i = i + 1 - // else - // A[k] = R[j] - // j = j + 1 - -static int combine(int B[], int first, int inter, int end) -{ - int len_left = inter - first + 1; - int len_right = end - inter; - int i; - int j; - int k; - int *L; - int *R; - int invs_cross = 0; - - L = (int *)calloc(len_left + 1, sizeof(int)); - R = (int *)calloc(len_right + 1, sizeof(int)); - for (i = 0; i < len_left; i++) - L[i] = B[first + i]; - for (j = 0; j < len_right; j++) - R[j] = B[inter + j + 1]; - L[len_left] = INT_MAX; - R[len_right] = INT_MAX; - - i = 0; - j = 0; - for (k = first; k <= end; k++) - { - if (L[i] <= R[j]) - B[k] = L[i++]; - else { - B[k] = R[j++]; - invs_cross = invs_cross + len_left - i; - } - - } - free(L); - free(R); - return invs_cross; -} - -int divide(int B[], int first, int end) -{ - int invs_left, invs_right, invs_cross; - - if (first < end) - { - int middle = (first + end) / 2; - - invs_left = divide(B, first, middle); - invs_right = divide(B, middle + 1, end); - invs_cross = combine(B, first, middle, end); - return invs_left + invs_right + invs_cross; - } - return 0; -} - -int inversion(int A[], int first, int end) { - int i; - int *B = (int *) calloc(end - first + 1, sizeof(int)); - - for (i = first; i <= end; i++) - B[i] = A[i]; - i = divide(B, first, end); - free(B); - return i; -} diff --git a/inversion_tree.py b/inversion_tree.py index e02fa8d..97f818f 100644 --- a/inversion_tree.py +++ b/inversion_tree.py @@ -10,8 +10,8 @@ def inversion(A): i = i + 1 x = rank_node(key, None, None, None, 0, 1) T.insert(x) - # print 'x.key = {}, x.rank = {}'.format(x.key, x.rank) + # print( 'x.key = {}, x.rank = {}'.format(x.key, x.rank)) inversion = inversion + i - x.rank return inversion else: - print "Not invalid argument" + print("Not invalid argument") diff --git a/k_way_merge.py b/k_way_merge.py index af45cf1..f014ba6 100644 --- a/k_way_merge.py +++ b/k_way_merge.py @@ -28,13 +28,17 @@ def merge(list1, list2): def k_way_merge(lists): - '''Merge k sorted lists and return it as one sorted list''' + """ + Merge k sorted lists and return it as one sorted list + :param lists: + :return: + """ length = len(lists) if length == 1: return lists[0] elif length == 2: return merge(lists[0], lists[1]) else: - list1 = k_way_merge(lists[0:length / 2]) - list2 = k_way_merge(lists[length / 2 : length]) + list1 = k_way_merge(lists[:length // 2]) + list2 = k_way_merge(lists[length // 2:]) return merge(list1, list2) diff --git a/k_way_merge_test.py b/k_way_merge_test.py deleted file mode 100644 index 3245415..0000000 --- a/k_way_merge_test.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env ipython -import unittest -import random -from k_way_merge import k_way_merge - -class TestKWayMerge(unittest.TestCase): - def test_k_way_merge(self): - for j in range(0, 10000): - A = [random.randint(1, 10000) for i in range(0, 100)] - lists = [None] * 10 - for i in range(0, 10): - lists[i] = A[10 * i : (i + 1) * 10] - lists[i].sort() - A.sort() - self.assertEquals(k_way_merge(lists), A) - diff --git a/kleene_star.py b/kleene_star.py index 8a21a21..c7238fd 100644 --- a/kleene_star.py +++ b/kleene_star.py @@ -1,7 +1,8 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python from numpy import zeros + def kleene_star(x, L, A): length = len(x) m = zeros((length, length)) @@ -13,7 +14,4 @@ def kleene_star(x, L, A): m[i - 1, j - 1] = 1 if m[i - 1, j - 1] != 1: m[i - 1, j - 1] = A(x[i - 1:j], L) - if m[0, length - 1] != 0: - return True - else: - return False + return m[0, length - 1] != 0 diff --git a/knapsack_0_1.py b/knapsack_0_1.py index 52407b4..ed2fc0b 100644 --- a/knapsack_0_1.py +++ b/knapsack_0_1.py @@ -1,17 +1,19 @@ from numpy import zeros + def knapsack_0_1(W, w, v): n = len(w) return knapsack_0_1_aux(W, w, v, 1, n) + def knapsack_0_1_aux(W, w, v, m, n): - ''' + """ m: the first item n: the last item W: total weight w: the list of weights of items v: the list of values of items - ''' + """ # if m > n, then we have scanned all the items if m > n: @@ -25,16 +27,18 @@ def knapsack_0_1_aux(W, w, v, m, n): else: 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)) + def knapsack_0_1_memoized(W, w, v): m = 1 n = len(w) - value = zeros((W + 1, n + 1)) - solution = zeros((W + 1, n + 1)) - for i in range(0, W + 1): - for j in range(0, n + 1): + value = zeros((W + 1, n + 1)) + solution = zeros((W + 1, n + 1)) + for i in range(W + 1): + for j in range(n + 1): value[i, j] = float("-Inf") knapsack_0_1_memoized_aux(W, w, v, m, n, value, solution) - return value,solution + return value, solution + def knapsack_0_1_memoized_aux(W, w, v, m, n, value, solution): if m > n: @@ -42,7 +46,7 @@ def knapsack_0_1_memoized_aux(W, w, v, m, n, value, solution): if value[W, m] >= 0: return value[W, m] if W < w[m - 1]: - value[W, m] = knapsack_0_1_memoized_aux(W, w, v, m + 1, n, value, solution) + value[W, m] = knapsack_0_1_memoized_aux(W, w, v, m + 1, n, value, solution) solution[W, m] = 0 else: s = knapsack_0_1_memoized_aux(W - w[m - 1], w, v, m + 1, n, value, solution) + v[m - 1] @@ -52,12 +56,13 @@ def knapsack_0_1_memoized_aux(W, w, v, m, n, value, solution): value[W, m] = max(s, t) return value[W, m] + def print_knapsack_solution(solution, w): W = solution.shape[0] - 1 n = solution.shape[1] - 1 i = 1 while W != 0 and i <= n: if solution[W, i] == 1: - print i + print(i) W = W - w[i - 1] i = i + 1 diff --git a/kth-Quantiles.py b/kth-Quantiles.py index 13d9ef6..258a9a6 100755 --- a/kth-Quantiles.py +++ b/kth-Quantiles.py @@ -1,44 +1,50 @@ -#! /usr/bin/env ipython +#! /usr/bin/env python import math import random from randomized_select import randomized_select from quicksort import randomized_quicksort + def kth_quantiles(A, B, k, p, r): if k > 0: n = r - p + 1 location = math.floor(k / 2) * math.ceil(n / k) - B[math.floor(k / 2)]= randomized_select(A, p, r, location) + B[math.floor(k / 2)] = randomized_select(A, p, r, location) kth_quantiles(A, B, p, math.floor(k / 2) - 1, location - 1) kth_quantiles(A, B, math.floor(k / 2), location + 1, r) + def median_of_two_arrays(X, x_start, x_end, Y, y_start, y_end, size): - print X[x_start:x_end + 1], '\t', Y[y_start:y_end + 1], '\t', size + print(X[x_start:x_end + 1], '\t', Y[y_start:y_end + 1], '\t', size) if size == 1: return min(X[x_start], Y[y_start]) xc = X[x_start + int(math.floor(size / 2)) - 1] yc = Y[y_start + int(math.ceil(size / 2)) - 1] - print xc, yc + print(xc, yc) if xc == yc: return xc elif xc < yc: - return median_of_two_arrays(X, x_start + int(math.floor(size / 2)), x_end, Y, y_start, y_end, math.ceil(size / 2)) + return median_of_two_arrays(X, x_start + int(math.floor(size / 2)), x_end, Y, y_start, y_end, + math.ceil(size / 2)) else: - return median_of_two_arrays(X, x_start, x_end, Y, y_start + int(math.ceil(size / 2)), y_end, math.floor(size / 2)) -A = [random.randint(1, 100) for i in range(0, 15)] -print A -randomized_quicksort(A, 0, 14) -print A -B = [random.randint(1, 100) for i in range(0, 15)] -print B -randomized_quicksort(B, 0, 14) -print B -print median_of_two_arrays(A, 0, 14, B, 0, 14, 3.0) -#randomized_select(A, 0, 14, 7) -#print A -#for i in range(1, 16): -# randomized_select(A, 0, 14, i) -# print i, '\t', A -# print randomized_select(A, 0, 14, i) + return median_of_two_arrays(X, x_start, x_end, Y, y_start + int(math.ceil(size / 2)), y_end, + math.floor(size / 2)) + +if __name__ == '__main__': + A = [random.randint(1, 100) for i in range(15)] + print(A) + randomized_quicksort(A, 0, 14) + print(A) + B = [random.randint(1, 100) for i in range(15)] + print(B) + randomized_quicksort(B, 0, 14) + print(B) + print(median_of_two_arrays(A, 0, 14, B, 0, 14, 3.0)) +# randomized_select(A, 0, 14, 7) +# print( A) +# for i in range(1, 16): +# randomized_select(A, 0, 14, i) +# print( i, '\t', A) +# print( randomized_select(A, 0, 14, i)) diff --git a/linked_list.py b/linked_list.py deleted file mode 100644 index ead4c9a..0000000 --- a/linked_list.py +++ /dev/null @@ -1,35 +0,0 @@ -class linked_list(object): - def __init__(self, key = None): - self.head = None - self.size = 0 - self.key = key - def empty(self): - return self.size == 0 - def search(self, k): - x = self.head - while x != None and x.key != k: - x = x.next - return x - def insert(self, x): - self.size = self.size + 1 - x.next = self.head - if self.head != None: - self.head.prev = x - self.head = x - x.prev = None - def delete(self, x): - self.size = self.size - 1 - if x.prev != None: - x.prev.next = x.next - else: - self.head = x.next - if x.next != None: - x.next.prev = x.prev - def extract(self, x): - self.delete(x) - return x -class linked_list_node(object): - def __init__(self, element): - self.key = element - self.prev = None - self.next = None diff --git a/linked_list_test.py b/linked_list_test.py deleted file mode 100644 index c1f44f6..0000000 --- a/linked_list_test.py +++ /dev/null @@ -1,54 +0,0 @@ -import unittest -from linked_list import linked_list, linked_list_node - -class TestLinkedList(unittest.TestCase): - def test_insert(self): - L = linked_list() - a = linked_list_node(1) - b = linked_list_node(4) - c = linked_list_node(16) - d = linked_list_node(9) - e = linked_list_node(25) - L.insert(a) - L.insert(b) - L.insert(c) - L.insert(d) - L.insert(e) - l = [] - x = L.head - while x != None: - l.append(x) - x = x.next - self.assertEquals(l, [e, d, c, b, a]) - def test_search(self): - L = linked_list() - a = linked_list_node(1) - b = linked_list_node(4) - c = linked_list_node(16) - d = linked_list_node(9) - e = linked_list_node(25) - L.insert(a) - L.insert(b) - L.insert(c) - L.insert(d) - L.insert(e) - self.assertEquals(L.search(4), b) - def test_delete(self): - L = linked_list() - a = linked_list_node(1) - b = linked_list_node(4) - c = linked_list_node(16) - d = linked_list_node(9) - e = linked_list_node(25) - L.insert(a) - L.insert(b) - L.insert(c) - L.insert(d) - L.insert(e) - L.delete(b) - l = [] - x = L.head - while x != None: - l.append(x) - x = x.next - self.assertEquals(l, [e, d, c, a]) diff --git a/linkedlist.py b/linkedlist.py new file mode 100644 index 0000000..a4d9b41 --- /dev/null +++ b/linkedlist.py @@ -0,0 +1,45 @@ +from typing import Any, Optional + + +class LinkedListNode: + def __init__(self, key: Any): + self.key: Any = key + self.prev: Optional[LinkedListNode] = None + self.next: Optional[LinkedListNode] = None + + +class LinkedList: + def __init__(self, key=None): + self.head: Optional[LinkedListNode] = None + self.size: int = 0 + self.key = key + + def empty(self) -> bool: + return self.size == 0 + + def search(self, key: Any) -> Optional[LinkedListNode]: + node = self.head + while node and node.key != key: + node = node.next + return node + + def insert(self, node: LinkedListNode) -> None: + self.size = self.size + 1 + node.next = self.head + if self.head: + self.head.prev = node + self.head = node + node.prev = None + + def delete(self, node: LinkedListNode) -> None: + self.size = self.size - 1 + if node.prev: + node.prev.next = node.next + else: + self.head = node.next + if node.next: + node.next.prev = node.prev + + def extract(self, node: LinkedListNode) -> LinkedListNode: + self.delete(node) + return node diff --git a/longest_common_subsequence.py b/longest_common_subsequence.py index 2d4db66..dcf61a7 100644 --- a/longest_common_subsequence.py +++ b/longest_common_subsequence.py @@ -1,5 +1,6 @@ from numpy import zeros + def lcs_length(X, Y): m = len(X) n = len(Y) @@ -17,7 +18,9 @@ def lcs_length(X, Y): else: c[i, j] = c[i, j - 1] b[i, j] = 2 - return c,b + return c, b + + def lcs_length_one_row(X, Y): m = len(X) n = len(Y) @@ -35,14 +38,15 @@ def lcs_length_one_row(X, Y): a = c[j] c[j] = value return c[n] + + def print_lcs(b, X, i, j): if i == 0 or j == 0: return if b[i, j] == 0: print_lcs(b, X, i - 1, j - 1) - print X[i - 1], + print(X[i - 1], ) elif b[i, j] == 1: print_lcs(b, X, i - 1, j) else: print_lcs(b, X, i, j - 1) - diff --git a/longest_palindrome_subsequence.py b/longest_palindrome_subsequence.py index 66b87b5..ff1ff0e 100644 --- a/longest_palindrome_subsequence.py +++ b/longest_palindrome_subsequence.py @@ -3,11 +3,12 @@ from longest_common_subsequence import lcs_length, print_lcs + def longest_palindrome_subsequence(s): - #c, b = lcs_length(s, s[::-1]) - #print_lcs(b, s, len(s), len(s)) + # c, b = lcs_length(s, s[::-1]) + # print(_lcs(b, s, len(s), len(s))) n = len(s) - c = [[0] * n for i in range(n)] + c = [[0] * n for _ in range(n)] for i in range(n): c[i][i] = 1 for i in range(n - 1): @@ -16,15 +17,16 @@ def longest_palindrome_subsequence(s): else: c[i][i + 1] = 1 for length in range(3, n + 1): - for i in range(0, n - length + 1): + for i in range(n - length + 1): j = i + length - 1 if s[i] == s[j]: - print i, j, c[i + 1][j - 1] + print(i, j, c[i + 1][j - 1]) c[i][j] = 2 + c[i + 1][j - 1] else: c[i][j] = max(c[i][j - 1], c[i + 1][j]) return c + def print_lps(c, s): start = 0 end = len(s) - 1 @@ -48,8 +50,3 @@ def print_lps(c, s): l.insert(index, s[start]) idx.insert(index, start) return ''.join(l), idx - - - - - diff --git a/lowest_common_multiple.py b/lowest_common_multiple.py new file mode 100644 index 0000000..7706aba --- /dev/null +++ b/lowest_common_multiple.py @@ -0,0 +1,5 @@ +from gcd import gcd + + +def lcm(num1: int, num2: int): + return num1 * num2 // gcd(num1, num2) diff --git a/main.c b/main.c deleted file mode 100644 index 0c2685f..0000000 --- a/main.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include - -int main(int argc, char *argv[]) { - //int pow1(int, unsigned); - //int pow1(int, unsigned); - //int num = atoi(argv[1]); - //int exp = atoi(argv[2]); -// - //printf("%d\n", pow2(num, exp)); - //printf("%d\n", pow1(num, exp)); - void matrix_exp(int *, int *, int, int); - int A[16] = {-1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, -1}; - int B[16]; - int C[4] = {1, 1, 0, 1}; //3, 2, -4, -2};//1, 0, 0, 1}; - int E[9] = {2, 1, 1, 3, 1, 0, 0, 1, 2};//1, 0, 0, 1, 0, 1, 0, 1, 0}; - int D[4]; - int i, j; - int n = 2; - matrix_exp(C, D, n, atoi(argv[1])); - for (i = 0; i < n; i++) { - for (j = 0; j < n; j++) - printf("%d\t", *(D + n * i + j)); - printf("\n"); - } - - return 0; -} diff --git a/matrix_chain_order.py b/matrix_chain_order.py index e494ae4..e32d7ab 100644 --- a/matrix_chain_order.py +++ b/matrix_chain_order.py @@ -1,6 +1,7 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + +from numpy import zeros -from numpy import zeros def bottom_up_matrix_chain_order(p): n = len(p) - 1 @@ -15,7 +16,9 @@ def bottom_up_matrix_chain_order(p): if q < m[i, j]: m[i, j] = q s[i, j] = k - return m,s + return m, s + + def memoized_matrix_chain_order(p): n = len(p) - 1 m = zeros((n + 1, n + 1)) @@ -23,6 +26,8 @@ def memoized_matrix_chain_order(p): for j in range(1, n + 1): m[i, j] = float("Inf") return lookup_chain(m, p, 1, n) + + def lookup_chain(m, p, i, j): if m[i, j] < float("Inf"): return m[i, j] @@ -30,26 +35,32 @@ def lookup_chain(m, p, i, j): m[i, j] = 0 else: for k in range(i, j): - q = lookup_chain(m, p, i, k) + lookup_chain(m, p, k + 1, j) + p[i - 1] * p[k] * p[j] + q = lookup_chain(m, p, i, k) + lookup_chain(m, p, + k + 1, j) + p[i - 1] * p[k] * p[j] if q < m[i, j]: m[i, j] = q return m[i, j] + + def print_optimal_parens(s, i, j): if i == j: - print "A{}".format(int(i)), + print("A{}".format(int(i)), ) else: - print "(", + print("(", ) print_optimal_parens(s, i, s[i, j]) print_optimal_parens(s, s[i, j] + 1, j) - print ")", + print(")", ) + # An incorrect greedy approach for matrix chain order problem def greedy_matrix_chain_order(p): n = len(p) - 1 return greedy_matrix_chain_order_aux(p, 1, n) + + def greedy_matrix_chain_order_aux(p, i, j): if i == j: - return 0 + return 0 q = float("Inf") for k in range(i, j): value = p[i - 1] * p[k] * p[j] diff --git a/memoized_cut_rod.py b/memoized_cut_rod.py index 86a608c..3f5da3e 100644 --- a/memoized_cut_rod.py +++ b/memoized_cut_rod.py @@ -2,6 +2,7 @@ def memoized_cut_rod(p, n): r = [float("-Inf")] * (n + 1) return memoized_cut_rod_aux(p, n, r) + def memoized_cut_rod_aux(p, n, r): if r[n] >= 0: return r[n] @@ -13,5 +14,3 @@ def memoized_cut_rod_aux(p, n, r): q = max(q, p[i - 1] + memoized_cut_rod_aux(p, n - i, r)) r[n] = q return q - - diff --git a/merge-sort.c b/merge-sort.c deleted file mode 100644 index b46723d..0000000 --- a/merge-sort.c +++ /dev/null @@ -1,47 +0,0 @@ -// implemention of algorithm merge sort - -#include -#include -// A version of merge procedure that uses sentinels -void merge(int a[], int begin, int middle, int end) { - int n1 = middle - begin + 1; - int n2 = end - middle; -// What's this? - int l[n1 + 1], r[n2 + 1]; - int i, j, k; - - for (i=0; i < n1; i++) - l[i] = a[begin + i]; - for (j=0; j < n2; j++) - r[j] = a[middle + j + 1]; - l[n1] = INT_MAX; - r[n2] = INT_MAX; - i = 0, j = 0; - for (k = begin; k <= end; k++) { - if (l[i] <= r[j]) { - a[k] = l[i]; - i++; - } - else { - a[k] = r[j]; - j++; - } - } -} - -void merge_sort(int a[], int start, int end) { - if (start < end) { - int middle = (start + end) / 2; - merge_sort(a, start, middle); - merge_sort(a, middle+1, end); - merge(a, start, middle, end); - } -} - -int main() { - int a[8] = {1,3,4,5,2,6,0,10}; - - merge_sort(a, 0, 7); - printf("%d, %d, %d, %d, %d, %d, %d, %d\n", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]); - return 0; -} diff --git a/merge.py b/merge.py new file mode 100644 index 0000000..62957e5 --- /dev/null +++ b/merge.py @@ -0,0 +1,56 @@ +def merge_with_sentinel(array, left, mid, right): + """ + merge procedure with sentinels + + merge array[left...mid] and array[mid + 1...right] + :param array: + :param left: + :param mid: + :param right: + :return: + """ + left_part = array[left: mid + 1] + left_part.append(float("Inf")) + right_part = array[mid + 1: right + 1] + right_part.append(float("Inf")) + i = 0 + j = 0 + for k in range(left, right + 1): + if left_part[i] <= right_part[j]: + array[k] = left_part[i] + i += 1 + else: + array[k] = right_part[j] + j += 1 + + +def merge_without_sentinel(array, left, mid, right): + """ + merge procedure without sentinels + + A merge procedure without sentinels that stops once either array `left_part` or `right_part` has had all its elements + copied back to `array` and then copying the remainder of another array back into `array` + :param array: + :param left: + :param mid: + :param right: + :return: + """ + left_part = array[left: mid + 1] + right_part = array[mid + 1: right + 1] + i = 0 + j = 0 + k = left + while i < len(left_part) and j < len(right_part): + if left_part[i] <= right_part[j]: + array[k] = left_part[i] + k += 1 + i += 1 + else: + array[k] = right_part[j] + k += 1 + j += 1 + if i < len(left_part): + array[k: right + 1] = left_part[i:] + else: + array[k: right + 1] = right_part[j:] \ No newline at end of file diff --git a/merge_sort.py b/merge_sort.py index 5435558..12bad53 100644 --- a/merge_sort.py +++ b/merge_sort.py @@ -1,26 +1,86 @@ -def merge(A, p, q, r): - n1 = q - p + 1 - n2 = r - q - L = [0] * (n1 + 1) - R = [0] * (n2 + 1) - for i in range(0, n1): - L[i] = A[p + i] - for j in range(0, n2): - R[j] = A[q + j + 1] - L[n1] = float("Inf") - R[n2] = float("Inf") - i = 0 - j = 0 - for k in range(p, r + 1): - if L[i] <= R[j]: - A[k] = L[i] - i = i + 1 - else: - A[k] = R[j] - j = j + 1 -def merge_sort(A, p, r): - if p < r: - q = (p + r) / 2 - merge_sort(A, p, q) - merge_sort(A, q + 1, r) - merge(A, p, q, r) +from insertion_sort import insertion_sort +from merge import merge_with_sentinel + + +def merge_sort(array, merge_method=merge_with_sentinel): + """ + inplace O(nlgn) sort + :param array: + :param merge_method: + :return: + """ + _merge_sort(array, 0, len(array) - 1, merge_method) + + +def _merge_sort(array, left, right, merge_method): + if left < right: + mid = (left + right) // 2 + _merge_sort(array, left, mid, merge_method) + _merge_sort(array, mid + 1, right, merge_method) + merge_method(array, left, mid, right) + + +def merge_ins_sort_bottom_to_top(array, partition: int = 2): + """ + Although merge sort runs faster than insertion sort asymptotically, + the constant factors in insertion sort can make it faster in practice for small problem sizes on many machines. + Thus, it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when + subproblems become sufficiently small. Consider a modification to merge sort in which n/k sublists of length k are + sorted using insertion sort and then merged using the standard merging mechanism, where k is a value to be determined. + + bottom to top version with number of sublists specified + :param array: + :param partition: number of sublists + :return: + """ + assert partition > 0 + n = len(array) + sublist_length = n // partition + sublist_number = partition + for i in range(sublist_number): + left = sublist_length * i + right = min(sublist_length * (i + 1) - 1, n - 1) + insertion_sort(array, left, right) + while sublist_number > 1: + for i in range(0, sublist_number - 1, 2): + merge_with_sentinel(array, sublist_length * i, sublist_length * (i + 1) - 1, + min(sublist_length * (i + 2) - 1, n - 1)) + sublist_length *= 2 + sublist_number = sublist_number // 2 + + +def merge_ins_sort_top_to_bottom(array, sublist_length): + """ + Although merge sort runs faster than insertion sort asymptotically, the constant factors in insertion sort can make + it faster in practice for small problem sizes on many machines. + Thus, it makes sense to coarsen the leaves of the recursion by using insertion sort within merge sort when + subproblems become sufficiently small. Consider a modification to merge sort in which n/k sublists of length k are + sorted using insertion sort and then merged using the standard merging mechanism, where k is a value to be determined. + + top to bottom version with sublist length specified + :param array: + :param sublist_length: + :return: + """ + n = len(array) + assert 0 < sublist_length < n + _merge_ins_sort_top_to_bottom(array, 0, n - 1, sublist_length) + + +def _merge_ins_sort_top_to_bottom(array, start, end, sublist_length): + """ + + :param array: + :param start: + :param end: + :param sublist_length: + :return: + """ + length = end - start + 1 + if length > sublist_length: + mid = (start + end) // 2 + _merge_ins_sort_top_to_bottom(array, start, mid, sublist_length) + _merge_ins_sort_top_to_bottom(array, mid + 1, end, sublist_length) + merge_with_sentinel(array, start, mid, end) + else: + insertion_sort(array, start, end) diff --git a/min_gap_tree.py b/min_gap_tree.py index 44df937..c47891f 100644 --- a/min_gap_tree.py +++ b/min_gap_tree.py @@ -1,22 +1,29 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class min_gap_node(rb_node): + +class MinGapNode(RbNode): def __init__(self, key, p, left, right, color, successor, min_gap): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.successor = successor self.min_gap = min_gap -class min_gap_tree(rb_tree): - positive_infinity = min_gap_node(float("Inf"), None, None, None, 1, None, float("Inf")) - nil = min_gap_node(None, None, None, None, 1, positive_infinity, float("Inf")) + + +class MinGapTree(RbTree): + positive_infinity = MinGapNode( + float("Inf"), None, None, None, 1, None, float("Inf")) + nil = MinGapNode(None, None, None, None, 1, + positive_infinity, float("Inf")) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: - self.insert(min_gap_node(i, None, None, None, 0, None, None)) + self.insert(MinGapNode(i, None, None, None, 0, None, None)) else: - print "Not invalid argument" + print("Not invalid argument") + def insert(self, z): y = self.nil x = self.root @@ -43,12 +50,14 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red traverse = z while traverse != self.nil: - traverse.min_gap = min(traverse.left.min_gap, traverse.successor.key - traverse.key, traverse.right.min_gap) + traverse.min_gap = min( + traverse.left.min_gap, traverse.successor.key - traverse.key, traverse.right.min_gap) traverse = traverse.p self.insert_fixed(z) + def delete(self, z): traverse = self.predecessor(z) y = z @@ -73,17 +82,20 @@ def delete(self, z): y.left = z.left y.left.p = y y.color = z.color - # After we delete z, the only nodes whose successor attributes need to be updated are z's successor and z's predecessor + # After we delete z, the only nodes whose successor attributes need to be updated are z's successor and z's predecessor traverse.successor = z.successor while traverse != self.nil: - traverse.min_gap = min(traverse.left.min_gap, traverse.successor.key - traverse.key, traverse.right.min_gap) + traverse.min_gap = min( + traverse.left.min_gap, traverse.successor.key - traverse.key, traverse.right.min_gap) traverse = traverse.p traverse = x.p while traverse != self.nil: - traverse.min_gap = min(traverse.left.min_gap, traverse.successor.key - traverse.key, traverse.right.min_gap) + traverse.min_gap = min( + traverse.left.min_gap, traverse.successor.key - traverse.key, traverse.right.min_gap) traverse = traverse.p if y_original_color == 1: self.delete_fixup(x) + def left_rotate(self, x): y = x.right x.right = y.left @@ -99,7 +111,9 @@ def left_rotate(self, x): y.left = x x.p = y y.min_gap = x.min_gap - x.min_gap = min(x.left.min_gap, x.successor.key - x.key, x.right.min_gap) + x.min_gap = min(x.left.min_gap, x.successor.key - + x.key, x.right.min_gap) + def right_rotate(self, y): x = y.left y.left = x.right @@ -115,7 +129,9 @@ def right_rotate(self, y): x.right = y y.p = x x.min_gap = y.min_gap - y.min_gap = min(y.left.min_gap, y.successor.key - y.key, y.right.min_gap) + y.min_gap = min(y.left.min_gap, y.successor.key - + y.key, y.right.min_gap) + def predecessor(self, x): if x.left != self.nil: return x.left.maximum() diff --git a/min_heap_with_linked_list.py b/min_heap_with_linked_list.py index fc2a7bd..9eebd03 100644 --- a/min_heap_with_linked_list.py +++ b/min_heap_with_linked_list.py @@ -1,19 +1,25 @@ -from linked_list import linked_list_node, linked_list +import sys -class min_heap(list): + +class MinHeap(list): def __init__(self, data): list.__init__(self, data) self.length = len(data) self.heap_size = self.length self.build_min_heap() + def __contains__(self, y): return y in self[0:self.heap_size] + def left(self, i): return 2 * i + 1 + def right(self, i): return 2 * i + 2 + def parent(self, i): return (i - 1) / 2 + def min_heapify(self, i): l = self.left(i) r = self.right(i) @@ -23,16 +29,20 @@ def min_heapify(self, i): smallest = i if (r <= (self.heap_size - 1)) and (self[r].key < self[smallest].key): smallest = r - if smallest != i: - self[i],self[smallest] = self[smallest],self[i] + if smallest != i: + self[i], self[smallest] = self[smallest], self[i] self.min_heapify(smallest) + def build_min_heap(self): self.heap_size = self.length - for i in range(self.length / 2 - 1, -1, -1): + for i in range(self.length // 2 - 1, -1, -1): self.min_heapify(i) -class min_priority_queue(min_heap): + + +class MinPriorityQueue(MinHeap): def heap_minimum(self): return self[0].head + def heap_extract_min(self): if self.heap_size < 1: sys.exit("heap underflow") @@ -42,6 +52,7 @@ def heap_extract_min(self): self.heap_size = self.heap_size - 1 self.min_heapify(0) return minimum + def heap_decrease_key(self, i, element, key): if key > self[i]: sys.exit("new key is larger than current key") @@ -49,8 +60,9 @@ def heap_decrease_key(self, i, element, key): while i > 0 and self[self.parent(i)] > self[i]: tmp = self[self.parent(i)] self[self.parent(i)] = self[i] - self[i] = tmp + self[i] = tmp i = self.parent(i) + def min_heap_insert(self, key): if self.heap_size >= self.length: sys.exit("heap overflow") diff --git a/min_heap_with_linked_list_test.py b/min_heap_with_linked_list_test.py index 67bbdaf..05e0cc3 100644 --- a/min_heap_with_linked_list_test.py +++ b/min_heap_with_linked_list_test.py @@ -1,89 +1,93 @@ import unittest from min_heap_with_linked_list import min_heap, min_priority_queue -from linked_list import linked_list, linked_list_node +from linkedlist import LinkedList, LinkedListNode + class TestHeap(unittest.TestCase): def test_min_heapify(self): - L1 = linked_list(1) - L2 = linked_list(2) - L2.insert(linked_list_node(2)) - L2.insert(linked_list_node(2)) - L3 = linked_list(3) - L3.insert(linked_list_node(3)) - L3.insert(linked_list_node(3)) - L4 = linked_list(4) - L4.insert(linked_list_node(4)) - L5 = linked_list(5) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) + L1 = LinkedList(1) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) h = min_heap([L5, L1, L2, L3, L4]) h.min_heapify(0) - self.assertEquals(h, [L1, L3, L2, L5, L4]) + self.assertEqual(h, [L1, L3, L2, L5, L4]) + def test_build_min_heap(self): - L1 = linked_list(1) - L2 = linked_list(2) - L2.insert(linked_list_node(2)) - L2.insert(linked_list_node(2)) - L3 = linked_list(3) - L3.insert(linked_list_node(3)) - L3.insert(linked_list_node(3)) - L4 = linked_list(4) - L4.insert(linked_list_node(4)) - L5 = linked_list(5) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) + L1 = LinkedList(1) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) h = min_heap([L3, L4, L5, L2, L1]) h.build_min_heap() - self.assertEquals(h, [L1, L2, L5, L3, L4]) + self.assertEqual(h, [L1, L2, L5, L3, L4]) + def test_heap_minimum(self): - L1 = linked_list(1) - L1.insert(linked_list_node(1)) - L1.insert(linked_list_node(1)) - L2 = linked_list(2) - L2.insert(linked_list_node(2)) - L2.insert(linked_list_node(2)) - L3 = linked_list(3) - L3.insert(linked_list_node(3)) - L3.insert(linked_list_node(3)) - L4 = linked_list(4) - L4.insert(linked_list_node(4)) - L5 = linked_list(5) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) + L1 = LinkedList(1) + L1.insert(LinkedListNode(1)) + L1.insert(LinkedListNode(1)) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) q = min_priority_queue([L1, L2, L3, L4, L5]) - self.assertEquals(q.heap_minimum().key, 1) + self.assertEqual(q.heap_minimum().key, 1) + def test_heap_extract_min(self): - L1 = linked_list(1) - L1.insert(linked_list_node(1)) - L1.insert(linked_list_node(1)) - L2 = linked_list(2) - L2.insert(linked_list_node(2)) - L2.insert(linked_list_node(2)) - L3 = linked_list(3) - L3.insert(linked_list_node(3)) - L3.insert(linked_list_node(3)) - L4 = linked_list(4) - L4.insert(linked_list_node(4)) - L5 = linked_list(5) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) - L3.insert(linked_list_node(5)) + L1 = LinkedList(1) + L1.insert(LinkedListNode(1)) + L1.insert(LinkedListNode(1)) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) q = min_priority_queue([L1, L2, L3, L4, L5]) - self.assertEquals(q.heap_extract_min().key, 1) - self.assertEquals(q, [L1, L2, L3, L4, L5]) - self.assertEquals(q.heap_extract_min().key, 1) - self.assertEquals(q, [L2, L4, L3, L5, L5]) + self.assertEqual(q.heap_extract_min().key, 1) + self.assertEqual(q, [L1, L2, L3, L4, L5]) + self.assertEqual(q.heap_extract_min().key, 1) + self.assertEqual(q, [L2, L4, L3, L5, L5]) # def test_heap_decrease_key(self): # a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] -# q = min_priority_queue(a) +# q = MinPriorityQueue(a) # q.heap_decrease_key(8, 1) -# self.assertEquals(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) +# self.assertEqual(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) # def test_heap_insert(self): # a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] -# q = min_priority_queue(a) +# q = MinPriorityQueue(a) # q.heap_extract_min() # q.min_heap_insert(0) -# self.assertEquals(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) +# self.assertEqual(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) diff --git a/min_priority_queue_using_rb_tree.py b/min_priority_queue_using_rb_tree.py index e591e7e..dea6c42 100644 --- a/min_priority_queue_using_rb_tree.py +++ b/min_priority_queue_using_rb_tree.py @@ -1,18 +1,22 @@ -from rb_tree import rb_tree +from rb_tree import RbTree import sys -class min_priority_queue(rb_tree): + +class min_priority_queue(RbTree): def heap_minimum(self): return self.minimum() + def heap_extract_min(self): x = self.minimum() self.delete(x) return x + def heap_decrease_key(self, node, key): if key > node.key: sys.exit("new key is larger than current key") self.delete(node) node.key = key self.insert(node) + def min_heap_insert(self, node): self.insert(node) diff --git a/min_priority_queue_using_rb_tree_test.py b/min_priority_queue_using_rb_tree_test.py deleted file mode 100644 index d6faca0..0000000 --- a/min_priority_queue_using_rb_tree_test.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env ipython -import unittest -from min_priority_queue_using_rb_tree import min_priority_queue -from rb_tree import rb_node - -class TestMinPriorityQueue(unittest.TestCase): - def test_extract_min(self): - q = min_priority_queue([41, 38, 31, 12, 19, 9]) - self.assertEquals(q.heap_extract_min().key, 9) - self.assertEquals(q.heap_extract_min().key, 12) - self.assertEquals(q.heap_extract_min().key, 19) - self.assertEquals(q.heap_extract_min().key, 31) - self.assertEquals(q.heap_extract_min().key, 38) - self.assertEquals(q.heap_extract_min().key, 41) - def test_heap_decrease_key(self): - q = min_priority_queue([41, 38, 31, 12, 19, 9]) - q.heap_decrease_key(q.iterative_tree_search(9), 5) - q.heap_decrease_key(q.iterative_tree_search(38), 5) - self.assertEquals(q.heap_extract_min().key, 5) - self.assertEquals(q.heap_extract_min().key, 5) - self.assertEquals(q.heap_extract_min().key, 12) - self.assertEquals(q.heap_extract_min().key, 19) - self.assertEquals(q.heap_extract_min().key, 31) - self.assertEquals(q.heap_extract_min().key, 41) - def test_heap_insert(self): - q = min_priority_queue([41, 38, 31, 12, 19, 9]) - q.min_heap_insert(rb_node(5, None, None, None, 0)) - q.min_heap_insert(rb_node(38, None, None, None, 0)) - q.min_heap_insert(rb_node(50, None, None, None, 0)) - self.assertEquals(q.heap_extract_min().key, 5) - self.assertEquals(q.heap_extract_min().key, 9) - self.assertEquals(q.heap_extract_min().key, 12) - self.assertEquals(q.heap_extract_min().key, 19) - self.assertEquals(q.heap_extract_min().key, 31) - self.assertEquals(q.heap_extract_min().key, 38) - self.assertEquals(q.heap_extract_min().key, 38) - self.assertEquals(q.heap_extract_min().key, 41) - self.assertEquals(q.heap_extract_min().key, 50) -if __name__ == '__main__': - unittest.main() diff --git a/most_reliable_path.py b/most_reliable_path.py index 2a102bb..988e2b5 100644 --- a/most_reliable_path.py +++ b/most_reliable_path.py @@ -1,7 +1,8 @@ from graph import max_priority_queue + def most_reliable_path(G, r, s): - ''' + """ We are given a directed graph G = (V, E) on which each edge (u, v) that belongs to E has an associated value r(u, v), which is a real number in the range @@ -16,7 +17,7 @@ def most_reliable_path(G, r, s): s: the source r: the function that returns the probability that the channel from u to v will not fail. - ''' + """ initialize_single_source(G, s) S = set() Q = max_priority_queue(G.vertices, 'r') @@ -29,6 +30,7 @@ def most_reliable_path(G, r, s): v.p = u Q.heap_increase_key(v.index, u.r * r(u, v)) + def initialize_single_source(G, s): for v in G.vertices: v.r = 0 diff --git a/optimal_binary_search_tree.py b/optimal_binary_search_tree.py index b5b1419..6687b6d 100644 --- a/optimal_binary_search_tree.py +++ b/optimal_binary_search_tree.py @@ -1,11 +1,12 @@ from numpy import zeros + def optimal_bst(p, q, n): e = zeros((n + 2, n + 1)) w = zeros((n + 2, n + 1)) root = zeros((1 + n, 1 + n)) for i in range(1, n + 2): - print "i = {}".format(i) + print("i = {}".format(i)) e[i, i - 1] = q[i - 1] w[i, i - 1] = q[i - 1] for l in range(1, n + 1): @@ -18,27 +19,31 @@ def optimal_bst(p, q, n): if t < e[i, j]: e[i, j] = t root[i, j] = r - return e,root + return e, root + + def construct_optimal_bst(root): n = root.shape[1] - 1 r = root[1, n] - print "k{} is the root".format(int(r)) + print("k{} is the root".format(int(r))) construct_optimal_bst_aux(root, r, 1, r - 1) construct_optimal_bst_aux(root, r, r + 1, n) + + def construct_optimal_bst_aux(root, p, i, j): if j < p: if i <= j: r = root[i, j] - print "k{} is the left child of k{}".format(int(r), int(p)) + print("k{} is the left child of k{}".format(int(r), int(p))) construct_optimal_bst_aux(root, r, i, r - 1) construct_optimal_bst_aux(root, r, r + 1, j) else: - print "d{} is the left child of k{}".format(int(j), int(p)) + print("d{} is the left child of k{}".format(int(j), int(p))) if i > p: if i <= j: r = root[i, j] - print "k{} is the right child of k{}".format(int(r), int(p)) + print("k{} is the right child of k{}".format(int(r), int(p))) construct_optimal_bst_aux(root, r, i, r - 1) construct_optimal_bst_aux(root, r, r + 1, j) else: - print "d{} is the right child of k{}".format(int(j), int(p)) + print("d{} is the right child of k{}".format(int(j), int(p))) diff --git a/os_tree.py b/os_tree.py index a30d31e..46cd716 100755 --- a/os_tree.py +++ b/os_tree.py @@ -1,11 +1,13 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class os_node(rb_node): + +class OSNode(RbNode): def __init__(self, key, p, left, right, color, size): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.size = size + def select_recursive(self, i): r = self.left.size + 1 if i == r: @@ -14,6 +16,7 @@ def select_recursive(self, i): return self.left.select_recursive(i) else: return self.right.select_recursive(i - r) + def select_iterative(self, i): x = self while True: @@ -25,6 +28,7 @@ def select_iterative(self, i): else: x = x.right i = i - r + def key_rank(self, k): r = self.left.size + 1 if k == self.key: @@ -33,6 +37,7 @@ def key_rank(self, k): return self.left.key_rank(k) else: return r + self.right.key_rank(k) + def ith_successor(self, i): if i == 0: return self @@ -47,15 +52,19 @@ def ith_successor(self, i): y = y.p if y.size != 0: return y.ith_successor(i - r - 1) -class os_tree(rb_tree): - nil = os_node(None, None, None, None, 1, 0) + + +class os_tree(RbTree): + nil = OSNode(None, None, None, None, 1, 0) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: - self.insert(os_node(i, None, None, None, 0, 1)) + self.insert(OSNode(i, None, None, None, 0, 1)) else: - print "Not invalid argument" + print("Not invalid argument") + def insert(self, z): y = self.nil x = self.root @@ -75,8 +84,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def delete(self, z): y = z y_original_color = y.color @@ -106,6 +116,7 @@ def delete(self, z): traverse = traverse.p if y_original_color == 1: self.delete_fixup(x) + def left_rotate(self, x): y = x.right x.right = y.left @@ -122,6 +133,7 @@ def left_rotate(self, x): x.p = y y.size = x.size x.size = x.left.size + x.right.size + 1 + def right_rotate(self, y): x = y.left y.left = x.right @@ -138,6 +150,7 @@ def right_rotate(self, y): y.p = x x.size = y.size y.size = y.left.size + y.right.size + 1 + def rank(self, x): r = x.left.size + 1 y = x diff --git a/partition.py b/partition.py index 2f449b5..ae41bf5 100644 --- a/partition.py +++ b/partition.py @@ -1,58 +1,54 @@ import random -def partition(A, p, r): - x = A[r] - i = p - 1 - for j in range(p, r): - if A[j] <= x: - i = i + 1 - A[i], A[j] = A[j], A[i] - A[i + 1], A[r] = A[r], A[i + 1] - return i + 1 - -def partition2(A, p, r): - ''' - Partition A into three parts: < x, = x, > x. The return value is the median of the second part. So the return value is floor((p + r) / 2) when all elements in the array A[p .. r] have the same value. Partition in place. - ''' - x = A[r] - i = p - 1 + +def partition(array, left, right): + pivot_index = left + pivot = array[right] + for i in range(left, right): + if array[i] <= pivot: + array[i], array[pivot_index] = array[pivot_index], array[i] + pivot_index += 1 + array[pivot_index], array[right] = array[right], array[pivot_index] + return pivot_index + + +def partition2(array, left, right): + """ + Partition A into three parts: < x, = x, > x. The return value is the median of the second part. + So the return value is (left + right) // 2 when all elements in the array A[left .. right] have the same value. Partition in place. + """ + x = array[right] + i = left - 1 k = i - for j in range(p, r): - if A[j] < x: + for j in range(left, right): + if array[j] < x: i = i + 1 - A[i], A[j] = A[j], A[i] + array[i], array[j] = array[j], array[i] k = k + 1 if i != k: - A[j], A[k] = A[k], A[j] - elif A[j] == x: + array[j], array[k] = array[k], array[j] + elif array[j] == x: k = k + 1 - A[k], A[j] = A[j], A[k] - A[k + 1], A[r] = A[r], A[k + 1] - return (k + 2 + i) / 2 - -def partition3(A, p, r): - ''' - Variant of partition2. Requires O(n) extra space, but it is easier to implement. - ''' - x = A[r] - n = r - p + 1 - i = -1 - k = n - B = [0] * n - for j in range(p, r): - if A[j] < x: - i = i + 1 - B[i] = A[j] - elif A[j] > x: - k = k - 1 - B[k] = A[j] - for j in range(i + 1, k): - B[j] = x - for j in range(p, r + 1): - A[j] = B[j - p] - return (2 * p + i + k) / 2 - -def randomized_partition(A, p, r): - i = random.randint(p, r) - A[i], A[r] = A[r], A[i] - return partition(A, p, r) + array[k], array[j] = array[j], array[k] + array[k + 1], array[right] = array[right], array[k + 1] + return (k + 2 + i) // 2 + + +def partition3(array, left, right): + """ + Variant of partition. Requires O(n) extra space, but it is easier to implement. + """ + pivot = array[right] + left_part = [array[i] for i in range(left, right) if array[i] <= pivot] + right_part = [array[i] for i in range(left, right) if array[i] > pivot] + pivot_index = left + len(left_part) + array[left:pivot_index] = left_part[:] + array[pivot_index + 1:right + 1] = right_part[:] + array[pivot_index] = pivot + return pivot_index + + +def randomized_partition(array, left, right): + i = random.randint(left, right) + array[i], array[right] = array[right], array[i] + return partition(array, left, right) diff --git a/partition_test.py b/partition_test.py deleted file mode 100644 index c5407ef..0000000 --- a/partition_test.py +++ /dev/null @@ -1,17 +0,0 @@ -import unittest -from partition import partition, partition2, partition3 - -class TestPartition(unittest.TestCase): - def test_partition(self): - a = [2, 8, 7, 1, 3, 5, 6, 4] - partition(a, 0, 7) - self.assertEquals(a, [2, 1, 3, 4, 7, 5, 6, 8]) - def test_partition2(self): - a = [2, 8, 7, 1, 4, 5, 6, 4] - partition2(a, 0, 7) - self.assertEquals(a, [2, 1, 4, 4, 7, 5, 6, 8]) - def test_partition3(self): - a = [2, 8, 7, 1, 3, 5, 6, 4] - partition3(a, 0, 7) - self.assertEquals(a, [2, 1, 3, 4, 6, 5, 7, 8]) - diff --git a/pointer_tree.py b/pointer_tree.py index 57e431f..aeae9c1 100644 --- a/pointer_tree.py +++ b/pointer_tree.py @@ -1,25 +1,34 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class pointer_node(rb_node): + +class pointer_node(RbNode): def __init__(self, key, p, left, right, color, minimum, maximum, predecessor, successor): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.minimum = minimum self.maximum = maximum self.predecessor = predecessor self.successor = successor -class pointer_tree(rb_tree): - negative_infinity = pointer_node(float("-Inf"), None, None, None, 1, None, None, None, None) - positive_infinity = pointer_node(float("Inf"), None, None, None, 1, None, None, None, None) - nil = pointer_node(None, None, None, None, 1, negative_infinity, positive_infinity, None, None) + + +class pointer_tree(RbTree): + negative_infinity = pointer_node( + float("-Inf"), None, None, None, 1, None, None, None, None) + positive_infinity = pointer_node( + float("Inf"), None, None, None, 1, None, None, None, None) + nil = pointer_node(None, None, None, None, 1, + negative_infinity, positive_infinity, None, None) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: - self.insert(pointer_node(i, None, None, None, 0, None, None, None, None)) + self.insert(pointer_node(i, None, None, + None, 0, None, None, None, None)) else: - print "Not invalid argument" + print("Not invalid argument") + def insert(self, z): y = self.nil x = self.root @@ -61,8 +70,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def left_rotate(self, x): y = x.right x.right = y.left @@ -82,6 +92,7 @@ def left_rotate(self, x): x.maximum = x else: x.maximum = x.right.maximum + def right_rotate(self, y): x = y.left y.left = x.right @@ -101,6 +112,7 @@ def right_rotate(self, y): y.minimum = y else: y.minimum = y.left.minimum + def delete(self, z): y = z y_original_color = y.color @@ -124,7 +136,7 @@ def delete(self, z): y.left = z.left y.left.p = y y.color = z.color - # After we delete z, the only nodes whose predecessor and successor attributes need to be updated are z's successor and z's predecessor + # After we delete z, the only nodes whose predecessor and successor attributes need to be updated are z's successor and z's predecessor z.predecessor.successor = z.successor z.successor.predecessor = z.predecessor traverse = x.p diff --git a/polar_angle.py b/polar_angle.py index 67f2b4a..d4ab834 100644 --- a/polar_angle.py +++ b/polar_angle.py @@ -1,33 +1,42 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -from heap import max_heap +from heap import MaxHeap -class vector(object): - def __init__(self, p2, p1 = (0, 0)): + +class Vector: + def __init__(self, p2, p1=(0, 0)): self.x = p2[0] - p1[0] self.y = p2[1] - p1[0] + def cross_product(self, v): return self.x * v.y - v.x * self.y + def __lt__(self, v): return self.cross_product(v) > 0 + def __gt__(self, v): return self.cross_product(v) < 0 + def __eq__(self, v): return self.cross_product(v) == 0 + def __le__(self, v): return self.cross_product(v) >= 0 + def __ge__(self, v): return self.cross_product(v) <= 0 + + def polar_angle(p0, point_list): - '''sort a sequence of n points according to + """sort a sequence of n points according to their polar angles with respect to a given origin point p0. - ''' - v0 = vector((p0[0] + 1, p0[1]), p0) # The polar angle of v0 is 0 - vector_list = [vector(p, p0) for p in point_list] - angle_0 = [] #list of vectors whose polar angles are 0 - angle_pi = [] #list of vectors whose polar angles are pi - angle_0_pi = [] #list of vectors whose polar angles are larger than 0 and smaller than pi - angle_pi_2pi = [] #list of vectors whose polar angles are larger than pi and smaller than 2pi + """ + v0 = Vector((p0[0] + 1, p0[1]), p0) # The polar angle of v0 is 0 + vector_list = [Vector(p, p0) for p in point_list] + angle_0 = [] # list of vectors whose polar angles are 0 + angle_pi = [] # list of vectors whose polar angles are pi + angle_0_pi = [] # list of vectors whose polar angles are larger than 0 and smaller than pi + angle_pi_2pi = [] # list of vectors whose polar angles are larger than pi and smaller than 2pi for v in vector_list: if v == v0: if v.x > 0: @@ -38,8 +47,8 @@ def polar_angle(p0, point_list): angle_pi_2pi.append(v) elif v > v0: angle_0_pi.append(v) - heap_0_pi = max_heap(angle_0_pi) - heap_pi_2pi = max_heap(angle_pi_2pi) + heap_0_pi = MaxHeap(angle_0_pi) + heap_pi_2pi = MaxHeap(angle_pi_2pi) heap_0_pi.heapsort() heap_pi_2pi.heapsort() return [(v.x, v.y) for v in (angle_0 + heap_0_pi + angle_pi + heap_pi_2pi)] diff --git a/polygon_area.py b/polygon_area.py index 262f89c..6d41e6e 100644 --- a/polygon_area.py +++ b/polygon_area.py @@ -1,9 +1,11 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python +from typing import Sequence, Tuple, Union -def polygon_area(P): - n = len(P) - S = 0 - for i in range(0, n - 1): - S = S + (P[i][0] + P[i + 1][0]) * (P[i + 1][1] - P[i][1]) - S = S + (P[0][0] + P[n - 1][0]) * (P[0][1] - P[n - 1][1]) - return 0.5 * abs(S) +Number = Union[int, float] + + +def polygon_area(polygon: Sequence[Tuple[Number, Number]]) -> float: + n = len(polygon) + area = sum((polygon[i][0] + polygon[i + 1][0]) * (polygon[i + 1][1] - polygon[i][1]) for i in range(n - 1)) + area += (polygon[0][0] + polygon[n - 1][0]) * (polygon[0][1] - polygon[n - 1][1]) + return 0.5 * abs(area) diff --git a/polynomial_multiply.py b/polynomial_multiply.py index 11fd194..15c8d7d 100644 --- a/polynomial_multiply.py +++ b/polynomial_multiply.py @@ -1,23 +1,24 @@ import math -import ft +import fft -def polynominal_multiply(a, b, precision = 0): + +def polynominal_multiply(a, b, precision=0): a_len = len(a) b_len = len(b) length = int(2 ** (1 + math.ceil(math.log(max(a_len, b_len))))) - print length + print(length) extend_a = [0] * length extend_b = [0] * length - for i in range(0, a_len): + for i in range(a_len): extend_a[i] = a[i] for i in range(a_len, length): extend_a[i] = 0 - for i in range(0, b_len): + for i in range(b_len): extend_b[i] = b[i] for i in range(b_len, length): extend_b[i] = 0 - a_fft = ft.recursive_fft(extend_a) - b_fft = ft.recursive_fft(extend_b) - m_fft = [a_fft[i] * b_fft[i] for i in range(0, len(a_fft))] - ab = ft.recursive_inverse_fft(m_fft) - return [round(ab[i].real, precision) for i in range(0, a_len + b_len - 1)] + a_fft = fft.recursive_fft(extend_a) + b_fft = fft.recursive_fft(extend_b) + m_fft = [a_fft[i] * b_fft[i] for i in range(len(a_fft))] + ab = fft.recursive_inverse_fft(m_fft) + return [round(ab[i].real, precision) for i in range(a_len + b_len - 1)] diff --git a/pow.c b/pow.c deleted file mode 100644 index 491909c..0000000 --- a/pow.c +++ /dev/null @@ -1,38 +0,0 @@ -// AUTHOR: WangQiang -// CREATE DATE: -// LAST UPDATE DATE: 20140524 -// EMAIL: cntqrxj@gmail.com - -/* pow: comput x^n; return value: x ^ n */ -int pow1(int x, unsigned n) { - int square; - - if (n == 0) - return 1; - if (n == 1) - return x; - - square = x * x; - if (n == 2) - return square; - if (n % 2) - return pow1(square, n / 2) * x; - else - return pow1(square, n / 2); -} - -int pow2(int x, unsigned n) { - int tmp; - - if (n == 0) - return 1; - if (n == 1) - return x; - if (n == 2) - return x * x; - tmp = pow2(x, n / 2); - if (n % 2) - return tmp * tmp * x; - else - return tmp * tmp; -} diff --git a/pow.py b/pow.py new file mode 100644 index 0000000..00b5f0a --- /dev/null +++ b/pow.py @@ -0,0 +1,22 @@ +def pow1(x, n: int): + """ + compute x ^ n + """ + if n == 0: + return 1 + square = x * x + if n % 2: + return pow1(square, n // 2) * x + return pow1(square, n // 2) + + +def pow2(x, n: int): + """ + compute x ^ n + """ + if n == 0: + return 1 + tmp = pow2(x, n // 2) + if n % 2: + return tmp * tmp * x + return tmp * tmp diff --git a/priority_queue.py b/priority_queue.py index 7d9252b..2d39594 100644 --- a/priority_queue.py +++ b/priority_queue.py @@ -1,9 +1,11 @@ import sys -from heap import max_heap, min_heap +from heap import MaxHeap, MinHeap -class max_priority_queue(max_heap): + +class MaxPriorityQueue(MaxHeap): def heap_maximum(self): return self[0] + def heap_extract_max(self): if self.heap_size < 1: sys.exit("heap underflow") @@ -12,29 +14,33 @@ def heap_extract_max(self): self.heap_size = self.heap_size - 1 self.max_heapify(0) return maximum + def heap_increase_key(self, i, key): if key < self[i]: sys.exit("new key is smaller than current key") self[i] = key while i > 0 and self[self.parent(i)] < self[i]: - tmp = self[self.parent(i)] - self[self.parent(i)] = self[i] - self[i] = tmp + self[i], self[self.parent(i)] = self[self.parent(i)], self[i] i = self.parent(i) + def max_heap_insert(self, key): if self.heap_size >= self.length: sys.exit("heap overflow") self.heap_size = self.heap_size + 1 self[self.heap_size - 1] = float("-Inf") self.heap_increase_key(self.heap_size - 1, key) + def heap_delete(self, i): self.heap_increase_key(i, float("Inf")) self[0], self[self.heap_size - 1] = self[self.heap_size - 1], self[0] self.heap_size = self.heap_size - 1 self.max_heapify(0) -class min_priority_queue(min_heap): + + +class MinPriorityQueue(MinHeap): def heap_minimum(self): return self[0] + def heap_extract_min(self): if self.heap_size < 1: sys.exit("heap underflow") @@ -43,15 +49,15 @@ def heap_extract_min(self): self.heap_size = self.heap_size - 1 self.min_heapify(0) return minimum + def heap_decrease_key(self, i, key): if key > self[i]: sys.exit("new key is larger than current key") self[i] = key while i > 0 and self[self.parent(i)] > self[i]: - tmp = self[self.parent(i)] - self[self.parent(i)] = self[i] - self[i] = tmp + self[i], self[self.parent(i)] = self[self.parent(i)], self[i] i = self.parent(i) + def min_heap_insert(self, key): if self.heap_size >= self.length: sys.exit("heap overflow") diff --git a/priority_queue_test.py b/priority_queue_test.py deleted file mode 100644 index b9a9999..0000000 --- a/priority_queue_test.py +++ /dev/null @@ -1,74 +0,0 @@ -import unittest -from priority_queue import max_priority_queue, min_priority_queue - -class TestMaxPriorityQueue(unittest.TestCase): - def test_init(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - q = max_priority_queue(a) - self.assertEquals(q, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) - def test_heap_maximum(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - self.assertEquals(max_priority_queue(a).heap_maximum(), 16) - def test_heap_extract_max(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - h = max_priority_queue(a) - self.assertEquals(h.heap_extract_max(), 16) - self.assertEquals(h, [14, 8, 10, 4, 7, 9, 3, 2, 1, 1]) - def test_heap_increase_key(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - h = max_priority_queue(a) - h.heap_increase_key(8, 15) - self.assertEquals(h, [16, 15, 10, 14, 7, 9, 3, 2, 8, 1]) - def test_heap_insert(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - queue = max_priority_queue(a) - queue.heap_extract_max() - queue.max_heap_insert(100) - self.assertEquals(queue, [100, 14, 10, 4, 8, 9, 3, 2, 1, 7]) - def test_heap_delete(self): - a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] - h = max_priority_queue(a) - h.heap_delete(4) - self.assertEquals(h[0:h.heap_size], [16, 14, 10, 8, 1, 9, 3, 2, 4]) - h.heap_delete(2) - self.assertEquals(h[0:h.heap_size], [16, 14, 9, 8, 1, 4, 3, 2]) - h.heap_delete(0) - self.assertEquals(h[0:h.heap_size], [14, 8, 9, 2, 1, 4, 3]) - h.heap_delete(5) - self.assertEquals(h[0:h.heap_size], [14, 8, 9, 2, 1, 3]) - h.heap_delete(3) - self.assertEquals(h[0:h.heap_size], [14, 8, 9, 3, 1]) - h.heap_delete(1) - self.assertEquals(h[0:h.heap_size], [14, 3, 9, 1]) - h.heap_delete(3) - self.assertEquals(h[0:h.heap_size], [14, 3, 9]) - h.heap_delete(2) - self.assertEquals(h[0:h.heap_size], [14, 3]) - h.heap_delete(1) - self.assertEquals(h[0:h.heap_size], [14]) - h.heap_delete(0) - self.assertEquals(h[0:h.heap_size], []) -class TestMinPriorityQueue(unittest.TestCase): - def test_init(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - q = min_priority_queue(a) - self.assertEquals(q, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) - def test_heap_minimum(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - self.assertEquals(min_priority_queue(a).heap_minimum(), 1) - def test_heap_extract_min(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - q = min_priority_queue(a) - self.assertEquals(q.heap_extract_min(), 1) - self.assertEquals(q, [2, 4, 3, 10, 7, 8, 9, 16, 14, 16]) - def test_heap_decrease_key(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - q = min_priority_queue(a) - q.heap_decrease_key(8, 1) - self.assertEquals(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) - def test_heap_insert(self): - a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] - q = min_priority_queue(a) - q.heap_extract_min() - q.min_heap_insert(0) - self.assertEquals(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) diff --git a/qsort.c b/qsort.c deleted file mode 100644 index 9729ace..0000000 --- a/qsort.c +++ /dev/null @@ -1,25 +0,0 @@ -/* qsort: sort v[left]...v[right] into increasing order */ -void qsort(int v[], int left, int right) { - int i, last; - - void swap(int v[], int, int); - - if (left >= right) /* do nothing if array contains */ - return; /* fewer than two elements */ - swap(v, left, (left + right)/2); - last = left; - for (i = left + 1; i <= right; i++) - if (v[i] < v[left]) - swap(v, ++last, i); - swap(v, left, last); - qsort(v, left, last - 1 ); - qsort(v, last+1, right); -} - -void swap(int v[], int i, int j) { - int temp; - - temp = v[i]; - v[i] = v[j]; - v[j] = temp; -} diff --git a/quicksort.py b/quicksort.py index e269c00..02b79e7 100644 --- a/quicksort.py +++ b/quicksort.py @@ -1,11 +1,15 @@ -from partition import partition, partition2, partition3, randomized_partition -def quicksort(A, p, r, partition_method = partition): - if p < r: - q = partition_method(A, p, r) - quicksort(A, p, q - 1) - quicksort(A, q+1, r) -def randomized_quicksort(A, p, r): - if p < r: - q = randomized_partition(A, p, r) - randomized_quicksort(A, p, q - 1) - randomized_quicksort(A, q+1, r) +from partition import partition, randomized_partition + + +def quicksort(array, left, right, partition_method=partition): + if left < right: + index = partition_method(array, left, right) + quicksort(array, left, index - 1) + quicksort(array, index + 1, right) + + +def randomized_quicksort(array, left, right): + if left < right: + index = randomized_partition(array, left, right) + randomized_quicksort(array, left, index - 1) + randomized_quicksort(array, index + 1, right) diff --git a/quicksort_test.py b/quicksort_test.py deleted file mode 100644 index e09c230..0000000 --- a/quicksort_test.py +++ /dev/null @@ -1,32 +0,0 @@ -import unittest -from partition import partition, partition2, partition3 -import random -from quicksort import quicksort, randomized_quicksort - -class TestQuickSort(unittest.TestCase): - def test_quicksort(self): - for i in range(0, 100): - A = [random.randint(1, 10000) for i in range(0, 100)] - B = A[:] - quicksort(A, 0, len(A) - 1, partition) - B.sort() - self.assertEquals(A, B) - for i in range(0, 100): - A = [random.randint(1, 10000) for i in range(0, 100)] - B = A[:] - quicksort(A, 0, len(A) - 1, partition2) - B.sort() - self.assertEquals(A, B) - for i in range(0, 100): - A = [random.randint(1, 10000) for i in range(0, 100)] - B = A[:] - quicksort(A, 0, len(A) - 1, partition3) - B.sort() - self.assertEquals(A, B) - def test_randomized_quicksort(self): - for i in range(0, 100): - A = [random.randint(1, 10000) for i in range(0, 100)] - B = A[:] - randomized_quicksort(A, 0, len(A) - 1) - B.sort() - self.assertEquals(A, B) diff --git a/random_array.py b/random_array.py new file mode 100644 index 0000000..e1a7cca --- /dev/null +++ b/random_array.py @@ -0,0 +1,6 @@ +import random + + +def random_arrays(array_num=100, array_size=100, array_lowerbound=0, array_upperbound=10000): + for _ in range(array_num): + yield [random.randint(array_lowerbound, array_upperbound) for _ in range(array_size)] diff --git a/randomized_permute.py b/randomized_permute.py index b1d05c6..a5bc53a 100644 --- a/randomized_permute.py +++ b/randomized_permute.py @@ -1,16 +1,17 @@ import random + def randomize_in_place(A): - ''' + """ An algorithm to permute the given array in place. It computes a uniform random permutation. - ''' + """ n = len(A) - for i in range(0, n): + for i in range(n): j = random.randint(i, n - 1) A[i], A[j] = A[j], A[i] -#def permute_by_sorting(A): +# def permute_by_sorting(A): # n = len(A) # P = [0] * n -# for i in +# for i in diff --git a/randomized_select.py b/randomized_select.py index fac9905..101525f 100644 --- a/randomized_select.py +++ b/randomized_select.py @@ -1,5 +1,6 @@ from partition import randomized_partition + def randomized_select(A, p, r, i): if p == r: return A[p] @@ -11,4 +12,3 @@ def randomized_select(A, p, r, i): return randomized_select(A, p, q - 1, i) else: return randomized_select(A, q + 1, r, i - k) - diff --git a/rank_tree.py b/rank_tree.py index e9d66d4..5c1e8e5 100644 --- a/rank_tree.py +++ b/rank_tree.py @@ -1,17 +1,20 @@ # The variant of os_tree that use rank instead of size -#!/usr/bin/env ipython +# !/usr/bin/env python -from rb_tree import rb_node, rb_tree +from rb_tree import RbNode, RbTree -class rank_node(rb_node): + +class rank_node(RbNode): def __init__(self, key, p, left, right, color, rank): - rb_node.__init__(self, key, p, left, right, color) + RbNode.__init__(self, key, p, left, right, color) self.rank = rank + def update_rank_whole_tree(self, amount): if self.rank != 0: self.rank = self.rank + amount self.left.update_rank_whole_tree(amount) self.right.update_rank_whole_tree(amount) + def decrease_all_successors(self, amount): self.rank = self.rank - amount self.right.update_rank_whole_tree(-1 * amount) @@ -23,15 +26,18 @@ def decrease_all_successors(self, amount): if y.rank != 0: y.decrease_all_successors(amount) -class rank_tree(rb_tree): + +class rank_tree(RbTree): nil = rank_node(None, None, None, None, 1, 0) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: self.insert(rank_node(i, None, None, None, 0, 1)) else: - print "Not invalid argument" + print("Not invalid argument") + def insert(self, z): y = self.nil x = self.root @@ -55,10 +61,11 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def delete(self, z): - z.decrease_all_successors(1) # z is counted as a successor + z.decrease_all_successors(1) # z is counted as a successor y = z y_original_color = y.color if z.left == self.nil: diff --git a/rb_tree.py b/rb_tree.py index 3d5d0a3..77a33c9 100644 --- a/rb_tree.py +++ b/rb_tree.py @@ -1,13 +1,15 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python # we use 0 to mean red, 1 to mean black from tree import Node, Tree -class rb_node(Node): + +class RbNode(Node): def __init__(self, key, p, left, right, color): Node.__init__(self, key, p, left, right) self.color = color + def minimum(self, nil): x = self y = x @@ -16,17 +18,21 @@ def minimum(self, nil): x = x.left return y -class rb_tree(Tree): - nil = rb_node(None, None, None, None, 1) + +class RbTree(Tree): + nil = RbNode(None, None, None, None, 1) root = nil + def __init__(self, values): if isinstance(values, list): for i in values: - self.insert(rb_node(i, None, None, None, 0)) + self.insert(RbNode(i, None, None, None, 0)) else: - print "Not invalid argument" + print("Not invalid argument") + def minimum(self): return self.root.minimum(self.nil) + def __getitem__(self, key): return self.iterative_tree_search(key) @@ -82,8 +88,9 @@ def insert(self, z): z.p = y z.left = self.nil z.right = self.nil - z.color = 0 #red + z.color = 0 # red self.insert_fixed(z) + def insert_fixed(self, z): while z.p.color == 0: if z.p.p.left == z.p: @@ -117,6 +124,7 @@ def insert_fixed(self, z): z.color = 0 z.p.color = 1 self.root.color = 1 + def iterative_tree_search(self, k): x = self.root while x != self.nil and x.key != k: @@ -134,6 +142,7 @@ def transplant(self, u, v): else: u.p.right = v v.p = u.p + def delete(self, z): y = z y_original_color = y.color @@ -159,6 +168,7 @@ def delete(self, z): y.color = z.color if y_original_color == 1: self.delete_fixup(x) + def delete_fixup(self, x): while x != self.root and x.color == 1: if x == x.p.left: diff --git a/right_horizontal_ray_intersect.py b/right_horizontal_ray_intersect.py index 9ba42d5..0f2c43f 100644 --- a/right_horizontal_ray_intersect.py +++ b/right_horizontal_ray_intersect.py @@ -1,9 +1,10 @@ -#!/usr/bin/ipython +#!/usr/bin/python from segment_intersect import segments_intersect + def right_horizontal_ray_intersect(p0, p1, p2): - '''An algorithm to determine whether a given right horizontal ray from p0 intersects a line segment p1p2''' + """An algorithm to determine whether a given right horizontal ray from p0 intersects a line segment p1p2""" max_x = max(p1[0], p2[0]) if max_x < p0[0]: return False @@ -15,6 +16,7 @@ def right_horizontal_ray_intersect(p0, p1, p2): return equal(p0, p1) or equal(p0, p2) else: return segments_intersect(p1, p2, p0, (max_x, p0[1])) - + + def equal(p1, p2): return p1[0] == p2[0] and p1[1] == p2[1] diff --git a/segment_intersect.py b/segment_intersect.py index b17b420..9a594ab 100644 --- a/segment_intersect.py +++ b/segment_intersect.py @@ -1,11 +1,12 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + def segments_intersect(p1, p2, p3, p4): d1 = direction(p3, p4, p1) d2 = direction(p3, p4, p2) d3 = direction(p1, p2, p3) d4 = direction(p1, p2, p4) - if ((d1 > 0 and d2 < 0) or (d1 < 0 and d2 > 0)) and ((d3 > 0 and d4 < 0) or (d3 < 0 and d4 > 0)): + if ((d1 > 0 > d2) or (d1 < 0 < d2)) and ((d3 > 0 > d4) or (d3 < 0 < d4)): return True elif d1 == 0 and on_segment(p3, p4, p1): return True @@ -17,12 +18,14 @@ def segments_intersect(p1, p2, p3, p4): return True else: return False + + def direction(pi, pj, pk): v1 = (pk[0] - pi[0], pk[1] - pi[1]) v2 = (pj[0] - pi[0], pj[1] - pi[1]) return v1[0] * v2[1] - v2[0] * v1[1] + + def on_segment(pi, pj, pk): - if min(pi[0], pj[0]) <= pk[0] and pk[0] <= max(pi[0], pj[0]) and min(pi[1], pj[1]) <= pk[1] and pk[1] <= max(pi[1], pj[1]): - return True - else: - return False + return min(pi[0], pj[0]) <= pk[0] <= max(pi[0], pj[0]) and min(pi[1], pj[1]) <= pk[1] <= max( + pi[1], pj[1]) diff --git a/selection-sort.c b/selection-sort.c deleted file mode 100644 index 1ed70eb..0000000 --- a/selection-sort.c +++ /dev/null @@ -1,29 +0,0 @@ -#include - -void SelectionSort(int *A, int n) { - int i, j; - int min, index; - int tmp; - - for (i = 0; i < n - 1; i++) { - min = A[i]; - index = i; - - for (j = i + 1; j < n; j++) - if (A[j] < min) { - min = A[j]; - index = j; - } - tmp = A[i]; - A[i] = A[index]; - A[index] = tmp; - } -} - -int main() { - int A[6] = {6, 5, 5, 3, 100, 1}; - - SelectionSort(A, 6); - printf("%d, %d, %d, %d, %d, %d\n", A[0], A[1], A[2], A[3], A[4], A[5]); - return 0; -} diff --git a/selection_sort.py b/selection_sort.py new file mode 100644 index 0000000..a7b18a8 --- /dev/null +++ b/selection_sort.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python +# encoding: utf-8 + + +def selection_sort(array: list): + """ + Inplace sort + Consider sorting n numbers stored in array A by first finding the smallest element of A + and exchanging it with the element in A[0] . Then find the second smallest element of A, and exchange it with A[1]. + Continue in this manner for the first n - 1 elements of A. + :param array: + :return: + """ + n = len(array) + for i in range(n - 1): + minimum = array[i] + index = i + for j in range(i + 1, n): + if minimum > array[j]: + minimum = array[j] + index = j + array[i], array[index] = array[index], array[i] diff --git a/simplex.py b/simplex.py index d472d2d..249ed80 100644 --- a/simplex.py +++ b/simplex.py @@ -1,34 +1,36 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import sys + def pivot(N, B, A, b, c, v, l, e): new_A = dict() new_b = dict() new_c = dict() -#Compute the coefficients of the equation for new basic variable + # Compute the coefficients of the equation for new basic variable new_b[e] = b[l] / A[l][e] new_A[e] = dict() for j in N - {e}: new_A[e][j] = A[l][j] / A[l][e] new_A[e][l] = 1 / A[l][e] -#Compute the coefficients of the remaining constraints + # Compute the coefficients of the remaining constraints for i in B - {l}: new_A[i] = dict() new_b[i] = b[i] - A[i][e] * new_b[e] for j in N - {e}: new_A[i][j] = A[i][j] - A[i][e] * new_A[e][j] new_A[i][l] = -1 * A[i][e] * new_A[e][l] -#Compute the objective function + # Compute the objective function new_v = v + c[e] * new_b[e] for j in N - {e}: new_c[j] = c[j] - c[e] * new_A[e][j] new_c[l] = -1 * c[e] * new_A[e][l] -#Compute new sets of basic and nonbasic variables + # Compute new sets of basic and nonbasic variables new_N = (N - {e}).union({l}) new_B = (B - {l}).union({e}) return new_N, new_B, new_A, new_b, new_c, new_v + def simplex(A, b, c): N, B, A, b, c, v = initialize_simplex(A, b, c) while True: @@ -37,7 +39,7 @@ def simplex(A, b, c): if c[j] > 0: e = j break - if e == None: + if not e: break minimum = float("Inf") for i in sorted(B): @@ -50,7 +52,7 @@ def simplex(A, b, c): return "unbounded" else: (N, B, A, b, c, v) = pivot(N, B, A, b, c, v, l, e) - print N, B, A, b, c, v + print(N, B, A, b, c, v) n = len(N) x = [0] * n for i in range(1, n + 1): @@ -58,11 +60,12 @@ def simplex(A, b, c): x[i - 1] = b[i] return x + def initialize_simplex(A, b, c): m = len(b) n = len(c) minimum = float("Inf") - for i in range(0, m): + for i in range(m): if minimum > b[i]: k = i + 1 minimum = b[i] @@ -88,29 +91,29 @@ def initialize_simplex(A, b, c): new_A[n + i] = dict() new_A[n + i][0] = -1 for j in range(1, n + 1): - new_A[n + i][j] = A[i -1][j - 1] + new_A[n + i][j] = A[i - 1][j - 1] for j in range(1, n + 1): new_c[j] = 0 new_c[0] = -1 A = new_A b = new_b c = new_c - N = set(range(0, n + 1)) + N = set(range(n + 1)) B = set(range(n + 1, n + m + 1)) v = 0 l = n + k (N, B, A, b, c, v) = pivot(N, B, A, b, c, v, l, 0) - print N, B, A, b, c, v + print(N, B, A, b, c, v) while True: e = None - print N + print(N) for j in sorted(N): - print "c[{}] = {}".format(j, c[j]) + print("c[{}] = {}".format(j, c[j])) if c[j] > 0: e = j break - print "e = {}".format(e) - if e == None: + print("e = {}".format(e)) + if not e: break minimum = float("Inf") for i in sorted(B): @@ -119,15 +122,15 @@ def initialize_simplex(A, b, c): if minimum > delta: l = i minimum = delta - print "l = {}".format(l) + print("l = {}".format(l)) if minimum == float("Inf"): -# return "unbounded" + # return "unbounded" break else: (N, B, A, b, c, v) = pivot(N, B, A, b, c, v, l, e) - print N, B, A, b, c, v + print(N, B, A, b, c, v) if abs(v) <= 2.0e-10: - # if v == 0: + # if v == 0: if 0 in B: for e in N: if A[0][e] != 0: @@ -144,21 +147,20 @@ def initialize_simplex(A, b, c): N = N - {0} for j in N: new_c[j] = 0 - j - print N, B, A, b, c, v + print(N, B, A, b, c, v) for i in range(1, n + 1): if i in B: v = v + c[i] * b[i] for j in N: new_c[j] = new_c[j] - c[i] * A[i][j] else: - print "i = {}".format(i) - print N - print B - print new_c - print c + print("i = {}".format(i)) + print(N) + print(B) + print(new_c) + print(c) new_c[i] = new_c[i] + c[i - 1] - print N, B, new_A, b, new_c, v + print(N, B, new_A, b, new_c, v) return N, B, new_A, b, new_c, v else: sys.exit("infeasible") diff --git a/single_edge.py b/single_edge.py index 50e57b1..f3736c9 100644 --- a/single_edge.py +++ b/single_edge.py @@ -1,135 +1,144 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -class node(object): +class node: def __init__(self, key, right): self.right = right self.key = key -class graph(object): - def __init__(self, data, option = 0): + + +class graph: + def __init__(self, data, option=0): if option == 0: self.vertices_number = len(data) self.vertices = [None] * self.vertices_number self.edges_number = 0 - for i in range(0, self.vertices_number): + for i in range(self.vertices_number): for j in data[i]: self.insert_edge(i + 1, j) elif option == 1: self.vertices_number = data self.vertices = [None] * self.vertices_number self.edges_number = 0 + def transpose(self): t = graph(self.vertices_number, 1) - for i in range(0, self.vertices_number): + for i in range(self.vertices_number): j = self.vertices[i] - while j != None: + while j is not None: t.insert_edge(j.key, i + 1) j = j.right return t + def union(self, g): u = graph(self.vertices_number, 1) - for i in range(0, self.vertices_number): + for i in range(self.vertices_number): j = self.vertices[i] - while j != None: + while j is not None: u.insert_edge(i + 1, j.key) j = j.right - for i in range(0, g.vertices_number): + for i in range(g.vertices_number): j = g.vertices[i] - while j != None: + while j is not None: u.insert_edge(i + 1, j.key) j = j.right - return u + return u + def single_edge(self): g = self.union(self.transpose()) single = graph(g.vertices_number, 1) s = [0] * g.vertices_number - for u in range(0, g.vertices_number): + for u in range(g.vertices_number): v = g.vertices[u] - while v != None: + while v: if (u + 1) != v.key and s[v.key - 1] == 0: single.insert_edge(u + 1, v.key) s[v.key - 1] = 1 v = v.right v = g.vertices[u] - while v != None: + while v: if s[v.key - 1] == 1: s[v.key - 1] = 0 v = v.right s[u] = 2 return single + def insert_edge(self, u, v): a = node(v, self.vertices[u - 1]) self.vertices[u - 1] = a self.edges_number = self.edges_number + 1 + def print_graph(self): - for i in range(0, self.vertices_number): + for i in range(self.vertices_number): j = self.vertices[i] - print '{}: '.format(i + 1), - while j != None: - print j.key, + print('{}: '.format(i + 1), ) + while j is not None: + print(j.key, ) j = j.right - print + print() + def square(self): grandchild = graph(self.vertices_number, 1) descendent = graph(self.vertices_number, 1) s = [0] * self.vertices_number # generate grandchild graph - for i in range(0, self.vertices_number): + for i in range(self.vertices_number): j = self.vertices[i] - while j != None: + while j is not None: k = self.vertices[j.key - 1] - while k != None: + while k is not None: if s[k.key - 1] == 0: - grandchild.insert_edge(i + 1, k.key) + grandchild.insert_edge(i + 1, k.key) s[k.key - 1] = 1 k = k.right j = j.right j = grandchild.vertices[i] - while j != None: + while j is not None: s[j.key - 1] = 0 j = j.right # generate great grandchild graph - for i in range(0, grandchild.vertices_number): + for i in range(grandchild.vertices_number): j = grandchild.vertices[i] - while j != None: + while j is not None: k = self.vertices[j.key - 1] - while k != None: + while k is not None: if s[k.key - 1] == 0: - descendent.insert_edge(i + 1, k.key) + descendent.insert_edge(i + 1, k.key) k = k.right j = j.right j = descendent.vertices[i] - while j != None: + while j is not None: s[j.key - 1] = 0 j = j.right square = graph(self.vertices_number, 1) - for i in range(0, self.vertices_number): + for i in range(self.vertices_number): j = self.vertices[i] - print j - while j != None: + print(j) + while j is not None: square.insert_edge(i + 1, j.key) s[j.key - 1] = 1 j = j.right j = grandchild.vertices[i] - while j != None: + while j is not None: if s[j.key - 1] == 0 and (i + 1) != j.key: square.insert_edge(i + 1, j.key) s[j.key - 1] = 1 j = j.right j = descendent.vertices[i] - while j != None: + while j is not None: if s[j.key - 1] == 0 and (i + 1) != j.key: square.insert_edge(i + 1, j.key) s[j.key - 1] = 1 j = j.right j = square.vertices[i] - while j != None: + while j is not None: s[j.key - 1] = 0 j = j.right -# self.print_graph() -# grandchild.print_graph() -# print -# descendent.print_graph() + # self.print(_graph()) + # grandchild.print(_graph()) + # print() + # descendent.print(_graph()) return square + def grandchild(self): pass diff --git a/square-matrix-multiply-Strassen.py b/square_matrix_multiply_Strassen.py similarity index 50% rename from square-matrix-multiply-Strassen.py rename to square_matrix_multiply_Strassen.py index f39dd74..a006392 100755 --- a/square-matrix-multiply-Strassen.py +++ b/square_matrix_multiply_Strassen.py @@ -1,40 +1,36 @@ #! /usr/bin/python2.7 -# AUTHOR: WangQiang -# CREATE DATE: 20140603 -# LAST UPDATE DATE: 20140604 -# EMAIL: cntqrxj@gmail.com - from numpy import * + def square_matrix_multiply(A, B): shape = A.shape length = shape[0] half = length / 2 - - C = zeros(shape, dtype = int64) + + C = zeros(shape, dtype=int64) if length == 1: C[0, 0] = A[0, 0] * B[0, 0] return C - - S1 = zeros((half, half), dtype = int64) - S2 = zeros((half, half), dtype = int64) - S3 = zeros((half, half), dtype = int64) - S4 = zeros((half, half), dtype = int64) - S5 = zeros((half, half), dtype = int64) - S6 = zeros((half, half), dtype = int64) - S7 = zeros((half, half), dtype = int64) - S8 = zeros((half, half), dtype = int64) - S9 = zeros((half, half), dtype = int64) - S10 = zeros((half, half), dtype = int64) - P1 = zeros((half, half), dtype = int64) - P2 = zeros((half, half), dtype = int64) - P3 = zeros((half, half), dtype = int64) - P4 = zeros((half, half), dtype = int64) - P5 = zeros((half, half), dtype = int64) - P6 = zeros((half, half), dtype = int64) - P7 = zeros((half, half), dtype = int64) + S1 = zeros((half, half), dtype=int64) + S2 = zeros((half, half), dtype=int64) + S3 = zeros((half, half), dtype=int64) + S4 = zeros((half, half), dtype=int64) + S5 = zeros((half, half), dtype=int64) + S6 = zeros((half, half), dtype=int64) + S7 = zeros((half, half), dtype=int64) + S8 = zeros((half, half), dtype=int64) + S9 = zeros((half, half), dtype=int64) + S10 = zeros((half, half), dtype=int64) + + P1 = zeros((half, half), dtype=int64) + P2 = zeros((half, half), dtype=int64) + P3 = zeros((half, half), dtype=int64) + P4 = zeros((half, half), dtype=int64) + P5 = zeros((half, half), dtype=int64) + P6 = zeros((half, half), dtype=int64) + P7 = zeros((half, half), dtype=int64) S1 = B[0:half, half:length] - B[half:length, half:length] S2 = A[0:half, 0:half] + A[0:half, half:length] @@ -54,21 +50,22 @@ def square_matrix_multiply(A, B): P5 = square_matrix_multiply(S5, S6) P6 = square_matrix_multiply(S7, S8) P7 = square_matrix_multiply(S9, S10) - + C[0:half, 0:half] = P5 + P4 - P2 + P6 C[0:half, half:length] = P1 + P2 C[half:length, 0:half] = P3 + P4 C[half:length, half:length] = P5 + P1 - P3 - P7 - - return C -#A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) -#B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) -#A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) -#B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) -A = array([[1, 3], [7, 5]]) -B = array([[6, 8], [4, 2]]) -#A = array([[1, 2, 3], [4, 5, 6]]) -#B = array([[1, 2], [4, 5]]) -print square_matrix_multiply(A, B) -#print dot(A, B) + return C + + +# # A = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) +# # B = array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]]) +# # A = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +# # B = array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) +# A = array([[1, 3], [7, 5]]) +# B = array([[6, 8], [4, 2]]) +# # A = array([[1, 2, 3], [4, 5, 6]]) +# # B = array([[1, 2], [4, 5]]) +# print(square_matrix_multiply(A, B)) +# # print( dot(A, B)) diff --git a/stack.py b/stack.py index 854f5bf..19b17d3 100644 --- a/stack.py +++ b/stack.py @@ -1,30 +1,36 @@ -class FullException(BaseException): +class FullException(Exception): pass -class EmptyException(BaseException): + + +class EmptyException(Exception): pass -class stack(list): +class Stack(list): def __init__(self, size): - list.__init__(self, [None] * size) + super(Stack, self).__init__([None] * size) self.top = -1 self.size = len(size) + def push(self, x): if self.full(): raise FullException("This stack is full") else: self.top = self.top + 1 self[self.top] = x - def pop(self): + + def pop(self, *args, **kwargs): if self.empty(): raise EmptyException('This stack is empty') else: self.top = self.top - 1 return self[self.top + 1] + def empty(self): - return self.top == -1: + return self.top == -1 + def full(self): - return self.top == self.size - 1: + return self.top == self.size - 1 # def multipop(self, k): # l = [] diff --git a/synthetic_division.py b/synthetic_division.py index 260e3e5..d3b84a9 100644 --- a/synthetic_division.py +++ b/synthetic_division.py @@ -1,4 +1,5 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + def synthetic_division(A, n, x): q = [0] * (n - 1) diff --git a/test.sh b/test.sh deleted file mode 100644 index 8de1f72..0000000 --- a/test.sh +++ /dev/null @@ -1 +0,0 @@ -for f in $(ls *test.py | cut -d '.' -f1); do ipython -m unittest $f;done diff --git a/tests/Bellman_Ford_matrix_test.py b/tests/Bellman_Ford_matrix_test.py new file mode 100644 index 0000000..012f71c --- /dev/null +++ b/tests/Bellman_Ford_matrix_test.py @@ -0,0 +1,22 @@ +from Bellman_Ford_matrix import Bellman_Ford_matrix, slow_all_pairs_shortest_paths +import unittest +import numpy + + +class TestBellmanFordMatrix(unittest.TestCase): + def test_Bellman_Ford_matrix(self): + W = numpy.array([[float("Inf"), 6., 7., float("Inf"), float("Inf")], [float("Inf"), float("Inf"), 8., 5., -4.], + [float("Inf"), float("Inf"), float("Inf"), -3., 9.], + [float("Inf"), -2., float("Inf"), float("Inf"), float("Inf")], + [2., float("Inf"), float("Inf"), 7., float("Inf")]]) + d, p = Bellman_Ford_matrix(W, 1) + self.assertEqual(d, [0, 2.0, 7.0, 4.0, -2.0]) + self.assertEqual(p, [None, 4, 1, 3, 2]) + + def test_slow_all_pairs_shortest_paths(self): + W = numpy.array([[0, 6., 7., float("Inf"), float("Inf")], [float("Inf"), 0, 8., 5., -4.], + [float("Inf"), float("Inf"), 0, -3., 9.], [float("Inf"), -2., float("Inf"), 0, float("Inf")], + [2., float("Inf"), float("Inf"), 7., 0]]) + L = slow_all_pairs_shortest_paths(W, 1) + # print(L) + self.assertEqual(L, [0, 2.0, 7.0, 4.0, -2.0]) diff --git a/tests/Horner_rule_test.py b/tests/Horner_rule_test.py new file mode 100644 index 0000000..2e33809 --- /dev/null +++ b/tests/Horner_rule_test.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import unittest +import random +from Horner_rule import Horner_rule + + +class TestHornerRule(unittest.TestCase): + def test_horner_rule(self): + for _ in range(100): + x = random.randint(1, 5) + coefficients = [random.randint(0, 100) for _ in range(11)] + expected_result = 0 + for index, coefficient in enumerate(coefficients): + expected_result += coefficient * x ** index + self.assertEqual(Horner_rule(x, coefficients), expected_result) diff --git a/Johnson_test.py b/tests/Johnson_test.py similarity index 85% rename from Johnson_test.py rename to tests/Johnson_test.py index 5352e58..f062a6a 100644 --- a/Johnson_test.py +++ b/tests/Johnson_test.py @@ -2,6 +2,7 @@ from graph import Vertex, Graph import unittest + class TestJohnson(unittest.TestCase): def testJohnson(self): a1 = Vertex(1) @@ -14,10 +15,10 @@ def testJohnson(self): g = Graph(vertices, edges) weight = [3, 8, -4, 1, 7, 4, 2, -5, 6] w = dict() - for i,j in zip(edges, weight): - w[i] = j + for i, j in zip(edges, weight): + w[i] = j D = Johnson(g, w) - print D + # print(D) a1 = Vertex(1) a2 = Vertex(2) a3 = Vertex(3) @@ -29,7 +30,7 @@ def testJohnson(self): g = Graph(vertices, edges) weight = [-1, 1, 2, 2, -8, -4, 3, 7, 5, 10] w = dict() - for i,j in zip(edges, weight): - w[i] = j + for i, j in zip(edges, weight): + w[i] = j D = Johnson(g, w) - print D + # print(D) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/all_pairs_shortest_paths_test.py b/tests/all_pairs_shortest_paths_test.py new file mode 100644 index 0000000..a5bf18b --- /dev/null +++ b/tests/all_pairs_shortest_paths_test.py @@ -0,0 +1,43 @@ +from all_pairs_shortest_paths import slow_all_pairs_shortest_paths, faster_all_pairs_shortest_paths +import unittest +import numpy as np + + +class TestAllPairsShortestPaths(unittest.TestCase): + def test_slow_all_pairs_shortest_paths(self): + W = np.array([[0, 3, 8, float("Inf"), -4], [float("Inf"), 0, float("Inf"), 1, 7], + [float("Inf"), 4, 0, float("Inf"), float("Inf")], [2, float("Inf"), -5, 0, float("Inf")], + [float("Inf"), float("Inf"), float("Inf"), 6, 0]]) + R = slow_all_pairs_shortest_paths(W) + 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]]) + self.assertEqual((R == L).all(), True) + W = np.array([[0, float("Inf"), float("Inf"), float("Inf"), -1, float("Inf")], + [1, 0, float("Inf"), 2, float("Inf"), float("Inf")], + [float("Inf"), 2, 0, float("Inf"), float("Inf"), -8], + [-4, float("Inf"), float("Inf"), 0, 3, float("Inf")], + [float("Inf"), 7, float("Inf"), float("Inf"), 0, float("Inf")], + [float("Inf"), 5, 10, float("Inf"), float("Inf"), 0]]) + R = slow_all_pairs_shortest_paths(W) + L = np.array([[0, 6, float("Inf"), 8, -1, float("Inf")], [-2, 0, float("Inf"), 2, -3, float("Inf")], + [-5, -3, 0, -1, -6, -8], [-4, 2, float("Inf"), 0, -5, float("Inf")], + [5, 7, float("Inf"), 9, 0, float("Inf")], [3, 5, 10, 7, 2, 0]]) + self.assertEqual((R == L).all(), True) + + def test_faster_all_pairs_shortest_paths(self): + W = np.array([[0, 3, 8, float("Inf"), -4], [float("Inf"), 0, float("Inf"), 1, 7], + [float("Inf"), 4, 0, float("Inf"), float("Inf")], [2, float("Inf"), -5, 0, float("Inf")], + [float("Inf"), float("Inf"), float("Inf"), 6, 0]]) + R = faster_all_pairs_shortest_paths(W) + 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]]) + self.assertEqual((R == L).all(), True) + W = np.array([[0, float("Inf"), float("Inf"), float("Inf"), -1, float("Inf")], + [1, 0, float("Inf"), 2, float("Inf"), float("Inf")], + [float("Inf"), 2, 0, float("Inf"), float("Inf"), -8], + [-4, float("Inf"), float("Inf"), 0, 3, float("Inf")], + [float("Inf"), 7, float("Inf"), float("Inf"), 0, float("Inf")], + [float("Inf"), 5, 10, float("Inf"), float("Inf"), 0]]) + R = faster_all_pairs_shortest_paths(W) + L = np.array([[0, 6, float("Inf"), 8, -1, float("Inf")], [-2, 0, float("Inf"), 2, -3, float("Inf")], + [-5, -3, 0, -1, -6, -8], [-4, 2, float("Inf"), 0, -5, float("Inf")], + [5, 7, float("Inf"), 9, 0, float("Inf")], [3, 5, 10, 7, 2, 0]]) + self.assertEqual((R == L).all(), True) diff --git a/bh_tree_test.py b/tests/bh_tree_test.py similarity index 94% rename from bh_tree_test.py rename to tests/bh_tree_test.py index 4979b1f..24bf74d 100755 --- a/bh_tree_test.py +++ b/tests/bh_tree_test.py @@ -1,27 +1,31 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from bh_tree import bh_tree, bh_node -class TestRbtree(unittest.TestCase): +class TestRbTree(unittest.TestCase): def test_insert_one(self): T = bh_tree([41]) self.wrap(T, 41, 1) + def test_insert_two(self): T = bh_tree([41, 38]) self.wrap(T, 41, 1) self.wrap(T, 38, 1) + def test_insert_three(self): T = bh_tree([41, 38, 31]) self.wrap(T, 38, 1) self.wrap(T, 31, 1) self.wrap(T, 41, 1) + def test_insert_four(self): T = bh_tree([41, 38, 31, 12]) self.wrap(T, 38, 2) self.wrap(T, 31, 1) self.wrap(T, 41, 1) self.wrap(T, 12, 1) + def test_insert_five(self): T = bh_tree([41, 38, 31, 12, 19]) self.wrap(T, 38, 2) @@ -29,6 +33,7 @@ def test_insert_five(self): self.wrap(T, 41, 1) self.wrap(T, 12, 1) self.wrap(T, 31, 1) + def test_insert_six(self): T = bh_tree([41, 38, 31, 12, 19, 9]) self.wrap(T, 38, 2) @@ -37,6 +42,7 @@ def test_insert_six(self): self.wrap(T, 12, 1) self.wrap(T, 31, 1) self.wrap(T, 9, 1) + def test_delete_one(self): T = bh_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -45,6 +51,7 @@ def test_delete_one(self): self.wrap(T, 41, 1) self.wrap(T, 12, 1) self.wrap(T, 31, 1) + def test_delete_two(self): T = bh_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -53,6 +60,7 @@ def test_delete_two(self): self.wrap(T, 19, 1) self.wrap(T, 41, 1) self.wrap(T, 31, 1) + def test_delete_three(self): T = bh_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -61,6 +69,7 @@ def test_delete_three(self): self.wrap(T, 38, 2) self.wrap(T, 31, 1) self.wrap(T, 41, 1) + def test_delete_four(self): T = bh_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -69,6 +78,7 @@ def test_delete_four(self): T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, 1) self.wrap(T, 41, 1) + def test_delete_five(self): T = bh_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -77,6 +87,7 @@ def test_delete_five(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) self.wrap(T, 41, 1) + def test_delete_six(self): T = bh_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -85,8 +96,11 @@ def test_delete_six(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.root, T.nil) + self.assertEqual(T.root, T.nil) + def wrap(self, tree, node, bh): - self.assertEquals(tree.iterative_tree_search(node).bh, bh) + self.assertEqual(tree.iterative_tree_search(node).bh, bh) + + if __name__ == '__main__': unittest.main() diff --git a/tests/binary_search_test.py b/tests/binary_search_test.py new file mode 100644 index 0000000..999d173 --- /dev/null +++ b/tests/binary_search_test.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +import unittest +import random +from binary_search import binary_search, bisect_left, bisect_right + + +class TestBinarySearch(unittest.TestCase): + def test_binary_search(self): + for _ in range(100): + array = sorted([random.randint(1, 10000) for _ in range(100)]) + target = random.randint(1, 10000) + index = binary_search(target, array) + if index == -1: + self.assertNotIn(target, array) + else: + self.assertEqual(target, array[index]) + + def test_bisect_left(self): + for length in range(10): + array = sorted([random.randint(1, 10) for _ in range(length)]) + target = random.randint(0, 15) + index = bisect_left(array, target) + self.assertTrue(all(val < target for val in array[:index])) + self.assertTrue(all(val >= target for val in array[index:])) + + def test_bisect_right(self): + for length in range(10): + array = sorted([random.randint(1, 10) for _ in range(length)]) + target = random.randint(0, 15) + index = bisect_right(array, target) + self.assertTrue(all(val <= target for val in array[:index])) + self.assertTrue(all(val > target for val in array[index:])) diff --git a/tests/bubble_sort_test.py b/tests/bubble_sort_test.py new file mode 100644 index 0000000..3fd80be --- /dev/null +++ b/tests/bubble_sort_test.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +import unittest +import random +from bubble_sort import bubble_sort + + +class TestBubbleSort(unittest.TestCase): + def test_bubble_sort(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + bubble_sort(array) + self.assertEqual(array, sorted(array_copy)) diff --git a/tests/constraints_test.py b/tests/constraints_test.py new file mode 100644 index 0000000..8fca7d0 --- /dev/null +++ b/tests/constraints_test.py @@ -0,0 +1,74 @@ +from constraints import difference_constraints, equality_constraints, difference_constraints_without_aux_vertex, \ + single_variable_constraints, difference_constraints_with_arbitrary_weight +import unittest +from math import floor + + +class TestConstraints(unittest.TestCase): + def test_difference_constraints(self): + A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], + [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] + b = [0, -1, 1, 5, 4, -1, -3, -3] + self.assertEqual(difference_constraints(A, b), [-5, -3, 0, -1, -4]) + A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], + [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] + b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] + self.assertEqual(difference_constraints(A, b), [-5, -3, 0, -1, -6, -8]) + A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], + [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] + b = [4, 5, -6, 1, 3, 5, 10, -4, 8] + self.assertEqual(difference_constraints(A, b), None) + A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], + [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] + b = [1, -4, 2, 7.3, 5, 10.1, 2.9, -1.11, 3, -8.6] + c = [int(floor(i)) for i in b] + print(difference_constraints(A, c)) + + def test_equality_constraints(self): + A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], + [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] + b = [0, -1, 1, 5, 4, -1, -3, -3] + self.assertEqual(equality_constraints(A, b), None) + A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], + [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] + b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] + self.assertEqual(equality_constraints(A, b), None) + A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], + [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] + b = [4, 5, -6, 1, 3, 5, 10, -4, 8] + self.assertEqual(equality_constraints(A, b), None) + A = [[-1, 1, 0], [0, -1, 1], [-1, 0, 1]] + b = [1, 1, 2] + self.assertEqual(equality_constraints(A, b), [-2, -1, 0]) + + def test_difference_constraints_without_aux_vertex(self): + A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], + [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] + b = [0, -1, 1, 5, 4, -1, -3, -3] + self.assertEqual(difference_constraints_without_aux_vertex(A, b), [-5, -3, 0, -1, -4]) + A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], + [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] + b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] + self.assertEqual(difference_constraints_without_aux_vertex(A, b), [-5, -3, 0, -1, -6, -8]) + A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], + [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] + b = [4, 5, -6, 1, 3, 5, 10, -4, 8] + self.assertEqual(difference_constraints_without_aux_vertex(A, b), None) + + def test_single_variable_constraints(self): + A = [[1, 0], [0, 1], [-1, 0], [0, -1], [1, 0]] + b = [3, 1, 5, -1, 2] + self.assertEqual(single_variable_constraints(A, b), [2, 1]) + A = [[1, 0], [0, 1], [-1, 0], [0, -1], [1, 0]] + b = [3, -1, 5, -1, 2] + self.assertEqual(single_variable_constraints(A, b), None) +# def test_difference_constraints_with_arbitrary_weight(self): +# A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, 0, -1], [-1, 0, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] +# b = [0, -1, 1, 5, 4, -1, -3, -3] +# self.assertEqual(difference_constraints_with_arbitrary_weight(A, b), [-5, -3, 0, -1, -4]) +# A = [[1, -1, 0, 0, 0, 0], [1, 0, 0, -1, 0, 0], [0, 1, -1, 0, 0, 0], [0, 1, 0, 0, -1, 0], [0, 1, 0, 0, 0, -1], [0, 0, 1, 0, 0, -1], [0, -1, 0, 1, 0, 0], [-1, 0, 0, 0, 1, 0], [0, 0, 0, -1, 1, 0], [0, 0, -1, 0, 0, 1]] +# b = [1, -4, 2, 7, 5, 10, 2, -1, 3, -8] +# self.assertEqual(difference_constraints_with_arbitrary_weight(A, b), [-5, -3, 0, -1, -6, -8]) +# A = [[1, -1, 0, 0, 0], [1, 0, 0, 0, -1], [0, 1, 0, -1, 0], [0, -1, 1, 0, 0], [-1, 0, 0, 1, 0], [0, 0, -1, 1, 0], [0, 0, 0, 1, -1], [0, 0, -1, 0, 1], [0, 0, 0, -1, 1]] +# b = [4, 5, -6, 1, 3, 5, 10, -4, 8] +# self.assertEqual(difference_constraints_with_arbitrary_weight(A, b), None) diff --git a/tests/contains_test.py b/tests/contains_test.py new file mode 100644 index 0000000..dee5f30 --- /dev/null +++ b/tests/contains_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python + +import unittest +from contains import contains + + +class TestContains(unittest.TestCase): + def test_contains(self): + x = [1, 1.5, 3.5, 2.3, 10.01] + self.assertEqual(contains(x, 5), { + (1, 2), (2.3, 3.3), (3.5, 4.5), (10.01, 11.01)}) + x = [3.5, 5.2, -1.1, -4, -12, -11.33] + self.assertEqual(contains(x, 6), { + (-12, -11), (-4, -3), (-1.1, -0.10000000000000009), (3.5, 4.5), (5.2, 6.2)}) diff --git a/counting_sort_test.py b/tests/counting_sort_test.py similarity index 52% rename from counting_sort_test.py rename to tests/counting_sort_test.py index ace37b9..adfd457 100644 --- a/counting_sort_test.py +++ b/tests/counting_sort_test.py @@ -1,12 +1,13 @@ import unittest from counting_sort import counting_sort + class TestHeap(unittest.TestCase): def test_counting_sort(self): - A = [2,5,3,0,2,3,0,3] + A = [2, 5, 3, 0, 2, 3, 0, 3] B = [] - for i in range(0, len(A)): + for i in range(len(A)): B.append(0) counting_sort(A, B, 5) - self.assertEquals(B, [0,0,2,2,3,3,3,5]) - self.assertEquals(A, [2,5,3,0,2,3,0,3]) + self.assertEqual(B, [0, 0, 2, 2, 3, 3, 3, 5]) + self.assertEqual(A, [2, 5, 3, 0, 2, 3, 0, 3]) diff --git a/tests/cut_rod_test.py b/tests/cut_rod_test.py new file mode 100755 index 0000000..596b93e --- /dev/null +++ b/tests/cut_rod_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +import unittest + +from cut_rod import bottom_up_cut_rod, bottom_up_cut_rod_two_subproblem, memoized_cut_rod, print_cut_rod_solution, \ + bottom_up_cut_rod_with_fixed_cut_cost, extended_memoized_cut_rod + + +class TestCutRod(unittest.TestCase): + def test_bottom_up_cut_rod(self): + p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] + values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, + 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] + for i in range(len(values), 2): + self.assertEqual(bottom_up_cut_rod(p, values[i]), values[i + 1]) + + def test_bottom_up_cut_rod_two_subproblem(self): + p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] + values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, + 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] + for i in range(len(values), 2): + self.assertEqual(bottom_up_cut_rod_two_subproblem( + p, values[i]), values[i + 1]) + + def test_memoized_cut_rod(self): + p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] + values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, + 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] + for i in range(len(values), 2): + self.assertEqual(memoized_cut_rod(p, values[i]), values[i + 1]) + + def test_bottom_up_cut_rod_with_fixed_cut_cost(self): + p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] + values = [1, 1, 2, 5, 3, 8, 4, 9, 5, 11, + 6, 17, 7, 17, 8, 20, 9, 24, 10, 30] + for i in range(len(values), 2): + self.assertEqual(bottom_up_cut_rod_with_fixed_cut_cost( + p, values[i], 2), values[i + 1]) + values = [1, 1, 2, 5, 3, 8, 4, 9, 5, 11.5, + 6, 17, 7, 17, 8, 20.5, 9, 24, 10, 30] + for i in range(len(values), 2): + self.assertEqual(bottom_up_cut_rod_with_fixed_cut_cost( + p, values[i], 1.5), values[i + 1]) + + def test_print_rod_solution(self): + p = [1, 5, 8, 9, 10, 17, 17, 20, 24, 30] + values = [1, 1, 2, 5, 3, 8, 4, 10, 5, 13, + 6, 17, 7, 18, 8, 22, 9, 25, 10, 30] + print_cut_rod_solution(p, 9, extended_memoized_cut_rod) diff --git a/depth_tree_test.py b/tests/depth_tree_test.py similarity index 95% rename from depth_tree_test.py rename to tests/depth_tree_test.py index c9d6ac2..1e5f13b 100755 --- a/depth_tree_test.py +++ b/tests/depth_tree_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from depth_tree import depth_tree, depth_node @@ -7,21 +7,25 @@ class TestRbtree(unittest.TestCase): def test_insert_one(self): T = depth_tree([41]) self.wrap(T, 41, 0) + def test_insert_two(self): T = depth_tree([41, 38]) self.wrap(T, 41, 0) self.wrap(T, 38, 1) + def test_insert_three(self): T = depth_tree([41, 38, 31]) self.wrap(T, 38, 0) self.wrap(T, 31, 1) self.wrap(T, 41, 1) + def test_insert_four(self): T = depth_tree([41, 38, 31, 12]) self.wrap(T, 38, 0) self.wrap(T, 31, 1) self.wrap(T, 41, 1) self.wrap(T, 12, 2) + def test_insert_five(self): T = depth_tree([41, 38, 31, 12, 19]) self.wrap(T, 38, 0) @@ -29,6 +33,7 @@ def test_insert_five(self): self.wrap(T, 41, 1) self.wrap(T, 12, 2) self.wrap(T, 31, 2) + def test_insert_six(self): T = depth_tree([41, 38, 31, 12, 19, 9]) self.wrap(T, 38, 0) @@ -37,6 +42,7 @@ def test_insert_six(self): self.wrap(T, 12, 2) self.wrap(T, 31, 2) self.wrap(T, 9, 3) + def test_delete_one(self): T = depth_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -45,6 +51,7 @@ def test_delete_one(self): self.wrap(T, 41, 1) self.wrap(T, 12, 2) self.wrap(T, 31, 2) + def test_delete_two(self): T = depth_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -53,6 +60,7 @@ def test_delete_two(self): self.wrap(T, 19, 1) self.wrap(T, 41, 1) self.wrap(T, 31, 2) + def test_delete_three(self): T = depth_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -61,6 +69,7 @@ def test_delete_three(self): self.wrap(T, 38, 0) self.wrap(T, 31, 1) self.wrap(T, 41, 1) + def test_delete_four(self): T = depth_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -69,6 +78,7 @@ def test_delete_four(self): T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, 0) self.wrap(T, 41, 1) + def test_delete_five(self): T = depth_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -77,6 +87,7 @@ def test_delete_five(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) self.wrap(T, 41, 0) + def test_delete_six(self): T = depth_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -85,8 +96,11 @@ def test_delete_six(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.nil.depth, -1) + self.assertEqual(T.nil.depth, -1) + def wrap(self, tree, node, depth): - self.assertEquals(tree.iterative_tree_search(node).depth, depth) + self.assertEqual(tree.iterative_tree_search(node).depth, depth) + + if __name__ == '__main__': unittest.main() diff --git a/disjoint_sets_forest_test.py b/tests/disjoint_sets_forest_test.py similarity index 61% rename from disjoint_sets_forest_test.py rename to tests/disjoint_sets_forest_test.py index 7e1ce6b..5d431ce 100644 --- a/disjoint_sets_forest_test.py +++ b/tests/disjoint_sets_forest_test.py @@ -1,41 +1,45 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest import disjoint_sets_forest as ds + + class TestDisjointSets(unittest.TestCase): def test_forest(self): pool = [0] * 17 for i in range(1, 17): pool[i] = ds.node(i) for i in range(1, 17): - self.assertEquals(pool[i].p, pool[i]) + self.assertEqual(pool[i].p, pool[i]) for i in range(1, 16, 2): pool[i].union(pool[i + 1]) parent_list = [2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14, 14, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) for i in range(1, 14, 4): pool[i].union(pool[i + 2]) parent_list = [2, 4, 4, 4, 6, 8, 8, 8, 10, 12, 12, 12, 14, 16, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) pool[1].union(pool[5]) parent_list = [4, 4, 4, 8, 8, 8, 8, 8, 10, 12, 12, 12, 14, 16, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) pool[11].union(pool[13]) parent_list = [4, 4, 4, 8, 8, 8, 8, 8, 10, 12, 12, 16, 16, 16, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) pool[1].union(pool[10]) parent_list = [8, 4, 4, 8, 8, 8, 8, 16, 10, 16, 12, 16, 16, 16, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) self.assertTrue(pool[2].find_set() == pool[16]) - parent_list = [8, 16, 4, 16, 8, 8, 8, 16, 10, 16, 12, 16, 16, 16, 16, 16] + parent_list = [8, 16, 4, 16, 8, 8, 8, + 16, 10, 16, 12, 16, 16, 16, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) self.assertTrue(pool[9].find_set() == pool[16]) - parent_list = [8, 16, 4, 16, 8, 8, 8, 16, 16, 16, 12, 16, 16, 16, 16, 16] + parent_list = [8, 16, 4, 16, 8, 8, 8, + 16, 16, 16, 12, 16, 16, 16, 16, 16] for i in range(1, 17): - self.assertEquals(pool[i].p, pool[parent_list[i - 1]]) + self.assertEqual(pool[i].p, pool[parent_list[i - 1]]) diff --git a/disjoint_sets_test.py b/tests/disjoint_sets_test.py similarity index 90% rename from disjoint_sets_test.py rename to tests/disjoint_sets_test.py index e78f8f4..9fa89ca 100644 --- a/disjoint_sets_test.py +++ b/tests/disjoint_sets_test.py @@ -1,15 +1,17 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest import disjoint_sets_linked_list as ds + + class TestDisjointSets(unittest.TestCase): def test_linked_lists_with_head_and_tail(self): pool = [0] * 17 for i in range(1, 17): pool[i] = ds.node(i) a = ds.header(pool[i]) - self.assertEquals(a.head, pool[i]) - self.assertEquals(a.tail, pool[i]) + self.assertEqual(a.head, pool[i]) + self.assertEqual(a.tail, pool[i]) for i in range(1, 16, 2): pool[i].union(pool[i + 1]) for i in range(1, 14, 4): @@ -19,6 +21,7 @@ def test_linked_lists_with_head_and_tail(self): pool[1].union(pool[10]) self.assertTrue(pool[2].find_set() == pool[1]) self.assertTrue(pool[9].find_set() == pool[1]) + def test_linked_lists_no_tail(self): pool = [0] * 17 for i in range(1, 17): diff --git a/tests/graph_test.py b/tests/graph_test.py new file mode 100644 index 0000000..caedff1 --- /dev/null +++ b/tests/graph_test.py @@ -0,0 +1,741 @@ +#!/usr/bin/env python +import unittest +from typing import List +from graph import Vertex, Graph + + +class TestGraph(unittest.TestCase): + def setUp(self): + self.graphs: List[Graph] = [] + v1 = Vertex(1) + v2 = Vertex(2) + v3 = Vertex(3) + v4 = Vertex(4) + v5 = Vertex(5) + v6 = Vertex(6) + self.v1 = v1 + self.v2 = v2 + self.v3 = v3 + self.v4 = v4 + self.v5 = v5 + self.v6 = v6 + vertices = [v1, v2, v3, v4, v5, v6] + edges = [(v1, v2), (v1, v3), (v2, v3), (v2, v4), (v2, v5), (v3, v4), + (v3, v6), (v4, v5), (v5, v6)] + self.graphs.append(Graph(vertices, edges)) + edges = [(v1, v2), (v2, v3), (v3, v4), (v4, v2), (v3, v5), (v2, v4), + (v4, v3), (v1, v6)] + self.graphs.append(Graph([v1, v2, v3, v4, v5, v6], edges)) + + def tearDown(self): + pass + + @staticmethod + def _build_graph(cls, keys, pairs, directed): + d = dict() + vertices = [None] * len(keys) + edges = [None] * len(pairs) + for i in range(len(vertices)): + vertices[i] = Vertex(keys[i]) + d[keys[i]] = vertices[i] + + for i in range(len(edges)): + w1, w2 = pairs[i] + edges[i] = (d[w1], d[w2]) + return Graph(vertices, edges, directed) + + def testBfs(self): + s = Vertex('s') + r = Vertex('r') + v = Vertex('v') + w = Vertex('w') + t = Vertex('t') + x = Vertex('x') + u = Vertex('u') + y = Vertex('y') + z = Vertex('z') + vertices = [v, r, s, w, t, x, u, y, z] + edges = [(s, r), (s, w), (r, v), (r, s), (v, r), (w, s), (w, t), + (w, x), (t, w), (t, x), (t, u), (u, t), (u, x), + (u, y), (x, w), (x, t), (x, u), (x, y), (y, x), (y, u)] + g = Graph(vertices, edges) + # g.print(AllEdges()) + # for i in g.vertices: + # i.print(Edge()) + # print() + g.bfs(s) + # g.print(Vertices()) + self.assertEqual(s.distance, 0) + self.assertEqual(r.distance, 1) + self.assertEqual(v.distance, 2) + self.assertEqual(w.distance, 1) + self.assertEqual(t.distance, 2) + self.assertEqual(x.distance, 2) + self.assertEqual(u.distance, 3) + self.assertEqual(y.distance, 3) + + # def testDfs(self): + # s = Vertex('s') + # v = Vertex('v') + # z = Vertex('z') + # w = Vertex('w') + # y = Vertex('y') + # x = Vertex('x') + # t = Vertex('t') + # u = Vertex('u') + # # edges_list = [(z, w), (s, w), (y, w), + # # (x, ), (x, ), (z, ), (v, u), (v, t)] + # # vertices = (s, v, z, w, y, x, t, u) + # # map( + # # lambda vertex, edges: + # # map(lambda vertex, edge: + # # vertex.addEdge(edge), + # # zip([vertex] * len(edges) , edges)), + # # zip(vertices, edges_list)) + # vertices = [s, v, z, w, y, x, t, u] + # edges = [(y, x), (x, z), (z, y), (z, w), (w, x), (s, z), + # (s, w), (v, w), (v, s), (t, v), (t, u), (u, v), (u, t)] + # g = Graph(vertices, edges) + # g.dfs() + # # vertices = (s, v, z, w, y, x, t, u) + + def testIsCyclic(self): + s = Vertex('s') + v = Vertex('v') + z = Vertex('z') + vertices = [s, v, z] + self.assertFalse(Graph(vertices, [(s, v), (v, z)]).is_cyclic()) + self.assertTrue(Graph(vertices, [(s, v), (v, z), (z, s)]).is_cyclic()) + + def testPathNum(self): + m = Vertex('m') + n = Vertex('n') + o = Vertex('o') + p = Vertex('p') + q = Vertex('q') + r = Vertex('r') + s = Vertex('s') + t = Vertex('t') + u = Vertex('u') + v = Vertex('v') + w = Vertex('w') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [m, n, o, p, q, r, s, t, u, v, w, x, y, z] + edges = [(m, q), (m, r), (m, x), (n, q), (n, o), (n, u), + (o, r), (o, s), (o, v), (p, o), (p, s), (p, z), (q, t), + (r, u), (r, y), (s, r), (u, t), (v, w), + (v, x), (w, z), (y, v)] + g = Graph(vertices, edges) + self.assertEqual(g.path_num(m, v), 1) + self.assertEqual(g.path_num(n, v), 3) + self.assertEqual(g.path_num(o, v), 3) + self.assertEqual(g.path_num(p, v), 4) + self.assertEqual(g.path_num(q, v), 0) + self.assertEqual(g.path_num(r, v), 1) + self.assertEqual(g.path_num(s, v), 1) + self.assertEqual(g.path_num(t, v), 0) + self.assertEqual(g.path_num(u, v), 0) + self.assertEqual(g.path_num(v, v), 1) + self.assertEqual(g.path_num(w, v), 0) + self.assertEqual(g.path_num(x, v), 0) + self.assertEqual(g.path_num(y, v), 1) + self.assertEqual(g.path_num(z, v), 0) + + g = self.graphs[0] + self.assertEqual(g.path_num(self.v1, self.v2), 1) + self.assertEqual(g.path_num(self.v1, self.v3), 2) + self.assertEqual(g.path_num(self.v1, self.v4), 3) + self.assertEqual(g.path_num(self.v1, self.v5), 4) + self.assertEqual(g.path_num(self.v1, self.v6), 6) + self.assertEqual(g.path_num(self.v2, self.v1), 0) + self.assertEqual(g.path_num(self.v2, self.v3), 1) + self.assertEqual(g.path_num(self.v2, self.v4), 2) + self.assertEqual(g.path_num(self.v2, self.v5), 3) + self.assertEqual(g.path_num(self.v2, self.v6), 4) + g = self.graphs[1] + self.assertEqual(g.path_num(self.v1, self.v5), 1) + + def testSCC(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + vertices = [a, b, c, d, e, f, g, h] + edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (b, e), + (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] + G = Graph(vertices, edges) + G.strongly_connected_components() + self.assertEqual(a.cc, 1) + self.assertEqual(b.cc, 1) + self.assertEqual(c.cc, 2) + self.assertEqual(d.cc, 2) + self.assertEqual(e.cc, 1) + self.assertEqual(f.cc, 3) + self.assertEqual(g.cc, 3) + self.assertEqual(h.cc, 4) + + def testSimplified(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + vertices = [a, b, c, d, e, f, g, h] + # edges = [(a, c), (b, a), (d, h), (d, f), (e, a), (a, b), (b, c), + # (d, c), (c, d), (b, e), (e, f), (b, f), (g, f), (f, g), (c, g), + # (g, h), (h, h)] + edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (b, e), + (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] + G = Graph(vertices, edges) + s = G.simplified() + # for u in s.vertices: + # print( "u.key: {}, u.cc: {}".format(u.key, u.cc) ) + # s.print(Edge(u)) + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + vertices = [a, b, c, d, e, f] + edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), + (c, e), (b, e), (d, f), (e, f), (f, e)] + G = Graph(vertices, edges) + s = G.simplified() + # for u in s.vertices: + # print( "u.key: {}, u.cc: {}".format(u.key, u.cc) ) + # s.print(Edge(u)) + + def testComponentGraph(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + vertices = [a, b, c, d, e, f, g, h] + edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (d, h), (b, e), + (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), (h, h)] + G = Graph(vertices, edges) + cg = G.component_graph() + # print() + # for u in cg.vertices: + # print( "u.key: {}".format(u.key) ) + # cg.print(Edge(u)) + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + vertices = [a, b, c, d, e, f] + edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), + (c, e), (b, e), (d, f), (e, f), (f, e)] + G = Graph(vertices, edges) + cg = G.component_graph() + + # print( "www") + # print() + # for u in cg.vertices: + # print( "u.key: {}".format(u.key) ) + # cg.print(Edge(u)) + def testSemiconnected(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + vertices = [a, b, c, d, e, f, g, h] + edges = [(e, a), (a, b), (b, c), (d, c), (c, d), (d, h), (b, e), + (e, f), (b, f), (g, f), (f, g), (c, g), (g, h), + (h, h)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), True) + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + vertices = [a, b, c, d, e, f] + edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), + (c, e), (b, e), (d, f), (e, f), (f, e)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), True) + edges = [(a, b), (b, a), (b, c), (b, d), (c, b), (d, b), (e, f)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), False) + abe = Vertex('abe') + cd = Vertex('cd') + fg = Vertex('fg') + h = Vertex('h') + vertices = [abe, cd, fg, h] + edges = [(abe, fg), (abe, cd), (fg, h), (cd, h), (cd, fg)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), True) + edges = [(abe, fg), (abe, cd), (fg, h), (cd, h)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), False) + edges = [(abe, fg), (abe, cd), (cd, h), (cd, fg)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), False) + edges = [(abe, fg), (abe, cd), (fg, h), (cd, fg)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), True) + edges = [(abe, cd), (fg, h), (cd, fg)] + G = Graph(vertices, edges) + self.assertEqual(G.semiconnected(), True) + + def testCut(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + i = Vertex('i') + vertices = [a, b, c, d, e, f, g, h, i] + edges = [(a, b), (b, c), (b, h), (c, i), (d, c), (e, d), (f, d), + (f, e), (f, c), (g, f), (g, h), (g, i), (h, a), (h, i)] + G = Graph(vertices, edges, directed=False) + # weight = [4, 8, 11, 2, 7, 9, 14, 10, 4, 2, 2, 1, 8, 7] + weight = [4, 8, 11, 2, 7, 9, 14, 10, 4, 2, 1, 6, 8, 7] + z = dict() + for x, y in zip(edges, weight): + z[x] = y + z[(x[1], x[0])] = y + + def w(x, y): + return z[(x, y)] + + G.cut(a, h, w) + r1 = set() + r2 = set() + for u in G.vertices: + if u.root == a: + r1.add(u) + else: + r2.add(u) + self.assertEqual(r1, set([a, b])) + self.assertEqual(r2, set([h, i, g, c, f, d, e])) + + # for u in G.vertices: + # print( "u.key: {}, u.root = {}".format(u.key, u.root)) + def testKruskal(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + i = Vertex('i') + vertices = [a, b, c, d, e, f, g, h, i] + edges = [(a, b), (a, h), (b, a), (b, c), (b, h), (c, b), (c, i), + (c, f), (c, d), (d, c), (d, e), (d, f), (e, d), + (e, f), (f, d), (f, e), (f, c), (f, g), (g, f), (g, h), + (g, i), (h, a), (h, b), (h, i), (h, g), (i, c), + (i, h), (i, g)] + G = Graph(vertices, edges) + weight = [4, 8, 4, 8, 11, 8, 2, 4, 7, 7, 9, 14, 9, + 10, 14, 10, 4, 2, 2, 1, 6, 8, 11, 7, 1, 2, 7, 6] + z = dict() + for x, y in zip(edges, weight): + z[x] = y + print("{}: {}".format(x, y)) + + def w(x, y): + return z[(x, y)] + + ls = G.Kruskal(w) + print(ls) + + def testPrim(self): + a = Vertex('a') + b = Vertex('b') + c = Vertex('c') + d = Vertex('d') + e = Vertex('e') + f = Vertex('f') + g = Vertex('g') + h = Vertex('h') + i = Vertex('i') + vertices = [a, b, c, d, e, f, g, h, i] + # edges = [(a, b), (a, h), (b, a), (b, c), (b, h), (c, b), (c, i), + # (c, f), (c, d), (d, c), (d, e), (d, f), (e, d), (e, f), (f, d), + # (f, e), (f, c), (f, g), (g, f), (g, h), (g, i), (h, a), (h, b), + # (h, i), (h, g), (i, c), (i, h), (i, g)] + # weight = [4, 8, 4, 8, 11, 8, 2, 4, 7, 7, 9, 14, 9, 10, 14, 10, 4, 2, + # 2, 1, 6, 8, 11, 7, 1, 2, 7, 6] + edges = [(a, b), (b, c), (b, h), (c, i), (d, c), (e, d), (f, d), + (f, e), (f, c), (g, f), (g, h), (g, i), (h, a), (h, i)] + weight = [4, 8, 11, 2, 7, 9, 14, 10, 4, 2, 1, 6, 8, 7] + G = Graph(vertices, edges, False) + z = dict() + for x, y in zip(edges, weight): + z[x] = y + z[(x[1], x[0])] = y + # print( "Prim edges: {}, weight: {}".format(x, y)) + + def w(x, y): + return z[(x, y)] + + G.Prim(w, i) + s = set() + for u in G.vertices: + s.add((u.p, u)) + # self.assertEqual(s, set([(g, h), (f, g), (None, i), (c, d), + # (c, f), (i, c), (h, a), (d, e), (a, b)])) + + def testBellmanFord(self): + s = Vertex('s') + t = Vertex('t') + y = Vertex('y') + x = Vertex('x') + z = Vertex('z') + vertices = [s, t, y, x, z] + edges = [(s, t), (s, y), (t, y), (t, x), (t, z), + (y, x), (y, z), (x, t), (z, s), (z, x)] + weight = [6, 7, 8, 5, -4, -3, 9, -2, 2, 7] + G = Graph(vertices, edges) + we = dict() + for x, y in zip(edges, weight): + we[x] = y + + def w(x, y): + return we[(x, y)] + + G.Bellman_Ford(w, z) + + def testBellmanFordModified(self): + s = Vertex('s') + t = Vertex('t') + u = Vertex('u') + v = Vertex('v') + x = Vertex('x') + y = Vertex('y') + vertices = [s, t, u, v, x, y] + edges = [(s, t), (s, v), (s, x), (s, y), (t, u), (v, u)] + weight = [1, 0, 3, 4, 2, 6] + G = Graph(vertices, edges) + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + # G.Bellman_Ford(w, s) + G.Bellman_Ford_modified(w, s) + self.assertEqual([i.p for i in vertices], [None, s, t, s, s, s]) + self.assertEqual([i.d for i in vertices], [0, 1, 3, 0, 3, 4]) + r = Vertex('r') + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [r, s, t, x, y, z] + edges = [(r, s), (r, t), (s, t), (s, x), (t, x), + (t, y), (t, z), (x, y), (x, z), (y, z)] + weight = [5, 3, 2, 6, 7, 4, 2, -1, 1, -2] + G = Graph(vertices, edges) + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + G.Bellman_Ford_modified(w, s) + self.assertEqual([i.p for i in vertices], [None, None, s, s, x, y]) + self.assertEqual([i.d for i in vertices], [ + float("Inf"), 0, 2, 6, 5, 3]) + + def testTopologicalSort(self): + r = Vertex('r') + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [r, s, t, x, y, z] + edges = [(r, s), (r, t), (s, t), (s, x), (t, x), + (t, y), (t, z), (x, y), (x, z), (y, z)] + graph = Graph(vertices, edges) + # Prove that Graph.topological_sort actually does a topological sort. + # A topological sort of a dag(directed acyclic graph) G = (V, E) is a linear ordering of all the vertices + # such that if G contains an edge (u, v), then u appears before v in the ordering. + mapping = {vertex: index for index, vertex in enumerate(graph.topological_sort())} + self.assertTrue(all(mapping[u] < mapping[v] for u, v in graph.edges)) + + def testDagShortestPaths(self): + r = Vertex('r') + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [r, s, t, x, y, z] + edges = [(r, s), (r, t), (s, t), (s, x), (t, x), + (t, y), (t, z), (x, y), (x, z), (y, z)] + weight = [5, 3, 2, 6, 7, 4, 2, -1, 1, -2] + G = Graph(vertices, edges) + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + G.dag_shortest_paths(w, s) + self.assertEqual([i.p for i in vertices], [None, None, s, s, x, y]) + self.assertEqual([i.d for i in vertices], [ + float("Inf"), 0, 2, 6, 5, 3]) + G.dag_shortest_paths(w, r) + self.assertEqual([i.p for i in vertices], [None, r, r, t, t, t]) + self.assertEqual([i.d for i in vertices], [0, 5, 3, 10, 7, 5]) + + def testDagShortestPathsModified(self): + u = Vertex('u') + v = Vertex('v') + w = Vertex('w') + z = Vertex('z') + u.weight = 1 + v.weight = 2 + w.weight = 3 + z.weight = 4 + vertices = [u, v, w, z] + edges = [(u, v), (v, w), (v, z)] + G = Graph(vertices, edges) + self.assertEqual(G.dag_shortest_paths_modified(u), [u, v, z]) + + def testTotalPathNumber(self): + r = Vertex('r') + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [r, s, t, x, y, z] + edges = [(r, s), (r, t), (s, t), (s, x), (t, x), + (t, y), (t, z), (x, y), (x, z), (y, z)] + weight = [5, 3, 2, 6, 7, 4, 2, -1, 1, -2] + G = Graph(vertices, edges) + number = G.total_path_number() + self.assertEqual([i.num for i in vertices], [21, 12, 7, 3, 1, 0]) + self.assertEqual(number, 44) + + def testDijkstra(self): + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [s, t, x, y, z] + edges = [(s, t), (s, y), (t, x), (t, y), (x, z), + (y, t), (y, x), (y, z), (z, s), (z, x)] + g = Graph(vertices, edges) + weight = [10, 5, 1, 2, 4, 3, 9, 2, 7, 6] + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + g.Dijkstra(w, s) + self.assertEqual([i.p for i in vertices], [None, y, t, s, y]) + self.assertEqual([i.d for i in vertices], [0, 8, 9, 5, 7]) + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [s, t, x, y, z] + edges = [(s, t), (s, y), (t, x), (t, y), (x, z), + (y, t), (y, x), (y, z), (z, s), (z, x)] + g = Graph(vertices, edges) + weight = [3, 5, 6, 2, 2, 1, 4, 6, 3, 7] + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + g.Dijkstra(w, s) + self.assertEqual([i.p for i in vertices], [None, s, t, s, y]) + self.assertEqual([i.d for i in vertices], [0, 3, 9, 5, 11]) + g.Dijkstra(w, z) + self.assertEqual([i.p for i in vertices], [z, s, z, s, None]) + self.assertEqual([i.d for i in vertices], [3, 6, 7, 8, 0]) + + def testDijkstraModified(self): + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [s, t, x, y, z] + edges = [(s, t), (s, y), (t, x), (t, y), (x, z), + (y, t), (y, x), (y, z), (z, s), (z, x)] + g = Graph(vertices, edges) + weight = [10, 5, 1, 2, 4, 3, 9, 2, 7, 6] + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + g.Dijkstra_modified(w, s, 10) + self.assertEqual([i.p for i in vertices], [None, y, t, s, y]) + self.assertEqual([i.d for i in vertices], [0, 8, 9, 5, 7]) + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') + vertices = [s, t, x, y, z] + edges = [(s, t), (s, y), (t, x), (t, y), (x, z), + (y, t), (y, x), (y, z), (z, s), (z, x)] + g = Graph(vertices, edges) + weight = [3, 5, 6, 2, 2, 1, 4, 6, 3, 7] + we = dict() + for i, j in zip(edges, weight): + we[i] = j + + def w(x, y): + return we[(x, y)] + + g.Dijkstra_modified(w, s, 7) + self.assertEqual([i.p for i in vertices], [None, s, t, s, y]) + self.assertEqual([i.d for i in vertices], [0, 3, 9, 5, 11]) + g.Dijkstra_modified(w, z, 7) + self.assertEqual([i.p for i in vertices], [z, s, z, s, None]) + self.assertEqual([i.d for i in vertices], [3, 6, 7, 8, 0]) + + def testSingleEdge(self): + a = Vertex(1) + b = Vertex(2) + c = Vertex(3) + d = Vertex(4) + vertices = [a, b, c, d] + edges = [(a, b), (b, a), (a, c), (d, d)] + graph1 = Graph(vertices, edges) + graph2 = graph1.single_edge() + edges = {(a, b), (b, a), (a, c), (c, a)} + vertices = set(vertices) + self.assertEqual(graph2.vertices, vertices) + self.assertEqual(graph2.edges, edges) + self.assertEqual(graph2.adj[a], {b, c}) + self.assertEqual(graph2.adj[b], {a}) + self.assertEqual(graph2.adj[c], {a}) + self.assertEqual(graph2.adj[d], set()) + + def testUnion(self): + a = Vertex(1) + b = Vertex(2) + c = Vertex(3) + d = Vertex(4) + G1 = Graph([a, b, c], [(a, b), (a, c)]) + G2 = Graph([c, d], [(c, d)]) + G3 = G1.union(G2) + self.assertEqual(G3.vertices, {a, b, c, d}) + self.assertEqual(G3.edges, {(a, b), (a, c), (c, d)}) + self.assertEqual(G3.adj[a], {b, c}) + self.assertEqual(G3.adj[b], set()) + self.assertEqual(G3.adj[c], {d}) + self.assertEqual(G3.adj[d], set()) + G1 = Graph([a, b, c], [(a, b), (a, c)], directed=False) + G2 = Graph([c, d], [(c, d)], directed=False) + G3 = G1.union(G2) + self.assertEqual(G3.vertices, {a, b, c, d}) + self.assertEqual( + G3.edges, {(a, b), (b, a), (a, c), (c, a), (c, d), (d, c)}) + self.assertEqual(G3.adj[a], {b, c}) + self.assertEqual(G3.adj[b], {a}) + self.assertEqual(G3.adj[c], {d, a}) + self.assertEqual(G3.adj[d], {c}) + + def testCopy(self): + a = Vertex(1) + b = Vertex(2) + c = Vertex(3) + G1 = Graph([a, b, c], [(a, b), (a, c)]) + G2 = G1.copy() + self.assertEqual(G1, G2) + + def testSquareGraph(self): + a = Vertex(1) + b = Vertex(2) + c = Vertex(3) + d = Vertex(4) + G = Graph([a, b, c, d], [(a, b), (a, c), (c, d)]) + sqrt = G.square() + self.assertEqual(sqrt.vertices, {a, b, c, d}) + self.assertEqual(sqrt.edges, {(a, b), (a, c), (a, d), (c, d)}) + self.assertEqual(sqrt.adj[a], {b, c, d}) + self.assertEqual(sqrt.adj[b], set()) + self.assertEqual(sqrt.adj[c], {d}) + self.assertEqual(sqrt.adj[d], set()) + a = Vertex(1) + b = Vertex(2) + c = Vertex(3) + G = Graph([a, b, c], [(a, b), (b, c), (a, c)]) + sqrt = G.square() + self.assertEqual(G, sqrt) + + def testMht(self): + print("start mht") + g = self.graphs[0] + g.mht() + print("height") + print(self.v1.h) + print(self.v2.h) + print(self.v3.h) + print(self.v4.h) + print(self.v5.h) + print(self.v6.h) + print("height") + print(self.v1.mh) + print(self.v2.mh) + print(self.v3.mh) + print(self.v4.mh) + print(self.v5.mh) + print(self.v6.mh) +# def testJohnson(self): +# a1 = Vertex(1) +# a2 = Vertex(2) +# a3 = Vertex(3) +# a4 = Vertex(4) +# a5 = Vertex(5) +# vertices = [a1, a2, a3, a4, a5] +# edges = [(a1, a2), (a1, a3), (a1, a5), (a2, a4), (a2, a5), (a3, a2), +# (a4, a1), (a4, a3), (a5, a4)] +# g = Graph(vertices, edges) +# weight = [3, 8, -4, 1, 7, 4, 2, -5, 6] +# we = dict() +# for i,j in zip(edges, weight): +# we[i] = j +# def w(x, y): +# return we[(x, y)] +# g.Johnson(w) diff --git a/hamiltonian_path_test.py b/tests/hamiltonian_path_test.py similarity index 50% rename from hamiltonian_path_test.py rename to tests/hamiltonian_path_test.py index 3dd2c32..ab7eb9d 100644 --- a/hamiltonian_path_test.py +++ b/tests/hamiltonian_path_test.py @@ -1,32 +1,33 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from graph import Vertex, Graph from hamiltonian_path import hamiltonian_path + class TestHamiltonianPath(unittest.TestCase): def testHamPath(self): - r = Vertex('r') - s = Vertex('s') - t = Vertex('t') - x = Vertex('x') - y = Vertex('y') - z = Vertex('z') + r = Vertex('r') + s = Vertex('s') + t = Vertex('t') + x = Vertex('x') + y = Vertex('y') + z = Vertex('z') vertices = [r, s, t, x, y, z] edges = [(r, s), (s, t), (t, x), (x, y), (y, z)] G = Graph(vertices, edges) - self.assertEquals([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False, True]) + self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False, True]) edges = [(r, s), (r, t), (s, x), (s, y), (t, z)] G = Graph(vertices, edges) - self.assertEquals([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False, False]) + self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False, False]) edges = [(r, s), (s, t), (s, x), (t, x)] vertices = [r, s, t, x] G = Graph(vertices, edges) - self.assertEquals([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, True]) + self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, True]) edges = [(r, s), (s, t), (s, x), (t, x), (r, y), (y, s)] vertices = [r, s, t, x, y] G = Graph(vertices, edges) - self.assertEquals([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, True, False]) + self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, True, False]) edges = [(r, s), (s, t), (s, x), (t, x), (r, y)] vertices = [r, s, t, x, y] G = Graph(vertices, edges) - self.assertEquals([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False]) + self.assertEqual([hamiltonian_path(G, r, v) for v in vertices], [False, False, False, False, False]) diff --git a/tests/heap_test.py b/tests/heap_test.py new file mode 100644 index 0000000..9bf8d74 --- /dev/null +++ b/tests/heap_test.py @@ -0,0 +1,39 @@ +import unittest +from heap import MaxHeap, MinHeap + + +class TestHeap(unittest.TestCase): + # def test_init(self): + # a = heap([4, 1, 3, 2, 16, 9, 10, 14, 8, 7]) + # self.assertEqual(a.__heap, a) + # self.assertEqual(a.__length, 10) + # self.assertEqual(a.__heap_size, 10) + def test_max_heapify(self): + a = [16, 4, 10, 14, 7, 9, 3, 2, 8, 1] + h = MaxHeap(a) + h.max_heapify(1) + self.assertEqual(h, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) + + def test_build_max_heap(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + h = MaxHeap(a) + h.build_max_heap() + self.assertEqual(h, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) + + def test_heapsort(self): + a = [4, 1, 3, 3, 16, 9, 10, 14, 8, 7] + h = MaxHeap(a) + h.heapsort() + self.assertEqual(h, [1, 3, 3, 4, 7, 8, 9, 10, 14, 16]) + + def test_min_heapify(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + h = MinHeap(a) + h.min_heapify(1) + self.assertEqual(h, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) + + def test_build_min_heap(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + h = MinHeap(a) + h.build_min_heap() + self.assertEqual(h, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) diff --git a/tests/insertion_sort_test.py b/tests/insertion_sort_test.py new file mode 100644 index 0000000..1b84092 --- /dev/null +++ b/tests/insertion_sort_test.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +import unittest +import random +from insertion_sort import insertion_sort, insertion_sort_recursive, insert_with_linear_search, \ + insert_with_binary_search + + +class TestInsertionSort(unittest.TestCase): + def test_insertion_sort_with_linear_search(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + insertion_sort(array, insert_method=insert_with_linear_search) + self.assertEqual(array, sorted(array_copy)) + + def test_insertion_sort_with_binary_search(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + insertion_sort(array, insert_method=insert_with_binary_search) + self.assertEqual(array, sorted(array_copy)) + + def test_insertion_sort_recursive(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + insertion_sort_recursive(array) + self.assertEqual(array, sorted(array_copy)) + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + insertion_sort_recursive( + array, insert_method=insert_with_binary_search) + self.assertEqual(array, sorted(array_copy)) diff --git a/interval_tree_test.py b/tests/interval_tree_test.py similarity index 88% rename from interval_tree_test.py rename to tests/interval_tree_test.py index e5b8be0..b5dc140 100755 --- a/interval_tree_test.py +++ b/tests/interval_tree_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from interval_tree import interval, interval_tree, interval_node @@ -6,11 +6,13 @@ class TestIntervalTree(unittest.TestCase): def test_insert_one(self): intervals = [] - values = [16, 21, 8, 9, 25, 30, 5, 8, 15, 23, 17, 19, 26, 26, 0, 3, 6, 10, 19, 20] + values = [16, 21, 8, 9, 25, 30, 5, 8, 15, + 23, 17, 19, 26, 26, 0, 3, 6, 10, 19, 20] for i in range(0, len(values), 2): intervals.append(interval(values[i], values[i + 1])) T = interval_tree(intervals) - values = [16, 30, 8, 23, 25, 30, 5, 10, 15, 23, 17, 20, 26, 26, 0, 3, 6, 10, 19, 20] + values = [16, 30, 8, 23, 25, 30, 5, 10, 15, + 23, 17, 20, 26, 26, 0, 3, 6, 10, 19, 20] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -21,6 +23,7 @@ def test_insert_one(self): values = [38, 45, 19, 45, 41, 41, 12, 45, 31, 35, 9, 21] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) + def test_delete_one(self): intervals = [] values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -31,6 +34,7 @@ def test_delete_one(self): values = [38, 45, 19, 45, 41, 41, 12, 45, 31, 35] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) + def test_delete_two(self): intervals = [] values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -42,6 +46,7 @@ def test_delete_two(self): values = [38, 42, 19, 35, 41, 41, 31, 35] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) + def test_delete_three(self): intervals = [] values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -54,6 +59,7 @@ def test_delete_three(self): values = [38, 42, 31, 35, 41, 41] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) + def test_delete_four(self): intervals = [] values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -67,6 +73,7 @@ def test_delete_four(self): values = [38, 42, 41, 41] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) + def test_delete_five(self): intervals = [] values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -81,6 +88,7 @@ def test_delete_five(self): values = [41, 41] for i in range(0, len(values), 2): self.wrap(T, values[i], values[i + 1]) + def test_delete_six(self): intervals = [] values = [41, 41, 38, 42, 31, 35, 12, 45, 19, 23, 9, 21] @@ -93,8 +101,8 @@ def test_delete_six(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.nil.maximum, float("-Inf")) - + self.assertEqual(T.nil.maximum, float("-Inf")) + def test_interval_search(self): intervals = [] values = [41, 41, 38, 52, 43, 48] @@ -103,13 +111,13 @@ def test_interval_search(self): T = interval_tree(intervals) i = interval(50, 51) t = T.closed_interval_search(i) - self.assertEquals(T.root.left, t) + self.assertEqual(T.root.left, t) i = interval(58, 60) t = T.closed_interval_search(i) - self.assertEquals(T.nil, t) + self.assertEqual(T.nil, t) i = interval(38, 48) t = T.closed_interval_search(i) - self.assertEquals(T.root, t) + self.assertEqual(T.root, t) def test_interval_search_minimum_low_end(self): intervals = [] @@ -119,13 +127,13 @@ def test_interval_search_minimum_low_end(self): T = interval_tree(intervals) i = interval(22, 51) t = T.closed_interval_search_minimum_low_end(i) - self.assertEquals(T.root.left, t) + self.assertEqual(T.root.left, t) i = interval(58, 60) t = T.closed_interval_search_minimum_low_end(i) - self.assertEquals(T.nil, t) + self.assertEqual(T.nil, t) i = interval(38, 48) t = T.closed_interval_search_minimum_low_end(i) - self.assertEquals(T.root.left, t) + self.assertEqual(T.root.left, t) def test_list_all_overlapping_intervals(self): intervals = [] @@ -152,26 +160,29 @@ def test_interval_search_exactly(self): T = interval_tree(intervals) i = interval(22, 51) t = T.interval_search_exactly(i) - self.assertEquals(t, T.nil) + self.assertEqual(t, T.nil) i = interval(41, 41) t = T.interval_search_exactly(i) - self.assertEquals(t, T.root) + self.assertEqual(t, T.root) i = interval(38, 52) t = T.interval_search_exactly(i) - self.assertEquals(t, T.root.left) + self.assertEqual(t, T.root.left) i = interval(43, 48) t = T.interval_search_exactly(i) - self.assertEquals(t, T.root.right) + self.assertEqual(t, T.root.right) i = interval(43, 49) t = T.interval_search_exactly(i) - self.assertEquals(t, T.nil) + self.assertEqual(t, T.nil) i = interval(20, 50) t = T.interval_search_exactly(i) - self.assertEquals(t, T.nil) + self.assertEqual(t, T.nil) i = interval(39, 41) t = T.interval_search_exactly(i) - self.assertEquals(t, T.nil) + self.assertEqual(t, T.nil) + def wrap(self, tree, node, maximum): - self.assertEquals(tree.iterative_tree_search(node).maximum, maximum) + self.assertEqual(tree.iterative_tree_search(node).maximum, maximum) + + if __name__ == '__main__': unittest.main() diff --git a/tests/inversion_test.py b/tests/inversion_test.py new file mode 100644 index 0000000..b85bac9 --- /dev/null +++ b/tests/inversion_test.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python +# encoding: utf-8 +import unittest +import random +from inversion import inversion_with_insertion_sort, inversion_with_merge_sort + + +class TestInversion(unittest.TestCase): + def test_inversion_with_insertion_sort(self): + for _ in range(100): + array = [random.randint(0, 100) for _ in range(100)] + expected_result = 0 + for i in range(len(array)): + for j in range(i + 1, len(array)): + if array[i] > array[j]: + expected_result += 1 + self.assertEqual(inversion_with_insertion_sort(array), expected_result) + + def test_inversion_with_merge_sort(self): + for _ in range(100): + array = [random.randint(0, 100) for _ in range(100)] + expected_result = 0 + for i in range(len(array)): + for j in range(i + 1, len(array)): + if array[i] > array[j]: + expected_result += 1 + self.assertEqual(inversion_with_merge_sort(array), expected_result) diff --git a/tests/k_way_merge_test.py b/tests/k_way_merge_test.py new file mode 100644 index 0000000..e1944fd --- /dev/null +++ b/tests/k_way_merge_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +import unittest +from k_way_merge import k_way_merge +from random_array import random_arrays + + +class TestKWayMerge(unittest.TestCase): + def test_k_way_merge(self): + for array in random_arrays(): + lists = [] + for i in range(10): + lists.append(array[10 * i: (i + 1) * 10]) + lists[-1].sort() + self.assertEqual(k_way_merge(lists), sorted(array)) diff --git a/tests/linked_list_test.py b/tests/linked_list_test.py new file mode 100644 index 0000000..06779d2 --- /dev/null +++ b/tests/linked_list_test.py @@ -0,0 +1,57 @@ +import unittest +from linkedlist import LinkedList, LinkedListNode + + +class TestLinkedList(unittest.TestCase): + def test_insert(self): + L = LinkedList() + a = LinkedListNode(1) + b = LinkedListNode(4) + c = LinkedListNode(16) + d = LinkedListNode(9) + e = LinkedListNode(25) + L.insert(a) + L.insert(b) + L.insert(c) + L.insert(d) + L.insert(e) + l = [] + x = L.head + while x: + l.append(x) + x = x.next + self.assertEqual(l, [e, d, c, b, a]) + + def test_search(self): + L = LinkedList() + a = LinkedListNode(1) + b = LinkedListNode(4) + c = LinkedListNode(16) + d = LinkedListNode(9) + e = LinkedListNode(25) + L.insert(a) + L.insert(b) + L.insert(c) + L.insert(d) + L.insert(e) + self.assertEqual(L.search(4), b) + + def test_delete(self): + L = LinkedList() + a = LinkedListNode(1) + b = LinkedListNode(4) + c = LinkedListNode(16) + d = LinkedListNode(9) + e = LinkedListNode(25) + L.insert(a) + L.insert(b) + L.insert(c) + L.insert(d) + L.insert(e) + L.delete(b) + l = [] + x = L.head + while x: + l.append(x) + x = x.next + self.assertEqual(l, [e, d, c, a]) diff --git a/longest_common_subsequence_test.py b/tests/longest_common_subsequence_test.py similarity index 58% rename from longest_common_subsequence_test.py rename to tests/longest_common_subsequence_test.py index 84bd881..3aaa4ec 100644 --- a/longest_common_subsequence_test.py +++ b/tests/longest_common_subsequence_test.py @@ -1,28 +1,30 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from longest_common_subsequence import lcs_length_one_row, lcs_length + class TestLCS(unittest.TestCase): def test_lcs_length(self): X = "ABCBDAB" Y = "BDCABA" - c,b = lcs_length(X, Y) - self.assertEquals(c[len(X), len(Y)], 4) + c, b = lcs_length(X, Y) + self.assertEqual(c[len(X), len(Y)], 4) X = [1, 0, 0, 1, 0, 1, 0, 1] Y = [0, 1, 0, 1, 1, 0, 1, 1, 0] - c,b = lcs_length(X, Y) - self.assertEquals(c[len(X), len(Y)], 6) + c, b = lcs_length(X, Y) + self.assertEqual(c[len(X), len(Y)], 6) X = "ACCGGTCGAGTGCGCGGAAGCCGGCCGAA" Y = "GTCGTTCGGAATGCCGTTGCTCTGTAAA" - c,b = lcs_length(X, Y) - self.assertEquals(c[len(X), len(Y)], 20) + c, b = lcs_length(X, Y) + self.assertEqual(c[len(X), len(Y)], 20) + def test_lcs_length_one_row(self): X = "ABCBDAB" Y = "BDCABA" - self.assertEquals(lcs_length_one_row(X, Y), 4) + self.assertEqual(lcs_length_one_row(X, Y), 4) X = [1, 0, 0, 1, 0, 1, 0, 1] Y = [0, 1, 0, 1, 1, 0, 1, 1, 0] - self.assertEquals(lcs_length_one_row(X, Y), 6) + self.assertEqual(lcs_length_one_row(X, Y), 6) X = "ACCGGTCGAGTGCGCGGAAGCCGGCCGAA" Y = "GTCGTTCGGAATGCCGTTGCTCTGTAAA" - self.assertEquals(lcs_length_one_row(X, Y), 20) + self.assertEqual(lcs_length_one_row(X, Y), 20) diff --git a/longest_monotonically_increasing_subsequence_test.py b/tests/longest_monotonically_increasing_subsequence_test.py similarity index 59% rename from longest_monotonically_increasing_subsequence_test.py rename to tests/longest_monotonically_increasing_subsequence_test.py index 6f94d7f..3be5ef2 100644 --- a/longest_monotonically_increasing_subsequence_test.py +++ b/tests/longest_monotonically_increasing_subsequence_test.py @@ -7,8 +7,8 @@ class TestLMIS(unittest.TestCase): def test_longest_monotonically_increasing_subsequence(self): X = [5, 4, 1, 3, 2] - self.assertEquals(longest_monotonically_increasing_subsequence(X), 2) + self.assertEqual(longest_monotonically_increasing_subsequence(X), 2) X = [1, 3, 4, 2, 5] - self.assertEquals(longest_monotonically_increasing_subsequence(X), 4) + self.assertEqual(longest_monotonically_increasing_subsequence(X), 4) X = [1, 3, 10, 5, 3, 4] - self.assertEquals(longest_monotonically_increasing_subsequence(X), 3) + self.assertEqual(longest_monotonically_increasing_subsequence(X), 3) diff --git a/tests/merge_sort_test.py b/tests/merge_sort_test.py new file mode 100644 index 0000000..7455c8b --- /dev/null +++ b/tests/merge_sort_test.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +import unittest +import random +from merge_sort import merge_sort, merge_with_sentinel, merge_without_sentinel, merge_ins_sort_bottom_to_top, \ + merge_ins_sort_top_to_bottom + + +class TestMergeSort(unittest.TestCase): + def test_merge_sort_with_sentinel(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + merge_sort(array, merge_with_sentinel) + self.assertEqual(array, sorted(array_copy)) + + def test_merge_sort_without_sentinel(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + merge_sort(array, merge_without_sentinel) + self.assertEqual(array, sorted(array_copy)) + + def test_merge_ins_sort(self): + for length in range(100, 200): + array = [random.randint(1, 10000) for _ in range(length)] + array_copy = array[:] + merge_ins_sort_bottom_to_top(array, partition=1) + self.assertEqual(array, sorted(array_copy)) + for length in range(100, 200): + array = [random.randint(1, 10000) for _ in range(length)] + array_copy = array[:] + merge_ins_sort_top_to_bottom(array, sublist_length=15) + self.assertEqual(array, sorted(array_copy)) diff --git a/min_gap_tree_test.py b/tests/min_gap_tree_test.py similarity index 76% rename from min_gap_tree_test.py rename to tests/min_gap_tree_test.py index aef1bb7..2bcf352 100755 --- a/min_gap_tree_test.py +++ b/tests/min_gap_tree_test.py @@ -1,92 +1,106 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest -from min_gap_tree import min_gap_tree, min_gap_node +from min_gap_tree import MinGapTree, MinGapNode class TestMinGapTree(unittest.TestCase): def test_insert_one(self): - T = min_gap_tree([50]) + T = MinGapTree([50]) self.wrap(T, 50, float("Inf")) + def test_insert_two(self): - T = min_gap_tree([50, 38]) + T = MinGapTree([50, 38]) self.wrap(T, 50, 12) self.wrap(T, 38, 12) + def test_insert_three(self): - T = min_gap_tree([50, 38, 31]) + T = MinGapTree([50, 38, 31]) self.wrap(T, 38, 7) self.wrap(T, 31, 7) self.wrap(T, 50, float("Inf")) + def test_insert_four(self): - T = min_gap_tree([50, 38, 31, 12]) - self.wrap(T, 38, 7) + T = MinGapTree([50, 38, 31, 12]) + self.wrap(T, 38, 7) self.wrap(T, 31, 7) self.wrap(T, 50, float("Inf")) self.wrap(T, 12, 19) + def test_insert_five(self): - T = min_gap_tree([50, 38, 31, 12, 19]) - self.wrap(T, 38, 7) + T = MinGapTree([50, 38, 31, 12, 19]) + self.wrap(T, 38, 7) self.wrap(T, 19, 7) self.wrap(T, 50, float("Inf")) self.wrap(T, 12, 7) self.wrap(T, 31, 7) + def test_insert_six(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) self.wrap(T, 38, 3) self.wrap(T, 19, 3) self.wrap(T, 50, float("Inf")) self.wrap(T, 12, 3) self.wrap(T, 31, 7) self.wrap(T, 9, 3) + def test_delete_one(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) self.wrap(T, 38, 7) self.wrap(T, 19, 7) self.wrap(T, 50, float("Inf")) self.wrap(T, 12, 7) self.wrap(T, 31, 7) + def test_delete_two(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) self.wrap(T, 38, 7) self.wrap(T, 19, 7) self.wrap(T, 50, float("Inf")) self.wrap(T, 31, 7) + def test_delete_three(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) self.wrap(T, 38, 7) self.wrap(T, 31, 7) self.wrap(T, 50, float("Inf")) + def test_delete_four(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, 12) self.wrap(T, 50, float("Inf")) + def test_delete_five(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) self.wrap(T, 50, float("Inf")) + def test_delete_six(self): - T = min_gap_tree([50, 38, 31, 12, 19, 9]) + T = MinGapTree([50, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(50)) - self.assertEquals(T.root, T.nil) + self.assertEqual(T.root, T.nil) + def wrap(self, tree, node, min_gap): - self.assertEquals(tree.iterative_tree_search(node).min_gap, min_gap) + self.assertEqual(tree.iterative_tree_search(node).min_gap, min_gap) + + if __name__ == '__main__': unittest.main() diff --git a/tests/min_heap_with_linked_list_test.py b/tests/min_heap_with_linked_list_test.py new file mode 100644 index 0000000..91c7202 --- /dev/null +++ b/tests/min_heap_with_linked_list_test.py @@ -0,0 +1,94 @@ +import unittest + +from linkedlist import LinkedList, LinkedListNode +from min_heap_with_linked_list import MinHeap, MinPriorityQueue + + +class TestHeap(unittest.TestCase): + def test_min_heapify(self): + L1 = LinkedList(1) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + h = MinHeap([L5, L1, L2, L3, L4]) + h.min_heapify(0) + self.assertEqual(h, [L1, L3, L2, L5, L4]) + + def test_build_min_heap(self): + L1 = LinkedList(1) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + h = MinHeap([L3, L4, L5, L2, L1]) + h.build_min_heap() + self.assertEqual(h, [L1, L2, L5, L3, L4]) + + def test_heap_minimum(self): + L1 = LinkedList(1) + L1.insert(LinkedListNode(1)) + L1.insert(LinkedListNode(1)) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + q = MinPriorityQueue([L1, L2, L3, L4, L5]) + self.assertEqual(q.heap_minimum().key, 1) + + def test_heap_extract_min(self): + L1 = LinkedList(1) + L1.insert(LinkedListNode(1)) + L1.insert(LinkedListNode(1)) + L2 = LinkedList(2) + L2.insert(LinkedListNode(2)) + L2.insert(LinkedListNode(2)) + L3 = LinkedList(3) + L3.insert(LinkedListNode(3)) + L3.insert(LinkedListNode(3)) + L4 = LinkedList(4) + L4.insert(LinkedListNode(4)) + L5 = LinkedList(5) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + L3.insert(LinkedListNode(5)) + q = MinPriorityQueue([L1, L2, L3, L4, L5]) + self.assertEqual(q.heap_extract_min().key, 1) + self.assertEqual(q, [L1, L2, L3, L4, L5]) + self.assertEqual(q.heap_extract_min().key, 1) + self.assertEqual(q, [L2, L4, L3, L5, L5]) +# def test_heap_decrease_key(self): +# a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] +# q = MinPriorityQueue(a) +# q.heap_decrease_key(8, 1) +# self.assertEqual(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) +# def test_heap_insert(self): +# a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] +# q = MinPriorityQueue(a) +# q.heap_extract_min() +# q.min_heap_insert(0) +# self.assertEqual(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) diff --git a/tests/min_priority_queue_using_rb_tree_test.py b/tests/min_priority_queue_using_rb_tree_test.py new file mode 100644 index 0000000..5bdbb4e --- /dev/null +++ b/tests/min_priority_queue_using_rb_tree_test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +import unittest +from min_priority_queue_using_rb_tree import min_priority_queue +from rb_tree import RbNode + + +class TestMinPriorityQueue(unittest.TestCase): + def test_extract_min(self): + q = min_priority_queue([41, 38, 31, 12, 19, 9]) + self.assertEqual(q.heap_extract_min().key, 9) + self.assertEqual(q.heap_extract_min().key, 12) + self.assertEqual(q.heap_extract_min().key, 19) + self.assertEqual(q.heap_extract_min().key, 31) + self.assertEqual(q.heap_extract_min().key, 38) + self.assertEqual(q.heap_extract_min().key, 41) + + def test_heap_decrease_key(self): + q = min_priority_queue([41, 38, 31, 12, 19, 9]) + q.heap_decrease_key(q.iterative_tree_search(9), 5) + q.heap_decrease_key(q.iterative_tree_search(38), 5) + self.assertEqual(q.heap_extract_min().key, 5) + self.assertEqual(q.heap_extract_min().key, 5) + self.assertEqual(q.heap_extract_min().key, 12) + self.assertEqual(q.heap_extract_min().key, 19) + self.assertEqual(q.heap_extract_min().key, 31) + self.assertEqual(q.heap_extract_min().key, 41) + + def test_heap_insert(self): + q = min_priority_queue([41, 38, 31, 12, 19, 9]) + q.min_heap_insert(RbNode(5, None, None, None, 0)) + q.min_heap_insert(RbNode(38, None, None, None, 0)) + q.min_heap_insert(RbNode(50, None, None, None, 0)) + self.assertEqual(q.heap_extract_min().key, 5) + self.assertEqual(q.heap_extract_min().key, 9) + self.assertEqual(q.heap_extract_min().key, 12) + self.assertEqual(q.heap_extract_min().key, 19) + self.assertEqual(q.heap_extract_min().key, 31) + self.assertEqual(q.heap_extract_min().key, 38) + self.assertEqual(q.heap_extract_min().key, 38) + self.assertEqual(q.heap_extract_min().key, 41) + self.assertEqual(q.heap_extract_min().key, 50) + + +if __name__ == '__main__': + unittest.main() diff --git a/most_reliable_path_test.py b/tests/most_reliable_path_test.py similarity index 52% rename from most_reliable_path_test.py rename to tests/most_reliable_path_test.py index 1383f7b..4817889 100644 --- a/most_reliable_path_test.py +++ b/tests/most_reliable_path_test.py @@ -2,6 +2,7 @@ import unittest from graph import Vertex, Graph + class TestMostReliablePath(unittest.TestCase): def test_most_reliable_path(self): s = Vertex('s') @@ -11,15 +12,17 @@ def test_most_reliable_path(self): vertices = [s, u, v, w] edges = [(s, u), (s, v), (s, w), (u, v), (u, w), (w, u)] G = Graph(vertices, edges) - probabilities = [0.2, 0.1, 0.15, 0.7, 0.6, 0.9] + probabilities = [0.2, 0.1, 0.15, 0.7, 0.6, 0.9] re = dict() - for i,j in zip(edges, probabilities): - re[i] = j + for i, j in zip(edges, probabilities): + re[i] = j + def r(x, y): - return re[(x, y)] + return re[(x, y)] + most_reliable_path(G, r, s) - self.assertEquals([i.p for i in vertices], [None, s, u, s]) - self.assertEquals([round(i.r, 2) for i in vertices], [1, 0.2, 0.14, 0.15]) + self.assertEqual([i.p for i in vertices], [None, s, u, s]) + self.assertEqual([round(i.r, 2) for i in vertices], [1, 0.2, 0.14, 0.15]) most_reliable_path(G, r, u) - self.assertEquals([i.p for i in vertices], [None, None, u, u]) - self.assertEquals([round(i.r, 2) for i in vertices], [0, 1, 0.7, 0.6]) + self.assertEqual([i.p for i in vertices], [None, None, u, u]) + self.assertEqual([round(i.r, 2) for i in vertices], [0, 1, 0.7, 0.6]) diff --git a/os_tree_test.py b/tests/os_tree_test.py similarity index 50% rename from os_tree_test.py rename to tests/os_tree_test.py index 83e77b2..4d99ede 100755 --- a/os_tree_test.py +++ b/tests/os_tree_test.py @@ -1,55 +1,61 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest -from os_tree import os_tree, os_node +from os_tree import os_tree, OSNode class TestOstree(unittest.TestCase): def test_insert_one(self): T = os_tree([41]) - print T.root.iterative_tree_search(41).p.key - self.assertEquals(T.root, T.root.iterative_tree_search(41)) - self.assertEquals(T.nil.size, 0) + print(T.root.iterative_tree_search(41).p.key) + self.assertEqual(T.root, T.root.iterative_tree_search(41)) + self.assertEqual(T.nil.size, 0) self.wrap(T, 41, -1, -1, -1, 1, 1) + def test_insert_two(self): T = os_tree([41, 38]) - self.assertEquals(T.root, T.iterative_tree_search(41)) - self.assertEquals(T.nil.size, 0) + self.assertEqual(T.root, T.iterative_tree_search(41)) + self.assertEqual(T.nil.size, 0) self.wrap(T, 41, 38, -1, -1, 1, 2) self.wrap(T, 38, -1, -1, 41, 0, 1) + def test_insert_three(self): T = os_tree([41, 38, 31]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.size, 0) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.size, 0) self.wrap(T, 38, 31, 41, -1, 1, 3) self.wrap(T, 31, -1, -1, 38, 0, 1) self.wrap(T, 41, -1, -1, 38, 0, 1) + def test_insert_four(self): T = os_tree([41, 38, 31, 12]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.size, 0) - self.wrap(T, 38, 31, 41, -1, 1, 4) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.size, 0) + self.wrap(T, 38, 31, 41, -1, 1, 4) self.wrap(T, 31, 12, -1, 38, 1, 2) self.wrap(T, 41, -1, -1, 38, 1, 1) self.wrap(T, 12, -1, -1, 31, 0, 1) + def test_insert_five(self): T = os_tree([41, 38, 31, 12, 19]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.size, 0) - self.wrap(T, 38, 19, 41, -1, 1, 5) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.size, 0) + self.wrap(T, 38, 19, 41, -1, 1, 5) self.wrap(T, 19, 12, 31, 38, 1, 3) self.wrap(T, 41, -1, -1, 38, 1, 1) self.wrap(T, 12, -1, -1, 19, 0, 1) self.wrap(T, 31, -1, -1, 19, 0, 1) + def test_insert_six(self): T = os_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.size, 0) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.size, 0) self.wrap(T, 38, 19, 41, -1, 1, 6) self.wrap(T, 19, 12, 31, 38, 0, 4) self.wrap(T, 41, -1, -1, 38, 1, 1) self.wrap(T, 12, 9, -1, 19, 1, 2) self.wrap(T, 31, -1, -1, 19, 1, 1) self.wrap(T, 9, -1, -1, 12, 0, 1) + def test_delete_one(self): T = os_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -58,6 +64,7 @@ def test_delete_one(self): self.wrap(T, 41, -1, -1, 38, 1, 1) self.wrap(T, 12, -1, -1, 19, 1, 1) self.wrap(T, 31, -1, -1, 19, 1, 1) + def test_delete_two(self): T = os_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -66,6 +73,7 @@ def test_delete_two(self): self.wrap(T, 19, -1, 31, 38, 1, 2) self.wrap(T, 41, -1, -1, 38, 1, 1) self.wrap(T, 31, -1, -1, 19, 0, 1) + def test_delete_three(self): T = os_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -74,6 +82,7 @@ def test_delete_three(self): self.wrap(T, 38, 31, 41, -1, 1, 3) self.wrap(T, 31, -1, -1, 38, 1, 1) self.wrap(T, 41, -1, -1, 38, 1, 1) + def test_delete_four(self): T = os_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -82,6 +91,7 @@ def test_delete_four(self): T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, -1, 41, -1, 1, 2) self.wrap(T, 41, -1, -1, 38, 0, 1) + def test_delete_five(self): T = os_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -90,6 +100,7 @@ def test_delete_five(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) self.wrap(T, 41, -1, -1, -1, 1, 1) + def test_delete_six(self): T = os_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -98,62 +109,72 @@ def test_delete_six(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.root, T.nil) - self.assertEquals(T.nil.size, 0) + self.assertEqual(T.root, T.nil) + self.assertEqual(T.nil.size, 0) + def test_key_rank(self): T = os_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.root.key_rank(41), 6) - self.assertEquals(T.root.key_rank(38), 5) - self.assertEquals(T.root.key_rank(31), 4) - self.assertEquals(T.root.key_rank(12), 2) - self.assertEquals(T.root.key_rank(19), 3) - self.assertEquals(T.root.key_rank(9), 1) + self.assertEqual(T.root.key_rank(41), 6) + self.assertEqual(T.root.key_rank(38), 5) + self.assertEqual(T.root.key_rank(31), 4) + self.assertEqual(T.root.key_rank(12), 2) + self.assertEqual(T.root.key_rank(19), 3) + self.assertEqual(T.root.key_rank(9), 1) + def test_rank(self): T = os_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.rank(T.iterative_tree_search(41)), 6) - self.assertEquals(T.rank(T.iterative_tree_search(38)), 5) - self.assertEquals(T.rank(T.iterative_tree_search(31)), 4) - self.assertEquals(T.rank(T.iterative_tree_search(12)), 2) - self.assertEquals(T.rank(T.iterative_tree_search(19)), 3) - self.assertEquals(T.rank(T.iterative_tree_search(9)), 1) + self.assertEqual(T.rank(T.iterative_tree_search(41)), 6) + self.assertEqual(T.rank(T.iterative_tree_search(38)), 5) + self.assertEqual(T.rank(T.iterative_tree_search(31)), 4) + self.assertEqual(T.rank(T.iterative_tree_search(12)), 2) + self.assertEqual(T.rank(T.iterative_tree_search(19)), 3) + self.assertEqual(T.rank(T.iterative_tree_search(9)), 1) + def test_select(self): T = os_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.root.select_recursive(1).key, 9) - self.assertEquals(T.root.select_recursive(2).key, 12) - self.assertEquals(T.root.select_recursive(3).key, 19) - self.assertEquals(T.root.select_recursive(4).key, 31) - self.assertEquals(T.root.select_recursive(5).key, 38) - self.assertEquals(T.root.select_recursive(6).key, 41) - self.assertEquals(T.root.select_iterative(1).key, 9) - self.assertEquals(T.root.select_iterative(2).key, 12) - self.assertEquals(T.root.select_iterative(3).key, 19) - self.assertEquals(T.root.select_iterative(4).key, 31) - self.assertEquals(T.root.select_iterative(5).key, 38) - self.assertEquals(T.root.select_iterative(6).key, 41) + self.assertEqual(T.root.select_recursive(1).key, 9) + self.assertEqual(T.root.select_recursive(2).key, 12) + self.assertEqual(T.root.select_recursive(3).key, 19) + self.assertEqual(T.root.select_recursive(4).key, 31) + self.assertEqual(T.root.select_recursive(5).key, 38) + self.assertEqual(T.root.select_recursive(6).key, 41) + self.assertEqual(T.root.select_iterative(1).key, 9) + self.assertEqual(T.root.select_iterative(2).key, 12) + self.assertEqual(T.root.select_iterative(3).key, 19) + self.assertEqual(T.root.select_iterative(4).key, 31) + self.assertEqual(T.root.select_iterative(5).key, 38) + self.assertEqual(T.root.select_iterative(6).key, 41) + def test_ith_successor(self): T = os_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.iterative_tree_search(9).ith_successor(1).key, 12) - self.assertEquals(T.iterative_tree_search(9).ith_successor(2).key, 19) - self.assertEquals(T.iterative_tree_search(9).ith_successor(3).key, 31) - self.assertEquals(T.iterative_tree_search(9).ith_successor(4).key, 38) - self.assertEquals(T.iterative_tree_search(9).ith_successor(5).key, 41) -# def test_insert_stack(self): -# T = os_tree([]) -# for i in 41, 38, 31, 12, 19, 9: -# T.insert_stack(os_node(i, None, None, None, 0)) -# self.assertEquals(T.root, T.iterative_tree_search(38)) -# self.assertEquals(T.nil.color, 1) -# self.wrap(T, 38, 19, 41, -1, 1) -# self.wrap(T, 19, 12, 31, 38, 0) -# self.wrap(T, 41, -1, -1, 38, 1) -# self.wrap(T, 12, 9, -1, 19, 1) -# self.wrap(T, 31, -1, -1, 19, 1) -# self.wrap(T, 9, -1, -1, 12, 0) + self.assertEqual(T.iterative_tree_search(9).ith_successor(1).key, 12) + self.assertEqual(T.iterative_tree_search(9).ith_successor(2).key, 19) + self.assertEqual(T.iterative_tree_search(9).ith_successor(3).key, 31) + self.assertEqual(T.iterative_tree_search(9).ith_successor(4).key, 38) + self.assertEqual(T.iterative_tree_search(9).ith_successor(5).key, 41) + + # def test_insert_stack(self): + # T = os_tree([]) + # for i in 41, 38, 31, 12, 19, 9: + # T.insert_stack(OSNode(i, None, None, None, 0)) + # self.assertEqual(T.root, T.iterative_tree_search(38)) + # self.assertEqual(T.nil.color, 1) + # self.wrap(T, 38, 19, 41, -1, 1) + # self.wrap(T, 19, 12, 31, 38, 0) + # self.wrap(T, 41, -1, -1, 38, 1) + # self.wrap(T, 12, 9, -1, 19, 1) + # self.wrap(T, 31, -1, -1, 19, 1) + # self.wrap(T, 9, -1, -1, 12, 0) def wrap(self, tree, node, left, right, p, color, size): - self.assertEquals(tree.iterative_tree_search(node).left, tree.iterative_tree_search(left)) - self.assertEquals(tree.iterative_tree_search(node).right, tree.iterative_tree_search(right)) - self.assertEquals(tree.iterative_tree_search(node).p, tree.iterative_tree_search(p)) - self.assertEquals(tree.iterative_tree_search(node).color, color) - self.assertEquals(tree.iterative_tree_search(node).size, size) + self.assertEqual(tree.iterative_tree_search( + node).left, tree.iterative_tree_search(left)) + self.assertEqual(tree.iterative_tree_search( + node).right, tree.iterative_tree_search(right)) + self.assertEqual(tree.iterative_tree_search( + node).p, tree.iterative_tree_search(p)) + self.assertEqual(tree.iterative_tree_search(node).color, color) + self.assertEqual(tree.iterative_tree_search(node).size, size) + + if __name__ == '__main__': unittest.main() diff --git a/tests/partition_test.py b/tests/partition_test.py new file mode 100644 index 0000000..b2c67ce --- /dev/null +++ b/tests/partition_test.py @@ -0,0 +1,24 @@ +import unittest +from partition import partition, partition2, partition3 +from random_array import random_arrays + + +class TestPartition(unittest.TestCase): + def test_partition(self): + for array in random_arrays(): + pivot_index = partition(array, 0, len(array) - 1) + pivot = array[pivot_index] + self.assertTrue(all(array[i] <= pivot for i in range(pivot_index)) and all( + array[i] > pivot for i in range(pivot_index + 1, len(array)))) + + def test_partition2(self): + a = [2, 8, 7, 1, 4, 5, 6, 4] + partition2(a, 0, 7) + self.assertEqual(a, [2, 1, 4, 4, 7, 5, 6, 8]) + + def test_partition3(self): + for array in random_arrays(): + pivot_index = partition3(array, 0, len(array) - 1) + pivot = array[pivot_index] + self.assertTrue(all(array[i] <= pivot for i in range(pivot_index)) and all( + array[i] > pivot for i in range(pivot_index + 1, len(array)))) diff --git a/pointer_tree_test.py b/tests/pointer_tree_test.py similarity index 88% rename from pointer_tree_test.py rename to tests/pointer_tree_test.py index 4ef4f6c..925b129 100755 --- a/pointer_tree_test.py +++ b/tests/pointer_tree_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from pointer_tree import pointer_tree, pointer_node @@ -7,21 +7,25 @@ class TestOstree(unittest.TestCase): def test_insert_one(self): T = pointer_tree([41]) self.wrap(T, 41, 41, 41, float("-Inf"), float("Inf")) + def test_insert_two(self): T = pointer_tree([41, 38]) self.wrap(T, 41, 38, 41, 38, float("Inf")) self.wrap(T, 38, 38, 38, float("-Inf"), 41) + def test_insert_three(self): T = pointer_tree([41, 38, 31]) self.wrap(T, 38, 31, 41, 31, 41) self.wrap(T, 31, 31, 31, float("-Inf"), 38) self.wrap(T, 41, 41, 41, 38, float("Inf")) + def test_insert_four(self): T = pointer_tree([41, 38, 31, 12]) self.wrap(T, 38, 12, 41, 31, 41) self.wrap(T, 31, 12, 31, 12, 38) self.wrap(T, 41, 41, 41, 38, float("Inf")) self.wrap(T, 12, 12, 12, float("-Inf"), 31) + def test_insert_five(self): T = pointer_tree([41, 38, 31, 12, 19]) self.wrap(T, 38, 12, 41, 31, 41) @@ -29,6 +33,7 @@ def test_insert_five(self): self.wrap(T, 41, 41, 41, 38, float("Inf")) self.wrap(T, 12, 12, 12, float("-Inf"), 19) self.wrap(T, 31, 31, 31, 19, 38) + def test_insert_six(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) self.wrap(T, 38, 9, 41, 31, 41) @@ -37,6 +42,7 @@ def test_insert_six(self): self.wrap(T, 12, 9, 12, 9, 19) self.wrap(T, 31, 31, 31, 19, 38) self.wrap(T, 9, 9, 9, float("-Inf"), 12) + def test_delete_one(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -45,6 +51,7 @@ def test_delete_one(self): self.wrap(T, 41, 41, 41, 38, float("Inf")) self.wrap(T, 12, 12, 12, float("-Inf"), 19) self.wrap(T, 31, 31, 31, 19, 38) + def test_delete_two(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -53,6 +60,7 @@ def test_delete_two(self): self.wrap(T, 19, 19, 31, float("-Inf"), 31) self.wrap(T, 41, 41, 41, 38, float("Inf")) self.wrap(T, 31, 31, 31, 19, 38) + def test_delete_three(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -61,6 +69,7 @@ def test_delete_three(self): self.wrap(T, 38, 31, 41, 31, 41) self.wrap(T, 31, 31, 31, float("-Inf"), 38) self.wrap(T, 41, 41, 41, 38, float("Inf")) + def test_delete_four(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -69,6 +78,7 @@ def test_delete_four(self): T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, 38, 41, float("-Inf"), 41) self.wrap(T, 41, 41, 41, 38, float("Inf")) + def test_delete_five(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -76,7 +86,8 @@ def test_delete_five(self): T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) - self.wrap(T, 41, 41, 41, float("-Inf"), float("Inf")) + self.wrap(T, 41, 41, 41, float("-Inf"), float("Inf")) + def test_delete_six(self): T = pointer_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -85,11 +96,16 @@ def test_delete_six(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.root, T.nil) + self.assertEqual(T.root, T.nil) + def wrap(self, tree, node, minimum, maximum, predecessor, successor): - self.assertEquals(tree.iterative_tree_search(node).minimum.key, minimum) - self.assertEquals(tree.iterative_tree_search(node).maximum.key, maximum) - self.assertEquals(tree.iterative_tree_search(node).predecessor.key, predecessor) - self.assertEquals(tree.iterative_tree_search(node).successor.key, successor) + self.assertEqual(tree.iterative_tree_search(node).minimum.key, minimum) + self.assertEqual(tree.iterative_tree_search(node).maximum.key, maximum) + self.assertEqual(tree.iterative_tree_search( + node).predecessor.key, predecessor) + self.assertEqual(tree.iterative_tree_search( + node).successor.key, successor) + + if __name__ == '__main__': unittest.main() diff --git a/tests/polygon_area_test.py b/tests/polygon_area_test.py new file mode 100644 index 0000000..7afde26 --- /dev/null +++ b/tests/polygon_area_test.py @@ -0,0 +1,12 @@ +import unittest +from polygon_area import polygon_area + + +class TestPolygonArea(unittest.TestCase): + def test_rectangle_area(self): + rectangle = ((0, 0), (0, 2), (2, 2), (2, 0)) + self.assertEqual(polygon_area(rectangle), 4) + + def test_triangle_area(self): + triangle = ((0, 0), (5, 0), (2.5, 5)) + self.assertEqual(polygon_area(triangle), 12.5) diff --git a/tests/priority_queue_test.py b/tests/priority_queue_test.py new file mode 100644 index 0000000..5c21b0b --- /dev/null +++ b/tests/priority_queue_test.py @@ -0,0 +1,86 @@ +import unittest +from priority_queue import MaxPriorityQueue, MinPriorityQueue + + +class TestMaxPriorityQueue(unittest.TestCase): + def test_init(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + q = MaxPriorityQueue(a) + self.assertEqual(q, [16, 14, 10, 8, 7, 9, 3, 2, 4, 1]) + + def test_heap_maximum(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + self.assertEqual(MaxPriorityQueue(a).heap_maximum(), 16) + + def test_heap_extract_max(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + h = MaxPriorityQueue(a) + self.assertEqual(h.heap_extract_max(), 16) + self.assertEqual(h, [14, 8, 10, 4, 7, 9, 3, 2, 1, 1]) + + def test_heap_increase_key(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + h = MaxPriorityQueue(a) + h.heap_increase_key(8, 15) + self.assertEqual(h, [16, 15, 10, 14, 7, 9, 3, 2, 8, 1]) + + def test_heap_insert(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + queue = MaxPriorityQueue(a) + queue.heap_extract_max() + queue.max_heap_insert(100) + self.assertEqual(queue, [100, 14, 10, 4, 8, 9, 3, 2, 1, 7]) + + def test_heap_delete(self): + a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] + h = MaxPriorityQueue(a) + h.heap_delete(4) + self.assertEqual(h[0:h.heap_size], [16, 14, 10, 8, 1, 9, 3, 2, 4]) + h.heap_delete(2) + self.assertEqual(h[0:h.heap_size], [16, 14, 9, 8, 1, 4, 3, 2]) + h.heap_delete(0) + self.assertEqual(h[0:h.heap_size], [14, 8, 9, 2, 1, 4, 3]) + h.heap_delete(5) + self.assertEqual(h[0:h.heap_size], [14, 8, 9, 2, 1, 3]) + h.heap_delete(3) + self.assertEqual(h[0:h.heap_size], [14, 8, 9, 3, 1]) + h.heap_delete(1) + self.assertEqual(h[0:h.heap_size], [14, 3, 9, 1]) + h.heap_delete(3) + self.assertEqual(h[0:h.heap_size], [14, 3, 9]) + h.heap_delete(2) + self.assertEqual(h[0:h.heap_size], [14, 3]) + h.heap_delete(1) + self.assertEqual(h[0:h.heap_size], [14]) + h.heap_delete(0) + self.assertEqual(h[0:h.heap_size], []) + + +class TestMinPriorityQueue(unittest.TestCase): + def test_init(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + q = MinPriorityQueue(a) + self.assertEqual(q, [1, 2, 3, 4, 7, 8, 9, 10, 14, 16]) + + def test_heap_minimum(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + self.assertEqual(MinPriorityQueue(a).heap_minimum(), 1) + + def test_heap_extract_min(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + q = MinPriorityQueue(a) + self.assertEqual(q.heap_extract_min(), 1) + self.assertEqual(q, [2, 4, 3, 10, 7, 8, 9, 16, 14, 16]) + + def test_heap_decrease_key(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + q = MinPriorityQueue(a) + q.heap_decrease_key(8, 1) + self.assertEqual(q, [1, 1, 3, 2, 7, 8, 9, 10, 4, 16]) + + def test_heap_insert(self): + a = [1, 10, 3, 2, 7, 8, 9, 4, 14, 16] + q = MinPriorityQueue(a) + q.heap_extract_min() + q.min_heap_insert(0) + self.assertEqual(q, [0, 2, 3, 10, 4, 8, 9, 16, 14, 7]) diff --git a/tests/quicksort_test.py b/tests/quicksort_test.py new file mode 100644 index 0000000..0ebac67 --- /dev/null +++ b/tests/quicksort_test.py @@ -0,0 +1,34 @@ +import unittest +from partition import partition, partition2, partition3 +import random +from quicksort import quicksort, randomized_quicksort + + +class TestQuickSort(unittest.TestCase): + def test_quicksort(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + quicksort(array, 0, len(array) - 1, partition) + array_copy.sort() + self.assertEqual(array, array_copy) + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + quicksort(array, 0, len(array) - 1, partition2) + array_copy.sort() + self.assertEqual(array, array_copy) + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + quicksort(array, 0, len(array) - 1, partition3) + array_copy.sort() + self.assertEqual(array, array_copy) + + def test_randomized_quicksort(self): + for _ in range(100): + array = [random.randint(1, 10000) for _ in range(100)] + array_copy = array[:] + randomized_quicksort(array, 0, len(array) - 1) + array_copy.sort() + self.assertEqual(array, array_copy) diff --git a/randomized_select_test.py b/tests/randomized_select_test.py similarity index 55% rename from randomized_select_test.py rename to tests/randomized_select_test.py index 64b6d72..a500497 100644 --- a/randomized_select_test.py +++ b/tests/randomized_select_test.py @@ -1,12 +1,14 @@ import unittest from randomized_select import randomized_select + class TestRandSelect(unittest.TestCase): def test_randomize_select_distinct(self): a = [10, 11, 5, 3, 2, 6, 0, 8, 100, 50] - self.assertEquals(randomized_select(a, 0, 9, 5), 6) + self.assertEqual(randomized_select(a, 0, 9, 5), 6) + def test_randomize_select_duplicate(self): a = [10, 11, 5, 8, 2, 6, 8, 8, 100, 50] - self.assertEquals(randomized_select(a, 0, 9, 4), 8) - self.assertEquals(randomized_select(a, 0, 9, 5), 8) - self.assertEquals(randomized_select(a, 0, 9, 6), 8) + self.assertEqual(randomized_select(a, 0, 9, 4), 8) + self.assertEqual(randomized_select(a, 0, 9, 5), 8) + self.assertEqual(randomized_select(a, 0, 9, 6), 8) diff --git a/rank_tree_test.py b/tests/rank_tree_test.py similarity index 72% rename from rank_tree_test.py rename to tests/rank_tree_test.py index 2aa547e..6c8c484 100755 --- a/rank_tree_test.py +++ b/tests/rank_tree_test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from rank_tree import rank_tree, rank_node @@ -6,50 +6,56 @@ class TestOstree(unittest.TestCase): def test_insert_one(self): T = rank_tree([41]) - print T.root.iterative_tree_search(41).p.key - self.assertEquals(T.root, T.root.iterative_tree_search(41)) - self.assertEquals(T.nil.rank, 0) + print(T.root.iterative_tree_search(41).p.key) + self.assertEqual(T.root, T.root.iterative_tree_search(41)) + self.assertEqual(T.nil.rank, 0) self.wrap(T, 41, -1, -1, -1, 1, 1) + def test_insert_two(self): T = rank_tree([41, 38]) - self.assertEquals(T.root, T.iterative_tree_search(41)) - self.assertEquals(T.nil.rank, 0) + self.assertEqual(T.root, T.iterative_tree_search(41)) + self.assertEqual(T.nil.rank, 0) self.wrap(T, 41, 38, -1, -1, 1, 2) self.wrap(T, 38, -1, -1, 41, 0, 1) + def test_insert_three(self): T = rank_tree([41, 38, 31]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.rank, 0) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.rank, 0) self.wrap(T, 38, 31, 41, -1, 1, 2) self.wrap(T, 31, -1, -1, 38, 0, 1) self.wrap(T, 41, -1, -1, 38, 0, 3) + def test_insert_four(self): T = rank_tree([41, 38, 31, 12]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.rank, 0) - self.wrap(T, 38, 31, 41, -1, 1, 3) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.rank, 0) + self.wrap(T, 38, 31, 41, -1, 1, 3) self.wrap(T, 31, 12, -1, 38, 1, 2) self.wrap(T, 41, -1, -1, 38, 1, 4) self.wrap(T, 12, -1, -1, 31, 0, 1) + def test_insert_five(self): T = rank_tree([41, 38, 31, 12, 19]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.rank, 0) - self.wrap(T, 38, 19, 41, -1, 1, 4) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.rank, 0) + self.wrap(T, 38, 19, 41, -1, 1, 4) self.wrap(T, 19, 12, 31, 38, 1, 2) self.wrap(T, 41, -1, -1, 38, 1, 5) self.wrap(T, 12, -1, -1, 19, 0, 1) self.wrap(T, 31, -1, -1, 19, 0, 3) + def test_insert_six(self): T = rank_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.rank, 0) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.rank, 0) self.wrap(T, 38, 19, 41, -1, 1, 5) self.wrap(T, 19, 12, 31, 38, 0, 3) self.wrap(T, 41, -1, -1, 38, 1, 6) self.wrap(T, 12, 9, -1, 19, 1, 2) self.wrap(T, 31, -1, -1, 19, 1, 4) self.wrap(T, 9, -1, -1, 12, 0, 1) + def test_delete_one(self): T = rank_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -58,6 +64,7 @@ def test_delete_one(self): self.wrap(T, 41, -1, -1, 38, 1, 5) self.wrap(T, 12, -1, -1, 19, 1, 1) self.wrap(T, 31, -1, -1, 19, 1, 3) + def test_delete_two(self): T = rank_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -66,6 +73,7 @@ def test_delete_two(self): self.wrap(T, 19, -1, 31, 38, 1, 1) self.wrap(T, 41, -1, -1, 38, 1, 4) self.wrap(T, 31, -1, -1, 19, 0, 2) + def test_delete_three(self): T = rank_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -74,6 +82,7 @@ def test_delete_three(self): self.wrap(T, 38, 31, 41, -1, 1, 2) self.wrap(T, 31, -1, -1, 38, 1, 1) self.wrap(T, 41, -1, -1, 38, 1, 3) + def test_delete_four(self): T = rank_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -82,6 +91,7 @@ def test_delete_four(self): T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, -1, 41, -1, 1, 1) self.wrap(T, 41, -1, -1, 38, 0, 2) + def test_delete_five(self): T = rank_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -90,6 +100,7 @@ def test_delete_five(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) self.wrap(T, 41, -1, -1, -1, 1, 1) + def test_delete_six(self): T = rank_tree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) @@ -98,13 +109,19 @@ def test_delete_six(self): T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.root, T.nil) - self.assertEquals(T.nil.rank, 0) + self.assertEqual(T.root, T.nil) + self.assertEqual(T.nil.rank, 0) + def wrap(self, tree, node, left, right, p, color, rank): - self.assertEquals(tree.iterative_tree_search(node).left, tree.iterative_tree_search(left)) - self.assertEquals(tree.iterative_tree_search(node).right, tree.iterative_tree_search(right)) - self.assertEquals(tree.iterative_tree_search(node).p, tree.iterative_tree_search(p)) - self.assertEquals(tree.iterative_tree_search(node).color, color) - self.assertEquals(tree.iterative_tree_search(node).rank, rank) + self.assertEqual(tree.iterative_tree_search( + node).left, tree.iterative_tree_search(left)) + self.assertEqual(tree.iterative_tree_search( + node).right, tree.iterative_tree_search(right)) + self.assertEqual(tree.iterative_tree_search( + node).p, tree.iterative_tree_search(p)) + self.assertEqual(tree.iterative_tree_search(node).color, color) + self.assertEqual(tree.iterative_tree_search(node).rank, rank) + + if __name__ == '__main__': unittest.main() diff --git a/rb_tree_test.py b/tests/rb_tree_test.py similarity index 62% rename from rb_tree_test.py rename to tests/rb_tree_test.py index 9efa1f6..36a6a58 100755 --- a/rb_tree_test.py +++ b/tests/rb_tree_test.py @@ -1,108 +1,125 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest -from rb_tree import rb_tree, rb_node +from rb_tree import RbTree, RbNode class TestRbtree(unittest.TestCase): def test_insert_one(self): - T = rb_tree([41]) - print T.root.iterative_tree_search(41).p.key - self.assertEquals(T.root, T.root.iterative_tree_search(41)) - self.assertEquals(T.nil.color, 1) + T = RbTree([41]) + print(T.root.iterative_tree_search(41).p.key) + self.assertEqual(T.root, T.root.iterative_tree_search(41)) + self.assertEqual(T.nil.color, 1) self.wrap(T, 41, -1, -1, -1, 1) + def test_insert_two(self): - T = rb_tree([41, 38]) - self.assertEquals(T.root, T.iterative_tree_search(41)) - self.assertEquals(T.nil.color, 1) + T = RbTree([41, 38]) + self.assertEqual(T.root, T.iterative_tree_search(41)) + self.assertEqual(T.nil.color, 1) self.wrap(T, 41, 38, -1, -1, 1) self.wrap(T, 38, -1, -1, 41, 0) + def test_insert_three(self): - T = rb_tree([41, 38, 31]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.color, 1) + T = RbTree([41, 38, 31]) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.color, 1) self.wrap(T, 38, 31, 41, -1, 1) self.wrap(T, 31, -1, -1, 38, 0) self.wrap(T, 41, -1, -1, 38, 0) + def test_insert_four(self): - T = rb_tree([41, 38, 31, 12]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.color, 1) - self.wrap(T, 38, 31, 41, -1, 1) + T = RbTree([41, 38, 31, 12]) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.color, 1) + self.wrap(T, 38, 31, 41, -1, 1) self.wrap(T, 31, 12, -1, 38, 1) self.wrap(T, 41, -1, -1, 38, 1) self.wrap(T, 12, -1, -1, 31, 0) + def test_insert_five(self): - T = rb_tree([41, 38, 31, 12, 19]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.color, 1) - self.wrap(T, 38, 19, 41, -1, 1) + T = RbTree([41, 38, 31, 12, 19]) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.color, 1) + self.wrap(T, 38, 19, 41, -1, 1) self.wrap(T, 19, 12, 31, 38, 1) self.wrap(T, 41, -1, -1, 38, 1) self.wrap(T, 12, -1, -1, 19, 0) self.wrap(T, 31, -1, -1, 19, 0) + def test_insert_six(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) - self.assertEquals(T.root, T.iterative_tree_search(38)) - self.assertEquals(T.nil.color, 1) + T = RbTree([41, 38, 31, 12, 19, 9]) + self.assertEqual(T.root, T.iterative_tree_search(38)) + self.assertEqual(T.nil.color, 1) self.wrap(T, 38, 19, 41, -1, 1) self.wrap(T, 19, 12, 31, 38, 0) self.wrap(T, 41, -1, -1, 38, 1) self.wrap(T, 12, 9, -1, 19, 1) self.wrap(T, 31, -1, -1, 19, 1) self.wrap(T, 9, -1, -1, 12, 0) + def test_delete_one(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) + T = RbTree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) self.wrap(T, 38, 19, 41, -1, 1) self.wrap(T, 19, 12, 31, 38, 0) self.wrap(T, 41, -1, -1, 38, 1) self.wrap(T, 12, -1, -1, 19, 1) self.wrap(T, 31, -1, -1, 19, 1) + def test_delete_two(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) + T = RbTree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) self.wrap(T, 38, 19, 41, -1, 1) self.wrap(T, 19, -1, 31, 38, 1) self.wrap(T, 41, -1, -1, 38, 1) self.wrap(T, 31, -1, -1, 19, 0) + def test_delete_three(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) + T = RbTree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) self.wrap(T, 38, 31, 41, -1, 1) self.wrap(T, 31, -1, -1, 38, 1) self.wrap(T, 41, -1, -1, 38, 1) + def test_delete_four(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) + T = RbTree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) self.wrap(T, 38, -1, 41, -1, 1) self.wrap(T, 41, -1, -1, 38, 0) + def test_delete_five(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) + T = RbTree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) self.wrap(T, 41, -1, -1, -1, 1) + def test_delete_six(self): - T = rb_tree([41, 38, 31, 12, 19, 9]) + T = RbTree([41, 38, 31, 12, 19, 9]) T.delete(T.iterative_tree_search(9)) T.delete(T.iterative_tree_search(12)) T.delete(T.iterative_tree_search(19)) T.delete(T.iterative_tree_search(31)) T.delete(T.iterative_tree_search(38)) T.delete(T.iterative_tree_search(41)) - self.assertEquals(T.root, T.nil) + self.assertEqual(T.root, T.nil) + def wrap(self, tree, node, left, right, p, color): - self.assertEquals(tree.iterative_tree_search(node).left, tree.iterative_tree_search(left)) - self.assertEquals(tree.iterative_tree_search(node).right, tree.iterative_tree_search(right)) - self.assertEquals(tree.iterative_tree_search(node).p, tree.iterative_tree_search(p)) - self.assertEquals(tree.iterative_tree_search(node).color, color) + self.assertEqual(tree.iterative_tree_search( + node).left, tree.iterative_tree_search(left)) + self.assertEqual(tree.iterative_tree_search( + node).right, tree.iterative_tree_search(right)) + self.assertEqual(tree.iterative_tree_search( + node).p, tree.iterative_tree_search(p)) + self.assertEqual(tree.iterative_tree_search(node).color, color) + + if __name__ == '__main__': unittest.main() diff --git a/tests/selection_sort_test.py b/tests/selection_sort_test.py new file mode 100644 index 0000000..5f538a4 --- /dev/null +++ b/tests/selection_sort_test.py @@ -0,0 +1,14 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import unittest +from random_array import random_arrays +from selection_sort import selection_sort + + +class TestSelectionSort(unittest.TestCase): + def test_selection_sort(self): + for array in random_arrays(): + sorted_array = sorted(array) + selection_sort(array) + self.assertEqual(array, sorted_array) diff --git a/tests/test_binary_add.py b/tests/test_binary_add.py new file mode 100644 index 0000000..2f9f1a6 --- /dev/null +++ b/tests/test_binary_add.py @@ -0,0 +1,9 @@ +from unittest import TestCase +from binary_add import binary_add + + +class Test(TestCase): + def test_binary_add(self): + array1 = [1, 0, 1, 0] + array2 = [0, 1, 1, 0] + self.assertEqual(binary_add(array1, array2), [1, 0, 0, 0, 0]) diff --git a/tests/test_deque.py b/tests/test_deque.py new file mode 100644 index 0000000..e74d940 --- /dev/null +++ b/tests/test_deque.py @@ -0,0 +1,50 @@ +from unittest import TestCase + +from Queue import FullException, EmptyException +from deque import Deque + + +class TestDeque(TestCase): + def test_enqueue_tail_and_dequeue_head(self): + deque = Deque(3) + deque.enqueue_tail(1) + deque.enqueue_tail(2) + with self.assertRaises(FullException): + deque.enqueue_tail(3) + self.assertEqual(1, deque.dequeue_head()) + self.assertEqual(2, deque.dequeue_head()) + with self.assertRaises(EmptyException): + deque.dequeue_head() + + def test_enqueue_head_and_dequeue_tail(self): + deque = Deque(3) + deque.enqueue_head(1) + deque.enqueue_head(2) + with self.assertRaises(FullException): + deque.enqueue_head(3) + self.assertEqual(1, deque.dequeue_tail()) + self.assertEqual(2, deque.dequeue_tail()) + with self.assertRaises(EmptyException): + deque.dequeue_tail() + + def test_enqueue_tail_and_dequeue_tail(self): + deque = Deque(3) + deque.enqueue_tail(1) + deque.enqueue_tail(2) + self.assertEqual(2, deque.dequeue_tail()) + self.assertEqual(1, deque.dequeue_tail()) + with self.assertRaises(EmptyException): + deque.dequeue_tail() + with self.assertRaises(EmptyException): + deque.dequeue_head() + + def test_enqueue_head_and_dequeue_head(self): + deque = Deque(3) + deque.enqueue_head(1) + deque.enqueue_head(2) + self.assertEqual(2, deque.dequeue_head()) + self.assertEqual(1, deque.dequeue_head()) + with self.assertRaises(EmptyException): + deque.dequeue_tail() + with self.assertRaises(EmptyException): + deque.dequeue_head() diff --git a/tests/test_dynamic_array.py b/tests/test_dynamic_array.py new file mode 100644 index 0000000..194f7fa --- /dev/null +++ b/tests/test_dynamic_array.py @@ -0,0 +1,15 @@ +from unittest import TestCase +from dynamic_array import DynamicArray + + +class TestDynamicArray(TestCase): + def test_add_and_get_and_size(self): + dynamic_array = DynamicArray(2) + self.assertEqual(0, dynamic_array.size()) + dynamic_array.add(1) + dynamic_array.add(2) + dynamic_array.add(3) + self.assertEqual(3, dynamic_array.size()) + self.assertEqual(1, dynamic_array.get(0)) + self.assertEqual(2, dynamic_array.get(1)) + self.assertEqual(3, dynamic_array.get(2)) diff --git a/tests/test_euclid.py b/tests/test_euclid.py new file mode 100644 index 0000000..0c7909c --- /dev/null +++ b/tests/test_euclid.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# encoding: utf-8 +from unittest import TestCase + +from euclid import euclid + + +class TestEuclid(TestCase): + def test_gcd(self): + self.assertEqual(euclid(10, 3), 1) + self.assertEqual(euclid(10, 4), 2) + self.assertEqual(euclid(10, 1), 1) + self.assertEqual(euclid(10, 5), 5) diff --git a/tests/test_gcd.py b/tests/test_gcd.py new file mode 100644 index 0000000..8a2d9f2 --- /dev/null +++ b/tests/test_gcd.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python +# encoding: utf-8 +from unittest import TestCase + +from gcd import gcd + + +class TestGcd(TestCase): + def test_gcd(self): + self.assertEqual(gcd(10, 3), 1) + self.assertEqual(gcd(10, 4), 2) + self.assertEqual(gcd(10, 1), 1) + self.assertEqual(gcd(10, 5), 5) diff --git a/tests/test_lowest_common_multiple.py b/tests/test_lowest_common_multiple.py new file mode 100644 index 0000000..ed59060 --- /dev/null +++ b/tests/test_lowest_common_multiple.py @@ -0,0 +1,9 @@ +from unittest import TestCase +from lowest_common_multiple import lcm + + +class LcmTest(TestCase): + def test_lcm(self): + self.assertEqual(lcm(10, 1), 10) + self.assertEqual(lcm(10, 8), 40) + self.assertEqual(lcm(15, 9), 45) diff --git a/tests/test_merge.py b/tests/test_merge.py new file mode 100644 index 0000000..18881b8 --- /dev/null +++ b/tests/test_merge.py @@ -0,0 +1,25 @@ +from unittest import TestCase +from merge import merge_without_sentinel, merge_with_sentinel +from random_array import random_arrays + + +class MergeTest(TestCase): + def test_merge_with_sentinel(self): + for array in random_arrays(): + left_array = array[:len(array) // 2] + right_array = array[len(array) // 2:] + left_array.sort() + right_array.sort() + result_array = left_array + right_array + merge_with_sentinel(result_array, 0, len(array) // 2 - 1, len(array) - 1) + self.assertEqual(result_array, sorted(array)) + + def test_merge_without_sentinel(self): + for array in random_arrays(): + left_array = array[:len(array) // 2] + right_array = array[len(array) // 2:] + left_array.sort() + right_array.sort() + result_array = left_array + right_array + merge_without_sentinel(result_array, 0, len(array) // 2 - 1, len(array) - 1) + self.assertEqual(result_array, sorted(array)) diff --git a/tests/test_pow.py b/tests/test_pow.py new file mode 100644 index 0000000..48d87b0 --- /dev/null +++ b/tests/test_pow.py @@ -0,0 +1,16 @@ +import math +import random +from unittest import TestCase +from pow import pow1, pow2 + + +class Test(TestCase): + def test_pow1(self): + x = random.randint(1, 10) + for n in range(10): + self.assertEqual(pow1(x, n), math.pow(x, n)) + + def test_pow2(self): + x = random.randint(1, 10) + for n in range(10): + self.assertEqual(pow2(x, n), math.pow(x, n)) diff --git a/tests/test_queue.py b/tests/test_queue.py new file mode 100644 index 0000000..c8eb359 --- /dev/null +++ b/tests/test_queue.py @@ -0,0 +1,30 @@ +from unittest import TestCase +from Queue import Queue, EmptyException, FullException + + +class TestQueue(TestCase): + def test_enqueue_and_dequeue(self): + queue = Queue(3) + queue.enqueue(1) + queue.enqueue(2) + with self.assertRaises(FullException): + queue.enqueue(3) + self.assertEqual(1, queue.dequeue()) + self.assertEqual(2, queue.dequeue()) + with self.assertRaises(EmptyException): + queue.dequeue() + + def test_empty(self): + queue = Queue(2) + self.assertTrue(queue.empty()) + + def test_full(self): + queue = Queue(2) + queue.enqueue(1) + self.assertTrue(queue.full()) + queue = Queue(1) + self.assertTrue(queue.full()) + + def test_capacity(self): + queue = Queue(5) + self.assertEqual(4, queue.capacity()) diff --git a/tests/two_sum_test.py b/tests/two_sum_test.py new file mode 100644 index 0000000..415afac --- /dev/null +++ b/tests/two_sum_test.py @@ -0,0 +1,17 @@ +import unittest +from random_array import random_arrays +import random +from two_sum import two_sum + + +class TestInsertionSort(unittest.TestCase): + def test_two_sum(self): + for array in random_arrays(array_num=1000, array_size=10, array_lowerbound=1, array_upperbound=20): + x = random.randint(1, 100) + n = len(array) + result = False + for i in range(n): + for j in range(i + 1, n): + if array[i] + array[j] == x: + result = True + self.assertEqual(two_sum(x, array), result) diff --git a/tests/universal_sink_test.py b/tests/universal_sink_test.py new file mode 100644 index 0000000..5d7a11e --- /dev/null +++ b/tests/universal_sink_test.py @@ -0,0 +1,31 @@ +import universal_sink as us +import unittest +import numpy + + +class TestRbtree(unittest.TestCase): + def test_universal_sink(self): + data = numpy.array( + [[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], + [1, 0, 0, 0, 0, 1]]) + self.assertEqual(us.universal_sink(data), 1) + data = numpy.array( + [[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], + [1, 1, 0, 0, 0, 1]]) + self.assertEqual(us.universal_sink(data), 2) + data = numpy.array( + [[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], + [1, 1, 1, 0, 0, 1]]) + self.assertEqual(us.universal_sink(data), 3) + data = numpy.array( + [[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], + [0, 0, 0, 1, 0, 1]]) + self.assertEqual(us.universal_sink(data), 4) + data = numpy.array( + [[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], + [1, 1, 1, 0, 1, 1]]) + self.assertEqual(us.universal_sink(data), 5) + data = numpy.array( + [[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], + [0, 0, 0, 0, 0, 0]]) + self.assertEqual(us.universal_sink(data), 6) diff --git a/vEB_tree_test.py b/tests/vEB_tree_test.py similarity index 51% rename from vEB_tree_test.py rename to tests/vEB_tree_test.py index ec3dbc9..a1fb46e 100644 --- a/vEB_tree_test.py +++ b/tests/vEB_tree_test.py @@ -1,8 +1,9 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from vEB_tree import vEB_node + class testVEB(unittest.TestCase): def test_vEB(self): v = vEB_node(2 ** 8) @@ -10,10 +11,10 @@ def test_vEB(self): for i in l: v.insert(i) for i in l: - self.assertEquals(v.member(i), True) - self.assertEquals(v.member(2), False) - self.assertEquals(v.member(3), False) + self.assertEqual(v.member(i), True) + self.assertEqual(v.member(2), False) + self.assertEqual(v.member(3), False) v.delete(1) - self.assertEquals(v.member(1), False) + self.assertEqual(v.member(1), False) v.delete(100) - self.assertEquals(v.member(100), False) + self.assertEqual(v.member(100), False) diff --git a/wrestlers_test.py b/tests/wrestlers_test.py similarity index 57% rename from wrestlers_test.py rename to tests/wrestlers_test.py index 78cf83c..a3fa9d1 100644 --- a/wrestlers_test.py +++ b/tests/wrestlers_test.py @@ -1,13 +1,17 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import unittest from wrestlers import wrestlers + class TestWrestler(unittest.TestCase): def testBfs(self): wrestlersList = [1, 2, 3, 4, 5, 6, 7, 8] - rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), (3, 6), (5, 6), (5, 7), (5, 8), (6, 8), (7, 8)] + rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), (3, 6), + (5, 6), (5, 7), (5, 8), (6, 8), (7, 8)] self.assertEqual(wrestlers(wrestlersList, rivalriesList), False) - rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), (3, 6), (5, 7), (5, 8), (6, 8), (7, 8)] + rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), + (3, 6), (5, 7), (5, 8), (6, 8), (7, 8)] self.assertEqual(wrestlers(wrestlersList, rivalriesList), False) - rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), (3, 6), (5, 7), (5, 8), (6, 8)] + rivalriesList = [(1, 2), (1, 3), (2, 4), (3, 5), + (3, 6), (5, 7), (5, 8), (6, 8)] self.assertEqual(wrestlers(wrestlersList, rivalriesList), True) diff --git a/three_points_colinear.py b/three_points_colinear.py index f1ebe7a..dd87706 100644 --- a/three_points_colinear.py +++ b/three_points_colinear.py @@ -1,10 +1,11 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -from heap import max_heap +from heap import MaxHeap -class vector(object): - def __init__(self, p1, p2, p1_index = 0, p2_index = 0): - # gurantee that the polar angle of this vector with respect to the origin point is in the range [0, pi) + +class vector: + def __init__(self, p1, p2, p1_index=0, p2_index=0): + # gurantee that the polar angle of this Vector with respect to the origin point is in the range [0, pi) if p1[1] > p2[1]: self.x = p1[0] - p2[0] self.y = p1[1] - p2[1] @@ -18,28 +19,35 @@ def __init__(self, p1, p2, p1_index = 0, p2_index = 0): self.p2 = p2 self.p1_index = p1_index self.p2_index = p2_index + def cross_product(self, v): return self.x * v.y - v.x * self.y + def __lt__(self, v): return self.cross_product(v) > 0 + def __gt__(self, v): return self.cross_product(v) < 0 + def __eq__(self, v): return self.cross_product(v) == 0 + def __le__(self, v): return self.cross_product(v) >= 0 + def __ge__(self, v): return self.cross_product(v) <= 0 + def three_points_colinear(points_list): - '''An algorithm to determine whether any three points in a set of n points are colinear''' + """ to determine whether any three points in a set of n points are colinear""" n = len(points_list) vectors_list = [] - for i in range(0, n): + for i in range(n): for j in range(i + 1, n): vectors_list.append(vector(points_list[i], points_list[j], i, j)) v0 = vector((1, 0), (0, 0)) - heap_vectors = max_heap(vectors_list) + heap_vectors = MaxHeap(vectors_list) heap_vectors.heapsort() status = [False] * n v = heap_vectors[0] @@ -61,9 +69,9 @@ def three_points_colinear(points_list): stack.append(v.p1_index) stack.append(v.p2_index) else: - print len(stack) - print stack - for i in range(0, len(stack)): + print(len(stack)) + print(stack) + for i in range(len(stack)): status[stack.pop()] = False stack.append(v.p1_index) stack.append(v.p2_index) diff --git a/three_sum.py b/three_sum.py index 4fec1d0..6387f4a 100644 --- a/three_sum.py +++ b/three_sum.py @@ -1,23 +1,23 @@ #!/usr/bin/env python # coding=utf-8 -def threeSum(A): - '''Given an array A of n integers, find one triplet + +def three_sum(array): + """ + Given an array `array` of n integers, find one triplet in the array which gives the sum of zero. - A must be in increasing order''' - n = len(A) + `array` must be in increasing order + """ + n = len(array) for i in range(n - 2): j = i + 1 k = n - 1 while k >= j: - if A[i] + A[j] + A[k] == 0: - return (A[i], A[j], A[k]) - elif A[i] + A[j] + A[k] > 0: + if array[i] + array[j] + array[k] == 0: + return array[i], array[j], array[k] + elif array[i] + array[j] + array[k] > 0: k = k - 1 else: j = j + 1 - - - diff --git a/tree.py b/tree.py index 07327b6..deedc02 100755 --- a/tree.py +++ b/tree.py @@ -1,123 +1,139 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python -import random -class Node(object): +class Node: def __init__(self, key, p, left, right): self.key = key self.p = p self.left = left self.right = right + def inorder_tree_walk(self): - if self.left != None: - self.left.inorder_tree_walk() - print self.key, - if self.right != None: - self.right.inorder_tree_walk() + if self.left is not None: + self.left.inorder_tree_walk() + print(self.key, ) + if self.right is not None: + self.right.inorder_tree_walk() + def preorder_tree_walk(self): - print self.key, - if self.left != None: - self.left.preorder_tree_walk() - if self.right != None: - self.right.preorder_tree_walk() + print(self.key, ) + if self.left is not None: + self.left.preorder_tree_walk() + if self.right is not None: + self.right.preorder_tree_walk() + def postorder_tree_walk(self): - if self.left != None: - self.left.postorder_tree_walk() - if self.right != None: - self.right.postorder_tree_walk() - print self.key, + if self.left is not None: + self.left.postorder_tree_walk() + if self.right is not None: + self.right.postorder_tree_walk() + print(self.key, ) + def inorder_tree_walk_stack(self): - s = [] - s.append({"data": self, "status": 0}) + s = [{"data": self, "status": 0}] while len(s) != 0: record = s.pop() if record["status"] == 0: x = record["data"] - if x.right != None: + if x.right is not None: s.append({"data": x.right, "status": 0}) s.append({"data": x, "status": 1}) - if x.left != None: + if x.left is not None: s.append({"data": x.left, "status": 0}) else: - print record["data"].key, - print + print(record["data"].key, ) + print() + def iterative_tree_search(self, k): x = self - while x != None and x.key != k: + while x is not None and x.key != k: if x.key < k: x = x.right else: x = x.left return x + def minimum(self): x = self - while x.left != None: + while x.left is not None: x = x.left return x + def maximum(self): x = self - while x.right != None: + while x.right is not None: x = x.right return x + def successor(self): x = self - if x.right != None: + if x.right is not None: return x.right.minimum() else: - while x.p != None and x.p.right == x: + while x.p is not None and x.p.right == x: x = x.p return x.p + def predecessor(self): x = self - if x.left != None: + if x.left is not None: return x.left.maximum() else: - while x.p != None and x.p.left == x: + while x.p is not None and x.p.left == x: x = x.p return x.p -class Tree(object): + + +class Tree: root = None + def __init__(self, values): if isinstance(values, list): for i in values: self.insert(Node(i, None, None, None)) else: - print "Not invalid argument" + print("Not invalid argument") + def minimum(self): return self.root.minimum() + def __getitem__(self, key): return self.root.iterative_tree_search(key) + def insert(self, node): y = None x = self.root - while x != None: + while x is not None: y = x if node.key <= x.key: x = x.left else: x = x.right node.p = y - if y == None: + if y is None: self.root = node elif node.key <= y.key: y.left = node else: y.right = node + def iterative_tree_search(self, k): pass + def transplant(self, u, v): - if u.p == None: + if u.p is None: self.root = v elif u == u.p.left: u.p.left = v else: u.p.right = v - if v != None: + if v is not None: v.p = u.p + def delete(self, z): - if z.left == None: + if z.left is None: self.transplant(z, z.right) - elif z.right == None: + elif z.right is None: self.transplant(z, z.left) else: y = z.right.minimum() @@ -128,31 +144,33 @@ def delete(self, z): self.transplant(z, y) y.left = z.left y.left.p = y -#A = [random.randint(1, 100) for i in range(0, 15)] -#A = [29, 81, 53, 51, 28, 31, 57, 30, 22, 62, 6, 50, 7, 2, 24, 55, 54, 56, 98] -#print A -#T = Tree(A) -#T.delete(T.root.iterative_tree_search(57)) -#T.delete(T.root.iterative_tree_search(81)) -#T.root.postorder_tree_walk() -#print "maximum: %d" % (T.root.maximum().key) -#inorder_tree_walk_stack(T.root) -#T.root.inorder_tree_walk_stack() -#T.root.inorder_tree_walk() -print -#T.root.preorder_tree_walk() -print -#T.root.postorder_tree_walk() -#x = T.root.iterative_tree_search(50) -#if x == None: -# print "None" -#else: -# print x.key -#print T.root.mimimum().key + + +# A = [random.randint(1, 100) for i in range(15)] +# A = [29, 81, 53, 51, 28, 31, 57, 30, 22, 62, 6, 50, 7, 2, 24, 55, 54, 56, 98] +# print( A) +# T = Tree(A) +# T.delete(T.root.iterative_tree_search(57)) +# T.delete(T.root.iterative_tree_search(81)) +# T.root.postorder_tree_walk() +# print( "maximum: %d" % (T.root.maximum().key)) +# inorder_tree_walk_stack(T.root) +# T.root.inorder_tree_walk_stack() +# T.root.inorder_tree_walk() +# print() +# T.root.preorder_tree_walk() +# print() +# T.root.postorder_tree_walk() +# x = T.root.iterative_tree_search(50) +# if x is None: +# print( "None") +# else: +# print( x.key) +# print( T.root.mimimum().key) # -#su = T.root.successor() -#if su: -# print su.key -#pr = T.root.predecessor() -#if pr: -# print "predecessor of root is %d " % (pr.key) +# su = T.root.successor() +# if su: +# print( su.key) +# pr = T.root.predecessor() +# if pr: +# print( "predecessor of root is %d " % (pr.key)) diff --git a/two_sum.py b/two_sum.py new file mode 100644 index 0000000..cb906c6 --- /dev/null +++ b/two_sum.py @@ -0,0 +1,20 @@ +def two_sum(x: int, array: list): + """ + an algorithm that, given a set S of n integers and another integer x, + determines whether or not there exist two elements in S whose sum is exactly x. + :param x: + :param array: + :return: + """ + sorted_array = sorted(array) + i = 0 + j = len(array) - 1 + while i < j: + sum = sorted_array[i] + sorted_array[j] + if sum == x: + return True + elif sum < x: + i = i + 1 + else: + j = j - 1 + return False diff --git a/universal_sink.py b/universal_sink.py index 1aab58a..2768126 100644 --- a/universal_sink.py +++ b/universal_sink.py @@ -1,22 +1,24 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python + def universal_sink(M): - ''' + """ An algorithm to determine whether a directed graph G contains a universal sink---a vertex with in-degree |V| - 1 and out-degree 0---in time O(V), given an adjacency matrix for G - + M: numpy matrix, the adjacency matrix for the graph rtype: vertex index if G contains a universal sink, otherwise, return None - ''' + """ return universal_sink_aux(M, 1) + def universal_sink_aux(M, i): - ''' + """ M: numpy matrix i: vertex index - ''' + """ size = M.shape[0] j = i while True: @@ -30,6 +32,6 @@ def universal_sink_aux(M, i): for j in range(1, size + 1): if M[j - 1][i - 1] == 0 and j != i: return None - return i + return i else: return universal_sink_aux(M, j) diff --git a/universal_sink_test.py b/universal_sink_test.py deleted file mode 100644 index de46f8a..0000000 --- a/universal_sink_test.py +++ /dev/null @@ -1,18 +0,0 @@ -import universal_sink as us -import unittest -import numpy - -class TestRbtree(unittest.TestCase): - def test_universal_sink(self): - data = numpy.array([[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], [1, 0, 0, 0, 0, 1]]) - self.assertEquals(us.universal_sink(data), 1) - data = numpy.array([[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], [1, 1, 0, 0, 0, 1]]) - self.assertEquals(us.universal_sink(data), 2) - data = numpy.array([[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], [1, 1, 1, 0, 0, 1]]) - self.assertEquals(us.universal_sink(data), 3) - data = numpy.array([[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], [0, 0, 0, 1, 0, 1]]) - self.assertEquals(us.universal_sink(data), 4) - data = numpy.array([[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], [1, 1, 1, 0, 1, 1]]) - self.assertEquals(us.universal_sink(data), 5) - data = numpy.array([[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], [0, 0, 0, 0, 0, 0]]) - self.assertEquals(us.universal_sink(data), 6) diff --git a/vEB_tree.py b/vEB_tree.py index 08ab25c..de193fb 100644 --- a/vEB_tree.py +++ b/vEB_tree.py @@ -1,10 +1,11 @@ -#!/usr/bin/env ipython +#!/usr/bin/env python import math -class vEB_node(object): + +class vEB_node: def __init__(self, u): - '''u must be exact power of 2, as required by CLRS; otherwise, the behavior is undefined''' + """u must be exact power of 2, as required by CLRS; otherwise, the behavior is undefined""" self.u = u self.min = None self.max = None @@ -12,14 +13,18 @@ def __init__(self, u): self.root = int(math.sqrt(u)) self.cluster = [0] * self.root self.summary = vEB_node(self.root) - for i in range(0, self.root): + for i in range(self.root): self.cluster[i] = vEB_node(self.root) + def high(self, x): - return x / self.root + return x // self.root + def low(self, x): return x % self.root + def index(self, x, y): return x * self.root + y + def member(self, x): if self.min == x or self.max == x: return True @@ -27,49 +32,53 @@ def member(self, x): return False else: return self.cluster[self.high(x)].member(self.low(x)) + def successor(self, x): if self.u == 2: if x == 0 and self.max == 1: return 1 else: return None - elif self.min != None and x < self.min: + elif self.min is not None and x < self.min: return self.min else: max_low = self.cluster[self.high(x)].max - if max_low != None and self.low(x) < max_low: + if max_low is not None and self.low(x) < max_low: offset = self.cluster[self.high(x)].successor(self.low(x)) return self.index(self.high(x), offset) else: succ_cluster = self.summary.successor(self.high(x)) - if succ_cluster == None: + if succ_cluster is None: return None else: offset = self.cluster[succ_cluster].min return self.index(succ_cluster, offset) + def empty_tree_insert(self, x): self.min = x self.max = x + def insert(self, x): - if self.min == None: + if self.min is None: self.empty_tree_insert(x) elif (x == self.min) or (x == self.max): return else: if x < self.min: - x,self.min = self.min,x + x, self.min = self.min, x if self.u > 2: - if self.cluster[self.high(x)].min == None: + if self.cluster[self.high(x)].min is None: self.summary.insert(self.high(x)) self.cluster[self.high(x)].empty_tree_insert(self.low(x)) else: self.cluster[self.high(x)].insert(self.low(x)) if x > self.max: self.max = x + def delete(self, x): -# print "u = {}, x = {}".format(self.u, x) + # print( "u = {}, x = {}".format(self.u, x)) if self.min == self.max: - # print "min = {}, max = {}".format(self.min, self.max) + # print( "min = {}, max = {}".format(self.min, self.max)) if x == self.min: self.min = None self.max = None @@ -86,24 +95,29 @@ def delete(self, x): x = self.index(first_cluster, self.cluster[first_cluster].min) self.min = x self.cluster[self.high(x)].delete(self.low(x)) - if self.cluster[self.high(x)].min == None: + if self.cluster[self.high(x)].min is None: self.summary.delete(self.high(x)) if x == self.max: summary_max = self.summary.max - if summary_max == None: + if summary_max is None: self.max = self.min else: - self.max = self.index(summary_max, self.cluster[summary_max].max) + self.max = self.index( + summary_max, self.cluster[summary_max].max) elif x == self.max: - self.max = self.index(self.high(x), self.cluster[self.high(x)].max) + self.max = self.index( + self.high(x), self.cluster[self.high(x)].max) + def print_veb(self): if self.u == 2: - print "u = {}, min = {}, max = {}".format(self.u, self.min, self.max) + print("u = {}, min = {}, max = {}".format( + self.u, self.min, self.max)) else: - print "u = {}, min = {}, max = {}".format(self.u, self.min, self.max) - print "Summary: \t", + print("u = {}, min = {}, max = {}".format( + self.u, self.min, self.max)) + print("Summary: \t", ) self.summary.print_veb() - print - for i in range(0, self.root): + print() + for i in range(self.root): self.cluster[i].print_veb() - print + print() diff --git a/wrestlers.py b/wrestlers.py index 19d1d2c..fca182c 100644 --- a/wrestlers.py +++ b/wrestlers.py @@ -1,8 +1,9 @@ -from queue import queue +from queue import Queue from graph import Graph, Vertex + def wrestlers(wrestlersList, rivalriesList): - ''' + """ There are two types of professional wrestlers: "babyfaces" ("good guys") and "heels" ("bad guys"). Between any pair of professional wrestlers, there may or may not be a rivalry. @@ -11,7 +12,7 @@ def wrestlers(wrestlersList, rivalriesList): possible to designate some of the wrestlers as babyfaces and There remainder as heels such that each rivalry is between a babyfaces and a heel. - ''' + """ d = dict() vertices = [None] * len(wrestlersList) edges = [None] * len(rivalriesList) @@ -28,16 +29,17 @@ def wrestlers(wrestlersList, rivalriesList): u.type = 0 for u in g.vertices: if u.type == 0: - if _bfs(g, u) == False: + if not _bfs(g, u): return False return True + def _bfs(g, s): s.type = 1 - q = queue(2 * len(g.vertices)) - q.enqueue(s) + q = Queue(2 * len(g.vertices)) + q.put(s) while not q.empty(): - u = q.dequeue() + u = q.get() for v in g.adj[u]: if u.type == v.type: return False @@ -46,5 +48,5 @@ def _bfs(g, s): v.type = 2 else: v.type = 1 - q.enqueue(v) + q.put(v) return True