| 1 | """ |
|---|
| 2 | This program is the same as "Translate Psuedo Code To Cobra 2", but uses some |
|---|
| 3 | typing to improve compile-time error checking and boost run-time performance. |
|---|
| 4 | The list elements are still treated as dynamically typed so that any kind of |
|---|
| 5 | list can be used. |
|---|
| 6 | |
|---|
| 7 | Authors: Max Grender-Jones, Charles Esterbrook |
|---|
| 8 | """ |
|---|
| 9 | |
|---|
| 10 | use System.Collections |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | class Sorter |
|---|
| 14 | |
|---|
| 15 | sig SortMethod(list as IList) as dynamic |
|---|
| 16 | |
|---|
| 17 | shared |
|---|
| 18 | |
|---|
| 19 | def testSort(sortMethod as SortMethod) |
|---|
| 20 | assert sortMethod([1,2,3,4]) == [1,2,3,4] |
|---|
| 21 | assert sortMethod([3,4,1,2]) == [1,2,3,4] |
|---|
| 22 | assert sortMethod([4,3,2,1]) == [1,2,3,4] |
|---|
| 23 | assert sortMethod(['c','d','b','a']) == ['a','b','c','d'] |
|---|
| 24 | assert sortMethod([1,1,1,1]) == [1,1,1,1] |
|---|
| 25 | |
|---|
| 26 | def bubbleSort(list as IList) as dynamic |
|---|
| 27 | """ |
|---|
| 28 | From http://en.wikipedia.org/wiki/Bubble_sort#Pseudocode_implementation |
|---|
| 29 | procedure bubbleSort( A : list of sortable items ) defined as: |
|---|
| 30 | do |
|---|
| 31 | swapped := false |
|---|
| 32 | for each i in 0 to length( A ) - 2 do: |
|---|
| 33 | if A[ i ] > A[ i + 1 ] then |
|---|
| 34 | swap( A[ i ], A[ i + 1 ] ) |
|---|
| 35 | swapped := true |
|---|
| 36 | end if |
|---|
| 37 | end for |
|---|
| 38 | while swapped |
|---|
| 39 | end procedure |
|---|
| 40 | """ |
|---|
| 41 | test |
|---|
| 42 | .testSort(ref .bubbleSort) |
|---|
| 43 | body |
|---|
| 44 | swapped = false |
|---|
| 45 | post while swapped |
|---|
| 46 | swapped = false |
|---|
| 47 | for i in list.count - 1 |
|---|
| 48 | if list[i] to dynamic > list[i+1] to dynamic |
|---|
| 49 | list.swap(i, i+1) |
|---|
| 50 | swapped = true |
|---|
| 51 | return list |
|---|
| 52 | |
|---|
| 53 | def heapSort(list as IList) as dynamic |
|---|
| 54 | """ |
|---|
| 55 | From http://en.wikipedia.org/wiki/Heapsort#Pseudocode |
|---|
| 56 | function heapSort(a, count) is |
|---|
| 57 | input: an unordered array a of length count |
|---|
| 58 | |
|---|
| 59 | (first place a in max-heap order) |
|---|
| 60 | heapify(a, count) |
|---|
| 61 | |
|---|
| 62 | end := count - 1 |
|---|
| 63 | while end > 0 do |
|---|
| 64 | (swap the root(maximum value) of the heap with the last element of the heap) |
|---|
| 65 | swap(a[end], a[0]) |
|---|
| 66 | (decrease the size of the heap by one so that the previous max value will |
|---|
| 67 | stay in its proper placement) |
|---|
| 68 | end := end - 1 |
|---|
| 69 | (put the heap back in max-heap order) |
|---|
| 70 | siftDown(a, 0, end) |
|---|
| 71 | """ |
|---|
| 72 | test |
|---|
| 73 | .testSort(ref .heapSort) |
|---|
| 74 | body |
|---|
| 75 | .heapify(list) |
|---|
| 76 | last = list.count - 1 |
|---|
| 77 | while last > 0 |
|---|
| 78 | list.swap(0, last) |
|---|
| 79 | last -= 1 |
|---|
| 80 | .siftDown(list, 0, last) |
|---|
| 81 | return list |
|---|
| 82 | |
|---|
| 83 | def heapify(list as IList) |
|---|
| 84 | """ |
|---|
| 85 | From http://en.wikipedia.org/wiki/Heapsort#Pseudocode |
|---|
| 86 | function heapify(a,count) is |
|---|
| 87 | (start is assigned the index in a of the last parent node) |
|---|
| 88 | start := (count - 1) / 2 |
|---|
| 89 | |
|---|
| 90 | while start >= 0 do |
|---|
| 91 | (sift down the node at index start to the proper place such that all nodes below |
|---|
| 92 | the start index are in heap order) |
|---|
| 93 | siftDown(a, start, count-1) |
|---|
| 94 | start := start - 1 |
|---|
| 95 | (after sifting down the root all nodes/elements are in heap order) |
|---|
| 96 | """ |
|---|
| 97 | start = (list.count-1) // 2 |
|---|
| 98 | while start >= 0 |
|---|
| 99 | .siftDown(list, start, list.count-1) |
|---|
| 100 | start -= 1 |
|---|
| 101 | |
|---|
| 102 | def siftDown(list as IList, first as int, last as int) |
|---|
| 103 | """ |
|---|
| 104 | From http://en.wikipedia.org/wiki/Heapsort#Pseudocode |
|---|
| 105 | function siftDown(a, start, end) is |
|---|
| 106 | input: end represents the limit of how far down the heap to sift. |
|---|
| 107 | root := start |
|---|
| 108 | |
|---|
| 109 | while root * 2 + 1 <= end do (While the root has at least one child) |
|---|
| 110 | child := root * 2 + 1 (root*2+1 points to the left child) |
|---|
| 111 | (If the child has a sibling and the child's value is less than its sibling's...) |
|---|
| 112 | if child < end and a[child] < a[child + 1] then |
|---|
| 113 | child := child + 1 (... then point to the right child instead) |
|---|
| 114 | if a[root] < a[child] then (out of max-heap order) |
|---|
| 115 | swap(a[root], a[child]) |
|---|
| 116 | root := child (repeat to continue sifting down the child now) |
|---|
| 117 | else |
|---|
| 118 | return |
|---|
| 119 | """ |
|---|
| 120 | root = first |
|---|
| 121 | while root*2+1 <= last |
|---|
| 122 | child = root*2 + 1 |
|---|
| 123 | if child < last and list[child] to dynamic < list[child+1] to dynamic |
|---|
| 124 | child += 1 |
|---|
| 125 | if list[root] to dynamic < list[child] to dynamic |
|---|
| 126 | list.swap(root, child) |
|---|
| 127 | root = child |
|---|
| 128 | else |
|---|
| 129 | return |
|---|
| 130 | |
|---|
| 131 | def insertionSort(list as IList) as dynamic |
|---|
| 132 | """ |
|---|
| 133 | From http://en.wikipedia.org/wiki/Insertion_sort |
|---|
| 134 | insertionSort(array A) |
|---|
| 135 | for i = 1 to length[A]-1 do |
|---|
| 136 | value = A[i] |
|---|
| 137 | j = i-1 |
|---|
| 138 | while j >= 0 and A[j] > value do |
|---|
| 139 | A[j + 1] = A[j] |
|---|
| 140 | j = j-1 |
|---|
| 141 | A[j+1] = value |
|---|
| 142 | """ |
|---|
| 143 | test |
|---|
| 144 | .testSort(ref .insertionSort) |
|---|
| 145 | body |
|---|
| 146 | for i in 1 : list.count |
|---|
| 147 | value = list[i] to dynamic |
|---|
| 148 | j = i - 1 |
|---|
| 149 | while j >= 0 and list[j] > value |
|---|
| 150 | list[j+1] = list[j] |
|---|
| 151 | j -= 1 |
|---|
| 152 | list[j+1] = value |
|---|
| 153 | return list |
|---|
| 154 | |
|---|
| 155 | def quickSort(list as IList) as dynamic |
|---|
| 156 | """ |
|---|
| 157 | From http://en.wikipedia.org/wiki/Quicksort |
|---|
| 158 | function quicksort(array) |
|---|
| 159 | var list less, equal, greater |
|---|
| 160 | if length(array) <= 1 |
|---|
| 161 | return array |
|---|
| 162 | select a pivot value pivot from array |
|---|
| 163 | for each x in array |
|---|
| 164 | if x < pivot then append x to less |
|---|
| 165 | if x = pivot then append x to equal |
|---|
| 166 | if x > pivot then append x to greater |
|---|
| 167 | return concatenate(quicksort(less), equal, quicksort(greater)) |
|---|
| 168 | """ |
|---|
| 169 | test |
|---|
| 170 | .testSort(ref .quickSort) |
|---|
| 171 | body |
|---|
| 172 | if list.count <= 1 |
|---|
| 173 | return list |
|---|
| 174 | else |
|---|
| 175 | less = [] |
|---|
| 176 | equal = [] |
|---|
| 177 | more = [] |
|---|
| 178 | for x as dynamic in list[1:] |
|---|
| 179 | if x < list[0] |
|---|
| 180 | less.add(x) |
|---|
| 181 | else if x > list[0] |
|---|
| 182 | more.add(x) |
|---|
| 183 | else |
|---|
| 184 | equal.add(x) |
|---|
| 185 | equal.add(list[0]) |
|---|
| 186 | result = .quickSort(less) |
|---|
| 187 | result.addRange(equal) |
|---|
| 188 | result.addRange(.quickSort(more)) |
|---|
| 189 | return result |
|---|
| 190 | |
|---|
| 191 | def main |
|---|
| 192 | .quickSort([1,2,3,4]) |
|---|