├── .gitignore ├── LICENSE ├── README.md ├── c ├── containers │ ├── dynamic_array.c │ ├── dynamic_array.h │ ├── dynamic_array_testspecial.c │ ├── heap.c │ ├── heap.h │ ├── heap_testspecial.c │ ├── linked_list.c │ ├── linked_list.h │ ├── linked_list_test.c │ └── makefile ├── makefile ├── sort │ ├── insertion_sort.c │ ├── insertion_sort.h │ ├── insertion_sort_test.c │ ├── merge_sort.c │ ├── merge_sort.h │ ├── merge_sort_test.c │ ├── quicksort.c │ ├── quicksort.h │ └── quicksort_test.c ├── tree │ └── binary │ │ ├── binary_tree.c │ │ ├── binary_tree.h │ │ └── binary_tree_test.c └── various │ ├── balanced_parens.c │ ├── balanced_parens.h │ ├── balanced_parens_test.c │ ├── combination_letters.c │ ├── combination_letters.h │ ├── combination_letters_test.c │ ├── max_subarray.c │ ├── max_subarray.h │ ├── max_subarray_test.c │ ├── permute_letters.c │ ├── permute_letters.h │ ├── permute_letters_test.c │ ├── reverse_words.c │ ├── reverse_words.h │ ├── reverse_words_test.c │ ├── tele_words.c │ ├── tele_words.h │ └── tele_words_test.c ├── go ├── graph │ ├── example_mst_test.go │ ├── example_topsort_test.go │ ├── functions.go │ ├── functions_test.go │ ├── graph.go │ ├── graph_heap.go │ ├── graph_test.go │ ├── lite │ │ └── litegraph.go │ ├── search.go │ └── todo.md ├── matrix │ ├── multiply.go │ └── multiply_test.go ├── sort │ ├── dupsort │ │ ├── dupsort.go │ │ ├── mergesort.go │ │ └── mergesort_test.go │ ├── heap.go │ ├── heap_test.go │ ├── integers │ │ ├── countingsort.go │ │ ├── countingsort_test.go │ │ ├── mergesort.go │ │ └── mergesort_test.go │ ├── quicksort.go │ ├── quicksort_test.go │ ├── sort.go │ └── sort_test.go ├── tree │ ├── binary │ │ ├── binaryTree.go │ │ └── binaryTree_test.go │ └── heap │ │ ├── heap.go │ │ └── heap_test.go └── various │ ├── dynamic │ ├── lcs.go │ ├── lcs_test.go │ ├── rodcutting.go │ └── rodcutting_test.go │ ├── inversions.go │ ├── inversions_test.go │ ├── maxsubarray.go │ ├── maxsubarray_test.go │ ├── random_select.go │ └── random_select_test.go └── java └── project └── src └── dnyamic └── matrixChainMultiply ├── MatrixInfo.java └── MatrixInfoTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.sw[a-z] 2 | .metadata 3 | .classpath 4 | .project 5 | .settings 6 | bin/ 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Travis Bischel. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Algoimpl 2 | 3 | A collection of various algorithms in various languages. I have tried 4 | to organize them into appropriate directories in case anybody wants to 5 | import a package in to their library. 6 | 7 | My go [graph](http://godoc.org/github.com/twmb/algoimpl/go/graph) package 8 | is well built. Use it. Give me suggestions. 9 | -------------------------------------------------------------------------------- /c/containers/dynamic_array.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "dynamic_array.h" 6 | 7 | struct dynamic_array { 8 | void **elements; 9 | int len; 10 | int cap; 11 | 12 | void **elements_start; // points to original starting position after a slice 13 | int *slicecount; 14 | 15 | pthread_mutexattr_t mutexattr; 16 | pthread_mutex_t mutex; // uesd to update slicecount 17 | }; 18 | 19 | dynarr *create_dynarr(void) { 20 | dynarr *r = malloc(sizeof(dynarr)); 21 | r->len = 0; 22 | r->cap = 0; 23 | 24 | r->elements = malloc(0); 25 | 26 | r->slicecount = malloc(sizeof(int)); 27 | *r->slicecount = 0; 28 | 29 | pthread_mutexattr_init(&r->mutexattr); 30 | pthread_mutex_init(&r->mutex, &r->mutexattr); 31 | return r; 32 | } 33 | 34 | dynarr *make_dynarr(int len, int cap) { 35 | dynarr *r = malloc(sizeof(dynarr)); 36 | if (len < 0) { 37 | exit(-1); 38 | } 39 | if (cap < len) { 40 | cap = len; 41 | } 42 | r->len = len; 43 | r->cap = cap; 44 | r->elements = malloc(cap * sizeof(void*)); 45 | r->elements_start = r->elements; 46 | 47 | r->slicecount = malloc(sizeof(int)); 48 | *r->slicecount = 0; 49 | 50 | pthread_mutexattr_init(&r->mutexattr); 51 | pthread_mutex_init(&r->mutex, &r->mutexattr); 52 | return r; 53 | } 54 | 55 | void destroy_dynarr(dynarr *array) { 56 | pthread_mutex_lock(&array->mutex); 57 | if (*array->slicecount == 0) { 58 | free(array->slicecount); 59 | free(array->elements_start); 60 | pthread_mutex_unlock(&array->mutex); 61 | pthread_mutexattr_destroy(&array->mutexattr); 62 | pthread_mutex_destroy(&array->mutex); 63 | free(array); 64 | } else { 65 | (*array->slicecount)--; 66 | pthread_mutex_unlock(&array->mutex); 67 | free(array); 68 | } 69 | } 70 | 71 | void *dynarr_append(dynarr *array, void *element) { 72 | // Appending should only free the previous elements pointer 73 | // if no other slices currently contain those elements. 74 | // Hence, appending will never free anything that has slices of it. 75 | // However, if the array does need to allocate a larger capacity, 76 | // it will no longer belong to any previous slices. 77 | if (array->cap == 0) { 78 | void **new_array = malloc(sizeof(void*)); 79 | if (*array->slicecount > 0) { 80 | pthread_mutex_lock(&array->mutex); 81 | (*array->slicecount)--; 82 | pthread_mutex_lock(&array->mutex); 83 | array->slicecount = malloc(sizeof(int)); 84 | *array->slicecount = 0; 85 | } else { 86 | free(array->elements); 87 | } 88 | array->elements = new_array; 89 | array->elements_start = array->elements; 90 | array->cap = 1; 91 | } 92 | 93 | if (array->len == array->cap) { 94 | void **new_array; 95 | if (array->cap > 1000) { 96 | new_array = malloc(sizeof(void*) * 1.2 * array->cap); 97 | array->cap = (int)(array->cap * 1.2); 98 | 99 | } else { 100 | new_array = malloc(sizeof(void*) * 2 * array->cap); 101 | array->cap *= 2; 102 | } 103 | memcpy(new_array, array->elements, sizeof(void*) * array->len); 104 | if (*array->slicecount > 0) { 105 | pthread_mutex_lock(&array->mutex); 106 | (*array->slicecount)--; 107 | pthread_mutex_unlock(&array->mutex); 108 | array->slicecount = malloc(sizeof(int)); 109 | *array->slicecount = 0; 110 | } else { 111 | free(array->elements); 112 | } 113 | array->elements = new_array; 114 | array->elements_start = array->elements; 115 | } 116 | 117 | if (array->elements != NULL) { 118 | array->elements[array->len] = element; 119 | } 120 | array->len++; 121 | return array->elements; 122 | } 123 | 124 | dynarr *dynarr_slice(dynarr *array, int from, int to) { 125 | if (to > array->len) { 126 | exit(1); 127 | } 128 | dynarr *new = malloc(sizeof(dynarr)); 129 | new->elements = &array->elements[from]; 130 | // Elements start is needed if the original array is destroyed 131 | // before this new one. Otherwise, will not know where the original 132 | // elements began. 133 | new->elements_start = array->elements_start; 134 | new->len = to-from; 135 | new->cap = array->cap-from; 136 | new->slicecount = array->slicecount; 137 | new->mutexattr = array->mutexattr; 138 | new->mutex = array->mutex; 139 | pthread_mutex_lock(&array->mutex); 140 | (*array->slicecount)++; 141 | pthread_mutex_unlock(&array->mutex); 142 | return new; 143 | } 144 | 145 | void *dynarr_at(dynarr *array, int position) { 146 | return array->elements[position]; 147 | } 148 | 149 | void dynarr_set(dynarr *array, int position, void *element) { 150 | array->elements[position] = element; 151 | } 152 | 153 | int dynarr_len(dynarr *array) { 154 | return array->len; 155 | } 156 | -------------------------------------------------------------------------------- /c/containers/dynamic_array.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_DYNARRAY 2 | #define TWMB_DYNARRAY 3 | 4 | typedef struct dynamic_array dynarr; 5 | 6 | // Creates and returns a new dynamic array. 7 | // destroy_dynarr must be called to delete it. 8 | dynarr *create_dynarr(void); 9 | // Makes and returns a new dynamic array with the given length 10 | // and capacity. destroy_dynarr must be called to delete it. 11 | dynarr *make_dynarr(int len, int cap); 12 | // Destroys a dynamic array. If there are no remaining slices 13 | // of a dynamic array's elements, this destroys the elements 14 | // the dynamic array contained. 15 | void destroy_dynarr(dynarr *array); 16 | // Appends to the end of a dynamic array. It reallocates 17 | // elements and updates the capacity as necessary. 18 | void *dynarr_append(dynarr *array, void *element); 19 | // Slices and returns a new dynamic array. The return value must 20 | // not overwrite the array being slice as that array must be destroyed 21 | // for all memory to be freed. 22 | dynarr *dynarr_slice(dynarr *array, int from, int to); 23 | // Returns the element at the requested position in the array. 24 | void *dynarr_at(dynarr *array, int position); 25 | // Sets the element at the given position in the array to the new element. 26 | void dynarr_set(dynarr *array, int position, void *element); 27 | // Returns the current length of the dynamic array. 28 | int dynarr_len(dynarr *array); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /c/containers/dynamic_array_testspecial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "dynamic_array.c" 5 | 6 | int check_dynarr(dynarr *d, int exp_len, int exp_cap) { 7 | int rval; 8 | if (d->len != exp_len) { 9 | printf("failed at creating length %d, len = %d\n", exp_len, d->len); 10 | rval = -1; 11 | } 12 | if (d->cap != exp_cap) { 13 | printf("failed at creating cap %d, cap = %d\n", exp_cap, d->cap); 14 | rval = -1; 15 | } 16 | return rval; 17 | } 18 | 19 | int test_makedynarr() { 20 | int rval = 0; 21 | dynarr *d = make_dynarr(3, 4); 22 | rval |= check_dynarr(d, 3, 4); 23 | destroy_dynarr(d); 24 | 25 | d = make_dynarr(5, -1); 26 | rval |= check_dynarr(d, 5, 5); 27 | destroy_dynarr(d); 28 | 29 | d = make_dynarr(0, 0); 30 | rval |= check_dynarr(d, 0, 0); 31 | destroy_dynarr(d); 32 | 33 | return rval; 34 | } 35 | 36 | int test_dynarr_append() { 37 | int rval = 0; 38 | dynarr *d = create_dynarr(); 39 | for (int64_t i = 0; i < 20; i++) { 40 | dynarr_append(d, (void *)i); 41 | if (i != (int64_t)dynarr_at(d, i)) { 42 | printf("dynarr_append: expected val %lu != actual %lu\n", 43 | i, (int64_t)dynarr_at(d, i)); 44 | rval = -1; 45 | } 46 | } 47 | destroy_dynarr(d); 48 | return rval; 49 | } 50 | 51 | int test_dynarr_slice() { 52 | int rval = 0; 53 | 54 | dynarr *d = create_dynarr(); 55 | for (int64_t i = 0; i < 20; i++) { 56 | dynarr_append(d, (void *)i); 57 | } 58 | 59 | dynarr *n = dynarr_slice(d, 10, 15); 60 | for (int64_t i = 0; i < dynarr_len(n); i++) { 61 | if (i + 10 != (int64_t)dynarr_at(n, i)) { 62 | printf("dynarr_slice: expected val %lu != actual %lu\n", 63 | i + 10, (int64_t)dynarr_at(n, i)); 64 | rval = -1; 65 | } 66 | } 67 | destroy_dynarr(d); 68 | destroy_dynarr(n); 69 | 70 | return rval; 71 | } 72 | 73 | // dynarr_at tested with other functions 74 | 75 | int test_dynarr_set() { 76 | int rval = 0; 77 | 78 | dynarr *d = create_dynarr(); 79 | for (int64_t i = 0; i < 20; i++) { 80 | dynarr_append(d, (void *)i); 81 | dynarr_set(d, i, (void *)(i*i)); 82 | 83 | if (i * i != (int64_t)dynarr_at(d, i)) { 84 | printf("dynarr_set: expected val %lu != actual %lu\n", 85 | i * i, (int64_t)dynarr_at(d, i)); 86 | rval = -1; 87 | } 88 | } 89 | destroy_dynarr(d); 90 | 91 | return rval; 92 | } 93 | 94 | int test_dynarr_len() { 95 | int rval = 0; 96 | 97 | dynarr *d0 = create_dynarr(); 98 | for (int64_t i = 0; i < 20; i++) { 99 | dynarr_append(d0, (void *)i); 100 | } 101 | if (20 != dynarr_len(d0)) { 102 | printf("dynarr_len: expected length 20 for d0, actual %d\n", dynarr_len(d0)); 103 | rval = -1; 104 | } 105 | 106 | dynarr *d1 = dynarr_slice(d0, 10, 15); 107 | destroy_dynarr(d0); 108 | if (5 != dynarr_len(d1)) { 109 | printf("dynarr_len: expected length 5 for d1, actual %d\n", dynarr_len(d1)); 110 | rval = -1; 111 | } 112 | destroy_dynarr(d1); 113 | 114 | dynarr *d2 = make_dynarr(5, 10); 115 | if (5 != dynarr_len(d2)) { 116 | printf("dynarr_len: expected length 5 for d2, actual %d\n", dynarr_len(d2)); 117 | rval = -1; 118 | } 119 | destroy_dynarr(d2); 120 | 121 | return rval; 122 | } 123 | 124 | int main(void) { 125 | int rval = 0; 126 | rval |= test_makedynarr(); 127 | rval |= test_dynarr_append(); 128 | rval |= test_dynarr_slice(); 129 | rval |= test_dynarr_set(); 130 | rval |= test_dynarr_len(); 131 | return rval; 132 | } 133 | -------------------------------------------------------------------------------- /c/containers/heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "heap.h" 4 | 5 | struct heap { 6 | void *container; 7 | bool (*less)(void *c, int l, int r); 8 | int (*len)(void *c); 9 | void (*swap)(void *c, int l, int r); 10 | void (*push)(void *c, void *e); 11 | void *(*pop)(void *c); 12 | }; 13 | 14 | Heap create_heap(void) { 15 | Heap newheap = malloc(sizeof(struct heap)); 16 | newheap->container = NULL; 17 | newheap->less = NULL; 18 | newheap->len = NULL; 19 | newheap->swap = NULL; 20 | newheap->push = NULL; 21 | newheap->pop = NULL; 22 | return newheap; 23 | } 24 | 25 | void destroy_heap(Heap h) { 26 | free(h); 27 | } 28 | 29 | void set_heap_container(Heap h, void *container) { 30 | h->container = container; 31 | } 32 | void set_heap_lessfunc(Heap h, bool (*less)(void*, int, int)) { 33 | h->less = less; 34 | } 35 | void set_heap_lenfunc(Heap h, int (*len)(void*)) { 36 | h->len = len; 37 | } 38 | void set_heap_swapfunc(Heap h, void (*swap)(void*, int, int)) { 39 | h->swap = swap; 40 | } 41 | void set_heap_pushfunc(Heap h, void (*push)(void*, void*)) { 42 | h->push = push; 43 | } 44 | void set_heap_popfunc(Heap h, void *(*pop)(void*)) { 45 | h->pop = pop; 46 | } 47 | 48 | static inline int parent(int i) { 49 | return (i - 1) / 2; 50 | } 51 | static inline int lchild(int i) { 52 | return i * 2 + 1; 53 | } 54 | static inline int rchild(int i) { 55 | return i * 2 + 2; 56 | } 57 | 58 | static void shuffleUp(Heap h, int elem) { 59 | while (true) { 60 | int p = parent(elem); 61 | if (p == elem || !h->less(h->container, elem, p)) { 62 | break; 63 | } 64 | h->swap(h->container, p, elem); 65 | elem = p; 66 | } 67 | } 68 | 69 | static void shuffleDown(Heap h, int elem, int len) { 70 | while (true) { 71 | int minchild = lchild(elem); 72 | if (minchild >= len) { 73 | return; 74 | } 75 | int r = rchild(elem); 76 | if (r < len && h->less(h->container, r, minchild)) { 77 | minchild = r; 78 | } 79 | if (!h->less(h->container, minchild, elem)) { 80 | return; 81 | } 82 | h->swap(h->container, minchild, elem); 83 | elem = minchild; 84 | } 85 | } 86 | 87 | void heap_push(Heap h, void *elem) { 88 | h->push(h->container, elem); 89 | shuffleUp(h, h->len(h->container)-1); 90 | } 91 | 92 | void *heap_pop(Heap h) { 93 | return heap_delete(h, 0); 94 | } 95 | 96 | void *heap_delete(Heap h, int elem) { 97 | int n = h->len(h->container) - 1; 98 | if (n != elem) { 99 | h->swap(h->container, n, elem); 100 | shuffleDown(h, elem, n); 101 | shuffleUp(h, elem); 102 | } 103 | return h->pop(h->container); 104 | } 105 | 106 | void heapify(Heap h) { 107 | int n = h->len(h->container); 108 | for (int i = n / 2 - 1; i >= 0; i--) { 109 | shuffleDown(h, i, n); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /c/containers/heap.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_HEAP_C 2 | #define TWMB_HEAP_C 3 | 4 | #include 5 | 6 | // A Heap defines an interface for using heap functions. 7 | // To use a Heap, first call create_heap followed by the 8 | // set functions. After that, either call heapify on your 9 | // heap that has existing elements in the container or use 10 | // the heap normally. 11 | typedef struct heap *Heap; 12 | 13 | // Pushes an element onto the heap. 14 | void heap_push(Heap h, void *elem); 15 | // Pops and returns an element from the heap. 16 | void *heap_pop(Heap h); 17 | // Removes and returns the element at the specified index. 18 | void *heap_delete(Heap h, int elem); 19 | 20 | // Creates and returns an empty heap. 21 | // Initialize it with the set_heap functions before using the heap. 22 | Heap create_heap(void); 23 | // Creates a heap out of an unordered container. 24 | void heapify(Heap h); 25 | // Destroys the heap. 26 | void destroy_heap(Heap h); 27 | 28 | // Sets the abstract collection that the heap will use. 29 | void set_heap_container(Heap h, void *container); 30 | // Less compares two elements in the collection. 31 | void set_heap_lessfunc(Heap h, bool (*less)(void *container, int left, int right)); 32 | // Len returns the length of the collection. 33 | void set_heap_lenfunc(Heap h, int (*len)(void *container)); 34 | // Swap swaps two elements in the collection. 35 | void set_heap_swapfunc(Heap h, void (*swap)(void *container, int left, int right)); 36 | // Push adds an element to the end of the collection. 37 | void set_heap_pushfunc(Heap h, void (*push)(void *container, void *elem)); 38 | // Pop removes and returns the element from the end of the collection. 39 | void set_heap_popfunc(Heap h, void *(*pop)(void *container)); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /c/containers/heap_testspecial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "heap.c" 5 | #include "dynamic_array.h" 6 | 7 | // ******* functions for int[5] array ******** 8 | bool ints_less(void *c, int l, int r) { 9 | int *a = c; 10 | return a[l] < a[r]; 11 | } 12 | int ints_len(void *container) { 13 | return 15; 14 | } 15 | void ints_swap(void *container, int left, int right) { 16 | if (left != right) { 17 | int *d = container; 18 | d[left] ^= d[right]; 19 | d[right] ^= d[left]; 20 | d[left] ^= d[right]; 21 | } 22 | } 23 | // ******* functions for dynamic array ******** 24 | bool dynarr_less(void *container, int left, int right) { 25 | dynarr **d = container; 26 | return dynarr_at(*d, left) < dynarr_at(*d, right); 27 | } 28 | int dynarr_lenfunc(void *container) { 29 | return dynarr_len(*(dynarr **)container); 30 | } 31 | void dynarr_swap(void *container, int left, int right) { 32 | if (left != right) { 33 | dynarr **d = container; 34 | dynarr_set(*d, left, (void *)((int64_t)dynarr_at(*d, left) ^ (int64_t)dynarr_at(*d, right))); 35 | dynarr_set(*d, right,(void *)((int64_t)dynarr_at(*d, left) ^ (int64_t)dynarr_at(*d, right))); 36 | dynarr_set(*d, left, (void *)((int64_t)dynarr_at(*d, left) ^ (int64_t)dynarr_at(*d, right))); 37 | } 38 | } 39 | void dynarr_push(void *d, void *elem) { 40 | dynarr_append(*(dynarr **)d, elem); 41 | } 42 | void *dynarr_pop(void *container) { 43 | dynarr **d = container; 44 | void *end = dynarr_at(*d, dynarr_len(*d) - 1); 45 | dynarr *n = dynarr_slice(*d, 0, dynarr_len(*d) - 1); 46 | destroy_dynarr(*d); 47 | *d = n; 48 | return end; 49 | } 50 | // ******* ********* *** ******* ***** ******** 51 | 52 | Heap myheap; 53 | 54 | struct indexcalc { 55 | int in, want; 56 | }; 57 | 58 | int check_valid_intheap(int *array, int current, int len) { 59 | int rval = 0; 60 | int lc = lchild(current); 61 | int rc = rchild(current); 62 | 63 | if (lc < len) { 64 | if (array[lc] < array[current]) { 65 | printf("array left child %d < parent %d\n", array[lc], array[current]); 66 | printf("["); 67 | for (int i = 0; i < len; i++) { 68 | printf("%d ", array[i]); 69 | } 70 | printf("]\n"); 71 | return -1; 72 | } 73 | rval |= check_valid_intheap(array, lc, len); 74 | } 75 | if (rc < len) { 76 | if (array[rc] < array[current]) { 77 | printf("array right child %d < parent %d\n", array[rc], array[current]); 78 | printf("["); 79 | for (int i = 0; i < len; i++) { 80 | printf("%d ", array[i]); 81 | } 82 | printf("]\n"); 83 | return -1; 84 | } 85 | rval |= check_valid_intheap(array, rc, len); 86 | } 87 | return rval; 88 | } 89 | 90 | int check_valid_dynarr_heap(dynarr *d, int current, int len) { 91 | int rval = 0; 92 | int lc = lchild(current); 93 | int rc = rchild(current); 94 | 95 | if (lc < len) { 96 | if (dynarr_at(d, lc) < dynarr_at(d, current)) { 97 | printf("dynarr left child %lu < parent %lu\n", (int64_t)dynarr_at(d, lc), (int64_t)dynarr_at(d, current)); 98 | printf("["); 99 | for (int i = 0; i < len; i++) { 100 | printf("%lu ", (int64_t)dynarr_at(d, i)); 101 | } 102 | printf("]\n"); 103 | return -1; 104 | } 105 | rval |= check_valid_dynarr_heap(d, lc, len); 106 | } 107 | if (rc < len) { 108 | if (dynarr_at(d, rc) < dynarr_at(d, current)) { 109 | printf("dynarr right child %lu < parent %lu\n", (int64_t)dynarr_at(d, rc), (int64_t)dynarr_at(d, current)); 110 | printf("["); 111 | for (int i = 0; i < len; i++) { 112 | printf("%lu ", (int64_t)dynarr_at(d, i)); 113 | } 114 | printf("]\n"); 115 | return -1; 116 | } 117 | rval |= check_valid_dynarr_heap(d, rc, len); 118 | } 119 | return rval; 120 | } 121 | 122 | int test_parent(void) { 123 | struct indexcalc tests[] = { 124 | {.in = 0, .want = 0}, 125 | {.in = 1, .want = 0}, // lchild 126 | {.in = 2, .want = 0}, // rchild 127 | {.in = 7, .want = 3}, // lchild 128 | {.in = 8, .want = 3}, // rchild 129 | }; 130 | 131 | for (int i = 0; i < sizeof(tests)/sizeof(struct indexcalc); i++) { 132 | if (parent(tests[i].in) != tests[i].want) { 133 | printf("heapstatic: parent failed for input %d, returned %d, expected %d\n", tests[i].in, parent(tests[i].in), tests[i].want); 134 | return -1; 135 | } 136 | } 137 | return 0; 138 | } 139 | 140 | int test_lchild(void) { 141 | struct indexcalc tests[] = { 142 | {.in = 0, .want = 1}, 143 | {.in = 3, .want = 7}, // lchild 144 | }; 145 | 146 | for (int i = 0; i < sizeof(tests)/sizeof(struct indexcalc); i++) { 147 | if (lchild(tests[i].in) != tests[i].want) { 148 | printf("heapstatic: lchild failed for input %d, returned %d, expected %d\n", tests[i].in, lchild(tests[i].in), tests[i].want); 149 | return -1; 150 | } 151 | } 152 | return 0; 153 | } 154 | 155 | int test_rchild(void) { 156 | struct indexcalc tests[] = { 157 | {.in = 0, .want = 2}, 158 | {.in = 3, .want = 8}, // rchild 159 | }; 160 | 161 | for (int i = 0; i < sizeof(tests)/sizeof(struct indexcalc); i++) { 162 | if (rchild(tests[i].in) != tests[i].want) { 163 | printf("heapstatic: rchild failed for input %d, returned %d, expected %d\n", tests[i].in, rchild(tests[i].in), tests[i].want); 164 | return -1; 165 | } 166 | } 167 | return 0; 168 | } 169 | 170 | int test_shuffleUp(void) { 171 | int rval = 0; 172 | 173 | int container1[5] = { 1, 2, 3, 4, 0 }; 174 | int container2[5] = { 4, 3, 2, 1, 0 }; 175 | int container3[5] = { 0, 1, 2, 3, 4 }; 176 | 177 | set_heap_container(myheap, &container1); 178 | shuffleUp(myheap, 4); 179 | rval |= check_valid_intheap(container1, 0, 5); 180 | 181 | set_heap_container(myheap, &container2); 182 | for (int i = 0; i < 5; i++) { 183 | shuffleUp(myheap, i); 184 | } 185 | rval |= check_valid_intheap(container2, 0, 5); 186 | 187 | set_heap_container(myheap, &container3); 188 | for (int i = 0; i < 5; i++) { 189 | shuffleUp(myheap, i); 190 | } 191 | rval |= check_valid_intheap(container3, 0, 5); 192 | 193 | return rval; 194 | } 195 | 196 | int test_shuffleDown(void) { 197 | int rval = 0; 198 | 199 | int container4[5] = { 4, 0, 1, 2, 3 }; 200 | int container5[5] = { 0, 4, 1, 2, 3 }; 201 | int container6[5] = { 0, 1, 2, 3, 4 }; 202 | 203 | set_heap_container(myheap, &container4); 204 | shuffleDown(myheap, 0, 5); 205 | rval |= check_valid_intheap(container4, 0, 5); 206 | 207 | set_heap_container(myheap, &container5); 208 | shuffleDown(myheap, 1, 5); 209 | rval |= check_valid_intheap(container5, 0, 5); 210 | 211 | set_heap_container(myheap, &container6); 212 | for (int i = 0; i < 5; i++) { 213 | shuffleDown(myheap, i, 5); 214 | } 215 | rval |= check_valid_intheap(container6, 0, 5); 216 | 217 | return rval; 218 | } 219 | 220 | int test_heap_push(void) { 221 | dynarr *d = create_dynarr(); 222 | set_heap_container(myheap, &d); 223 | for (int64_t i = 0; i < 20; i++) { 224 | heap_push(myheap, (void *)i); 225 | } 226 | int rval = check_valid_dynarr_heap(d, 0, dynarr_len(d)); 227 | destroy_dynarr(d); 228 | return rval; 229 | } 230 | 231 | int test_heap_pop(void) { 232 | int rval = 0; 233 | dynarr *d = create_dynarr(); 234 | set_heap_container(myheap, &d); 235 | for (int64_t i = 0; i < 20; i++) { 236 | heap_push(myheap, (void *)i); 237 | } 238 | for (int64_t i = 0; i < 20; i++) { 239 | int64_t r = (int64_t)heap_pop(myheap); 240 | rval |= check_valid_dynarr_heap(d, 0, dynarr_len(d)); 241 | if (r != i) { 242 | printf("heap_pop: expected %lu, got %lu\n", i, r); 243 | rval |= -1; 244 | } 245 | } 246 | destroy_dynarr(d); 247 | return rval; 248 | } 249 | 250 | int test_heap_delete(void) { 251 | int rval = 0; 252 | dynarr *d = create_dynarr(); 253 | set_heap_container(myheap, &d); 254 | for (int64_t i = 0; i < 20; i++) { 255 | heap_push(myheap, (void *)i); 256 | } 257 | for (int64_t i = 0; i < 20; i++) { 258 | int64_t r = (int64_t)heap_delete(myheap, 0); 259 | rval |= check_valid_dynarr_heap(d, 0, dynarr_len(d)); 260 | if (r != i) { 261 | printf("heap_pop: expected %lu, got %lu\n", i, r); 262 | rval = -1; 263 | } 264 | } 265 | destroy_dynarr(d); 266 | return rval; 267 | } 268 | 269 | int test_heapify(void) { 270 | int rval = 0; 271 | dynarr *d = create_dynarr(); 272 | set_heap_container(myheap, &d); 273 | for (int64_t i = 0; i < 20; i++) { 274 | dynarr_append(d, (void *)i); 275 | } 276 | heapify(myheap); 277 | rval |= check_valid_dynarr_heap(d, 0, dynarr_len(d)); 278 | destroy_dynarr(d); 279 | return rval; 280 | } 281 | 282 | 283 | int main(void) { 284 | int rval = 0; 285 | rval |= test_parent(); 286 | rval |= test_lchild(); 287 | rval |= test_rchild(); 288 | // testing shuffles with a int[5], only len, less and swap called 289 | myheap = create_heap(); 290 | set_heap_lessfunc(myheap, &ints_less); 291 | set_heap_lenfunc(myheap, &ints_len); 292 | set_heap_swapfunc(myheap, &ints_swap); 293 | 294 | rval |= test_shuffleUp(); 295 | rval |= test_shuffleDown(); 296 | 297 | set_heap_lessfunc(myheap, &dynarr_less); 298 | set_heap_lenfunc(myheap, &dynarr_lenfunc); 299 | set_heap_swapfunc(myheap, &dynarr_swap); 300 | set_heap_pushfunc(myheap, &dynarr_push); 301 | set_heap_popfunc(myheap, &dynarr_pop); 302 | 303 | rval |= test_heap_push(); 304 | rval |= test_heap_pop(); 305 | rval |= test_heap_delete(); 306 | 307 | rval |= test_heapify(); 308 | 309 | destroy_heap(myheap); 310 | 311 | return rval; 312 | } 313 | -------------------------------------------------------------------------------- /c/containers/linked_list.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "linked_list.h" 4 | 5 | linked_list new_linked_list() { 6 | linked_list l; 7 | l.head = NULL; 8 | return l; 9 | } 10 | 11 | void delete_ll(linked_list *list) { 12 | while(list->head != NULL) { 13 | item *next = list->head->next; 14 | free(list->head); 15 | list->head = next; 16 | } 17 | } 18 | 19 | // Adds a new item to the linked list 20 | void push_ll(linked_list *list, void *data) { 21 | item *new_item = (item *)malloc(sizeof(item)); 22 | if (!new_item) { 23 | return; 24 | } 25 | new_item->data = data; 26 | new_item->next = list->head; 27 | list->head = new_item; 28 | } 29 | 30 | // Removes and returns pointer to the data at the front of the list 31 | void *pop_ll(linked_list *list) { 32 | if (list->head == NULL) { 33 | return NULL; 34 | } 35 | void *r_val = list->head->data; 36 | item *next = list->head->next; 37 | free(list->head); 38 | list->head = next; 39 | return r_val; 40 | } 41 | 42 | void *remove_element_ll(linked_list *list, void *data) { 43 | if (list->head == NULL) { 44 | return NULL; 45 | } 46 | item *trail = list->head; 47 | item *deleteme = list->head->next; 48 | while (deleteme != NULL && deleteme->data != data) { 49 | trail = deleteme; 50 | deleteme = deleteme->next; 51 | } 52 | trail->next = deleteme->next; 53 | void *r_val = deleteme->data; 54 | free(deleteme); 55 | return r_val; 56 | } 57 | -------------------------------------------------------------------------------- /c/containers/linked_list.h: -------------------------------------------------------------------------------- 1 | #ifndef GITHUB_TWMB_C_LL 2 | #define GITHUB_TWMB_C_LL 3 | 4 | // Push, remove 5 | typedef struct item { 6 | struct item *next; 7 | void *data; 8 | } item; 9 | 10 | typedef struct { 11 | item *head; 12 | } linked_list; 13 | 14 | linked_list new_linked_list(); 15 | void delete_ll(linked_list *list); 16 | void push_ll(linked_list *list, void *data); 17 | void *pop_ll(linked_list *list); 18 | void *remove_element_ll(linked_list *list, void *data); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /c/containers/linked_list_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "linked_list.h" 5 | 6 | int main() { 7 | linked_list mine = new_linked_list(); 8 | int failed = 0; 9 | push_ll(&mine, (void *)3); 10 | push_ll(&mine, (void *)2); 11 | push_ll(&mine, (void *)2); 12 | remove_element_ll(&mine, (void *)2); 13 | delete_ll(&mine); 14 | if (mine.head != NULL) { 15 | printf("linked list head not null after trying to delete all elements\n"); 16 | failed = -1; 17 | } 18 | return failed; 19 | } 20 | -------------------------------------------------------------------------------- /c/containers/makefile: -------------------------------------------------------------------------------- 1 | ALL_TEST_SRC := $(shell find . -name '*_testspecial.c') 2 | ALL_TEST_EXE := ${ALL_TEST_SRC:.c=} 3 | 4 | CFLAGS := -g -Wall -pedantic -std=c11 5 | 6 | special: heap_testspecial dynamic_array_testspecial 7 | 8 | test: special 9 | @for test in ${ALL_TEST_EXE} ; \ 10 | do \ 11 | echo testing $${test} ; \ 12 | ./$${test} ; \ 13 | if [ $$? -ne 0 ] ; \ 14 | then \ 15 | /bin/echo -e "\e[01;31mfailed\e[m" ;\ 16 | else \ 17 | echo passed ; \ 18 | fi ; \ 19 | echo ; \ 20 | done 21 | 22 | heap_testspecial: heap_testspecial.c heap.c dynamic_array.c heap.h dynamic_array.h 23 | clang ${CFLAGS} -o $@ heap_testspecial.c dynamic_array.c -lpthread 24 | 25 | dynamic_array_testspecial: dynamic_array_testspecial.c dynamic_array.c dynamic_array.h 26 | clang ${CFLAGS} -o $@ dynamic_array_testspecial.c -lpthread 27 | 28 | clean: 29 | rm -f heap_testspecial dynamic_array_testspecial 30 | -------------------------------------------------------------------------------- /c/makefile: -------------------------------------------------------------------------------- 1 | ALL_TEST_SRC := $(shell find . -name '*_test.c') 2 | ALL_TEST_EXE := ${ALL_TEST_SRC:.c=} 3 | 4 | ALL_TESTSTATIC_SRC := $(shell find . -name '*_teststatic.c') 5 | ALL_TESTSTATIC_EXE := ${ALL_TESTSTATIC_SRC:.c=} 6 | 7 | CFLAGS := -Wall -pedantic -std=c11 8 | 9 | all: ${ALL_TEST_EXE} ${ALL_TESTSTATIC_EXE} 10 | 11 | clean: 12 | rm -f ${ALL_TEST_EXE} ${ALL_TESTSTATIC_EXE} 13 | 14 | test: all 15 | @for test in ${ALL_TEST_EXE} ${ALL_TESTSTATIC_EXE};\ 16 | do \ 17 | echo testing $${test} ; \ 18 | ./$${test} ; \ 19 | if [ $$? -ne 0 ] ; \ 20 | then \ 21 | /bin/echo -e "\e[01;31mfailed\e[m" ; \ 22 | else \ 23 | echo passed ; \ 24 | fi ; \ 25 | echo ; \ 26 | done 27 | 28 | %_test: %_test.c %.c %.h 29 | clang ${CFLAGS} -o $@ $(filter %_test.c %.c, $^) 30 | 31 | %_teststatic: %_teststatic.c %.c %.h 32 | clang ${CFLAGS} -o $@ $(filter %_teststatic.c, $^) 33 | -------------------------------------------------------------------------------- /c/sort/insertion_sort.c: -------------------------------------------------------------------------------- 1 | #include "insertion_sort.h" 2 | 3 | void insertion_sort(int *arr, int start, int length) { 4 | int current, i; 5 | for (int j = start+1; j < length; j++) { 6 | current = arr[j]; // save copy of number we are inserting 7 | for (i = j-1; i >= start && arr[i] > current; i--) { 8 | if (arr[i] > current) { 9 | arr[i+1]=arr[i]; // slide larger left int right one 10 | } 11 | } 12 | arr[i] = current; // insert into position 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /c/sort/insertion_sort.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_INSERTION_SORT 2 | #define TWMB_INSERTION_SORT 3 | 4 | // pointer to array to sort, start index, length 5 | void insertion_sort(int *arr, int start, int length); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /c/sort/insertion_sort_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "insertion_sort.h" 4 | 5 | int main(int argc, char **argv) { 6 | int failed = 0; 7 | int us1[1] = {-1}; 8 | int us2[5] = {4,3,2,1,2}; 9 | insertion_sort(us1, 0, 0); 10 | insertion_sort(us2, 0, 5); 11 | int prev = us2[0]; 12 | for (int i = 0; i < 5; i++) { 13 | if (us2[i] < prev) { 14 | printf("us2 error: index %d, val %d > index %d, val %d\n", i, us2[i], i-1, prev); 15 | failed = -1; 16 | } 17 | } 18 | return failed; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /c/sort/merge_sort.c: -------------------------------------------------------------------------------- 1 | #include "merge_sort.h" 2 | 3 | typedef struct { 4 | int start; 5 | int end; 6 | } merge_segment; 7 | 8 | // combines the left and right segments from scrambled into sorted 9 | // sort from start bounds to end bounds into sorted, then copy 10 | // correct positions back into scrambled (this could be improved, obviously) 11 | void merge_combine(int *scrambled, int *sorted, 12 | merge_segment l, merge_segment r) { 13 | int li=l.start, ri=r.start, ci=l.start; // left start always < right start 14 | while (li < l.end && ri < r.end) { 15 | if (scrambled[li] < scrambled[ri]) { 16 | sorted[ci++] = scrambled[li++]; 17 | } else { 18 | sorted[ci++] = scrambled[ri++]; 19 | } 20 | } 21 | while (li < l.end) { 22 | sorted[ci++]=scrambled[li++]; 23 | } 24 | while (ri < r.end) { 25 | sorted[ci++]=scrambled[ri++]; 26 | } 27 | for (ci = l.start; ci < r.end; ci++) { 28 | scrambled[ci] = sorted[ci]; 29 | } 30 | } 31 | 32 | // scrambled needs to be sorted, sorted is the target int array 33 | merge_segment merge_sort_impl(int *scrambled, int *sorted, int from, int to) { 34 | if (to-1 > from) { 35 | merge_segment left = merge_sort_impl(scrambled, sorted, from, (to+from)/2); 36 | merge_segment right = merge_sort_impl(scrambled, sorted, (to+from)/2, to); 37 | merge_combine(scrambled, sorted, left, right); 38 | } 39 | merge_segment n = {from,to}; 40 | return n; 41 | } 42 | 43 | void merge_sort(int *scrambled, int from, int to){ 44 | int sorter[to-from]; 45 | merge_sort_impl(scrambled, sorter, from, to); 46 | } 47 | -------------------------------------------------------------------------------- /c/sort/merge_sort.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_MERGE_SORT 2 | #define TWMB_MERGE_SORT 3 | 4 | void merge_sort(int *scrambled, int from, int to); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /c/sort/merge_sort_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "merge_sort.h" 4 | 5 | int main(int argv, char **argc) { 6 | int failed = 0; 7 | int us1[1] = {-1}; 8 | int us2[5] = {4,3,2,1,2}; 9 | merge_sort(us1, 0, 1); 10 | merge_sort(us2, 0, 5); 11 | int prev = us2[0]; 12 | for (int i = 0; i < 5; i++) { 13 | if (us2[i] < prev) { 14 | printf("us2 error: index %d, val %d > index %d, val %d\n", i, us2[i], i-1, prev); 15 | failed = -1; 16 | } 17 | } 18 | return failed; 19 | } 20 | -------------------------------------------------------------------------------- /c/sort/quicksort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "quicksort.h" 5 | 6 | // XOR swap algorithm 7 | static void swap(int *left, int *right) { 8 | if (left != right) { 9 | *left ^= *right; 10 | *right ^= *left; 11 | *left ^= *right; 12 | } 13 | } 14 | 15 | // http://biobio.loc.edu/chu/web/Courses/COSI216/median3.htm 16 | // see link for explanation 17 | // TODO: change to use bubblesort, median of median of threes like 18 | // http://golang.org/src/pkg/sort/sort.go?s=4433:4458#L182 19 | static int median_of_three_ints(int *array, int len) { 20 | len--; 21 | int indices[3] = {0, len/2, len}; 22 | int small = array[0], large = array[len/2], final = array[len]; 23 | if (small > large) { 24 | swap(&small, &large); 25 | swap(&indices[0], &indices[1]); 26 | } 27 | if (final < small) { 28 | return indices[0]; 29 | } 30 | if (final > large) { 31 | return indices[1]; 32 | } 33 | return indices[2]; 34 | } 35 | 36 | // Performs the quicksort algorithm assuming the pivot 37 | // is at the end. It returns the index of the pivot after 38 | // sorting. 39 | static int do_quicksort(int *array, size_t len) { 40 | int lessBarrier = 1; 41 | for (int i = 1; i < len; i++) { 42 | if (array[i] < array[0]) { 43 | swap(&array[i], &array[lessBarrier]); 44 | lessBarrier++; 45 | } 46 | } 47 | swap(&array[0], &array[lessBarrier-1]); 48 | return lessBarrier-1; 49 | } 50 | 51 | void quicksort_ints(int *array, size_t nmemb) { 52 | // Tail call quicksort 53 | while (nmemb > 1) { 54 | int pivotIndex = median_of_three_ints(array, nmemb); 55 | swap(&array[pivotIndex], &array[0]); 56 | pivotIndex = do_quicksort(array, nmemb); 57 | quicksort_ints(&array[pivotIndex+1], nmemb - 1 - pivotIndex); 58 | nmemb = pivotIndex; 59 | } 60 | } 61 | 62 | // http://biobio.loc.edu/chu/web/Courses/COSI216/median3.htm 63 | // see link for explanation 64 | //static int median_of_three(void *array, int len, (*less)(void *left, void *right)) { 65 | // len--; 66 | // bool swapped = false; 67 | // int small = indices[0], large = indices[1], final = indices[2]; 68 | // if (less(large, small) large) { 69 | // swap(&small, &large); 70 | // swap(&indices[0], &indices[1]); 71 | // } 72 | // if (final < small) { 73 | // return indices[0]; 74 | // } 75 | // if (final > large) { 76 | // return indices[1]; 77 | // } 78 | // return indices[2]; 79 | //} 80 | // 81 | //void quicksort(void *array, 82 | // bool (*less)(void *left, void *right), 83 | // void (*swap)(void *left, void *right), 84 | // int (*len)(void *array)) { 85 | // while (len(array) > 0) { 86 | // int pivotIndedx = median_of_three(array, len(array)); 87 | // 88 | // } 89 | //} 90 | // 91 | -------------------------------------------------------------------------------- /c/sort/quicksort.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_QUICKSORT 2 | #define TWMB_QUICKSORT 3 | 4 | #include 5 | 6 | // Runs quicksort on an array of ints of length len. 7 | // Uses median of three for choosing the pivot. 8 | void quicksort_ints(int *array, size_t nmemb); 9 | 10 | // TODO: implement 11 | // Runs quicksort on a generic array of elements. 12 | // It requires three function pointers to operate 13 | // on this array. 14 | //void quicksort(void *array, 15 | // // takes a left and right element and returns 16 | // // if the left is smaller than the right 17 | // bool (*less)(void *left, void *right), 18 | // // takes a left and right element and swaps them 19 | // void (*swap)(void *left, void *right), 20 | // // returns the length of the array 21 | // int (*len)(void)); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /c/sort/quicksort_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "quicksort.h" 5 | 6 | struct test { 7 | int *in, *want, sizes; 8 | }; 9 | 10 | bool intsEqual(int *left, int *right, int len) { 11 | for (int i = 0; i < len; i++) { 12 | if (left[i] != right[i]) { 13 | return false; 14 | } 15 | } 16 | return true; 17 | } 18 | 19 | int main(void) { 20 | int rVal = 0; 21 | 22 | int t0[] = {0}; 23 | int e0[] = {0}; 24 | int t1[] = {-1,-1,-1}; 25 | int e1[] = {-1,-1,-1}; 26 | int t2[] = {3,2,1,0,-1,-2,-3}; 27 | int e2[] = {-3,-2,-1,0,1,2,3}; 28 | int t3[] = {-3,3,-2,2,-1,1,0}; 29 | int e3[] = {-3,-2,-1,0,1,2,3}; 30 | int t4[] = {5,4,1,7,6}; 31 | int e4[] = {1,4,5,6,7}; 32 | 33 | int testcount = 5; 34 | struct test tests[] = { 35 | {t0, e0, 1}, 36 | {t1, e1, 3}, 37 | {t2, e2, 7}, 38 | {t3, e3, 7}, 39 | {t4, e4, 5}, 40 | }; 41 | 42 | for (int i = 0; i < testcount; i++) { 43 | quicksort_ints(tests[i].in, tests[i].sizes); 44 | if (!intsEqual(tests[i].in, tests[i].want, tests[i].sizes)) { 45 | fprintf(stderr, "quicksort failed, output: "); 46 | for (int j = 0; j < tests[i].sizes; j++) { 47 | fprintf(stderr, "%d ", tests[i].in[j]); 48 | } 49 | fprintf(stderr, "\n"); 50 | rVal = -1; 51 | } 52 | } 53 | return rVal; 54 | } 55 | -------------------------------------------------------------------------------- /c/tree/binary/binary_tree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "binary_tree.h" 6 | 7 | struct binary_tree new_binary_tree() { 8 | struct binary_tree new; 9 | new.root = NULL; 10 | return new; 11 | } 12 | 13 | int push_binary_tree(struct binary_tree *tree, void *data, 14 | bool (*less)(void *left_data, void *right_data)) { 15 | struct node *currentParent = tree->root; 16 | struct node *current = tree->root; 17 | while (current != NULL) { 18 | if (less(data, current->data)) { 19 | currentParent = current; 20 | current = current->lchild; 21 | } else { 22 | currentParent = current; 23 | current = current->rchild; 24 | } 25 | } 26 | struct node *new_node = (struct node *)malloc(sizeof(struct node)); 27 | if (!new_node) { 28 | return -1; 29 | } 30 | new_node->parent = currentParent; 31 | new_node->data = data; 32 | new_node->lchild = NULL; 33 | new_node->rchild = NULL; 34 | if (currentParent == NULL) { // no root element 35 | tree->root = new_node; 36 | return 0; 37 | } 38 | if (less(new_node->data, currentParent->data)) { 39 | currentParent->lchild = new_node; 40 | } else { 41 | currentParent->rchild = new_node; 42 | } 43 | return 0; 44 | } 45 | 46 | void transplant(struct node *replace, struct node *replacement) { 47 | if (replace->parent == NULL) { 48 | // do nothing 49 | } else if (replace == replace->parent->lchild) { 50 | replace->parent->lchild = replacement; 51 | } else { 52 | replace->parent->rchild = replacement; 53 | } 54 | if (replacement != NULL) { 55 | replacement->parent = replace->parent; 56 | } 57 | replace->parent = NULL; 58 | replace->lchild = NULL; 59 | replace->rchild = NULL; 60 | return; 61 | } 62 | 63 | struct node *minimum(struct node *node) { 64 | if (node == NULL) { 65 | return NULL; 66 | } 67 | struct node *minimum = node; 68 | while (minimum->lchild != NULL) { 69 | minimum = minimum->lchild; 70 | } 71 | return minimum; 72 | } 73 | 74 | struct node *successor(struct node *node) { 75 | if (node == NULL) { 76 | return NULL; 77 | } 78 | if (node->rchild != NULL) { 79 | return minimum(node->rchild); 80 | } 81 | return node->parent; // may be null 82 | } 83 | 84 | void *delete_node_binary_tree(struct node **p_deletenode) { 85 | if (p_deletenode == NULL || *p_deletenode == NULL) { 86 | return NULL; 87 | } 88 | struct node *deletenode = *p_deletenode; 89 | void *data = deletenode->data; 90 | if (deletenode->lchild == NULL) { 91 | *p_deletenode = deletenode->rchild; 92 | transplant(deletenode, deletenode->rchild); 93 | free(deletenode); 94 | return data; 95 | } else if (deletenode->rchild == NULL) { 96 | *p_deletenode = deletenode->lchild; 97 | transplant(deletenode, deletenode->lchild); 98 | free(deletenode); 99 | return data; 100 | } else { 101 | // left and right are not nil 102 | // find successor in right child to replace here 103 | struct node *suc_node = successor(deletenode); // will not be null 104 | if (suc_node != deletenode->rchild) { 105 | transplant(suc_node, suc_node->rchild); 106 | deletenode->rchild->parent = suc_node; 107 | suc_node->rchild = deletenode->rchild; 108 | } 109 | suc_node->lchild = deletenode->lchild; 110 | deletenode->lchild->parent = suc_node; 111 | transplant(deletenode, suc_node); 112 | free(deletenode); 113 | *p_deletenode = suc_node; 114 | return data; 115 | } 116 | } 117 | 118 | void walk_node(struct node *node, void (*print_node)(void *data)) { 119 | if (node != NULL) { 120 | walk_node(node->lchild, print_node); 121 | print_node(node->data); 122 | walk_node(node->rchild, print_node); 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /c/tree/binary/binary_tree.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_BIN_TREE 2 | #define TWMB_BIN_TREE 3 | 4 | #include 5 | #include 6 | 7 | struct node { 8 | struct node *lchild; 9 | struct node *rchild; 10 | struct node *parent; 11 | void *data; 12 | }; 13 | 14 | struct binary_tree { 15 | struct node *root; 16 | }; 17 | 18 | // Returns a new binary tree. 19 | struct binary_tree new_binary_tree(); 20 | // Adds data to a binary tree using the passed in less function. 21 | int push_binary_tree(struct binary_tree *tree, void *data, 22 | bool (*less)(void *left, void *right)); 23 | // Walks the binary tree under the input node in order, calling 24 | // the print function for each node's data element. 25 | void walk_node(struct node *node, void (*print_node)(void *data)); 26 | // Deletes a node from a binary tree and returns a void * to the 27 | // data that was attached to it. 28 | void *delete_node_binary_tree(struct node **deletenode); 29 | // Finds the minimum node in the tree starting from the input node. 30 | struct node *minimum(struct node *node); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /c/tree/binary/binary_tree_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "binary_tree.h" 6 | 7 | bool less(void *left_data, void *right_data) { 8 | if ((int64_t)left_data < (int64_t)right_data) { 9 | return true; 10 | } 11 | return false; 12 | } 13 | 14 | void print_node(void *data) { 15 | printf("%lu ", (int64_t)data); 16 | } 17 | 18 | int main() { 19 | // dirty repetitive tests, but thorough 20 | int failed = 0; 21 | struct binary_tree tree = new_binary_tree(); // tree of ints 22 | push_binary_tree(&tree, (void *)1, &less); 23 | push_binary_tree(&tree, (void *)0, &less); 24 | push_binary_tree(&tree, (void *)1, &less); 25 | push_binary_tree(&tree, (void *)3, &less); // 1 26 | push_binary_tree(&tree, (void *)4, &less); // 0 1 27 | push_binary_tree(&tree, (void *)2, &less); // 3 28 | push_binary_tree(&tree, (void *)1, &less); // 2 4 29 | push_binary_tree(&tree, (void *)2, &less); // 1 2 3 9 30 | push_binary_tree(&tree, (void *)3, &less); // 8 11 31 | push_binary_tree(&tree, (void *)9, &less); // 32 | push_binary_tree(&tree, (void *)11, &less); 33 | push_binary_tree(&tree, (void *)8, &less); 34 | void *returned; 35 | returned = delete_node_binary_tree(&tree.root); // 1 36 | if ((int64_t) returned != 1) { 37 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 1); 38 | failed = -1; 39 | } 40 | returned = delete_node_binary_tree(&tree.root); // 1 41 | if ((int64_t) returned != 1) { 42 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 1); 43 | failed = -1; 44 | } 45 | returned = delete_node_binary_tree(&tree.root); // 1 46 | if ((int64_t) returned != 1) { 47 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 1); 48 | failed = -1; 49 | } 50 | returned = delete_node_binary_tree(&tree.root); // 2 51 | if ((int64_t) returned != 2) { 52 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 2); 53 | failed = -1; 54 | } 55 | returned = delete_node_binary_tree(&tree.root); // 2 56 | if ((int64_t) returned != 2) { 57 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 2); 58 | failed = -1; 59 | } 60 | returned = delete_node_binary_tree(&tree.root); // 3 61 | if ((int64_t) returned != 3) { 62 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 3); 63 | failed = -1; 64 | } 65 | returned = delete_node_binary_tree(&tree.root); // 3 66 | if ((int64_t) returned != 3) { 67 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 3); 68 | failed = -1; 69 | } 70 | returned = delete_node_binary_tree(&tree.root); // 4 71 | if ((int64_t) returned != 4) { 72 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 4); 73 | failed = -1; 74 | } 75 | returned = delete_node_binary_tree(&tree.root); // 8 76 | if ((int64_t) returned != 8) { 77 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 8); 78 | failed = -1; 79 | } 80 | returned = delete_node_binary_tree(&tree.root); // 9 81 | if ((int64_t) returned != 9) { 82 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 9); 83 | failed = -1; 84 | } 85 | returned = delete_node_binary_tree(&tree.root); // 11 86 | if ((int64_t) returned != 11) { 87 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 11); 88 | failed = -1; 89 | } 90 | returned = delete_node_binary_tree(&tree.root); // 0 91 | if ((int64_t) returned != 0) { 92 | printf("deleted node value %lu != expected %d\n", (int64_t)returned, 0); 93 | failed = -1; 94 | } 95 | return failed; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /c/various/balanced_parens.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "balanced_parens.h" 4 | 5 | char do_is_balanced(const char **string) { 6 | for (; **string != '\0'; ++*string) { 7 | switch (**string) { 8 | case '(': if (++*string, do_is_balanced(string) != ')') return '('; break; 9 | case '{': if (++*string, do_is_balanced(string) != '}') return '{'; break; 10 | case '[': if (++*string, do_is_balanced(string) != ']') return '['; break; 11 | case ')': 12 | case ']': 13 | case '}': 14 | return **string; 15 | } 16 | } 17 | return **string; 18 | } 19 | 20 | bool is_balanced(const char *string) { 21 | return do_is_balanced(&string) == '\0'; 22 | } 23 | -------------------------------------------------------------------------------- /c/various/balanced_parens.h: -------------------------------------------------------------------------------- 1 | #ifndef BALANCED_PARENS_TWMB 2 | #define BALANCED_PARENS_TWMB 3 | 4 | #include 5 | 6 | // Returns whether or not the input string 7 | // has in order balanced parens (can be '(', '{', or '['). 8 | bool is_balanced(const char *string); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /c/various/balanced_parens_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "balanced_parens.h" 4 | 5 | int main() { 6 | int failed = 0; 7 | 8 | if (!is_balanced("asdf")) { 9 | failed = -1; 10 | printf("failed on input \"asdf\"\n"); 11 | } 12 | if (!is_balanced("({})")) { 13 | failed = -1; 14 | printf("failed on input \"({})\"\n"); 15 | } 16 | char *str = "asdf(asdf{asdf{asdf}asdf[asdf(asdf)]})"; 17 | if (!is_balanced(str)) { 18 | failed = -1; 19 | printf("failed on input \"%s\"\n", str); 20 | } 21 | if (is_balanced("(")) { 22 | failed = -1; 23 | printf("failed on input \"(\"\n"); 24 | } 25 | if (is_balanced("a(sdf])")) { 26 | failed = -1; 27 | printf("failed on input \"a(sdf])\"\n"); 28 | } 29 | return failed; 30 | } 31 | -------------------------------------------------------------------------------- /c/various/combination_letters.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "combination_letters.h" 4 | 5 | void do_combine_letters(const char *letters, char *printer, int printer_len, int letters_len, int start_letter) { 6 | for (int i = start_letter; i < letters_len; i++) { 7 | printer[printer_len] = letters[i]; 8 | printf("%s\n", printer); 9 | if (i < letters_len-1) { 10 | do_combine_letters(letters, printer, printer_len+1, letters_len, i+1); 11 | } 12 | printer[printer_len] = '\0'; 13 | } 14 | } 15 | 16 | void combine_letters(const char *letters, int len) { 17 | char printer[len]; 18 | for (int i = 0; i < len; i++) { 19 | printer[i] = '\0'; 20 | } 21 | do_combine_letters(letters, printer, 0, len, 0); 22 | } 23 | 24 | 25 | -------------------------------------------------------------------------------- /c/various/combination_letters.h: -------------------------------------------------------------------------------- 1 | #ifndef COMBINE_LETTERS_H 2 | #define COMBINE_LETTERS_H 3 | 4 | // Prints all combinations of a string. 5 | void combine_letters(const char *letters, int len); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /c/various/combination_letters_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "combination_letters.h" 6 | 7 | #define BUFLEN 100 8 | 9 | int main() { 10 | int failed = 0; 11 | 12 | char buffer[] = {[BUFLEN] = '\0'}; 13 | int pipefds[2]; 14 | int stdoutfd = dup(STDOUT_FILENO); 15 | if (pipe(pipefds) != 0) { 16 | return -1; 17 | } 18 | dup2(pipefds[1], STDOUT_FILENO); 19 | close(pipefds[1]); 20 | 21 | combine_letters("wxyz", 4); 22 | fflush(stdout); 23 | char *expect = "w\nwx\nwxy\nwxyz\nwxz\nwy\nwyz\nwz\nx\nxy\nxyz\nxz\ny\nyz\nz\n"; 24 | 25 | read(pipefds[0], buffer, BUFLEN); 26 | if (strcmp(buffer, expect)) { 27 | failed = -1; 28 | printf("error, buffer %s not equal to '%s'\n", buffer, expect); 29 | } 30 | 31 | dup2(stdoutfd, STDOUT_FILENO); 32 | return failed; 33 | } 34 | 35 | -------------------------------------------------------------------------------- /c/various/max_subarray.c: -------------------------------------------------------------------------------- 1 | #include "max_subarray.h" 2 | 3 | max_info max_subarray_crossing(int *arr, int l, int r) { 4 | int m = (r + l) / 2; 5 | int li = m-1, lsum = arr[m-1], nsum = arr[m-1]; 6 | for (int n = li-1; n >= l; n--) { 7 | nsum += arr[n]; 8 | if (nsum > lsum) { 9 | lsum = nsum; 10 | li = n; 11 | } 12 | } 13 | int ri = m, rsum = arr[m]; 14 | nsum = arr[m]; 15 | for (int n = ri+1; n < r; n++) { 16 | nsum += arr[n]; 17 | if (nsum > rsum) { 18 | rsum = nsum; 19 | ri = n; 20 | } 21 | } 22 | max_info best = {li, ++ri, lsum + rsum}; 23 | return best; 24 | } 25 | 26 | max_info max_subarray_recursive(int *arr, int l, int r) { 27 | if (r - l <= 1) { 28 | max_info max = {l, r, 0}; 29 | if (r == l) { 30 | return max; 31 | } 32 | max.sum = arr[l]; 33 | return max; 34 | } else { 35 | max_info max_left = max_subarray_recursive(arr, l, (r+l)/2); 36 | max_info max_right = max_subarray_recursive(arr, (r+l)/2, r); 37 | max_info max_crossing = max_subarray_crossing(arr, l, r); 38 | if (max_left.sum > max_right.sum && max_left.sum > max_crossing.sum) { 39 | return max_left; 40 | } else if (max_right.sum > max_left.sum && max_right.sum > max_crossing.sum) { 41 | return max_right; 42 | } else { 43 | return max_crossing; 44 | } 45 | } 46 | } 47 | 48 | // maximum subarray from left to (not through) right 49 | max_info max_subarray(int *arr, int l, int r) { 50 | max_info max_now = {l, l, 0}; 51 | if (r - l <= 1) { 52 | max_now.r = r; 53 | if (r == l) { 54 | return max_now; 55 | } 56 | max_now.sum = arr[l]; 57 | return max_now; 58 | } 59 | max_now.sum = arr[l]; 60 | max_info max_so_far = {l, l, arr[l]}; 61 | for (l += 1; l < r; l++) { 62 | if (max_now.sum + arr[l] > arr[l]) { // yet net higher than start 63 | max_now.r = l; 64 | max_now.sum += arr[l]; 65 | } else { // new lowest low 66 | max_now.l = l; 67 | max_now.r = l; 68 | max_now.sum = arr[l]; 69 | } 70 | if (max_now.sum > max_so_far.sum) { 71 | max_so_far = max_now; 72 | } 73 | } 74 | max_so_far.r++; // increment to one past the actual right index 75 | return max_so_far; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /c/various/max_subarray.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_MAX_SUBARRAY 2 | #define TWMB_MAX_SUBARRAY 3 | 4 | typedef struct { 5 | int l; 6 | int r; 7 | int sum; 8 | } max_info; 9 | 10 | max_info max_subarray_recursive(int *arr, int l, int r); 11 | max_info max_subarray(int *arr, int l, int r); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /c/various/max_subarray_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "max_subarray.h" 4 | 5 | typedef struct { 6 | int *In; 7 | int InStart, InEnd, WantLI, WantRI, WantSum; 8 | } test_vals; 9 | 10 | int main(int argc, char **argv) { 11 | int failed = 0; // false 12 | 13 | int a0[1] = {-1}; 14 | int a1[4] = {3,-1,-1,4}; // whole thing 15 | int a2[4] = {-1,1,1,-1}; // crossing middle 16 | int a3[4] = {-1,-2,1,2}; // right side 17 | int a4[4] = {1,2,-3,-4}; // left side 18 | int a5[6] = {1,-2,-3,5,6,7}; // 6 length, right side 19 | int a6[5] = {1,-2,-3,5,6}; //5 length, right side 20 | 21 | int test_count = 10; 22 | test_vals tests[10] = { // test count 23 | {a0, 0, 1, 0, 1, -1}, // array, start, end, want li, want ri, want sum 24 | {a1, 0, 4, 0, 4, 5}, 25 | {a2, 0, 4, 1, 3, 2}, 26 | {a3, 0, 4, 2, 4, 3}, 27 | {a4, 0, 4, 0, 2, 3}, 28 | {a5, 0, 6, 3, 6, 18}, 29 | {a6, 0, 5, 3, 5, 11}, 30 | {a6, 0, 3, 0, 1, 1}, 31 | {a6, 3, 5, 3, 5, 11}, 32 | {a6, 1, 3, 1, 2, -2}, 33 | }; 34 | 35 | for (int i = 0; i < test_count; i++) { 36 | max_info info = max_subarray(tests[i].In, tests[i].InStart, tests[i].InEnd); 37 | if (info.l != tests[i].WantLI || 38 | info.r != tests[i].WantRI || 39 | info.sum != tests[i].WantSum) { 40 | printf("failure on %d, ret info: (%d, %d, %d), expected: (%d, %d, %d)\n", 41 | i, info.l, info.r, info.sum, 42 | tests[i].WantLI, tests[i].WantRI, tests[i].WantSum); 43 | failed = 1; // true 44 | } 45 | } 46 | 47 | if (failed) { 48 | printf("max_subarray failed iterative tests\n"); 49 | } 50 | 51 | int failed2 = 0; 52 | 53 | for (int i = 0; i < test_count; i++) { 54 | max_info info = max_subarray_recursive(tests[i].In, tests[i].InStart, tests[i].InEnd); 55 | if (info.l != tests[i].WantLI || 56 | info.r != tests[i].WantRI || 57 | info.sum != tests[i].WantSum) { 58 | printf("failure on %d, ret info: (%d, %d, %d), expected: (%d, %d, %d)\n", 59 | i, info.l, info.r, info.sum, 60 | tests[i].WantLI, tests[i].WantRI, tests[i].WantSum); 61 | failed2 = 1; // true 62 | } 63 | } 64 | 65 | if (failed2) { 66 | printf("max subarray failed recursive tests\n"); 67 | } 68 | if (failed || failed2) { 69 | return -1; 70 | } 71 | return 0; 72 | } 73 | 74 | -------------------------------------------------------------------------------- /c/various/permute_letters.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "permute_letters.h" 6 | 7 | void do_permute_letters(const char *letters, int len, bool *used, char *buffer, int position) { 8 | if (position == len) { 9 | printf("%s\n", buffer); 10 | return; 11 | } 12 | for (int i = 0; i < len; i++) { 13 | if (!used[i]) { 14 | buffer[position] = letters[i]; 15 | used[i] = true; 16 | do_permute_letters(letters, len, used, buffer, position+1); 17 | used[i] = false; 18 | } 19 | } 20 | } 21 | 22 | void permute_letters(const char *letters, int len) { 23 | char buffer[len+1]; 24 | buffer[len] = '\0'; 25 | strcpy(buffer, letters); 26 | bool used[len]; 27 | for (int i = 0; i < len; i++) { 28 | used[i] = false; 29 | } 30 | do_permute_letters(letters, len, used, buffer, 0); 31 | } 32 | -------------------------------------------------------------------------------- /c/various/permute_letters.h: -------------------------------------------------------------------------------- 1 | #ifndef PERMUTE_LETTERS_H 2 | #define PERMUTE_LETTERS_H 3 | 4 | // Prints all permutations of a string. 5 | void permute_letters(const char *letters, int len); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /c/various/permute_letters_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "permute_letters.h" 6 | 7 | #define BUFLEN 40 8 | 9 | int main() { 10 | int failed = 0; 11 | 12 | char buffer[] = {[BUFLEN] = '\0'}; 13 | int pipefds[2]; 14 | int stdoutfd = dup(STDOUT_FILENO); 15 | if (pipe(pipefds) != 0) { 16 | return -1; 17 | } 18 | dup2(pipefds[1], STDOUT_FILENO); 19 | close(pipefds[1]); 20 | 21 | permute_letters("hat", 3); 22 | // Expect 23 | //`hat 24 | //`hta 25 | //`aht 26 | //`ath 27 | //`tha 28 | //`tah 29 | //` 30 | fflush(stdout); 31 | 32 | read(pipefds[0], buffer, BUFLEN); 33 | if (strcmp(buffer, "hat\nhta\naht\nath\ntha\ntah\n")) { 34 | failed = -1; 35 | printf("error, buffer %s not equal to 'hat\nhta\naht\nath\ntha\ntah\n'", buffer); 36 | } 37 | 38 | dup2(stdoutfd, STDOUT_FILENO); 39 | return failed; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /c/various/reverse_words.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void reverse_string(char *string, int start, int end) { 4 | char tmp; 5 | while (end > start) { 6 | tmp = string[start]; 7 | string[start] = string[end]; 8 | string[end] = tmp; 9 | end--; start++; 10 | } 11 | } 12 | 13 | void reverse_words(char line[]) { 14 | int len = strlen(line); 15 | if (len < 1) { 16 | return; 17 | } 18 | if (line[len-1] == '\n') { 19 | reverse_string(line,0,len-2); 20 | } else { 21 | reverse_string(line,0,len-1); 22 | } 23 | int wordstart = 0, wordend = 0; 24 | for (; line[wordend] != '\0' && line[wordend] != '\n'; wordend++) { 25 | if(line[wordend] == ' ') { 26 | reverse_string(line, wordstart, wordend-1); 27 | wordstart = wordend + 1; 28 | } 29 | } 30 | reverse_string(line, wordstart, wordend-1); 31 | } 32 | -------------------------------------------------------------------------------- /c/various/reverse_words.h: -------------------------------------------------------------------------------- 1 | #ifndef TWMB_REVERSE_WORDS 2 | #define TWMB_REVERSE_WORDS 3 | 4 | void reverse_words(char *words); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /c/various/reverse_words_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "reverse_words.h" 5 | 6 | int main(int argc, char **argv) { 7 | // char line[80]; 8 | // fgets(line, sizeof(line), stdin); 9 | int failed = 0; 10 | char line[] = "hello this is easy\n"; 11 | reverse_words(line); 12 | if (strcmp(line, "easy is this hello\n")) { 13 | failed = -1; 14 | printf("error, line %s not equal to 'easy is this hello\n'", line); 15 | } 16 | line[0] = '\0'; 17 | reverse_words(line); 18 | if (strcmp(line, "")) { 19 | failed = -1; 20 | printf("error, line %s not equal to ''", line); 21 | } 22 | line[0] = '\n'; 23 | line[1] = '\0'; 24 | reverse_words(line); 25 | if (strcmp(line, "\n")) { 26 | failed = -1; 27 | printf("error, line %s not equal to '\n'", line); 28 | } 29 | return failed; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /c/various/tele_words.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "tele_words.h" 4 | 5 | //struct stringNums { 6 | // char **strings; 7 | // int len; 8 | //}; 9 | // 10 | //struct stringNums phone_number_letters(const char *number, int len) { 11 | // struct stringNums r; 12 | // if (len == 1) { 13 | // if (number[0] == '0' || number[0] == '1') { 14 | // r.len = 1; 15 | // r.strings = malloc(sizeof(char *)); 16 | // r.strings[0] = malloc(sizeof(char)); 17 | // r.strings[0][0] = get_char_key(number[0] - '0', 0); 18 | // } else { 19 | // r.len = 3; 20 | // r.strings = malloc(3 * sizeof(char *)); 21 | // for (int i = 0; i < 3; i++) { 22 | // r.strings[i] = malloc(sizeof(char)); 23 | // r.strings[i][0] = get_char_key(number[0] - '0', i); 24 | // } 25 | // } 26 | // } else { 27 | // struct stringNums substrings = first_phone_number_letters(number + 1, len - 1); 28 | // if (number[0] == '0' || number[0] == '1') { 29 | // r.len = substrings.len; 30 | // r.strings = malloc(substrings.len * sizeof(char *)); 31 | // for (int j = 0; j < substrings.len; j++) { 32 | // r.strings[j] = malloc(len * sizeof(char)); 33 | // strcpy(r.strings[j] + 1, substrings.strings[j]); 34 | // r.strings[j][0] = get_char_key(number[0] - '0', 0); 35 | // } 36 | // } else { 37 | // r.len = 3 * substrings.len; 38 | // r.strings = malloc(3 * substrings.len * sizeof(char *)); 39 | // for (int i = 0; i < 3; i++) { 40 | // for (int j = 0; j < substrings.len; j++) { 41 | // r.strings[i*substrings.len + j] = malloc(len * sizeof(char)); 42 | // strcpy(r.strings[i*substrings.len + j] + 1, substrings.strings[j]); 43 | // r.strings[i*substrings.len + j][0] = get_char_key(number[0] - '0', i); 44 | // } 45 | // } 46 | // } 47 | // for (int i = 0; i < substrings.len; i++) { 48 | // free(substrings.strings[i]); 49 | // } 50 | // free(substrings.strings); 51 | // } 52 | // return r; 53 | //} 54 | 55 | char get_char_key(int number, int place) { 56 | switch (number) { 57 | case 0: 58 | return 'Y'; break; 59 | case 1: 60 | return 'Z'; break; 61 | default: 62 | return 'A' + (number - 2) * 3 + place; 63 | } 64 | } 65 | 66 | void do_phone_number_letters(char *number, int len, char *buffer) { 67 | if (*buffer == '\0') { 68 | printf("%s\n", buffer - len); 69 | return; 70 | } 71 | for (int i = 0; i < 3; i++) { 72 | buffer[0] = get_char_key(number[0] - '0', i); 73 | do_phone_number_letters(number + 1, len, buffer + 1); 74 | if (number[0] == '0' || number[0] == '1') { 75 | return; 76 | } 77 | } 78 | } 79 | 80 | void phone_number_letters(char *number, int len) { 81 | char buffer[len + 1]; 82 | for (int i = 0; i < len; i++) { 83 | // initialize to not be null 84 | buffer[i] = 'a'; 85 | } 86 | buffer[len] = '\0'; 87 | do_phone_number_letters(number, len, buffer); 88 | } 89 | -------------------------------------------------------------------------------- /c/various/tele_words.h: -------------------------------------------------------------------------------- 1 | #ifndef TELE_WORDS_TWMB 2 | #define TELE_WORDS_TWMB 3 | 4 | // Assuming numbers contains only ascii digits, 5 | // this function cycles through and prints all 6 | // variations of letters that the numbers could 7 | // be. 0=Y, 1=Z, 2=A,B,C, 3=etc. 8 | void phone_number_letters(char *numbers, int len); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /c/various/tele_words_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "tele_words.h" 6 | 7 | #define BUFLEN 20 8 | 9 | int main() { 10 | int failed = 0; 11 | 12 | char buffer[] = {[BUFLEN] = '\0'}; 13 | int pipefds[2]; 14 | int stdoutfd = dup(STDOUT_FILENO); 15 | if (pipe(pipefds) != 0) { 16 | return -1; 17 | } 18 | dup2(pipefds[1], STDOUT_FILENO); 19 | close(pipefds[1]); 20 | 21 | phone_number_letters("012", 3); 22 | // Expect 23 | //`YZA 24 | //`YZB 25 | //`YZC 26 | //` 27 | fflush(stdout); 28 | 29 | read(pipefds[0], buffer, BUFLEN); 30 | if (strcmp(buffer, "YZA\nYZB\nYZC\n")) { 31 | failed = -1; 32 | printf("error, buffer %s not equal to 'YZA\nYZB\nYZC\n'", buffer); 33 | } 34 | 35 | dup2(stdoutfd, STDOUT_FILENO); 36 | return failed; 37 | } 38 | -------------------------------------------------------------------------------- /go/graph/example_mst_test.go: -------------------------------------------------------------------------------- 1 | package graph_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/twmb/algoimpl/go/graph" 6 | ) 7 | 8 | func ExampleGraph_MinimumSpanningTree() { 9 | g := graph.New(graph.Undirected) 10 | nodes := make(map[rune]graph.Node, 0) 11 | nodes['a'] = g.MakeNode() 12 | nodes['b'] = g.MakeNode() 13 | nodes['c'] = g.MakeNode() 14 | nodes['d'] = g.MakeNode() 15 | nodes['e'] = g.MakeNode() 16 | nodes['f'] = g.MakeNode() 17 | nodes['g'] = g.MakeNode() 18 | nodes['h'] = g.MakeNode() 19 | nodes['i'] = g.MakeNode() 20 | g.MakeEdgeWeight(nodes['a'], nodes['b'], 4) 21 | g.MakeEdgeWeight(nodes['a'], nodes['h'], 8) 22 | g.MakeEdgeWeight(nodes['b'], nodes['c'], 8) 23 | g.MakeEdgeWeight(nodes['b'], nodes['h'], 11) 24 | g.MakeEdgeWeight(nodes['c'], nodes['d'], 7) 25 | g.MakeEdgeWeight(nodes['c'], nodes['f'], 4) 26 | g.MakeEdgeWeight(nodes['c'], nodes['i'], 2) 27 | g.MakeEdgeWeight(nodes['d'], nodes['e'], 9) 28 | g.MakeEdgeWeight(nodes['d'], nodes['f'], 14) 29 | g.MakeEdgeWeight(nodes['e'], nodes['f'], 10) 30 | g.MakeEdgeWeight(nodes['f'], nodes['g'], 2) 31 | g.MakeEdgeWeight(nodes['g'], nodes['h'], 1) 32 | g.MakeEdgeWeight(nodes['g'], nodes['i'], 6) 33 | g.MakeEdgeWeight(nodes['h'], nodes['i'], 7) 34 | mst := g.MinimumSpanningTree() 35 | weightSum := 0 36 | for i := range mst { 37 | weightSum += mst[i].Weight 38 | } 39 | fmt.Println(weightSum) 40 | // Output: 37 41 | } 42 | -------------------------------------------------------------------------------- /go/graph/example_topsort_test.go: -------------------------------------------------------------------------------- 1 | package graph_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/twmb/algoimpl/go/graph" 6 | ) 7 | 8 | func ExampleGraph_TopologicalSort() { 9 | g := graph.New(graph.Directed) 10 | 11 | clothes := make(map[string]graph.Node, 0) 12 | // Make a mapping from strings to a node 13 | clothes["shirt"] = g.MakeNode() 14 | clothes["tie"] = g.MakeNode() 15 | clothes["jacket"] = g.MakeNode() 16 | clothes["belt"] = g.MakeNode() 17 | clothes["watch"] = g.MakeNode() 18 | clothes["undershorts"] = g.MakeNode() 19 | clothes["pants"] = g.MakeNode() 20 | clothes["shoes"] = g.MakeNode() 21 | clothes["socks"] = g.MakeNode() 22 | // Make references back to the string values 23 | for key, node := range clothes { 24 | *node.Value = key 25 | } 26 | // Connect the elements 27 | g.MakeEdge(clothes["shirt"], clothes["tie"]) 28 | g.MakeEdge(clothes["tie"], clothes["jacket"]) 29 | g.MakeEdge(clothes["shirt"], clothes["belt"]) 30 | g.MakeEdge(clothes["belt"], clothes["jacket"]) 31 | g.MakeEdge(clothes["undershorts"], clothes["pants"]) 32 | g.MakeEdge(clothes["undershorts"], clothes["shoes"]) 33 | g.MakeEdge(clothes["pants"], clothes["belt"]) 34 | g.MakeEdge(clothes["pants"], clothes["shoes"]) 35 | g.MakeEdge(clothes["socks"], clothes["shoes"]) 36 | sorted := g.TopologicalSort() 37 | for i := range sorted { 38 | fmt.Println(*sorted[i].Value) 39 | } 40 | // Output: 41 | // socks 42 | // undershorts 43 | // pants 44 | // shoes 45 | // watch 46 | // shirt 47 | // belt 48 | // tie 49 | // jacket 50 | } 51 | -------------------------------------------------------------------------------- /go/graph/functions.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "errors" 5 | "github.com/twmb/algoimpl/go/graph/lite" 6 | "math/rand" 7 | "sort" 8 | "sync" 9 | ) 10 | 11 | const ( 12 | dequeued = ^(1<<31 - 1) 13 | unseen = 0 14 | seen = 1 15 | ) 16 | 17 | // O(V + E). It does not matter to traverse back 18 | // on a bidirectional edge, because any vertex dfs is 19 | // recursing on is marked as visited and won't be visited 20 | // again anyway. 21 | func (g *Graph) dfs(node *node, finishList *[]Node) { 22 | node.state = seen 23 | for _, edge := range node.edges { 24 | if edge.end.state == unseen { 25 | edge.end.parent = node 26 | g.dfs(edge.end, finishList) 27 | } 28 | } 29 | *finishList = append(*finishList, node.container) 30 | } 31 | 32 | func (g *Graph) dfsReversedEdges(node *node, finishList *[]Node) { 33 | node.state = seen 34 | for _, edge := range node.reversedEdges { 35 | if edge.end.state == unseen { 36 | edge.end.parent = node 37 | g.dfsReversedEdges(edge.end, finishList) 38 | } 39 | } 40 | *finishList = append(*finishList, node.container) 41 | } 42 | 43 | func (g *Graph) bfs(n *node, finishList *[]Node) { 44 | queue := make([]*node, 0, len(n.edges)) 45 | queue = append(queue, n) 46 | for i := 0; i < len(queue); i++ { 47 | node := queue[i] 48 | node.state = seen 49 | for _, edge := range node.edges { 50 | if edge.end.state == unseen { 51 | edge.end.state = seen 52 | queue = append(queue, edge.end) 53 | } 54 | } 55 | } 56 | *finishList = make([]Node, 0, len(queue)) 57 | for i := range queue { 58 | *finishList = append(*finishList, queue[i].container) 59 | } 60 | } 61 | 62 | // TopologicalSort topoligically sorts a directed acyclic graph. 63 | // If the graph is cyclic, the sort order will change 64 | // based on which node the sort starts on. 65 | // 66 | // The StronglyConnectedComponents function can be used to determine if a graph has cycles. 67 | func (g *Graph) TopologicalSort() []Node { 68 | if g.Kind == Undirected { 69 | return nil 70 | } 71 | // init states 72 | for i := range g.nodes { 73 | g.nodes[i].state = unseen 74 | } 75 | sorted := make([]Node, 0, len(g.nodes)) 76 | // sort preorder (first jacket, then shirt) 77 | for _, node := range g.nodes { 78 | if node.state == unseen { 79 | g.dfs(node, &sorted) 80 | } 81 | } 82 | // now make post order for correct sort (jacket follows shirt). O(V) 83 | length := len(sorted) 84 | for i := 0; i < length/2; i++ { 85 | sorted[i], sorted[length-i-1] = sorted[length-i-1], sorted[i] 86 | } 87 | return sorted 88 | } 89 | 90 | // Reverse returns reversed copy of the directed graph g. 91 | // This function can be used to copy an undirected graph. 92 | func (g *Graph) Reverse() *Graph { 93 | reversed := New(Directed) 94 | if g.Kind == Undirected { 95 | reversed = New(Undirected) 96 | } 97 | // O(V) 98 | for _ = range g.nodes { 99 | reversed.MakeNode() 100 | } 101 | // O(V + E) 102 | for _, node := range g.nodes { 103 | for _, edge := range node.edges { 104 | reversed.MakeEdge(reversed.nodes[edge.end.index].container, 105 | reversed.nodes[node.index].container) 106 | } 107 | } 108 | return reversed 109 | } 110 | 111 | // StronglyConnectedComponents returns a slice of strongly connected nodes in a directed graph. 112 | // If used on an undirected graph, this function returns distinct connected components. 113 | func (g *Graph) StronglyConnectedComponents() [][]Node { 114 | if g.Kind == Undirected { 115 | return g.sccUndirected() 116 | } 117 | return g.sccDirected() 118 | } 119 | 120 | // the connected components algorithm for an undirected graph 121 | func (g *Graph) sccUndirected() [][]Node { 122 | components := make([][]Node, 0) 123 | for _, node := range g.nodes { 124 | if node.state == unseen { 125 | component := make([]Node, 0) 126 | g.bfs(node, &component) 127 | components = append(components, component) 128 | } 129 | } 130 | return components 131 | } 132 | 133 | // the Strongly Connected Components algorithm for a directed graph 134 | func (g *Graph) sccDirected() [][]Node { 135 | components := make([][]Node, 0) 136 | finishOrder := g.TopologicalSort() 137 | for i := range finishOrder { 138 | finishOrder[i].node.state = unseen 139 | } 140 | for _, sink := range finishOrder { 141 | if g.nodes[sink.node.index].state == unseen { 142 | component := make([]Node, 0) 143 | g.dfsReversedEdges(g.nodes[sink.node.index], &component) 144 | components = append(components, component) 145 | } 146 | } 147 | return components 148 | } 149 | 150 | // RandMinimumCut runs Kargers algorithm to find a random minimum cut 151 | // on the graph. If iterations is < 1, this will return an empty slice. 152 | // Otherwise, it returns a slice of the edges crossing the best minimum 153 | // cut found in any iteration. Call rand.Seed() before using this function. 154 | // 155 | // This function takes a number of iterations to start concurrently. If 156 | // concurrent is <= 1, it will run one iteration at a time. 157 | // 158 | // If the graph is Directed, this will return a cut of edges in both directions. 159 | // If the graph is Undirected, this will return a proper min cut. 160 | func (g *Graph) RandMinimumCut(iterations, concurrent int) []Edge { 161 | var mutex sync.Mutex 162 | doneChan := make(chan struct{}, iterations) 163 | if concurrent < 1 { 164 | concurrent = 1 165 | } 166 | sem := make(chan struct{}, concurrent) 167 | for i := 0; i < concurrent; i++ { 168 | sem <- struct{}{} 169 | } 170 | // make a lite slice of the edges 171 | var baseAllEdges []lite.Edge 172 | for n := range g.nodes { 173 | for _, edge := range g.nodes[n].edges { 174 | if g.Kind == Undirected && n < edge.end.index { 175 | continue 176 | } 177 | baseAllEdges = append(baseAllEdges, lite.Edge{Start: n, 178 | End: edge.end.index, S: g.nodes[n], E: edge}) 179 | } 180 | } 181 | 182 | minCutLite := make([]lite.Edge, len(baseAllEdges)) 183 | 184 | for iter := 0; iter < iterations; iter++ { 185 | <-sem 186 | go func() { 187 | nodecount := len(g.nodes) 188 | allEdges := make([]lite.Edge, len(baseAllEdges)) 189 | copy(allEdges, baseAllEdges) 190 | // shuffle for random edge removal order 191 | shuffle(allEdges) 192 | for nodecount > 2 { 193 | // remove first edge, keep the start node, collapse the end node 194 | // anything that points to the collapsing node now points to the keep node 195 | // anything that starts at the collapsing node now starts at the keep node 196 | keep := allEdges[len(allEdges)-1].Start 197 | remove := allEdges[len(allEdges)-1].End 198 | allEdges = allEdges[:len(allEdges)-1] 199 | for e := 0; e < len(allEdges); e++ { 200 | if allEdges[e].Start == remove { 201 | allEdges[e].Start = keep 202 | } 203 | if allEdges[e].End == remove { 204 | allEdges[e].End = keep 205 | } 206 | // remove the edge if it self looped 207 | if allEdges[e].Start == allEdges[e].End { 208 | allEdges[e] = allEdges[len(allEdges)-1] 209 | allEdges = allEdges[:len(allEdges)-1] 210 | e-- 211 | } 212 | } 213 | // every edge removed removes a node 214 | nodecount-- 215 | } 216 | 217 | mutex.Lock() 218 | if iter == 0 || len(allEdges) < len(minCutLite) { 219 | minCutLite = make([]lite.Edge, len(allEdges)) 220 | copy(minCutLite, allEdges) 221 | } 222 | mutex.Unlock() 223 | 224 | doneChan <- struct{}{} 225 | sem <- struct{}{} 226 | }() 227 | } 228 | for iter := 0; iter < iterations; iter++ { 229 | <-doneChan 230 | } 231 | 232 | minCut := make([]Edge, len(minCutLite)) 233 | for i := range minCutLite { 234 | start := minCutLite[i].S.(*node) 235 | edge := minCutLite[i].E.(edge) 236 | minCut[i] = Edge{Weight: edge.weight, Start: start.container, 237 | End: edge.end.container} 238 | } 239 | return minCut 240 | } 241 | 242 | // Fischer-Yates shuffle 243 | func shuffle(edges []lite.Edge) { 244 | for i := len(edges) - 1; i > 0; i-- { 245 | j := rand.Intn(i + 1) 246 | edges[j], edges[i] = edges[i], edges[j] 247 | } 248 | } 249 | 250 | // MinimumSpanningTree will return the edges corresponding to the 251 | // minimum spanning tree in the graph based off of edge weight values. 252 | // This will return nil for a directed graph. 253 | func (g *Graph) MinimumSpanningTree() []Edge { 254 | if g.Kind == Directed { 255 | return nil 256 | } 257 | // create priority queue for vertices 258 | // node.data is the index into the heap 259 | // node.state is the weight of an edge to its parent 260 | nodesBase := nodeSlice(make([]*node, len(g.nodes))) 261 | copy(nodesBase, g.nodes) 262 | for i := range nodesBase { 263 | nodesBase[i].state = 1<<31 - 1 264 | nodesBase[i].data = i 265 | } 266 | nodesBase[0].state = 0 267 | nodesBase[0].parent = nil 268 | nodes := &nodesBase 269 | nodes.heapInit() 270 | 271 | for len(*nodes) > 0 { 272 | min := nodes.pop() 273 | for _, edge := range min.edges { 274 | v := edge.end // get the other side of the edge 275 | if nodes.heapContains(v) && edge.weight < v.state { 276 | v.parent = min 277 | nodes.update(v.data, edge.weight) 278 | } 279 | } 280 | } 281 | 282 | mst := make([]Edge, 0, len(g.nodes)-1) 283 | for _, node := range g.nodes { 284 | if node.parent != nil { 285 | mst = append(mst, Edge{Weight: node.state, 286 | Start: node.container, End: node.parent.container}) 287 | } else { 288 | node.data = 0 289 | } 290 | } 291 | 292 | return mst 293 | } 294 | 295 | // MaxSpacingClustering returns a slice of clusters 296 | // with the distance between the clusters maximized as 297 | // well as the maximized distance between these clusters. 298 | // It takes as input the number of clusters to compute. 299 | func (g *Graph) MaxSpacingClustering(n int) ([][]Node, int, error) { 300 | if n < 1 || n > len(g.nodes) { 301 | return nil, 0, errors.New("MaxSpacingClustering: invalid number of clusters requested") 302 | } 303 | mst := g.MinimumSpanningTree() 304 | sort.Sort(sort.Reverse(edgeSlice(mst))) 305 | distance := 0 306 | 307 | // node.data is a cluster it belongs to 308 | for i := 0; i < n-1; i++ { 309 | // Use the start node: to 'remove' an edge and set 310 | // a leader node to belong to a cluster, start of the edge's parent. 311 | // The only node that will have a nil parent is an end node from MST above. 312 | // This node already automatically belongs to cluster 0. 313 | mst[i].Start.node.parent = nil 314 | mst[i].Start.node.data = i + 1 315 | distance = mst[i].Weight 316 | } 317 | 318 | clusters := make([][]Node, n) 319 | for _, node := range g.nodes { 320 | c := determineCluster(node) 321 | clusters[c] = append(clusters[c], node.container) 322 | } 323 | return clusters, distance, nil 324 | } 325 | 326 | func determineCluster(n *node) int { 327 | // all nodes .data member is set to the dequeued const from MST's .pop(). 328 | // I use the .data member in clustering as the cluster number. 329 | // Thus, if .data == dequeued, then the cluster has not been set yet. 330 | if n.data == dequeued { 331 | n.data = determineCluster(n.parent) 332 | } 333 | return n.data 334 | } 335 | 336 | type edgeSlice []Edge 337 | 338 | func (e edgeSlice) Len() int { 339 | return len(e) 340 | } 341 | func (e edgeSlice) Swap(i, j int) { 342 | e[i], e[j] = e[j], e[i] 343 | } 344 | func (e edgeSlice) Less(i, j int) bool { 345 | return e[i].Weight < e[j].Weight 346 | } 347 | -------------------------------------------------------------------------------- /go/graph/functions_test.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | // RandMinimumCut has been tested in practice (Coursera Algo course 1). If any bugs crop up, email me. 8 | 9 | func BenchmarkTopologicalSort(b *testing.B) { 10 | b.StopTimer() 11 | graph, _ := setupTopologicalSort() 12 | b.StartTimer() 13 | for i := 0; i < b.N; i++ { 14 | graph.TopologicalSort() 15 | } 16 | } 17 | 18 | func TestTopologicalSort(t *testing.T) { 19 | graph, wantOrder := setupTopologicalSort() 20 | result := graph.TopologicalSort() 21 | firstLen := len(result) 22 | result = graph.TopologicalSort() 23 | if len(result) != firstLen { 24 | t.Errorf("topologicalSort 2 times fails") 25 | } 26 | for i := range result { 27 | if result[i] != wantOrder[i] { 28 | t.Errorf("index %v in result != wanted, value: %v, want value: %v", i, result[i], wantOrder[i]) 29 | } 30 | } 31 | } 32 | 33 | func setupTopologicalSort() (*Graph, []Node) { 34 | graph := New(Directed) 35 | nodes := make([]Node, 0) 36 | // create graph on page 613 of CLRS ed. 3 37 | nodes = append(nodes, graph.MakeNode()) // shirt 38 | nodes = append(nodes, graph.MakeNode()) // tie 39 | nodes = append(nodes, graph.MakeNode()) // jacket 40 | nodes = append(nodes, graph.MakeNode()) // belt 41 | nodes = append(nodes, graph.MakeNode()) // watch 42 | nodes = append(nodes, graph.MakeNode()) // undershorts 43 | nodes = append(nodes, graph.MakeNode()) // pants 44 | nodes = append(nodes, graph.MakeNode()) // shoes 45 | nodes = append(nodes, graph.MakeNode()) // socks 46 | graph.MakeEdge(nodes[0], nodes[1]) 47 | graph.MakeEdge(nodes[1], nodes[2]) 48 | graph.MakeEdge(nodes[0], nodes[3]) 49 | graph.MakeEdge(nodes[3], nodes[2]) 50 | graph.MakeEdge(nodes[5], nodes[6]) 51 | graph.MakeEdge(nodes[5], nodes[7]) 52 | graph.MakeEdge(nodes[6], nodes[3]) 53 | graph.MakeEdge(nodes[6], nodes[7]) 54 | graph.MakeEdge(nodes[8], nodes[7]) 55 | wantOrder := make([]Node, len(graph.nodes)) 56 | wantOrder[0] = nodes[8] // socks 57 | wantOrder[1] = nodes[5] // undershorts 58 | wantOrder[2] = nodes[6] // pants 59 | wantOrder[3] = nodes[7] // shoes 60 | wantOrder[4] = nodes[4] // watch 61 | wantOrder[5] = nodes[0] // shirt 62 | wantOrder[6] = nodes[3] // belt 63 | wantOrder[7] = nodes[1] // tie 64 | wantOrder[8] = nodes[2] // jacket 65 | return graph, wantOrder 66 | } 67 | 68 | func TestStronglyConnectedComponents(t *testing.T) { 69 | testSCCDirected(t) 70 | testSCCUndirected(t) 71 | } 72 | 73 | func testSCCDirected(t *testing.T) { 74 | graph, want := setupSCCDirected() 75 | components := graph.StronglyConnectedComponents() 76 | for j := range components { 77 | for i := range want[j] { 78 | if !componentContains(components[j], want[j][i]) { 79 | t.Errorf("component slice %v does not contain want node %v", components[j], want[j][i]) 80 | } 81 | } 82 | } 83 | } 84 | 85 | func testSCCUndirected(t *testing.T) { 86 | g, want := setupSCCUndirected() 87 | components := g.StronglyConnectedComponents() 88 | for j := range components { 89 | for i := range want[j] { 90 | if !componentContains(components[j], want[j][i]) { 91 | t.Errorf("component slice %v does not contain want node %v", components[j], want[j][i]) 92 | } 93 | } 94 | } 95 | } 96 | 97 | func BenchmarkSCCUndirected(b *testing.B) { 98 | b.StopTimer() 99 | graph, _ := setupSCCUndirected() 100 | b.StartTimer() 101 | for i := 0; i < b.N; i++ { 102 | graph.StronglyConnectedComponents() 103 | } 104 | } 105 | 106 | func BenchmarkSCCDirected(b *testing.B) { 107 | b.StopTimer() 108 | graph, _ := setupSCCDirected() 109 | b.StartTimer() 110 | for i := 0; i < b.N; i++ { 111 | graph.StronglyConnectedComponents() 112 | } 113 | } 114 | 115 | func setupSCCDirected() (*Graph, [][]Node) { 116 | graph := New(Directed) 117 | nodes := make([]Node, 0) 118 | // create SCC graph on page 616 of CLRS ed 3 119 | nodes = append(nodes, graph.MakeNode()) //0, c 120 | nodes = append(nodes, graph.MakeNode()) //1, g 121 | nodes = append(nodes, graph.MakeNode()) //2, f 122 | nodes = append(nodes, graph.MakeNode()) //3, h 123 | nodes = append(nodes, graph.MakeNode()) //4, d 124 | nodes = append(nodes, graph.MakeNode()) //5, b 125 | nodes = append(nodes, graph.MakeNode()) //6, e 126 | nodes = append(nodes, graph.MakeNode()) //7, a 127 | graph.MakeEdge(nodes[0], nodes[1]) 128 | graph.MakeEdge(nodes[0], nodes[4]) 129 | graph.MakeEdge(nodes[1], nodes[2]) 130 | graph.MakeEdge(nodes[1], nodes[3]) 131 | graph.MakeEdge(nodes[2], nodes[1]) 132 | graph.MakeEdge(nodes[3], nodes[3]) 133 | graph.MakeEdge(nodes[4], nodes[3]) 134 | graph.MakeEdge(nodes[4], nodes[0]) 135 | graph.MakeEdge(nodes[5], nodes[6]) 136 | graph.MakeEdge(nodes[5], nodes[0]) 137 | graph.MakeEdge(nodes[5], nodes[2]) 138 | graph.MakeEdge(nodes[6], nodes[2]) 139 | graph.MakeEdge(nodes[6], nodes[7]) 140 | graph.MakeEdge(nodes[7], nodes[5]) 141 | want := make([][]Node, 4) 142 | want[0] = make([]Node, 3) 143 | want[1] = make([]Node, 2) 144 | want[2] = make([]Node, 2) 145 | want[3] = make([]Node, 1) 146 | want[0][0] = nodes[6] 147 | want[0][1] = nodes[7] 148 | want[0][2] = nodes[5] 149 | want[1][0] = nodes[0] 150 | want[1][1] = nodes[4] 151 | want[2][0] = nodes[2] 152 | want[2][1] = nodes[1] 153 | want[3][0] = nodes[3] 154 | return graph, want 155 | } 156 | 157 | func setupSCCUndirected() (*Graph, [][]Node) { 158 | g := New(Undirected) 159 | nodes := make([]Node, 0) 160 | nodes = append(nodes, g.MakeNode()) 161 | nodes = append(nodes, g.MakeNode()) 162 | nodes = append(nodes, g.MakeNode()) 163 | nodes = append(nodes, g.MakeNode()) 164 | nodes = append(nodes, g.MakeNode()) 165 | nodes = append(nodes, g.MakeNode()) 166 | nodes = append(nodes, g.MakeNode()) 167 | nodes = append(nodes, g.MakeNode()) 168 | nodes = append(nodes, g.MakeNode()) 169 | nodes = append(nodes, g.MakeNode()) 170 | nodes = append(nodes, g.MakeNode()) 171 | g.MakeEdge(nodes[0], nodes[1]) 172 | g.MakeEdge(nodes[0], nodes[10]) 173 | g.MakeEdge(nodes[2], nodes[3]) // 1: 0--1 2: 2--3 174 | g.MakeEdge(nodes[3], nodes[4]) // | / | 175 | g.MakeEdge(nodes[4], nodes[5]) // 10 5--4 176 | g.MakeEdge(nodes[8], nodes[7]) // 8 177 | g.MakeEdge(nodes[9], nodes[8]) // 3: /|\ 178 | g.MakeEdge(nodes[8], nodes[6]) // / | \ 179 | g.MakeEdge(nodes[10], nodes[1]) // 7 9 6 180 | want := make([][]Node, 3) 181 | want[0] = make([]Node, 3) 182 | want[1] = make([]Node, 4) 183 | want[2] = make([]Node, 4) 184 | want[0][0] = nodes[0] 185 | want[0][1] = nodes[1] 186 | want[0][2] = nodes[10] 187 | want[1][0] = nodes[2] 188 | want[1][1] = nodes[3] 189 | want[1][2] = nodes[4] 190 | want[1][3] = nodes[5] 191 | want[2][0] = nodes[8] 192 | want[2][1] = nodes[7] 193 | want[2][2] = nodes[9] 194 | want[2][3] = nodes[6] 195 | return g, want 196 | } 197 | 198 | func TestMinimumSpanningTree(t *testing.T) { 199 | g := New(Undirected) 200 | nodes := make(map[string]Node, 0) 201 | nodes["a"] = g.MakeNode() 202 | nodes["b"] = g.MakeNode() 203 | nodes["c"] = g.MakeNode() 204 | nodes["d"] = g.MakeNode() 205 | nodes["e"] = g.MakeNode() 206 | nodes["f"] = g.MakeNode() 207 | nodes["g"] = g.MakeNode() 208 | nodes["h"] = g.MakeNode() 209 | nodes["i"] = g.MakeNode() 210 | for key, node := range nodes { 211 | *node.Value = key 212 | } 213 | g.MakeEdgeWeight(nodes["a"], nodes["b"], 4) 214 | g.MakeEdgeWeight(nodes["a"], nodes["h"], 8) 215 | g.MakeEdgeWeight(nodes["b"], nodes["h"], 11) 216 | g.MakeEdgeWeight(nodes["b"], nodes["c"], 8) 217 | g.MakeEdgeWeight(nodes["c"], nodes["i"], 2) 218 | g.MakeEdgeWeight(nodes["c"], nodes["f"], 4) 219 | g.MakeEdgeWeight(nodes["c"], nodes["d"], 7) 220 | g.MakeEdgeWeight(nodes["d"], nodes["e"], 9) 221 | g.MakeEdgeWeight(nodes["d"], nodes["f"], 14) 222 | g.MakeEdgeWeight(nodes["e"], nodes["f"], 10) 223 | g.MakeEdgeWeight(nodes["f"], nodes["g"], 2) 224 | g.MakeEdgeWeight(nodes["g"], nodes["h"], 1) 225 | g.MakeEdgeWeight(nodes["g"], nodes["i"], 6) 226 | g.MakeEdgeWeight(nodes["h"], nodes["i"], 7) 227 | mst := g.MinimumSpanningTree() 228 | mstNodes := make(map[Node]bool, 0) 229 | spanCost := 0 230 | for _, edge := range mst { 231 | if _, exists := mstNodes[edge.Start]; !exists { 232 | mstNodes[edge.Start] = true 233 | } 234 | if _, exists := mstNodes[edge.End]; !exists { 235 | mstNodes[edge.End] = true 236 | } 237 | spanCost += edge.Weight 238 | } 239 | if len(mstNodes) != len(nodes) { // 9 240 | t.Errorf("mst: # of nodes in MST is %v, expected %v", len(mstNodes), len(nodes)) 241 | } 242 | if spanCost != 37 { 243 | t.Errorf("mst: expected MST cost of 37, got %v", spanCost) 244 | } 245 | 246 | } 247 | 248 | func componentContains(component []Node, node Node) bool { 249 | for i := range component { 250 | if component[i].node.index == node.node.index { // for SCC, the nodes will be reversed but the indices will be the same 251 | return true 252 | } 253 | } 254 | return false 255 | } 256 | -------------------------------------------------------------------------------- /go/graph/graph.go: -------------------------------------------------------------------------------- 1 | // Implements an adjacency list graph as a slice of generic nodes 2 | // and includes some useful graph functions. 3 | package graph 4 | 5 | import ( 6 | "errors" 7 | ) 8 | 9 | // Directed or undirected. 10 | type GraphType int 11 | 12 | const ( 13 | Undirected GraphType = iota 14 | Directed 15 | ) 16 | 17 | // Graph is an adjacency slice representation of a graph. Can be directed or undirected. 18 | type Graph struct { 19 | nodes []*node 20 | Kind GraphType 21 | } 22 | 23 | type node struct { 24 | edges []edge 25 | reversedEdges []edge 26 | index int 27 | state int // used for metadata 28 | data int // also used for metadata 29 | parent *node // also used for metadata 30 | container Node // who holds me 31 | } 32 | 33 | // Node connects to a backing node on the graph. It can safely be used in maps. 34 | type Node struct { 35 | // In an effort to prevent access to the actual graph 36 | // and so that the Node type can be used in a map while 37 | // the graph changes metadata, the Node type encapsulates 38 | // a pointer to the actual node data. 39 | node *node 40 | // Value can be used to store information on the caller side. 41 | // Its use is optional. See the Topological Sort example for 42 | // a reason on why to use this pointer. 43 | // The reason it is a pointer is so that graph function calls 44 | // can test for equality on Nodes. The pointer wont change, 45 | // the value it points to will. If the pointer is explicitly changed, 46 | // graph functions that use Nodes will cease to work. 47 | Value *interface{} 48 | } 49 | 50 | type edge struct { 51 | weight int 52 | end *node 53 | } 54 | 55 | // An Edge connects two Nodes in a graph. To modify Weight, use 56 | // the MakeEdgeWeight function. Any local modifications will 57 | // not be seen in the graph. 58 | type Edge struct { 59 | Weight int 60 | Start Node 61 | End Node 62 | } 63 | 64 | // New creates and returns an empty graph. 65 | // If kind is Directed, returns a directed graph. 66 | // This function returns an undirected graph by default. 67 | func New(kind GraphType) *Graph { 68 | g := &Graph{} 69 | if kind == Directed { 70 | g.Kind = Directed 71 | } 72 | return g 73 | } 74 | 75 | // MakeNode creates a node, adds it to the graph and returns the new node. 76 | func (g *Graph) MakeNode() Node { 77 | newNode := &node{index: len(g.nodes)} 78 | newNode.container = Node{node: newNode, Value: new(interface{})} 79 | g.nodes = append(g.nodes, newNode) 80 | return newNode.container 81 | } 82 | 83 | // RemoveNode removes a node from the graph and all edges connected to it. 84 | // This function nils points in the Node structure. If 'remove' is used in 85 | // a map, you must delete the map index first. 86 | func (g *Graph) RemoveNode(remove *Node) { 87 | if remove.node == nil { 88 | return 89 | } 90 | // O(V) 91 | nodeExists := false 92 | // remove all edges that connect from a different node to this one 93 | for _, node := range g.nodes { 94 | if node == remove.node { 95 | nodeExists = true 96 | continue 97 | } 98 | 99 | // O(E) 100 | swapIndex := -1 // index that the edge-to-remove is at 101 | for i := range node.edges { 102 | if node.edges[i].end == remove.node { 103 | swapIndex = i 104 | } 105 | } 106 | if swapIndex > -1 { 107 | swapNRemoveEdge(swapIndex, &node.edges) 108 | } 109 | 110 | // deal with possible reversed edge 111 | swapIndex = -1 112 | for i := range node.reversedEdges { 113 | if node.reversedEdges[i].end == remove.node { 114 | swapIndex = i 115 | } 116 | } 117 | if swapIndex > -1 { 118 | swapNRemoveEdge(swapIndex, &node.reversedEdges) 119 | } 120 | if node.index > remove.node.index { 121 | node.index-- 122 | } 123 | } 124 | if nodeExists { 125 | copy(g.nodes[remove.node.index:], g.nodes[remove.node.index+1:]) 126 | g.nodes = g.nodes[:len(g.nodes)-1] 127 | } 128 | remove.node.parent = nil 129 | remove.node = nil 130 | } 131 | 132 | // MakeEdge calls MakeEdgeWeight with a weight of 0 and returns an error if either of the nodes do not 133 | // belong in the graph. Calling MakeEdge multiple times on the same nodes will not create multiple edges. 134 | func (g *Graph) MakeEdge(from, to Node) error { 135 | return g.MakeEdgeWeight(from, to, 0) 136 | } 137 | 138 | // MakeEdgeWeight creates an edge in the graph with a corresponding weight. 139 | // It returns an error if either of the nodes do not belong in the graph. 140 | // 141 | // Calling MakeEdgeWeight multiple times on the same nodes will not create multiple edges; 142 | // this function will update the weight on the node to the new value. 143 | func (g *Graph) MakeEdgeWeight(from, to Node, weight int) error { 144 | if from.node == nil || from.node.index >= len(g.nodes) || g.nodes[from.node.index] != from.node { 145 | return errors.New("First node in MakeEdge call does not belong to this graph") 146 | } 147 | if to.node == nil || to.node.index >= len(g.nodes) || g.nodes[to.node.index] != to.node { 148 | return errors.New("Second node in MakeEdge call does not belong to this graph") 149 | } 150 | 151 | for i := range from.node.edges { // check if edge already exists 152 | if from.node.edges[i].end == to.node { 153 | from.node.edges[i].weight = weight 154 | 155 | // If the graph is undirected, fix the to node's weight as well 156 | if g.Kind == Undirected && to != from { 157 | for j := range to.node.edges { 158 | if to.node.edges[j].end == from.node { 159 | to.node.edges[j].weight = weight 160 | } 161 | } 162 | } 163 | return nil 164 | } 165 | } 166 | newEdge := edge{weight: weight, end: to.node} 167 | from.node.edges = append(from.node.edges, newEdge) 168 | reversedEdge := edge{weight: weight, end: from.node} // weight for undirected graph only 169 | if g.Kind == Directed { // reversed edges are only used in directed graph algorithms 170 | to.node.reversedEdges = append(to.node.reversedEdges, reversedEdge) 171 | } 172 | if g.Kind == Undirected && to != from { 173 | to.node.edges = append(to.node.edges, reversedEdge) 174 | } 175 | return nil 176 | } 177 | 178 | // RemoveEdge removes edges starting at the from node and ending at the to node. 179 | // If the graph is undirected, RemoveEdge will remove all edges between the nodes. 180 | func (g *Graph) RemoveEdge(from, to Node) { 181 | fromEdges := from.node.edges 182 | toEdges := to.node.edges 183 | toReversedEdges := to.node.reversedEdges 184 | for e := range fromEdges { // fix from->to 185 | if fromEdges[e].end == to.node { 186 | swapNRemoveEdge(e, &fromEdges) 187 | from.node.edges = fromEdges 188 | break 189 | } 190 | } 191 | for e := range toReversedEdges { // fix reversed edges to->from 192 | if toReversedEdges[e].end == from.node { 193 | swapNRemoveEdge(e, &toReversedEdges) 194 | to.node.reversedEdges = toReversedEdges 195 | break 196 | } 197 | } 198 | if g.Kind == Undirected && from.node != to.node { 199 | for e := range toEdges { 200 | if toEdges[e].end == from.node { 201 | swapNRemoveEdge(e, &toEdges) 202 | to.node.edges = toEdges 203 | break 204 | } 205 | } 206 | } 207 | } 208 | 209 | // Neighbors returns a slice of nodes that are reachable from the given node in a graph. 210 | func (g *Graph) Neighbors(n Node) []Node { 211 | neighbors := make([]Node, 0, len(n.node.edges)) 212 | if g.nodes[n.node.index] == n.node { 213 | for _, edge := range n.node.edges { 214 | neighbors = append(neighbors, edge.end.container) 215 | } 216 | } 217 | return neighbors 218 | } 219 | 220 | // Swaps an edge to the end of the edges slice and 'removes' it by reslicing. 221 | func swapNRemoveEdge(remove int, edges *[]edge) { 222 | (*edges)[remove], (*edges)[len(*edges)-1] = (*edges)[len(*edges)-1], (*edges)[remove] 223 | *edges = (*edges)[:len(*edges)-1] 224 | } 225 | -------------------------------------------------------------------------------- /go/graph/graph_heap.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | // Not that I'm falling prey to NIH syndrome, but implementing my own 4 | // heap will speed up MST and Search algorithms because... 5 | // 6 | // Although asserting is relatively cheap, I also need update methods 7 | // and can save time with an explicit update function. 8 | // For reference, with one set of data: 9 | // - using containers/heap took 425 microseconds, 10 | // - switching to my own version of heap took 330 microseconds average, 11 | // - adding an update function takes 255 microseconds average. 12 | // So this was worth it. 13 | 14 | type nodeSlice []*node 15 | 16 | func (n nodeSlice) less(i, j int) bool { 17 | return n[i].state < n[j].state 18 | } 19 | func (n nodeSlice) swap(i, j int) { 20 | n[j].data, n[i].data = n[i].data, n[j].data // swap data containing indices 21 | n[j], n[i] = n[i], n[j] 22 | } 23 | 24 | func (n nodeSlice) shuffleUp(index int) { 25 | for { 26 | parent := (index - 1) / 2 27 | if parent == index || n.less(parent, index) { 28 | break 29 | } 30 | n.swap(parent, index) 31 | index = parent 32 | } 33 | } 34 | 35 | func (n nodeSlice) shuffleDown(elem, to int) { 36 | for { 37 | minchild := elem*2 + 1 // left child: elem * 2 + 1 38 | if minchild >= to { 39 | return 40 | } 41 | rchild := minchild + 1 // left child + 1 42 | if rchild < to && n.less(rchild, minchild) { 43 | minchild = rchild 44 | } 45 | if !n.less(minchild, elem) { 46 | return 47 | } 48 | n.swap(minchild, elem) 49 | elem = minchild 50 | } 51 | } 52 | 53 | func (n nodeSlice) heapInit() { 54 | length := len(n) 55 | for i := length/2 - 1; i >= 0; i-- { 56 | n.shuffleDown(i, length) 57 | } 58 | } 59 | 60 | func (p *nodeSlice) remove(index int) *node { 61 | n := *p 62 | length := len(n) - 1 63 | if length != index { 64 | n.swap(length, index) 65 | n.shuffleDown(index, length) 66 | n.shuffleUp(index) 67 | } 68 | popped := n[length] 69 | popped.data = dequeued 70 | n = n[0:length] 71 | *p = n 72 | return popped 73 | } 74 | 75 | // I don't need shuffleDown call because all updates update to a 76 | // smaller state (for now) 77 | func (n nodeSlice) update(index, newState int) { 78 | n[index].state = newState 79 | n.shuffleUp(index) 80 | } 81 | 82 | func (p *nodeSlice) push(x *node) { 83 | n := *p 84 | x.data = len(n) // index into heap 85 | n = append(n, x) 86 | n.shuffleUp(len(n) - 1) 87 | *p = n 88 | } 89 | 90 | func (p *nodeSlice) pop() *node { 91 | return p.remove(0) 92 | } 93 | func (n nodeSlice) heapContains(node *node) bool { // extend heap interface 94 | return node.data > dequeued 95 | } 96 | -------------------------------------------------------------------------------- /go/graph/graph_test.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func (g *Graph) edgeBack(from, to *node) bool { 8 | for _, v := range from.edges { 9 | if v.end == to { 10 | return true 11 | } 12 | } 13 | return false 14 | } 15 | 16 | func (g *Graph) reversedEdgeBack(from, to *node) bool { 17 | for _, v := range to.reversedEdges { 18 | if v.end == from { 19 | return true 20 | } 21 | } 22 | return false 23 | } 24 | 25 | func nodeSliceContains(slice []Node, node Node) bool { 26 | for i := range slice { 27 | if slice[i].node == node.node { // used for exact node checking as opposed to functions_test componentContains 28 | return true 29 | } 30 | } 31 | return false 32 | } 33 | 34 | func (g *Graph) verify(t *testing.T) { 35 | // over all the nodes 36 | for i, node := range g.nodes { 37 | if node.index != i { 38 | t.Errorf("node's graph index %v != actual graph index %v", node.index, i) 39 | } 40 | // over each edge 41 | for _, edge := range node.edges { 42 | 43 | // check that the graph contains it in the correct position 44 | if edge.end.index >= len(g.nodes) { 45 | t.Errorf("adjacent node end graph index %v >= len(g.nodes)%v", edge.end.index, len(g.nodes)) 46 | } 47 | if g.nodes[edge.end.index] != edge.end { 48 | t.Errorf("adjacent node %p does not belong to the graph on edge %v: should be %p", edge.end, edge, g.nodes[edge.end.index]) 49 | } 50 | // if graph is undirected, check that the to node's reversed edges connects to the from edge 51 | if g.Kind == Directed { 52 | if !g.reversedEdgeBack(node, edge.end) { 53 | t.Errorf("directed graph: node %v has edge to %v, reversedEdges start at end does not have edge back to node", node, edge.end) 54 | } 55 | } 56 | // if the graph is undirected, check that the adjacent node contains the original node back 57 | if g.Kind == Undirected { 58 | if !g.edgeBack(edge.end, node) { 59 | t.Errorf("undirected graph: node %v has adjacent node %v, adjacent node doesn't contain back", node, edge.end) 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | func TestNew(t *testing.T) { 67 | tests := []struct { 68 | InKind GraphType 69 | WantKind GraphType 70 | }{ 71 | {Directed, 1}, 72 | {Undirected, 0}, 73 | {3, 0}, 74 | } 75 | 76 | for _, test := range tests { 77 | got := New(test.InKind) 78 | if got.Kind != test.WantKind { 79 | t.Errorf("Received wrong kind of graph") 80 | } 81 | if len(got.nodes) > 0 { 82 | t.Errorf("Received new graph has nodes %v, shouldn't", got.nodes) 83 | } 84 | } 85 | } 86 | 87 | func TestMakeNode(t *testing.T) { 88 | graph := New(Undirected) 89 | nodes := make(map[Node]int, 0) 90 | for i := 0; i < 10; i++ { 91 | nodes[graph.MakeNode()] = i 92 | } 93 | graph.verify(t) 94 | graph = New(Directed) 95 | nodes = make(map[Node]int, 0) 96 | for i := 0; i < 10; i++ { 97 | nodes[graph.MakeNode()] = i 98 | } 99 | graph.verify(t) 100 | } 101 | 102 | func TestRemoveNode(t *testing.T) { 103 | g := New(Undirected) 104 | nodes := make([]Node, 2) 105 | nodes[0] = g.MakeNode() 106 | nodes[1] = g.MakeNode() 107 | g.MakeEdge(nodes[0], nodes[0]) 108 | g.MakeEdge(nodes[1], nodes[0]) 109 | g.MakeEdge(nodes[0], nodes[1]) 110 | g.MakeEdge(nodes[1], nodes[1]) 111 | g.verify(t) 112 | g.RemoveNode(&nodes[1]) 113 | g.verify(t) 114 | g.RemoveNode(&nodes[1]) 115 | g.verify(t) 116 | g.RemoveNode(&nodes[0]) 117 | g.verify(t) 118 | nodes = make([]Node, 10) 119 | g = New(Directed) 120 | for i := 0; i < 10; i++ { 121 | nodes[i] = g.MakeNode() 122 | } 123 | // connect every node to every node 124 | for j := 0; j < 10; j++ { 125 | for i := 0; i < 10; i++ { 126 | if g.MakeEdge(nodes[i], nodes[j]) != nil { 127 | t.Errorf("could not connect %v, %v", i, j) 128 | } 129 | } 130 | } 131 | g.verify(t) 132 | g.RemoveNode(&nodes[0]) 133 | g.verify(t) 134 | if nodes[0].node != nil { 135 | t.Errorf("Node still has reference to node in graph") 136 | } 137 | g.RemoveNode(&nodes[9]) 138 | g.verify(t) 139 | g.RemoveNode(&nodes[9]) 140 | g.verify(t) 141 | g.RemoveNode(&nodes[0]) 142 | g.verify(t) 143 | g.RemoveNode(&nodes[1]) 144 | g.verify(t) 145 | g.RemoveNode(&nodes[2]) 146 | g.verify(t) 147 | g.RemoveNode(&nodes[3]) 148 | g.verify(t) 149 | g.RemoveNode(&nodes[4]) 150 | g.verify(t) 151 | g.RemoveNode(&nodes[5]) 152 | g.verify(t) 153 | g.RemoveNode(&nodes[6]) 154 | g.verify(t) 155 | g.RemoveNode(&nodes[7]) 156 | g.verify(t) 157 | g.RemoveNode(&nodes[8]) 158 | g.verify(t) 159 | g.RemoveNode(&nodes[9]) 160 | g.verify(t) 161 | } 162 | 163 | func TestMakeEdge(t *testing.T) { 164 | graph := New(Undirected) 165 | mapped := make(map[int]Node, 0) 166 | for i := 0; i < 10; i++ { 167 | mapped[i] = graph.MakeNode() 168 | } 169 | for j := 0; j < 5; j++ { 170 | for i := 0; i < 10; i++ { 171 | graph.MakeEdge(mapped[i], mapped[(i+1+j)%10]) 172 | } 173 | } 174 | graph.verify(t) 175 | for i, node := range graph.nodes { 176 | if mapped[i].node != node { 177 | t.Errorf("Node at index %v != %v, wrong!", i, i) 178 | } 179 | } 180 | var nonGraphNode Node 181 | err := graph.MakeEdge(nonGraphNode, mapped[0]) 182 | if err == nil { 183 | t.Errorf("err was nil when expecting error for connecting non graph node to graph") 184 | } 185 | graph = New(Directed) 186 | mapped = make(map[int]Node, 0) 187 | for i := 0; i < 10; i++ { 188 | mapped[i] = graph.MakeNode() 189 | } 190 | for j := 0; j < 5; j++ { 191 | for i := 0; i < 10; i++ { 192 | graph.MakeEdge(mapped[i], mapped[(i+1+j)%10]) 193 | } 194 | } 195 | graph.verify(t) 196 | for i, node := range graph.nodes { 197 | if mapped[i].node != node { 198 | t.Errorf("Node at index %v = %v, != %v, wrong!", i, mapped[i], node) 199 | } 200 | } 201 | } 202 | 203 | func TestRemoveEdge(t *testing.T) { 204 | g := New(Undirected) 205 | nodes := make([]Node, 2) 206 | nodes[0] = g.MakeNode() 207 | nodes[1] = g.MakeNode() 208 | g.MakeEdge(nodes[0], nodes[0]) 209 | g.MakeEdge(nodes[1], nodes[0]) 210 | g.MakeEdge(nodes[0], nodes[1]) 211 | g.MakeEdge(nodes[1], nodes[1]) 212 | g.verify(t) 213 | g.RemoveEdge(nodes[0], nodes[0]) 214 | g.verify(t) 215 | g.RemoveEdge(nodes[0], nodes[1]) 216 | g.verify(t) 217 | g.RemoveEdge(nodes[1], nodes[1]) 218 | g.verify(t) 219 | 220 | nodes = make([]Node, 10) 221 | g = New(Directed) 222 | for i := 0; i < 10; i++ { 223 | nodes[i] = g.MakeNode() 224 | } 225 | // connect every node to every node 226 | for j := 0; j < 10; j++ { 227 | for i := 0; i < 10; i++ { 228 | if g.MakeEdge(nodes[i], nodes[j]) != nil { 229 | t.Errorf("could not connect %v, %v", i, j) 230 | } 231 | } 232 | } 233 | g.verify(t) 234 | g.RemoveEdge(nodes[5], nodes[4]) 235 | g.verify(t) 236 | g.RemoveEdge(nodes[9], nodes[0]) 237 | g.verify(t) 238 | g.RemoveEdge(nodes[9], nodes[0]) 239 | g.verify(t) 240 | g.RemoveEdge(nodes[0], nodes[0]) 241 | g.verify(t) 242 | g.RemoveEdge(nodes[1], nodes[0]) 243 | g.verify(t) 244 | g.RemoveEdge(nodes[2], nodes[0]) 245 | g.verify(t) 246 | g.RemoveEdge(nodes[3], nodes[0]) 247 | g.verify(t) 248 | g.RemoveEdge(nodes[4], nodes[0]) 249 | g.verify(t) 250 | g.RemoveEdge(nodes[5], nodes[0]) 251 | g.verify(t) 252 | g.RemoveEdge(nodes[6], nodes[0]) 253 | g.verify(t) 254 | g.RemoveEdge(nodes[7], nodes[0]) 255 | g.verify(t) 256 | g.RemoveEdge(nodes[8], nodes[0]) 257 | g.verify(t) 258 | g.RemoveEdge(nodes[9], nodes[0]) 259 | g.verify(t) 260 | } 261 | 262 | func TestNeighbors(t *testing.T) { 263 | g := New(Undirected) 264 | nodes := make([]Node, 2) 265 | nodes[0] = g.MakeNode() 266 | nodes[1] = g.MakeNode() 267 | g.MakeEdge(nodes[1], nodes[0]) 268 | g.verify(t) 269 | neighbors := g.Neighbors(nodes[0]) 270 | if !nodeSliceContains(neighbors, nodes[1]) { 271 | t.Errorf("nodes 1 not a neighbor of 0, even though connected in undirected graph") 272 | } 273 | oldGraphNode := nodes[0] 274 | nodes = make([]Node, 3) 275 | g = New(Directed) 276 | nodes[0] = g.MakeNode() 277 | nodes[1] = g.MakeNode() 278 | nodes[2] = g.MakeNode() 279 | g.MakeEdge(nodes[1], nodes[0]) 280 | g.MakeEdge(nodes[2], nodes[1]) // 2->1->0 281 | g.verify(t) 282 | neighbors = g.Neighbors(nodes[1]) 283 | if nodeSliceContains(neighbors, nodes[2]) { 284 | t.Errorf("nodes 2 is a neighbor of 0, even though not 1 not connected to 2 in undirected graph") 285 | } 286 | if !nodeSliceContains(neighbors, nodes[0]) { 287 | t.Errorf("nodes 0 not a neighbor of 0, even though 1 connects to 0 in directed graph") 288 | } 289 | neighbors = g.Neighbors(oldGraphNode) 290 | if len(neighbors) > 0 { 291 | t.Errorf("old graph node has neighbors in new graph: %v", neighbors) 292 | } 293 | } 294 | -------------------------------------------------------------------------------- /go/graph/lite/litegraph.go: -------------------------------------------------------------------------------- 1 | package lite 2 | 3 | type Graph []Node 4 | 5 | type Node struct { 6 | Edges []Edge 7 | } 8 | type Edge struct { 9 | Start, End int 10 | S, E interface{} 11 | } 12 | 13 | func NewGraph(size int) Graph { 14 | if size < 0 { 15 | return Graph(make([]Node, 0)) 16 | } 17 | return Graph(make([]Node, size)) 18 | } 19 | -------------------------------------------------------------------------------- /go/graph/search.go: -------------------------------------------------------------------------------- 1 | package graph 2 | 3 | type Path struct { 4 | Weight int 5 | Path []Edge 6 | } 7 | 8 | // DijkstraSearch returns the shortest path from the start node to every other 9 | // node in the graph. All edges must have a positive weight, otherwise this 10 | // function will return nil. 11 | func (g *Graph) DijkstraSearch(start Node) []Path { 12 | if start.node == nil || g.nodes[start.node.index] != start.node { 13 | return nil 14 | } 15 | paths := make([]Path, len(g.nodes)) 16 | 17 | nodesBase := nodeSlice(make([]*node, len(g.nodes))) 18 | copy(nodesBase, g.nodes) 19 | for i := range nodesBase { 20 | nodesBase[i].state = 1<<31 - 1 21 | nodesBase[i].data = i 22 | nodesBase[i].parent = nil 23 | } 24 | start.node.state = 0 // make it so 'start' sorts to the top of the heap 25 | nodes := &nodesBase 26 | nodes.heapInit() 27 | 28 | for len(*nodes) > 0 { 29 | curNode := nodes.pop() 30 | for _, edge := range curNode.edges { 31 | newWeight := curNode.state + edge.weight 32 | if newWeight < curNode.state { // negative edge length 33 | return nil 34 | } 35 | v := edge.end 36 | if nodes.heapContains(v) && newWeight < v.state { 37 | v.parent = curNode 38 | nodes.update(v.data, newWeight) 39 | } 40 | } 41 | 42 | // build path to this node 43 | if curNode.parent != nil { 44 | newPath := Path{Weight: curNode.state} 45 | newPath.Path = make([]Edge, len(paths[curNode.parent.index].Path)+1) 46 | copy(newPath.Path, paths[curNode.parent.index].Path) 47 | newPath.Path[len(newPath.Path)-1] = Edge{Weight: curNode.state - curNode.parent.state, 48 | Start: curNode.parent.container, End: curNode.container} 49 | paths[curNode.index] = newPath 50 | } else { 51 | paths[curNode.index] = Path{Weight: curNode.state, Path: []Edge{}} 52 | } 53 | } 54 | return paths 55 | } 56 | -------------------------------------------------------------------------------- /go/graph/todo.md: -------------------------------------------------------------------------------- 1 | TODO 2 | ---- 3 | ~~1) make mincut work on one large slice of shuffled edges (remove litegraph)~~ 4 | ~~2) add tests for reverseEdge consistency~~ 5 | ~~3) Write Dijkstras algorithm~~ 6 | 4) Write tests for Dijkstras algorithm 7 | 5) change ints to int64s ? 8 | 6) do MST eager implementation: http://algs4.cs.princeton.edu/43mst/ 9 | -------------------------------------------------------------------------------- /go/matrix/multiply.go: -------------------------------------------------------------------------------- 1 | package matrix 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | // I do not check if any row length differs from others: don't do that. 8 | // You know who does that? Crazy people. 9 | 10 | func testBounds(A, B [][]int) error { 11 | if len(A) == 0 || len(B) == 0 { 12 | return errors.New("Cannot multiply empty matrices") 13 | } 14 | if len(A[0]) == 0 || len(B[0]) == 0 { 15 | return errors.New("Cannot multiply empty matrices") 16 | } 17 | if len(A[0]) != len(B) { 18 | return errors.New("Dimension mismatch") 19 | } 20 | return nil 21 | } 22 | 23 | func BasicMultiply(A, B [][]int) ([][]int, error) { 24 | err := testBounds(A, B) 25 | if err != nil { 26 | return nil, err 27 | } 28 | C := make([][]int, len(A)) 29 | for r := range A { 30 | C[r] = make([]int, len(B[0])) 31 | for c := range B[0] { 32 | for k := range A[r] { 33 | C[r][c] += A[r][k] * B[k][c] 34 | } 35 | } 36 | } 37 | return C, nil 38 | } 39 | 40 | type multBounds struct { 41 | rs, re, cs, ce int // {row,column}{start,end} 42 | } 43 | 44 | // pad to power of two and deep copy the elements 45 | func pad(M [][]int, power int) [][]int { 46 | newM := make([][]int, power) 47 | for i := 0; i < len(M); i++ { 48 | newM[i] = make([]int, power) 49 | copy(newM[i], M[i]) 50 | } 51 | for i := len(M); i < power; i++ { 52 | newM[i] = make([]int, power) 53 | } 54 | return newM 55 | } 56 | 57 | func add(s1, s2, t [][]int, boundsT multBounds) { 58 | for j := 0; j < len(s1); j++ { 59 | for i := 0; i < len(s1[0]); i++ { 60 | t[boundsT.rs+j][boundsT.cs+i] += s1[j][i] + s2[j][i] 61 | } 62 | } 63 | } 64 | 65 | func recursiveMultiplyImpl(A, B, C [][]int, boundsA, boundsB multBounds) [][]int { 66 | if boundsA.re-boundsA.rs <= 1 { 67 | return [][]int{[]int{A[boundsA.rs][boundsA.cs] * B[boundsB.rs][boundsB.cs]}} 68 | } else { 69 | // currently these will be equal, if I modify the recursive function to not pad to equal power lengths of two, this will be more relevant 70 | tla := multBounds{boundsA.rs, (boundsA.rs + boundsA.re) / 2, boundsA.cs, (boundsA.cs + boundsA.ce) / 2} // top left a 71 | tra := multBounds{boundsA.rs, (boundsA.rs + boundsA.re) / 2, (boundsA.cs + boundsA.ce) / 2, boundsA.ce} // top right a 72 | bla := multBounds{(boundsA.rs + boundsA.re) / 2, boundsA.re, boundsA.cs, (boundsA.cs + boundsA.ce) / 2} // bottom left a 73 | bra := multBounds{(boundsA.rs + boundsA.re) / 2, boundsA.re, (boundsA.cs + boundsA.ce) / 2, boundsA.ce} // bottom right a 74 | 75 | tlb := multBounds{boundsB.rs, (boundsB.rs + boundsB.re) / 2, boundsB.cs, (boundsB.cs + boundsB.ce) / 2} // top left b 76 | trb := multBounds{boundsB.rs, (boundsB.rs + boundsB.re) / 2, (boundsB.cs + boundsB.ce) / 2, boundsB.ce} // top right b 77 | blb := multBounds{(boundsB.rs + boundsB.re) / 2, boundsB.re, boundsB.cs, (boundsB.cs + boundsB.ce) / 2} // bottom left b 78 | brb := multBounds{(boundsB.rs + boundsB.re) / 2, boundsB.re, (boundsB.cs + boundsB.ce) / 2, boundsB.ce} // bottom right b 79 | 80 | newC := make([][]int, boundsA.re-boundsA.rs) 81 | for j := range newC { 82 | newC[j] = make([]int, boundsA.ce-boundsA.cs) 83 | for i := range newC[j] { 84 | newC[j][i] = C[boundsA.rs+j][boundsA.cs+i] 85 | } 86 | } 87 | 88 | tlc := multBounds{0, len(newC) / 2, 0, len(newC[0]) / 2} 89 | trc := multBounds{len(newC) / 2, len(newC), 0, len(newC[0]) / 2} 90 | blc := multBounds{0, len(newC) / 2, len(newC[0]) / 2, len(newC[0])} 91 | brc := multBounds{len(newC) / 2, len(newC), len(newC[0]) / 2, len(newC[0])} 92 | 93 | r1 := recursiveMultiplyImpl(A, B, C, tla, tlb) 94 | r2 := recursiveMultiplyImpl(A, B, C, tra, blb) 95 | add(r1, r2, newC, tlc) 96 | 97 | r3 := recursiveMultiplyImpl(A, B, C, tla, trb) 98 | r4 := recursiveMultiplyImpl(A, B, C, tra, brb) 99 | add(r3, r4, newC, trc) 100 | 101 | r5 := recursiveMultiplyImpl(A, B, C, bla, tlb) 102 | r6 := recursiveMultiplyImpl(A, B, C, bra, blb) 103 | add(r5, r6, newC, blc) 104 | 105 | r7 := recursiveMultiplyImpl(A, B, C, bla, trb) 106 | r8 := recursiveMultiplyImpl(A, B, C, bra, brb) 107 | add(r7, r8, newC, brc) 108 | return newC 109 | } 110 | } 111 | 112 | func RecursiveMultiply(A, B [][]int) ([][]int, error) { 113 | // Note: I *really* hate recursive matrix multiplication. So, you can do it on any matrix, but I have not yet 114 | // made this efficient (even if it's O3, I still have many constant O2 additions that I don't need). I have 115 | // a mix of ideas in getting this to work. Ideally, I would only use one C matrix and do operations based off 116 | // of relative indices. But I don't have that yet. I both duplicate smaller boxes many times and pass around C. 117 | // So it's not smart. But it works! 118 | // So, the TODO list is: 119 | // 1) Take out the duplications on C boxes 120 | // 2) Take out the padding for the multipication and work magically with the numbers 121 | // 3) Implement Strassen's algorithm 122 | // 123 | // Yet again, I'm probably not going to do any of these unless I get *really* bored some day because I find this algorithm 124 | // so boring and somewhat needlessly complex to implement (with slices, though I could switch to arrays and maybe it'd be 125 | // easier that way. Hmm...). 126 | err := testBounds(A, B) 127 | if err != nil { 128 | return nil, err 129 | } 130 | C := make([][]int, len(A)) 131 | for i := range C { 132 | C[i] = make([]int, len(B[0])) 133 | } 134 | longest := len(A) 135 | if len(A[0]) > longest { 136 | longest = len(A[0]) 137 | } 138 | if len(B) > longest { 139 | longest = len(B) 140 | } 141 | power := 1 142 | for power < longest { 143 | power <<= 1 144 | } 145 | newA := pad(A, power) 146 | newB := pad(B, power) 147 | newC := pad(C, power) 148 | boundsA := multBounds{ 149 | 0, len(newA[0]), 0, len(newA), 150 | } 151 | boundsB := multBounds{ 152 | 0, len(newB[0]), 0, len(newB), 153 | } 154 | newC = recursiveMultiplyImpl(newA, newB, newC, boundsA, boundsB) 155 | C = newC[0:len(A)] 156 | for i := range C { 157 | C[i] = newC[i][0:len(B[0])] 158 | } 159 | return C, nil 160 | } 161 | -------------------------------------------------------------------------------- /go/matrix/multiply_test.go: -------------------------------------------------------------------------------- 1 | package matrix 2 | 3 | import ( 4 | "errors" 5 | "testing" 6 | ) 7 | 8 | type want struct { 9 | r [][]int 10 | e error 11 | } 12 | 13 | type test struct { 14 | inA [][]int 15 | inB [][]int 16 | want want 17 | } 18 | 19 | var tests []test 20 | 21 | func init() { 22 | var test1 test 23 | var want1 want 24 | test1.inA = [][]int{[]int{}} // test A empty 25 | test1.inB = [][]int{ 26 | []int{1, 0, 0, 0}, 27 | } 28 | want1.r = nil 29 | want1.e = errors.New("Cannot multiply empty matrices") 30 | test1.want = want1 31 | 32 | var test2 test 33 | var want2 want 34 | test2.inA = [][]int{ 35 | []int{1, 0, 0, 0}, 36 | } 37 | test2.inB = [][]int{[]int{}} // test B empty 38 | want2.r = nil 39 | want2.e = errors.New("Cannot multiply empty matrices") 40 | test2.want = want2 41 | 42 | var test3 test 43 | var want3 want 44 | test3.inA = [][]int{ 45 | []int{1, 0, 0, 0}, 46 | } 47 | test3.inB = [][]int{[]int{1, 2, 3}} // test dimension mismatch 48 | want3.r = nil 49 | want3.e = errors.New("Dimension mismatch") 50 | test3.want = want3 51 | 52 | var test4 test 53 | var want4 want 54 | test4.inA = [][]int{ 55 | []int{1, 2, 3, 4}, 56 | []int{1, 2, 3, 4}, 57 | } 58 | test4.inB = [][]int{ 59 | []int{1, 1}, 60 | []int{2, 2}, 61 | []int{3, 3}, 62 | []int{4, 4}, 63 | } 64 | want4.r = [][]int{ 65 | []int{30, 30}, 66 | []int{30, 30}, 67 | } 68 | want4.e = nil 69 | test4.want = want4 70 | 71 | tests = append(tests, test1) 72 | tests = append(tests, test2) 73 | tests = append(tests, test3) 74 | tests = append(tests, test4) 75 | 76 | } 77 | 78 | func TestBasicMultiply(t *testing.T) { 79 | for _, test := range tests { 80 | result, err := BasicMultiply(test.inA, test.inB) 81 | if err != nil { // if received error 82 | if result != nil { 83 | t.Errorf("wanted result nil for test inA %v, inB %v", test.inA, test.inB) 84 | continue 85 | } 86 | if test.want.e.Error() != err.Error() { 87 | t.Errorf("BasicMultiply err %v != want err %v", err, test.want.e) 88 | continue 89 | } 90 | } 91 | // if didn't receive error 92 | if len(result) != len(test.want.r) { 93 | t.Errorf("Row count not the same for test %v and result %v", test.want.r, result) 94 | continue 95 | } // these two errors should never happen, as BasicMultiply would panic first. 96 | for r := range test.want.r { 97 | if len(result[r]) != len(test.want.r[r]) { 98 | t.Errorf("Column count not the same for row %v of test %v and result %v", r, test.want.r, result) 99 | continue 100 | } 101 | for c := range test.want.r[r] { 102 | if result[r][c] != test.want.r[r][c] { 103 | t.Errorf("Values at %v,%v not equal for test %v, result %v", r, c, test.want.r, result) 104 | } 105 | } 106 | } 107 | } 108 | } 109 | 110 | func TestRecursiveMultiply(t *testing.T) { 111 | for _, test := range tests { 112 | result, err := RecursiveMultiply(test.inA, test.inB) 113 | if err != nil { // if received error 114 | if result != nil { 115 | t.Errorf("wanted result nil for test inA %v, inB %v", test.inA, test.inB) 116 | continue 117 | } 118 | if test.want.e.Error() != err.Error() { 119 | t.Errorf("BasicMultiply err %v != want err %v", err, test.want.e) 120 | continue 121 | } 122 | } 123 | // if didn't receive error 124 | if len(result) != len(test.want.r) { 125 | t.Errorf("Row count not the same for test %v and result %v", test.want.r, result) 126 | continue 127 | } // these two errors should never happen, as BasicMultiply would panic first. 128 | for r := range test.want.r { 129 | if len(result[r]) != len(test.want.r[r]) { 130 | t.Errorf("Column count not the same for row %v of test %v and result %v", r, test.want.r, result) 131 | continue 132 | } 133 | for c := range test.want.r[r] { 134 | if result[r][c] != test.want.r[r][c] { 135 | t.Errorf("Values at %v,%v not equal for test %v, result %v", r, c, test.want.r, result) 136 | } 137 | } 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /go/sort/dupsort/dupsort.go: -------------------------------------------------------------------------------- 1 | // Package dupsort, again, is my own implementation of different sort 2 | // functions. The difference between dupsort and sort is that this package 3 | // contains all algorithms that must actually access an element. This new 4 | // requirement means that dupsort needs a larger interface (by one function). 5 | // 6 | // Generally, an algorithm needs to access an element if it needs to duplicate 7 | // elements. Otherwise they could just be compared and swapped. This means 8 | // that this package includes all algorithms that need to copy what is being 9 | // sorted. 10 | package dupsort 11 | 12 | type DupSortable interface { 13 | // Len is the number of elements in the collection 14 | Len() int 15 | // Less returns whether the element i should 16 | // sort before the element j 17 | Less(i, j interface{}) bool 18 | // At accesses the element at index i 19 | At(i int) interface{} 20 | // Set sets the value at index i 21 | Set(i int, val interface{}) 22 | // New returns a new DupSortable of length i 23 | New(i int) DupSortable 24 | } 25 | -------------------------------------------------------------------------------- /go/sort/dupsort/mergesort.go: -------------------------------------------------------------------------------- 1 | // Implements merge sort on the abstract data type DupSortable 2 | package dupsort 3 | 4 | func mergeCombine(l, r DupSortable) DupSortable { 5 | combined := l.New(r.Len() + l.Len()) 6 | li, ri, ci := 0, 0, 0 7 | for ; li < l.Len() && ri < r.Len(); ci++ { 8 | if l.Less(l.At(li), r.At(ri)) { 9 | combined.Set(ci, l.At(li)) 10 | li++ 11 | } else { 12 | combined.Set(ci, r.At(ri)) 13 | ri++ 14 | } 15 | } 16 | for ; li < l.Len(); ci, li = ci+1, li+1 { 17 | combined.Set(ci, l.At(li)) 18 | } 19 | for ; ri < r.Len(); ci, ri = ci+1, ri+1 { 20 | combined.Set(ci, r.At(ri)) 21 | } 22 | return combined 23 | } 24 | 25 | func MergeSort(me DupSortable, from, to int) DupSortable { 26 | if from < to-1 { 27 | left := MergeSort(me, from, (from+to)/2) 28 | right := MergeSort(me, (from+to)/2, to) 29 | combined := mergeCombine(left, right) 30 | return combined 31 | } 32 | ele := me.New(to - from) 33 | if to-from > 0 { 34 | ele.Set(0, me.At(from)) 35 | } 36 | return ele 37 | } 38 | -------------------------------------------------------------------------------- /go/sort/dupsort/mergesort_test.go: -------------------------------------------------------------------------------- 1 | package dupsort 2 | 3 | import "testing" 4 | 5 | type Ints []int 6 | 7 | func (p Ints) Len() int { return len(p) } 8 | func (p Ints) Less(i, j interface{}) bool { 9 | l, okl := i.(int) 10 | r, okr := j.(int) 11 | if !okl || !okr { 12 | return false 13 | } 14 | return l < r 15 | } 16 | func (p Ints) At(i int) interface{} { return p[i] } 17 | func (p Ints) Set(i int, n interface{}) { 18 | v, ok := n.(int) 19 | if ok { 20 | p[i] = v 21 | } 22 | } 23 | func (p Ints) New(i int) DupSortable { 24 | ints := make([]int, i) 25 | return Ints(ints) 26 | } 27 | 28 | func TestMergeSort(t *testing.T) { 29 | // 100% line coverage 30 | tests := []struct { 31 | In, Want Ints 32 | }{ 33 | {Ints([]int{21, -10, 54, 0, 1098309}), Ints([]int{-10, 0, 21, 54, 1098309})}, 34 | {Ints([]int{}), Ints([]int{})}, 35 | {Ints([]int{4, 3, 2, 1, 2, 3}), Ints([]int{1, 2, 2, 3, 3, 4})}, 36 | } 37 | 38 | for _, test := range tests { 39 | gotI := MergeSort(test.In, 0, len(test.In)) 40 | got := gotI.(Ints) 41 | failed := false 42 | for i, v := range got { 43 | if v != test.Want[i] { 44 | t.Errorf("MergeSort, position %v, sortval %v, supposed to be %v", i, v, test.Want[i]) 45 | failed = true 46 | } 47 | } 48 | if failed { 49 | t.Errorf("Failing Ints: %v != %v", test.In, test.Want) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /go/sort/heap.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | // Shuffles a smaller value at index i in a heap 4 | // down to the appropriate spot. Complexity is O(lg n). 5 | func shuffleDown(heap Sortable, i, end int) { 6 | for { 7 | l := 2*i + 1 8 | if l >= end { // int overflow? (in go source) 9 | break 10 | } 11 | li := l 12 | if r := l + 1; r < end && heap.Less(l, r) { 13 | li = r // 2*i + 2 14 | } 15 | if heap.Less(li, i) { 16 | break 17 | } 18 | heap.Swap(li, i) 19 | i = li 20 | } 21 | } 22 | 23 | // Creates a max heap out of an unorganized Sortable collection. 24 | // Runs in O(n) time. 25 | func buildHeap(stuff Sortable) { 26 | for i := stuff.Len()/2 - 1; i >= 0; i-- { // start at first non leaf (equiv. to parent of last leaf) 27 | shuffleDown(stuff, i, stuff.Len()) 28 | } 29 | } 30 | 31 | // Runs HeapSort on a Sortable collection. 32 | // Runs in O(n * lg n) time, but amortizes worse than quicksort 33 | func HeapSort(stuff Sortable) { 34 | buildHeap(stuff) 35 | for i := stuff.Len() - 1; i > 0; i-- { 36 | stuff.Swap(0, i) // put max at end 37 | shuffleDown(stuff, 0, i) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /go/sort/heap_test.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "testing" 4 | 5 | // uses Ints from sort_test 6 | 7 | func TestHeapSort(t *testing.T) { 8 | tests := []struct { 9 | In, Want Ints 10 | }{ 11 | {Ints([]int{}), Ints([]int{})}, 12 | { 13 | Ints([]int{4, 1, 3, 2, 16, 9, 10, 14, 8, 7}), 14 | Ints([]int{1, 2, 3, 4, 7, 8, 9, 10, 14, 16}), 15 | }, 16 | } 17 | for _, test := range tests { 18 | HeapSort(test.In) 19 | failed := false 20 | for i, v := range test.In { 21 | if v != test.Want[i] { 22 | failed = true 23 | break 24 | } 25 | } 26 | if failed { 27 | t.Errorf("Failing Ints: result %v != want %v", test.In, test.Want) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /go/sort/integers/countingsort.go: -------------------------------------------------------------------------------- 1 | package integers 2 | 3 | // Runs counting sort on a slice of ints with the minVal being the minimum value 4 | // in the slice and maxVal being the maximum. 5 | // Has O(n + maxVal - minVal) time complexity, where n is the length of the slice. 6 | func CountingSort(me []int, minVal, maxVal int) (sorted []int) { 7 | sorted = make([]int, len(me)) 8 | counts := make([]int, maxVal+1-minVal) 9 | for i := range me { 10 | counts[me[i]-minVal]++ 11 | } 12 | for i := 1; i < len(counts); i++ { 13 | counts[i] += counts[i-1] 14 | } 15 | for i := range me { 16 | sorted[counts[me[i]-minVal]-1] = me[i] 17 | counts[me[i]-minVal]-- 18 | } 19 | return 20 | } 21 | -------------------------------------------------------------------------------- /go/sort/integers/countingsort_test.go: -------------------------------------------------------------------------------- 1 | package integers 2 | 3 | import "testing" 4 | 5 | func TestCountingSort(t *testing.T) { 6 | tests := []struct { 7 | In, Want []int 8 | InMinV, InMaxV int 9 | }{ 10 | {[]int{21, -10, 21, 0, 22}, []int{-10, 0, 21, 21, 22}, -10, 22}, 11 | {[]int{}, []int{}, 0, 0}, 12 | {[]int{4, 3, 2, 1, 2, 0, 0, 0, 0, 1, 3, 4, 2, 3, 4, 3}, []int{0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4}, 0, 4}, 13 | } 14 | 15 | for _, test := range tests { 16 | got := CountingSort(test.In, test.InMinV, test.InMaxV) 17 | failed := false 18 | for i, v := range got { 19 | if v != test.Want[i] { 20 | t.Errorf("CountingSort, position %v, sortval %v, supposed to be %v", i, v, test.Want[i]) 21 | failed = true 22 | } 23 | } 24 | if failed { 25 | t.Errorf("Failing Ints: %v != %v", test.In, test.Want) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /go/sort/integers/mergesort.go: -------------------------------------------------------------------------------- 1 | // Implements merge sort on []ints. 2 | // Knowing that the underlying type is a slice allows for using channels. 3 | // This also allows for using goroutines. 4 | package integers 5 | 6 | func mergeCombine(lch, rch <-chan int, tch chan<- int) { 7 | lv, lopen := <-lch 8 | rv, ropen := <-rch 9 | for lopen && ropen { 10 | if lv < rv { 11 | tch <- lv 12 | lv, lopen = <-lch 13 | } else { 14 | tch <- rv 15 | rv, ropen = <-rch 16 | } 17 | } 18 | for lopen { 19 | tch <- lv 20 | lv, lopen = <-lch 21 | } 22 | for ropen { 23 | tch <- rv 24 | rv, ropen = <-rch 25 | } 26 | close(tch) 27 | } 28 | 29 | // This function takes a slice to be sorted, a range to sort 30 | // and a channel to send in-order ints to. 31 | func MergeSort(me []int, from, to int, tch chan<- int) { 32 | if from < to-1 { 33 | lch, rch := make(chan int), make(chan int) 34 | go MergeSort(me, from, (from+to)/2, lch) 35 | go MergeSort(me, (from+to)/2, to, rch) 36 | mergeCombine(lch, rch, tch) 37 | } else { 38 | for i := from; i < to; i++ { 39 | tch <- me[i] 40 | } 41 | close(tch) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /go/sort/integers/mergesort_test.go: -------------------------------------------------------------------------------- 1 | package integers 2 | 3 | import "testing" 4 | 5 | func TestMergeSort(t *testing.T) { 6 | tests := []struct { 7 | In, Want []int 8 | }{ 9 | {[]int{21, -10, 54, 0, 1098309}, []int{-10, 0, 21, 54, 1098309}}, 10 | {[]int{}, []int{}}, 11 | {[]int{4, 3, 2, 1, 2, 3}, []int{1, 2, 2, 3, 3, 4}}, 12 | } 13 | 14 | for _, test := range tests { 15 | tch := make(chan int) 16 | got := make([]int, 0, len(test.In)) 17 | go MergeSort(test.In, 0, len(test.In), tch) 18 | for v := range tch { 19 | got = append(got, v) 20 | } 21 | failed := false 22 | for i, v := range got { 23 | if v != test.Want[i] { 24 | t.Errorf("MergeSort, position %v, sortval %v, supposed to be %v", i, v, test.Want[i]) 25 | failed = true 26 | } 27 | } 28 | if failed { 29 | t.Errorf("Failing Ints: %v != %v", test.In, test.Want) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /go/sort/quicksort.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | // currently chooses pivot to be s[to]. 4 | func partition(s Sortable, from, to int) int { 5 | i := from 6 | for j := from; j < to-1; j++ { 7 | if s.Less(j, to-1) { 8 | s.Swap(i, j) 9 | i++ 10 | } 11 | } 12 | s.Swap(to-1, i) 13 | return i 14 | } 15 | 16 | // TODO: median of three pivot, 17 | // tail call so only one recursive call 18 | // insertion sort for small values 19 | // wtf are the go authors doing with heapsort 20 | // dual pivot 21 | func quickSort(s Sortable, from, to int) { 22 | if to-from > 1 { 23 | pivot := partition(s, from, to) 24 | quickSort(s, from, pivot) 25 | quickSort(s, pivot+1, to) 26 | } 27 | } 28 | 29 | func QuickSort(s Sortable) { 30 | quickSort(s, 0, s.Len()) 31 | } 32 | -------------------------------------------------------------------------------- /go/sort/quicksort_test.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "testing" 4 | 5 | var ints = []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586} 6 | 7 | func TestQuickSort(t *testing.T) { 8 | // 100% line coverage 9 | tests := []struct { 10 | In, Want Ints 11 | }{ 12 | {Ints([]int{21, -10, 54, 0, 1098309}), Ints([]int{-10, 0, 21, 54, 1098309})}, 13 | {Ints([]int{}), Ints([]int{})}, 14 | {Ints([]int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}), Ints([]int{-5467984, -784, 0, 0, 42, 59, 74, 238, 905, 959, 7586, 7586, 9845})}, 15 | } 16 | 17 | for _, test := range tests { 18 | QuickSort(test.In) 19 | failed := false 20 | for i, v := range test.In { 21 | if v != test.Want[i] { 22 | t.Errorf("QuickSort, position %v, sortval %v, supposed to be %v", i, v, test.Want[i]) 23 | failed = true 24 | } 25 | } 26 | if failed { 27 | t.Errorf("Failing Ints: %v != %v", test.In, test.Want) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /go/sort/sort.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // 5 | // Package sort is my own implementation of different sort functions 6 | // The package will be similar, if not exactly the same as the go provided 7 | // sort package. I am using that to reference where I need to improve my code. 8 | // 9 | // Another reason for this is that, really, you need Len, Less and Swap if you 10 | // are to make a generic sort package 11 | // 12 | // This package will contain all sort algorithms that operate without needing 13 | // to access a specific element (in essence, all in place sorts) 14 | package sort 15 | 16 | type Sortable interface { 17 | // Len is the number of elements in the collection 18 | Len() int 19 | // Less returns whether the element at index i should 20 | // sort before the element at index j 21 | Less(i, j int) bool 22 | // Swaps the elements at indices i and j 23 | Swap(i, j int) 24 | } 25 | 26 | // Insertion sort on Sortable type 27 | // Does not have start and end indices yet, like the Go authors of sort 28 | func InsertionSort(stuff Sortable) { 29 | for j := 1; j < stuff.Len(); j++ { // from the second spot to the last 30 | for i := j; i > 0 && stuff.Less(i, i-1); i-- { // while left is larger 31 | stuff.Swap(i, i-1) // slide right one position 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /go/sort/sort_test.go: -------------------------------------------------------------------------------- 1 | package sort 2 | 3 | import "testing" 4 | 5 | type Ints []int 6 | 7 | func (p Ints) Len() int { return len(p) } 8 | func (p Ints) Less(i, j int) bool { return p[i] < p[j] } 9 | func (p Ints) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 10 | 11 | func TestInsertionSort(t *testing.T) { 12 | // 100% line coverage 13 | tests := []struct { 14 | In, Want Ints 15 | }{ 16 | {Ints([]int{21, -10, 54, 0, 1098309}), Ints([]int{-10, 0, 21, 54, 1098309})}, 17 | {Ints([]int{}), Ints([]int{})}, 18 | } 19 | 20 | for _, test := range tests { 21 | InsertionSort(test.In) 22 | failed := false 23 | for i, v := range test.In { 24 | if v != test.Want[i] { 25 | t.Errorf("InsertionSort, position %v, sortval %v, supposed to be %v", i, v, test.Want[i]) 26 | failed = true 27 | } 28 | } 29 | if failed { 30 | t.Errorf("Failing Ints: %v != %v", test.In, test.Want) 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /go/tree/binary/binaryTree.go: -------------------------------------------------------------------------------- 1 | // Package binary has functions for abusing a binary tree. 2 | package binary 3 | 4 | type BinaryTree struct { 5 | root *node 6 | size int 7 | } 8 | 9 | // Returns a new, empty binary tree. 10 | func New() *BinaryTree { 11 | return &BinaryTree{size: 0} 12 | } 13 | 14 | type node struct { 15 | parent *node 16 | left *node 17 | right *node 18 | value Comparable 19 | } 20 | 21 | // A type that implements the comparable interface can be used in binary trees. 22 | type Comparable interface { 23 | // Returns -1 if other is less, 0 if they are equal and 1 if other is greater. 24 | CompareTo(other Comparable) int 25 | } 26 | 27 | func walkInOrder(node *node, walked []Comparable) []Comparable { 28 | if node != nil { 29 | walked = walkInOrder(node.left, walked) 30 | walked = append(walked, node.value) 31 | walked = walkInOrder(node.right, walked) 32 | return walked 33 | } 34 | return nil 35 | } 36 | 37 | // Returns an in order Comparable slice of the binary tree. 38 | func (b *BinaryTree) Walk() []Comparable { 39 | walked := make([]Comparable, 0, b.size) 40 | return walkInOrder(b.root, walked) 41 | } 42 | 43 | func walkPreOrder(node *node, walked []Comparable) []Comparable { 44 | if node != nil { 45 | walked = append(walked, node.value) 46 | walked = walkPreOrder(node.left, walked) 47 | walked = walkPreOrder(node.right, walked) 48 | return walked 49 | } 50 | return nil 51 | } 52 | 53 | // Returns a pre order Comparable slice of the binary tree. 54 | func (b *BinaryTree) WalkPreOrder() []Comparable { 55 | walked := make([]Comparable, 0, b.size) 56 | return walkPreOrder(b.root, walked) 57 | } 58 | 59 | func walkPostOrder(node *node, walked []Comparable) []Comparable { 60 | if node != nil { 61 | walked = walkPostOrder(node.left, walked) 62 | walked = walkPostOrder(node.right, walked) 63 | walked = append(walked, node.value) 64 | return walked 65 | } 66 | return nil 67 | } 68 | 69 | // Returns a post order Comparable slice of the binary tree. 70 | func (b *BinaryTree) WalkPostOrder() []Comparable { 71 | walked := make([]Comparable, 0, b.size) 72 | return walkPostOrder(b.root, walked) 73 | } 74 | 75 | // Search for a Comparable in the tree and returns the node that contains it. 76 | // If no node does, returns nil. 77 | func (b *BinaryTree) search(target Comparable) *node { 78 | current := b.root 79 | for current != nil { 80 | switch current.value.CompareTo(target) { 81 | case -1: 82 | current = current.left 83 | case 0: 84 | return current 85 | case 1: 86 | current = current.right 87 | } 88 | } 89 | return nil 90 | } 91 | 92 | // Returns true if the binary tree contains the target Comparable 93 | func (b *BinaryTree) Contains(target Comparable) bool { 94 | return b.search(target) != nil 95 | } 96 | 97 | // returns a pointer to the node that contains the minimum 98 | // starting from the start node 99 | func minimum(startNode *node) *node { 100 | current := startNode 101 | for current.left != nil { 102 | current = current.left 103 | } 104 | return current 105 | } 106 | 107 | // Returns a pointer to a copy of the minimum value 108 | // in the binary tree. If the tree is empty, this will 109 | // return nil. 110 | func (b *BinaryTree) Minimum() *Comparable { 111 | return &minimum(b.root).value 112 | } 113 | 114 | // Returns a pointer to a copy of the maximum value 115 | // in the binary tree. If the tree is empty, this will 116 | // return nil. 117 | func (b *BinaryTree) Maximum() *Comparable { 118 | current := b.root 119 | for current.right != nil { 120 | current = current.right 121 | } 122 | // copy 123 | rval := current.value 124 | return &rval 125 | } 126 | 127 | // Returns a pointer to the successor value of a target Comparable in a binary tree. 128 | // The pointer will be nil if the tree does not contain the target 129 | // of if there is no successor (i.e., you want the successor to the maximum value) 130 | func (b *BinaryTree) Successor(target Comparable) *Comparable { 131 | current := b.search(target) 132 | if current == nil { 133 | return nil 134 | } 135 | if current.right != nil { 136 | return &minimum(current.right).value 137 | } 138 | if current == b.root { // if root has no right side, at max, no successor 139 | return nil 140 | } 141 | parent := current.parent 142 | for parent != nil && current == parent.right { 143 | current = parent 144 | parent = current.parent 145 | } 146 | return ¤t.value 147 | } 148 | 149 | // Inserts a comparable value into a binary tree. 150 | // Expected running time O(lg n), worst case running time O(n) 151 | // for a tree with n nodes. 152 | func (b *BinaryTree) Insert(value Comparable) { 153 | newNode := new(node) 154 | newNode.value = value 155 | y := (*node)(nil) 156 | x := b.root 157 | for x != nil { 158 | y = x 159 | if value.CompareTo(x.value) == -1 { // less 160 | x = x.left 161 | } else { 162 | x = x.right 163 | } 164 | } 165 | newNode.parent = y 166 | if newNode.parent == nil { 167 | b.root = newNode 168 | } else if newNode.value.CompareTo(y.value) == -1 { 169 | y.left = newNode 170 | } else { 171 | y.right = newNode 172 | } 173 | b.size++ 174 | } 175 | 176 | // Sets the replacement node's parent information to that 177 | // of the old node and updates the parent of the old node 178 | // to point to the replacement. This also updates pointer 179 | // values on the old node to nil. For garbage collection. 180 | func (b *BinaryTree) transplant(old, replacement *node) { 181 | if old.parent == nil { 182 | b.root = replacement 183 | } else if old == old.parent.left { 184 | old.parent.left = replacement 185 | } else { 186 | old.parent.right = replacement 187 | } 188 | if replacement != nil { 189 | replacement.parent = old.parent 190 | } 191 | // garbage collect 192 | old.parent = nil 193 | old.left = nil 194 | old.right = nil 195 | } 196 | 197 | // Deletes and returns a pointer to a Comparable value from 198 | // the binary tree. If the value was not in the binary tree, 199 | // this function returns nil. Running time is O(h) for a tree of 200 | // height h. 201 | func (b *BinaryTree) Delete(value Comparable) *Comparable { 202 | // first find the node because of my decision to not allow access to nodes. 203 | node := b.search(value) 204 | if node == nil { 205 | return nil 206 | } 207 | if node.left == nil { 208 | b.transplant(node, node.right) 209 | } else if node.right == nil { 210 | b.transplant(node, node.left) 211 | } else { 212 | replacement := minimum(node.right) 213 | if replacement.parent != node { 214 | b.transplant(replacement, replacement.right) // sever ties 215 | replacement.right = node.right 216 | } 217 | replacement.right.parent = replacement 218 | replacement.left = node.left 219 | replacement.left.parent = replacement 220 | b.transplant(node, replacement) 221 | } 222 | return &node.value 223 | } 224 | -------------------------------------------------------------------------------- /go/tree/binary/binaryTree_test.go: -------------------------------------------------------------------------------- 1 | package binary 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type Int int 8 | 9 | // Returns -1 if other is not a comparable 10 | func (i Int) CompareTo(other Comparable) int { 11 | o, ok := other.(Int) 12 | if !ok || i < o { 13 | return -1 14 | } else if i == o { 15 | return 0 16 | } else { 17 | return 1 18 | } 19 | } 20 | 21 | func TestNew(t *testing.T) { 22 | got := New() 23 | if got.root != nil || got.size != 0 { 24 | t.Errorf("New produced incorrect empty binary tree %v", got) 25 | } 26 | } 27 | 28 | func verify(n *node, t *testing.T) { 29 | if n != nil { 30 | if n.left != nil { 31 | compared := n.left.value.CompareTo(n.value) 32 | if compared == 1 { 33 | t.Errorf("Left child %v > parent %v", n.left.value, n.value) 34 | } 35 | } 36 | if n.right != nil { 37 | compared := n.right.value.CompareTo(n.value) 38 | if compared == -1 { 39 | t.Errorf("Right child %v < parent %v", n.right.value, n.value) 40 | } 41 | } 42 | verify(n.left, t) 43 | verify(n.right, t) 44 | } 45 | } 46 | 47 | func TestInsert(t *testing.T) { 48 | tree := New() 49 | verify(tree.root, t) 50 | for i := 0; i < 10; i++ { 51 | tree.Insert(Int(i)) 52 | verify(tree.root, t) 53 | } 54 | tree = New() 55 | verify(tree.root, t) 56 | for i := 10; i >= 0; i-- { 57 | tree.Insert(Int(i)) 58 | verify(tree.root, t) 59 | } 60 | tree = New() 61 | tree.Insert(Int(5)) // 5 62 | tree.Insert(Int(3)) // 3 8 63 | tree.Insert(Int(2)) // 2 3 6 9 64 | tree.Insert(Int(3)) //0 4 5 7 65 | tree.Insert(Int(0)) // 1 66 | tree.Insert(Int(1)) 67 | tree.Insert(Int(4)) 68 | tree.Insert(Int(8)) 69 | tree.Insert(Int(6)) 70 | tree.Insert(Int(9)) 71 | tree.Insert(Int(5)) 72 | tree.Insert(Int(7)) 73 | verify(tree.root, t) 74 | } 75 | 76 | func TestDelete(t *testing.T) { 77 | tree := New() 78 | for i := 0; i < 10; i++ { 79 | tree.Insert(Int(i)) 80 | } 81 | for i := 0; i < 10; i++ { 82 | returned := tree.Delete(Int(i)) // deletes root each time 83 | if (*returned).(Int) != Int(i) { 84 | t.Errorf("returned value %v != expected %v", *returned, i) 85 | } 86 | verify(tree.root, t) 87 | } 88 | tree = New() 89 | for i := 10; i >= 0; i-- { 90 | tree.Insert(Int(i)) 91 | } 92 | for i := 10; i >= 0; i-- { 93 | returned := tree.Delete(Int(i)) 94 | if (*returned).(Int) != Int(i) { 95 | t.Errorf("returned value %v != expected %v", *returned, i) 96 | } 97 | verify(tree.root, t) 98 | } 99 | tree = New() 100 | tree.Insert(Int(5)) // 5 101 | tree.Insert(Int(3)) // 3 8 102 | tree.Insert(Int(2)) // 2 3 6 9 103 | tree.Insert(Int(3)) //0 4 5 7 104 | tree.Insert(Int(0)) // 1 105 | tree.Insert(Int(1)) 106 | tree.Insert(Int(4)) 107 | tree.Insert(Int(8)) 108 | tree.Insert(Int(6)) 109 | tree.Insert(Int(9)) 110 | tree.Insert(Int(5)) 111 | tree.Insert(Int(7)) 112 | tree.Delete(Int(5)) 113 | verify(tree.root, t) 114 | tree.Delete(Int(3)) 115 | verify(tree.root, t) 116 | tree.Delete(Int(2)) 117 | verify(tree.root, t) 118 | tree.Delete(Int(3)) 119 | verify(tree.root, t) 120 | tree.Delete(Int(0)) 121 | verify(tree.root, t) 122 | tree.Delete(Int(4)) 123 | verify(tree.root, t) 124 | tree.Delete(Int(8)) 125 | verify(tree.root, t) 126 | tree.Delete(Int(6)) 127 | verify(tree.root, t) 128 | tree.Delete(Int(9)) 129 | verify(tree.root, t) 130 | tree.Delete(Int(5)) 131 | verify(tree.root, t) 132 | tree.Delete(Int(1)) 133 | verify(tree.root, t) 134 | tree.Delete(Int(7)) 135 | verify(tree.root, t) 136 | } 137 | 138 | func TestWalk(t *testing.T) { 139 | tree := New() 140 | tree.Insert(Int(5)) // 5 141 | tree.Insert(Int(3)) // 3 8 142 | tree.Insert(Int(2)) // 2 3 6 9 143 | tree.Insert(Int(3)) //0 4 5 7 144 | tree.Insert(Int(0)) // 1 145 | tree.Insert(Int(1)) 146 | tree.Insert(Int(4)) 147 | tree.Insert(Int(8)) 148 | tree.Insert(Int(6)) 149 | tree.Insert(Int(9)) 150 | tree.Insert(Int(5)) 151 | tree.Insert(Int(7)) 152 | verify(tree.root, t) 153 | walked := tree.Walk() 154 | for i := 0; i < len(walked)-1; i++ { 155 | if walked[i].(Int).CompareTo(walked[i+1]) == 1 { 156 | t.Errorf("In order walk out of order results: %v before %v", walked[i], walked[i+1]) 157 | } 158 | } 159 | } 160 | 161 | func TestWalkPostOrder(t *testing.T) { 162 | tree := New() 163 | for i := 0; i < 10; i++ { 164 | tree.Insert(Int(i)) 165 | } 166 | tree.Insert(Int(9)) 167 | verify(tree.root, t) 168 | walked := tree.Walk() 169 | for i := 0; i < len(walked)-1; i++ { 170 | if walked[i].(Int).CompareTo(walked[i+1]) == -1 { 171 | t.Errorf("Post order walk out of order results: %v after %v", walked[i], walked[i+1]) 172 | } 173 | } 174 | } 175 | 176 | // one long left branch - should walk in ascending order 177 | func TestWalkPreOrder(t *testing.T) { 178 | tree := New() 179 | for i := 0; i < 10; i++ { 180 | tree.Insert(Int(10 - i)) 181 | } 182 | tree.Insert(Int(1)) 183 | verify(tree.root, t) 184 | walked := tree.Walk() 185 | for i := 0; i < len(walked)-1; i++ { 186 | if walked[i].(Int).CompareTo(walked[i+1]) == 1 { 187 | t.Errorf("Post order walk out of order results: %v after %v", walked[i], walked[i+1]) 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /go/tree/heap/heap.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | // 5 | // Package sort is my own implementation of different sort functions 6 | // Package heap has functions for creating and abusing a heap. 7 | // It is almost identically the same as containers/heap, so 8 | // just use that. 9 | package heap 10 | 11 | import ( 12 | "sort" 13 | ) 14 | 15 | // Any type that implements Interface may be used as a 16 | // max-tree. A tree must be either first Init()'d or build from scratch. 17 | // The tree functions will panic if called inappropriately (as in, you 18 | // cannot call Pop on an empty tree). 19 | // 20 | // This interface embeds sort.Interface, meaning elements 21 | // can be compared and swapped. 22 | // 23 | // Note that Push and Pop are for this package to call. To add or remove 24 | // elements from a tree, use tree.Push and tree.Pop. 25 | type Interface interface { 26 | sort.Interface 27 | // Adds a value to the end of the collection. 28 | Push(val interface{}) 29 | // Removes the value at the end of the collection. 30 | Pop() interface{} 31 | } 32 | 33 | // Creates a max heap out of an unorganized Interface collection. 34 | // Runs in O(n) time, where n = h.Len(). 35 | func Init(h Interface) { 36 | for i := h.Len()/2 - 1; i >= 0; i-- { // start at first non leaf (equiv. to parent of last leaf) 37 | shuffleDown(h, i, h.Len()) 38 | } 39 | } 40 | 41 | // Removes and returns the maximum of the heap and reorganizes. 42 | // The complexity is O(lg n). 43 | func Pop(h Interface) interface{} { 44 | n := h.Len() - 1 45 | h.Swap(n, 0) 46 | shuffleDown(h, 0, n) 47 | return h.Pop() 48 | } 49 | 50 | // This function will push a new value into a priority queue. 51 | func Push(h Interface, val interface{}) { 52 | h.Push(val) 53 | shuffleUp(h, h.Len()-1) 54 | } 55 | 56 | // Removes and returns the element at index i 57 | func Remove(h Interface, i int) (v interface{}) { 58 | n := h.Len() - 1 59 | if n != i { 60 | h.Swap(n, i) 61 | shuffleDown(h, i, n) 62 | shuffleUp(h, i) 63 | } 64 | return h.Pop() 65 | } 66 | 67 | // Shuffles a smaller value at index i in a heap 68 | // down to the appropriate spot. Complexity is O(lg n). 69 | func shuffleDown(heap Interface, i, end int) { 70 | for { 71 | l := 2*i + 1 72 | if l >= end { // int overflow? (in go source) 73 | break 74 | } 75 | li := l 76 | if r := l + 1; r < end && heap.Less(l, r) { 77 | li = r // 2*i + 2 78 | } 79 | if heap.Less(li, i) { 80 | break 81 | } 82 | heap.Swap(li, i) 83 | i = li 84 | } 85 | } 86 | 87 | // Shuffles a larger value in a heap at index i 88 | // up to the appropriate spot. Complexity is O(lg n). 89 | func shuffleUp(heap Interface, i int) { 90 | for { 91 | pi := (i - 1) / 2 // (i + 1) / 2 - 1, parent 92 | if i == pi || !heap.Less(pi, i) { 93 | break 94 | } 95 | heap.Swap(pi, i) 96 | i = pi 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /go/tree/heap/heap_test.go: -------------------------------------------------------------------------------- 1 | package heap 2 | 3 | // Note: I should add more test cases similar to what is in container/heap/heap.go file, 4 | // ...but this is good. 5 | import ( 6 | "testing" 7 | ) 8 | 9 | type Ints []int 10 | 11 | func (p *Ints) Len() int { return len(*p) } 12 | func (p *Ints) Less(i, j int) bool { return (*p)[i] < (*p)[j] } 13 | func (p *Ints) Swap(i, j int) { (*p)[i], (*p)[j] = (*p)[j], (*p)[i] } 14 | func (p *Ints) Push(v interface{}) { *p = append(*p, v.(int)) } 15 | func (p *Ints) Pop() (v interface{}) { *p, v = (*p)[:p.Len()-1], (*p)[p.Len()-1]; return } 16 | 17 | // Untested Init function, but it was tested before I deleted At() - it works, do not want to write right now. 18 | func TestPush(t *testing.T) { 19 | tests := []struct { 20 | In Interface 21 | PushVal interface{} 22 | WantInts Ints 23 | }{ 24 | { 25 | Interface((*Ints)(&[]int{})), 26 | 0, 27 | Ints([]int{0}), 28 | }, 29 | { 30 | Interface((*Ints)(&[]int{16, 14, 10, 8, 7, 9, 3, 2, 4, 1})), 31 | 15, 32 | Ints([]int{16, 15, 10, 8, 14, 9, 3, 2, 4, 1, 7}), 33 | }, 34 | } 35 | for _, test := range tests { 36 | Push(test.In, test.PushVal) 37 | changedInts := test.In.(*Ints) 38 | failed := false 39 | for i, v := range *changedInts { 40 | if v != test.WantInts[i] { 41 | failed = true 42 | break 43 | } 44 | } 45 | if failed { 46 | t.Errorf("Failing Ints: result %v != want %v", changedInts, test.WantInts) 47 | } 48 | } 49 | } 50 | 51 | func TestPop(t *testing.T) { 52 | tests := []struct { 53 | In Interface 54 | PopIndex int 55 | WantInts Ints 56 | WantV int 57 | }{ 58 | { 59 | Interface((*Ints)(&[]int{16, 14, 10, 8, 7, 9, 3, 2, 4, 1})), 60 | 1, 61 | Ints([]int{14, 8, 10, 4, 7, 9, 3, 2, 1}), 62 | //Ints([]int{16, 8, 10, 4, 7, 9, 3, 2, 1}), 63 | 16, 64 | }, 65 | } 66 | for _, test := range tests { 67 | got := Pop(test.In).(int) 68 | if test.WantV != got { 69 | t.Errorf("Return value %v != wanted %v", got, test.WantV) 70 | } 71 | changedInts := test.In.(*Ints) 72 | failed := false 73 | for i, v := range *changedInts { 74 | if v != test.WantInts[i] { 75 | failed = true 76 | break 77 | } 78 | } 79 | if failed { 80 | t.Errorf("Failing Ints: result %v != want %v", changedInts, test.WantInts) 81 | } 82 | } 83 | } 84 | 85 | // Taken from Go source code "heap_test.go" and modified to fit my structures 86 | // I must learn to make tests this easy... 87 | func (h Ints) verify(t *testing.T, i int) { 88 | n := h.Len() 89 | left := 2*i + 1 90 | right := 2*i + 2 91 | if left < n { 92 | if h.Less(i, left) { 93 | t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h[i], left, h[left]) 94 | return 95 | } 96 | h.verify(t, left) 97 | } 98 | if right < n { 99 | if h.Less(i, right) { 100 | t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h[i], left, h[right]) 101 | return 102 | } 103 | h.verify(t, right) 104 | } 105 | } 106 | 107 | func TestRemove1(t *testing.T) { 108 | h := new(Ints) 109 | for i := 0; i < 10; i++ { 110 | Push(h, i) 111 | } 112 | h.verify(t, 0) 113 | // removes the max every time 114 | for i := 0; h.Len() > 0; i++ { 115 | x := Remove(h, 0) 116 | if x.(int) != 9-i { 117 | t.Errorf("Remove(0) got %d; want %d", x, i) 118 | } 119 | h.verify(t, 0) 120 | } 121 | } 122 | 123 | func TestRemove2(t *testing.T) { 124 | N := 10 125 | h := new(Ints) 126 | for i := 0; i < N; i++ { 127 | Push(h, i) 128 | } 129 | h.verify(t, 0) 130 | // tests that it removed all 131 | m := make(map[int]bool) 132 | for h.Len() > 0 { 133 | x := Remove(h, (h.Len()-1)/2) // remove from middle 134 | m[x.(int)] = true 135 | h.verify(t, 0) 136 | } 137 | if len(m) != N { 138 | t.Errorf("len(m) = %d; want %d", len(m), N) 139 | } 140 | // and removed all correctly 141 | for i := 0; i < len(m); i++ { 142 | if !m[i] { 143 | t.Errorf("m[%d] doesn't exist", i) 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /go/various/dynamic/lcs.go: -------------------------------------------------------------------------------- 1 | package dynamic 2 | 3 | // Returns the longest common subsequence of two strings in O(mn) time 4 | // and space complexity, where m and n are the lengths of the strings. 5 | func LongestCommonSubsequence(first, second string) string { 6 | 7 | firstRunes := []rune(first) 8 | secondRunes := []rune(second) 9 | 10 | // Create lookup table - sides initialized to zero already 11 | table := make([][]int, 1+len(firstRunes)) 12 | for i := range table { 13 | table[i] = make([]int, 1+len(secondRunes)) 14 | } 15 | 16 | for i := 0; i < len(firstRunes); i++ { 17 | for j := 0; j < len(secondRunes); j++ { 18 | if firstRunes[i] == secondRunes[j] { 19 | table[i+1][j+1] = 1 + table[i][j] 20 | } else { // +1 to table indices because the zero row/column corresponds to no letters 21 | table[i+1][j+1] = max(table[i+1][j], table[i][j+1]) // favor longer first string 22 | } 23 | } 24 | } 25 | 26 | lcsRunes := make([]rune, 0) 27 | 28 | for i := len(firstRunes); i > 0; { 29 | for j := len(secondRunes); i > 0; { 30 | if table[i][j] == table[i-1][j] { // favored longer first string 31 | i-- // letters at {i,j} not equal, but equal at {i-1, j} 32 | } else if table[i][j] == table[i][j-1] { 33 | j-- // letters at {i,j} not equal, {i-1, j} not equal, equal at {i, j-1} 34 | } else { 35 | i-- // letters at {i,j} equal 36 | j-- 37 | lcsRunes = append(lcsRunes, firstRunes[i]) 38 | } 39 | } 40 | } 41 | 42 | // lcsRunes is backwards, reverse 43 | runelen := len(lcsRunes) 44 | for i := 0; i < runelen/2; i++ { 45 | lcsRunes[i], lcsRunes[runelen-i-1] = lcsRunes[runelen-i-1], lcsRunes[i] 46 | } 47 | return string(lcsRunes) 48 | } 49 | 50 | // returns the greater of the two ints, favoring the first if they are equal 51 | func max(first, second int) int { 52 | if first >= second { 53 | return first 54 | } 55 | return second 56 | } 57 | -------------------------------------------------------------------------------- /go/various/dynamic/lcs_test.go: -------------------------------------------------------------------------------- 1 | package dynamic_test 2 | 3 | import ( 4 | "github.com/twmb/algoimpl/go/various/dynamic" 5 | "testing" 6 | ) 7 | 8 | func TestLongestCommonSubsequence(t *testing.T) { 9 | tests := []struct { 10 | InF, InS, Want string 11 | }{ 12 | {"hi", "hello", "h"}, 13 | {"ABCBDAB", "BDCABA", "BCBA"}, 14 | {"thisisatest", "testing123testing", "tsitest"}, 15 | {"1234", "1224533324", "1234"}, 16 | {"", "", ""}, 17 | } 18 | 19 | for _, test := range tests { 20 | lcs := dynamic.LongestCommonSubsequence(test.InF, test.InS) 21 | if lcs != test.Want { 22 | t.Errorf("Input %v, %v recieved output %v, != want %v", test.InF, test.InS, lcs, test.Want) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /go/various/dynamic/rodcutting.go: -------------------------------------------------------------------------------- 1 | package dynamic 2 | 3 | type MoneyRod struct { 4 | CutPositions []int 5 | Profit int 6 | } 7 | 8 | var profits []int 9 | var firstCuts []int 10 | var profitsCalculatedIndex int 11 | 12 | func InitPrices(prices []int) { 13 | profits = prices 14 | firstCuts = make([]int, len(profits)) 15 | for i := range firstCuts { 16 | firstCuts[i] = i 17 | } 18 | profitsCalculatedIndex = 0 19 | } 20 | 21 | // Assumes that the 0 index of prices corresponds to a rod of 0 length (and will have a price of 0) 22 | func CutRod(rodlength int) MoneyRod { 23 | if rodlength > profitsCalculatedIndex { 24 | if rodlength > len(profits) { 25 | return MoneyRod{} 26 | } 27 | for j := 1; j <= rodlength; j++ { 28 | for i := 1; i <= j/2; i++ { 29 | if profits[j] < profits[j-i]+profits[i] { 30 | firstCuts[j] = j - i 31 | profits[j] = profits[j-i] + profits[i] 32 | } 33 | } 34 | } 35 | profitsCalculatedIndex = rodlength 36 | } 37 | 38 | maxProfit := profits[rodlength] 39 | cutPositions := make([]int, 0) 40 | for rodlength > 0 { 41 | cutPositions = append(cutPositions, rodlength) 42 | rodlength -= firstCuts[rodlength] 43 | } 44 | return MoneyRod{CutPositions: cutPositions, Profit: maxProfit} 45 | } 46 | -------------------------------------------------------------------------------- /go/various/dynamic/rodcutting_test.go: -------------------------------------------------------------------------------- 1 | package dynamic_test 2 | 3 | import ( 4 | "github.com/twmb/algoimpl/go/various/dynamic" 5 | "testing" 6 | ) 7 | 8 | func TestCutRod(t *testing.T) { 9 | prices := make([]int, 11) 10 | prices[1] = 1 11 | prices[2] = 5 12 | prices[3] = 8 13 | prices[4] = 9 14 | prices[5] = 10 15 | prices[6] = 17 16 | prices[7] = 17 17 | prices[8] = 20 18 | prices[9] = 24 19 | prices[10] = 30 20 | 21 | idealProfits := make([]int, 11) 22 | idealProfits[1] = 1 23 | idealProfits[2] = 5 24 | idealProfits[3] = 8 25 | idealProfits[4] = 10 26 | idealProfits[5] = 13 27 | idealProfits[6] = 17 28 | idealProfits[7] = 18 29 | idealProfits[8] = 22 30 | idealProfits[9] = 25 31 | idealProfits[10] = 30 32 | 33 | dynamic.InitPrices(prices) 34 | for i := len(prices) - 1; i >= 0; i-- { 35 | got := dynamic.CutRod(i) 36 | if got.Profit != idealProfits[i] { 37 | t.Errorf("Expected profit %v, got profit %v with positions %v", idealProfits[i], got.Profit, got.CutPositions) 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /go/various/inversions.go: -------------------------------------------------------------------------------- 1 | package various 2 | 3 | func inversionsCombine(left, right, combined []int) int { 4 | inversions := 0 5 | k, li, ri := 0, 0, 0 // index in combined array 6 | for ; li < len(left) && ri < len(right); k++ { 7 | if left[li] < right[ri] { 8 | combined[k] = left[li] 9 | li++ 10 | } else { // right less than left 11 | combined[k] = right[ri] 12 | inversions += len(left) - li // if a right element is larger than a left, 13 | ri++ // then it is larger than every element remaining on the left 14 | } 15 | } 16 | for ; li < len(left); li, k = li+1, k+1 { 17 | combined[k] = left[li] 18 | } 19 | for ; ri < len(right); ri, k = ri+1, k+1 { 20 | combined[k] = right[ri] 21 | } 22 | return inversions 23 | } 24 | 25 | // performs a mergesort while counting inversions 26 | func inversionsCount(array, buffer []int) int { 27 | if len(array) <= 1 { 28 | return 0 29 | } 30 | cleft := inversionsCount(buffer[:len(array)/2], array[:len(array)/2]) 31 | cright := inversionsCount(buffer[len(array)/2:], array[len(array)/2:]) 32 | ccross := inversionsCombine(array[:len(array)/2], array[len(array)/2:], buffer) 33 | return cleft + ccross + cright 34 | } 35 | 36 | // Inversions will return the number of inversions in a given input integer array. 37 | // An inversion is when a smaller number appears after a larger number. 38 | // For example, [1,3,5,2,4,6] has three inversions: [3,2], [5,2] and [5,4]. 39 | // Runs in O(n lg n) time, where n is the size of the input. 40 | func Inversions(array []int) int { 41 | buffer0 := make([]int, len(array)) 42 | buffer1 := make([]int, len(array)) 43 | copy(buffer0, array[:]) 44 | copy(buffer1, array[:]) 45 | count := inversionsCount(buffer0, buffer1) 46 | return count 47 | } 48 | -------------------------------------------------------------------------------- /go/various/inversions_test.go: -------------------------------------------------------------------------------- 1 | package various_test 2 | 3 | import ( 4 | "github.com/twmb/algoimpl/go/various" 5 | "testing" 6 | ) 7 | 8 | func TestInversions(t *testing.T) { 9 | tests := []struct { 10 | In []int 11 | Want int 12 | }{ 13 | {[]int{9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, 45}, 14 | {[]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, 0}, 15 | {[]int{1, 3, 5, 2, 4, 6}, 3}, 16 | {[]int{}, 0}, 17 | } 18 | for _, test := range tests { 19 | count := various.Inversions(test.In) 20 | if count != test.Want { 21 | t.Errorf("Input array %v, expected count %v, got %v", test.In, test.Want, count) 22 | } 23 | } 24 | } 25 | 26 | func BenchmarkInversions5(b *testing.B) { 27 | b.StopTimer() 28 | inverse := make([]int, 1<<5) 29 | for i := 0; i < 1<<5; i++ { 30 | inverse[i] = 1<<5 - i 31 | } 32 | b.StartTimer() 33 | for i := 0; i < b.N; i++ { 34 | various.Inversions(inverse) 35 | } 36 | } 37 | 38 | func BenchmarkInversions10(b *testing.B) { 39 | b.StopTimer() 40 | inverse := make([]int, 1<<10) 41 | for i := 0; i < 1<<10; i++ { 42 | inverse[i] = 1<<10 - i 43 | } 44 | b.StartTimer() 45 | for i := 0; i < b.N; i++ { 46 | various.Inversions(inverse) 47 | } 48 | } 49 | 50 | func BenchmarkInversions20(b *testing.B) { 51 | b.StopTimer() 52 | inverse := make([]int, 1<<20) 53 | for i := 0; i < 1<<20; i++ { 54 | inverse[i] = 1<<20 - i 55 | } 56 | b.StartTimer() 57 | for i := 0; i < b.N; i++ { 58 | various.Inversions(inverse) 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /go/various/maxsubarray.go: -------------------------------------------------------------------------------- 1 | // Implements the maximum subarray algorithm on a slice of ints 2 | package various 3 | 4 | func maxCrossingSubarray(array []int, from, to int) (li, ri, sum int) { 5 | mid := (from + to) / 2 6 | // left index, left side's sum, new running sum 7 | li, lsum, nsum := mid-1, array[mid-1], array[mid-1] 8 | for n := li - 1; n >= from; n-- { 9 | nsum += array[n] 10 | if nsum > lsum { 11 | lsum = nsum 12 | li = n 13 | } 14 | } 15 | ri, rsum, nsum := mid, array[mid], array[mid] 16 | for n := ri + 1; n < to; n++ { 17 | nsum += array[n] 18 | if nsum > rsum { 19 | rsum = nsum 20 | ri = n 21 | } 22 | } 23 | return li, ri + 1, lsum + rsum // one after last valid index 24 | } 25 | 26 | func MaxSubarrayRecursive(array []int, from, to int) (li, ri, sum int) { 27 | if from >= to-1 { 28 | if to-from == 0 { 29 | return from, to, 0 30 | } 31 | return from, to, array[from] 32 | } else { 33 | lli, lri, lv := MaxSubarrayRecursive(array, from, (from+to)/2) 34 | rli, rri, rv := MaxSubarrayRecursive(array, (from+to)/2, to) 35 | cli, cri, cv := maxCrossingSubarray(array, from, to) 36 | if lv > rv && lv > cv { 37 | return lli, lri, lv // left's left index, right index, sum 38 | } else if rv > lv && rv > cv { 39 | return rli, rri, rv // right's left index, right index, sum 40 | } else { 41 | return cli, cri, cv // crossing left index, right index, sum 42 | } 43 | } 44 | } 45 | 46 | // iterative 47 | func MaxSubarray(array []int, from, to int) (li, ri, sum int) { 48 | if to-from <= 1 { 49 | if to-from == 1 { 50 | return from, to, array[from] 51 | } 52 | return from, to, 0 53 | } 54 | hli, hri, hsum := from, from, array[from] // subarray right now 55 | bli, bri, bsum := from, from, array[from] // best so far 56 | 57 | for here := from + 1; here < to; here++ { 58 | if hsum+array[here] > array[here] { // if subarray now is still 59 | // higher than when started 60 | hri = here // slide right index right one more 61 | hsum += array[here] // record new sum 62 | } else { // else subarray lost, begin tracking from local valley 63 | hli, hri, hsum = here, here, array[here] 64 | } 65 | if hsum > bsum { // record highest sum while it is net positive 66 | bli, bri, bsum = hli, hri, hsum 67 | } 68 | } 69 | return bli, bri + 1, bsum // here's right index is absolute, want one past 70 | } 71 | 72 | func MaxSubarray2(a []int) (max []int, sum int) { 73 | if len(a) < 1 { 74 | return a, 0 75 | } 76 | sum = a[0] 77 | sumHere := sum 78 | startMaxHere := 0 79 | maxHere := a[:1] 80 | max = maxHere 81 | for i := 1; i < len(a); i = i + 1 { 82 | if sumHere+a[i] < a[i] { 83 | sumHere = a[i] 84 | startMaxHere = i 85 | } else { 86 | sumHere += a[i] 87 | } 88 | maxHere = a[startMaxHere : i+1] 89 | if sumHere > sum { 90 | sum = sumHere 91 | max = maxHere 92 | } 93 | } 94 | return 95 | } 96 | -------------------------------------------------------------------------------- /go/various/maxsubarray_test.go: -------------------------------------------------------------------------------- 1 | package various 2 | 3 | import "testing" 4 | 5 | var tests = []struct { 6 | In []int 7 | WantLI, WantRI, WantSum int 8 | }{ 9 | {[]int{}, 0, 0, 0}, 10 | {[]int{-1}, 0, 1, -1}, 11 | {[]int{3, -1, -1, 4}, 0, 4, 5}, //whole thing 12 | {[]int{-1, 1, 1, -1}, 1, 3, 2}, //crossing 13 | {[]int{-1, -2, 1, 2}, 2, 4, 3}, //right side 14 | {[]int{1, 2, -3, -4}, 0, 2, 3}, //left side 15 | {[]int{1, -2, -3, 5, 6, 7}, 3, 6, 18}, // 6 length, right side 16 | {[]int{1, -2, -3, 5, 6}, 3, 5, 11}, // 5 length, right side 17 | } 18 | 19 | func TestMaxSubarrayRecursive(t *testing.T) { 20 | for _, test := range tests { 21 | li, ri, sum := MaxSubarrayRecursive(test.In, 0, len(test.In)) 22 | if li != test.WantLI || ri != test.WantRI || sum != test.WantSum { 23 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for array %v", li, ri, sum, test.WantLI, test.WantRI, test.WantSum, test.In) 24 | } 25 | } 26 | li, ri, sum := MaxSubarrayRecursive(tests[2].In, 2, len(tests[2].In)) // test half 27 | if li != 3 || ri != 4 || sum != 4 { 28 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for right half test of array %v", li, ri, sum, 3, 4, 4, tests[2].In) 29 | } 30 | li, ri, sum = MaxSubarrayRecursive(tests[3].In, 0, 2) // test left 31 | if li != 1 || ri != 2 || sum != 1 { 32 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for right half test of array %v", li, ri, sum, 1, 2, 1, tests[3].In) 33 | } 34 | li, ri, sum = MaxSubarrayRecursive(tests[5].In, 1, 3) // test middle 35 | if li != 1 || ri != 2 || sum != 2 { 36 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for right half test of array %v", li, ri, sum, 1, 2, 2, tests[5].In) 37 | } 38 | 39 | } 40 | 41 | func TestMaxSubarray(t *testing.T) { 42 | for _, test := range tests { 43 | li, ri, sum := MaxSubarray(test.In, 0, len(test.In)) 44 | if li != test.WantLI || ri != test.WantRI || sum != test.WantSum { 45 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for array %v", li, ri, sum, test.WantLI, test.WantRI, test.WantSum, test.In) 46 | } 47 | } 48 | li, ri, sum := MaxSubarray(tests[2].In, 2, len(tests[2].In)) // test half 49 | if li != 3 || ri != 4 || sum != 4 { 50 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for right half test of array %v", li, ri, sum, 3, 4, 4, tests[2].In) 51 | } 52 | li, ri, sum = MaxSubarray(tests[3].In, 0, 2) // test left 53 | if li != 1 || ri != 2 || sum != 1 { 54 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for right half test of array %v", li, ri, sum, 1, 2, 1, tests[3].In) 55 | } 56 | li, ri, sum = MaxSubarray(tests[5].In, 1, 3) // test middle 57 | if li != 1 || ri != 2 || sum != 2 { 58 | t.Errorf("test results (%v, %v, %v) != test expected (%v, %v, %v) for right half test of array %v", li, ri, sum, 1, 2, 2, tests[5].In) 59 | } 60 | } 61 | 62 | var tests2 = []struct { 63 | In, Want []int 64 | WantSum int 65 | }{ 66 | {[]int{}, []int{}, 0}, 67 | {[]int{-1}, []int{-1}, -1}, 68 | {[]int{3, -1, -1, 4}, []int{3, -1, -1, 4}, 5}, //whole thing 69 | {[]int{-1, 1, 1, -1}, []int{1, 1}, 2}, //crossing 70 | {[]int{-1, -2, 1, 2}, []int{1, 2}, 3}, //right side 71 | {[]int{1, 2, -3, -4}, []int{1, 2}, 3}, //left side 72 | {[]int{1, -2, -3, 5, 6, 7}, []int{5, 6, 7}, 18}, // 6 length, right side 73 | {[]int{1, -2, -3, 5, 6}, []int{5, 6}, 11}, // 5 length, right side 74 | } 75 | 76 | func TestMaxSubarray2(t *testing.T) { 77 | for testI, test := range tests2 { 78 | got, sum := MaxSubarray2(test.In) 79 | if len(got) != len(test.Want) { 80 | t.Errorf("test %v: got slice len != want slice len, got: %v, want: %v", testI, len(got), len(test.Want)) 81 | continue 82 | } 83 | for i := 0; i < len(got); i++ { 84 | if got[i] != test.Want[i] { 85 | t.Errorf("wanted %v at index %v, got %v", test.Want[i], i, got[i]) 86 | } 87 | } 88 | if sum != test.WantSum { 89 | t.Errorf("test %v: got sum %v != want sum %v", testI, sum, test.WantSum) 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /go/various/random_select.go: -------------------------------------------------------------------------------- 1 | package various 2 | 3 | import ( 4 | "math/rand" 5 | "time" 6 | ) 7 | 8 | // returns the final pivot index 9 | func partition(slice []int) int { 10 | pi := rand.Intn(len(slice)) 11 | n := len(slice) - 1 // convenience 12 | slice[n], slice[pi] = slice[pi], slice[n] // swap pivot to end 13 | b := 0 // boundry between larger and smaller elements. demarcates first element index larger than p[i] 14 | for i := 0; i < n; i++ { 15 | if slice[i] < slice[n] { 16 | slice[i], slice[b] = slice[b], slice[i] // smaller element, swap boundry element (large) with this smaller element 17 | b++ // and increment the boundry to point past the smaller element 18 | } 19 | } 20 | pi = b 21 | slice[n], slice[pi] = slice[pi], slice[n] // swap pivot to boundry between larger and smaller 22 | return pi // and return the index 23 | } 24 | 25 | func selectOrder(i int, slice []int) int { 26 | if len(slice) == 1 { 27 | return slice[0] 28 | } else { 29 | q := partition(slice) 30 | if i == q { 31 | return slice[q] 32 | } else if i < q { 33 | return selectOrder(i, slice[:q]) 34 | } 35 | return selectOrder(i-(q+1), slice[q+1:]) 36 | } 37 | } 38 | 39 | // Returns the ith smallest element from a slice of integers. 40 | // Runs in expected O(n) time, O(n^2) worst time (unlikely) 41 | func SelectOrder(i int, slice []int) int { 42 | rand.Seed(time.Now().Unix()) 43 | cslice := make([]int, len(slice)) // copy 44 | copy(cslice, slice[:]) 45 | return selectOrder(i, cslice) 46 | } 47 | -------------------------------------------------------------------------------- /go/various/random_select_test.go: -------------------------------------------------------------------------------- 1 | package various_test 2 | 3 | import ( 4 | "github.com/twmb/algoimpl/go/various" 5 | "testing" 6 | ) 7 | 8 | func TestSelectOrder(t *testing.T) { 9 | tests := []struct { 10 | InI, Want int 11 | InS []int 12 | }{ 13 | {InI: 0, Want: 0, InS: []int{0, 1, 2, 3}}, 14 | {InI: 0, Want: 0, InS: []int{3, 2, 1, 0}}, 15 | {InI: 1, Want: 1, InS: []int{0, 1, 2, 3}}, 16 | {InI: 1, Want: 1, InS: []int{3, 2, 1, 0}}, 17 | {InI: 2, Want: 2, InS: []int{0, 1, 2, 3}}, 18 | {InI: 2, Want: 2, InS: []int{3, 2, 1, 0}}, 19 | {InI: 3, Want: 3, InS: []int{0, 1, 2, 3}}, 20 | {InI: 3, Want: 3, InS: []int{3, 2, 1, 0}}, 21 | } 22 | 23 | for _, test := range tests { 24 | got := various.SelectOrder(test.InI, test.InS) 25 | if got != test.Want { 26 | t.Errorf("Got value %v != expected value %v for order %v of slice %v", got, test.Want, test.InI, test.InS) 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /java/project/src/dnyamic/matrixChainMultiply/MatrixInfo.java: -------------------------------------------------------------------------------- 1 | package dnyamic.matrixChainMultiply; 2 | 3 | public class MatrixInfo { 4 | public int rows, cols; 5 | 6 | public MatrixInfo(int rows, int cols) { 7 | this.rows = rows; 8 | this.cols = cols; 9 | } 10 | 11 | /** Finds the minimum number of multiply operations needed to multiply a 12 | * chain sequence of matrices (each of which is represented by the MatrixInfo object). 13 | * TODO: add multiplication order (currently only number of multiplications) 14 | * @param matrices An array of MatrixInfo objects 15 | * @return the minimum number of operations needed to multiply the matrices. 16 | */ 17 | public static int chainMultiply(MatrixInfo[] matrices) { 18 | if (matrices.length <= 0) { 19 | return 0; 20 | } 21 | int[][] m = new int[matrices.length][matrices.length]; 22 | // int[][] s = new int[matrices.length][matrices.length]; 23 | for (int i = 0; i < matrices.length; i++) { 24 | m[i][i] = 0; 25 | } 26 | for (int l = 2; l <= matrices.length; l++) { 27 | for (int i = 0; i <= matrices.length - l; i++) { 28 | int j = i + l - 1; 29 | m[i][j] = Integer.MAX_VALUE; 30 | for (int k = i; k < j; k++) { 31 | int q = m[i][k] + m[k+1][j] + matrices[i].rows * matrices[k].cols * matrices[j].cols; 32 | if (q < m[i][j]) { 33 | m[i][j] = q; 34 | // s[i][j] = k; 35 | } 36 | } 37 | } 38 | } 39 | return m[0][matrices.length - 1]; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /java/project/src/dnyamic/matrixChainMultiply/MatrixInfoTest.java: -------------------------------------------------------------------------------- 1 | package dnyamic.matrixChainMultiply; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import org.junit.Test; 6 | 7 | public class MatrixInfoTest { 8 | 9 | @Test 10 | public void testChainMultiply() { 11 | // From CLRS ed. 3 page 376 12 | MatrixInfo[] matrices = new MatrixInfo[]{ 13 | new MatrixInfo(30,35), 14 | new MatrixInfo(35,15), 15 | new MatrixInfo(15,5), 16 | new MatrixInfo(5,10), 17 | new MatrixInfo(10,20), 18 | new MatrixInfo(20,25)}; 19 | assertEquals(15125, MatrixInfo.chainMultiply(matrices)); 20 | 21 | matrices = new MatrixInfo[]{ 22 | new MatrixInfo(2, 3), 23 | new MatrixInfo(3, 2), 24 | }; 25 | assertEquals(12, MatrixInfo.chainMultiply(matrices)); 26 | 27 | matrices = new MatrixInfo[]{ 28 | new MatrixInfo(1,1), 29 | }; 30 | assertEquals(0, MatrixInfo.chainMultiply(matrices)); 31 | 32 | matrices = new MatrixInfo[]{}; 33 | assertEquals(0, MatrixInfo.chainMultiply(matrices)); 34 | } 35 | } 36 | --------------------------------------------------------------------------------