Skip to content

Commit

Permalink
Reveal reference solutions (#133)
Browse files Browse the repository at this point in the history
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Simone Baffelli <[email protected]>
Co-authored-by: edoardob90 <[email protected]>
  • Loading branch information
4 people authored Aug 31, 2023
1 parent 5da0ace commit 285620b
Show file tree
Hide file tree
Showing 12 changed files with 573 additions and 324 deletions.
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ ignore =
E501
W503
E203
TRY301
per-file-ignores =
binder/ipython_config.py:E266
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,4 @@ dmypy.json
.DS_Store
*_files/
*.html
.idea/
10 changes: 10 additions & 0 deletions .mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[mypy]
; Do not warn about missing return statements
warn_no_return = False
; Show error messages in context
show_error_context = True
; Allow untyped definitions and calls
disallow_untyped_defs = False
disallow_untyped_calls = False
; Disable import errors
disable_error_code = import
2 changes: 1 addition & 1 deletion binder/ipython_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Configuration file for ipython.

c = get_config() # noqa
c = get_config() # noqa # type: ignore

# ------------------------------------------------------------------------------
# InteractiveShellApp(Configurable) configuration
Expand Down
7 changes: 1 addition & 6 deletions magic_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,8 @@
"%%ipytest\n",
"# or %%ipytest test_module_name\n",
"\n",
"len('a')\n",
"def solution_power2(x: int) -> int:\n",
" print('hi')\n",
" len('b')\n",
" print(len('bb'))\n",
" return x ** 2\n",
"len('aaa')"
" return x * 2"
]
},
{
Expand Down
32 changes: 14 additions & 18 deletions tutorial/tests/test_control_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def is_prime(num: int) -> bool:
return True


def reference_solution_find_factors(num: int) -> List[int]:
def reference_find_factors(num: int) -> List[int]:
"""Dumb way to find the factors of an integer"""
if is_prime(num):
return [1, num]
Expand All @@ -149,7 +149,7 @@ def reference_solution_find_factors(num: int) -> List[int]:

@pytest.mark.parametrize("num", [350, 487, 965, 816, 598, 443, 13, 17, 211])
def test_find_factors(num: int, function_to_test) -> None:
assert function_to_test(num) == reference_solution_find_factors(num)
assert function_to_test(num) == reference_find_factors(num)


#
Expand All @@ -162,7 +162,7 @@ def test_find_factors(num: int, function_to_test) -> None:
)


def reference_solution_find_pair(nums: List[int]) -> int:
def reference_find_pair(nums: List[int]) -> int:
"""Reference solution (part 1)"""
complements = {}
for num in nums:
Expand All @@ -173,10 +173,10 @@ def reference_solution_find_pair(nums: List[int]) -> int:

@pytest.mark.parametrize("nums", [nums_1, nums_2])
def test_find_pair(nums: List[int], function_to_test) -> None:
assert function_to_test(nums) == reference_solution_find_pair(nums)
assert function_to_test(nums) == reference_find_pair(nums)


def reference_solution_find_triplet_slow(nums: List[int]) -> int:
def reference_find_triplet_slow(nums: List[int]) -> int:
"""Reference solution (part 2), O(n^3)"""
n = len(nums)
for i in range(n - 2):
Expand All @@ -186,7 +186,7 @@ def reference_solution_find_triplet_slow(nums: List[int]) -> int:
return nums[i] * nums_2[j] * nums[k]


def reference_solution_find_triplet(nums: List[int]) -> int:
def reference_find_triplet(nums: List[int]) -> int:
"""Reference solution (part 2), O(n^2)"""
n = len(nums)
for i in range(n - 1):
Expand All @@ -201,15 +201,15 @@ def reference_solution_find_triplet(nums: List[int]) -> int:

@pytest.mark.parametrize("nums", [nums_1, nums_2])
def test_find_triplet(nums: List[int], function_to_test) -> None:
assert function_to_test(nums) == reference_solution_find_triplet(nums)
assert function_to_test(nums) == reference_find_triplet(nums)


