From fe9334b06fe3b0fd0401dd14b1bf1faca3ee689c Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Thu, 16 Sep 2021 21:55:36 -0600 Subject: [PATCH 01/27] add secrets draft --- .../list-comprehensions/.meta/config.json | 2 +- concepts/list-comprehensions/links.json | 23 +++------ exercises/concept/secrets/.docs/hints.md | 0 .../concept/secrets/.docs/instructions.md | 49 +++++++++++++++++++ .../concept/secrets/.docs/introduction.md | 24 +++++++++ exercises/concept/secrets/.meta/exemplar.py | 11 +++++ exercises/concept/secrets/secrets.py | 11 +++++ exercises/concept/secrets/secrets_test.py | 33 +++++++++++++ 8 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 exercises/concept/secrets/.docs/hints.md create mode 100644 exercises/concept/secrets/.docs/instructions.md create mode 100644 exercises/concept/secrets/.docs/introduction.md create mode 100644 exercises/concept/secrets/.meta/exemplar.py create mode 100644 exercises/concept/secrets/secrets.py create mode 100644 exercises/concept/secrets/secrets_test.py diff --git a/concepts/list-comprehensions/.meta/config.json b/concepts/list-comprehensions/.meta/config.json index 9b9e8da5a9..888a5496ff 100644 --- a/concepts/list-comprehensions/.meta/config.json +++ b/concepts/list-comprehensions/.meta/config.json @@ -1,5 +1,5 @@ { "blurb": "TODO: add blurb for this concept", - "authors": ["bethanyg", "cmccandless"], + "authors": ["Steffan153"], "contributors": [] } diff --git a/concepts/list-comprehensions/links.json b/concepts/list-comprehensions/links.json index eb5fb7c38a..bec0b4a373 100644 --- a/concepts/list-comprehensions/links.json +++ b/concepts/list-comprehensions/links.json @@ -1,18 +1,9 @@ [ - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - } + { "description": "Python Docs: Defining Functions", "url": "https://docs.python.org/3/tutorial/controlflow.html#defining-functions" }, + { "description": "Python Docs Tutorial: Lambda Expressions", "url": "https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions" }, + { "description": "Functions as Objects in Python", "url": "https://medium.com/python-pandemonium/function-as-objects-in-python-d5215e6d1b0d" }, + { "description": "Composing Programs: Higher-Order Functions", "url": "https://composingprograms.com/pages/16-higher-order-functions.html" }, + { "description": "Learn by Example: Python Lambda Function", "url": "https://www.learnbyexample.org/python-lambda-function/" }, + { "description": "Real Python: How to Use Python Lambda Fuctions", "url": "https://realpython.com/python-lambda/" }, + { "description": "Trey Hunner: Overusing Lambda expressions in Python", "url": "https://treyhunner.com/2018/09/stop-writing-lambda-expressions/" } ] diff --git a/exercises/concept/secrets/.docs/hints.md b/exercises/concept/secrets/.docs/hints.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/exercises/concept/secrets/.docs/instructions.md b/exercises/concept/secrets/.docs/instructions.md new file mode 100644 index 0000000000..3054084dd6 --- /dev/null +++ b/exercises/concept/secrets/.docs/instructions.md @@ -0,0 +1,49 @@ +# Instructions + +In this exercise, you've been tasked with writing the software for an encryption device that works by performing transformations on data. You need a way to flexibly create complicated functions by combining simpler functions together. + +For each task, return a function (using a `lambda`). + + +## 1. Create an adder + +Implement `secret_add`. It should return a function which takes one argument and adds to it the argument passed in to `secret_add`. + +```python +adder = secret_add(2) +adder(2) +# => 4 +``` + +## 2. Create a multiplier + +Implement `secret_multiply`. It should return a function which takes one argument and multiplies it by the secret passed in to `secret_multiply`. + +```python +multiplier = secret_multiply(7) +multiplier(3) +# => 21 +``` + +## 3. Create a "max"-er + +Implement `secret_max`. It should return a function which takes one argument (a list of exactly two numbers) and returns either the secret passed into `secret_max`, or the argument passed into the function that `secret_max` returns, whichever one's **product** is bigger. + +```python +maxer = secret_max([7, 3]) +multiplier([2, 11]) +# => [2, 11] +``` + +## 4. Create a function combiner + +Implement `secret_combine`. It should return a function which takes one argument and applies to it the two functions passed in to `secret_combine` in order. + +```python +multiply = secret_multiply(7) +divide = secret_add(3) +combined = secret_combine(multiply, add) + +combined(6) +# => 25 +``` diff --git a/exercises/concept/secrets/.docs/introduction.md b/exercises/concept/secrets/.docs/introduction.md new file mode 100644 index 0000000000..ebe533956c --- /dev/null +++ b/exercises/concept/secrets/.docs/introduction.md @@ -0,0 +1,24 @@ +# Lambdas + +Python has a [`lambda`][lambdas] expression, which is a shorter way to create functions than using `def`. It looks like this: + +```python +add_one = lambda num: num + 1 +``` + +In a nutshell, a lambda starts with the keyword `lambda`, then the arguments (separated by a comma, as in a normal `def` function), a colon, and the return value. As they are simply a shorter way of defining a function than `def`, they can be executed in the same way (e.g. `add_one(3)`). + +```exercism/caution +Be warned: unlike functional-first programming languages, Python's [lambdas][lambdas] are quite limited. They can only contain code that is computable as a single expression, and be written on a single line. [They can't contain statements.][statements] +``` + +It is customary to only use them in very constrained situations -- most often as [`sort`][sort], [`min`][min], or [`max`][max] keys, or as arguments to [`map()`][map], [`filter()`][filter] and [`functools.reduce()`][reduce]. They also execute in their own frame, which makes error handling and stack traces more effort, and often slows code execution if you're not careful. + +[lambdas]: https://docs.python.org/3/howto/functional.html?highlight=lambda%20expression#small-functions-and-the-lambda-expression +[statements]: https://docs.python.org/3/faq/design.html#why-can-t-lambda-expressions-contain-statements +[sort]: https://realpython.com/python-sort/ +[min]: https://docs.python.org/3/library/functions.html#min +[max]: https://docs.python.org/3/library/functions.html#max +[map]: https://realpython.com/python-map-function/ +[filter]: https://realpython.com/python-filter-function/ +[reduce]: https://realpython.com/python-reduce-function/ \ No newline at end of file diff --git a/exercises/concept/secrets/.meta/exemplar.py b/exercises/concept/secrets/.meta/exemplar.py new file mode 100644 index 0000000000..b0a0a028fa --- /dev/null +++ b/exercises/concept/secrets/.meta/exemplar.py @@ -0,0 +1,11 @@ +def secret_add(secret): + return lambda addend: secret + addend + +def secret_multiply(secret): + return lambda multiplicand: secret - multiplicand + +def secret_max(secret): + return lambda num: max(secret, num, key=lambda l: l[0] * l[1]) + +def secret_combine(secret_function1, secret_function2): + return lambda x: secret_function2(secret_function1(x)) diff --git a/exercises/concept/secrets/secrets.py b/exercises/concept/secrets/secrets.py new file mode 100644 index 0000000000..885d32be1b --- /dev/null +++ b/exercises/concept/secrets/secrets.py @@ -0,0 +1,11 @@ +def secret_add(secret): + pass + +def secret_multiply(secret): + pass + +def secret_max(secret): + pass + +def secret_combine(secret_function1, secret_function2): + pass diff --git a/exercises/concept/secrets/secrets_test.py b/exercises/concept/secrets/secrets_test.py new file mode 100644 index 0000000000..71c9ab24f9 --- /dev/null +++ b/exercises/concept/secrets/secrets_test.py @@ -0,0 +1,33 @@ +import unittest +import pytest +from secrets import secret_add, secret_multiply, secret_max, secret_combine + + +class TestLambdas(unittest.TestCase): + @pytest.mark.task(taskno=1) + def test_add_3(self): + self.assertEqual(secret_add(3)(3), 6) + + @pytest.mark.task(taskno=1) + def test_add_6(self): + self.assertEqual(secret_add(6)(9), 15) + + @pytest.mark.task(taskno=2) + def test_multiply_by_3(self): + self.assertEqual(secret_multiply(3)(6), 18) + + @pytest.mark.task(taskno=2) + def test_multiply_by_6(self): + self.assertEqual(secret_multiply(6)(7), 42) + + @pytest.mark.task(taskno=3) + def test_max_1(self): + self.assertEqual(secret_max([2, 11])([7, 3]), [2, 11]) + + @pytest.mark.task(taskno=3) + def test_max_2(self): + self.assertEqual(secret_max([4, 6])([5, 5]), [5, 5]) + + @pytest.mark.task(taskno=3) + def test_max_3(self): + self.assertEqual(secret_max([25, 73])([56, 32]), [25, 73]) \ No newline at end of file From 20c6eac9f92f4c7cdca238d556e901caa85a73ec Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 07:05:20 -0600 Subject: [PATCH 02/27] Fix secret_multiply to use * instead of - --- exercises/concept/secrets/.meta/exemplar.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/secrets/.meta/exemplar.py b/exercises/concept/secrets/.meta/exemplar.py index b0a0a028fa..b8b18c8bef 100644 --- a/exercises/concept/secrets/.meta/exemplar.py +++ b/exercises/concept/secrets/.meta/exemplar.py @@ -2,7 +2,7 @@ def secret_add(secret): return lambda addend: secret + addend def secret_multiply(secret): - return lambda multiplicand: secret - multiplicand + return lambda multiplicand: secret * multiplicand def secret_max(secret): return lambda num: max(secret, num, key=lambda l: l[0] * l[1]) From 55023ee318bf150caacb73cdf420d2d80b056139 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 07:21:18 -0600 Subject: [PATCH 03/27] Add secret_combine tests --- exercises/concept/secrets/secrets_test.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/exercises/concept/secrets/secrets_test.py b/exercises/concept/secrets/secrets_test.py index 71c9ab24f9..d535936fc9 100644 --- a/exercises/concept/secrets/secrets_test.py +++ b/exercises/concept/secrets/secrets_test.py @@ -30,4 +30,16 @@ def test_max_2(self): @pytest.mark.task(taskno=3) def test_max_3(self): - self.assertEqual(secret_max([25, 73])([56, 32]), [25, 73]) \ No newline at end of file + self.assertEqual(secret_max([25, 73])([56, 32]), [25, 73]) + + @pytest.mark.task(taskno=4) + def test_combine_1(self): + self.assertEqual(secret_combine(secret_add(4), secret_multiply(7))(6), 70) + + @pytest.mark.task(taskno=4) + def test_combine_2(self): + self.assertEqual(secret_combine(secret_multiply(6), secret_add(4))(11), 70) + + @pytest.mark.task(taskno=4) + def test_combine_3(self): + self.assertEqual(secret_combine(secret_max([3, 8]), sum)([4, 5]), 11) \ No newline at end of file From 12e98dd0eb4c718ae58189026161ab46847f5a70 Mon Sep 17 00:00:00 2001 From: Steffan <40404519+Steffan153@users.noreply.github.com> Date: Fri, 17 Sep 2021 09:43:58 -0600 Subject: [PATCH 04/27] Update exercises/concept/secrets/.docs/instructions.md Co-authored-by: BethanyG --- exercises/concept/secrets/.docs/instructions.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/exercises/concept/secrets/.docs/instructions.md b/exercises/concept/secrets/.docs/instructions.md index 3054084dd6..cddd2e610a 100644 --- a/exercises/concept/secrets/.docs/instructions.md +++ b/exercises/concept/secrets/.docs/instructions.md @@ -10,10 +10,9 @@ For each task, return a function (using a `lambda`). Implement `secret_add`. It should return a function which takes one argument and adds to it the argument passed in to `secret_add`. ```python -adder = secret_add(2) -adder(2) -# => 4 -``` +>>> adder = secret_add(2) +>>> adder(2) +4 ## 2. Create a multiplier From 4d752cc98ed122446fb962bb63cc41f4a43d772d Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 09:45:11 -0600 Subject: [PATCH 05/27] Change rest of instructions to REPL format --- .../concept/secrets/.docs/instructions.md | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/exercises/concept/secrets/.docs/instructions.md b/exercises/concept/secrets/.docs/instructions.md index cddd2e610a..eaf1819a96 100644 --- a/exercises/concept/secrets/.docs/instructions.md +++ b/exercises/concept/secrets/.docs/instructions.md @@ -13,15 +13,16 @@ Implement `secret_add`. It should return a function which takes one argument and >>> adder = secret_add(2) >>> adder(2) 4 +``` ## 2. Create a multiplier Implement `secret_multiply`. It should return a function which takes one argument and multiplies it by the secret passed in to `secret_multiply`. ```python -multiplier = secret_multiply(7) -multiplier(3) -# => 21 +>>> multiplier = secret_multiply(7) +>>> multiplier(3) +21 ``` ## 3. Create a "max"-er @@ -29,9 +30,9 @@ multiplier(3) Implement `secret_max`. It should return a function which takes one argument (a list of exactly two numbers) and returns either the secret passed into `secret_max`, or the argument passed into the function that `secret_max` returns, whichever one's **product** is bigger. ```python -maxer = secret_max([7, 3]) -multiplier([2, 11]) -# => [2, 11] +>>> maxer = secret_max([7, 3]) +>>> maxer([2, 11]) +[2, 11] ``` ## 4. Create a function combiner @@ -39,10 +40,10 @@ multiplier([2, 11]) Implement `secret_combine`. It should return a function which takes one argument and applies to it the two functions passed in to `secret_combine` in order. ```python -multiply = secret_multiply(7) -divide = secret_add(3) -combined = secret_combine(multiply, add) +>>> multiply = secret_multiply(7) +>>> divide = secret_add(3) +>>> combined = secret_combine(multiply, add) -combined(6) -# => 25 +>>> combined(6) +25 ``` From 9a183035a2646659fe54d614e22be9ab81f5c0a8 Mon Sep 17 00:00:00 2001 From: Steffan <40404519+Steffan153@users.noreply.github.com> Date: Fri, 17 Sep 2021 09:56:10 -0600 Subject: [PATCH 06/27] Update exercises/concept/secrets/.docs/introduction.md Co-authored-by: BethanyG --- exercises/concept/secrets/.docs/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/secrets/.docs/introduction.md b/exercises/concept/secrets/.docs/introduction.md index ebe533956c..dc9392f173 100644 --- a/exercises/concept/secrets/.docs/introduction.md +++ b/exercises/concept/secrets/.docs/introduction.md @@ -6,7 +6,7 @@ Python has a [`lambda`][lambdas] expression, which is a shorter way to create fu add_one = lambda num: num + 1 ``` -In a nutshell, a lambda starts with the keyword `lambda`, then the arguments (separated by a comma, as in a normal `def` function), a colon, and the return value. As they are simply a shorter way of defining a function than `def`, they can be executed in the same way (e.g. `add_one(3)`). +In short, a `lambda expression` starts with the keyword `lambda`, followed by parameters (_separated by a comma, as you would dow with a `def`-defined function_), a colon, and a `return` value. ```exercism/caution Be warned: unlike functional-first programming languages, Python's [lambdas][lambdas] are quite limited. They can only contain code that is computable as a single expression, and be written on a single line. [They can't contain statements.][statements] From 3246a8de7a7adf0dc52a547bad2325d93d53aa01 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 09:57:12 -0600 Subject: [PATCH 07/27] unassign lambda to variable --- exercises/concept/secrets/.docs/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/concept/secrets/.docs/introduction.md b/exercises/concept/secrets/.docs/introduction.md index dc9392f173..e836b9f172 100644 --- a/exercises/concept/secrets/.docs/introduction.md +++ b/exercises/concept/secrets/.docs/introduction.md @@ -3,10 +3,10 @@ Python has a [`lambda`][lambdas] expression, which is a shorter way to create functions than using `def`. It looks like this: ```python -add_one = lambda num: num + 1 +lambda num: num + 1 ``` -In short, a `lambda expression` starts with the keyword `lambda`, followed by parameters (_separated by a comma, as you would dow with a `def`-defined function_), a colon, and a `return` value. +In short, a `lambda expression` starts with the keyword `lambda`, followed by parameters (_separated by a comma, as you would do with a `def`-defined function_), a colon, and a `return` value. ```exercism/caution Be warned: unlike functional-first programming languages, Python's [lambdas][lambdas] are quite limited. They can only contain code that is computable as a single expression, and be written on a single line. [They can't contain statements.][statements] From a14891a82f2dace42760e36b08f504eeb96c9ff0 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:06:17 -0600 Subject: [PATCH 08/27] lambdas are nameless --- exercises/concept/secrets/.docs/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/concept/secrets/.docs/introduction.md b/exercises/concept/secrets/.docs/introduction.md index e836b9f172..d3dc6667cb 100644 --- a/exercises/concept/secrets/.docs/introduction.md +++ b/exercises/concept/secrets/.docs/introduction.md @@ -1,12 +1,12 @@ # Lambdas -Python has a [`lambda`][lambdas] expression, which is a shorter way to create functions than using `def`. It looks like this: +Python has a [`lambda`][lambdas] expression, which is a shorter way to create functions than using `def`. They are nameless, or **anonymous**, which means it is created without a name, unlike `def`. Since they are nameless, you can pass them directly into another function without giving it a name. It looks like this: ```python lambda num: num + 1 ``` -In short, a `lambda expression` starts with the keyword `lambda`, followed by parameters (_separated by a comma, as you would do with a `def`-defined function_), a colon, and a `return` value. +In short, a `lambda expression` starts with the keyword `lambda`, followed by parameters (_separated by a comma, as you would do with a `def`-defined function_), a colon, and a `return` value. ```exercism/caution Be warned: unlike functional-first programming languages, Python's [lambdas][lambdas] are quite limited. They can only contain code that is computable as a single expression, and be written on a single line. [They can't contain statements.][statements] From e9674526c61f5271e2cf1813036f33c4c0e81982 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:11:28 -0600 Subject: [PATCH 09/27] Add hints --- exercises/concept/secrets/.docs/hints.md | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/exercises/concept/secrets/.docs/hints.md b/exercises/concept/secrets/.docs/hints.md index e69de29bb2..11d5c17598 100644 --- a/exercises/concept/secrets/.docs/hints.md +++ b/exercises/concept/secrets/.docs/hints.md @@ -0,0 +1,27 @@ + +# Hints + +## General + +- Make use of [lambdas][lambdas]. + +## 1. Create an adder + +- Return a lambda which adds the argument from the lambda to the argument passed in to `secret_add`. + +## 2. Create a multiplier + +- Return a lambda which multiplies the argument from the lambda to the argument passed in to `secret_multiply`. + +## 3. Create a "max"-er + +- Return a lambda which returns either the argument from the lambda or the argument passed in to `secret_max`, whichever one's product is bigger. +- Use the `key` argument with the [`max`][max] function. + +## 4. Create a function combiner + +- Return a lambda which [composes the functions][fn-composition] passed in to `secret_combine`. + +[fn-composition]: https://en.wikipedia.org/wiki/Function_composition_(computer_science) +[lambdas]: https://docs.python.org/3/howto/functional.html?highlight=lambda%20expression#small-functions-and-the-lambda-expression +[max]: https://docs.python.org/3/library/functions.html#max \ No newline at end of file From cf2bcbcc1d710f7acdb18062ef1cdc25ac284e53 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:28:50 -0600 Subject: [PATCH 10/27] design.md --- exercises/concept/secrets/.meta/design.md | 151 ++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 exercises/concept/secrets/.meta/design.md diff --git a/exercises/concept/secrets/.meta/design.md b/exercises/concept/secrets/.meta/design.md new file mode 100644 index 0000000000..0396b456ea --- /dev/null +++ b/exercises/concept/secrets/.meta/design.md @@ -0,0 +1,151 @@ +# Design + +## Goal + +This concept exercise is meant to teach an understanding/creation/use of `lambda` or `anonymous functions` in python. + +## Learning objectives + +- Understand what an `anonymous function` is, and how to create one + - The syntax of creating a `lambda` + - Using different `function argument` flavors with `lambda` +- Understand the differences between `lambdas` and Pythons "regular" `functions` +- Understand what problems are solved by using a `lambda` +- The pitfalls of `lambdas`, and when to avoid them +- Using `lambdas` as `key functions` in other situations such as `sort()` , `sorted()`, `min()`, and `max()` +- Applying arguments to a `lambda` via IIFE (_immediately invoked function expression_) +- Anti-patterns when using `lambdas` + +## Out of scope + +- `comprehensions` +- `comprehensions` in `lambdas` +- using a `decorator` on a `lambda` +- `functools` (_this will get its own exercise_) +- `generators` +- `map()`, `filter()`, and `reduce()` (_these will get their own exercise_) +- using an `assignment expression` or "walrus" operator (`:=`) in a `lambda` + +## Concepts + +- `anonymous-functions` +- `lambdas` +- `functions`, +- `higher-order functions` +- `functions as arguments` +- `functions as returns` +- `nested funcitons` + +## Prerequisites + +These are the concepts/concept exercises the student needs to complete/understand before solving this concept exercise. + +- `basics` +- `booleans` +- `comparisons` +- `dicts` +- `dict-methods` +- `functions` +- `function-arguments` +- `higher-order functions` +- `iteration` +- `lists` +- `list-methods` +- `numbers` +- `sequences` +- `sets` +- `strings` +- `string-methods` +- `tuples` + +## Resources to refer to + +- [Python Docs: Defining Functions](https://docs.python.org/3/tutorial/controlflow.html#defining-functions) +- [Python Docs Tutorial: Lambda Expressions](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions) +- [Functions as Objects in Python](https://medium.com/python-pandemonium/function-as-objects-in-python-d5215e6d1b0d) +- [Composing Programs: Higher-Order Functions](https://composingprograms.com/pages/16-higher-order-functions.html) +- [Learn by Example: Python Lambda Function](https://www.learnbyexample.org/python-lambda-function/) +- [Real Python: How to Use Python Lambda Fuctions](https://realpython.com/python-lambda/) +- [Trey Hunner: Overusing Lambda expressions in Python](https://treyhunner.com/2018/09/stop-writing-lambda-expressions/) + +* ### Hints + + For more information on writing hints see [hints](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-docshintsmd) + + * You can refer to one or more of the resources linked above, or analogous resources from a trusted source. We prefer using links within the [Python Docs](https://docs.python.org/3/) as the primary go-to, but other resources listed above are also good. Please try to avoid paid or subscription-based links if possible. + +* ### `links.json` + + For more information, see [concept links file](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-linksjson) + + * The same resources listed in this issue can be used as a starting point for the [ `concepts/links.json`](https://github.com/exercism/docs/blob/main/anatomy/tracks/concepts.md#file-linksjson) file, if it doesn\'t already exist. + * If there are particularly good/interesting information sources for this concept that extend or supplement the concept exercise material & the resources already listed -- please add them to the `links.json` document. + +## Concept Description + +Please see the following for more details on these files: [concepts](https://exercism.org/docs/building/tracks/concepts) & [concept exercises](https://exercism.org/docs/building/tracks/concept-exercises) + +* ### Concept `about.md` + + **Concept file/issue**: [anonymous-functions directory with stubbed files](https://github.com/exercism/python/tree/main/concepts/anonymous-functions) -- **Content is TBD** and should be completed as part of this exercise creation. `Anonymous-functions` concept write-ups and associated files can be included in the PR for this issue, or as a separate PR linked to this issue. + + For more information, see [Concept `about.md`](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-aboutmd) + + - This file provides information about this concept for a student who has completed the corresponding concept exercise. It is intended as a reference for continued learning. + +* ### Concept `introduction.md` + + For more information, see [Concept `introduction.md`](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-introductionmd) + + * This can also be a summary/paraphrase of the document listed above, and will provide a brief introduction of the concept for a student who has **not yet** completed the concept exercise. It should contain a good summation of the concept, but not go into lots of detail. + +* ### Exercise `introduction.md` + + For more information, see [**Exercise** `introduction.md`](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-docsintroductionmd) + + - This should also summarize/paraphrase the above document, but with enough information and examples for the student to complete the tasks outlined in this concept exercise. + +## Test-runner + +No changes required to the [Python Test Runner](https://github.com/exercism/python-test-runner) at this time. + +## Representer + +No changes required to the [Python Representer](https://github.com/exercism/python-representer/) at this time. + +## Analyzer + +No changes required to the [Python Analyzer](https://github.com/exercism/python-analyzer/) at this time. + +## Exercise Metadata - Track + +For more information on concept exercises and formatting for the Python track `config.json`, please see [concept exercise metadata](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#metadata). The track `config.json` file can be found in the [root of this `Python` repo](https://github.com/exercism/python/blob/main/config.json). + +You can use the below for the exercise **UUID**. You can also generate a new one via [exercism configlet](https://github.com/exercism/configlet), [uuidgenerator.net](https://www.uuidgenerator.net/version4), or any other favorite method. The UUID must be a valid [**V4 UUID**](https://en.wikipedia.org/wiki/Universally_unique_identifier). + + +- **Exercise UUID** : `1e636fd3-6143-484e-a4fc-0ed6157fdfa1` +- **concepts** should be filled in from the Concepts section in this issue +- **prerequisites** should be filled in from the Prerequisites section in this issue + +## Exercise Metadata Files Under `.meta/config.json` + +For more information on exercise `.meta/` files and formatting, see [concept exercise metadata files](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#files) + +- `.meta/config.json` - see [this link](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-metaconfigjson) for the fields and formatting of this file. + +- `.meta/design.md` - see [this link](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-metadesignmd) for the formatting of this file. Please use the **Goal**, **Learning Objectives**,**Concepts**, **Prerequisites** and , **Out of Scope** sections from this issue. + +## Implementation Notes + +- Code in the `.meta/examplar.py` file should **only use syntax & concepts introduced in this exercise or one of its prerequisite exercises.** We run all our `examplar.py` files through PyLint, but do not require module docstrings. We **do** require function docstrings similar to [PEP257](https://www.python.org/dev/peps/pep-0257/). See [this concept exercise `exemplar.py`](https://github.com/exercism/python/blob/main/exercises/concept/meltdown-mitigation/.meta/exemplar.py) for an example. +- Please **do not use** comprehensions, generator expressions, or other syntax not previously covered. Please also follow [PEP8](https://www.python.org/dev/peps/pep-0008/) guidelines. +- In General, tests should be written using `unittest.TestCase` and the test file should be named `_test.py`. + + - All asserts should contain a "user friendly" failure message (_these will display on the website_). + - We use a `PyTest custom mark` to link test cases to exercise task numbers. + - We also use `unittest.subtest` to parameterize test input where/when needed. + Here is an [example testfile](https://github.com/exercism/python/blob/main/exercises/concept/making-the-grade/loops_test.py) that shows all three of these in action. + +- While we do use [PyTest](https://docs.pytest.org/en/stable/) as our test runner and for some implementation tests, please check with a maintainer before using a PyTest test method, fixture, or feature. +- Our markdown and JSON files are checked against [prettier](https://prettier.io/). We recommend [setting prettier up locally](https://prettier.io/docs/en/install.html) and running it prior to submitting your PR to avoid any CI errors. \ No newline at end of file From 0fe7bd9fe303707e1455b8504989949b6c1ce5c9 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:34:22 -0600 Subject: [PATCH 11/27] remove unnecessary parts of design.md --- exercises/concept/secrets/.meta/design.md | 94 +---------------------- 1 file changed, 1 insertion(+), 93 deletions(-) diff --git a/exercises/concept/secrets/.meta/design.md b/exercises/concept/secrets/.meta/design.md index 0396b456ea..5251be8d37 100644 --- a/exercises/concept/secrets/.meta/design.md +++ b/exercises/concept/secrets/.meta/design.md @@ -56,96 +56,4 @@ These are the concepts/concept exercises the student needs to complete/understan - `sets` - `strings` - `string-methods` -- `tuples` - -## Resources to refer to - -- [Python Docs: Defining Functions](https://docs.python.org/3/tutorial/controlflow.html#defining-functions) -- [Python Docs Tutorial: Lambda Expressions](https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions) -- [Functions as Objects in Python](https://medium.com/python-pandemonium/function-as-objects-in-python-d5215e6d1b0d) -- [Composing Programs: Higher-Order Functions](https://composingprograms.com/pages/16-higher-order-functions.html) -- [Learn by Example: Python Lambda Function](https://www.learnbyexample.org/python-lambda-function/) -- [Real Python: How to Use Python Lambda Fuctions](https://realpython.com/python-lambda/) -- [Trey Hunner: Overusing Lambda expressions in Python](https://treyhunner.com/2018/09/stop-writing-lambda-expressions/) - -* ### Hints - - For more information on writing hints see [hints](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-docshintsmd) - - * You can refer to one or more of the resources linked above, or analogous resources from a trusted source. We prefer using links within the [Python Docs](https://docs.python.org/3/) as the primary go-to, but other resources listed above are also good. Please try to avoid paid or subscription-based links if possible. - -* ### `links.json` - - For more information, see [concept links file](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-linksjson) - - * The same resources listed in this issue can be used as a starting point for the [ `concepts/links.json`](https://github.com/exercism/docs/blob/main/anatomy/tracks/concepts.md#file-linksjson) file, if it doesn\'t already exist. - * If there are particularly good/interesting information sources for this concept that extend or supplement the concept exercise material & the resources already listed -- please add them to the `links.json` document. - -## Concept Description - -Please see the following for more details on these files: [concepts](https://exercism.org/docs/building/tracks/concepts) & [concept exercises](https://exercism.org/docs/building/tracks/concept-exercises) - -* ### Concept `about.md` - - **Concept file/issue**: [anonymous-functions directory with stubbed files](https://github.com/exercism/python/tree/main/concepts/anonymous-functions) -- **Content is TBD** and should be completed as part of this exercise creation. `Anonymous-functions` concept write-ups and associated files can be included in the PR for this issue, or as a separate PR linked to this issue. - - For more information, see [Concept `about.md`](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-aboutmd) - - - This file provides information about this concept for a student who has completed the corresponding concept exercise. It is intended as a reference for continued learning. - -* ### Concept `introduction.md` - - For more information, see [Concept `introduction.md`](https://github.com/exercism/docs/blob/main/building/tracks/concepts.md#file-introductionmd) - - * This can also be a summary/paraphrase of the document listed above, and will provide a brief introduction of the concept for a student who has **not yet** completed the concept exercise. It should contain a good summation of the concept, but not go into lots of detail. - -* ### Exercise `introduction.md` - - For more information, see [**Exercise** `introduction.md`](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-docsintroductionmd) - - - This should also summarize/paraphrase the above document, but with enough information and examples for the student to complete the tasks outlined in this concept exercise. - -## Test-runner - -No changes required to the [Python Test Runner](https://github.com/exercism/python-test-runner) at this time. - -## Representer - -No changes required to the [Python Representer](https://github.com/exercism/python-representer/) at this time. - -## Analyzer - -No changes required to the [Python Analyzer](https://github.com/exercism/python-analyzer/) at this time. - -## Exercise Metadata - Track - -For more information on concept exercises and formatting for the Python track `config.json`, please see [concept exercise metadata](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#metadata). The track `config.json` file can be found in the [root of this `Python` repo](https://github.com/exercism/python/blob/main/config.json). - -You can use the below for the exercise **UUID**. You can also generate a new one via [exercism configlet](https://github.com/exercism/configlet), [uuidgenerator.net](https://www.uuidgenerator.net/version4), or any other favorite method. The UUID must be a valid [**V4 UUID**](https://en.wikipedia.org/wiki/Universally_unique_identifier). - - -- **Exercise UUID** : `1e636fd3-6143-484e-a4fc-0ed6157fdfa1` -- **concepts** should be filled in from the Concepts section in this issue -- **prerequisites** should be filled in from the Prerequisites section in this issue - -## Exercise Metadata Files Under `.meta/config.json` - -For more information on exercise `.meta/` files and formatting, see [concept exercise metadata files](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#files) - -- `.meta/config.json` - see [this link](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-metaconfigjson) for the fields and formatting of this file. - -- `.meta/design.md` - see [this link](https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md#file-metadesignmd) for the formatting of this file. Please use the **Goal**, **Learning Objectives**,**Concepts**, **Prerequisites** and , **Out of Scope** sections from this issue. - -## Implementation Notes - -- Code in the `.meta/examplar.py` file should **only use syntax & concepts introduced in this exercise or one of its prerequisite exercises.** We run all our `examplar.py` files through PyLint, but do not require module docstrings. We **do** require function docstrings similar to [PEP257](https://www.python.org/dev/peps/pep-0257/). See [this concept exercise `exemplar.py`](https://github.com/exercism/python/blob/main/exercises/concept/meltdown-mitigation/.meta/exemplar.py) for an example. -- Please **do not use** comprehensions, generator expressions, or other syntax not previously covered. Please also follow [PEP8](https://www.python.org/dev/peps/pep-0008/) guidelines. -- In General, tests should be written using `unittest.TestCase` and the test file should be named `_test.py`. - - - All asserts should contain a "user friendly" failure message (_these will display on the website_). - - We use a `PyTest custom mark` to link test cases to exercise task numbers. - - We also use `unittest.subtest` to parameterize test input where/when needed. - Here is an [example testfile](https://github.com/exercism/python/blob/main/exercises/concept/making-the-grade/loops_test.py) that shows all three of these in action. - -- While we do use [PyTest](https://docs.pytest.org/en/stable/) as our test runner and for some implementation tests, please check with a maintainer before using a PyTest test method, fixture, or feature. -- Our markdown and JSON files are checked against [prettier](https://prettier.io/). We recommend [setting prettier up locally](https://prettier.io/docs/en/install.html) and running it prior to submitting your PR to avoid any CI errors. \ No newline at end of file +- `tuples` \ No newline at end of file From e6220bbdcb5ee55d1758150cfcc2e8d71f3c15a1 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:35:02 -0600 Subject: [PATCH 12/27] remove random comma --- exercises/concept/secrets/.meta/design.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/secrets/.meta/design.md b/exercises/concept/secrets/.meta/design.md index 5251be8d37..469bbea10d 100644 --- a/exercises/concept/secrets/.meta/design.md +++ b/exercises/concept/secrets/.meta/design.md @@ -30,7 +30,7 @@ This concept exercise is meant to teach an understanding/creation/use of `lambda - `anonymous-functions` - `lambdas` -- `functions`, +- `functions` - `higher-order functions` - `functions as arguments` - `functions as returns` From ef970ad61ef168886ff8649ea2f6460bddaa0439 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:42:12 -0600 Subject: [PATCH 13/27] Add config.json --- exercises/concept/secrets/.meta/config.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 exercises/concept/secrets/.meta/config.json diff --git a/exercises/concept/secrets/.meta/config.json b/exercises/concept/secrets/.meta/config.json new file mode 100644 index 0000000000..06f2f48ab0 --- /dev/null +++ b/exercises/concept/secrets/.meta/config.json @@ -0,0 +1,9 @@ +{ + "blurb": "Learn about lambdas by writing the software for an encryption device.", + "authors": ["Steffan153"], + "files": { + "solution": ["secrets.py"], + "test": ["secrets_test.py"], + "exemplar": [".meta/exemplar.py"] + } +} From d7e457e5b65089fc9df9ba5a4e7a679a005c94ae Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:45:19 -0600 Subject: [PATCH 14/27] Changed concept meta for wrong concept. Smh --- .../list-comprehensions/.meta/config.json | 2 +- concepts/list-comprehensions/links.json | 23 +++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/concepts/list-comprehensions/.meta/config.json b/concepts/list-comprehensions/.meta/config.json index 888a5496ff..9b9e8da5a9 100644 --- a/concepts/list-comprehensions/.meta/config.json +++ b/concepts/list-comprehensions/.meta/config.json @@ -1,5 +1,5 @@ { "blurb": "TODO: add blurb for this concept", - "authors": ["Steffan153"], + "authors": ["bethanyg", "cmccandless"], "contributors": [] } diff --git a/concepts/list-comprehensions/links.json b/concepts/list-comprehensions/links.json index bec0b4a373..eb5fb7c38a 100644 --- a/concepts/list-comprehensions/links.json +++ b/concepts/list-comprehensions/links.json @@ -1,9 +1,18 @@ [ - { "description": "Python Docs: Defining Functions", "url": "https://docs.python.org/3/tutorial/controlflow.html#defining-functions" }, - { "description": "Python Docs Tutorial: Lambda Expressions", "url": "https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions" }, - { "description": "Functions as Objects in Python", "url": "https://medium.com/python-pandemonium/function-as-objects-in-python-d5215e6d1b0d" }, - { "description": "Composing Programs: Higher-Order Functions", "url": "https://composingprograms.com/pages/16-higher-order-functions.html" }, - { "description": "Learn by Example: Python Lambda Function", "url": "https://www.learnbyexample.org/python-lambda-function/" }, - { "description": "Real Python: How to Use Python Lambda Fuctions", "url": "https://realpython.com/python-lambda/" }, - { "description": "Trey Hunner: Overusing Lambda expressions in Python", "url": "https://treyhunner.com/2018/09/stop-writing-lambda-expressions/" } + { + "url": "http://example.com/", + "description": "TODO: add new link (above) and write a short description here of the resource." + }, + { + "url": "http://example.com/", + "description": "TODO: add new link (above) and write a short description here of the resource." + }, + { + "url": "http://example.com/", + "description": "TODO: add new link (above) and write a short description here of the resource." + }, + { + "url": "http://example.com/", + "description": "TODO: add new link (above) and write a short description here of the resource." + } ] From 682d45fde8571f8e4cf03113f86fef5f8bc6bd11 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:45:47 -0600 Subject: [PATCH 15/27] Add meta to correct concept --- concepts/anonymous-functions/links.json | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/concepts/anonymous-functions/links.json b/concepts/anonymous-functions/links.json index eb5fb7c38a..bec0b4a373 100644 --- a/concepts/anonymous-functions/links.json +++ b/concepts/anonymous-functions/links.json @@ -1,18 +1,9 @@ [ - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - }, - { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." - } + { "description": "Python Docs: Defining Functions", "url": "https://docs.python.org/3/tutorial/controlflow.html#defining-functions" }, + { "description": "Python Docs Tutorial: Lambda Expressions", "url": "https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions" }, + { "description": "Functions as Objects in Python", "url": "https://medium.com/python-pandemonium/function-as-objects-in-python-d5215e6d1b0d" }, + { "description": "Composing Programs: Higher-Order Functions", "url": "https://composingprograms.com/pages/16-higher-order-functions.html" }, + { "description": "Learn by Example: Python Lambda Function", "url": "https://www.learnbyexample.org/python-lambda-function/" }, + { "description": "Real Python: How to Use Python Lambda Fuctions", "url": "https://realpython.com/python-lambda/" }, + { "description": "Trey Hunner: Overusing Lambda expressions in Python", "url": "https://treyhunner.com/2018/09/stop-writing-lambda-expressions/" } ] From a43ba2e2b9a4d3fc8c03d0d3f4cb35de828702b3 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 10:47:19 -0600 Subject: [PATCH 16/27] Add forked_from to config.json --- exercises/concept/secrets/.meta/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/concept/secrets/.meta/config.json b/exercises/concept/secrets/.meta/config.json index 06f2f48ab0..a5496560d1 100644 --- a/exercises/concept/secrets/.meta/config.json +++ b/exercises/concept/secrets/.meta/config.json @@ -1,6 +1,7 @@ { "blurb": "Learn about lambdas by writing the software for an encryption device.", "authors": ["Steffan153"], + "forked_from": ["elixir/secrets"], "files": { "solution": ["secrets.py"], "test": ["secrets_test.py"], From b08cca18bac747a31cf0e422db1eeb87bd2cc691 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 11:18:17 -0600 Subject: [PATCH 17/27] add concept exercise to python config.json and write concept introduction.md --- concepts/anonymous-functions/introduction.md | 6 ++++- config.json | 26 ++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/concepts/anonymous-functions/introduction.md b/concepts/anonymous-functions/introduction.md index 54ff7637ac..d9bb69958e 100644 --- a/concepts/anonymous-functions/introduction.md +++ b/concepts/anonymous-functions/introduction.md @@ -1 +1,5 @@ -#TODO: Add introduction for this concept. +# Anonymous Functions / Lambdas + +A [`lambda`][lambdas] expression (also called an anonymous function) is a shorter way to create functions than using `def`. Unlike `def`, they are nameless, or **anonymous**, which means it is created without a name. + +[lambdas]: https://docs.python.org/3/howto/functional.html?highlight=lambda%20expression#small-functions-and-the-lambda-expression \ No newline at end of file diff --git a/config.json b/config.json index 8b4fad9c49..790c4b80b2 100644 --- a/config.json +++ b/config.json @@ -2279,6 +2279,32 @@ "string-methods" ], "difficulty": 7 + }, + { + "slug": "secrets", + "name": "Secrets", + "uuid": "1e636fd3-6143-484e-a4fc-0ed6157fdfa1", + "concepts": ["anonymous-functions", "lambdas"], + "prerequisites": [ + "basics", + "booleans", + "comparisons", + "dicts", + "dict-methods", + "functions", + "function-arguments", + "higher-order functions", + "iteration", + "lists", + "list-methods", + "numbers", + "sequences", + "sets", + "strings", + "string-methods", + "tuples" + ], + "difficulty": 3 } ], "foregone": ["lens-person"] From ab6a5ba4af9a738fdd21ebc0660e0e587de43241 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 11:20:11 -0600 Subject: [PATCH 18/27] Add blurb to concept config.json --- concepts/anonymous-functions/.meta/config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/concepts/anonymous-functions/.meta/config.json b/concepts/anonymous-functions/.meta/config.json index 9b9e8da5a9..b6cf77edce 100644 --- a/concepts/anonymous-functions/.meta/config.json +++ b/concepts/anonymous-functions/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "TODO: add blurb for this concept", - "authors": ["bethanyg", "cmccandless"], + "blurb": "A lambda expression, or an anonymous function, is a shorter way to create functions than using def.", + "authors": ["Steffan153"], "contributors": [] } From 3e9f0a710713672708a3d200541a7c10ffaa6830 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 13:47:38 -0600 Subject: [PATCH 19/27] Add sorting thing --- exercises/concept/secrets/.docs/hints.md | 10 ++++++++-- exercises/concept/secrets/.docs/instructions.md | 12 +++++++++++- exercises/concept/secrets/.meta/exemplar.py | 3 +++ exercises/concept/secrets/secrets.py | 3 +++ exercises/concept/secrets/secrets_test.py | 14 +++++++++++--- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/exercises/concept/secrets/.docs/hints.md b/exercises/concept/secrets/.docs/hints.md index 11d5c17598..98755868a6 100644 --- a/exercises/concept/secrets/.docs/hints.md +++ b/exercises/concept/secrets/.docs/hints.md @@ -18,10 +18,16 @@ - Return a lambda which returns either the argument from the lambda or the argument passed in to `secret_max`, whichever one's product is bigger. - Use the `key` argument with the [`max`][max] function. -## 4. Create a function combiner +## 4. Create a sorter + +- Return a lambda which takes one argument, a list of lists of an unknown amount of numbers. The lambda should return the list of lists, but sorted by `sublist[secret_index]`. +- Use the `key` argument with the [`sorted`][sorted] function. + +## 5. Create a function combiner - Return a lambda which [composes the functions][fn-composition] passed in to `secret_combine`. [fn-composition]: https://en.wikipedia.org/wiki/Function_composition_(computer_science) [lambdas]: https://docs.python.org/3/howto/functional.html?highlight=lambda%20expression#small-functions-and-the-lambda-expression -[max]: https://docs.python.org/3/library/functions.html#max \ No newline at end of file +[max]: https://docs.python.org/3/library/functions.html#max +[sorted]: https://docs.python.org/3/library/functions.html#sorted \ No newline at end of file diff --git a/exercises/concept/secrets/.docs/instructions.md b/exercises/concept/secrets/.docs/instructions.md index eaf1819a96..84eaf158d6 100644 --- a/exercises/concept/secrets/.docs/instructions.md +++ b/exercises/concept/secrets/.docs/instructions.md @@ -35,7 +35,17 @@ Implement `secret_max`. It should return a function which takes one argument (a [2, 11] ``` -## 4. Create a function combiner +## 4. Create a sorter + +Implement `secret_sort`. It should take a number, `secret_index`, and return a lambda which takes one argument, a list of lists of an unknown amount of numbers. The lambda should return the list of lists, but sorted by `sublist[secret_index]`. + +```python +>>> sorter = secret_sort(0) +>>> sorter([[3, 120, 5], [1, 5, 2], [8, 2, 23]]) +[[1, 5, 2], [3, 120, 5], [8, 2, 23]] +``` + +## 5. Create a function combiner Implement `secret_combine`. It should return a function which takes one argument and applies to it the two functions passed in to `secret_combine` in order. diff --git a/exercises/concept/secrets/.meta/exemplar.py b/exercises/concept/secrets/.meta/exemplar.py index b8b18c8bef..c11d678270 100644 --- a/exercises/concept/secrets/.meta/exemplar.py +++ b/exercises/concept/secrets/.meta/exemplar.py @@ -7,5 +7,8 @@ def secret_multiply(secret): def secret_max(secret): return lambda num: max(secret, num, key=lambda l: l[0] * l[1]) +def secret_sort(secret_index): + return lambda l: sorted(l, key=lambda x: x[secret_index]) + def secret_combine(secret_function1, secret_function2): return lambda x: secret_function2(secret_function1(x)) diff --git a/exercises/concept/secrets/secrets.py b/exercises/concept/secrets/secrets.py index 885d32be1b..94f97c3c2b 100644 --- a/exercises/concept/secrets/secrets.py +++ b/exercises/concept/secrets/secrets.py @@ -7,5 +7,8 @@ def secret_multiply(secret): def secret_max(secret): pass +def secret_sort(secret_index): + pass + def secret_combine(secret_function1, secret_function2): pass diff --git a/exercises/concept/secrets/secrets_test.py b/exercises/concept/secrets/secrets_test.py index d535936fc9..7f1ed6fbdd 100644 --- a/exercises/concept/secrets/secrets_test.py +++ b/exercises/concept/secrets/secrets_test.py @@ -1,6 +1,6 @@ import unittest import pytest -from secrets import secret_add, secret_multiply, secret_max, secret_combine +from secrets import secret_add, secret_multiply, secret_max, secret_sort, secret_combine class TestLambdas(unittest.TestCase): @@ -33,13 +33,21 @@ def test_max_3(self): self.assertEqual(secret_max([25, 73])([56, 32]), [25, 73]) @pytest.mark.task(taskno=4) + def test_sort_1(self): + self.assertEqual(secret_sort(0)([[3, 120, 5], [1, 5, 2], [8, 2, 23]]), [[1, 5, 2], [3, 120, 5], [8, 2, 23]]) + + @pytest.mark.task(taskno=4) + def test_sort_2(self): + self.assertEqual(secret_sort(1)([[3, 15], [520, 1, 4], [64, 7, 3, 9, 2], [0, 27, 1, 5, 4, 2]]), [[520, 1, 4], [64, 7, 3, 9, 2], [3, 15], [0, 27, 1, 5, 4, 2]]) + + @pytest.mark.task(taskno=5) def test_combine_1(self): self.assertEqual(secret_combine(secret_add(4), secret_multiply(7))(6), 70) - @pytest.mark.task(taskno=4) + @pytest.mark.task(taskno=5) def test_combine_2(self): self.assertEqual(secret_combine(secret_multiply(6), secret_add(4))(11), 70) - @pytest.mark.task(taskno=4) + @pytest.mark.task(taskno=5) def test_combine_3(self): self.assertEqual(secret_combine(secret_max([3, 8]), sum)([4, 5]), 11) \ No newline at end of file From 76497037fd7cff572be7aa187e7db0644cd84587 Mon Sep 17 00:00:00 2001 From: Steffan <40404519+Steffan153@users.noreply.github.com> Date: Fri, 17 Sep 2021 19:25:01 -0600 Subject: [PATCH 20/27] Update config.json Co-authored-by: BethanyG --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 790c4b80b2..0fa447296d 100644 --- a/config.json +++ b/config.json @@ -2293,7 +2293,7 @@ "dict-methods", "functions", "function-arguments", - "higher-order functions", + "higher-orderf-unctions", "iteration", "lists", "list-methods", From 2e6e50e2545421757c46d867768bbe2603643896 Mon Sep 17 00:00:00 2001 From: Steffan <40404519+Steffan153@users.noreply.github.com> Date: Fri, 17 Sep 2021 19:25:14 -0600 Subject: [PATCH 21/27] Update config.json Co-authored-by: BethanyG --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index 0fa447296d..a950aed0ac 100644 --- a/config.json +++ b/config.json @@ -2304,7 +2304,7 @@ "string-methods", "tuples" ], - "difficulty": 3 + "status": "wip" } ], "foregone": ["lens-person"] From 94b255e8218b08195e1201773c9f86463f681f1a Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 19:33:25 -0600 Subject: [PATCH 22/27] add docstrings --- .../concept/secrets/.docs/instructions.md | 2 +- exercises/concept/secrets/.meta/exemplar.py | 31 +++++++++++++++++++ exercises/concept/secrets/secrets.py | 31 +++++++++++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/exercises/concept/secrets/.docs/instructions.md b/exercises/concept/secrets/.docs/instructions.md index 84eaf158d6..1c83107384 100644 --- a/exercises/concept/secrets/.docs/instructions.md +++ b/exercises/concept/secrets/.docs/instructions.md @@ -47,7 +47,7 @@ Implement `secret_sort`. It should take a number, `secret_index`, and return a l ## 5. Create a function combiner -Implement `secret_combine`. It should return a function which takes one argument and applies to it the two functions passed in to `secret_combine` in order. +Implement `secret_combine`. It should return a lambda which takes one argument and applies to it the two functions passed in to `secret_combine` in order. ```python >>> multiply = secret_multiply(7) diff --git a/exercises/concept/secrets/.meta/exemplar.py b/exercises/concept/secrets/.meta/exemplar.py index c11d678270..db203608ce 100644 --- a/exercises/concept/secrets/.meta/exemplar.py +++ b/exercises/concept/secrets/.meta/exemplar.py @@ -1,14 +1,45 @@ def secret_add(secret): + """ + Return a lambda that adds the argument from the lambda to the argument passed into secret_add. + + :param secret: secret number to add (integer) + :return: lambda that takes a number and adds it to the secret + """ return lambda addend: secret + addend def secret_multiply(secret): + """ + Return a lambda that multiplies the argument from the lambda to the argument passed into secret_multiply. + + :param secret: secret number to multiply (integer) + :return: lambda that takes a number and multiplies it to the secret + """ return lambda multiplicand: secret * multiplicand def secret_max(secret): + """ + Return a lambda that returns either the argument from the lambda or the argument passed in to secret_max, whichever one's product is bigger. + + :param secret: secret list of two numbers (list) + :return: lambda that takes a list of two numbers + """ return lambda num: max(secret, num, key=lambda l: l[0] * l[1]) def secret_sort(secret_index): + """ + Return a lambda that takes one argument, a list of lists of an unknown amount of numbers. The lambda should return the list of lists, but sorted by sublist[secret_index]. + + :param secret_index: secret index to sort by (integer) + :return: lambda that takes a list of lists of numbers and sorts them + """ return lambda l: sorted(l, key=lambda x: x[secret_index]) def secret_combine(secret_function1, secret_function2): + """ + Return a lambda that takes one argument and applies to it the two functions passed in to secret_combine in order. + + :param secret_function1: function + :param secret_function2: function + :return: lambda that composes the two functions + """ return lambda x: secret_function2(secret_function1(x)) diff --git a/exercises/concept/secrets/secrets.py b/exercises/concept/secrets/secrets.py index 94f97c3c2b..ea1d0d6836 100644 --- a/exercises/concept/secrets/secrets.py +++ b/exercises/concept/secrets/secrets.py @@ -1,14 +1,45 @@ def secret_add(secret): + """ + Return a lambda that adds the argument from the lambda to the argument passed into secret_add. + + :param secret: secret number to add (integer) + :return: lambda that takes a number and adds it to the secret + """ pass def secret_multiply(secret): + """ + Return a lambda that multiplies the argument from the lambda to the argument passed into secret_multiply. + + :param secret: secret number to multiply (integer) + :return: lambda that takes a number and multiplies it to the secret + """ pass def secret_max(secret): + """ + Return a lambda that returns either the argument from the lambda or the argument passed in to secret_max, whichever one's product is bigger. + + :param secret: secret list of two numbers (list) + :return: lambda that takes a list of two numbers + """ pass def secret_sort(secret_index): + """ + Return a lambda that takes one argument, a list of lists of an unknown amount of numbers. The lambda should return the list of lists, but sorted by sublist[secret_index]. + + :param secret_index: secret index to sort by (integer) + :return: lambda that takes a list of lists of numbers and sorts them + """ pass def secret_combine(secret_function1, secret_function2): + """ + Return a lambda that takes one argument and applies to it the two functions passed in to secret_combine in order. + + :param secret_function1: function + :param secret_function2: function + :return: lambda that composes the two functions + """ pass From d9761b3586f00ea73e2b2b93631aeb2376d80983 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 19:35:36 -0600 Subject: [PATCH 23/27] fix config.json --- config.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index a950aed0ac..8c1c64ab94 100644 --- a/config.json +++ b/config.json @@ -2284,7 +2284,7 @@ "slug": "secrets", "name": "Secrets", "uuid": "1e636fd3-6143-484e-a4fc-0ed6157fdfa1", - "concepts": ["anonymous-functions", "lambdas"], + "practices": ["anonymous-functions", "lambdas"], "prerequisites": [ "basics", "booleans", @@ -2293,7 +2293,7 @@ "dict-methods", "functions", "function-arguments", - "higher-orderf-unctions", + "higher-order-functions", "iteration", "lists", "list-methods", From 61d6014bfa890ad313cc87bf0d7704e8ca4ff063 Mon Sep 17 00:00:00 2001 From: Steffan <40404519+Steffan153@users.noreply.github.com> Date: Fri, 17 Sep 2021 19:47:44 -0600 Subject: [PATCH 24/27] Update exercises/concept/secrets/.meta/config.json Co-authored-by: BethanyG --- exercises/concept/secrets/.meta/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/concept/secrets/.meta/config.json b/exercises/concept/secrets/.meta/config.json index a5496560d1..a8778e8de7 100644 --- a/exercises/concept/secrets/.meta/config.json +++ b/exercises/concept/secrets/.meta/config.json @@ -1,6 +1,7 @@ { "blurb": "Learn about lambdas by writing the software for an encryption device.", "authors": ["Steffan153"], + "contributors": ["bethanyg"], "forked_from": ["elixir/secrets"], "files": { "solution": ["secrets.py"], From 7727da68c1f598cb9fca79930704f1276dea1d91 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 19:50:30 -0600 Subject: [PATCH 25/27] Move secrets in config.json to concept --- config.json | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/config.json b/config.json index 8c1c64ab94..66bff60c1d 100644 --- a/config.json +++ b/config.json @@ -175,6 +175,32 @@ "concepts": ["sets"], "prerequisites": ["basics", "dicts", "lists", "loops", "tuples"], "status": "beta" + }, + { + "slug": "secrets", + "name": "Secrets", + "uuid": "1e636fd3-6143-484e-a4fc-0ed6157fdfa1", + "concepts": ["anonymous-functions", "lambdas"], + "prerequisites": [ + "basics", + "booleans", + "comparisons", + "dicts", + "dict-methods", + "functions", + "function-arguments", + "higher-order-functions", + "iteration", + "lists", + "list-methods", + "numbers", + "sequences", + "sets", + "strings", + "string-methods", + "tuples" + ], + "status": "wip" } ], "practice": [ @@ -2279,32 +2305,6 @@ "string-methods" ], "difficulty": 7 - }, - { - "slug": "secrets", - "name": "Secrets", - "uuid": "1e636fd3-6143-484e-a4fc-0ed6157fdfa1", - "practices": ["anonymous-functions", "lambdas"], - "prerequisites": [ - "basics", - "booleans", - "comparisons", - "dicts", - "dict-methods", - "functions", - "function-arguments", - "higher-order-functions", - "iteration", - "lists", - "list-methods", - "numbers", - "sequences", - "sets", - "strings", - "string-methods", - "tuples" - ], - "status": "wip" } ], "foregone": ["lens-person"] From 33db8cdb4a5465cd0b1132ec40054c46493adcc2 Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 19:54:21 -0600 Subject: [PATCH 26/27] add messages to tests --- exercises/concept/secrets/secrets_test.py | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/exercises/concept/secrets/secrets_test.py b/exercises/concept/secrets/secrets_test.py index 7f1ed6fbdd..d2cce9952b 100644 --- a/exercises/concept/secrets/secrets_test.py +++ b/exercises/concept/secrets/secrets_test.py @@ -6,48 +6,48 @@ class TestLambdas(unittest.TestCase): @pytest.mark.task(taskno=1) def test_add_3(self): - self.assertEqual(secret_add(3)(3), 6) + self.assertEqual(secret_add(3)(3), 6, msg="secret_add(3)(3) should be 6") @pytest.mark.task(taskno=1) def test_add_6(self): - self.assertEqual(secret_add(6)(9), 15) + self.assertEqual(secret_add(6)(9), 15, msg="secret_add(6)(9) should be 15") @pytest.mark.task(taskno=2) def test_multiply_by_3(self): - self.assertEqual(secret_multiply(3)(6), 18) + self.assertEqual(secret_multiply(3)(6), 18, msg="secret_add(3)(6) should be 18") @pytest.mark.task(taskno=2) def test_multiply_by_6(self): - self.assertEqual(secret_multiply(6)(7), 42) + self.assertEqual(secret_multiply(6)(7), 42, msg="secret_add(6)(7) should be 42") @pytest.mark.task(taskno=3) def test_max_1(self): - self.assertEqual(secret_max([2, 11])([7, 3]), [2, 11]) + self.assertEqual(secret_max([2, 11])([7, 3]), [2, 11], msg="secret_max([2, 11])([7, 3]) should be [2, 11]") @pytest.mark.task(taskno=3) def test_max_2(self): - self.assertEqual(secret_max([4, 6])([5, 5]), [5, 5]) + self.assertEqual(secret_max([4, 6])([5, 5]), [5, 5], msg="secret_max([4, 6])([5, 5]) should be [5, 5]") @pytest.mark.task(taskno=3) def test_max_3(self): - self.assertEqual(secret_max([25, 73])([56, 32]), [25, 73]) + self.assertEqual(secret_max([25, 73])([56, 32]), [25, 73], msg="secret_max([25, 73])([56, 32]) should be [25, 73]") @pytest.mark.task(taskno=4) def test_sort_1(self): - self.assertEqual(secret_sort(0)([[3, 120, 5], [1, 5, 2], [8, 2, 23]]), [[1, 5, 2], [3, 120, 5], [8, 2, 23]]) + self.assertEqual(secret_sort(0)([[3, 120, 5], [1, 5, 2], [8, 2, 23]]), [[1, 5, 2], [3, 120, 5], [8, 2, 23]], msg="secret_sort(0)([[3, 120, 5], [1, 5, 2], [8, 2, 23]]) should return the list sorted by the first item of every list inside the list") @pytest.mark.task(taskno=4) def test_sort_2(self): - self.assertEqual(secret_sort(1)([[3, 15], [520, 1, 4], [64, 7, 3, 9, 2], [0, 27, 1, 5, 4, 2]]), [[520, 1, 4], [64, 7, 3, 9, 2], [3, 15], [0, 27, 1, 5, 4, 2]]) + self.assertEqual(secret_sort(1)([[3, 15], [520, 1, 4], [64, 7, 3, 9, 2], [0, 27, 1, 5, 4, 2]]), [[520, 1, 4], [64, 7, 3, 9, 2], [3, 15], [0, 27, 1, 5, 4, 2]], msg="secret_sort(1)([[3, 15], ...]) should return the list sorted by the second item of every list") @pytest.mark.task(taskno=5) def test_combine_1(self): - self.assertEqual(secret_combine(secret_add(4), secret_multiply(7))(6), 70) + self.assertEqual(secret_combine(secret_add(4), secret_multiply(7))(6), 70, msg="secret_combine(secret_add(4), secret_multiply(7))(6) should be 70") @pytest.mark.task(taskno=5) def test_combine_2(self): - self.assertEqual(secret_combine(secret_multiply(6), secret_add(4))(11), 70) + self.assertEqual(secret_combine(secret_multiply(6), secret_add(4))(11), 70, msg="secret_combine(secret_multiply(6), secret_add(4))(11) should be 70") @pytest.mark.task(taskno=5) def test_combine_3(self): - self.assertEqual(secret_combine(secret_max([3, 8]), sum)([4, 5]), 11) \ No newline at end of file + self.assertEqual(secret_combine(secret_max([3, 8]), sum)([4, 5]), 11, msg="(secret_combine(secret_max([3, 8]), sum)([4, 5]) should be 11") \ No newline at end of file From 1b4a4a8f78de30164be3b1e4afd2caaf1fb5f93e Mon Sep 17 00:00:00 2001 From: Caleb Miller Date: Fri, 17 Sep 2021 20:19:09 -0600 Subject: [PATCH 27/27] remove random paren --- exercises/concept/secrets/secrets_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/secrets/secrets_test.py b/exercises/concept/secrets/secrets_test.py index d2cce9952b..74dfeb99ff 100644 --- a/exercises/concept/secrets/secrets_test.py +++ b/exercises/concept/secrets/secrets_test.py @@ -50,4 +50,4 @@ def test_combine_2(self): @pytest.mark.task(taskno=5) def test_combine_3(self): - self.assertEqual(secret_combine(secret_max([3, 8]), sum)([4, 5]), 11, msg="(secret_combine(secret_max([3, 8]), sum)([4, 5]) should be 11") \ No newline at end of file + self.assertEqual(secret_combine(secret_max([3, 8]), sum)([4, 5]), 11, msg="secret_combine(secret_max([3, 8]), sum)([4, 5]) should be 11") \ No newline at end of file