From 52f8e83274886826ac44894419988f1bcb176f73 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Fri, 7 Apr 2023 15:40:16 -0700 Subject: [PATCH 1/3] list-ops: add foldl canonical test; bring foldr in line with canonical specs and add canonical test --- .../practice/list-ops/.meta/additional_tests.json | 4 ++-- exercises/practice/list-ops/.meta/example.py | 2 +- exercises/practice/list-ops/.meta/template.j2 | 1 - exercises/practice/list-ops/.meta/tests.toml | 2 -- exercises/practice/list-ops/list_ops_test.py | 10 +++++++++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/exercises/practice/list-ops/.meta/additional_tests.json b/exercises/practice/list-ops/.meta/additional_tests.json index 7eb1d65c76..39c0a8bfa6 100644 --- a/exercises/practice/list-ops/.meta/additional_tests.json +++ b/exercises/practice/list-ops/.meta/additional_tests.json @@ -6,7 +6,7 @@ "input": { "list": ["e", "x", "e", "r", "c", "i", "s", "m"], "initial": "!", - "function": "(x, y) -> x + y" + "function": "(acc, el) -> el + acc" }, "expected": "exercism!" }, @@ -19,4 +19,4 @@ "expected": [1, "cat", 4.0, "xyz"] } ] -} \ No newline at end of file +} diff --git a/exercises/practice/list-ops/.meta/example.py b/exercises/practice/list-ops/.meta/example.py index ee43248f99..75f45033e2 100644 --- a/exercises/practice/list-ops/.meta/example.py +++ b/exercises/practice/list-ops/.meta/example.py @@ -29,7 +29,7 @@ def foldr(function, list, initial): if len(list) == 0: return initial else: - return function(list[0], foldr(function, list[1:], initial)) + return function(foldr(function, list[1:], initial), list[0]) def reverse(list): diff --git a/exercises/practice/list-ops/.meta/template.j2 b/exercises/practice/list-ops/.meta/template.j2 index c346d3c20f..cc28280f17 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -2,7 +2,6 @@ {% macro lambdify(function) -%} {% set function = function.replace("(", "", 1).replace(")", "", 1).replace(" ->", ":") %} {% set function = function.replace("modulo", "%") %} - {% set function = function.replace("/", "//") %} lambda {{function}} {%- endmacro %} diff --git a/exercises/practice/list-ops/.meta/tests.toml b/exercises/practice/list-ops/.meta/tests.toml index 7fe3c8d1a9..08b1edc044 100644 --- a/exercises/practice/list-ops/.meta/tests.toml +++ b/exercises/practice/list-ops/.meta/tests.toml @@ -71,7 +71,6 @@ reimplements = "e56df3eb-9405-416a-b13a-aabb4c3b5194" [d7fcad99-e88e-40e1-a539-4c519681f390] description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list" reimplements = "d2cf5644-aee1-4dfc-9b88-06896676fe27" -include = false [aeb576b9-118e-4a57-a451-db49fac20fdc] description = "folds (reduces) the given list from the right with a function -> empty list" @@ -96,7 +95,6 @@ reimplements = "c4b64e58-313e-4c47-9c68-7764964efb8e" [8066003b-f2ff-437e-9103-66e6df474844] description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list" reimplements = "be396a53-c074-4db3-8dd6-f7ed003cce7c" -include = false [94231515-050e-4841-943d-d4488ab4ee30] description = "reverse the elements of the list -> empty list" diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index cff6156dc6..a2a301295a 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -63,12 +63,18 @@ def test_foldl_empty_list(self): def test_foldl_direction_independent_function_applied_to_non_empty_list(self): self.assertEqual(foldl(lambda acc, el: el + acc, [1, 2, 3, 4], 5), 15) + def test_foldl_direction_dependent_function_applied_to_non_empty_list(self): + self.assertEqual(foldl(lambda acc, el: el / acc, [1, 2, 3, 4], 24), 64) + def test_foldr_empty_list(self): self.assertEqual(foldr(lambda acc, el: el * acc, [], 2), 2) def test_foldr_direction_independent_function_applied_to_non_empty_list(self): self.assertEqual(foldr(lambda acc, el: el + acc, [1, 2, 3, 4], 5), 15) + def test_foldr_direction_dependent_function_applied_to_non_empty_list(self): + self.assertEqual(foldr(lambda acc, el: el / acc, [1, 2, 3, 4], 24), 9) + def test_reverse_empty_list(self): self.assertEqual(reverse([]), []) @@ -84,7 +90,9 @@ def test_reverse_list_of_lists_is_not_flattened(self): def test_foldr_foldr_add_string(self): self.assertEqual( - foldr(lambda x, y: x + y, ["e", "x", "e", "r", "c", "i", "s", "m"], "!"), + foldr( + lambda acc, el: el + acc, ["e", "x", "e", "r", "c", "i", "s", "m"], "!" + ), "exercism!", ) From 16c72bd0883b4b6ce341d9be6bef7e0d0fb31f35 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Mon, 10 Apr 2023 19:46:21 -0700 Subject: [PATCH 2/3] list-ops tests: swap foldr args order to use func(el, acc) --- exercises/practice/list-ops/.meta/example.py | 2 +- exercises/practice/list-ops/.meta/template.j2 | 10 +++++++++- exercises/practice/list-ops/list_ops_test.py | 8 ++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/exercises/practice/list-ops/.meta/example.py b/exercises/practice/list-ops/.meta/example.py index 75f45033e2..ee43248f99 100644 --- a/exercises/practice/list-ops/.meta/example.py +++ b/exercises/practice/list-ops/.meta/example.py @@ -29,7 +29,7 @@ def foldr(function, list, initial): if len(list) == 0: return initial else: - return function(foldr(function, list[1:], initial), list[0]) + return function(list[0], foldr(function, list[1:], initial)) def reverse(list): diff --git a/exercises/practice/list-ops/.meta/template.j2 b/exercises/practice/list-ops/.meta/template.j2 index cc28280f17..be224ff251 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -1,4 +1,10 @@ {%- import "generator_macros.j2" as macros with context -%} +{% macro swap_args(function) -%} + {% set function = function.replace("(acc, el)", "(el, acc)") %} + {% set function = function.replace("(x, y)", "(y, x)") %} + {{function}} +{%- endmacro %} + {% macro lambdify(function) -%} {% set function = function.replace("(", "", 1).replace(")", "", 1).replace(" ->", ":") %} {% set function = function.replace("modulo", "%") %} @@ -29,8 +35,10 @@ {{ lambdify(input["function"]) }}, {{ input["list"] }} {%- elif case["property"] == "length" or case["property"] == "reverse" -%} {{ input["list"] }} - {%- elif case["property"] == "foldl" or case["property"] == "foldr" -%} + {%- elif case["property"] == "foldl" -%} {{ lambdify(input["function"]) }}, {{ input["list"] }}, {{ stringify(input["initial"]) }} + {%- elif case["property"] == "foldr" -%} + {{ lambdify(swap_args(input["function"])) }}, {{ input["list"] }}, {{ stringify(input["initial"]) }} {%- endif -%} ), {{ stringify(case["expected"]) }} diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index a2a301295a..617be353c6 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -67,13 +67,13 @@ def test_foldl_direction_dependent_function_applied_to_non_empty_list(self): self.assertEqual(foldl(lambda acc, el: el / acc, [1, 2, 3, 4], 24), 64) def test_foldr_empty_list(self): - self.assertEqual(foldr(lambda acc, el: el * acc, [], 2), 2) + self.assertEqual(foldr(lambda el, acc: el * acc, [], 2), 2) def test_foldr_direction_independent_function_applied_to_non_empty_list(self): - self.assertEqual(foldr(lambda acc, el: el + acc, [1, 2, 3, 4], 5), 15) + self.assertEqual(foldr(lambda el, acc: el + acc, [1, 2, 3, 4], 5), 15) def test_foldr_direction_dependent_function_applied_to_non_empty_list(self): - self.assertEqual(foldr(lambda acc, el: el / acc, [1, 2, 3, 4], 24), 9) + self.assertEqual(foldr(lambda el, acc: el / acc, [1, 2, 3, 4], 24), 9) def test_reverse_empty_list(self): self.assertEqual(reverse([]), []) @@ -91,7 +91,7 @@ def test_reverse_list_of_lists_is_not_flattened(self): def test_foldr_foldr_add_string(self): self.assertEqual( foldr( - lambda acc, el: el + acc, ["e", "x", "e", "r", "c", "i", "s", "m"], "!" + lambda el, acc: el + acc, ["e", "x", "e", "r", "c", "i", "s", "m"], "!" ), "exercism!", ) From 0c240c24b0e2bf013fe1ea4cf9ce8fa46ed9e639 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Wed, 12 Apr 2023 15:15:21 -0700 Subject: [PATCH 3/3] Make foldl also call func(el, acc) --- exercises/practice/list-ops/.meta/example.py | 2 +- exercises/practice/list-ops/.meta/template.j2 | 4 +--- exercises/practice/list-ops/list_ops_test.py | 6 +++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/exercises/practice/list-ops/.meta/example.py b/exercises/practice/list-ops/.meta/example.py index ee43248f99..eac3b3c774 100644 --- a/exercises/practice/list-ops/.meta/example.py +++ b/exercises/practice/list-ops/.meta/example.py @@ -22,7 +22,7 @@ def foldl(function, list, initial): if len(list) == 0: return initial else: - return foldl(function, list[1:], function(initial, list[0])) + return foldl(function, list[1:], function(list[0], initial)) def foldr(function, list, initial): diff --git a/exercises/practice/list-ops/.meta/template.j2 b/exercises/practice/list-ops/.meta/template.j2 index be224ff251..76c97ace37 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -35,9 +35,7 @@ {{ lambdify(input["function"]) }}, {{ input["list"] }} {%- elif case["property"] == "length" or case["property"] == "reverse" -%} {{ input["list"] }} - {%- elif case["property"] == "foldl" -%} - {{ lambdify(input["function"]) }}, {{ input["list"] }}, {{ stringify(input["initial"]) }} - {%- elif case["property"] == "foldr" -%} + {%- elif case["property"] == "foldl" or case["property"] == "foldr" -%} {{ lambdify(swap_args(input["function"])) }}, {{ input["list"] }}, {{ stringify(input["initial"]) }} {%- endif -%} ), diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index 617be353c6..94dd32e0d5 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -58,13 +58,13 @@ def test_map_non_empty_list(self): self.assertEqual(list_ops_map(lambda x: x + 1, [1, 3, 5, 7]), [2, 4, 6, 8]) def test_foldl_empty_list(self): - self.assertEqual(foldl(lambda acc, el: el * acc, [], 2), 2) + self.assertEqual(foldl(lambda el, acc: el * acc, [], 2), 2) def test_foldl_direction_independent_function_applied_to_non_empty_list(self): - self.assertEqual(foldl(lambda acc, el: el + acc, [1, 2, 3, 4], 5), 15) + self.assertEqual(foldl(lambda el, acc: el + acc, [1, 2, 3, 4], 5), 15) def test_foldl_direction_dependent_function_applied_to_non_empty_list(self): - self.assertEqual(foldl(lambda acc, el: el / acc, [1, 2, 3, 4], 24), 64) + self.assertEqual(foldl(lambda el, acc: el / acc, [1, 2, 3, 4], 24), 64) def test_foldr_empty_list(self): self.assertEqual(foldr(lambda el, acc: el * acc, [], 2), 2)