Skip to content

Commit 14781d7

Browse files
committed
fix existing approaches
1 parent 232c895 commit 14781d7

5 files changed

Lines changed: 54 additions & 37 deletions

File tree

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
{
22
"introduction": {
3-
"authors": ["safwansamsudeen"]
3+
"authors": ["safwansamsudeen"],
4+
"contributors": ["yrahcaz7"]
45
},
56
"approaches": [
67
{
78
"uuid": "db47397a-4551-49e8-8775-7e7aad79a38b",
89
"slug": "list-manipulation",
910
"title": "List manipulation",
1011
"blurb": "Manipulate and check lists to solve the exercise",
11-
"authors": ["safwansamsudeen"]
12+
"authors": ["safwansamsudeen"],
13+
"contributors": ["yrahcaz7"]
1214
},
1315
{
1416
"uuid": "61366160-c859-4d16-9085-171428209b8d",
1517
"slug": "using-strings",
1618
"title": "Using strings",
1719
"blurb": "Convert the lists to string and use string manipulation to solve the exercise",
18-
"authors": ["safwansamsudeen"]
20+
"authors": ["safwansamsudeen"],
21+
"contributors": ["yrahcaz7"]
1922
}
2023
]
2124
}

exercises/practice/sublist/.approaches/introduction.md

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# Introduction
2-
There are two broad ways to solve Sublist.
2+
3+
There are two broad ways to solve Sublist.
34

45
## General guidance
5-
To write the code, you need to branch out (probably with `if`) into the four different possible conditions, and return the appropriate name of the category.
6+
7+
To write the code, you need to branch out (probably with `if`) into the four different possible conditions, and return the appropriate name of the category.
68

79
## Approach: list manipulation
10+
811
The direct approach would be to manipulate and check the given lists to solve this.
912
This solution uses a helper function, which simplifies things, but the approach can be implemented without it.
1013

@@ -18,7 +21,7 @@ def check_sub_sequences(list_one, list_two):
1821
n1 = len(list_one)
1922
n2 = len(list_two)
2023
return any(list_two[i:i+n1] == list_one for i in range(n2 - n1 + 1))
21-
24+
2225
def sublist(list_one, list_two):
2326
if list_one == list_two:
2427
return EQUAL
@@ -32,27 +35,29 @@ def sublist(list_one, list_two):
3235
Read more on the [detail of this approach][approach-list-manipulation].
3336

3437
## Approach: using strings
35-
Another seemingly clever approach is to convert the lists to strings and then
36-
use the `in` operator to check for sub-sequences.
38+
39+
Another seemingly clever approach is to convert the lists to strings and then use the `in` operator to check for sub-sequences.
3740
**However, this does not work.**
41+
3842
```python
3943
SUBLIST = 1
4044
SUPERLIST = 2
4145
EQUAL = 3
4246
UNEQUAL = 4
4347

4448
def sublist(list_one, list_two):
45-
list_one_check = (str(list_one).strip("[]") + ",")
46-
list_two_check = (str(list_two).strip("[]") + ",")
47-
49+
list_one_check = str(list_one).strip("[]") + ","
50+
list_two_check = str(list_two).strip("[]") + ","
51+
4852
if list_one_check == list_two_check:
4953
return EQUAL
50-
elif list_one_check in list_two_check:
54+
if list_one_check in list_two_check:
5155
return SUBLIST
52-
elif list_two_check in list_one_check:
56+
if list_two_check in list_one_check:
5357
return SUPERLIST
5458
return UNEQUAL
5559
```
60+
5661
To understand more about this approach and **why it fails**, [read here][approach-using-strings].
5762

