From 100b8a244cdbcd16669e6b81ab82d6a628559e22 Mon Sep 17 00:00:00 2001 From: Mikhail Popov Date: Fri, 22 Oct 2021 14:38:08 +0200 Subject: [PATCH] Add std.mem.minMax() and std.mem.IndexOfMinMax() For finding the minimum and maximum values (and indices) in a slice in a single pass. --- lib/std/mem.zig | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index a69d1dcda0..6d5ae952eb 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -2174,6 +2174,26 @@ test "mem.max" { try testing.expectEqual(max(u8, "g"), 'g'); } +/// Finds the smallest and largest number in a slice. O(n). +/// Returns an anonymous struct with the fields `min` and `max`. +/// `slice` must not be empty. +pub fn minMax(comptime T: type, slice: []const T) struct { min: T, max: T } { + assert(slice.len > 0); + var minVal = slice[0]; + var maxVal = slice[0]; + for (slice[1..]) |item| { + minVal = math.min(minVal, item); + maxVal = math.max(maxVal, item); + } + return .{ .min = minVal, .max = maxVal }; +} + +test "mem.minMax" { + try testing.expectEqual(minMax(u8, "abcdefg"), .{ .min = 'a', .max = 'g' }); + try testing.expectEqual(minMax(u8, "bcdefga"), .{ .min = 'a', .max = 'g' }); + try testing.expectEqual(minMax(u8, "a"), .{ .min = 'a', .max = 'a' }); +} + /// Returns the index of the smallest number in a slice. O(n). /// `slice` must not be empty. pub fn indexOfMin(comptime T: type, slice: []const T) usize { @@ -2216,6 +2236,34 @@ test "mem.indexOfMax" { try testing.expectEqual(indexOfMax(u8, "a"), 0); } +/// Finds the indices of the smallest and largest number in a slice. O(n). +/// Returns an anonymous struct with the fields `index_min` and `index_max`. +/// `slice` must not be empty. +pub fn indexOfMinMax(comptime T: type, slice: []const T) struct { index_min: usize, index_max: usize } { + assert(slice.len > 0); + var minVal = slice[0]; + var maxVal = slice[0]; + var minIdx: usize = 0; + var maxIdx: usize = 0; + for (slice[1..]) |item, i| { + if (item < minVal) { + minVal = item; + minIdx = i + 1; + } + if (item > maxVal) { + maxVal = item; + maxIdx = i + 1; + } + } + return .{ .index_min = minIdx, .index_max = maxIdx }; +} + +test "mem.indexOfMinMax" { + try testing.expectEqual(indexOfMinMax(u8, "abcdefg"), .{ .index_min = 0, .index_max = 6 }); + try testing.expectEqual(indexOfMinMax(u8, "gabcdef"), .{ .index_min = 1, .index_max = 0 }); + try testing.expectEqual(indexOfMinMax(u8, "a"), .{ .index_min = 0, .index_max = 0 }); +} + pub fn swap(comptime T: type, a: *T, b: *T) void { const tmp = a.*; a.* = b.*;