authorgravatar for stereosteve@gmail.comSteve Perkins <stereosteve@gmail.com> 2016-11-03 04:10:33+00:00
committergravatar for stereosteve@gmail.comSteve Perkins <stereosteve@gmail.com> 2016-11-03 04:10:33+00:00
logcf00245bf9367f9a8ce11739372b4899639cdccf
treeb3e5d474d95811b3d45b5278e71851399d28b01d
parente761aa2d2f0034b1b6a071c4dae5262ef96997fb

sort requires compare function.

Provide some handy functions for builtin comparable types.

1 files changed, 24 insertions(+), 59 deletions(-)

std/sort.zig+24-59
...@@ -4,22 +4,22 @@ const math = @import("math.zig");...@@ -4,22 +4,22 @@ const math = @import("math.zig");
44
5pub const Cmp = math.Cmp;5pub const Cmp = math.Cmp;
66
7pub fn sort(inline T: type, array: []T) {7pub fn sort(inline T: type, array: []T, inline cmp: fn(a: T, b: T)->Cmp) {
8 if (array.len > 0) {8 if (array.len > 0) {
9 quicksort(T, array, 0, array.len - 1);9 quicksort(T, array, 0, array.len - 1, cmp);
10 }10 }
11}11}
1212
13fn quicksort(inline T: type, array: []T, left: usize, right: usize) {13fn quicksort(inline T: type, array: []T, left: usize, right: usize, inline cmp: fn(a: T, b: T)->Cmp) {
14 var i = left;14 var i = left;
15 var j = right;15 var j = right;
16 var p = (i + j) / 2;16 var p = (i + j) / 2;
1717
18 while (i <= j) {18 while (i <= j) {
19 while (array[i] < array[p]) {19 while (cmp(array[i], array[p]) == Cmp.Less) {
20 i += 1;20 i += 1;
21 }21 }
22 while (array[j] > array[p]) {22 while (cmp(array[j], array[p]) == Cmp.Greater) {
23 j -= 1;23 j -= 1;
24 }24 }
25 if (i <= j) {25 if (i <= j) {
...@@ -31,42 +31,28 @@ fn quicksort(inline T: type, array: []T, left: usize, right: usize) {...@@ -31,42 +31,28 @@ fn quicksort(inline T: type, array: []T, left: usize, right: usize) {
31 }31 }
32 }32 }
3333
34 if (left < j) quicksort(T, array, left, j);34 if (left < j) quicksort(T, array, left, j, cmp);
35 if (i < right) quicksort(T, array, i, right);35 if (i < right) quicksort(T, array, i, right, cmp);
36}36}
3737
38// ---------------------------------------38pub fn i32asc(a: i32, b: i32) -> Cmp {
39// sortCmp39 return if (a > b) Cmp.Greater else if (a < b) Cmp.Less else Cmp.Equal;
40}
4041
41pub fn sortCmp(inline T: type, array: []T, inline cmp: fn(a: T, b: T)->Cmp) {42pub fn i32desc(a: i32, b: i32) -> Cmp {
42 if (array.len > 0) {43 return reverse(i32asc(a, b));
43 quicksortCmp(T, array, 0, array.len - 1, cmp);
44 }
45}44}
4645
47fn quicksortCmp(inline T: type, array: []T, left: usize, right: usize, inline cmp: fn(a: T, b: T)->Cmp) {46pub fn u8asc(a: u8, b: u8) -> Cmp {
48 var i = left;47 return if (a > b) Cmp.Greater else if (a < b) Cmp.Less else Cmp.Equal;
49 var j = right;48}
50 var p = (i + j) / 2;
5149
52 while (i <= j) {50pub fn u8desc(a: u8, b: u8) -> Cmp {
53 while (cmp(array[i], array[p]) == Cmp.Less) {51 return reverse(u8asc(a, b));
54 i += 1;52}
55 }
56 while (cmp(array[j], array[p]) == Cmp.Greater) {
57 j -= 1;
58 }
59 if (i <= j) {
60 const tmp = array[i];
61 array[i] = array[j];
62 array[j] = tmp;
63 i += 1;
64 if (j > 0) j -= 1;
65 }
66 }
6753
68 if (left < j) quicksortCmp(T, array, left, j, cmp);54fn reverse(was: Cmp) -> Cmp {
69 if (i < right) quicksortCmp(T, array, i, right, cmp);55 return if (was == Cmp.Greater) Cmp.Less else if (was == Cmp.Less) Cmp.Greater else Cmp.Equal;
70}56}
7157
72// ---------------------------------------58// ---------------------------------------
...@@ -85,7 +71,7 @@ fn testSort() {...@@ -85,7 +71,7 @@ fn testSort() {
85 };71 };
8672
87 for (u8cases) |case| {73 for (u8cases) |case| {
88 sort(u8, case[0]);74 sort(u8, case[0], u8asc);
89 assert(str.eql(case[0], case[1]));75 assert(str.eql(case[0], case[1]));
90 }76 }
9177
...@@ -99,28 +85,14 @@ fn testSort() {...@@ -99,28 +85,14 @@ fn testSort() {
99 };85 };
10086
101 for (i32cases) |case| {87 for (i32cases) |case| {
102 sort(i32, case[0]);88 sort(i32, case[0], i32asc);
103 assert(str.sliceEql(i32, case[0], case[1]));89 assert(str.sliceEql(i32, case[0], case[1]));
104 }90 }
105}91}
10692
107fn testSortCmp() {93fn testSortDesc() {
108 @setFnTest(this, true);94 @setFnTest(this, true);
10995
110 const i32cases = [][][]i32 {
111 [][]i32{[]i32{}, []i32{}},
112 [][]i32{[]i32{1}, []i32{1}},
113 [][]i32{[]i32{0, 1}, []i32{0, 1}},
114 [][]i32{[]i32{1, 0}, []i32{0, 1}},
115 [][]i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}},
116 [][]i32{[]i32{2, 1, 3}, []i32{1, 2, 3}},
117 };
118
119 for (i32cases) |case| {
120 sortCmp(i32, case[0], normalCmp);
121 assert(str.sliceEql(i32, case[0], case[1]));
122 }
123
124 const revCases = [][][]i32 {96 const revCases = [][][]i32 {
125 [][]i32{[]i32{}, []i32{}},97 [][]i32{[]i32{}, []i32{}},
126 [][]i32{[]i32{1}, []i32{1}},98 [][]i32{[]i32{1}, []i32{1}},
...@@ -131,16 +103,9 @@ fn testSortCmp() {...@@ -131,16 +103,9 @@ fn testSortCmp() {
131 };103 };
132104
133 for (revCases) |case| {105 for (revCases) |case| {
134 sortCmp(i32, case[0], revCmp);106 sort(i32, case[0], i32desc);
135 assert(str.sliceEql(i32, case[0], case[1]));107 assert(str.sliceEql(i32, case[0], case[1]));
136 }108 }
137109
138}110}
139111
140fn normalCmp(a: i32, b: i32) -> Cmp {
141 return if (a > b) Cmp.Greater else if (a < b) Cmp.Less else Cmp.Equal;
142}
143
144fn revCmp(a: i32, b: i32) -> Cmp {
145 return if (a < b) Cmp.Greater else if (a > b) Cmp.Less else Cmp.Equal;
146}