const std = @import("std"); pub const IntersectionIterator = struct { ref: std.mem.TokenIterator(u8), rest: []const []const u8, /// Returns the next occurrence or null. Returned value is owned by originally passed slice pub fn next(self: *IntersectionIterator) ?[]const u8{ // If this returns null, there's no more items to check. We're finished. const needle = self.ref.next() orelse return null; // Search into every one of the strings haystack: for (self.rest) |haystack| { // The items are separated by spaces, iterate through those var haystack_iter = std.mem.tokenize(u8, haystack, " "); // If the word is found, it short circuits and tries the next haystack while (haystack_iter.next()) |hay_blade| { if (std.mem.eql(u8, hay_blade, needle)) continue :haystack; } // If this point is reached, the needle wasn't found. // Try the next one return self.next(); } // If we got here, no not-matching haysack was found. A match! return needle; } }; /// Finds the common tokens inside space separated strings /// and returns a slice to the first token that matches pub fn intersection(slices: []const []const u8) IntersectionIterator { // Tokenize the first entry and save the rest as references to check return IntersectionIterator{ .ref = std.mem.tokenize(u8, slices[0], " "), .rest = slices[1..], }; }