diff --git a/config.json b/config.json index a5e83711..78101a0a 100644 --- a/config.json +++ b/config.json @@ -182,9 +182,17 @@ ], "difficulty": 1 }, + { + "slug": "sublist", + "name": "Sublist", + "uuid": "a2c7d511-7f80-410b-923f-0343d0770d81", + "practices": [], + "prerequisites": [], + "difficulty": 3 + }, { "slug": "run-length-encoding", - "name": "Run Length Encoding", + "name": "Run-Length Encoding", "uuid": "71e5d918-6327-442a-98e8-3f9560b1ecd9", "practices": [], "prerequisites": [], diff --git a/exercises/practice/sublist/.docs/instructions.md b/exercises/practice/sublist/.docs/instructions.md new file mode 100644 index 00000000..8228edc6 --- /dev/null +++ b/exercises/practice/sublist/.docs/instructions.md @@ -0,0 +1,25 @@ +# Instructions + +Given any two lists `A` and `B`, determine if: + +- List `A` is equal to list `B`; or +- List `A` contains list `B` (`A` is a superlist of `B`); or +- List `A` is contained by list `B` (`A` is a sublist of `B`); or +- None of the above is true, thus lists `A` and `B` are unequal + +Specifically, list `A` is equal to list `B` if both lists have the same values in the same order. +List `A` is a superlist of `B` if `A` contains a contiguous sub-sequence of values equal to `B`. +List `A` is a sublist of `B` if `B` contains a contiguous sub-sequence of values equal to `A`. + +Examples: + +- If `A = []` and `B = []` (both lists are empty), then `A` and `B` are equal +- If `A = [1, 2, 3]` and `B = []`, then `A` is a superlist of `B` +- If `A = []` and `B = [1, 2, 3]`, then `A` is a sublist of `B` +- If `A = [1, 2, 3]` and `B = [1, 2, 3, 4, 5]`, then `A` is a sublist of `B` +- If `A = [3, 4, 5]` and `B = [1, 2, 3, 4, 5]`, then `A` is a sublist of `B` +- If `A = [3, 4]` and `B = [1, 2, 3, 4, 5]`, then `A` is a sublist of `B` +- If `A = [1, 2, 3]` and `B = [1, 2, 3]`, then `A` and `B` are equal +- If `A = [1, 2, 3, 4, 5]` and `B = [2, 3, 4]`, then `A` is a superlist of `B` +- If `A = [1, 2, 4]` and `B = [1, 2, 3, 4, 5]`, then `A` and `B` are unequal +- If `A = [1, 2, 3]` and `B = [1, 3, 2]`, then `A` and `B` are unequal diff --git a/exercises/practice/sublist/.meta/config.json b/exercises/practice/sublist/.meta/config.json new file mode 100644 index 00000000..8124bd0e --- /dev/null +++ b/exercises/practice/sublist/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "keiravillekode" + ], + "files": { + "solution": [ + "sublist.zig" + ], + "test": [ + "test_sublist.zig" + ], + "example": [ + ".meta/example.zig" + ] + }, + "blurb": "Write a function to determine if a list is a sublist of another list." +} diff --git a/exercises/practice/sublist/.meta/example.zig b/exercises/practice/sublist/.meta/example.zig new file mode 100644 index 00000000..5c0ede4c --- /dev/null +++ b/exercises/practice/sublist/.meta/example.zig @@ -0,0 +1,36 @@ +pub const Relation = enum { + equal, + sublist, + superlist, + unequal, +}; + +fn isEqual(list_one: []const i32, list_two: []const i32) bool { + if (list_one.len != list_two.len) { + return false; + } + + for (0..(list_one.len)) |i| { + if (list_one[i] != list_two[i]) { + return false; + } + } + + return true; +} + +fn isSublist(list_one: []const i32, list_two: []const i32) bool { + return isEqual(list_one, list_two[0..(list_one.len)]) or ((list_one.len < list_two.len) and isSublist(list_one, list_two[1..])); +} + +pub fn compare(list_one: []const i32, list_two: []const i32) Relation { + if (isEqual(list_one, list_two)) { + return .equal; + } else if (list_one.len <= list_two.len and isSublist(list_one, list_two)) { + return .sublist; + } else if (list_two.len <= list_one.len and isSublist(list_two, list_one)) { + return .superlist; + } else { + return .unequal; + } +} diff --git a/exercises/practice/sublist/.meta/tests.toml b/exercises/practice/sublist/.meta/tests.toml new file mode 100644 index 00000000..de5020a9 --- /dev/null +++ b/exercises/practice/sublist/.meta/tests.toml @@ -0,0 +1,64 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[97319c93-ebc5-47ab-a022-02a1980e1d29] +description = "empty lists" + +[de27dbd4-df52-46fe-a336-30be58457382] +description = "empty list within non empty list" + +[5487cfd1-bc7d-429f-ac6f-1177b857d4fb] +description = "non empty list contains empty list" + +[1f390b47-f6b2-4a93-bc23-858ba5dda9a6] +description = "list equals itself" + +[7ed2bfb2-922b-4363-ae75-f3a05e8274f5] +description = "different lists" + +[3b8a2568-6144-4f06-b0a1-9d266b365341] +description = "false start" + +[dc39ed58-6311-4814-be30-05a64bc8d9b1] +description = "consecutive" + +[d1270dab-a1ce-41aa-b29d-b3257241ac26] +description = "sublist at start" + +[81f3d3f7-4f25-4ada-bcdc-897c403de1b6] +description = "sublist in middle" + +[43bcae1e-a9cf-470e-923e-0946e04d8fdd] +description = "sublist at end" + +[76cf99ed-0ff0-4b00-94af-4dfb43fe5caa] +description = "at start of superlist" + +[b83989ec-8bdf-4655-95aa-9f38f3e357fd] +description = "in middle of superlist" + +[26f9f7c3-6cf6-4610-984a-662f71f8689b] +description = "at end of superlist" + +[0a6db763-3588-416a-8f47-76b1cedde31e] +description = "first list missing element from second list" + +[83ffe6d8-a445-4a3c-8795-1e51a95e65c3] +description = "second list missing element from first list" + +[7bc76cb8-5003-49ca-bc47-cdfbe6c2bb89] +description = "first list missing additional digits from second list" + +[0d7ee7c1-0347-45c8-9ef5-b88db152b30b] +description = "order matters to a list" + +[5f47ce86-944e-40f9-9f31-6368aad70aa6] +description = "same digits but different numbers" diff --git a/exercises/practice/sublist/sublist.zig b/exercises/practice/sublist/sublist.zig new file mode 100644 index 00000000..786e6367 --- /dev/null +++ b/exercises/practice/sublist/sublist.zig @@ -0,0 +1,12 @@ +pub const Relation = enum { + equal, + sublist, + superlist, + unequal, +}; + +pub fn compare(list_one: []const i32, list_two: []const i32) Relation { + _ = list_one; + _ = list_two; + @compileError("please implement the compare function"); +} diff --git a/exercises/practice/sublist/test_sublist.zig b/exercises/practice/sublist/test_sublist.zig new file mode 100644 index 00000000..5a4bae81 --- /dev/null +++ b/exercises/practice/sublist/test_sublist.zig @@ -0,0 +1,148 @@ +const std = @import("std"); +const testing = std.testing; + +const sublist = @import("sublist.zig"); + +test "empty lists" { + const list_one = &[_]i32{}; + const list_two = &[_]i32{}; + const expected = .equal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "empty list within non empty list" { + const list_one = &[_]i32{}; + const list_two = &[_]i32{ 1, 2, 3 }; + const expected = .sublist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "non empty list contains empty list" { + const list_one = &[_]i32{ 1, 2, 3 }; + const list_two = &[_]i32{}; + const expected = .superlist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "list equals itself" { + const list_one = &[_]i32{ 1, 2, 3 }; + const list_two = &[_]i32{ 1, 2, 3 }; + const expected = .equal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "different lists" { + const list_one = &[_]i32{ 1, 2, 3 }; + const list_two = &[_]i32{ 2, 3, 4 }; + const expected = .unequal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "false start" { + const list_one = &[_]i32{ 1, 2, 5 }; + const list_two = &[_]i32{ 0, 1, 2, 3, 1, 2, 5, 6 }; + const expected = .sublist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "consecutive" { + const list_one = &[_]i32{ 1, 1, 2 }; + const list_two = &[_]i32{ 0, 1, 1, 1, 2, 1, 2 }; + const expected = .sublist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "sublist at start" { + const list_one = &[_]i32{ 0, 1, 2 }; + const list_two = &[_]i32{ 0, 1, 2, 3, 4, 5 }; + const expected = .sublist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "sublist in middle" { + const list_one = &[_]i32{ 2, 3, 4 }; + const list_two = &[_]i32{ 0, 1, 2, 3, 4, 5 }; + const expected = .sublist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "sublist at end" { + const list_one = &[_]i32{ 3, 4, 5 }; + const list_two = &[_]i32{ 0, 1, 2, 3, 4, 5 }; + const expected = .sublist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "at start of superlist" { + const list_one = &[_]i32{ 0, 1, 2, 3, 4, 5 }; + const list_two = &[_]i32{ 0, 1, 2 }; + const expected = .superlist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "in middle of superlist" { + const list_one = &[_]i32{ 0, 1, 2, 3, 4, 5 }; + const list_two = &[_]i32{ 2, 3 }; + const expected = .superlist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "at end of superlist" { + const list_one = &[_]i32{ 0, 1, 2, 3, 4, 5 }; + const list_two = &[_]i32{ 3, 4, 5 }; + const expected = .superlist; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "first list missing element from second list" { + const list_one = &[_]i32{ 1, 3 }; + const list_two = &[_]i32{ 1, 2, 3 }; + const expected = .unequal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "second list missing element from first list" { + const list_one = &[_]i32{ 1, 2, 3 }; + const list_two = &[_]i32{ 1, 3 }; + const expected = .unequal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "first list missing additional digits from second list" { + const list_one = &[_]i32{ 1, 2 }; + const list_two = &[_]i32{ 1, 22 }; + const expected = .unequal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "order matters to a list" { + const list_one = &[_]i32{ 1, 2, 3 }; + const list_two = &[_]i32{ 3, 2, 1 }; + const expected = .unequal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +} + +test "same digits but different numbers" { + const list_one = &[_]i32{ 1, 0, 1 }; + const list_two = &[_]i32{ 10, 1 }; + const expected = .unequal; + const actual = sublist.compare(list_one, list_two); + try testing.expectEqual(expected, actual); +}