#
# Exercise 3: Cats with hats
#


def reference_solution_cats_with_hats() -> int:
def reference_cats_with_hats() -> int:
"""Solution with dictionaries"""
cats = {i: False for i in range(1, 101)}

Expand All @@ -222,7 +222,7 @@ def reference_solution_cats_with_hats() -> int:


def test_cats_with_hats(function_to_test) -> None:
assert function_to_test() == reference_solution_cats_with_hats()
assert function_to_test() == reference_cats_with_hats()


#
Expand All @@ -241,9 +241,7 @@ def parse_data(filename: str) -> List[List[int]]:
trees_1, trees_2 = (parse_data(f"trees_{num}.txt") for num in (1, 2))


def reference_solution_toboggan_p1(
trees_map: List[List[int]], right: int, down: int
) -> int:
def reference_toboggan_p1(trees_map: List[List[int]], right: int, down: int) -> int:
"""Reference solution (part 1)"""
start, trees, depth, width = [0, 0], 0, len(trees_map), len(trees_map[0])
while start[0] < depth:
Expand All @@ -262,18 +260,16 @@ def reference_solution_toboggan_p1(
def test_toboggan_p1(
trees_map: List[List[int]], right: int, down: int, function_to_test
) -> None:
assert function_to_test(trees_map, right, down) == reference_solution_toboggan_p1(
assert function_to_test(trees_map, right, down) == reference_toboggan_p1(
trees_map, right, down
)


def reference_solution_toboggan_p2(
trees_map: List[List[int]], slopes: Tuple[Tuple[int]]
) -> int:
def reference_toboggan_p2(trees_map: List[List[int]], slopes: Tuple[Tuple[int]]) -> int:
"""Reference solution (part 2)"""
total = 1
for right, down in slopes:
total *= reference_solution_toboggan_p1(trees_map, right, down)
total *= reference_toboggan_p1(trees_map, right, down)
return total


Expand All @@ -293,6 +289,6 @@ def reference_solution_toboggan_p2(
def test_toboggan_p2(
trees_map: List[List[int]], slopes: Tuple[Tuple[int]], function_to_test
) -> None:
assert function_to_test(trees_map, slopes) == reference_solution_toboggan_p2(
assert function_to_test(trees_map, slopes) == reference_toboggan_p2(
trees_map, slopes
)
43 changes: 20 additions & 23 deletions tutorial/tests/test_functional_programming.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from numpy.typing import NDArray


def reference_solution_exercise2(my_list: List[int], k: int):
def reference_exercise2(my_list: List[int], k: int) -> List[int]:
return [i for i in my_list if i % k == 0]


Expand All @@ -24,7 +24,7 @@ def check_for_loop_in_body(fun: Callable) -> bool:
return False


def reference_solution_filter_even(my_list: "list[int]") -> "list[int]":
def reference_filter_even(my_list: List[int]) -> List[int]:
return list(filter(lambda x: x % 2 == 0, my_list))


Expand All @@ -39,15 +39,15 @@ def reference_solution_filter_even(my_list: "list[int]") -> "list[int]":
def test_filter_even(function_to_test: Callable, my_list: List[int]):
res = function_to_test(my_list)
assert type(res) == list, "The function you wrote does not return a list"
assert res == reference_solution_filter_even(
assert res == reference_filter_even(
my_list
), "The list you return is not equal to the expected solution"
assert not check_for_loop_in_body(
function_to_test
), "You are not allowed to use a for loop in this exercise"


def reference_solution_add_one(my_list: List[int]) -> List[int]:
def reference_add_one(my_list: List[int]) -> List[int]:
return list(map(lambda x: x + 1, my_list)) # noqa: C417


Expand All @@ -60,7 +60,7 @@ def reference_solution_add_one(my_list: List[int]) -> List[int]:
],
)
def test_add_one(function_to_test: Callable, my_list: List[int]):
assert function_to_test(my_list) == reference_solution_add_one(
assert function_to_test(my_list) == reference_add_one(
my_list
), "The list you return is not equal to the expected solution"
assert not check_for_loop_in_body(
Expand All @@ -76,14 +76,14 @@ def test_add_one(function_to_test: Callable, my_list: List[int]):
],
)
def test_exercise2(
function_to_test: Callable[[int, int], int],
function_to_test: Callable[[List[int]], int],
my_list: List[int],
k: int,
):
assert function_to_test(my_list, k) == reference_solution_exercise2(my_list, k)
assert function_to_test(my_list, k) == reference_exercise2(my_list, k)


def reference_solution_exercise3(x: List[List[int]]) -> List[List[int]]:
def reference_exercise3(x: List[List[int]]) -> List[List[int]]:
return [list(i) for i in zip(*x)]


Expand All @@ -96,28 +96,27 @@ def test_exercise3(
):
res = function_to_test(my_input.tolist())
assert (
res == reference_solution_exercise3(my_input.tolist())
res == reference_exercise3(my_input.tolist())
and res == my_input.transpose().tolist()
)


def reference_solution_exercise4(my_list: List[List[Any]]) -> List[Any]:
def reference_exercise4(my_list: List[List[Any]]) -> List[Any]:
return functools.reduce(lambda x, y: x + y, my_list)


@pytest.mark.parametrize(
"my_input, reference_func",
"my_input",
[
([[1, 2, 3, 4], [4, 5, 5], [4, 5, 6]], reference_solution_exercise4),
([["a", "b", "c"], ["d", "f", "e"], ["another"]], reference_solution_exercise4),
[[1, 2, 3, 4], [4, 5, 5], [4, 5, 6]],
[["a", "b", "c"], ["d", "f", "e"], ["another"]],
],
)
def test_exercise4(
function_to_test: Callable[[List[List[any]]], List[Any]],
function_to_test: Callable[[List[List[Any]]], List[Any]],
my_input: List[List[Any]],
reference_func: Callable,
):
assert function_to_test(my_input) == reference_func(my_input)
assert function_to_test(my_input) == reference_exercise4(my_input)


@functools.lru_cache
Expand All @@ -126,7 +125,7 @@ def get_data_exercise5() -> List[str]:
return words.splitlines()


def reference_solution_exercise5(w: List[str]) -> List[Tuple[str, int]]:
def reference_exercise5(w: List[str]) -> List[Tuple[str, int]]:
return [
(k, len(list(v)))
for k, v in itertools.groupby(sorted(w, key=lambda x: x[0]), key=lambda x: x[0])
Expand All @@ -135,21 +134,19 @@ def reference_solution_exercise5(w: List[str]) -> List[Tuple[str, int]]:

def test_exercise5(function_to_test: Callable[[List[str]], List[Tuple[str, int]]]):
data = get_data_exercise5()
assert function_to_test(data) == reference_solution_exercise5(data)
assert function_to_test(data) == reference_exercise5(data)


def reference_solution_exercise6(
my_list: List[Tuple[str, int]]
) -> List[Tuple[str, float]]:
def reference_exercise6(my_list: List[Tuple[str, int]]) -> List[Tuple[str, float]]:
total = sum(map(lambda x: x[1], my_list)) # noqa: C417
return [(letter, freq / total) for letter, freq in my_list]


def test_exercise6(
function_to_test: Callable[[List[Tuple[str, int]]], List[Tuple[str, float]]]
):
input_data = reference_solution_exercise5(get_data_exercise5())
assert function_to_test(input_data) == reference_solution_exercise6(input_data)
input_data = reference_exercise5(get_data_exercise5())
assert function_to_test(input_data) == reference_exercise6(input_data)


def reference_function_exercise7(my_list: List[str]) -> List[str]:
Expand Down
Loading

0 comments on commit 285620b

Please sign in to comment.