diff options
Diffstat (limited to 'util/mem.zig')
-rw-r--r-- | util/mem.zig | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/util/mem.zig b/util/mem.zig index 89ba67b..3b68dad 100644 --- a/util/mem.zig +++ b/util/mem.zig @@ -1,5 +1,7 @@ const std = @import("std"); + const math = std.math; +const testing_allocator = std.testing.allocator; /// Returns the position of the smallest number in a slice. pub fn min_idx(comptime T: type, slice: []const T) usize { @@ -15,3 +17,60 @@ pub fn min_idx(comptime T: type, slice: []const T) usize { } return idx; } + +/// Returns a slice of the duplicated values amongst all slices. +/// { {1,2,3,4}, {4,5,6,1} } -> {1,4} +pub fn dupl_values(comptime T: type, allocator: std.mem.Allocator, haystacks: []const []const T) ![]T { + var haystacks_maps = blk: { + var r = std.ArrayList(std.AutoHashMap(T, bool)).init(allocator); + for (haystacks) |haystack| { + var haystack_map = std.AutoHashMap(T, bool).init(allocator); + for (haystack) |item| { + try haystack_map.put(item, true); + } + try r.append(haystack_map); + } + break :blk r.toOwnedSlice(); + }; + + defer blk: { + for (haystacks_maps) |*haystack| { + haystack.deinit(); + } + allocator.free(haystacks_maps); + break :blk; + } + + var dupl = std.ArrayList(T).init(allocator); + var seen = std.AutoHashMap(T, bool).init(allocator); + defer seen.deinit(); + + for (haystacks[0]) |item| { + if (seen.contains(item)) + continue; + + try seen.put(item, true); + + var duplicated = true; + + for (haystacks_maps[1..]) |map| { + if (!map.contains(item)) { + duplicated = false; + continue; + } + } + + if (duplicated) + try dupl.append(item); + } + + return dupl.toOwnedSlice(); +} + +test "dupl_values" { + const haystack = [_][]const u8{ &[_]u8{ 1, 2, 3, 1 }, &[_]u8{ 2, 3, 1, 5 }, &[_]u8{ 3, 2, 1, 4 } }; + var foo = try dupl_values(u8, testing_allocator, &haystack); + defer testing_allocator.free(foo); + + try std.testing.expect(std.mem.eql(u8, foo, &[_]u8{ 1, 2, 3 })); +} |