forked from Kaggle/learntools
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathex4.py
More file actions
175 lines (139 loc) · 6.68 KB
/
ex4.py
File metadata and controls
175 lines (139 loc) · 6.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
from learntools.core.utils import bind_exercises
from learntools.core.problem import *
from learntools.core.richtext import *
CS = CodeSolution
# Complete fn that takes a list and returns the second element
class SelectSecondItem(FunctionProblem):
#TODO: Wrap index errors
_var = 'select_second'
_test_cases = [
([1, 2, 3], 2),
([[1], [2], [4]], [2]),
(list(range(10)), 1),
([1], None),
([], None),
]
_hint = "Python starts counting at 0. So the second item isn't indexed with a 2"
_solution = CS(
"""def select_second(L):
if len(L) < 2:
return None
return L[1]""")
class LosingTeamCaptain(FunctionProblem):
_var = 'losing_team_captain'
_test_cases = [
([["Paul", "John", "Ringo", "George"]], "John"),
([["Paul", "John", "Ringo", "George"], ["Jen", "Jamie"]], "Jamie"),
([["Who", "What", "I don't Know", "I'll tell you later"], ["Al", "Bonnie", "Clyde"]], "Bonnie"),
]
_hint = ("The last item in a list `L` can be selected with `L[-1]`."
" The first item in the first sublist would be selected as `L[0][0]`"
)
_solution = CS(
"""def losing_team_captain(teams):
return teams[-1][1]""")
class PurpleShell(FunctionProblem):
_var = 'purple_shell'
_hint = ("Your function should change the list it receives, but not return anything\n\n"
"To swap the list elements, think back to the code you used in the very first exercise to swap"
" two variables."
)
def check(self, fn):
lists = (["M","L"],
["M","L","J"],
[1,2,3,4,5]
)
def sol_fn(x): x[0], x[-1] = x[-1], x[0]
for l in lists:
copy_for_soln_fn = l.copy()
copy_for_user_fn = l.copy()
sol_fn(copy_for_soln_fn) # create desired output for comparison
user_output = fn(copy_for_user_fn) # also applies swap in this line
assert(type(user_output) == type(None)), ("Your function should not return anything."
" Instead, change the list without returning it.")
assert copy_for_user_fn == copy_for_soln_fn, (
"After running function on list {} expected its new value to be {}"
" but actually was {}").format(repr(l), repr(copy_for_soln_fn), repr(copy_for_user_fn))
_solution = CS(
"""def purple_shell(racers):
# One slick way to do the swap is x[0], x[-1] = x[-1], x[0].
temp = racers[0]
racers[0] = racers[-1]
racers[-1] = temp""")
class UnderstandLen(EqualityCheckProblem):
_var = 'lengths'
_expected = [3, 2, 0, 2]
_default_values = [ [] ]
_hint = "Use len to check the lengths of the lists. Call the solution function for an explanation"
_solution = (
"""
- a: There are three items in this list. Nothing tricky yet.
- b: The list `[2, 3]` counts as a single item. It has one item before it. So we have 2 items in the list
- c: The empty list has 0 items
- d: The expression is the same as the list `[2, 3]`, which has length 2.""")
class FashionablyLate(FunctionProblem):
_var = 'fashionably_late'
_test_cases = [
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "Adela"), False),
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "Fleda"), False),
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "Owen"), False),
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "May"), False),
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "Mona"), True),
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "Gilbert"), True),
((['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'], "Ford"), False),
((["Paul", "John", "Ringo", "George"], "John"), False),
((["Paul", "John", "Ringo", "George"], "Ringo"), True),
((["Lebron", "Kevin"], "Lebron"), False),
((["Lebron", "Kevin"], "Kevin"), False),
]
_hint = ("Use the index method to find when the person arrived. Check whether "
"that is a fashionably late spot given the list length (`len`). Think about 0-indexing"
)
_solution = CS(
"""def fashionably_late(arrivals, name):
order = arrivals.index(name)
return order >= len(arrivals) / 2 and order != len(arrivals) - 1""")
class CountNegativesRiddle(FunctionProblem):
_bonus = True
_var = 'count_negatives'
_test_cases = [
([], 0),
([0, -1, -1], 2),
([3, -3, 2, -1, 4, -4, 5, 5], 3),
([1, 2, 3, 4, 5, 0], 0),
]
_hint = ('Can you think of a way you could solve this problem if the input list'
' was guaranteed to be sorted and guaranteed to contain 0?')
_solution = """
Here's a non-obvious solution using only tools shown in the tutorial notebook:
```python
def count_negatives(nums):
nums.append(0)
# We could also have used the list.sort() method, which modifies a list, putting it in sorted order.
nums = sorted(nums)
return nums.index(0)
```
The above implementation relies on the fact that `list.index` returns the index of the *first* occurrence of a value. (You can verify this by calling `help(list.index)`.) So if, after sorting the list in ascending order, the value 0 is at index 0, then the number of negatives is 0. If 0 is at index 2 (i.e. the third element), then there are two elements smaller than 0. And so on.
*Note*: it's usually considered "impolite" to modify a list that someone passes to your function without giving them some warning (i.e. unless the docstring says that it modifies its input). So, if we wanted to be nice, we could have started by making a copy of nums using the `list.copy()` method (e.g. `our_nums = nums.copy()`), and then working with that copy rather than the original.
If you're a big Lisp fan, you might have written this technically compliant solution (we haven't talked about recursion, but I guess this doesn't use any syntax or functions we haven't seen yet...):
```python
def count_negatives(nums):
# Equivalent to "if len(nums) == 0". An empty list is 'falsey'.
if not nums:
return 0
else:
# Implicitly converting a boolean to an int! See question 6 of the
# exercise on booleans and conditionals
return (nums[0] < 0) + count_negatives(nums[1:])
```"""
qvars = bind_exercises(globals(), [
SelectSecondItem,
LosingTeamCaptain,
PurpleShell,
UnderstandLen,
FashionablyLate,
CountNegativesRiddle,
],
tutorial_id=108,
)
__all__ = list(qvars)