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");
44
55pub 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) {
88 if (array.len > 0) {
9 quicksort(T, array, 0, array.len - 1);
9 quicksort(T, array, 0, array.len - 1, cmp);
1010 }
1111}
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) {
1414 var i = left;
1515 var j = right;
1616 var p = (i + j) / 2;
1717
1818 while (i <= j) {
19 while (array[i] < array[p]) {
19 while (cmp(array[i], array[p]) == Cmp.Less) {
2020 i += 1;
2121 }
22 while (array[j] > array[p]) {
22 while (cmp(array[j], array[p]) == Cmp.Greater) {
2323 j -= 1;
2424 }
2525 if (i <= j) {
......@@ -31,42 +31,28 @@ fn quicksort(inline T: type, array: []T, left: usize, right: usize) {
3131 }
3232 }
3333
34 if (left < j) quicksort(T, array, left, j);
35 if (i < right) quicksort(T, array, i, right);
34 if (left < j) quicksort(T, array, left, j, cmp);
35 if (i < right) quicksort(T, array, i, right, cmp);
3636}
3737
38// ---------------------------------------
39// sortCmp
38pub fn i32asc(a: i32, b: i32) -> Cmp {
39 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) {
42 if (array.len > 0) {
43 quicksortCmp(T, array, 0, array.len - 1, cmp);
44 }
42pub fn i32desc(a: i32, b: i32) -> Cmp {
43 return reverse(i32asc(a, b));
4544}
4645
47fn quicksortCmp(inline T: type, array: []T, left: usize, right: usize, inline cmp: fn(a: T, b: T)->Cmp) {
48 var i = left;
49 var j = right;
50 var p = (i + j) / 2;
46pub fn u8asc(a: u8, b: u8) -> Cmp {
47 return if (a > b) Cmp.Greater else if (a < b) Cmp.Less else Cmp.Equal;
48}
5149
52 while (i <= j) {
53 while (cmp(array[i], array[p]) == Cmp.Less) {
54 i += 1;
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 }
50pub fn u8desc(a: u8, b: u8) -> Cmp {
51 return reverse(u8asc(a, b));
52}
6753
68 if (left < j) quicksortCmp(T, array, left, j, cmp);
69 if (i < right) quicksortCmp(T, array, i, right, cmp);
54fn reverse(was: Cmp) -> Cmp {
55 return if (was == Cmp.Greater) Cmp.Less else if (was == Cmp.Less) Cmp.Greater else Cmp.Equal;
7056}
7157
7258// ---------------------------------------
......@@ -85,7 +71,7 @@ fn testSort() {
8571 };
8672
8773 for (u8cases) |case| {
88 sort(u8, case[0]);
74 sort(u8, case[0], u8asc);
8975 assert(str.eql(case[0], case[1]));
9076 }
9177
......@@ -99,28 +85,14 @@ fn testSort() {
9985 };
10086
10187 for (i32cases) |case| {
102 sort(i32, case[0]);
88 sort(i32, case[0], i32asc);
10389 assert(str.sliceEql(i32, case[0], case[1]));
10490 }
10591}
10692
107fn testSortCmp() {
93fn testSortDesc() {
10894 @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
12496 const revCases = [][][]i32 {
12597 [][]i32{[]i32{}, []i32{}},
12698 [][]i32{[]i32{1}, []i32{1}},
......@@ -131,16 +103,9 @@ fn testSortCmp() {
131103 };
132104
133105 for (revCases) |case| {
134 sortCmp(i32, case[0], revCmp);
106 sort(i32, case[0], i32desc);
135107 assert(str.sliceEql(i32, case[0], case[1]));
136108 }
137109
138110}
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}