Skip to content

Commit

Permalink
Add sublist (#593)
Browse files Browse the repository at this point in the history
* Add `sublist`

* Fix stub class name

Co-authored-by: Glenn Jackman <[email protected]>

---------

Co-authored-by: Glenn Jackman <[email protected]>
  • Loading branch information
BNAndras and glennj authored Sep 26, 2024
1 parent a3f55f3 commit f22c834
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@
"stacks"
]
},
{
"slug": "sublist",
"name": "Sublist",
"uuid": "fe7d5efd-dae8-4d49-9604-e029da900ca1",
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "word-count",
"name": "Word Count",
Expand Down
25 changes: 25 additions & 0 deletions exercises/practice/sublist/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -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 sub-sequence of values equal to `B`.
List `A` is a sublist of `B` if `B` contains a 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
17 changes: 17 additions & 0 deletions exercises/practice/sublist/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"authors": [
"BNAndras"
],
"files": {
"solution": [
"lib/sublist.dart"
],
"test": [
"test/sublist_test.dart"
],
"example": [
".meta/lib/example.dart"
]
},
"blurb": "Write a function to determine if a list is a sublist of another list."
}
46 changes: 46 additions & 0 deletions exercises/practice/sublist/.meta/lib/example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import 'package:collection/collection.dart';

enum Classification { equal, unequal, sublist, superlist }

class Sublist {
Function eq = const ListEquality().equals;

Classification sublist(List<int> listOne, List<int> listTwo) {
if (listOne.isEmpty && listTwo.isEmpty) {
return Classification.equal;
} else if (listOne.isEmpty) {
return Classification.sublist;
} else if (listTwo.isEmpty) {
return Classification.superlist;
}

if (isSublist(listOne, listTwo)) {
return listOne.length < listTwo.length
? Classification.sublist
: Classification.equal;
}

if (isSublist(listTwo, listOne)) {
return listOne.length > listTwo.length
? Classification.superlist
: Classification.equal;
}

return Classification.unequal;
}

bool isSublist(List<int> listOne, List<int> listTwo) {
if (listOne.length > listTwo.length) {
return false;
}

for (int i = 0; i <= listTwo.length - listOne.length; i++) {
final fragment = listTwo.slice(i, i + listOne.length);
if (eq(fragment, listOne)) {
return true;
}
}

return false;
}
}
64 changes: 64 additions & 0 deletions exercises/practice/sublist/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -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"
18 changes: 18 additions & 0 deletions exercises/practice/sublist/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
analyzer:
strong-mode:
implicit-casts: false
implicit-dynamic: false
errors:
unused_element: error
unused_import: error
unused_local_variable: error
dead_code: error

linter:
rules:
# Error Rules
- avoid_relative_lib_imports
- avoid_types_as_parameter_names
- literal_only_boolean_expressions
- no_adjacent_strings_in_list
- valid_regexps
5 changes: 5 additions & 0 deletions exercises/practice/sublist/lib/sublist.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Implement the Classification enum.

class Sublist {
// your code here...
}
5 changes: 5 additions & 0 deletions exercises/practice/sublist/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
name: 'sublist'
environment:
sdk: '>=3.2.0 <4.0.0'
dev_dependencies:
test: '<2.0.0'
152 changes: 152 additions & 0 deletions exercises/practice/sublist/test/sublist_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import 'package:sublist/sublist.dart';
import 'package:test/test.dart';

void main() {
final sublist = Sublist();

group('Sublist', () {
test('empty lists', () {
List<int> listOne = [];
List<int> listTwo = [];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.equal;
expect(result, equals(expected));
}, skip: false);

test('empty list within non empty list', () {
List<int> listOne = [];
List<int> listTwo = [1, 2, 3];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.sublist;
expect(result, equals(expected));
}, skip: true);

test('non empty list contains empty list', () {
List<int> listOne = [1, 2, 3];
List<int> listTwo = [];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.superlist;
expect(result, equals(expected));
}, skip: true);

test('list equals itself', () {
List<int> listOne = [1, 2, 3];
List<int> listTwo = [1, 2, 3];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.equal;
expect(result, equals(expected));
}, skip: true);

test('different lists', () {
List<int> listOne = [1, 2, 3];
List<int> listTwo = [2, 3, 4];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.unequal;
expect(result, equals(expected));
}, skip: true);

test('false start', () {
List<int> listOne = [1, 2, 5];
List<int> listTwo = [0, 1, 2, 3, 1, 2, 5, 6];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.sublist;
expect(result, equals(expected));
}, skip: true);

test('consecutive', () {
List<int> listOne = [1, 1, 2];
List<int> listTwo = [0, 1, 1, 1, 2, 1, 2];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.sublist;
expect(result, equals(expected));
}, skip: true);

test('sublist at start', () {
List<int> listOne = [0, 1, 2];
List<int> listTwo = [0, 1, 2, 3, 4, 5];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.sublist;
expect(result, equals(expected));
}, skip: true);

test('sublist in middle', () {
List<int> listOne = [2, 3, 4];
List<int> listTwo = [0, 1, 2, 3, 4, 5];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.sublist;
expect(result, equals(expected));
}, skip: true);

test('sublist at end', () {
List<int> listOne = [3, 4, 5];
List<int> listTwo = [0, 1, 2, 3, 4, 5];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.sublist;
expect(result, equals(expected));
}, skip: true);

test('at start of superlist', () {
List<int> listOne = [0, 1, 2, 3, 4, 5];
List<int> listTwo = [0, 1, 2];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.superlist;
expect(result, equals(expected));
}, skip: true);

test('in middle of superlist', () {
List<int> listOne = [0, 1, 2, 3, 4, 5];
List<int> listTwo = [2, 3];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.superlist;
expect(result, equals(expected));
}, skip: true);

test('at end of superlist', () {
List<int> listOne = [0, 1, 2, 3, 4, 5];
List<int> listTwo = [3, 4, 5];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.superlist;
expect(result, equals(expected));
}, skip: true);

test('first list missing element from second list', () {
List<int> listOne = [1, 3];
List<int> listTwo = [1, 2, 3];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.unequal;
expect(result, equals(expected));
}, skip: true);

test('second list missing element from first list', () {
List<int> listOne = [1, 2, 3];
List<int> listTwo = [1, 3];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.unequal;
expect(result, equals(expected));
}, skip: true);

test('first list missing additional digits from second list', () {
List<int> listOne = [1, 2];
List<int> listTwo = [1, 22];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.unequal;
expect(result, equals(expected));
}, skip: true);

test('order matters to a list', () {
List<int> listOne = [1, 2, 3];
List<int> listTwo = [3, 2, 1];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.unequal;
expect(result, equals(expected));
}, skip: true);

test('same digits but different numbers', () {
List<int> listOne = [1, 0, 1];
List<int> listTwo = [10, 1];
final result = sublist.sublist(listOne, listTwo);
final expected = Classification.unequal;
expect(result, equals(expected));
}, skip: true);
});
}

0 comments on commit f22c834

Please sign in to comment.