sort.odin 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. package slice
  2. Ordering :: enum {
  3. Less = -1,
  4. Equal = 0,
  5. Greater = +1,
  6. }
  7. cmp :: proc(a, b: $E) -> Ordering where ORD(E) {
  8. switch {
  9. case a < b:
  10. return .Less
  11. case a > b:
  12. return .Greater
  13. }
  14. return .Equal
  15. }
  16. cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
  17. return proc(a, b: E) -> Ordering {
  18. switch {
  19. case a < b:
  20. return .Less
  21. case a > b:
  22. return .Greater
  23. }
  24. return .Equal
  25. }
  26. }
  27. // sort sorts a slice
  28. // This sort is not guaranteed to be stable
  29. sort :: proc(data: $T/[]$E) where ORD(E) {
  30. when size_of(E) != 0 {
  31. if n := len(data); n > 1 {
  32. _quick_sort_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered)
  33. }
  34. }
  35. }
  36. sort_by_indices :: proc{ sort_by_indices_allocate, _sort_by_indices}
  37. sort_by_indices_allocate :: proc(data: $T/[]$E, indices: []int, allocator := context.allocator) -> (sorted: T) {
  38. assert(len(data) == len(indices))
  39. sorted = make(T, len(data), allocator)
  40. for v, i in indices {
  41. sorted[i] = data[v]
  42. }
  43. return
  44. }
  45. _sort_by_indices :: proc(data, sorted: $T/[]$E, indices: []int) {
  46. assert(len(data) == len(indices))
  47. assert(len(data) == len(sorted))
  48. for v, i in indices {
  49. sorted[i] = data[v]
  50. }
  51. }
  52. sort_by_indices_overwrite :: proc(data: $T/[]$E, indices: []int) {
  53. assert(len(data) == len(indices))
  54. temp := make([]int, len(data), context.allocator)
  55. defer delete(temp)
  56. for v, i in indices {
  57. temp[i] = data[v]
  58. }
  59. swap_with_slice(data, temp)
  60. }
  61. // sort sorts a slice and returns a slice of the original indices
  62. // This sort is not guaranteed to be stable
  63. sort_with_indices :: proc(data: $T/[]$E, allocator := context.allocator) -> (indices: []int) where ORD(E) {
  64. indices = make([]int, len(data), allocator)
  65. when size_of(E) != 0 {
  66. if n := len(data); n > 1 {
  67. for _, idx in indices {
  68. indices[idx] = idx
  69. }
  70. _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), struct{}{}, .Ordered)
  71. }
  72. return indices
  73. }
  74. return indices
  75. }
  76. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  77. // This sort is not guaranteed to be stable
  78. sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  79. when size_of(E) != 0 {
  80. if n := len(data); n > 1 {
  81. _quick_sort_general(data, 0, n, _max_depth(n), less, .Less)
  82. }
  83. }
  84. }
  85. // sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  86. // This sort is not guaranteed to be stable
  87. sort_by_with_indices :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool, allocator := context.allocator) -> (indices : []int) {
  88. indices = make([]int, len(data), allocator)
  89. when size_of(E) != 0 {
  90. if n := len(data); n > 1 {
  91. for _, idx in indices {
  92. indices[idx] = idx
  93. }
  94. _quick_sort_general_with_indices(data, indices, 0, n, _max_depth(n), less, .Less)
  95. return indices
  96. }
  97. }
  98. return indices
  99. }
  100. sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  101. when size_of(E) != 0 {
  102. if n := len(data); n > 1 {
  103. _quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp)
  104. }
  105. }
  106. }
  107. // stable_sort sorts a slice
  108. stable_sort :: proc(data: $T/[]$E) where ORD(E) {
  109. when size_of(E) != 0 {
  110. if n := len(data); n > 1 {
  111. _stable_sort_general(data, struct{}{}, .Ordered)
  112. }
  113. }
  114. }
  115. // stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
  116. stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
  117. when size_of(E) != 0 {
  118. if n := len(data); n > 1 {
  119. _stable_sort_general(data, less, .Less)
  120. }
  121. }
  122. }
  123. stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
  124. when size_of(E) != 0 {
  125. if n := len(data); n > 1 {
  126. _stable_sort_general(data, cmp, .Cmp)
  127. }
  128. }
  129. }
  130. is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
  131. for i := len(array)-1; i > 0; i -= 1 {
  132. if array[i] < array[i-1] {
  133. return false
  134. }
  135. }
  136. return true
  137. }
  138. is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
  139. for i := len(array)-1; i > 0; i -= 1 {
  140. if less(array[i], array[i-1]) {
  141. return false
  142. }
  143. }
  144. return true
  145. }
  146. is_sorted_by_cmp :: is_sorted_cmp
  147. is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
  148. for i := len(array)-1; i > 0; i -= 1 {
  149. if cmp(array[i], array[i-1]) == .Less {
  150. return false
  151. }
  152. }
  153. return true
  154. }
  155. reverse_sort :: proc(data: $T/[]$E) where ORD(E) {
  156. sort_by(data, proc(i, j: E) -> bool {
  157. return j < i
  158. })
  159. }
  160. reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) where ORD(E) {
  161. context._internal = rawptr(less)
  162. sort_by(data, proc(i, j: E) -> bool {
  163. k := (proc(i, j: E) -> bool)(context._internal)
  164. return k(j, i)
  165. })
  166. }
  167. reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) where ORD(E) {
  168. context._internal = rawptr(cmp)
  169. sort_by_cmp(data, proc(i, j: E) -> Ordering {
  170. k := (proc(i, j: E) -> Ordering)(context._internal)
  171. return k(j, i)
  172. })
  173. }
  174. // TODO(bill): Should `sort_by_key` exist or is `sort_by` more than enough?
  175. sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  176. context._internal = rawptr(key)
  177. sort_by(data, proc(i, j: E) -> bool {
  178. k := (proc(E) -> K)(context._internal)
  179. return k(i) < k(j)
  180. })
  181. }
  182. reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
  183. context._internal = rawptr(key)
  184. sort_by(data, proc(i, j: E) -> bool {
  185. k := (proc(E) -> K)(context._internal)
  186. return k(j) < k(i)
  187. })
  188. }
  189. is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) {
  190. for i := len(array)-1; i > 0; i -= 1 {
  191. if key(array[i]) < key(array[i-1]) {
  192. return false
  193. }
  194. }
  195. return true
  196. }
  197. @(private)
  198. _max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
  199. for i := n; i > 0; i >>= 1 {
  200. depth += 1
  201. }
  202. return depth * 2
  203. }