diff --git a/rust/sublist/.exercism/config.json b/rust/sublist/.exercism/config.json new file mode 100644 index 0000000..fa42dec --- /dev/null +++ b/rust/sublist/.exercism/config.json @@ -0,0 +1,37 @@ +{ + "authors": [ + "EduardoBautista" + ], + "contributors": [ + "ashleygwilliams", + "coriolinus", + "cwhakes", + "eddyp", + "EduardoBautista", + "efx", + "ErikSchierboom", + "IanWhitney", + "kytrinyx", + "lutostag", + "mkantor", + "nfiles", + "petertseng", + "rofrol", + "stringparser", + "xakon", + "ZapAnton" + ], + "files": { + "solution": [ + "src/lib.rs", + "Cargo.toml" + ], + "test": [ + "tests/sublist.rs" + ], + "example": [ + ".meta/example.rs" + ] + }, + "blurb": "Write a function to determine if a list is a sublist of another list." +} diff --git a/rust/sublist/.gitignore b/rust/sublist/.gitignore new file mode 100644 index 0000000..96ef6c0 --- /dev/null +++ b/rust/sublist/.gitignore @@ -0,0 +1,2 @@ +/target +Cargo.lock diff --git a/rust/sublist/Cargo.toml b/rust/sublist/Cargo.toml new file mode 100644 index 0000000..c900a2e --- /dev/null +++ b/rust/sublist/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "sublist" +version = "0.1.0" +edition = "2024" + +# Not all libraries from crates.io are available in Exercism's test runner. +# The full list of available libraries is here: +# https://github.com/exercism/rust-test-runner/blob/main/local-registry/Cargo.toml +[dependencies] diff --git a/rust/sublist/HELP.md b/rust/sublist/HELP.md new file mode 100644 index 0000000..22a6c00 --- /dev/null +++ b/rust/sublist/HELP.md @@ -0,0 +1,89 @@ +# Help + +## Running the tests + +Execute the tests with: + +```bash +$ cargo test +``` + +All but the first test have been ignored. After you get the first test to +pass, open the tests source file which is located in the `tests` directory +and remove the `#[ignore]` flag from the next test and get the tests to pass +again. Each separate test is a function with `#[test]` flag above it. +Continue, until you pass every test. + +If you wish to run _only ignored_ tests without editing the tests source file, use: + +```bash +$ cargo test -- --ignored +``` + +If you are using Rust 1.51 or later, you can run _all_ tests with + +```bash +$ cargo test -- --include-ignored +``` + +To run a specific test, for example `some_test`, you can use: + +```bash +$ cargo test some_test +``` + +If the specific test is ignored, use: + +```bash +$ cargo test some_test -- --ignored +``` + +To learn more about Rust tests refer to the online [test documentation][rust-tests]. + +[rust-tests]: https://doc.rust-lang.org/book/ch11-02-running-tests.html + +## Submitting your solution + +You can submit your solution using the `exercism submit src/lib.rs Cargo.toml` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Rust track's documentation](https://exercism.org/docs/tracks/rust) +- The [Rust track's programming category on the forum](https://forum.exercism.org/c/programming/rust) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +## Rust Installation + +Refer to the [exercism help page][help-page] for Rust installation and learning +resources. + +## Submitting the solution + +Generally you should submit all files in which you implemented your solution (`src/lib.rs` in most cases). If you are using any external crates, please consider submitting the `Cargo.toml` file. This will make the review process faster and clearer. + +## Feedback, Issues, Pull Requests + +Head to [the forum](https://forum.exercism.org/c/programming/rust/) and create a post to provide feedback about an exercise or if you want to help implement new exercises. +Members of the rust track team are happy to help! + +The GitHub [track repository][github] is the home for all of the Rust exercises. + +If you want to know more about Exercism, take a look at the [contribution guide]. + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + +[help-page]: https://exercism.org/tracks/rust/learning +[github]: https://github.com/exercism/rust +[contribution guide]: https://exercism.org/docs/community/contributors \ No newline at end of file diff --git a/rust/sublist/README.md b/rust/sublist/README.md new file mode 100644 index 0000000..26bc897 --- /dev/null +++ b/rust/sublist/README.md @@ -0,0 +1,56 @@ +# Sublist + +Welcome to Sublist on Exercism's Rust Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## 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 + +## Source + +### Created by + +- @EduardoBautista + +### Contributed to by + +- @ashleygwilliams +- @coriolinus +- @cwhakes +- @eddyp +- @EduardoBautista +- @efx +- @ErikSchierboom +- @IanWhitney +- @kytrinyx +- @lutostag +- @mkantor +- @nfiles +- @petertseng +- @rofrol +- @stringparser +- @xakon +- @ZapAnton \ No newline at end of file diff --git a/rust/sublist/src/lib.rs b/rust/sublist/src/lib.rs new file mode 100644 index 0000000..75636a0 --- /dev/null +++ b/rust/sublist/src/lib.rs @@ -0,0 +1,40 @@ +#[derive(Debug, PartialEq, Eq)] +pub enum Comparison { + Equal, + Sublist, + Superlist, + Unequal, +} + +trait SublistSearcher { + fn contains_slice(&self, sublist: &[T]) -> bool; +} + +impl SublistSearcher for [T] +where + T: PartialEq, +{ + fn contains_slice(&self, sublist: &[T]) -> bool { + self.is_empty() && sublist.is_empty() + || (!sublist.is_empty() && self.windows(sublist.len()).any(|x| x == sublist)) + } +} + +pub fn sublist(first_list: &[i32], second_list: &[i32]) -> Comparison { + match (first_list.len(), second_list.len()) { + (len_1, len_2) if len_1 == len_2 && first_list == second_list => Comparison::Equal, + (len_1, len_2) + if second_list.is_empty() && !first_list.is_empty() + || (len_1 > len_2 && first_list.contains_slice(second_list)) => + { + Comparison::Superlist + } + (len_1, len_2) + if first_list.is_empty() && !second_list.is_empty() + || (len_1 < len_2 && second_list.contains_slice(first_list)) => + { + Comparison::Sublist + } + _ => Comparison::Unequal, + } +} diff --git a/rust/sublist/tests/sublist.rs b/rust/sublist/tests/sublist.rs new file mode 100644 index 0000000..2dbe97b --- /dev/null +++ b/rust/sublist/tests/sublist.rs @@ -0,0 +1,163 @@ +use sublist::*; + +#[test] +fn empty_lists() { + let list_one: &[i32] = &[]; + let list_two: &[i32] = &[]; + let output = sublist(list_one, list_two); + let expected = Comparison::Equal; + assert_eq!(output, expected); +} + +#[test] +fn empty_list_within_non_empty_list() { + let list_one: &[i32] = &[]; + let list_two: &[i32] = &[1, 2, 3]; + let output = sublist(list_one, list_two); + let expected = Comparison::Sublist; + assert_eq!(output, expected); +} + +#[test] +fn non_empty_list_contains_empty_list() { + let list_one: &[i32] = &[1, 2, 3]; + let list_two: &[i32] = &[]; + let output = sublist(list_one, list_two); + let expected = Comparison::Superlist; + assert_eq!(output, expected); +} + +#[test] +fn list_equals_itself() { + let list_one: &[i32] = &[1, 2, 3]; + let list_two: &[i32] = &[1, 2, 3]; + let output = sublist(list_one, list_two); + let expected = Comparison::Equal; + assert_eq!(output, expected); +} + +#[test] +fn different_lists() { + let list_one: &[i32] = &[1, 2, 3]; + let list_two: &[i32] = &[2, 3, 4]; + let output = sublist(list_one, list_two); + let expected = Comparison::Unequal; + assert_eq!(output, expected); +} + +#[test] +fn false_start() { + let list_one: &[i32] = &[1, 2, 5]; + let list_two: &[i32] = &[0, 1, 2, 3, 1, 2, 5, 6]; + let output = sublist(list_one, list_two); + let expected = Comparison::Sublist; + assert_eq!(output, expected); +} + +#[test] +fn consecutive() { + let list_one: &[i32] = &[1, 1, 2]; + let list_two: &[i32] = &[0, 1, 1, 1, 2, 1, 2]; + let output = sublist(list_one, list_two); + let expected = Comparison::Sublist; + assert_eq!(output, expected); +} + +#[test] +fn sublist_at_start() { + let list_one: &[i32] = &[0, 1, 2]; + let list_two: &[i32] = &[0, 1, 2, 3, 4, 5]; + let output = sublist(list_one, list_two); + let expected = Comparison::Sublist; + assert_eq!(output, expected); +} + +#[test] +fn sublist_in_middle() { + let list_one: &[i32] = &[2, 3, 4]; + let list_two: &[i32] = &[0, 1, 2, 3, 4, 5]; + let output = sublist(list_one, list_two); + let expected = Comparison::Sublist; + assert_eq!(output, expected); +} + +#[test] +fn sublist_at_end() { + let list_one: &[i32] = &[3, 4, 5]; + let list_two: &[i32] = &[0, 1, 2, 3, 4, 5]; + let output = sublist(list_one, list_two); + let expected = Comparison::Sublist; + assert_eq!(output, expected); +} + +#[test] +fn at_start_of_superlist() { + let list_one: &[i32] = &[0, 1, 2, 3, 4, 5]; + let list_two: &[i32] = &[0, 1, 2]; + let output = sublist(list_one, list_two); + let expected = Comparison::Superlist; + assert_eq!(output, expected); +} + +#[test] +fn in_middle_of_superlist() { + let list_one: &[i32] = &[0, 1, 2, 3, 4, 5]; + let list_two: &[i32] = &[2, 3]; + let output = sublist(list_one, list_two); + let expected = Comparison::Superlist; + assert_eq!(output, expected); +} + +#[test] +fn at_end_of_superlist() { + let list_one: &[i32] = &[0, 1, 2, 3, 4, 5]; + let list_two: &[i32] = &[3, 4, 5]; + let output = sublist(list_one, list_two); + let expected = Comparison::Superlist; + assert_eq!(output, expected); +} + +#[test] +fn first_list_missing_element_from_second_list() { + let list_one: &[i32] = &[1, 3]; + let list_two: &[i32] = &[1, 2, 3]; + let output = sublist(list_one, list_two); + let expected = Comparison::Unequal; + assert_eq!(output, expected); +} + +#[test] +fn second_list_missing_element_from_first_list() { + let list_one: &[i32] = &[1, 2, 3]; + let list_two: &[i32] = &[1, 3]; + let output = sublist(list_one, list_two); + let expected = Comparison::Unequal; + assert_eq!(output, expected); +} + +#[test] +fn first_list_missing_additional_digits_from_second_list() { + let list_one: &[i32] = &[1, 2]; + let list_two: &[i32] = &[1, 22]; + let output = sublist(list_one, list_two); + let expected = Comparison::Unequal; + assert_eq!(output, expected); +} + +#[test] +fn order_matters_to_a_list() { + let list_one: &[i32] = &[1, 2, 3]; + let list_two: &[i32] = &[3, 2, 1]; + let output = sublist(list_one, list_two); + let expected = Comparison::Unequal; + assert_eq!(output, expected); +} + +#[test] +fn same_digits_but_different_numbers() { + let list_one: &[i32] = &[1, 0, 1]; + let list_two: &[i32] = &[10, 1]; + let output = sublist(list_one, list_two); + let expected = Comparison::Unequal; + assert_eq!(output, expected); +}