authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-04 14:25:00-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-12-04 14:25:00-05:00
log44e896f613b8fa9b74e3fa992b265d8a5f052aad
treeccdf27338c13dcf7d77d6b5477fa37ad98f80dd9
parent137cb32f5e586bdd74dcc65b734b54d26080dfee
parent841a37ab597d3075c1cb15dc5280e04b48eafa27
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3844 from Snektron/sort-improvements

Small sort improvements

1 files changed, 108 insertions(+), 8 deletions(-)

lib/std/sort.zig+108-8
......@@ -1189,24 +1189,124 @@ fn fuzzTest(rng: *std.rand.Random) void {
11891189 }
11901190}
11911191
1192pub fn min(comptime T: type, items: []T, lessThan: fn (lhs: T, rhs: T) bool) T {
1193 var i: usize = 0;
1192pub fn argMin(comptime T: type, items: []const T, lessThan: fn (lhs: T, rhs: T) bool) ?usize {
1193 if (items.len == 0) {
1194 return null;
1195 }
1196
11941197 var smallest = items[0];
1195 for (items[1..]) |item| {
1198 var smallest_index: usize = 0;
1199 for (items[1..]) |item, i| {
11961200 if (lessThan(item, smallest)) {
11971201 smallest = item;
1202 smallest_index = i + 1;
11981203 }
11991204 }
1200 return smallest;
1205
1206 return smallest_index;
12011207}
12021208
1203pub fn max(comptime T: type, items: []T, lessThan: fn (lhs: T, rhs: T) bool) T {
1204 var i: usize = 0;
1209test "std.sort.argMin" {
1210 testing.expectEqual(@as(?usize, null), argMin(i32, &[_]i32{}, asc(i32)));
1211 testing.expectEqual(@as(?usize, 0), argMin(i32, &[_]i32{1}, asc(i32)));
1212 testing.expectEqual(@as(?usize, 0), argMin(i32, &[_]i32{ 1, 2, 3, 4, 5 }, asc(i32)));
1213 testing.expectEqual(@as(?usize, 3), argMin(i32, &[_]i32{ 9, 3, 8, 2, 5 }, asc(i32)));
1214 testing.expectEqual(@as(?usize, 0), argMin(i32, &[_]i32{ 1, 1, 1, 1, 1 }, asc(i32)));
1215 testing.expectEqual(@as(?usize, 0), argMin(i32, &[_]i32{ -10, 1, 10 }, asc(i32)));
1216 testing.expectEqual(@as(?usize, 3), argMin(i32, &[_]i32{ 6, 3, 5, 7, 6 }, desc(i32)));
1217}
1218
1219pub fn min(comptime T: type, items: []const T, lessThan: fn (lhs: T, rhs: T) bool) ?T {
1220 const i = argMin(T, items, lessThan) orelse return null;
1221 return items[i];
1222}
1223
1224test "std.sort.min" {
1225 testing.expectEqual(@as(?i32, null), min(i32, &[_]i32{}, asc(i32)));
1226 testing.expectEqual(@as(?i32, 1), min(i32, &[_]i32{1}, asc(i32)));
1227 testing.expectEqual(@as(?i32, 1), min(i32, &[_]i32{ 1, 2, 3, 4, 5 }, asc(i32)));
1228 testing.expectEqual(@as(?i32, 2), min(i32, &[_]i32{ 9, 3, 8, 2, 5 }, asc(i32)));
1229 testing.expectEqual(@as(?i32, 1), min(i32, &[_]i32{ 1, 1, 1, 1, 1 }, asc(i32)));
1230 testing.expectEqual(@as(?i32, -10), min(i32, &[_]i32{ -10, 1, 10 }, asc(i32)));
1231 testing.expectEqual(@as(?i32, 7), min(i32, &[_]i32{ 6, 3, 5, 7, 6 }, desc(i32)));
1232}
1233
1234pub fn argMax(comptime T: type, items: []const T, lessThan: fn (lhs: T, rhs: T) bool) ?usize {
1235 if (items.len == 0) {
1236 return null;
1237 }
1238
12051239 var biggest = items[0];
1206 for (items[1..]) |item| {
1240 var biggest_index: usize = 0;
1241 for (items[1..]) |item, i| {
12071242 if (lessThan(biggest, item)) {
12081243 biggest = item;
1244 biggest_index = i + 1;
12091245 }
12101246 }
1211 return biggest;
1247
1248 return biggest_index;
1249}
1250
1251test "std.sort.argMax" {
1252 testing.expectEqual(@as(?usize, null), argMax(i32, &[_]i32{}, asc(i32)));
1253 testing.expectEqual(@as(?usize, 0), argMax(i32, &[_]i32{1}, asc(i32)));
1254 testing.expectEqual(@as(?usize, 4), argMax(i32, &[_]i32{ 1, 2, 3, 4, 5 }, asc(i32)));
1255 testing.expectEqual(@as(?usize, 0), argMax(i32, &[_]i32{ 9, 3, 8, 2, 5 }, asc(i32)));
1256 testing.expectEqual(@as(?usize, 0), argMax(i32, &[_]i32{ 1, 1, 1, 1, 1 }, asc(i32)));
1257 testing.expectEqual(@as(?usize, 2), argMax(i32, &[_]i32{ -10, 1, 10 }, asc(i32)));
1258 testing.expectEqual(@as(?usize, 1), argMax(i32, &[_]i32{ 6, 3, 5, 7, 6 }, desc(i32)));
1259}
1260
1261pub fn max(comptime T: type, items: []const T, lessThan: fn (lhs: T, rhs: T) bool) ?T {
1262 const i = argMax(T, items, lessThan) orelse return null;
1263 return items[i];
1264}
1265
1266test "std.sort.max" {
1267 testing.expectEqual(@as(?i32, null), max(i32, &[_]i32{}, asc(i32)));
1268 testing.expectEqual(@as(?i32, 1), max(i32, &[_]i32{1}, asc(i32)));
1269 testing.expectEqual(@as(?i32, 5), max(i32, &[_]i32{ 1, 2, 3, 4, 5 }, asc(i32)));
1270 testing.expectEqual(@as(?i32, 9), max(i32, &[_]i32{ 9, 3, 8, 2, 5 }, asc(i32)));
1271 testing.expectEqual(@as(?i32, 1), max(i32, &[_]i32{ 1, 1, 1, 1, 1 }, asc(i32)));
1272 testing.expectEqual(@as(?i32, 10), max(i32, &[_]i32{ -10, 1, 10 }, asc(i32)));
1273 testing.expectEqual(@as(?i32, 3), max(i32, &[_]i32{ 6, 3, 5, 7, 6 }, desc(i32)));
1274}
1275
1276pub fn isSorted(comptime T: type, items: []const T, lessThan: fn (lhs: T, rhs: T) bool) bool {
1277 var i: usize = 1;
1278 while (i < items.len) : (i += 1) {
1279 if (lessThan(items[i], items[i - 1])) {
1280 return false;
1281 }
1282 }
1283
1284 return true;
1285}
1286
1287test "std.sort.isSorted" {
1288 testing.expect(isSorted(i32, &[_]i32{}, asc(i32)));
1289 testing.expect(isSorted(i32, &[_]i32{10}, asc(i32)));
1290 testing.expect(isSorted(i32, &[_]i32{ 1, 2, 3, 4, 5 }, asc(i32)));
1291 testing.expect(isSorted(i32, &[_]i32{ -10, 1, 1, 1, 10 }, asc(i32)));
1292
1293 testing.expect(isSorted(i32, &[_]i32{}, desc(i32)));
1294 testing.expect(isSorted(i32, &[_]i32{-20}, desc(i32)));
1295 testing.expect(isSorted(i32, &[_]i32{ 3, 2, 1, 0, -1 }, desc(i32)));
1296 testing.expect(isSorted(i32, &[_]i32{ 10, -10 }, desc(i32)));
1297
1298 testing.expect(isSorted(i32, &[_]i32{ 1, 1, 1, 1, 1 }, asc(i32)));
1299 testing.expect(isSorted(i32, &[_]i32{ 1, 1, 1, 1, 1 }, desc(i32)));
1300
1301 testing.expectEqual(false, isSorted(i32, &[_]i32{ 5, 4, 3, 2, 1 }, asc(i32)));
1302 testing.expectEqual(false, isSorted(i32, &[_]i32{ 1, 2, 3, 4, 5 }, desc(i32)));
1303
1304 testing.expect(isSorted(u8, "abcd", asc(u8)));
1305 testing.expect(isSorted(u8, "zyxw", desc(u8)));
1306
1307 testing.expectEqual(false, isSorted(u8, "abcd", desc(u8)));
1308 testing.expectEqual(false, isSorted(u8, "zyxw", asc(u8)));
1309
1310 testing.expect(isSorted(u8, "ffff", asc(u8)));
1311 testing.expect(isSorted(u8, "ffff", desc(u8)));
12121312}