5863
[approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/list-manipulation

exercises/practice/sublist/.approaches/list-manipulation/content.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# List manipulation
2+
23
The direct approach would be to manipulate and check the given lists to solve this.
34
This solution uses a helper function, which simplifies things, but the approach can be implemented without it.
45

@@ -12,7 +13,7 @@ def check_sub_sequences(list_one, list_two):
1213
n1 = len(list_one)
1314
n2 = len(list_two)
1415
return any(list_two[i:i+n1] == list_one for i in range(n2 - n1 + 1))
15-
16+
1617
def sublist(list_one, list_two):
1718
if list_one == list_two:
1819
return EQUAL
@@ -23,16 +24,16 @@ def sublist(list_one, list_two):
2324
return UNEQUAL
2425
```
2526

26-
We first check for equality using the `==` operator, if so, then we return `EQUAL`.
27-
A common way to do this differently would be to return `1` directly, but this is better practice as we [remove magic values][magic values].
27+
We first check for equality using the `==` operator, if so, then we return `EQUAL`.
28+
A common way to do this differently would be to return `1` directly, but this is better practice as we [remove magic values][magic values].
2829

2930
After that we call `check_sub_sequences` passing in `list_one` and `list_two`.
3031
In the helper function, we check if `any` of the possible sub-sequences in `list_two` of length `n1` (the length of the first list) are equal to the first list.
31-
If so, then we conclude that `list_one` is a `SUBLIST` of `list_two`.
32+
If so, then we conclude that `list_one` is a `SUBLIST` of `list_two`.
3233

3334
To find whether `list_one` is a `SUPERLIST` of `list_two`, we just reverse this process - pass in the lists in the opposite order.
3435
Thus, we check if `any` of the possible sub-sequences in `list_one` of length `n2` (the length of the second list) are equal to the second list.
3536

3637
If none of the above conditions are true, we conclude that the two lists are unequal.
3738

38-
[magic values]: https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad
39+
[magic values]: https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad
Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Using strings
2+
23
~~~~exercism/caution
3-
**This approach does not work, and this document exists to explain that.**
4+
**This approach does not work, and this document exists to explain that.**
45
Please do not use it in your code.
56
~~~~
67

7-
Another seemingly clever solution is to convert the lists to strings and then
8-
use the `in` operator to check for sub-sequences.
9-
Note that this approach, even if it worked, is not as performant as the
10-
previous one.
8+
Another seemingly clever solution is to convert the lists to strings and then use the `in` operator to check for sub-sequences.
9+
Note that this approach, even if it worked, is not as performant as the previous one.
10+
1111
```python
1212
SUBLIST = 1
1313
SUPERLIST = 2
@@ -20,28 +20,36 @@ def sublist(list_one, list_two):
2020

2121
if list_one_check == list_two_check:
2222
return EQUAL
23-
elif list_one_check in list_two_check:
23+
if list_one_check in list_two_check:
2424
return SUBLIST
25-
elif list_two_check in list_one_check:
25+
if list_two_check in list_one_check:
2626
return SUPERLIST
2727
return UNEQUAL
2828
```
29+
2930
Let's parse the code to see what it does.
30-
In this approach, we convert the lists to strings, so `[1, 2, 3]` becomes `"[1, 2, 3]"`, remove the brackets `"1, 2, 3"`, and add a comma `"1, 2, 3,"`.
31+
In this approach, we convert the lists to strings, so `[1, 2, 3]` becomes `"[1, 2, 3]"`, remove the brackets `"1, 2, 3"`, and add a comma `"1, 2, 3,"`.
3132
We check equality and then use the `in` operator to check for `SUBLIST` or `SUPERLIST`, and finally return `UNEQUAL`.
3233

33-
We add a comma because, say, we call `sublist` with `[1, 2]` and `[1, 22]`. `"1, 2" in "1, 22"` evaluates to `True`, so
34-
the **function would wrongly mark it as `SUBLIST`**.
34+
We add a comma because, say, we call `sublist` with `[1, 2]` and `[1, 22]`. `"1, 2" in "1, 22"` evaluates to `True`, so the **function would wrongly mark it as `SUBLIST`**.
35+
36+
This case can be handled by changing the code like this:
37+
38+
```python
39+
list_one_check = str(list_one).strip("[]") + ","
40+
list_two_check = str(list_two).strip("[]") + ","
41+
```
42+
43+
Yet, even though the code would pass all of the tests in the Exercism test suite, it would still fail in some cases.
44+
For example, if we call `sublist` with `[1, 2]` and `[5, "1, 2,", 7]`, the function would return `SUBLIST` when it should actually return `UNEQUAL`.
45+
46+
This could be avoided by changing the code to use a separator that isn't the default one:
3547

36-
This test can be overridden by changing the code like this:
3748
```python
38-
list_one_check = str(list_one).strip("[]") + ','
39-
list_two_check = str(list_two).strip("[]") + ','
49+
list_one_check = "|".join(str(item) for item in list_one) + "|"
50+
list_two_check = "|".join(str(item) for item in list_two) + "|"
4051
```
41-
Yet, the test case (which doesn't exist in the Exercism test suite) `["1", "2"]` and `["5", "'1', '2',", "7"]` would
42-
fail.
4352

44-
Students can add any arbitrary string into the representation to try to "defeat" this test - `list_one_check = str
45-
(list_one) + TOKEN`. The test suite currently test `TOKEN = ''`, but not others.
53+
However, this only avoids the (theoretical) test and does not fix the solution. For example, a test with the inputs `[1, 2]` and `[5, "1|2|", 7]` would now fail.
4654

47-
[gen-exp]: https://www.programiz.com/python-programming/generator
55+
No matter what separator is chosen, there will always be at least one input for which the function will return the wrong result. **This is why no approach that converts the lists to strings can ever be correct for all possible inputs.**

exercises/practice/sublist/.approaches/using-strings/snippet.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
def sublist(list_one, list_two):
33
list_one_check = str(list_one).strip("[]")
44
...
5-
elif list_one_check in list_two_check:
5+
if list_one_check in list_two_check:
66
return SUBLIST
77
...
88
return UNEQUAL

0 commit comments

Comments
 (0)