From 1772b0794f8ad10cbdefae5e14aa321933811c3f Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Tue, 14 Mar 2023 16:26:34 +0100 Subject: [PATCH 001/126] Sync sum-of-multiples docs with problem-specifications The sum-of-multiples exercise has been improved upstream in the problem-specifications repository. For more context, please see the pull request that updated the exercise: - https://github.com/exercism/problem-specifications/pull/2231 --- .../sum-of-multiples/.docs/instructions.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/exercises/practice/sum-of-multiples/.docs/instructions.md b/exercises/practice/sum-of-multiples/.docs/instructions.md index ff7fdffd86a..7b7ec006e2c 100644 --- a/exercises/practice/sum-of-multiples/.docs/instructions.md +++ b/exercises/practice/sum-of-multiples/.docs/instructions.md @@ -1,7 +1,18 @@ # Instructions -Given a number, find the sum of all the unique multiples of particular numbers up to but not including that number. +Given a list of factors and a limit, add up all the unique multiples of the factors that are less than the limit. +All inputs will be greater than or equal to zero. -If we list all the natural numbers below 20 that are multiples of 3 or 5, we get 3, 5, 6, 9, 10, 12, 15, and 18. +## Example -The sum of these multiples is 78. +Suppose the limit is 20 and the list of factors is [3, 5]. +We need to find the sum of all unique multiples of 3 and 5 that are less than 20. + +Multiples of 3 less than 20: 3, 6, 9, 12, 15, 18 +Multiples of 5 less than 20: 5, 10, 15 + +The unique multiples are: 3, 5, 6, 9, 10, 12, 15, 18 + +The sum of the unique multiples is: 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78 + +So, the answer is 78. From c4d8546f37c741d46d39a978a663b615f371c3d8 Mon Sep 17 00:00:00 2001 From: Hoai-Thu Vuong Date: Fri, 10 Mar 2023 14:18:29 +0700 Subject: [PATCH 002/126] fix typo in the instruction of guidos-gorgeous - remove double in --- exercises/concept/guidos-gorgeous-lasagna/.docs/instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/guidos-gorgeous-lasagna/.docs/instructions.md b/exercises/concept/guidos-gorgeous-lasagna/.docs/instructions.md index 106e30a392f..2d61cec837d 100644 --- a/exercises/concept/guidos-gorgeous-lasagna/.docs/instructions.md +++ b/exercises/concept/guidos-gorgeous-lasagna/.docs/instructions.md @@ -57,7 +57,7 @@ def elapsed_time_in_minutes(number_of_layers, elapsed_bake_time): :param number_of_layers: int - the number of layers in the lasagna. :param elapsed_bake_time: int - elapsed cooking time. - :return: int - total time elapsed (in in minutes) preparing and cooking. + :return: int - total time elapsed (in minutes) preparing and cooking. This function takes two integers representing the number of lasagna layers and the time already spent baking and calculates the total elapsed minutes spent cooking the From 8e5c58583b195ebc57cb0b5a866ad3ced9e5d872 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Thu, 16 Mar 2023 12:38:59 +0100 Subject: [PATCH 003/126] Sync binary-search docs with problem-specifications There were a few follow-on tweaks to binary-search. For context, this is part of the project to overhaul all the practice exercises. You can read about that here: https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 ---- If you approve this pull request, I will eventually merge it. However, if you are happy with this change **please merge the pull request**, as it will get the changes into the hands of the students much more quickly. If this pull request contradicts the exercise on your track, **please add a review with _request changes_**. This will block the pull request from getting merged. Otherwise we aim to take an optimistic merging approach. If you wish to suggest tweaks to these changes, please open a pull request to the exercism/problem-specifications repository to discuss, so that everyone who has an interest in the shared exercise descriptions can participate. --- .../practice/binary-search/.docs/instructions.md | 15 ++++++++------- .../practice/binary-search/.docs/introduction.md | 6 +++++- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/exercises/practice/binary-search/.docs/instructions.md b/exercises/practice/binary-search/.docs/instructions.md index 175c4c4ba8f..d7f1c899229 100644 --- a/exercises/practice/binary-search/.docs/instructions.md +++ b/exercises/practice/binary-search/.docs/instructions.md @@ -5,17 +5,18 @@ Your task is to implement a binary search algorithm. A binary search algorithm finds an item in a list by repeatedly splitting it in half, only keeping the half which contains the item we're looking for. It allows us to quickly narrow down the possible locations of our item until we find it, or until we've eliminated all possible locations. -```exercism/caution +~~~~exercism/caution Binary search only works when a list has been sorted. -``` +~~~~ The algorithm looks like this: -- Divide the sorted list in half and compare the middle element with the item we're looking for. -- If the middle element is our item, then we're done. -- If the middle element is greater than our item, we can eliminate that number and all the numbers **after** it. -- If the middle element is less than our item, we can eliminate that number and all the numbers **before** it. -- Repeat the process on the part of the list that we kept. +- Find the middle element of a sorted list and compare it with the item we're looking for. +- If the middle element is our item, then we're done! +- If the middle element is greater than our item, we can eliminate that element and all the elements **after** it. +- If the middle element is less than our item, we can eliminate that element and all the elements **before** it. +- If every element of the list has been eliminated then the item is not in the list. +- Otherwise, repeat the process on the part of the list that has not been eliminated. Here's an example: diff --git a/exercises/practice/binary-search/.docs/introduction.md b/exercises/practice/binary-search/.docs/introduction.md index 66c4b8a45cb..03496599e75 100644 --- a/exercises/practice/binary-search/.docs/introduction.md +++ b/exercises/practice/binary-search/.docs/introduction.md @@ -1,9 +1,13 @@ # Introduction You have stumbled upon a group of mathematicians who are also singer-songwriters. -They have written a song for each of their favorite numbers, and, as you can imagine, they have a lot of favorite numbers. +They have written a song for each of their favorite numbers, and, as you can imagine, they have a lot of favorite numbers (like [0][zero] or [73][seventy-three] or [6174][kaprekars-constant]). You are curious to hear the song for your favorite number, but with so many songs to wade through, finding the right song could take a while. Fortunately, they have organized their songs in a playlist sorted by the title — which is simply the number that the song is about. You realize that you can use a binary search algorithm to quickly find a song given the title. + +[zero]: https://en.wikipedia.org/wiki/0 +[seventy-three]: https://en.wikipedia.org/wiki/73_(number) +[kaprekars-constant]: https://en.wikipedia.org/wiki/6174_(number) From d783bd143271a8e1db36d655adfd8039754a9268 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Sat, 18 Mar 2023 11:22:17 +0100 Subject: [PATCH 004/126] Update INSTALLATION.md --- docs/INSTALLATION.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 9481ce512e3..ad3463291c0 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -6,7 +6,7 @@ Real Python also offers a [nice guide][helpful guide] to installation on various Finally, these posts by Brett Cannon [A quick-and-dirty guide][quick-and-dirty] and [Why you should use `python -m pip`][python-m-pip], give very helpful advice on how to manage Python installations and packages. **Note for MacOS users:** prior to MacOS Monterey (12.3), `Python 2.7` came pre-installed with the operating system. -Using `Python 2.7` with exercsim or most other programs is not recommended. +Using `Python 2.7` with Exercism or most other programs is not recommended. You should instead install Python 3 via one of the methods detailed below. As of MacOS Monterey (12.3), no version of Python will be pre-installed via MacOS. From 5b1ef82c4e2ffd6ad16e3d5b79f2fba047c88f2b Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Sat, 18 Mar 2023 11:54:00 +0100 Subject: [PATCH 005/126] basics: fix markdown --- concepts/basics/about.md | 2 +- concepts/basics/introduction.md | 2 +- exercises/concept/guidos-gorgeous-lasagna/.docs/introduction.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/concepts/basics/about.md b/concepts/basics/about.md index 929582357c8..30ea083022f 100644 --- a/concepts/basics/about.md +++ b/concepts/basics/about.md @@ -41,7 +41,7 @@ On the Python track, [variables][variables] are always written in [`snake_case`] ## Name Assignment (Variables & Constants) In Python, there are no keywords used in creating variables or constants. -Instead, programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables__) to any type of object using the assignment `=` operator: ` = `. +Instead, programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables_) to any type of object using the assignment `=` operator: ` = `. A name can be reassigned (or re-bound) to different values (different object types) over its lifetime. For example, `my_first_variable` can be re-assigned many times using `=`, and can refer to different object types with each re-assignment: diff --git a/concepts/basics/introduction.md b/concepts/basics/introduction.md index e48e6726515..34e2a8804d7 100644 --- a/concepts/basics/introduction.md +++ b/concepts/basics/introduction.md @@ -12,7 +12,7 @@ Python was created by Guido van Rossum and first released in 1991. ## Name Assignment (Variables & Constants) -Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables__) to any type of object using the assignment `=` operator: ` = `. +Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables_) to any type of object using the assignment `=` operator: ` = `. A name can be reassigned (or re-bound) to different values (different object types) over its lifetime. diff --git a/exercises/concept/guidos-gorgeous-lasagna/.docs/introduction.md b/exercises/concept/guidos-gorgeous-lasagna/.docs/introduction.md index edb9f0fe10e..f9be66c3fe9 100644 --- a/exercises/concept/guidos-gorgeous-lasagna/.docs/introduction.md +++ b/exercises/concept/guidos-gorgeous-lasagna/.docs/introduction.md @@ -24,7 +24,7 @@ On the Python track, [variables][variables] are always written in [`snake_case`] ## Name Assignment (Variables & Constants) -Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables__) to any type of object using the assignment `=` operator: ` = `. +Programmers can bind [_names_][facts-and-myths-about-python-names] (also called _variables_) to any type of object using the assignment `=` operator: ` = `. A name can be reassigned (or re-bound) to different values (different object types) over its lifetime. From 9f6787133a863290b59d71a2a0032943ca5303cf Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Wed, 22 Mar 2023 20:29:25 +0100 Subject: [PATCH 006/126] string-methods: fix typo --- concepts/string-methods/about.md | 4 ++-- exercises/concept/little-sisters-essay/.docs/introduction.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/concepts/string-methods/about.md b/concepts/string-methods/about.md index 81eaffb0a7a..e01cbaf8908 100644 --- a/concepts/string-methods/about.md +++ b/concepts/string-methods/about.md @@ -44,7 +44,7 @@ There may also be [locale][locale] rules in place for a language or character se >>> man_in_hat_th = 'ู้ชายในหมวก' >>> man_in_hat_ru = 'mужчина в шляпе' >>> man_in_hat_ko = '모자를 쓴 남자' ->>> main_in_hat_en = 'the man in the hat.' +>>> man_in_hat_en = 'the man in the hat.' >>> man_in_hat_th.title() 'ผู้ชายในหมวก' @@ -55,7 +55,7 @@ There may also be [locale][locale] rules in place for a language or character se >>> man_in_hat_ko.title() '모자를 쓴 남자' ->> main_in_hat_en.title() +>> man_in_hat_en.title() 'The Man In The Hat.' ``` diff --git a/exercises/concept/little-sisters-essay/.docs/introduction.md b/exercises/concept/little-sisters-essay/.docs/introduction.md index 1b0e9531123..24358f2fc28 100644 --- a/exercises/concept/little-sisters-essay/.docs/introduction.md +++ b/exercises/concept/little-sisters-essay/.docs/introduction.md @@ -24,7 +24,7 @@ There may also be [locale][locale] rules in place for a language or character se man_in_hat_th = 'ู้ชายในหมวก' man_in_hat_ru = 'mужчина в шляпе' man_in_hat_ko = '모자를 쓴 남자' -main_in_hat_en = 'the man in the hat.' +man_in_hat_en = 'the man in the hat.' >>> man_in_hat_th.title() 'ผู้ชายในหมวก' @@ -35,7 +35,7 @@ main_in_hat_en = 'the man in the hat.' >>> man_in_hat_ko.title() '모자를 쓴 남자' ->> main_in_hat_en.title() +>> man_in_hat_en.title() 'The Man In The Hat.' ``` From d8e8cb6ca70423c3b9db43b0ff64e16e4050bf2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Mar 2023 23:56:56 +0000 Subject: [PATCH 007/126] Bump actions/stale from 7 to 8 Bumps [actions/stale](https://github.com/actions/stale) from 7 to 8. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v7...v8) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 4742a0db0a0..41156435d82 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -8,7 +8,7 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v7 + - uses: actions/stale@v8 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 21 From 84c35bac97da78c09f9044f85f6a6335589124b6 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Thu, 30 Mar 2023 20:50:14 -0700 Subject: [PATCH 008/126] Removed numbers concept exercise from Palindrome Products practices array. --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index dbafb1ef987..1d118f79c88 100644 --- a/config.json +++ b/config.json @@ -1441,7 +1441,7 @@ "slug": "palindrome-products", "name": "Palindrome Products", "uuid": "fa795dcc-d390-4e98-880c-6e8e638485e3", - "practices": ["functions", "function-arguments", "numbers"], + "practices": ["functions", "function-arguments"], "prerequisites": [ "basics", "bools", From 9bbd540c5c752226296e586162cd76ffe4b6dde8 Mon Sep 17 00:00:00 2001 From: Hanson Char Date: Thu, 6 Apr 2023 07:47:02 -0700 Subject: [PATCH 009/126] Minor simplification to is_pangram in the Bit field approach --- exercises/practice/pangram/.approaches/bitfield/content.md | 4 ++-- .../practice/pangram/.articles/performance/code/Benchmark.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/exercises/practice/pangram/.approaches/bitfield/content.md b/exercises/practice/pangram/.approaches/bitfield/content.md index 20e460fea0d..b292540567e 100644 --- a/exercises/practice/pangram/.approaches/bitfield/content.md +++ b/exercises/practice/pangram/.approaches/bitfield/content.md @@ -9,9 +9,9 @@ ALL_26_BITS_SET = 67108863 def is_pangram(sentence): letter_flags = 0 for letter in sentence: - if letter >= 'a' and letter <= 'z': + if 'a' <= letter <= 'z': letter_flags |= 1 << ord(letter) - A_LCASE - elif letter >= 'A' and letter <= 'Z': + elif 'A' <= letter <= 'Z': letter_flags |= 1 << ord(letter) - A_UCASE return letter_flags == ALL_26_BITS_SET diff --git a/exercises/practice/pangram/.articles/performance/code/Benchmark.py b/exercises/practice/pangram/.articles/performance/code/Benchmark.py index 729cc967dc9..1b423744479 100644 --- a/exercises/practice/pangram/.articles/performance/code/Benchmark.py +++ b/exercises/practice/pangram/.articles/performance/code/Benchmark.py @@ -43,9 +43,9 @@ def is_pangram(sentence): def is_pangram(sentence): letter_flags = 0 for letter in sentence: - if letter >= 'a' and letter <= 'z': + if 'a' <= letter <= 'z': letter_flags |= 1 << (ord(letter) - A_LCASE) - elif letter >= 'A' and letter <= 'Z': + elif 'A' <= letter <= 'Z': letter_flags |= 1 << (ord(letter) - A_UCASE) return letter_flags == ALL_26_BITS_SET From c865759d7d45449eabbcfa73b9f08dc7adb4975f Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 7 Apr 2023 04:19:47 -0700 Subject: [PATCH 010/126] Updated refrences to Python 3.10 --> 3.11. (#3384) --- CONTRIBUTING.md | 13 +++++++------ README.md | 23 ++++++++++++++--------- docs/ABOUT.md | 12 ++++++++---- docs/GENERATOR.md | 17 +++++++++++++---- docs/INSTALLATION.md | 18 ++++++++++++------ docs/LEARNING.md | 5 +++-- docs/TESTS.md | 2 +- exercises/shared/.docs/help.md | 1 + 8 files changed, 59 insertions(+), 32 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 691ca9f92fc..7f082a56322 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -28,14 +28,13 @@ Please read this [community blog post](https://exercism.org/blog/freeing-our-mai **`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website]. This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students. -🌟   Track exercises support Python `3.7` - `3.10.6`. +🌟   Track exercises support Python `3.7` - `3.11.2`. Exceptions to this support are noted where they occur. - 🌟   Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.10.6`. +🌟   Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.2`. -Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree  🌴  . -Concept exercises are constrained to a small set of language or syntax features. -Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. -These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory. +Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree  🌴 . +Concept exercises are constrained to a small set of language or syntax features. +Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory.
@@ -430,3 +429,5 @@ configlet generate --spec-path path/to/problem/specifications [version-tagged-language-features]: https://docs.python.org/3/library/stdtypes.html#dict.popitem [website-contributing-section]: https://exercism.org/docs/building [yapf]: https://github.com/google/yapf + +[config-json]: https://github.com/exercism/python/blob/main/config.json diff --git a/README.md b/README.md index 64930816362..1c82f33b9d0 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

Exercism Python Track

                          [![Discourse topics](https://img.shields.io/discourse/topics?color=8A08E6&label=Connect%20&labelColor=FFDF58&logo=Discourse&logoColor=8A08E6&server=https%3A%2F%2Fforum.exercism.org&style=social)](https://forum.exercism.org) -  [![Exercism_II](https://img.shields.io/badge/Exercism--Built-9101FF?logo=python&logoColor=FFDF58&labelColor=3D7AAB&label=Python%203.10%20Powered)](https://exercism.org) +  [![Exercism_II](https://img.shields.io/badge/Exercism--Built-9101FF?logo=python&logoColor=FFDF58&labelColor=3D7AAB&label=Python%203.11%20Powered)](https://exercism.org)   [![Exercism_III](https://img.shields.io/badge/PAUSED-C73D4E?labelColor=3D454D&label=Contributions)](https://exercism.org/blog/freeing-our-maintainers)   [![Build Status](https://github.com/exercism/python/workflows/Exercises%20check/badge.svg)](https://github.com/exercism/python/actions?query=workflow%3A%22Exercises+check%22) @@ -17,11 +17,13 @@ Hi.  👋🏽  👋  **We are happy you are here.**  🎉&nb **`exercism/Python`** is one of many programming language tracks on [exercism(dot)org][exercism-website]. This repo holds all the instructions, tests, code, & support files for Python _exercises_ currently under development or implemented & available for students. -🌟   Track exercises support Python `3.7` - `3.10.6`. +🌟   Track exercises support Python `3.7` - `3.11.2`. Exceptions to this support are noted where they occur. - 🌟   Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.10.6`. +🌟   Track tooling (_test-runner, representer, analyzer, and Continuous Integration_) runs on Python `3.11.2`. -Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree  🌴  . Concept exercises are constrained to a small set of language or syntax features. Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory. +Exercises are grouped into **concept** exercises which teach the [Python syllabus][python-syllabus], and **practice** exercises, which are unlocked by progressing in the syllabus tree  🌴 . +Concept exercises are constrained to a small set of language or syntax features. +Practice exercises are open-ended, and can be used to practice concepts learned, try out new techniques, and _play_. These two exercise groupings can be found in the track [config.json][config-json], and under the `python/exercises` directory.

@@ -43,24 +45,25 @@ It might also be helpful to look at [Being a Good Community Member][being-a-good We 💛 💙   our community. **`But our maintainers are not accepting community contributions at this time.`** -Please read this [community blog post](https://exercism.org/blog/freeing-our-maintainers) for details. +Please read this [community blog post][freeing-maintainers] for details.
- + Here to suggest a new feature or new exercise?? **Hooray!**  🎉   -We'd love if you did that via our [Exercism Community Forum](https://forum.exercism.org/). Please keep in mind [Chesterton's Fence][chestertons-fence]. +We'd love if you did that via our [Exercism Community Forum](https://forum.exercism.org/). +Please read [Suggesting Exercise Improvements][suggesting-improvements] & [Chesterton's Fence][chestertons-fence]. _Thoughtful suggestions will likely result faster & more enthusiastic responses from volunteers._
- ✨ 🦄  _**Want to jump directly into Exercism specifications & detail?**_      [Structure][exercism-track-structure] **|** [Tasks][exercism-tasks] **|** [Concepts][exercism-concepts] **|** [Concept Exercises][concept-exercises] **|** [Practice Exercises][practice-exercises] **|** [Presentation][exercise-presentation]      [Writing Style Guide][exercism-writing-style] **|** [Markdown Specification][exercism-markdown-specification] (_✨ version in [contributing][website-contributing-section] on exercism.org_) -

+
+
## Python Software and Documentation @@ -94,10 +97,12 @@ This repository uses the [MIT License](/LICENSE). [exercism-track-structure]: https://github.com/exercism/docs/tree/main/building/tracks [exercism-website]: https://exercism.org/ [exercism-writing-style]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md +[freeing-maintainers]: https://exercism.org/blog/freeing-our-maintainers [practice-exercises]: https://github.com/exercism/docs/blob/main/building/tracks/practice-exercises.md [prs]: https://github.com/exercism/docs/blob/main/community/good-member/pull-requests.md [psf-license]: https://docs.python.org/3/license.html#psf-license [python-syllabus]: https://exercism.org/tracks/python/concepts +[suggesting-improvements]: https://github.com/exercism/docs/blob/main/community/good-member/suggesting-exercise-improvements.md [the-words-that-we-use]: https://github.com/exercism/docs/blob/main/community/good-member/words.md [website-contributing-section]: https://exercism.org/docs/building [zero-clause-bsd]: https://docs.python.org/3/license.html#zero-clause-bsd-license-for-code-in-the-python-release-documentation diff --git a/docs/ABOUT.md b/docs/ABOUT.md index 9b53653fd17..05c56799ac6 100644 --- a/docs/ABOUT.md +++ b/docs/ABOUT.md @@ -20,13 +20,14 @@ Code can be written and executed from the command line, in an interactive interp The [zen of Python (PEP 20)][the zen of python] and [What is Pythonic?][what is pythonic] lay out additional philosophies and perspectives on the language. -This track currently uses `Python 3.9.0`. +Tests and tooling for this track currently support `3.7` - `3.10.6` (_tests_) and [`Python 3.11`][311-new-features] (_tooling_). It is highly recommended that students upgrade to at least `Python 3.8`, as some features used by this track may not be supported in earlier versions. -That being said, most exercises can be completed using Python 3.7, and many can be worked in Python 3.6. -We will note when a feature is only available in a certain version. +That being said, most of the exercises will work with `Python 3.6+`, and many are compatible with `Python 2.7+`. +But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases]. +We will try to note when a feature is only available in a certain version. -Complete documentation for the current release of Python (3.9.7) can be found at [docs.python.org][python docs]. +Complete documentation for the current release of Python (3.11.2) can be found at [docs.python.org][python docs]. - [Python Tutorial][python tutorial] - [Python Library Reference][python library reference] @@ -36,6 +37,9 @@ Complete documentation for the current release of Python (3.9.7) can be found at - [Python Glossary of Terms][python glossary of terms] + +[311-new-features]: https://docs.python.org/3/whatsnew/3.11.html +[active-python-releases]: https://www.python.org/downloads/ [duck typing]: https://en.wikipedia.org/wiki/Duck_typing [dynamic typing in python]: https://stackoverflow.com/questions/11328920/is-python-strongly-typed [editors for python]: https://djangostars.com/blog/python-ide/ diff --git a/docs/GENERATOR.md b/docs/GENERATOR.md index d1a8a1da495..271c03d71f1 100644 --- a/docs/GENERATOR.md +++ b/docs/GENERATOR.md @@ -1,7 +1,8 @@ # Exercism Python Track Test Generator -The Python track uses a generator script and [Jinja2] templates for -creating test files from the canonical data. +The Python track uses a generator script and [Jinja2][Jinja2] templates for +creating test files from Exercism's [canonical data][canonical data]. + ## Table of Contents @@ -15,14 +16,16 @@ creating test files from the canonical data. * [Learning Jinja](#learning-jinja) * [Creating a templates](#creating-a-templates) + ## Script Usage -Test generation requires a local copy of the [problem-specifications] repository. +Test generation requires a local copy of the [problem-specifications][problem-specifications] repository. The script should be run from the root `python` directory, in order to correctly access the exercises. Run `bin/generate_tests.py --help` for usage information. + ## Test Templates Test templates support [Jinja2] syntax, and have the following context @@ -42,6 +45,7 @@ Additionally, the following template filters are added for convenience: - `error_case`: Checks if a test case expects an error to be thrown (ex: `{% for case in cases%}{% if case is error_case}`) - `regex_replace`: Regex string replacement (ex: `{{ "abc123" | regex_replace("\\d", "D") }}` -> `abcDDD`) + ### Conventions - General-use macros for highly repeated template structures are defined in `config/generator_macros.j2`. @@ -63,6 +67,7 @@ files. # Additional tests for this track ``` + ### Layout Most templates will look something like this: @@ -83,6 +88,7 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ macros.footer() }} ``` + ### Overriding Imports The names imported in `macros.header()` may be overridden by adding @@ -92,6 +98,7 @@ a list of alternate names to import (ex:`clock`): {{ macros.header(["Clock"])}} ``` + ### Ignoring Properties On rare occasion, it may be necessary to filter out properties that @@ -102,6 +109,7 @@ are not tested in this track. The `header` macro also accepts an {{ macros.header(ignore=["scores"]) }} ``` + ## Learning Jinja Starting with the [Jinja Documentation] is highly recommended, but a complete reading is not strictly necessary. @@ -127,8 +135,9 @@ Additional Resources: +[Jinja Documentation]: https://jinja.palletsprojects.com/en/3.1.x/ [Jinja2]: https://palletsprojects.com/p/jinja/ -[Jinja Documentation]: https://jinja.palletsprojects.com/en/2.10.x/ [Primer on Jinja Templating]: https://realpython.com/primer-on-jinja-templating/ [Python Jinja tutorial]: http://zetcode.com/python/jinja/ +[canonical data]: https://github.com/exercism/problem-specifications/tree/main/exercises [problem-specifications]: https://github.com/exercism/problem-specifications diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index ad3463291c0..8bf42a04529 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -7,7 +7,7 @@ Finally, these posts by Brett Cannon [A quick-and-dirty guide][quick-and-dirty] **Note for MacOS users:** prior to MacOS Monterey (12.3), `Python 2.7` came pre-installed with the operating system. Using `Python 2.7` with Exercism or most other programs is not recommended. -You should instead install Python 3 via one of the methods detailed below. +You should instead install [Python 3][Python-three downloads] via one of the methods detailed below. As of MacOS Monterey (12.3), no version of Python will be pre-installed via MacOS. Some quick links into the documentation by operating system: @@ -18,12 +18,18 @@ Some quick links into the documentation by operating system: We recommend reviewing some of the methods outlined in the Real Python article [Installing Python][installing-python] or the articles by Brett Cannon linked above. -Exercism tests and tooling currently support `Python 3.8` (_tests_) and `Python 3.9` (_tooling_). -This means that the [newest features of Python `3.10`][310-new-features] are **not** currently supported. -Please refer to the [Python 3.9.x documentation][3.9 docs] for what is currently supported. +Exercism tests and tooling currently support `3.7` - `3.10.6` (_tests_) and [`Python 3.11`][311-new-features] (_tooling_). +Exceptions to this support are noted where they occur. +Most of the exercises will work with `Python 3.6+`, and many are compatible with `Python 2.7+`. +But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases]. -[3.9 docs]: https://docs.python.org/3.9/ -[310-new-features]: https://docs.python.org/3/whatsnew/3.10.html + +Please refer to the [Python 3.11.x documentation][3.11 docs] for what is currently supported. + +[3.11 docs]: https://docs.python.org/3.11/ +[311-new-features]: https://docs.python.org/3/whatsnew/3.11.html +[Python-three downloads]: https://www.python.org/downloads/ +[active-python-releases]: https://www.python.org/downloads/ [helpful guide]: https://realpython.com/installing-python/ [installing-python]: https://realpython.com/installing-python/#what-your-options-are_1 [macos]: https://docs.python.org/3/using/mac.html diff --git a/docs/LEARNING.md b/docs/LEARNING.md index 15e4fd80215..f9cb1b22051 100644 --- a/docs/LEARNING.md +++ b/docs/LEARNING.md @@ -21,12 +21,13 @@ Below you will find some additional jumping-off places to start your learning jo - [Think Python][Think Python] - [Python for Non-Programmers][python-for-non-programmers] - [Python 4 Everyone][python4everyone] -- [Introduction to Computer Science and Programming in Python (MIT)][mitocw600] - [Googles Python Class][googles python class] - [Microsoft's Python Learning Path][MS Python] -- [PyCharm EDU **IDE** and **Courses**][pycharm edu] (_paid_) +- [Introduction to Computer Science and Programming in Python (MIT)][mitocw600] +- [Harvard CS50P][CS50P] +[CS50P]: https://pll.harvard.edu/course/cs50s-introduction-programming-python?delta=0 [Learn X in Y minutes]: https://learnxinyminutes.com/docs/python3/ [MS Python]: https://docs.microsoft.com/en-us/learn/paths/python-language/ [Python Documentation Tutorial]: https://docs.python.org/3/tutorial/index.html diff --git a/docs/TESTS.md b/docs/TESTS.md index 9e522b12d57..00ff924cd73 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -272,5 +272,5 @@ export PATH=”$PATH:{python_directory}}” [python command line]: https://docs.python.org/3/using/cmdline.html [python-m-pip]: https://snarky.ca/why-you-should-use-python-m-pip/ [quick-and-dirty]: https://snarky.ca/a-quick-and-dirty-guide-on-how-to-install-packages-for-python/ -[tutorial from pycqa.org]: https://pylint.pycqa.org/en/latest/tutorial.html +[tutorial from pycqa.org]: https://pylint.pycqa.org/en/v2.17.2/tutorial.html [working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers diff --git a/exercises/shared/.docs/help.md b/exercises/shared/.docs/help.md index 0e105b02d94..ef95bd6193b 100644 --- a/exercises/shared/.docs/help.md +++ b/exercises/shared/.docs/help.md @@ -3,6 +3,7 @@ Below are some resources for getting help if you run into trouble: - [The PSF](https://www.python.org) hosts Python downloads, documentation, and community resources. +- [The Exercism Community on Discord](https://exercism.org/r/discord) - [Python Community on Discord](https://pythondiscord.com/) is a very helpful and active community. - [/r/learnpython/](https://www.reddit.com/r/learnpython/) is a subreddit designed for Python learners. - [#python on Libera.chat](https://www.python.org/community/irc/) this is where the core developers for the language hang out and get work done. From 6cc4b919ec04e6e2e777e58ff926e77054b4c26c Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 7 Apr 2023 04:20:05 -0700 Subject: [PATCH 011/126] [Track CI] Upgrade Workflow to use Python `3.11.2` & Pytest `7.2.2` (#3382) * Upgraded CI workflow to use Python 3.11.2 and Pytest 7.2.2 * Pinned Pylint version to ~=2.17.1 * Added tomli to test_exercises.py imports. * Adding in tomli for dependancies. * Need to use latest build of Black due to Python 3.11 and packaging problems with tomli * Regenerated test files for exercises failing CI. * Try removing tomli to see if it fixes CI for Py3.11 * And more version fishing for black, which is the culprit here. * Regeneraed test files with black 22.3.0, since black 23.3.0 is incompatible with Python 3.11 due to tomli conflicts. * Trying a different strategy. Using only 3.11 for the main container. * Must import tomllib, part of exteded standard lib not core. * Wrapped tomllib in a try-catch and aliased importing tomli. Updated requirements to only install tmli on 3.10 and below. * Forgot to update the imports in the generator. * Added paasio test changes here, since this changes the CI checker to use Python 3.11. * Trying a msg= approach. --- .github/workflows/ci-workflow.yml | 6 +++--- bin/data.py | 11 +++++++++-- bin/generate_tests.py | 8 +++++++- exercises/practice/paasio/paasio_test.py | 20 ++++++++------------ requirements-generator.txt | 4 ++-- requirements.txt | 5 +++-- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml index fe8ff089a67..01ddab0cac5 100644 --- a/.github/workflows/ci-workflow.yml +++ b/.github/workflows/ci-workflow.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.10.6 + python-version: 3.11.2 - name: Download & Install dependencies run: | @@ -53,7 +53,7 @@ jobs: needs: housekeeping strategy: matrix: - python-version: [3.7, 3.8, 3.9, 3.10.6] + python-version: [3.7, 3.8, 3.9, 3.10.6, 3.11.2] steps: - uses: actions/checkout@v3 @@ -66,7 +66,7 @@ jobs: run: pip install dataclasses - name: Install pytest - run: pip install pytest~=7.1.2 + run: pip install pytest~=7.2.2 - name: Check exercises run: | diff --git a/bin/data.py b/bin/data.py index 54dec7612b3..7fce51b9087 100644 --- a/bin/data.py +++ b/bin/data.py @@ -4,9 +4,16 @@ from itertools import chain import json from pathlib import Path -import tomli from typing import List, Any, Dict, Type +# Tomli was subsumed into Python 3.11.x, but was renamed to to tomllib. +# This avoids ci failures for Python < 3.11.2. +try: + import tomllib +except ModuleNotFoundError: + import tomli as tomllib + + def _custom_dataclass_init(self, *args, **kwargs): # print(self.__class__.__name__, "__init__") @@ -355,7 +362,7 @@ class TestsTOML: @classmethod def load(cls, toml_path: Path): with toml_path.open("rb") as f: - data = tomli.load(f) + data = tomllib.load(f) return cls({uuid: TestCaseTOML(uuid, *opts) for uuid, opts in data.items() if diff --git a/bin/generate_tests.py b/bin/generate_tests.py index d0406aad5e2..8dc74936b14 100755 --- a/bin/generate_tests.py +++ b/bin/generate_tests.py @@ -34,11 +34,17 @@ from itertools import repeat from string import punctuation, whitespace from subprocess import check_call -import tomli from tempfile import NamedTemporaryFile from textwrap import wrap from typing import Any, Dict, List, NoReturn, Union +# Tomli was subsumed into Python 3.11.x, but was renamed to to tomllib. +# This avoids ci failures for Python < 3.11.2. +try: + import tomllib +except ModuleNotFoundError: + import tomli as tomllib + from jinja2 import Environment, FileSystemLoader, TemplateNotFound, UndefinedError from dateutil.parser import parse diff --git a/exercises/practice/paasio/paasio_test.py b/exercises/practice/paasio/paasio_test.py index 07a5cea7a55..c5c7ff73176 100644 --- a/exercises/practice/paasio/paasio_test.py +++ b/exercises/practice/paasio/paasio_test.py @@ -199,13 +199,13 @@ def test_meteredsocket_stats_read_only(self): self.assertEqual(282, socket.send_bytes) self.assertEqual(258, socket.recv_ops) self.assertEqual(259, socket.recv_bytes) - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'send_ops' of 'MeteredSocket' object has no setter"): socket.send_ops = 0 - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'send_bytes' of 'MeteredSocket' object has no setter"): socket.send_bytes = 0 - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'recv_ops' of 'MeteredSocket' object has no setter"): socket.recv_ops = 0 - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'recv_bytes' of 'MeteredSocket' object has no setter"): socket.recv_bytes = 0 self.assertEqual(278, socket.send_ops) self.assertEqual(282, socket.send_bytes) @@ -426,19 +426,15 @@ def test_meteredfile_stats_read_only(self, super_mock): file.write(b"bytes") self.assertEqual(78, file.write_ops) self.assertEqual(82, file.write_bytes) - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'write_ops' of 'MeteredFile' object has no setter"): file.write_ops = 0 - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'write_bytes' of 'MeteredFile' object has no setter"): file.write_bytes = 0 - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'read_ops' of 'MeteredFile' object has no setter"): file.read_ops = 0 - with self.assertRaisesRegex(AttributeError, "can't set"): + with self.assertRaises(AttributeError, msg="property 'read_bytes' of 'MeteredFile' object has no setter"): file.read_bytes = 0 self.assertEqual(78, file.write_ops) self.assertEqual(82, file.write_bytes) self.assertEqual(58, file.read_ops) self.assertEqual(59, file.read_bytes) - - -if __name__ == "__main__": - unittest.main() diff --git a/requirements-generator.txt b/requirements-generator.txt index 3c096bebc1e..d472d158b9b 100644 --- a/requirements-generator.txt +++ b/requirements-generator.txt @@ -1,6 +1,6 @@ -black==22.3.0 +black<=22.3.0 flake8~=5.0.4 Jinja2~=3.1.2 python-dateutil==2.8.1 markupsafe==2.0.1 -tomli~=2.0.1 +tomli>=1.1.0; python_full_version < '3.11.2' diff --git a/requirements.txt b/requirements.txt index d8556f8d612..5b97def747d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ astroid<=2.12.0 flake8~=5.0.4 -pylint~=2.14.5 +pylint~=2.17.1 +black<=22.3.0 yapf~=0.32.0 -tomli~=2.0.1 \ No newline at end of file +tomli>=1.1.0; python_full_version < '3.11.2' \ No newline at end of file From 944f0b8a5e1e3f55e3e70b94325a0108cc15ad9b Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Sun, 9 Apr 2023 14:15:01 +0200 Subject: [PATCH 012/126] Sync etl docs with problem-specifications The etl exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2250 --- exercises/practice/etl/.docs/instructions.md | 29 ++++++-------------- exercises/practice/etl/.docs/introduction.md | 16 +++++++++++ 2 files changed, 24 insertions(+), 21 deletions(-) create mode 100644 exercises/practice/etl/.docs/introduction.md diff --git a/exercises/practice/etl/.docs/instructions.md b/exercises/practice/etl/.docs/instructions.md index fffe64f2015..802863b5405 100644 --- a/exercises/practice/etl/.docs/instructions.md +++ b/exercises/practice/etl/.docs/instructions.md @@ -1,19 +1,8 @@ # Instructions -We are going to do the `Transform` step of an Extract-Transform-Load. +Your task is to change the data format of letters and their point values in the game. -## ETL - -Extract-Transform-Load (ETL) is a fancy way of saying, "We have some crufty, legacy data over in this system, and now we need it in this shiny new system over here, so we're going to migrate this." - -(Typically, this is followed by, "We're only going to need to run this once." -That's then typically followed by much forehead slapping and moaning about how stupid we could possibly be.) - -## The goal - -We're going to extract some Scrabble scores from a legacy system. - -The old system stored a list of letters per score: +Currently, letters are stored in groups based on their score, in a one-to-many mapping. - 1 point: "A", "E", "I", "O", "U", "L", "N", "R", "S", "T", - 2 points: "D", "G", @@ -23,18 +12,16 @@ The old system stored a list of letters per score: - 8 points: "J", "X", - 10 points: "Q", "Z", -The shiny new Scrabble system instead stores the score per letter, which makes it much faster and easier to calculate the score for a word. -It also stores the letters in lower-case regardless of the case of the input letters: +This needs to be changed to store each individual letter with its score in a one-to-one mapping. - "a" is worth 1 point. - "b" is worth 3 points. - "c" is worth 3 points. - "d" is worth 2 points. -- Etc. - -Your mission, should you choose to accept it, is to transform the legacy data format to the shiny new format. +- etc. -## Notes +As part of this change, the team has also decided to change the letters to be lower-case rather than upper-case. -A final note about scoring, Scrabble is played around the world in a variety of languages, each with its own unique scoring table. -For example, an "E" is scored at 2 in the Māori-language version of the game while being scored at 4 in the Hawaiian-language version. +~~~~exercism/note +If you want to look at how the data was previously structured and how it needs to change, take a look at the examples in the test suite. +~~~~ diff --git a/exercises/practice/etl/.docs/introduction.md b/exercises/practice/etl/.docs/introduction.md new file mode 100644 index 00000000000..5be65147d7f --- /dev/null +++ b/exercises/practice/etl/.docs/introduction.md @@ -0,0 +1,16 @@ +# Introduction + +You work for a company that makes an online multiplayer game called Lexiconia. + +To play the game, each player is given 13 letters, which they must rearrange to create words. +Different letters have different point values, since it's easier to create words with some letters than others. + +The game was originally launched in English, but it is very popular, and now the company wants to expand to other languages as well. + +Different languages need to support different point values for letters. +The point values are determined by how often letters are used, compared to other letters in that language. + +For example, the letter 'C' is quite common in English, and is only worth 3 points. +But in Norwegian it's a very rare letter, and is worth 10 points. + +To make it easier to add new languages, your team needs to change the way letters and their point values are stored in the game. From bff0b7e31d63b854a06475b8808cc9bb5eb3da22 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Sun, 9 Apr 2023 16:43:54 +0200 Subject: [PATCH 013/126] Sync linked-list docs with problem-specifications The linked-list exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2245 --- .../linked-list/.docs/instructions.md | 34 +++++++++---------- .../linked-list/.docs/introduction.md | 6 ++++ 2 files changed, 23 insertions(+), 17 deletions(-) create mode 100644 exercises/practice/linked-list/.docs/introduction.md diff --git a/exercises/practice/linked-list/.docs/instructions.md b/exercises/practice/linked-list/.docs/instructions.md index 3d949d39357..a47942d73db 100644 --- a/exercises/practice/linked-list/.docs/instructions.md +++ b/exercises/practice/linked-list/.docs/instructions.md @@ -1,26 +1,26 @@ # Instructions -Implement a doubly linked list. +Your team has decided to use a doubly linked list to represent each train route in the schedule. +Each station along the train's route will be represented by a node in the linked list. -Like an array, a linked list is a simple linear data structure. -Several common data types can be implemented using linked lists, like queues, stacks, and associative arrays. +You don't need to worry about arrival and departure times at the stations. +Each station will simply be represented by a number. -A linked list is a collection of data elements called *nodes*. -In a *singly linked list* each node holds a value and a link to the next node. -In a *doubly linked list* each node also holds a link to the previous node. +Routes can be extended, adding stations to the beginning or end of a route. +They can also be shortened by removing stations from the beginning or the end of a route. -You will write an implementation of a doubly linked list. -Implement a Node to hold a value and pointers to the next and previous nodes. -Then implement a List which holds references to the first and last node and offers an array-like interface for adding and removing items: +Sometimes a station gets closed down, and in that case the station needs to be removed from the route, even if it is not at the beginning or end of the route. -- `push` (*insert value at back*); -- `pop` (*remove value at back*); -- `shift` (*remove value at front*). -- `unshift` (*insert value at front*); +The size of a route is measured not by how far the train travels, but by how many stations it stops at. -To keep your implementation simple, the tests will not cover error conditions. -Specifically: `pop` or `shift` will never be called on an empty list. +```exercism/note +The linked list is a fundamental data structure in computer science, often used in the implementation of other data structures. +As the name suggests, it is a list of nodes that are linked together. +It is a list of "nodes", where each node links to its neighbor or neighbors. +In a **singly linked list** each node links only to the node that follows it. +In a **doubly linked list** each node links to both the node that comes before, as well as the node that comes after. -Read more about [linked lists on Wikipedia][linked-lists]. +If you want to dig deeper into linked lists, check out [this article][intro-linked-list] that explains it using nice drawings. -[linked-lists]: https://en.wikipedia.org/wiki/Linked_list +[intro-linked-list]: https://medium.com/basecs/whats-a-linked-list-anyway-part-1-d8b7e6508b9d +``` diff --git a/exercises/practice/linked-list/.docs/introduction.md b/exercises/practice/linked-list/.docs/introduction.md new file mode 100644 index 00000000000..6e83ae7b6e5 --- /dev/null +++ b/exercises/practice/linked-list/.docs/introduction.md @@ -0,0 +1,6 @@ +# Introduction + +You are working on a project to develop a train scheduling system for a busy railway network. + +You've been asked to develop a prototype for the train routes in the scheduling system. +Each route consists of a sequence of train stations that a given train stops at. From 999321d6237463b974a2d717c78c76e06ed5c881 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Sun, 9 Apr 2023 15:46:13 +0200 Subject: [PATCH 014/126] Sync word-count docs with problem-specifications The word-count exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2247 --- .../practice/word-count/.docs/instructions.md | 52 ++++++++++++------- .../practice/word-count/.docs/introduction.md | 8 +++ 2 files changed, 42 insertions(+), 18 deletions(-) create mode 100644 exercises/practice/word-count/.docs/introduction.md diff --git a/exercises/practice/word-count/.docs/instructions.md b/exercises/practice/word-count/.docs/instructions.md index 8b7f03ede7a..064393c8a0f 100644 --- a/exercises/practice/word-count/.docs/instructions.md +++ b/exercises/practice/word-count/.docs/instructions.md @@ -1,31 +1,47 @@ # Instructions -Given a phrase, count the occurrences of each _word_ in that phrase. +Your task is to count how many times each word occurs in a subtitle of a drama. -For the purposes of this exercise you can expect that a _word_ will always be one of: +The subtitles from these dramas use only ASCII characters. -1. A _number_ composed of one or more ASCII digits (ie "0" or "1234") OR -2. A _simple word_ composed of one or more ASCII letters (ie "a" or "they") OR -3. A _contraction_ of two _simple words_ joined by a single apostrophe (ie "it's" or "they're") +The characters often speak in casual English, using contractions like _they're_ or _it's_. +Though these contractions come from two words (e.g. _we are_), the contraction (_we're_) is considered a single word. -When counting words you can assume the following rules: +Words can be separated by any form of punctuation (e.g. ":", "!", or "?") or whitespace (e.g. "\t", "\n", or " "). +The only punctuation that does not separate words is the apostrophe in contractions. -1. The count is _case insensitive_ (ie "You", "you", and "YOU" are 3 uses of the same word) -2. The count is _unordered_; the tests will ignore how words and counts are ordered -3. Other than the apostrophe in a _contraction_ all forms of _punctuation_ are regarded as spaces -4. The words can be separated by _any_ form of whitespace (ie "\t", "\n", " ") +Numbers are considered words. +If the subtitles say _It costs 100 dollars._ then _100_ will be its own word. -For example, for the phrase `"That's the password: 'PASSWORD 123'!", cried the Special Agent.\nSo I fled.` the count would be: +Words are case insensitive. +For example, the word _you_ occurs three times in the following sentence: + +> You come back, you hear me? DO YOU HEAR ME? + +The ordering of the word counts in the results doesn't matter. + +Here's an example that incorporates several of the elements discussed above: + +- simple words +- contractions +- numbers +- case insensitive words +- punctuation (including apostrophes) to separate words +- different forms of whitespace to separate words + +`"That's the password: 'PASSWORD 123'!", cried the Special Agent.\nSo I fled.` + +The mapping for this subtitle would be: ```text -that's: 1 -the: 2 -password: 2 123: 1 -cried: 1 -special: 1 agent: 1 -so: 1 -i: 1 +cried: 1 fled: 1 +i: 1 +password: 2 +so: 1 +special: 1 +that's: 1 +the: 2 ``` diff --git a/exercises/practice/word-count/.docs/introduction.md b/exercises/practice/word-count/.docs/introduction.md new file mode 100644 index 00000000000..1654508e79d --- /dev/null +++ b/exercises/practice/word-count/.docs/introduction.md @@ -0,0 +1,8 @@ +# Introduction + +You teach English as a foreign language to high school students. + +You've decided to base your entire curriculum on TV shows. +You need to analyze which words are used, and how often they're repeated. + +This will let you choose the simplest shows to start with, and to gradually increase the difficulty as time passes. From 7446286e8f3fe49d066478c9be7d3623c89e8ea8 Mon Sep 17 00:00:00 2001 From: HliebS <129861638+HliebS@users.noreply.github.com> Date: Mon, 10 Apr 2023 20:28:53 +0200 Subject: [PATCH 015/126] Fix English-Ukrainian translation typo (#3394) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The provided translation was from English to Russian. In Ukrainian "nine" is written with an apostrophe - дев'ять. --- exercises/concept/little-sisters-vocab/.docs/introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/concept/little-sisters-vocab/.docs/introduction.md b/exercises/concept/little-sisters-vocab/.docs/introduction.md index d7ccff84e64..220b9b73ebc 100644 --- a/exercises/concept/little-sisters-vocab/.docs/introduction.md +++ b/exercises/concept/little-sisters-vocab/.docs/introduction.md @@ -36,13 +36,13 @@ Strings can be concatenated using the `+` operator. ```python language = "Ukrainian" number = "nine" -word = "девять" +word = "дев'ять" sentence = word + " " + "means" + " " + number + " in " + language + "." >>> print(sentence) ... -"девять means nine in Ukrainian." +"дев'ять means nine in Ukrainian." ``` If a `list`, `tuple`, `set` or other collection of individual strings needs to be combined into a single `str`, [`.join()`][str-join], is a better option: From cade613a31dd4df3cff5aed75b380d451f71043a Mon Sep 17 00:00:00 2001 From: BethanyG Date: Mon, 10 Apr 2023 12:01:27 -0700 Subject: [PATCH 016/126] [Strings Concept] Update about.md to fix Ukrainian Example Per PR 3394, fixed the Ukraninian example in the concept `about.md`, to match the corrected on in the exercise `introduction.md`. --- concepts/strings/about.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/concepts/strings/about.md b/concepts/strings/about.md index 895bad45b42..0107f6e70f0 100644 --- a/concepts/strings/about.md +++ b/concepts/strings/about.md @@ -159,13 +159,13 @@ This method should be used sparingly, as it is not very performant or easily mai ```python language = "Ukrainian" number = "nine" -word = "девять" +word = "дев'ять" sentence = word + " " + "means" + " " + number + " in " + language + "." >>> print(sentence) ... -"девять means nine in Ukrainian." +"дев'ять means nine in Ukrainian." ``` If a `list`, `tuple`, `set` or other collection of individual strings needs to be combined into a single `str`, [`.join()`][str-join], is a better option: From 869f0723275a2f7e32b89e05d9baf150f40b2275 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Mon, 10 Apr 2023 14:20:06 +0200 Subject: [PATCH 017/126] Sync sum-of-multiples docs with problem-specifications The sum-of-multiples exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2249 --- .../sum-of-multiples/.docs/instructions.md | 29 ++++++++++++------- .../sum-of-multiples/.docs/introduction.md | 6 ++++ 2 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 exercises/practice/sum-of-multiples/.docs/introduction.md diff --git a/exercises/practice/sum-of-multiples/.docs/instructions.md b/exercises/practice/sum-of-multiples/.docs/instructions.md index 7b7ec006e2c..9c824bf1d5f 100644 --- a/exercises/practice/sum-of-multiples/.docs/instructions.md +++ b/exercises/practice/sum-of-multiples/.docs/instructions.md @@ -1,18 +1,27 @@ # Instructions -Given a list of factors and a limit, add up all the unique multiples of the factors that are less than the limit. -All inputs will be greater than or equal to zero. +Your task is to write the code that calculates the energy points that get awarded to players when they complete a level. -## Example +The points awarded depend on two things: -Suppose the limit is 20 and the list of factors is [3, 5]. -We need to find the sum of all unique multiples of 3 and 5 that are less than 20. +- The level (a number) that the player completed. +- The base value of each magical item collected by the player during that level. -Multiples of 3 less than 20: 3, 6, 9, 12, 15, 18 -Multiples of 5 less than 20: 5, 10, 15 +The energy points are awarded according to the following rules: -The unique multiples are: 3, 5, 6, 9, 10, 12, 15, 18 +1. For each magical item, take the base value and find all the multiples of that value that are less than or equal to the level number. +2. Combine the sets of numbers. +3. Remove any duplicates. +4. Calculate the sum of all the numbers that are left. -The sum of the unique multiples is: 3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78 +Let's look an example: -So, the answer is 78. +**The player completed level 20 and found two magical items with base values of 3 and 5.** + +To calculate the energy points earned by the player, we need to find all the unique multiples of these base values that are less than or equal to level 20. + +- Multiples of 3 up to 20: `{3, 6, 9, 12, 15, 18}` +- Multiples of 5 up to 20: `{5, 10, 15, 20}` +- Combine the sets and remove duplicates: `{3, 5, 6, 9, 10, 12, 15, 18, 20}` +- Sum the unique multiples: `3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 + 20 = 98` +- Therefore, the player earns **98** energy points for completing level 20 and finding the two magical items with base values of 3 and 5. diff --git a/exercises/practice/sum-of-multiples/.docs/introduction.md b/exercises/practice/sum-of-multiples/.docs/introduction.md new file mode 100644 index 00000000000..69cabeed5ab --- /dev/null +++ b/exercises/practice/sum-of-multiples/.docs/introduction.md @@ -0,0 +1,6 @@ +# Introduction + +You work for a company that makes an online, fantasy-survival game. + +When a player finishes a level, they are awarded energy points. +The amount of energy awarded depends on which magical items the player found while exploring that level. From 914774cc9bc730450295c843fc9861c16f28800f Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Tue, 11 Apr 2023 20:31:05 +0200 Subject: [PATCH 018/126] sync sum of multiples docs (#3398) * Sync sum-of-multiples docs with problem-specifications The sum-of-multiples exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2249 * Sync sum-of-multiples docs with problem-specifications There were a few follow-on tweaks to sum-of-multiples. For context, this is part of the project to overhaul all the practice exercises. You can read about that here: https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 ---- If you approve this pull request, I will eventually merge it. However, if you are happy with this change **please merge the pull request**, as it will get the changes into the hands of the students much more quickly. If this pull request contradicts the exercise on your track, **please add a review with _request changes_**. This will block the pull request from getting merged. Otherwise we aim to take an optimistic merging approach. If you wish to suggest tweaks to these changes, please open a pull request to the exercism/problem-specifications repository to discuss, so that everyone who has an interest in the shared exercise descriptions can participate. * Update instructions.md Resolved merge conflicts, and am now attempting to re-push to repo. --------- Co-authored-by: BethanyG --- .../sum-of-multiples/.docs/instructions.md | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/exercises/practice/sum-of-multiples/.docs/instructions.md b/exercises/practice/sum-of-multiples/.docs/instructions.md index 9c824bf1d5f..e9a25636e51 100644 --- a/exercises/practice/sum-of-multiples/.docs/instructions.md +++ b/exercises/practice/sum-of-multiples/.docs/instructions.md @@ -7,21 +7,21 @@ The points awarded depend on two things: - The level (a number) that the player completed. - The base value of each magical item collected by the player during that level. -The energy points are awarded according to the following rules: +The energy points are awarded according to the following rules: -1. For each magical item, take the base value and find all the multiples of that value that are less than or equal to the level number. +1. For each magical item, take the base value and find all the multiples of that value that are less than the level number. 2. Combine the sets of numbers. 3. Remove any duplicates. -4. Calculate the sum of all the numbers that are left. +4. Calculate the sum of all the numbers that are left. -Let's look an example: +Let's look at an example: **The player completed level 20 and found two magical items with base values of 3 and 5.** -To calculate the energy points earned by the player, we need to find all the unique multiples of these base values that are less than or equal to level 20. +To calculate the energy points earned by the player, we need to find all the unique multiples of these base values that are less than level 20. -- Multiples of 3 up to 20: `{3, 6, 9, 12, 15, 18}` -- Multiples of 5 up to 20: `{5, 10, 15, 20}` -- Combine the sets and remove duplicates: `{3, 5, 6, 9, 10, 12, 15, 18, 20}` -- Sum the unique multiples: `3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 + 20 = 98` -- Therefore, the player earns **98** energy points for completing level 20 and finding the two magical items with base values of 3 and 5. +- Multiples of 3 less than 20: `{3, 6, 9, 12, 15, 18}` +- Multiples of 5 less than 20: `{5, 10, 15}` +- Combine the sets and remove duplicates: `{3, 5, 6, 9, 10, 12, 15, 18}` +- Sum the unique multiples: `3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78` +- Therefore, the player earns **78** energy points for completing level 20 and finding the two magical items with base values of 3 and 5 From 8ae39796b7ebefb1cbca3d26461df3367466fbdf Mon Sep 17 00:00:00 2001 From: Al Momin Faruk <31950303+mominfaruk@users.noreply.github.com> Date: Wed, 12 Apr 2023 22:44:51 +0600 Subject: [PATCH 019/126] Replace stale link by working link with valuable informtion (#3399) * Replace stale link by working link with valuable informtion * Update concepts/tuples/links.json --------- Co-authored-by: BethanyG --- concepts/tuples/links.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/concepts/tuples/links.json b/concepts/tuples/links.json index a6a22b9b8fa..a0d85de8a5a 100644 --- a/concepts/tuples/links.json +++ b/concepts/tuples/links.json @@ -16,8 +16,8 @@ "description": "Lists vs Tuples" }, { - "url": "http://e-scribe.com/post/understanding-tuples-vs-lists-in-python/", - "description": "Understanding tuples vs lists in Python" + "url": "https://stackoverflow.com/a/626871", + "description": "What's the difference between lists and tuples?" }, { "url": "https://jtauber.com/blog/2006/04/15/python_tuples_are_not_just_constant_lists/", From aecf530858499c4fbb8dcaaab24baf26e11b0cc5 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Mon, 10 Apr 2023 18:48:26 -0700 Subject: [PATCH 020/126] Synced tests.toml for depricated exercises. --- .../practice/accumulate/.meta/tests.toml | 35 ++++++++++ .../.meta/tests.toml | 62 +++++++++++++++++ exercises/practice/strain/.meta/tests.toml | 66 +++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 exercises/practice/accumulate/.meta/tests.toml create mode 100644 exercises/practice/parallel-letter-frequency/.meta/tests.toml create mode 100644 exercises/practice/strain/.meta/tests.toml diff --git a/exercises/practice/accumulate/.meta/tests.toml b/exercises/practice/accumulate/.meta/tests.toml new file mode 100644 index 00000000000..150ec2e896e --- /dev/null +++ b/exercises/practice/accumulate/.meta/tests.toml @@ -0,0 +1,35 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[64d97c14-36dd-44a8-9621-2cecebd6ed23] +description = "accumulate empty" +include = false + +[00008ed2-4651-4929-8c08-8b4dbd70872e] +description = "accumulate squares" +include = false + +[551016da-4396-4cae-b0ec-4c3a1a264125] +description = "accumulate upcases" +include = false + +[cdf95597-b6ec-4eac-a838-3480d13d0d05] +description = "accumulate reversed strings" +include = false + +[bee8e9b6-b16f-4cd2-be3b-ccf7457e50bb] +description = "accumulate recursively" +include = false + +[0b357334-4cad-49e1-a741-425202edfc7c] +description = "accumulate recursively" +include = false +reimplements = "bee8e9b6-b16f-4cd2-be3b-ccf7457e50bb" diff --git a/exercises/practice/parallel-letter-frequency/.meta/tests.toml b/exercises/practice/parallel-letter-frequency/.meta/tests.toml new file mode 100644 index 00000000000..6cf36e6fd2d --- /dev/null +++ b/exercises/practice/parallel-letter-frequency/.meta/tests.toml @@ -0,0 +1,62 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[c054d642-c1fa-4234-8007-9339f2337886] +description = "no texts" +include = false + +[818031be-49dc-4675-b2f9-c4047f638a2a] +description = "one text with one letter" +include = false + +[c0b81d1b-940d-4cea-9f49-8445c69c17ae] +description = "one text with multiple letters" +include = false + +[708ff1e0-f14a-43fd-adb5-e76750dcf108] +description = "two texts with one letter" +include = false + +[1b5c28bb-4619-4c9d-8db9-a4bb9c3bdca0] +description = "two texts with multiple letters" +include = false + +[6366e2b8-b84c-4334-a047-03a00a656d63] +description = "ignore letter casing" +include = false + +[92ebcbb0-9181-4421-a784-f6f5aa79f75b] +description = "ignore whitespace" +include = false + +[bc5f4203-00ce-4acc-a5fa-f7b865376fd9] +description = "ignore punctuation" +include = false + +[68032b8b-346b-4389-a380-e397618f6831] +description = "ignore numbers" +include = false + +[aa9f97ac-3961-4af1-88e7-6efed1bfddfd] +description = "Unicode letters" +include = false + +[7b1da046-701b-41fc-813e-dcfb5ee51813] +description = "combination of lower- and uppercase letters, punctuation and white space" +include = false + +[4727f020-df62-4dcf-99b2-a6e58319cb4f] +description = "large texts" +include = false + +[adf8e57b-8e54-4483-b6b8-8b32c115884c] +description = "many small texts" +include = false diff --git a/exercises/practice/strain/.meta/tests.toml b/exercises/practice/strain/.meta/tests.toml new file mode 100644 index 00000000000..66ed1044bd6 --- /dev/null +++ b/exercises/practice/strain/.meta/tests.toml @@ -0,0 +1,66 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[26af8c32-ba6a-4eb3-aa0a-ebd8f136e003] +description = "keep on empty list returns empty list" +include = false + +[f535cb4d-e99b-472a-bd52-9fa0ffccf454] +description = "keeps everything" +include = false + +[950b8e8e-f628-42a8-85e2-9b30f09cde38] +description = "keeps nothing" +include = false + +[92694259-6e76-470c-af87-156bdf75018a] +description = "keeps first and last" +include = false + +[938f7867-bfc7-449e-a21b-7b00cbb56994] +description = "keeps neither first nor last" +include = false + +[8908e351-4437-4d2b-a0f7-770811e48816] +description = "keeps strings" +include = false + +[2728036b-102a-4f1e-a3ef-eac6160d876a] +description = "keeps lists" +include = false + +[ef16beb9-8d84-451a-996a-14e80607fce6] +description = "discard on empty list returns empty list" +include = false + +[2f42f9bc-8e06-4afe-a222-051b5d8cd12a] +description = "discards everything" +include = false + +[ca990fdd-08c2-4f95-aa50-e0f5e1d6802b] +description = "discards nothing" +include = false + +[71595dae-d283-48ca-a52b-45fa96819d2f] +description = "discards first and last" +include = false + +[ae141f79-f86d-4567-b407-919eaca0f3dd] +description = "discards neither first nor last" +include = false + +[daf25b36-a59f-4f29-bcfe-302eb4e43609] +description = "discards strings" +include = false + +[a38d03f9-95ad-4459-80d1-48e937e4acaf] +description = "discards lists" +include = false From 218d2ba1cccab27cb64ccc8268e4ea88e938ae3f Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Wed, 12 Apr 2023 12:26:02 +0200 Subject: [PATCH 021/126] Sync rna-transcription docs with problem-specifications The rna-transcription exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2251 --- .../rna-transcription/.docs/instructions.md | 6 +++++- .../rna-transcription/.docs/introduction.md | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 exercises/practice/rna-transcription/.docs/introduction.md diff --git a/exercises/practice/rna-transcription/.docs/instructions.md b/exercises/practice/rna-transcription/.docs/instructions.md index 851bdb49db7..36da381f5a7 100644 --- a/exercises/practice/rna-transcription/.docs/instructions.md +++ b/exercises/practice/rna-transcription/.docs/instructions.md @@ -1,6 +1,6 @@ # Instructions -Given a DNA strand, return its RNA complement (per RNA transcription). +Your task is determine the RNA complement of a given DNA sequence. Both DNA and RNA strands are a sequence of nucleotides. @@ -14,3 +14,7 @@ Given a DNA strand, its transcribed RNA strand is formed by replacing each nucle - `C` -> `G` - `T` -> `A` - `A` -> `U` + +~~~~exercism/note +If you want to look at how the inputs and outputs are structured, take a look at the examples in the test suite. +~~~~ diff --git a/exercises/practice/rna-transcription/.docs/introduction.md b/exercises/practice/rna-transcription/.docs/introduction.md new file mode 100644 index 00000000000..6b3f44b532d --- /dev/null +++ b/exercises/practice/rna-transcription/.docs/introduction.md @@ -0,0 +1,16 @@ +# Introduction + +You work for a bioengineering company that specializes in developing therapeutic solutions. + +Your team has just been given a new project to develop a targeted therapy for a rare type of cancer. + +~~~~exercism/note +It's all very complicated, but the basic idea is that sometimes people's bodies produce too much of a given protein. +That can cause all sorts of havoc. + +But if you can create a very specific molecule (called a micro-RNA), it can prevent the protein from being produced. + +This technique is called [RNA Interference][rnai]. + +[rnai]: https://admin.acceleratingscience.com/ask-a-scientist/what-is-rnai/ +~~~~ From 196cfa37ea729ca5306d494767def568e5bc09e6 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Wed, 12 Apr 2023 11:29:02 +0200 Subject: [PATCH 022/126] Sync largest-series-product docs with problem-specifications The largest-series-product exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 - https://github.com/exercism/problem-specifications/pull/2246 --- .../.docs/instructions.md | 28 +++++++++++++------ .../.docs/introduction.md | 5 ++++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 exercises/practice/largest-series-product/.docs/introduction.md diff --git a/exercises/practice/largest-series-product/.docs/instructions.md b/exercises/practice/largest-series-product/.docs/instructions.md index 08586dd5933..f297b57f7c4 100644 --- a/exercises/practice/largest-series-product/.docs/instructions.md +++ b/exercises/practice/largest-series-product/.docs/instructions.md @@ -1,14 +1,26 @@ # Instructions -Given a string of digits, calculate the largest product for a contiguous substring of digits of length n. +Your task is to look for patterns in the long sequence of digits in the encrypted signal. -For example, for the input `'1027839564'`, the largest product for a series of 3 digits is 270 `(9 * 5 * 6)`, and the largest product for a series of 5 digits is 7560 `(7 * 8 * 3 * 9 * 5)`. +The technique you're going to use here is called the largest series product. -Note that these series are only required to occupy *adjacent positions* in the input; the digits need not be *numerically consecutive*. +Let's define a few terms, first. -For the input `'73167176531330624919225119674426574742355349194934'`, -the largest product for a series of 6 digits is 23520. +- **input**: the sequence of digits that you need to analyze +- **series**: a sequence of adjacent digits (those that are next to each other) that is contained within the input +- **span**: how many digits long each series is +- **product**: what you get when you multiply numbers together -For a series of zero digits, the largest product is 1 because 1 is the multiplicative identity. -(You don't need to know what a multiplicative identity is to solve this problem; -it just means that multiplying a number by 1 gives you the same number.) +Let's work through an example, with the input `"63915"`. + +- To form a series, take adjacent digits in the original input. +- If you are working with a span of `3`, there will be three possible series: + - `"639"` + - `"391"` + - `"915"` +- Then we need to calculate the product of each series: + - The product of the series `"639"` is 162 (`6 × 3 × 9 = 162`) + - The product of the series `"391"` is 27 (`3 × 9 × 1 = 27`) + - The product of the series `"915"` is 45 (`9 × 1 × 5 = 45`) +- 162 is bigger than both 27 and 45, so the largest series product of `"63915"` is from the series `"639"`. + So the answer is **162**. diff --git a/exercises/practice/largest-series-product/.docs/introduction.md b/exercises/practice/largest-series-product/.docs/introduction.md new file mode 100644 index 00000000000..597bb5fa15d --- /dev/null +++ b/exercises/practice/largest-series-product/.docs/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +You work for a government agency that has intercepted a series of encrypted communication signals from a group of bank robbers. +The signals contain a long sequence of digits. +Your team needs to use various digital signal processing techniques to analyze the signals and identify any patterns that may indicate the planning of a heist. From 478b3b3fbecbfa4a6fefa34bba2e03e191e9bfb7 Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Wed, 12 Apr 2023 11:29:18 +0200 Subject: [PATCH 023/126] Delete test cases from largest-series-product This deletes two deprecated test cases so that we can dramatically simplify the instructions for this exercise. --- exercises/practice/largest-series-product/.meta/tests.toml | 2 ++ .../largest-series-product/largest_series_product_test.py | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/exercises/practice/largest-series-product/.meta/tests.toml b/exercises/practice/largest-series-product/.meta/tests.toml index 6c111adf0f1..88316925977 100644 --- a/exercises/practice/largest-series-product/.meta/tests.toml +++ b/exercises/practice/largest-series-product/.meta/tests.toml @@ -41,9 +41,11 @@ description = "rejects span longer than string length" [06bc8b90-0c51-4c54-ac22-3ec3893a079e] description = "reports 1 for empty string and empty product (0 span)" +include = false [3ec0d92e-f2e2-4090-a380-70afee02f4c0] description = "reports 1 for nonempty string and empty product (0 span)" +include = false [6d96c691-4374-4404-80ee-2ea8f3613dd4] description = "rejects empty string and nonzero span" diff --git a/exercises/practice/largest-series-product/largest_series_product_test.py b/exercises/practice/largest-series-product/largest_series_product_test.py index 0a67d4ca14e..ba8ae10dc8e 100644 --- a/exercises/practice/largest-series-product/largest_series_product_test.py +++ b/exercises/practice/largest-series-product/largest_series_product_test.py @@ -46,12 +46,6 @@ def test_rejects_span_longer_than_string_length(self): err.exception.args[0], "span must be smaller than string length" ) - def test_reports_1_for_empty_string_and_empty_product_0_span(self): - self.assertEqual(largest_product("", 0), 1) - - def test_reports_1_for_nonempty_string_and_empty_product_0_span(self): - self.assertEqual(largest_product("123", 0), 1) - def test_rejects_empty_string_and_nonzero_span(self): with self.assertRaises(ValueError) as err: largest_product("", 1) From 17d4f7b5ea7b5e984fd9b419913d44c28c02e82a Mon Sep 17 00:00:00 2001 From: Matthijs <19817960+MatthijsBlom@users.noreply.github.com> Date: Thu, 6 Apr 2023 20:18:26 +0200 Subject: [PATCH 024/126] Synchronize example code with tests --- .../largest-series-product/.docs/instructions.append.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/largest-series-product/.docs/instructions.append.md b/exercises/practice/largest-series-product/.docs/instructions.append.md index 9250db2e8ca..5a0f9b92064 100644 --- a/exercises/practice/largest-series-product/.docs/instructions.append.md +++ b/exercises/practice/largest-series-product/.docs/instructions.append.md @@ -12,8 +12,8 @@ To raise a `ValueError` with a message, write the message as an argument to the # span of numbers is longer than number series raise ValueError("span must be smaller than string length") -# span of number is zero or negative -raise ValueError("span must be greater than zero") +# span of number is negative +raise ValueError("span must not be negative") # series includes non-number input raise ValueError("digits input must only contain digits") From f333803a543ceb89a01239a0bbad1bae865dc73b Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Thu, 13 Apr 2023 12:50:41 +0200 Subject: [PATCH 025/126] Sync saddle-points docs with problem-specifications The saddle-points exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 --- .../saddle-points/.docs/instructions.md | 31 +++++++++---------- .../saddle-points/.docs/introduction.md | 9 ++++++ 2 files changed, 24 insertions(+), 16 deletions(-) create mode 100644 exercises/practice/saddle-points/.docs/introduction.md diff --git a/exercises/practice/saddle-points/.docs/instructions.md b/exercises/practice/saddle-points/.docs/instructions.md index 920ecffed98..d861388e437 100644 --- a/exercises/practice/saddle-points/.docs/instructions.md +++ b/exercises/practice/saddle-points/.docs/instructions.md @@ -1,25 +1,24 @@ # Instructions -Detect saddle points in a matrix. +Your task is to find the potential trees where you could build your tree house. -So say you have a matrix like so: +The data company provides the data as grids that show the heights of the trees. +The rows of the grid represent the east-west direction, and the columns represent the north-south direction. -```text - 1 2 3 - |--------- -1 | 9 8 7 -2 | 5 3 2 <--- saddle point at row 2, column 1, with value 5 -3 | 6 6 7 -``` +An acceptable tree will be the the largest in its row, while being the smallest in its column. -It has a saddle point at row 2, column 1. +A grid might not have any good trees at all. +Or it might have one, or even several. -It's called a "saddle point" because it is greater than or equal to every element in its row and less than or equal to every element in its column. +Here is a grid that has exactly one candidate tree. -A matrix may have zero or more saddle points. + 1 2 3 4 + |----------- +1 | 9 8 7 8 +2 | 5 3 2 4 <--- potential tree house at row 2, column 1, for tree with height 5 +3 | 6 6 7 1 -Your code should be able to provide the (possibly empty) list of all the saddle points for any given matrix. +- Row 2 has values 5, 3, and 1. The largest value is 5. +- Column 1 has values 9, 5, and 6. The smallest value is 5. -The matrix can have a different number of rows and columns (Non square). - -Note that you may find other definitions of matrix saddle points online, but the tests for this exercise follow the above unambiguous definition. +So the point at `[2, 1]` (row: 2, column: 1) is a great spot for a tree house. diff --git a/exercises/practice/saddle-points/.docs/introduction.md b/exercises/practice/saddle-points/.docs/introduction.md new file mode 100644 index 00000000000..b582efbd21d --- /dev/null +++ b/exercises/practice/saddle-points/.docs/introduction.md @@ -0,0 +1,9 @@ +# Introduction + +You are planning on building a tree house in the woods near your house so that you can watch the sun rise and set. + +You've obtained data from a local survey company that shows the heights of all the trees in each rectangular section of the map. +You need to analyze each grid on the map to find the perfect tree for your tree house. + +The best tree will be the tallest tree compared to all the other trees to the east and west, so that you have the best possible view of the sunrises and sunsets. +You don't like climbing too much, so the perfect tree will also be the shortest among all the trees to the north and to the south. From c652ff3089fc253f62ed2b76a68f55a0937766a6 Mon Sep 17 00:00:00 2001 From: Meatball Date: Mon, 19 Dec 2022 09:27:16 +0100 Subject: [PATCH 026/126] Updated bank account --- bin/githelp.py | 2 +- .../practice/bank-account/.meta/template.j2 | 47 +++ .../practice/bank-account/.meta/tests.toml | 43 +++ .../bank-account/bank_account_test.py | 89 ++---- .../practice/bank-account/canonical_data.json | 285 ++++++++++++++++++ 5 files changed, 397 insertions(+), 69 deletions(-) create mode 100644 exercises/practice/bank-account/.meta/template.j2 create mode 100644 exercises/practice/bank-account/.meta/tests.toml create mode 100644 exercises/practice/bank-account/canonical_data.json diff --git a/bin/githelp.py b/bin/githelp.py index 3d3be06f664..9710e0c1361 100644 --- a/bin/githelp.py +++ b/bin/githelp.py @@ -6,7 +6,7 @@ from typing import Iterator, Union -GITHUB_EXERCISM = f"https://github.com/exercism" +GITHUB_EXERCISM = f"https://github.com/meatball133" class Repo(Enum): diff --git a/exercises/practice/bank-account/.meta/template.j2 b/exercises/practice/bank-account/.meta/template.j2 new file mode 100644 index 00000000000..99c21bc8f6a --- /dev/null +++ b/exercises/practice/bank-account/.meta/template.j2 @@ -0,0 +1,47 @@ +{%- import "generator_macros.j2" as macros with context -%} +{% macro test_case(case) -%} + def test_{{ case["description"] | to_snake }}(self): + account = BankAccount() + {%- set inputs = case["input"]["operations"] -%} + {%- if case["expected"] -%} + {%- set error_case = true -%} + {%- set error_msg = case["expected"]["error"] -%} + {%- set error_operation = inputs[-1]["operation"] -%} + {%- set final_value = inputs[-1]["value"] -%} + {% endif %} + {%- if case["expected"] and inputs|length > 1 -%} + {%- set inputs = inputs[:-1] -%} + {%- endif -%} + {%- for input in inputs -%} + {%- set operation = input["operation"] -%} + {%- set value = input["value"] -%} + {%- set expected = input["expected"] %} + {%- if operation and value %} + account.{{ operation }}({{ value }}) + {%- elif operation == "amount" %} + self.assertEqual(account.get_balance(), {{ expected }}) + {%- elif operation and not value %} + account.{{ operation }}() + {%- endif %} + {%- endfor %} + {%- if error_case %} + with self.assertRaises(ValueError) as err: + account.{{ error_operation }}({{ final_value if final_value else "" }}) + self.assertEqual(type(err.exception), ValueError) + self.assertEqual(err.exception.args[0], "{{ error_msg }}") + {%- endif %} +{% endmacro %} + +{{ macros.header(["BankAccount"]) }} + +class {{ exercise | camel_case }}Test(unittest.TestCase): + {% for case in cases -%} + {{ test_case(case) }} + {% endfor %} + {% if additional_cases | length -%} + + # Additional tests for this track + {% for case in additional_cases -%} + {{ test_case(case) }} + {% endfor %} + {%- endif %} diff --git a/exercises/practice/bank-account/.meta/tests.toml b/exercises/practice/bank-account/.meta/tests.toml new file mode 100644 index 00000000000..6778e39f458 --- /dev/null +++ b/exercises/practice/bank-account/.meta/tests.toml @@ -0,0 +1,43 @@ +# This is an auto-generated file. Regular comments will be removed when this +# file is regenerated. Regenerating will not touch any manually added keys, +# so comments can be added in a "comment" key. + +[983a1528-4ceb-45e5-8257-8ce01aceb5ed] +description = "encode yes" + +[e88d4ec3-c6bf-4752-8e59-5046c44e3ba7] +description = "encode no" + +[08f1af07-27ae-4b38-aa19-770bde558064] +description = "encode OMG" + +[6f6d242f-8c31-4ac6-8995-a90d42cad59f] +description = "encode spaces" + +[f9facfaa-d824-486e-8381-48832c4bbffd] +description = "encode mindblowingly" + +[7a65ba52-e35c-4fd2-8159-bda2bde6e59c] +description = "encode numbers" + +[570dfaa5-0532-4c1f-a7d3-0f65c3265608] +description = "encode deep thought" + +[c396d233-1c49-4272-98dc-7f502dbb9470] +description = "encode all the letters" + +[c06f534f-bdc2-4a02-a388-1063400684de] +description = "decode exercism" + +[0722d404-6116-4f92-ba3b-da7f88f1669c] +description = "decode a sentence" + +[ec42245f-9361-4341-8231-a22e8d19c52f] +description = "decode numbers" + +[4f381ef8-10ef-4507-8e1d-0631ecc8ee72] +description = "decode all the letters" + +[d45df9ea-1db0-47f3-b18c-d365db49d938] +description = "decode with too many spaces" + diff --git a/exercises/practice/bank-account/bank_account_test.py b/exercises/practice/bank-account/bank_account_test.py index 3a36b3ccb42..5a50505010a 100644 --- a/exercises/practice/bank-account/bank_account_test.py +++ b/exercises/practice/bank-account/bank_account_test.py @@ -1,87 +1,75 @@ -import sys -import threading -import time import unittest -from bank_account import BankAccount +from bank_account import ( + BankAccount, +) + +# Tests adapted from `problem-specifications//canonical-data.json` class BankAccountTest(unittest.TestCase): - def test_newly_opened_account_has_zero_balance(self): + def test_using_pop_raises_an_error_if_the_list_is_empty(self): account = BankAccount() account.open() self.assertEqual(account.get_balance(), 0) - def test_can_deposit_money(self): + def test_can_return_with_pop_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.deposit(100) self.assertEqual(account.get_balance(), 100) - def test_can_deposit_money_sequentially(self): - account = BankAccount() - account.open() - account.deposit(100) - account.deposit(50) - - self.assertEqual(account.get_balance(), 150) - - def test_can_withdraw_money(self): + def test_using_shift_raises_an_error_if_the_list_is_empty(self): account = BankAccount() account.open() account.deposit(100) account.withdraw(50) - self.assertEqual(account.get_balance(), 50) - def test_can_withdraw_money_sequentially(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.deposit(100) - account.withdraw(20) account.withdraw(80) - + account.withdraw(20) self.assertEqual(account.get_balance(), 0) - def test_checking_balance_of_closed_account_throws_error(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.close() - with self.assertRaises(ValueError) as err: - account.get_balance() + account.amount() self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_deposit_into_closed_account(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.close() - with self.assertRaises(ValueError) as err: account.deposit(50) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - - def test_withdraw_from_closed_account(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.close() - with self.assertRaises(ValueError) as err: account.withdraw(50) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_close_already_closed_account(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() + account.close() with self.assertRaises(ValueError) as err: account.close() self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_open_already_opened_account(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() with self.assertRaises(ValueError) as err: @@ -89,7 +77,7 @@ def test_open_already_opened_account(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account already open") - def test_reopened_account_does_not_retain_balance(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.deposit(50) @@ -97,63 +85,28 @@ def test_reopened_account_does_not_retain_balance(self): account.open() self.assertEqual(account.get_balance(), 0) - def test_cannot_withdraw_more_than_deposited(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.deposit(25) - with self.assertRaises(ValueError) as err: account.withdraw(50) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "amount must be less than balance") - def test_cannot_withdraw_negative(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() account.deposit(100) - with self.assertRaises(ValueError) as err: account.withdraw(-50) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "amount must be greater than 0") - def test_cannot_deposit_negative(self): + def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account = BankAccount() account.open() - with self.assertRaises(ValueError) as err: account.deposit(-50) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "amount must be greater than 0") - - def test_can_handle_concurrent_transactions(self): - account = BankAccount() - account.open() - account.deposit(1000) - - self.adjust_balance_concurrently(account) - - self.assertEqual(account.get_balance(), 1000) - - def adjust_balance_concurrently(self, account): - def transact(): - account.deposit(5) - time.sleep(0.001) - account.withdraw(5) - - # Greatly improve the chance of an operation being interrupted - # by thread switch, thus testing synchronization effectively - try: - sys.setswitchinterval(1e-12) - except AttributeError: - # For Python 2 compatibility - sys.setcheckinterval(1) - - threads = [threading.Thread(target=transact) for _ in range(1000)] - for thread in threads: - thread.start() - for thread in threads: - thread.join() - -if __name__ == '__main__': - unittest.main() diff --git a/exercises/practice/bank-account/canonical_data.json b/exercises/practice/bank-account/canonical_data.json new file mode 100644 index 00000000000..21e868eac9d --- /dev/null +++ b/exercises/practice/bank-account/canonical_data.json @@ -0,0 +1,285 @@ +{ + "exercise": "bank-account", + "comments": [ + "In order to keep the interface for the exercise close or equal to the ", + "description.md and also satisfying the canonical-data schema, the only ", + "properties are pop, push, shift, unshift. Some tracks also implement ", + "delete and count, via Track-Inserted hints. ", + " ", + "It is hard to have interesting tests using the property based approach so", + "this canonical data uses the following approach: ", + "- Each test input is an array of { operation, value?, expected? } ", + "- If operation is push, unshift, delete, then value is given ", + "- If operation is pop, shift, count, the expected value can be given ", + " ", + "Encoding tests and operations using the same field is necessary to have ", + "tests that don't just initialize the list, and then have one operation. " + ], + "cases": [ + { + "uuid": "983a1528-4ceb-45e5-8257-8ce01aceb5ed", + "description": "Using pop raises an error if the list is empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "amount", + "value": 0 + } + ] + }, "expected": {} + }, + { + "uuid": "e88d4ec3-c6bf-4752-8e59-5046c44e3ba7", + "description" : "Can return with pop and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": 100 + }, + { + "operation": "amount", + "expected": 100 + } + ] + }, + "expected": {} + }, + { + "uuid": "08f1af07-27ae-4b38-aa19-770bde558064", + "description": "Using shift raises an error if the list is empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": 100 + }, + { + "operation": "withdraw", + "value": 50 + }, + { + "operation": "amount", + "value": 50 + } + ] + }, + "expected": {} + }, + { + "uuid": "6f6d242f-8c31-4ac6-8995-a90d42cad59f", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": 100 + }, + { + "operation": "withdraw", + "value": 80 + }, + { + "operation": "withdraw", + "value": 20 + }, + { + "operation": "amount", + "value": 0 + } + ] + }, + "expected": {} + }, + { + "uuid": "f9facfaa-d824-486e-8381-48832c4bbffd", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "close" + }, + { + "operation": "amount" + } + ] + }, + "expected": {"error": "account not open"} + }, + { + "uuid": "7a65ba52-e35c-4fd2-8159-bda2bde6e59c", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "close" + }, + { + "operation": "deposit", + "value": 50 + } + ] + }, + "expected": {"error": "account not open"} + }, + { + "uuid": "570dfaa5-0532-4c1f-a7d3-0f65c3265608", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "close" + }, + { + "operation": "withdraw", + "value": 50 + } + ] + }, + "expected": {"error": "account not open"} + }, + { + "uuid": "c396d233-1c49-4272-98dc-7f502dbb9470", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "close" + } + ] + }, + "expected": {"error": "account not open"} + }, + { + "uuid": "c06f534f-bdc2-4a02-a388-1063400684de", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "open" + } + ] + }, + "expected": {"error": "account already open"} + }, + { + "uuid": "0722d404-6116-4f92-ba3b-da7f88f1669c", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": 50 + }, + { + "operation": "close" + }, + { + "operation": "open" + }, + { + "operation": "amount", + "value": 0 + } + ] + }, + "expected": {} + }, + { + "uuid": "ec42245f-9361-4341-8231-a22e8d19c52f", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": 25 + }, + { + "operation": "withdraw", + "value": 50 + } + ] + }, + "expected": {"error": "amount must be less than balance"} + }, + { + "uuid": "4f381ef8-10ef-4507-8e1d-0631ecc8ee72", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": 100 + }, + { + "operation": "withdraw", + "value": -50 + } + ] + }, + "expected": {"error": "amount must be greater than 0"} + }, + { + "uuid": "d45df9ea-1db0-47f3-b18c-d365db49d938", + "description": "Can return with shift and then raise an error if empty", + "property": "bankAccont", + "input": { + "operations": [ + { + "operation": "open" + }, + { + "operation": "deposit", + "value": -50 + } + ] + }, + "expected": {"error": "amount must be greater than 0"} + } +] +} \ No newline at end of file From 9bf39ef617a1960b393643bbe5cfc8933c56573e Mon Sep 17 00:00:00 2001 From: Meatball Date: Mon, 19 Dec 2022 09:38:24 +0100 Subject: [PATCH 027/126] fix --- exercises/practice/bank-account/.meta/template.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/exercises/practice/bank-account/.meta/template.j2 b/exercises/practice/bank-account/.meta/template.j2 index 99c21bc8f6a..3e2980484b6 100644 --- a/exercises/practice/bank-account/.meta/template.j2 +++ b/exercises/practice/bank-account/.meta/template.j2 @@ -11,6 +11,8 @@ {% endif %} {%- if case["expected"] and inputs|length > 1 -%} {%- set inputs = inputs[:-1] -%} + {%- elif case["expected"] -%} + {%- set inputs = [] -%} {%- endif -%} {%- for input in inputs -%} {%- set operation = input["operation"] -%} From f95892f4be9b5c896901571befd4bb26ca0b4f32 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Apr 2023 19:07:29 -0700 Subject: [PATCH 028/126] Re-worked PR for Newly Accepted Canonical Data - Removed and regenerated `tests.toml` - Removed and regenerated `bank_account_test.py` - Re-worked the JinJa2 template - Removed the custom `canonical_data.json` -Removed the `bin/githelp.py` workaround - Updated `example.py` - Added meatball and bethanyg as contributors --- bin/githelp.py | 2 +- .../practice/bank-account/.meta/config.json | 4 +- .../practice/bank-account/.meta/example.py | 2 +- .../practice/bank-account/.meta/template.j2 | 42 +-- .../practice/bank-account/.meta/tests.toml | 51 +++- .../bank-account/bank_account_test.py | 57 ++-- .../practice/bank-account/canonical_data.json | 285 ------------------ 7 files changed, 102 insertions(+), 341 deletions(-) delete mode 100644 exercises/practice/bank-account/canonical_data.json diff --git a/bin/githelp.py b/bin/githelp.py index 9710e0c1361..3d3be06f664 100644 --- a/bin/githelp.py +++ b/bin/githelp.py @@ -6,7 +6,7 @@ from typing import Iterator, Union -GITHUB_EXERCISM = f"https://github.com/meatball133" +GITHUB_EXERCISM = f"https://github.com/exercism" class Repo(Enum): diff --git a/exercises/practice/bank-account/.meta/config.json b/exercises/practice/bank-account/.meta/config.json index 8ab9aa0d888..51483ecb667 100644 --- a/exercises/practice/bank-account/.meta/config.json +++ b/exercises/practice/bank-account/.meta/config.json @@ -3,7 +3,9 @@ "contributors": [ "cmccandless", "Dog", - "tqa236" + "tqa236", + "bethanyg", + "meatball133" ], "files": { "solution": [ diff --git a/exercises/practice/bank-account/.meta/example.py b/exercises/practice/bank-account/.meta/example.py index 21248fa9257..90ddf31c23b 100644 --- a/exercises/practice/bank-account/.meta/example.py +++ b/exercises/practice/bank-account/.meta/example.py @@ -4,7 +4,7 @@ class BankAccount: def __init__(self): self.is_open = False - self.balance = 0 + self.balance = None self.lock = threading.Lock() def get_balance(self): diff --git a/exercises/practice/bank-account/.meta/template.j2 b/exercises/practice/bank-account/.meta/template.j2 index 3e2980484b6..f077837a0fd 100644 --- a/exercises/practice/bank-account/.meta/template.j2 +++ b/exercises/practice/bank-account/.meta/template.j2 @@ -3,47 +3,49 @@ def test_{{ case["description"] | to_snake }}(self): account = BankAccount() {%- set inputs = case["input"]["operations"] -%} - {%- if case["expected"] -%} + {%- if case["expected"]["error"] -%} {%- set error_case = true -%} {%- set error_msg = case["expected"]["error"] -%} {%- set error_operation = inputs[-1]["operation"] -%} - {%- set final_value = inputs[-1]["value"] -%} - {% endif %} - {%- if case["expected"] and inputs|length > 1 -%} + {%- set final_value = inputs[-1]["amount"] -%} {%- set inputs = inputs[:-1] -%} - {%- elif case["expected"] -%} - {%- set inputs = [] -%} - {%- endif -%} + {% endif %} {%- for input in inputs -%} {%- set operation = input["operation"] -%} - {%- set value = input["value"] -%} - {%- set expected = input["expected"] %} + {%- set value = input["amount"] -%} + {%- set expected = case["expected"] %} {%- if operation and value %} account.{{ operation }}({{ value }}) - {%- elif operation == "amount" %} + {%- elif not value and operation %} + {%- if not error_case and operation == "balance" %} self.assertEqual(account.get_balance(), {{ expected }}) - {%- elif operation and not value %} + {%- else %} account.{{ operation }}() - {%- endif %} - {%- endfor %} - {%- if error_case %} + {%- endif %} + {%- endif %} + {%- endfor %} + {%- if error_case %} with self.assertRaises(ValueError) as err: + {%- if error_operation == "balance" %} + account.get_balance({{ final_value if final_value else "" }}) + {%- else %} account.{{ error_operation }}({{ final_value if final_value else "" }}) + {%- endif %} self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "{{ error_msg }}") - {%- endif %} + {%- endif %} {% endmacro %} {{ macros.header(["BankAccount"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} - {{ test_case(case) }} + {{ test_case(case) }} {% endfor %} {% if additional_cases | length -%} - # Additional tests for this track - {% for case in additional_cases -%} - {{ test_case(case) }} - {% endfor %} + # Additional tests for this track + {% for case in additional_cases -%} + {{ test_case(case) }} + {% endfor %} {%- endif %} diff --git a/exercises/practice/bank-account/.meta/tests.toml b/exercises/practice/bank-account/.meta/tests.toml index 6778e39f458..1704a08c5ad 100644 --- a/exercises/practice/bank-account/.meta/tests.toml +++ b/exercises/practice/bank-account/.meta/tests.toml @@ -1,43 +1,62 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. [983a1528-4ceb-45e5-8257-8ce01aceb5ed] -description = "encode yes" +description = "Newly opened account has zero balance" [e88d4ec3-c6bf-4752-8e59-5046c44e3ba7] -description = "encode no" +description = "Single deposit" + +[3d9147d4-63f4-4844-8d2b-1fee2e9a2a0d] +description = "Multiple deposits" [08f1af07-27ae-4b38-aa19-770bde558064] -description = "encode OMG" +description = "Withdraw once" [6f6d242f-8c31-4ac6-8995-a90d42cad59f] -description = "encode spaces" +description = "Withdraw twice" + +[45161c94-a094-4c77-9cec-998b70429bda] +description = "Can do multiple operations sequentially" [f9facfaa-d824-486e-8381-48832c4bbffd] -description = "encode mindblowingly" +description = "Cannot check balance of closed account" [7a65ba52-e35c-4fd2-8159-bda2bde6e59c] -description = "encode numbers" +description = "Cannot deposit into closed account" + +[a0a1835d-faae-4ad4-a6f3-1fcc2121380b] +description = "Cannot deposit into unopened account" [570dfaa5-0532-4c1f-a7d3-0f65c3265608] -description = "encode deep thought" +description = "Cannot withdraw from closed account" [c396d233-1c49-4272-98dc-7f502dbb9470] -description = "encode all the letters" +description = "Cannot close an account that was not opened" [c06f534f-bdc2-4a02-a388-1063400684de] -description = "decode exercism" +description = "Cannot open an already opened account" [0722d404-6116-4f92-ba3b-da7f88f1669c] -description = "decode a sentence" +description = "Reopened account does not retain balance" [ec42245f-9361-4341-8231-a22e8d19c52f] -description = "decode numbers" +description = "Cannot withdraw more than deposited" [4f381ef8-10ef-4507-8e1d-0631ecc8ee72] -description = "decode all the letters" +description = "Cannot withdraw negative" [d45df9ea-1db0-47f3-b18c-d365db49d938] -description = "decode with too many spaces" +description = "Cannot deposit negative" +[ba0c1e0b-0f00-416f-8097-a7dfc97871ff] +description = "Can handle concurrent transactions" +include = false diff --git a/exercises/practice/bank-account/bank_account_test.py b/exercises/practice/bank-account/bank_account_test.py index 5a50505010a..76ddbfe404a 100644 --- a/exercises/practice/bank-account/bank_account_test.py +++ b/exercises/practice/bank-account/bank_account_test.py @@ -8,25 +8,32 @@ class BankAccountTest(unittest.TestCase): - def test_using_pop_raises_an_error_if_the_list_is_empty(self): + def test_newly_opened_account_has_zero_balance(self): account = BankAccount() account.open() self.assertEqual(account.get_balance(), 0) - def test_can_return_with_pop_and_then_raise_an_error_if_empty(self): + def test_single_deposit(self): account = BankAccount() account.open() account.deposit(100) self.assertEqual(account.get_balance(), 100) - def test_using_shift_raises_an_error_if_the_list_is_empty(self): + def test_multiple_deposits(self): account = BankAccount() account.open() account.deposit(100) - account.withdraw(50) - self.assertEqual(account.get_balance(), 50) + account.deposit(50) + self.assertEqual(account.get_balance(), 150) - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_withdraw_once(self): + account = BankAccount() + account.open() + account.deposit(100) + account.withdraw(75) + self.assertEqual(account.get_balance(), 25) + + def test_withdraw_twice(self): account = BankAccount() account.open() account.deposit(100) @@ -34,16 +41,26 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account.withdraw(20) self.assertEqual(account.get_balance(), 0) - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_can_do_multiple_operations_sequentially(self): + account = BankAccount() + account.open() + account.deposit(100) + account.deposit(110) + account.withdraw(200) + account.deposit(60) + account.withdraw(50) + self.assertEqual(account.get_balance(), 20) + + def test_cannot_check_balance_of_closed_account(self): account = BankAccount() account.open() account.close() with self.assertRaises(ValueError) as err: - account.amount() + account.get_balance() self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_deposit_into_closed_account(self): account = BankAccount() account.open() account.close() @@ -52,7 +69,14 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_deposit_into_unopened_account(self): + account = BankAccount() + with self.assertRaises(ValueError) as err: + account.deposit(50) + self.assertEqual(type(err.exception), ValueError) + self.assertEqual(err.exception.args[0], "account not open") + + def test_cannot_withdraw_from_closed_account(self): account = BankAccount() account.open() account.close() @@ -61,15 +85,14 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_close_an_account_that_was_not_opened(self): account = BankAccount() - account.close() with self.assertRaises(ValueError) as err: account.close() self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account not open") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_open_an_already_opened_account(self): account = BankAccount() account.open() with self.assertRaises(ValueError) as err: @@ -77,7 +100,7 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "account already open") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_reopened_account_does_not_retain_balance(self): account = BankAccount() account.open() account.deposit(50) @@ -85,7 +108,7 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): account.open() self.assertEqual(account.get_balance(), 0) - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_withdraw_more_than_deposited(self): account = BankAccount() account.open() account.deposit(25) @@ -94,7 +117,7 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "amount must be less than balance") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_withdraw_negative(self): account = BankAccount() account.open() account.deposit(100) @@ -103,7 +126,7 @@ def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "amount must be greater than 0") - def test_can_return_with_shift_and_then_raise_an_error_if_empty(self): + def test_cannot_deposit_negative(self): account = BankAccount() account.open() with self.assertRaises(ValueError) as err: diff --git a/exercises/practice/bank-account/canonical_data.json b/exercises/practice/bank-account/canonical_data.json deleted file mode 100644 index 21e868eac9d..00000000000 --- a/exercises/practice/bank-account/canonical_data.json +++ /dev/null @@ -1,285 +0,0 @@ -{ - "exercise": "bank-account", - "comments": [ - "In order to keep the interface for the exercise close or equal to the ", - "description.md and also satisfying the canonical-data schema, the only ", - "properties are pop, push, shift, unshift. Some tracks also implement ", - "delete and count, via Track-Inserted hints. ", - " ", - "It is hard to have interesting tests using the property based approach so", - "this canonical data uses the following approach: ", - "- Each test input is an array of { operation, value?, expected? } ", - "- If operation is push, unshift, delete, then value is given ", - "- If operation is pop, shift, count, the expected value can be given ", - " ", - "Encoding tests and operations using the same field is necessary to have ", - "tests that don't just initialize the list, and then have one operation. " - ], - "cases": [ - { - "uuid": "983a1528-4ceb-45e5-8257-8ce01aceb5ed", - "description": "Using pop raises an error if the list is empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "amount", - "value": 0 - } - ] - }, "expected": {} - }, - { - "uuid": "e88d4ec3-c6bf-4752-8e59-5046c44e3ba7", - "description" : "Can return with pop and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": 100 - }, - { - "operation": "amount", - "expected": 100 - } - ] - }, - "expected": {} - }, - { - "uuid": "08f1af07-27ae-4b38-aa19-770bde558064", - "description": "Using shift raises an error if the list is empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": 100 - }, - { - "operation": "withdraw", - "value": 50 - }, - { - "operation": "amount", - "value": 50 - } - ] - }, - "expected": {} - }, - { - "uuid": "6f6d242f-8c31-4ac6-8995-a90d42cad59f", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": 100 - }, - { - "operation": "withdraw", - "value": 80 - }, - { - "operation": "withdraw", - "value": 20 - }, - { - "operation": "amount", - "value": 0 - } - ] - }, - "expected": {} - }, - { - "uuid": "f9facfaa-d824-486e-8381-48832c4bbffd", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "close" - }, - { - "operation": "amount" - } - ] - }, - "expected": {"error": "account not open"} - }, - { - "uuid": "7a65ba52-e35c-4fd2-8159-bda2bde6e59c", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "close" - }, - { - "operation": "deposit", - "value": 50 - } - ] - }, - "expected": {"error": "account not open"} - }, - { - "uuid": "570dfaa5-0532-4c1f-a7d3-0f65c3265608", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "close" - }, - { - "operation": "withdraw", - "value": 50 - } - ] - }, - "expected": {"error": "account not open"} - }, - { - "uuid": "c396d233-1c49-4272-98dc-7f502dbb9470", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "close" - } - ] - }, - "expected": {"error": "account not open"} - }, - { - "uuid": "c06f534f-bdc2-4a02-a388-1063400684de", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "open" - } - ] - }, - "expected": {"error": "account already open"} - }, - { - "uuid": "0722d404-6116-4f92-ba3b-da7f88f1669c", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": 50 - }, - { - "operation": "close" - }, - { - "operation": "open" - }, - { - "operation": "amount", - "value": 0 - } - ] - }, - "expected": {} - }, - { - "uuid": "ec42245f-9361-4341-8231-a22e8d19c52f", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": 25 - }, - { - "operation": "withdraw", - "value": 50 - } - ] - }, - "expected": {"error": "amount must be less than balance"} - }, - { - "uuid": "4f381ef8-10ef-4507-8e1d-0631ecc8ee72", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": 100 - }, - { - "operation": "withdraw", - "value": -50 - } - ] - }, - "expected": {"error": "amount must be greater than 0"} - }, - { - "uuid": "d45df9ea-1db0-47f3-b18c-d365db49d938", - "description": "Can return with shift and then raise an error if empty", - "property": "bankAccont", - "input": { - "operations": [ - { - "operation": "open" - }, - { - "operation": "deposit", - "value": -50 - } - ] - }, - "expected": {"error": "amount must be greater than 0"} - } -] -} \ No newline at end of file From c64b14e4c835ab4e150c4b8610c6290e59d7b7aa Mon Sep 17 00:00:00 2001 From: Katrina Owen Date: Tue, 18 Apr 2023 09:31:14 +0200 Subject: [PATCH 029/126] Sync simple-linked-list docs with problem-specifications The simple-linked-list exercise has been overhauled as part of a project to make practice exercises more consistent and friendly. For more context, please see the discussion in the forum, as well as the pull request that updated the exercise in the problem-specifications repository: - https://forum.exercism.org/t/new-project-making-practice-exercises-more-consistent-and-human-across-exercism/3943 --- .../simple-linked-list/.docs/instructions.md | 20 +++++++++++-------- .../simple-linked-list/.docs/introduction.md | 5 +++++ 2 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 exercises/practice/simple-linked-list/.docs/introduction.md diff --git a/exercises/practice/simple-linked-list/.docs/instructions.md b/exercises/practice/simple-linked-list/.docs/instructions.md index 4d845fac06c..04640b1fb03 100644 --- a/exercises/practice/simple-linked-list/.docs/instructions.md +++ b/exercises/practice/simple-linked-list/.docs/instructions.md @@ -1,15 +1,19 @@ # Instructions -Write a simple linked list implementation that uses Elements and a List. +Write a prototype of the music player application. -The linked list is a fundamental data structure in computer science, often used in the implementation of other data structures. -They're pervasive in functional programming languages, such as Clojure, Erlang, or Haskell, but far less common in imperative languages such as Ruby or Python. +For the prototype, each song will simply be represented by a number. +Given a range of numbers (the song IDs), create a singly linked list. + +Given a singly linked list, you should be able to reverse the list to play the songs in the opposite order. -The simplest kind of linked list is a singly linked list. -Each element in the list contains data and a "next" field pointing to the next element in the list of elements. +~~~~exercism/note +The linked list is a fundamental data structure in computer science, often used in the implementation of other data structures. -This variant of linked lists is often used to represent sequences or push-down stacks (also called a LIFO stack; Last In, First Out). +The simplest kind of linked list is a **singly** linked list. +That means that each element (or "node") contains data, along with something that points to the next node in the list. -As a first take, lets create a singly linked list to contain the range (1..10), and provide functions to reverse a linked list and convert to and from arrays. +If you want to dig deeper into linked lists, check out [this article][intro-linked-list] that explains it using nice drawings. -When implementing this in a language with built-in linked lists, implement your own abstract data type. +[intro-linked-list]: https://medium.com/basecs/whats-a-linked-list-anyway-part-1-d8b7e6508b9d +~~~~ diff --git a/exercises/practice/simple-linked-list/.docs/introduction.md b/exercises/practice/simple-linked-list/.docs/introduction.md new file mode 100644 index 00000000000..0e1df72f9bf --- /dev/null +++ b/exercises/practice/simple-linked-list/.docs/introduction.md @@ -0,0 +1,5 @@ +# Introduction + +You work for a music streaming company. + +You've been tasked with creating a playlist feature for your music player application. From 86ac5442fe0e7f6a9dbf5fd4514899cfbb4c76df Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Fri, 7 Apr 2023 15:40:16 -0700 Subject: [PATCH 030/126] 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 7eb1d65c767..39c0a8bfa63 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 ee43248f99e..75f45033e2b 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 c346d3c20fb..cc28280f174 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 7fe3c8d1a9c..08b1edc0443 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 cff6156dc65..a2a301295ac 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 4c5cdbf5c11b4cb3463210de9164469dbaed896b Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Mon, 10 Apr 2023 19:46:21 -0700 Subject: [PATCH 031/126] 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 75f45033e2b..ee43248f99e 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 cc28280f174..be224ff251b 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 a2a301295ac..617be353c66 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 7e470c1d54edb7d3746260ddc7512db5ab80e433 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Wed, 12 Apr 2023 15:15:21 -0700 Subject: [PATCH 032/126] 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 ee43248f99e..eac3b3c7742 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 be224ff251b..76c97ace37b 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 617be353c66..94dd32e0d5a 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) From 648088ed514494594566010f05fcf3aedb9da78f Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Wed, 12 Apr 2023 21:21:25 -0700 Subject: [PATCH 033/126] Add a comment explaining the fold arg swap --- exercises/practice/list-ops/.meta/template.j2 | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/practice/list-ops/.meta/template.j2 b/exercises/practice/list-ops/.meta/template.j2 index 76c97ace37b..af52ffbcce2 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -1,5 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} {% macro swap_args(function) -%} + {# Args are swapped to use Rust's fold tradition where it calls func(el, acc) and not func(acc, el) #} {% set function = function.replace("(acc, el)", "(el, acc)") %} {% set function = function.replace("(x, y)", "(y, x)") %} {{function}} From 888021b1e8617196338c2cc17cecce323d573609 Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Wed, 12 Apr 2023 21:23:28 -0700 Subject: [PATCH 034/126] Remove the swap and use Haskell tradition, i.e. what the problem spec uses --- exercises/practice/list-ops/.meta/example.py | 4 ++-- exercises/practice/list-ops/.meta/template.j2 | 9 +-------- exercises/practice/list-ops/list_ops_test.py | 14 +++++++------- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/exercises/practice/list-ops/.meta/example.py b/exercises/practice/list-ops/.meta/example.py index eac3b3c7742..75f45033e2b 100644 --- a/exercises/practice/list-ops/.meta/example.py +++ b/exercises/practice/list-ops/.meta/example.py @@ -22,14 +22,14 @@ def foldl(function, list, initial): if len(list) == 0: return initial else: - return foldl(function, list[1:], function(list[0], initial)) + return foldl(function, list[1:], function(initial, list[0])) 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 af52ffbcce2..cc28280f174 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -1,11 +1,4 @@ {%- import "generator_macros.j2" as macros with context -%} -{% macro swap_args(function) -%} - {# Args are swapped to use Rust's fold tradition where it calls func(el, acc) and not func(acc, el) #} - {% 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", "%") %} @@ -37,7 +30,7 @@ {%- elif case["property"] == "length" or case["property"] == "reverse" -%} {{ input["list"] }} {%- elif case["property"] == "foldl" or case["property"] == "foldr" -%} - {{ lambdify(swap_args(input["function"])) }}, {{ input["list"] }}, {{ stringify(input["initial"]) }} + {{ lambdify(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 94dd32e0d5a..a2a301295ac 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -58,22 +58,22 @@ 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 el, acc: el * acc, [], 2), 2) + self.assertEqual(foldl(lambda acc, el: el * acc, [], 2), 2) def test_foldl_direction_independent_function_applied_to_non_empty_list(self): - self.assertEqual(foldl(lambda el, acc: el + acc, [1, 2, 3, 4], 5), 15) + 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 el, acc: el / acc, [1, 2, 3, 4], 24), 64) + self.assertEqual(foldl(lambda acc, el: el / acc, [1, 2, 3, 4], 24), 64) def test_foldr_empty_list(self): - self.assertEqual(foldr(lambda el, acc: el * acc, [], 2), 2) + 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 el, acc: el + acc, [1, 2, 3, 4], 5), 15) + 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 el, acc: el / acc, [1, 2, 3, 4], 24), 9) + self.assertEqual(foldr(lambda acc, el: 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 el, acc: el + acc, ["e", "x", "e", "r", "c", "i", "s", "m"], "!" + lambda acc, el: el + acc, ["e", "x", "e", "r", "c", "i", "s", "m"], "!" ), "exercism!", ) From 461e6fc91e418bbd2e36d0504903c3b3ad8cd00d Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Tue, 9 May 2023 13:41:17 -0700 Subject: [PATCH 035/126] [list-ops] Add IsaacG as a contributor --- exercises/practice/list-ops/.meta/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/practice/list-ops/.meta/config.json b/exercises/practice/list-ops/.meta/config.json index efc025a3543..cdb33138a4e 100644 --- a/exercises/practice/list-ops/.meta/config.json +++ b/exercises/practice/list-ops/.meta/config.json @@ -8,6 +8,7 @@ "Dog", "dvermd", "gabriel376", + "IsaacG", "N-Parsons", "pheanex", "rootulp", From c1cc9f9594034cc202d16fe0c8d984e23c47e6fa Mon Sep 17 00:00:00 2001 From: BethanyG Date: Thu, 18 May 2023 09:20:22 -0700 Subject: [PATCH 036/126] Updated metadata from problem specifications. --- exercises/practice/binary/.meta/config.json | 2 +- exercises/practice/etl/.meta/config.json | 4 ++-- exercises/practice/hexadecimal/.meta/config.json | 2 +- exercises/practice/nucleotide-count/.meta/config.json | 2 +- exercises/practice/octal/.meta/config.json | 2 +- exercises/practice/point-mutations/.meta/config.json | 2 +- exercises/practice/trinary/.meta/config.json | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/exercises/practice/binary/.meta/config.json b/exercises/practice/binary/.meta/config.json index 7170a4ab191..b9f5b07508a 100644 --- a/exercises/practice/binary/.meta/config.json +++ b/exercises/practice/binary/.meta/config.json @@ -26,5 +26,5 @@ ] }, "source": "All of Computer Science", - "source_url": "http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-" + "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" } diff --git a/exercises/practice/etl/.meta/config.json b/exercises/practice/etl/.meta/config.json index 4d99e6314da..32aab8ba3ba 100644 --- a/exercises/practice/etl/.meta/config.json +++ b/exercises/practice/etl/.meta/config.json @@ -27,7 +27,7 @@ ".meta/example.py" ] }, - "blurb": "We are going to do the `Transform` step of an Extract-Transform-Load.", - "source": "Exercise by the JumpstartLab team for students at The Turing School of Software and Design.", + "blurb": "Change the data format for scoring a game to more easily add other languages.", + "source": "Based on an exercise by the JumpstartLab team for students at The Turing School of Software and Design.", "source_url": "https://turing.edu" } diff --git a/exercises/practice/hexadecimal/.meta/config.json b/exercises/practice/hexadecimal/.meta/config.json index 352ca16d78c..b61e1a2c057 100644 --- a/exercises/practice/hexadecimal/.meta/config.json +++ b/exercises/practice/hexadecimal/.meta/config.json @@ -26,5 +26,5 @@ ] }, "source": "All of Computer Science", - "source_url": "http://www.wolframalpha.com/examples/NumberBases.html" + "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" } diff --git a/exercises/practice/nucleotide-count/.meta/config.json b/exercises/practice/nucleotide-count/.meta/config.json index 4e91bb7ee9f..e0c108f7b88 100644 --- a/exercises/practice/nucleotide-count/.meta/config.json +++ b/exercises/practice/nucleotide-count/.meta/config.json @@ -28,5 +28,5 @@ ] }, "source": "The Calculating DNA Nucleotides_problem at Rosalind", - "source_url": "http://rosalind.info/problems/dna/" + "source_url": "https://rosalind.info/problems/dna/" } diff --git a/exercises/practice/octal/.meta/config.json b/exercises/practice/octal/.meta/config.json index e39e3fb6870..4fe6c11bdef 100644 --- a/exercises/practice/octal/.meta/config.json +++ b/exercises/practice/octal/.meta/config.json @@ -26,5 +26,5 @@ ] }, "source": "All of Computer Science", - "source_url": "http://www.wolframalpha.com/input/?i=base+8" + "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" } diff --git a/exercises/practice/point-mutations/.meta/config.json b/exercises/practice/point-mutations/.meta/config.json index 2d8d765c187..b02f3706511 100644 --- a/exercises/practice/point-mutations/.meta/config.json +++ b/exercises/practice/point-mutations/.meta/config.json @@ -26,5 +26,5 @@ ] }, "source": "The Calculating Point Mutations problem at Rosalind", - "source_url": "http://rosalind.info/problems/hamm/" + "source_url": "https://rosalind.info/problems/hamm/" } diff --git a/exercises/practice/trinary/.meta/config.json b/exercises/practice/trinary/.meta/config.json index 104b505a620..da59ec6c571 100644 --- a/exercises/practice/trinary/.meta/config.json +++ b/exercises/practice/trinary/.meta/config.json @@ -26,5 +26,5 @@ ] }, "source": "All of Computer Science", - "source_url": "http://www.wolframalpha.com/input/?i=binary&a=*C.binary-_*MathWorld-" + "source_url": "https://www.wolframalpha.com/examples/mathematics/numbers/base-conversions" } From e03b3cdd56495a8497bb3108a86213f7a29c43f1 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Wed, 7 Dec 2022 22:58:17 +0100 Subject: [PATCH 037/126] depricated diffie-hellman --- config.json | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/config.json b/config.json index 1d118f79c88..47548a89015 100644 --- a/config.json +++ b/config.json @@ -1247,14 +1247,6 @@ ], "difficulty": 3 }, - { - "slug": "diffie-hellman", - "name": "Diffie-Hellman", - "uuid": "92e2d5f8-7d8a-4e81-a55c-52fa6be80c74", - "practices": ["numbers"], - "prerequisites": ["basics", "bools", "numbers"], - "difficulty": 3 - }, { "slug": "connect", "name": "Connect", @@ -2201,6 +2193,15 @@ "difficulty": 3, "status": "deprecated" }, + { + "slug": "diffie-hellman", + "name": "Diffie-Hellman", + "uuid": "92e2d5f8-7d8a-4e81-a55c-52fa6be80c74", + "practices": [], + "prerequisites": [], + "difficulty": 3, + "status": "deprecated" + }, { "slug": "trinary", "name": "Trinary", From 520c3e637033c1ed1329c46ef880ad03b5582d80 Mon Sep 17 00:00:00 2001 From: Carl Date: Tue, 27 Dec 2022 22:13:00 +0100 Subject: [PATCH 038/126] Started on improvments --- concepts/generators/about.md | 63 +++++++++++++++-------------- concepts/generators/introduction.md | 4 +- concepts/generators/links.json | 4 +- 3 files changed, 37 insertions(+), 34 deletions(-) diff --git a/concepts/generators/about.md b/concepts/generators/about.md index f1b97291e4c..a136dde5076 100644 --- a/concepts/generators/about.md +++ b/concepts/generators/about.md @@ -4,65 +4,63 @@ Generators are constructed much like other looping or recursive functions, but require a [`yield` expression](#the-yield-expression), which we will explore in depth a bit later. - An example is a function that returns the _squares_ from a given list of numbers. -As currently written, all input must be processed before any values can be returned: - +As currently written, all input must be processed before any values can be returned: ```python >>> def squares(list_of_numbers): ->>> squares = [] ->>> for number in list_of_numbers: ->>> squares.append(number ** 2) ->>> return squares +... squares = [] +... for number in list_of_numbers: +... squares.append(number ** 2) +... return squares ``` You can convert that function into a generator like this: ```python -def squares(list_of_numbers): - for number in list_of_number: - yield number ** 2 +>>> def squares_generator(list_of_numbers): +... for number in list_of_numbers: +... yield number ** 2 ``` The rationale behind this is that you use a generator when you do not need all the values _at once_. This saves memory and processing power, since only the value you are _currently working on_ is calculated. - ## Using a generator -Generators may be used in place of most `iterables` in Python. This includes _functions_ or _objects_ that require an `iterable`/`iterator` as an argument. +Generators may be used in place of most `iterables` in Python. This includes _functions_ or _objects_ that require an `iterable`/`iterator` as an argument. -To use the `squares()` generator: +To use the `squares_generator()` generator: ```python ->>> squared_numbers = squares([1, 2, 3, 4]) +>>> squared_numbers = squares_generator([1, 2, 3, 4]) >>> for square in squared_numbers: ->>> print(square) +... print(square) +... 1 4 9 16 ``` -Values within a generator can also be produced/accessed via the `next()` function. +Values within a generator can also be produced/accessed via the `next()` function. `next()` calls the `__next__()` method of a generator object, "advancing" or evaluating the generator code up to its `yield` expression, which then "yields" or returns the value. ```python -square_generator = squares([1, 2]) +>>> squared_numbers = squares_generator([1, 2]) ->>> next(square_generator) +>>> next(squared_numbers) 1 ->>> next(square_generator) +>>> next(squared_numbers) 4 ``` When a `generator` is fully consumed and has no more values to return, it throws a `StopIteration` error. ```python ->>> next(square_generator) +>>> next(squared_numbers) Traceback (most recent call last): File "", line 1, in StopIteration @@ -72,12 +70,12 @@ StopIteration Generators are a special sub-set of _iterators_. `Iterators` are the mechanism/protocol that enables looping over _iterables_. -Generators and and the iterators returned by common Python (`iterables`)[https://wiki.python.org/moin/Iterator] act very similarly, but there are some important differences to note: - +Generators and the iterators returned by common Python [`iterables`][iterables] act very similarly, but there are some important differences to note: - Generators are _one-way_; there is no "backing up" to a previous value. - Iterating over generators consume the returned values; no resetting. + - Generators (_being lazily evaluated_) are not sortable and can not be reversed. - Generators do _not_ have `indexes`, so you can't reference a previous or future value using addition or subtraction. @@ -88,7 +86,7 @@ Generators and and the iterators returned by common Python (`iterables`)[https:/ ## The yield expression -The [yield expression](https://docs.python.org/3.8/reference/expressions.html#yield-expressions) is very similar to the `return` expression. +The [yield expression][yield expression] is very similar to the `return` expression. _Unlike_ the `return` expression, `yield` gives up values to the caller at a _specific point_, suspending evaluation/return of any additional values until they are requested. @@ -100,10 +98,10 @@ Note: _Using `yield` expressions is prohibited outside of functions._ ```python >>> def infinite_sequence(): ->>> current_number = 0 ->>> while True: ->>> yield current_number ->>> current_number += 1 +... current_number = 0 +... while True: +... yield current_number +... current_number += 1 >>> lets_try = infinite_sequence() >>> lets_try.__next__() @@ -123,10 +121,13 @@ Generators are also very helpful when a process or calculation is _complex_, _ex ```python >>> def infinite_sequence(): ->>> current_number = 0 ->>> while True: ->>> yield current_number ->>> current_number += 1 +... current_number = 0 +... while True: +... yield current_number +... current_number += 1 ``` Now whenever `__next__()` is called on the `infinite_sequence` object, it will return the _previous number_ + 1. + +[iterables]: https://wiki.python.org/moin/Iterator +[yield expression]: https://docs.python.org/3.11/reference/expressions.html#yield-expressions diff --git a/concepts/generators/introduction.md b/concepts/generators/introduction.md index 2c148371330..82a686d1e05 100644 --- a/concepts/generators/introduction.md +++ b/concepts/generators/introduction.md @@ -1,5 +1,7 @@ # Introduction -A generator in Python is a _callable function_ that returns a [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation). +A generator in Python is a _callable function_ that returns a [lazy iterator][lazy iterator]. _Lazy iterators_ are similar to `lists`, and other `iterators`, but with one key difference: They do not store their `values` in memory, but _generate_ their values when needed. + +[lazy iterator]: https://en.wikipedia.org/wiki/Lazy_evaluation diff --git a/concepts/generators/links.json b/concepts/generators/links.json index b8ae2f7b648..eea7d4ae338 100644 --- a/concepts/generators/links.json +++ b/concepts/generators/links.json @@ -1,7 +1,7 @@ [ { - "url": "https://docs.python.org/3.8/reference/expressions.html#yield-expressions", - "description": "Official Python 3.8 docs for the yield expression." + "url": "https://docs.python.org/3.11/reference/expressions.html#yield-expressions", + "description": "Official Python 3.11 docs for the yield expression." }, { "url": "https://en.wikipedia.org/wiki/Lazy_evaluation", From e18b1e1c300243713198017aa1b84be53b704f09 Mon Sep 17 00:00:00 2001 From: Carl Date: Tue, 27 Dec 2022 23:28:51 +0100 Subject: [PATCH 039/126] Added an extra exercise --- .../plane-tickets/.docs/instructions.md | 45 +++++++++++++------ .../concept/plane-tickets/.meta/config.json | 2 +- .../concept/plane-tickets/.meta/exemplar.py | 29 +++++++++--- .../concept/plane-tickets/plane_tickets.py | 18 +++++++- .../plane-tickets/plane_tickets_test.py | 36 ++++++++++----- 5 files changed, 98 insertions(+), 32 deletions(-) diff --git a/exercises/concept/plane-tickets/.docs/instructions.md b/exercises/concept/plane-tickets/.docs/instructions.md index 290aad2ebb7..9863fe293fb 100644 --- a/exercises/concept/plane-tickets/.docs/instructions.md +++ b/exercises/concept/plane-tickets/.docs/instructions.md @@ -2,9 +2,10 @@ Conda airlines is the programming-world's biggest airline, with over 10.000 flights a day! -They are currently assigning all seats to passengers by hand, this will need to automated. +They are currently assigning all seats to passengers by hand, this will need to be automated. -They have asked _you_ to create software to automate the assigning of seats to passengers. They require your software to be memory efficient and performant. +They have asked _you_ to create software to automate the assigning of seats to passengers. +They require your software to be memory efficient and performant. Conda's airplanes have up to _4 seats_ in each row, and each airplane has many rows. @@ -12,13 +13,29 @@ While the rows are defined using numbers, seats in each row are defined using le You can use this table as a guide: -| x | 1 | 2 | -| :----: | :----: | :----:| -| Row | 5 | 21 | -| Seat letter | A | D | -| Result | 5A | 21D | +| x | 1 | 2 | +| :---------: | :-: | :-: | +| Row | 5 | 21 | +| Seat letter | A | D | +| Result | 5A | 21D | -## 1. Generate an amount of seats +## 1. Generate seat letters + +Implement the `generate_seat_letters()` function that returns an _iterable_ of seat letters given the following variable: + +`amount`: The amount of seat letters to be generated. + +The letters should be generated in alphabetical order, starting with `A` and ending with `D`. + +```python +>>> letters = generate_seat_letters(4) +>>> next(letters) +"A" +>>> next(letters) +"B" +``` + +## 2. Generate an amount of seats Implement the `generate_seats()` function that returns an _iterable_ of seats given the following variable: @@ -37,9 +54,10 @@ _Note: The returned seats should be ordered, like: 1A 1B 1C._ "1B" ``` -## 2. Assign seats to passengers +## 3. Assign seats to passengers -Implement the `assign_seats()` function that returns a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. Given is the following _list_: +Implement the `assign_seats()` function that returns a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. +Given is the following _list_: `passengers`: A list containing passenger names. @@ -50,15 +68,16 @@ Implement the `assign_seats()` function that returns a _dictionary_ of `passenge {'Jerimiah': '1A', 'Eric': '1B', 'Bethaney': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'} ``` -## 3. Ticket codes +## 4. Ticket codes Each ticket has a _12_ character long string code for identification. -This code begins with the `assigned_seat` followed by the `flight_id`. The rest of the code is appended by `0s`. +This code begins with the `assigned_seat` followed by the `flight_id`. +The rest of the code is appended by `0s`. Implement a `generator` that yields a `ticket_number` given the following arguments: -`seat_numbers`: A _list_ of *seat_numbers*. +`seat_numbers`: A _list_ of _seat_numbers_. `flight_id`: A string containing the flight identification. ```python diff --git a/exercises/concept/plane-tickets/.meta/config.json b/exercises/concept/plane-tickets/.meta/config.json index 016ff0cef23..2698188896e 100644 --- a/exercises/concept/plane-tickets/.meta/config.json +++ b/exercises/concept/plane-tickets/.meta/config.json @@ -16,6 +16,6 @@ ".meta/exemplar.py" ] }, - "icon": "poker", + "icon": "new-passport", "blurb": "Learn about generators by assigning seats to passengers." } diff --git a/exercises/concept/plane-tickets/.meta/exemplar.py b/exercises/concept/plane-tickets/.meta/exemplar.py index fa8927d759a..703e31cb3fc 100644 --- a/exercises/concept/plane-tickets/.meta/exemplar.py +++ b/exercises/concept/plane-tickets/.meta/exemplar.py @@ -1,11 +1,28 @@ -"""Plane Tickets Exercise""" +"""Functions to automate Conda airlines ticketing system.""" import math SEATS_IN_ROW = ['A', 'B', 'C', 'D'] -def generate_seats(amount): +def generate_seat_letters(amount): + """ Generate a series of seat letters for airline boarding. + + :param amount: Amount of seat letters to be generated. (int) + :return: Generator that yields seat letters. + + Seat letters are generated with each row having 4 seats. + These should be sorted from low to high. + + Example: A, B, C, D + + """ + + for seat in range(amount): + yield SEATS_IN_ROW[seat % 4] + + +def generate_seats(amount): """Generate a series of seat numbers for airline boarding. :param amount: Amount of seats to be generated. (int) @@ -21,16 +38,14 @@ def generate_seats(amount): """ amount = amount + 4 if amount >= 13 else amount - + letters = generate_seat_letters(amount) for seat in range(amount): row_number = math.ceil((seat+1) / 4) if row_number != 13: - seat_letter = SEATS_IN_ROW[seat % 4] - yield f'{str(row_number)}{seat_letter}' + yield f'{str(row_number)}{next(letters)}' def assign_seats(passengers): - - """Assign seats to passenger. + """Assign seats to passengers. :param passengers: A list of strings containing names of passengers. (list[str]) :return: A dictionary type object containing the names of the passengers as keys and seat numbers as values. diff --git a/exercises/concept/plane-tickets/plane_tickets.py b/exercises/concept/plane-tickets/plane_tickets.py index 44d685535b6..2d8ad345a70 100644 --- a/exercises/concept/plane-tickets/plane_tickets.py +++ b/exercises/concept/plane-tickets/plane_tickets.py @@ -1,4 +1,20 @@ -"""Plane Tickets Exercise""" +"""Functions to automate Conda airlines ticketing system.""" + +def generate_seat_letters(amount): + """ Generate a series of seat letters for airline boarding. + + :param amount: Amount of seat letters to be generated. (int) + :return: Generator that yields seat letters. + + Seat letters are generated with each row having 4 seats. + These should be sorted from low to high. + + Example: A, B, C, D + + """ + + pass + def generate_seats(amount): diff --git a/exercises/concept/plane-tickets/plane_tickets_test.py b/exercises/concept/plane-tickets/plane_tickets_test.py index f4255c43af6..1372e5cd2d7 100644 --- a/exercises/concept/plane-tickets/plane_tickets_test.py +++ b/exercises/concept/plane-tickets/plane_tickets_test.py @@ -3,6 +3,7 @@ import pytest from plane_tickets import ( + generate_seat_letters, generate_seats, assign_seats, generate_codes @@ -10,16 +11,31 @@ class PlaneTicketsTest(unittest.TestCase): - @pytest.mark.task(taskno=1) def test_task1_is_generator(self): # * Tests if [Task 1] actually returns a generator. input_var = 5 output_type = Generator error_message = f"Expected: {str(output_type)} type, but got a different type." - self.assertIsInstance(generate_seats(input_var), output_type, msg=error_message) + self.assertIsInstance(generate_seat_letters(input_var), output_type, msg=error_message) @pytest.mark.task(taskno=1) def test_task1_output(self): + input_vars = [1, 2, 3, 4, 5] + output = [["A"], ["A", "B"], ["A", "B", "C"], ["A", "B", "C", "D"], ["A", "B", "C", "D", "A"]] + for variant, (input_var, output) in enumerate(zip(input_vars, output), start=1): + error_message = f"Expected: {output}, but something went wrong while generating {input_var} seat(s)." + with self.subTest(f"variation #{variant}", input_data=input_var, output_data=output): + self.assertEqual(list(generate_seat_letters(input_var)), output, msg=error_message) + + @pytest.mark.task(taskno=2) + def test_task2_is_generator(self): # * Tests if [Task 2] actually returns a generator. + input_var = 5 + output_type = Generator + error_message = f"Expected: {str(output_type)} type, but got a different type." + self.assertIsInstance(generate_seats(input_var), output_type, msg=error_message) + + @pytest.mark.task(taskno=2) + def test_task2_output(self): input_vars = [1, 2, 3, 4, 5] output = [["1A"], ["1A", "1B"], ["1A", "1B", "1C"], ["1A", "1B", "1C", "1D"], ["1A", "1B", "1C", "1D", "2A"]] for variant, (input_var, output) in enumerate(zip(input_vars, output), start=1): @@ -27,8 +43,8 @@ def test_task1_output(self): with self.subTest(f"variation #{variant}", input_data=input_var, output_data=output): self.assertEqual(list(generate_seats(input_var)), output, msg=error_message) - @pytest.mark.task(taskno=1) - def test_task1_skips_row_13(self): + @pytest.mark.task(taskno=2) + def test_task3_skips_row_13(self): input_vars = [14 * 4] output = [["1A", "1B", "1C", "1D", "2A", "2B", "2C", "2D", "3A", "3B", "3C", "3D", "4A", "4B", "4C", "4D", @@ -42,8 +58,8 @@ def test_task1_skips_row_13(self): with self.subTest(f"variation #{variant}", input_data=input_var, output_data=output): self.assertEqual(list(generate_seats(input_var)), output, msg=error_message) - @pytest.mark.task(taskno=2) - def test_task2(self): + @pytest.mark.task(taskno=3) + def test_task3(self): input_vars = [["Passenger1", "Passenger2", "Passenger3", "Passenger4", "Passenger5"], ["TicketNo=5644", "TicketNo=2273", "TicketNo=493", "TicketNo=5411", "TicketNo=824"]] output = [{"Passenger1": "1A", "Passenger2": "1B", "Passenger3": "1C", "Passenger4": "1D", "Passenger5": "2A"}, @@ -53,15 +69,15 @@ def test_task2(self): with self.subTest(f"variation #{variant}", input_data=input_var, output_data=output): self.assertEqual(assign_seats(input_var), output, msg=error_message) - @pytest.mark.task(taskno=3) - def test_task3_is_generator(self): + @pytest.mark.task(taskno=4) + def test_task4_is_generator(self): input_var = ("11B", "HA80085") output_type = Generator error_message = f"Expected: {str(output_type)} type, but got a different type." self.assertIsInstance(generate_codes(input_var[0], input_var[1]), output_type, msg=error_message) - @pytest.mark.task(taskno=3) - def test_task3(self): + @pytest.mark.task(taskno=4) + def test_task4(self): input_vars = [(["12A", "38B", "69C", "102B"],"KL1022"), (["22C", "88B", "33A", "44B"], "DL1002")] output = [['12AKL1022000', '38BKL1022000', '69CKL1022000', '102BKL102200'], From ea3e886757332b4afb1beeec5017750e89b2f0c6 Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 28 Dec 2022 14:25:37 +0100 Subject: [PATCH 040/126] Small fix --- exercises/concept/plane-tickets/.meta/exemplar.py | 1 - exercises/concept/plane-tickets/plane_tickets.py | 3 --- 2 files changed, 4 deletions(-) diff --git a/exercises/concept/plane-tickets/.meta/exemplar.py b/exercises/concept/plane-tickets/.meta/exemplar.py index 703e31cb3fc..6bf9ce68a11 100644 --- a/exercises/concept/plane-tickets/.meta/exemplar.py +++ b/exercises/concept/plane-tickets/.meta/exemplar.py @@ -61,7 +61,6 @@ def assign_seats(passengers): return output def generate_codes(seat_numbers, flight_id): - """Generate codes for a ticket. :param seat_numbers: A list of seat numbers. (list[str]) diff --git a/exercises/concept/plane-tickets/plane_tickets.py b/exercises/concept/plane-tickets/plane_tickets.py index 2d8ad345a70..ff2e8a58eed 100644 --- a/exercises/concept/plane-tickets/plane_tickets.py +++ b/exercises/concept/plane-tickets/plane_tickets.py @@ -17,7 +17,6 @@ def generate_seat_letters(amount): def generate_seats(amount): - """ Generate a series of seat numbers for airline boarding. :param amount: Amount of seats to be generated. (int) @@ -35,7 +34,6 @@ def generate_seats(amount): pass def assign_seats(passengers): - """ Assign seats to passengers. :param passengers: A list of strings containing names of passengers. (list[str]) @@ -48,7 +46,6 @@ def assign_seats(passengers): pass def generate_codes(seat_numbers, flight_id): - """Generate codes for a ticket. :param seat_numbers: A list of seat numbers. (list[str]) From 16916968e77938041f2aa849731ffc008af68a1f Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 28 Dec 2022 14:46:58 +0100 Subject: [PATCH 041/126] Runed prettier and major changes to instructions.md --- .../plane-tickets/.docs/instructions.md | 54 ++++++++-------- .../concept/plane-tickets/.meta/design.md | 62 ++++++++----------- 2 files changed, 54 insertions(+), 62 deletions(-) diff --git a/exercises/concept/plane-tickets/.docs/instructions.md b/exercises/concept/plane-tickets/.docs/instructions.md index 9863fe293fb..2798bf8651e 100644 --- a/exercises/concept/plane-tickets/.docs/instructions.md +++ b/exercises/concept/plane-tickets/.docs/instructions.md @@ -7,25 +7,14 @@ They are currently assigning all seats to passengers by hand, this will need to They have asked _you_ to create software to automate the assigning of seats to passengers. They require your software to be memory efficient and performant. -Conda's airplanes have up to _4 seats_ in each row, and each airplane has many rows. - -While the rows are defined using numbers, seats in each row are defined using letters from the alphabet, with `seat A` being the first _seat_ in the row. - -You can use this table as a guide: - -| x | 1 | 2 | -| :---------: | :-: | :-: | -| Row | 5 | 21 | -| Seat letter | A | D | -| Result | 5A | 21D | - ## 1. Generate seat letters -Implement the `generate_seat_letters()` function that returns an _iterable_ of seat letters given the following variable: +Conda wants to generate seat letters for their airplanes. +Every row has _4 seats_. +They all have the same pattern: `A`, `B`, `C`, `D`. -`amount`: The amount of seat letters to be generated. - -The letters should be generated in alphabetical order, starting with `A` and ending with `D`. +Implement a function `generate_seat_letters()` that accepts an `int` that holds how many seat letters to be generated. +The function should then return an _iterable_ of seat letters. ```python >>> letters = generate_seat_letters(4) @@ -37,14 +26,24 @@ The letters should be generated in alphabetical order, starting with `A` and end ## 2. Generate an amount of seats -Implement the `generate_seats()` function that returns an _iterable_ of seats given the following variable: +Conda wants a system that can generate an amount of seats for their airplanes. +Each airplane has _4 seats_ in each row. +The rows are defined using numbers, starting from `1` and going up. +The seats should be ordered, like: `1A`, `1B`, `1C`, `1D`, `2A`, `2B`, `2C`, `2D`, `3A`, `3B`, `3C`, `3D`, ... + +Here is an example: -`amount`: The amount of seats to be generated. +| x | 1 | 2 | +| :---------: | :-: | :-: | +| Row | 5 | 21 | +| Seat letter | A | D | +| Result | 5A | 21D | Many airlines do not have _row_ number 13 on their flights, due to superstition amongst passengers. Conda Airlines also follows this convention, so make sure you _don't_ generate seats for _row_ number 13. -_Note: The returned seats should be ordered, like: 1A 1B 1C._ +Implement a function `generate_seats()` hat accepts an `int` that accepts an `int` that holds how many seats to be generated. +The function should then return an _iterable_ of seats given. ```python >>> seats = generate_seats(10) @@ -56,10 +55,10 @@ _Note: The returned seats should be ordered, like: 1A 1B 1C._ ## 3. Assign seats to passengers -Implement the `assign_seats()` function that returns a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. -Given is the following _list_: +Now that you have a function that generates seats, you can use it to assign seats to passengers. -`passengers`: A list containing passenger names. +Implement a function `assign_seats()` that accepts a `list` of passenger names. +The function should then return a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. ```python >>> passengers = ['Jerimiah', 'Eric', 'Bethaney', 'Byte', 'SqueekyBoots', 'Bob'] @@ -70,15 +69,16 @@ Given is the following _list_: ## 4. Ticket codes -Each ticket has a _12_ character long string code for identification. +Conda Airlines would like to have a unique code for each ticket. +Since they are a big airline, they have a lot of flights. +Meaning that there are multiple flights with the same seat number. +They want you to create a system that creats a unique ticket that has _12_ characters long string code for identification. This code begins with the `assigned_seat` followed by the `flight_id`. The rest of the code is appended by `0s`. -Implement a `generator` that yields a `ticket_number` given the following arguments: - -`seat_numbers`: A _list_ of _seat_numbers_. -`flight_id`: A string containing the flight identification. +Implement a function `generate_codes()` that accepts a `list` of `seat_numbers` and a `string` with the flight number. +The function should then return a `generator` that yields a `ticket_number`. ```python >>> seat_numbers = ['1A', '17D'] diff --git a/exercises/concept/plane-tickets/.meta/design.md b/exercises/concept/plane-tickets/.meta/design.md index 58542aab87c..0323418c857 100644 --- a/exercises/concept/plane-tickets/.meta/design.md +++ b/exercises/concept/plane-tickets/.meta/design.md @@ -2,16 +2,15 @@ This issue describes how to implement the `generators` concept exercise for the ## Goal -The goal of this exercise is to teach the syntax and use of `generators` in Python. +The goal of this exercise is to teach the syntax and use of `generators` in Python. ## Learning objectives -- Understand what generators are and how/when to use them -- Understand how generators relate to `loops` and `iterators` -- Understand how to use the `yield` keyword -- Understand the `__next__()` method -- Create a generator - +- Understand what generators are and how/when to use them +- Understand how generators relate to `loops` and `iterators` +- Understand how to use the `yield` keyword +- Understand the `__next__()` method +- Create a generator ## Out of scope @@ -22,32 +21,28 @@ The goal of this exercise is to teach the syntax and use of `generators` in Pyth - `yield from` - `generators` used as coroutines - ## Concepts covered -- `generators` -- `yield` -- `__next__()` -- `iterators` - +- `generators` +- `yield` +- `__next__()` +- `iterators` ## Prerequisites -- `conditionals` -- `dicts` -- `functions` -- `higher-order-functions` -- `lists` -- `loops` -- `iteration` -- `iterators` -- `sequences` - - +- `conditionals` +- `dicts` +- `functions` +- `higher-order-functions` +- `lists` +- `loops` +- `iteration` +- `iterators` +- `sequences` ## Resources to refer to -- [Generators (Python official docs)](https://docs.python.org/3/howto/functional.html#generators) +- [Generators (Python official docs)](https://docs.python.org/3/howto/functional.html#generators) - [generator (Python official docs glossary)](https://docs.python.org/3/glossary.html#term-generator) - [The yield statement (Python official docs)](https://docs.python.org/3/reference/simple_stmts.html#the-yield-statement) - [Yield expressions (Python official docs)](https://docs.python.org/3/reference/expressions.html#yieldexpr) @@ -57,21 +52,20 @@ The goal of this exercise is to teach the syntax and use of `generators` in Pyth ### Hints -- Referring to one or more of the resources linked above, or analogous resources from a trusted source. -- `Generators` section of the Python Docs Functional How to tutorial: [Generators](https://docs.python.org/3/howto/functional.html#generators) - +- Referring to one or more of the resources linked above, or analogous resources from a trusted source. +- `Generators` section of the Python Docs Functional How to tutorial: [Generators](https://docs.python.org/3/howto/functional.html#generators) -## Concept Description +## Concept Description -(_a variant of this can be used for the `v3/languages/python/concepts//about.md` doc and this exercises `introduction.md` doc._) +(_a variant of this can be used for the `v3/languages/python/concepts//about.md` doc and this exercises `introduction.md` doc._) _**Concept Description Needs to Be Filled In Here/Written**_ _Some "extras" that we might want to include as notes in the concept description, or as links in `links.json`:_ -- Additional `Generator-iterator methods`, such as `generator.send()` and `generator.throw()` +- Additional `Generator-iterator methods`, such as `generator.send()` and `generator.throw()` - `generator expressions` -- Asynchronous generator functions +- Asynchronous generator functions - `generators` used as coroutines ## Implementing @@ -80,10 +74,8 @@ The general Python track concept exercise implantation guide can be found [here] Tests should be written using `unittest.TestCase` and the test file named `generators_test.py`. -Code in the `.meta/example.py` file should **only use syntax & concepts introduced in this exercise or one of its prerequisites.** 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. +Code in the `.meta/example.py` file should **only use syntax & concepts introduced in this exercise or one of its prerequisites.** 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. ## Help If you have any questions while implementing the exercise, please post the questions as comments in this issue, or contact one of the maintainers on our Slack channel. - - From 0a08d61f4d7cabdf8b7885d668223a76fd20f404 Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 28 Dec 2022 21:03:43 +0100 Subject: [PATCH 042/126] spell fixes --- exercises/concept/plane-tickets/.docs/instructions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/concept/plane-tickets/.docs/instructions.md b/exercises/concept/plane-tickets/.docs/instructions.md index 2798bf8651e..f49c4ff8dfb 100644 --- a/exercises/concept/plane-tickets/.docs/instructions.md +++ b/exercises/concept/plane-tickets/.docs/instructions.md @@ -42,7 +42,7 @@ Here is an example: Many airlines do not have _row_ number 13 on their flights, due to superstition amongst passengers. Conda Airlines also follows this convention, so make sure you _don't_ generate seats for _row_ number 13. -Implement a function `generate_seats()` hat accepts an `int` that accepts an `int` that holds how many seats to be generated. +Implement a function `generate_seats()` that accepts an `int` that accepts an `int` that holds how many seats to be generated. The function should then return an _iterable_ of seats given. ```python @@ -72,7 +72,7 @@ The function should then return a _dictionary_ of `passenger` as _key_, and `sea Conda Airlines would like to have a unique code for each ticket. Since they are a big airline, they have a lot of flights. Meaning that there are multiple flights with the same seat number. -They want you to create a system that creats a unique ticket that has _12_ characters long string code for identification. +They want you to create a system that creates a unique ticket that has _12_ characters long string code for identification. This code begins with the `assigned_seat` followed by the `flight_id`. The rest of the code is appended by `0s`. From 4378e0c8d8fdbd7fe7adaa5ac4cae8a93067acef Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 29 Dec 2022 14:18:54 +0100 Subject: [PATCH 043/126] some improvments --- exercises/concept/plane-tickets/.docs/instructions.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/exercises/concept/plane-tickets/.docs/instructions.md b/exercises/concept/plane-tickets/.docs/instructions.md index f49c4ff8dfb..b321addbd38 100644 --- a/exercises/concept/plane-tickets/.docs/instructions.md +++ b/exercises/concept/plane-tickets/.docs/instructions.md @@ -10,8 +10,10 @@ They require your software to be memory efficient and performant. ## 1. Generate seat letters Conda wants to generate seat letters for their airplanes. -Every row has _4 seats_. -They all have the same pattern: `A`, `B`, `C`, `D`. +An airplane is made of rows of seats. +Each row has _4 seats_. +The rows seats has the same naming: `A`, `B`, `C`, `D`. +Meaning the first seat in the row is `A`, the second seat in the row is `B`, and so on. Implement a function `generate_seat_letters()` that accepts an `int` that holds how many seat letters to be generated. The function should then return an _iterable_ of seat letters. @@ -72,7 +74,7 @@ The function should then return a _dictionary_ of `passenger` as _key_, and `sea Conda Airlines would like to have a unique code for each ticket. Since they are a big airline, they have a lot of flights. Meaning that there are multiple flights with the same seat number. -They want you to create a system that creates a unique ticket that has _12_ characters long string code for identification. +They want you to create a system that creates a unique ticket that is _12_ characters long string code for identification. This code begins with the `assigned_seat` followed by the `flight_id`. The rest of the code is appended by `0s`. From 1cc64ac300f3eac61ef5b07a26561709b3d36211 Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 29 Dec 2022 14:30:16 +0100 Subject: [PATCH 044/126] Updated doc-string --- .../concept/plane-tickets/.meta/exemplar.py | 18 +++++++++--------- .../concept/plane-tickets/plane_tickets.py | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/exercises/concept/plane-tickets/.meta/exemplar.py b/exercises/concept/plane-tickets/.meta/exemplar.py index 6bf9ce68a11..27995eba7bc 100644 --- a/exercises/concept/plane-tickets/.meta/exemplar.py +++ b/exercises/concept/plane-tickets/.meta/exemplar.py @@ -8,8 +8,8 @@ def generate_seat_letters(amount): """ Generate a series of seat letters for airline boarding. - :param amount: Amount of seat letters to be generated. (int) - :return: Generator that yields seat letters. + :param amount: int - amount of seat letters to be generated. + :return: generator - generator that yields seat letters. Seat letters are generated with each row having 4 seats. These should be sorted from low to high. @@ -25,8 +25,8 @@ def generate_seat_letters(amount): def generate_seats(amount): """Generate a series of seat numbers for airline boarding. - :param amount: Amount of seats to be generated. (int) - :return: Generator that generates seat numbers. (generator) + :param amount: int - Amount of seats to be generated. + :return: generator - generator that yields seat numbers. There should be no row 13 @@ -47,8 +47,8 @@ def generate_seats(amount): def assign_seats(passengers): """Assign seats to passengers. - :param passengers: A list of strings containing names of passengers. (list[str]) - :return: A dictionary type object containing the names of the passengers as keys and seat numbers as values. + :param passengers: list[str] - A list of strings containing names of passengers. + :return: dict - with the names of the passengers as keys and seat numbers as values. Example output: {"Foo": "1A", "Bar": "1B"} @@ -63,9 +63,9 @@ def assign_seats(passengers): def generate_codes(seat_numbers, flight_id): """Generate codes for a ticket. - :param seat_numbers: A list of seat numbers. (list[str]) - :param flight_id: A string containing the flight identification. (str) - :return: Generator that generates 12 character long strings. (generator[str]) + :param seat_numbers: list[str] - list of seat numbers. + :param flight_id: str - string containing the flight identification. + :return: generator - generator that yields 12 character long strings. """ diff --git a/exercises/concept/plane-tickets/plane_tickets.py b/exercises/concept/plane-tickets/plane_tickets.py index ff2e8a58eed..b0c481e46ba 100644 --- a/exercises/concept/plane-tickets/plane_tickets.py +++ b/exercises/concept/plane-tickets/plane_tickets.py @@ -3,8 +3,8 @@ def generate_seat_letters(amount): """ Generate a series of seat letters for airline boarding. - :param amount: Amount of seat letters to be generated. (int) - :return: Generator that yields seat letters. + :param amount: int - amount of seat letters to be generated. + :return: generator - generator that yields seat letters. Seat letters are generated with each row having 4 seats. These should be sorted from low to high. @@ -19,8 +19,8 @@ def generate_seat_letters(amount): def generate_seats(amount): """ Generate a series of seat numbers for airline boarding. - :param amount: Amount of seats to be generated. (int) - :return: Generator that yields seat numbers. + :param amount: int - Amount of seats to be generated. + :return: generator - generator that yields seat numbers. There should be no row 13 @@ -36,8 +36,8 @@ def generate_seats(amount): def assign_seats(passengers): """ Assign seats to passengers. - :param passengers: A list of strings containing names of passengers. (list[str]) - :return: A dictionary type object containing the names of the passengers as keys and seat numbers as values. + :param passengers: list[str] - A list of strings containing names of passengers. + :return: dict - with the names of the passengers as keys and seat numbers as values. Example output: {"Foo": "1A", "Bar": "1B"} @@ -48,8 +48,8 @@ def assign_seats(passengers): def generate_codes(seat_numbers, flight_id): """Generate codes for a ticket. - :param seat_numbers: A list of seat numbers. (list[str]) - :param flight_id: A string containing the flight identification. (str) - :return: Generator that generates 12 character long strings. (generator[str]) + :param seat_numbers: list[str] - list of seat numbers. + :param flight_id: str - string containing the flight identification. + :return: generator - generator that yields 12 character long strings. """ From cd77e99ea0d62a23ac2bea9fc4d8d813681b4c45 Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 29 Dec 2022 23:43:26 +0100 Subject: [PATCH 045/126] added ckasses as prereq and minor changes --- concepts/generators/about.md | 4 +++- config.json | 2 +- exercises/concept/plane-tickets/.meta/design.md | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/concepts/generators/about.md b/concepts/generators/about.md index a136dde5076..9a26ab55480 100644 --- a/concepts/generators/about.md +++ b/concepts/generators/about.md @@ -94,7 +94,9 @@ When `yield` is evaluated, it pauses the execution of the enclosing function and The function then _stays in scope_, and when `__next__()` is called, execution resumes until `yield` is encountered again. -Note: _Using `yield` expressions is prohibited outside of functions._ +```exercism/note +Using `yield` expressions is prohibited outside of functions. +``` ```python >>> def infinite_sequence(): diff --git a/config.json b/config.json index 47548a89015..038123f69e5 100644 --- a/config.json +++ b/config.json @@ -184,7 +184,7 @@ "name": "Plane Tickets", "uuid": "3ba3fc89-3e1b-48a5-aff0-5aeaba8c8810", "concepts": ["generators"], - "prerequisites": ["conditionals", "dicts", "lists", "loops"], + "prerequisites": ["conditionals", "dicts", "lists", "loops", "classes"], "status": "wip" }, { diff --git a/exercises/concept/plane-tickets/.meta/design.md b/exercises/concept/plane-tickets/.meta/design.md index 0323418c857..96a4cc3cc91 100644 --- a/exercises/concept/plane-tickets/.meta/design.md +++ b/exercises/concept/plane-tickets/.meta/design.md @@ -39,6 +39,7 @@ The goal of this exercise is to teach the syntax and use of `generators` in Pyth - `iteration` - `iterators` - `sequences` +- `classes` ## Resources to refer to From 9b5bd3910708da4e6bcc5499789a985d1644e08f Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 30 Dec 2022 00:13:33 +0100 Subject: [PATCH 046/126] Updated doc string --- exercises/concept/plane-tickets/.meta/exemplar.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/concept/plane-tickets/.meta/exemplar.py b/exercises/concept/plane-tickets/.meta/exemplar.py index 27995eba7bc..20a4f252ebc 100644 --- a/exercises/concept/plane-tickets/.meta/exemplar.py +++ b/exercises/concept/plane-tickets/.meta/exemplar.py @@ -6,13 +6,13 @@ def generate_seat_letters(amount): - """ Generate a series of seat letters for airline boarding. + """Generate a series of seat letters for airline boarding. :param amount: int - amount of seat letters to be generated. :return: generator - generator that yields seat letters. - Seat letters are generated with each row having 4 seats. - These should be sorted from low to high. + Seat letters are generated with from A to D. + After D it should start again with A. Example: A, B, C, D From 0f0d8c86f279969bf0f191d177f2dd330582f513 Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 30 Dec 2022 12:41:11 +0100 Subject: [PATCH 047/126] Updated, links, added blurb, various other changes --- concepts/generators/.meta/config.json | 2 +- concepts/generators/links.json | 4 + .../concept/plane-tickets/.docs/hints.md | 17 ++- .../plane-tickets/.docs/instructions.md | 5 +- .../plane-tickets/.docs/introduction.md | 136 +++++++++++++++++- .../concept/plane-tickets/.meta/exemplar.py | 2 +- .../concept/plane-tickets/plane_tickets.py | 4 +- 7 files changed, 159 insertions(+), 11 deletions(-) diff --git a/concepts/generators/.meta/config.json b/concepts/generators/.meta/config.json index 2204a700df6..6c29169d3f4 100644 --- a/concepts/generators/.meta/config.json +++ b/concepts/generators/.meta/config.json @@ -1,5 +1,5 @@ { - "blurb": "Learn about generators by assigning seats to passengers.", + "blurb": "Generator are functions that returns a lazy iterator, lazy iterator is an iterator like: list, tuple, etc. But doesn't need store its content in memory", "authors": ["J08K"], "contributors": [] } diff --git a/concepts/generators/links.json b/concepts/generators/links.json index eea7d4ae338..2f43923cf5d 100644 --- a/concepts/generators/links.json +++ b/concepts/generators/links.json @@ -6,5 +6,9 @@ { "url": "https://en.wikipedia.org/wiki/Lazy_evaluation", "description": "Wikipedia page about lazy evaluation" + }, + { + "url": "https://realpython.com/introduction-to-python-generators/", + "description": "Real python, introduction to generators and yield" } ] diff --git a/exercises/concept/plane-tickets/.docs/hints.md b/exercises/concept/plane-tickets/.docs/hints.md index 72d814b22ae..11508ee3838 100644 --- a/exercises/concept/plane-tickets/.docs/hints.md +++ b/exercises/concept/plane-tickets/.docs/hints.md @@ -1,11 +1,24 @@ # Hints -## 1. Generate an amount of seats +## 1. Generate seat letters + +- The returned value should be of _type_ `generator`. +- You can have a sequence of letters from `A` to `D` and cycle through them. +- And use `yield` to return the next letter. + +## 2. Generate an amount of seats - The returned value should be of _type_ `generator`. - Row `13` should be skipped, so go from `12` to `14`. - Keep in mind that the returned values should be ordered from low to high. `1A, 1B, 2A, ...` +- It might be good to reuse or call other functions you have already completed here. -## 2. Assign seats to passengers +## 3. Assign seats to passengers - Make sure your seat numbers do not have any space in them. +- It might be good to reuse or call other functions you have already completed here. + +## 4. Ticket codes + +- You can use `len()` to get the length of a string. +- You can use `"" * ` to repeat a string. diff --git a/exercises/concept/plane-tickets/.docs/instructions.md b/exercises/concept/plane-tickets/.docs/instructions.md index b321addbd38..550c7f3f787 100644 --- a/exercises/concept/plane-tickets/.docs/instructions.md +++ b/exercises/concept/plane-tickets/.docs/instructions.md @@ -14,6 +14,7 @@ An airplane is made of rows of seats. Each row has _4 seats_. The rows seats has the same naming: `A`, `B`, `C`, `D`. Meaning the first seat in the row is `A`, the second seat in the row is `B`, and so on. +After reaching `D` it should start again with `A`. Implement a function `generate_seat_letters()` that accepts an `int` that holds how many seat letters to be generated. The function should then return an _iterable_ of seat letters. @@ -63,10 +64,10 @@ Implement a function `assign_seats()` that accepts a `list` of passenger names. The function should then return a _dictionary_ of `passenger` as _key_, and `seat_number` as _value_. ```python ->>> passengers = ['Jerimiah', 'Eric', 'Bethaney', 'Byte', 'SqueekyBoots', 'Bob'] +>>> passengers = ['Jerimiah', 'Eric', 'Bethany', 'Byte', 'SqueekyBoots', 'Bob'] >>> assign_seats(passengers) -{'Jerimiah': '1A', 'Eric': '1B', 'Bethaney': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'} +{'Jerimiah': '1A', 'Eric': '1B', 'Bethany': '1C', 'Byte': '1D', 'SqueekyBoots': '2A', 'Bob': '2B'} ``` ## 4. Ticket codes diff --git a/exercises/concept/plane-tickets/.docs/introduction.md b/exercises/concept/plane-tickets/.docs/introduction.md index 1b557b447f8..5ab9d6d2611 100644 --- a/exercises/concept/plane-tickets/.docs/introduction.md +++ b/exercises/concept/plane-tickets/.docs/introduction.md @@ -1,5 +1,135 @@ -# Introduction +# About -A generator in Python is a _callable function_ that returns a [lazy iterator](https://en.wikipedia.org/wiki/Lazy_evaluation). +## Constructing a generator -_Lazy iterators_ are similar to iterables such as `lists`, and other types of `iterators` in Python -- but with one key difference: `generators` do not store their `values` in memory, but _generate_ their values as needed or when called. +Generators are constructed much like other looping or recursive functions, but require a [`yield` expression](#the-yield-expression), which we will explore in depth a bit later. + +An example is a function that returns the _squares_ from a given list of numbers. +As currently written, all input must be processed before any values can be returned: + +```python +>>> def squares(list_of_numbers): +... squares = [] +... for number in list_of_numbers: +... squares.append(number ** 2) +... return squares +``` + +You can convert that function into a generator like this: + +```python +>>> def squares_generator(list_of_numbers): +... for number in list_of_numbers: +... yield number ** 2 +``` + +The rationale behind this is that you use a generator when you do not need all the values _at once_. + +This saves memory and processing power, since only the value you are _currently working on_ is calculated. + +## Using a generator + +Generators may be used in place of most `iterables` in Python. This includes _functions_ or _objects_ that require an `iterable`/`iterator` as an argument. + +To use the `squares_generator()` generator: + +```python +>>> squared_numbers = squares_generator([1, 2, 3, 4]) + +>>> for square in squared_numbers: +... print(square) +... +1 +4 +9 +16 +``` + +Values within a generator can also be produced/accessed via the `next()` function. +`next()` calls the `__next__()` method of a generator object, "advancing" or evaluating the generator code up to its `yield` expression, which then "yields" or returns the value. + +```python +>>> squared_numbers = squares_generator([1, 2]) + +>>> next(squared_numbers) +1 +>>> next(squared_numbers) +4 +``` + +When a `generator` is fully consumed and has no more values to return, it throws a `StopIteration` error. + +```python +>>> next(squared_numbers) +Traceback (most recent call last): + File "", line 1, in +StopIteration +``` + +### Difference between iterables and generators + +Generators are a special sub-set of _iterators_. +`Iterators` are the mechanism/protocol that enables looping over _iterables_. +Generators and the iterators returned by common Python [`iterables`][iterables] act very similarly, but there are some important differences to note: + +- Generators are _one-way_; there is no "backing up" to a previous value. + +- Iterating over generators consume the returned values; no resetting. + +- Generators (_being lazily evaluated_) are not sortable and can not be reversed. + +- Generators do _not_ have `indexes`, so you can't reference a previous or future value using addition or subtraction. + +- Generators cannot be used with the `len()` function. + +- Generators can be _finite_ or _infinite_, be careful when collecting all values from an _infinite_ generator. + +## The yield expression + +The [yield expression][yield expression] is very similar to the `return` expression. + +_Unlike_ the `return` expression, `yield` gives up values to the caller at a _specific point_, suspending evaluation/return of any additional values until they are requested. + +When `yield` is evaluated, it pauses the execution of the enclosing function and returns any values of the function _at that point in time_. + +The function then _stays in scope_, and when `__next__()` is called, execution resumes until `yield` is encountered again. + +```exercism/note +Using `yield` expressions is prohibited outside of functions. +``` + +```python +>>> def infinite_sequence(): +... current_number = 0 +... while True: +... yield current_number +... current_number += 1 + +>>> lets_try = infinite_sequence() +>>> lets_try.__next__() +0 +>>> lets_try.__next__() +1 +``` + +## Why generators? + +Generators are useful in a lot of applications. + +When working with a large collection, you might not want to put all of its values into `memory`. +A generator can be used to work on larger data piece-by-piece, saving memory and improving performance. + +Generators are also very helpful when a process or calculation is _complex_, _expensive_, or _infinite_: + +```python +>>> def infinite_sequence(): +... current_number = 0 +... while True: +... yield current_number +... current_number += 1 +``` + +Now whenever `__next__()` is called on the `infinite_sequence` object, it will return the _previous number_ + 1. + +[iterables]: https://wiki.python.org/moin/Iterator +[yield expression]: https://docs.python.org/3.11/reference/expressions.html#yield-expressions diff --git a/exercises/concept/plane-tickets/.meta/exemplar.py b/exercises/concept/plane-tickets/.meta/exemplar.py index 20a4f252ebc..9a3d7024076 100644 --- a/exercises/concept/plane-tickets/.meta/exemplar.py +++ b/exercises/concept/plane-tickets/.meta/exemplar.py @@ -11,7 +11,7 @@ def generate_seat_letters(amount): :param amount: int - amount of seat letters to be generated. :return: generator - generator that yields seat letters. - Seat letters are generated with from A to D. + Seat letters are generated from A to D. After D it should start again with A. Example: A, B, C, D diff --git a/exercises/concept/plane-tickets/plane_tickets.py b/exercises/concept/plane-tickets/plane_tickets.py index b0c481e46ba..4399791b223 100644 --- a/exercises/concept/plane-tickets/plane_tickets.py +++ b/exercises/concept/plane-tickets/plane_tickets.py @@ -6,8 +6,8 @@ def generate_seat_letters(amount): :param amount: int - amount of seat letters to be generated. :return: generator - generator that yields seat letters. - Seat letters are generated with each row having 4 seats. - These should be sorted from low to high. + Seat letters are generated from A to D. + After D it should start again with A. Example: A, B, C, D From bf45569950d3e638b90f005716b014f9126936fc Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 30 Dec 2022 21:08:53 +0100 Subject: [PATCH 048/126] fix --- exercises/concept/plane-tickets/.docs/instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/plane-tickets/.docs/instructions.md b/exercises/concept/plane-tickets/.docs/instructions.md index 550c7f3f787..b22a84f2213 100644 --- a/exercises/concept/plane-tickets/.docs/instructions.md +++ b/exercises/concept/plane-tickets/.docs/instructions.md @@ -45,7 +45,7 @@ Here is an example: Many airlines do not have _row_ number 13 on their flights, due to superstition amongst passengers. Conda Airlines also follows this convention, so make sure you _don't_ generate seats for _row_ number 13. -Implement a function `generate_seats()` that accepts an `int` that accepts an `int` that holds how many seats to be generated. +Implement a function `generate_seats()` that accepts an `int` that holds how many seats to be generated. The function should then return an _iterable_ of seats given. ```python From cb75dfa7dfb936f75dbd44bffdc08767ecf42054 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Tue, 10 Jan 2023 23:09:28 +0100 Subject: [PATCH 049/126] Update links.json --- concepts/generators/links.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/concepts/generators/links.json b/concepts/generators/links.json index 2f43923cf5d..972bbe7ae97 100644 --- a/concepts/generators/links.json +++ b/concepts/generators/links.json @@ -1,7 +1,7 @@ [ { - "url": "https://docs.python.org/3.11/reference/expressions.html#yield-expressions", - "description": "Official Python 3.11 docs for the yield expression." + "url": "https://docs.python.org/3.10/reference/expressions.html#yield-expressions", + "description": "Official Python 3.10 docs for the yield expression." }, { "url": "https://en.wikipedia.org/wiki/Lazy_evaluation", From 89738cea0ccd5820c7fd1fffad98672bae06ba03 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen <62411302+safwansamsudeen@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:52:42 +0530 Subject: [PATCH 050/126] Write approaches for Yacht (#3420) * write approaches for yacht * improve wording, structure, and code * update based on bethany's changes * Apply suggestions from code review Co-authored-by: BethanyG * improve snippets, add spm approach * Apply suggestions from code review --------- Co-authored-by: BethanyG --- .../practice/yacht/.approaches/config.json | 28 +++++++ .../yacht/.approaches/functions/content.md | 72 +++++++++++++++++ .../yacht/.approaches/functions/snippet.txt | 8 ++ .../yacht/.approaches/if-structure/content.md | 50 ++++++++++++ .../.approaches/if-structure/snippet.txt | 8 ++ .../yacht/.approaches/introduction.md | 77 +++++++++++++++++++ .../structural-pattern-matching/content.md | 55 +++++++++++++ .../structural-pattern-matching/snippet.txt | 8 ++ 8 files changed, 306 insertions(+) create mode 100644 exercises/practice/yacht/.approaches/config.json create mode 100644 exercises/practice/yacht/.approaches/functions/content.md create mode 100644 exercises/practice/yacht/.approaches/functions/snippet.txt create mode 100644 exercises/practice/yacht/.approaches/if-structure/content.md create mode 100644 exercises/practice/yacht/.approaches/if-structure/snippet.txt create mode 100644 exercises/practice/yacht/.approaches/introduction.md create mode 100644 exercises/practice/yacht/.approaches/structural-pattern-matching/content.md create mode 100644 exercises/practice/yacht/.approaches/structural-pattern-matching/snippet.txt diff --git a/exercises/practice/yacht/.approaches/config.json b/exercises/practice/yacht/.approaches/config.json new file mode 100644 index 00000000000..86d37075b8b --- /dev/null +++ b/exercises/practice/yacht/.approaches/config.json @@ -0,0 +1,28 @@ +{ + "introduction": { + "authors": ["safwansamsudeen"] + }, + "approaches": [ + { + "uuid": "3593cfe3-5cab-4141-b0a2-329148a66bb6", + "slug": "functions", + "title": "Lambdas with Functions", + "blurb": "Use lambdas with functions", + "authors": ["safwansamsudeen"] + }, + { + "uuid": "eccd1e1e-6c88-4823-9b25-944eccaa92e7", + "slug": "if-structure", + "title": "If structure", + "blurb": "Use an if structure", + "authors": ["safwansamsudeen"] + }, + { + "uuid": "72079791-e51f-4825-ad94-3b7516c631cc", + "slug": "structural-pattern-matching", + "title": "Structural Pattern Matching", + "blurb": "Use structural pattern matching", + "authors": ["safwansamsudeen"] + } + ] +} diff --git a/exercises/practice/yacht/.approaches/functions/content.md b/exercises/practice/yacht/.approaches/functions/content.md new file mode 100644 index 00000000000..2c6bfe527df --- /dev/null +++ b/exercises/practice/yacht/.approaches/functions/content.md @@ -0,0 +1,72 @@ +## Approach: Using Lambdas with Functions +Each bit of functionality for each category can be encoded in an anonymous function (otherwise known as a [`lambda` expression][lambda] or lambda form), and the constant name set to that function. + +In `score`, we call the category (as it now points to a function) passing in `dice` as an argument. + +```python +def digits(num): + return lambda dice: dice.count(num) * num + +YACHT = lambda dice: 50 if len(set(dice)) == 1 else 0 +ONES = digits(1) +TWOS = digits(2) +THREES = digits(3) +FOURS = digits(4) +FIVES = digits(5) +SIXES = digits(6) +FULL_HOUSE = lambda dice: sum(dice) if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3] else 0 +FOUR_OF_A_KIND = lambda dice: 4 * dice[1] if dice[0] == dice[3] or dice[1] == dice[4] else 0 +LITTLE_STRAIGHT = lambda dice: 30 if sorted(dice) == [1, 2, 3, 4, 5] else 0 +BIG_STRAIGHT = lambda dice: 30 if sorted(dice) == [2, 3, 4, 5, 6] else 0 +CHOICE = sum + +def score(dice, category): + return category(dice) +``` + + +Instead of setting each constant in `ONES` through `SIXES` to a separate function, we create a function `digits` that returns a function, using [closures][closures] transparently. + +For `LITTLE_STRAIGHT` and `BIG_STRAIGHT`, we first sort the dice and then check it against the hard-coded value. +Another way to solve this would be to check if `sum(dice) == 20 and len(set(dice)) == 5` (15 in `LITTLE_STRAIGHT`). +In `CHOICE`, `lambda number : sum(number)` is shortened to just `sum`. + +In `FULL_HOUSE`, we create a `set` to remove the duplicates and check the set's length along with the individual counts. +For `FOUR_OF_A_KIND`, we check if the first and the fourth element are the same or the second and the last element are the same - if so, there are (at least) four of the same number in the array. + +This solution is a succinct way to solve the exercise, although some of the one-liners can get a little long and hard to read. +Additionally, [PEP8][pep8] does not recommend assigning constant or variable names to `lambda` expressions, so it is a better practice to use `def`: +```python +def digits(num): + return lambda dice: dice.count(num) * num + +def YACHT(dice): return 50 if len(set(dice)) == 1 else 0 +ONES = digits(1) +TWOS = digits(2) +THREES = digits(3) +FOURS = digits(4) +FIVES = digits(5) +SIXES = digits(6) +def FULL_HOUSE(dice): return sum(dice) if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3] else 0 +def FOUR_OF_A_KIND(dice): return 4 * sorted(dice)[1] if len(set(dice)) < 3 and dice.count(dice[0]) in (1, 4, 5) else 0 +def LITTLE_STRAIGHT(dice): return 30 if sorted(dice) == [1, 2, 3, 4, 5] else 0 +def BIG_STRAIGHT(dice): return 30 if sorted(dice) == [2, 3, 4, 5, 6] else 0 +CHOICE = sum + +def score(dice, category): + return category(dice) +``` + +As you can see from the examples, the [ternary operator][ternary-operator] (_or ternary form_) is crucial in solving the exercise using one liners. +As functions are being used, it might be a better strategy to spread the code over multiple lines to improve readability. +```python +def YACHT(dice): + if dice.count(dice[0]) == len(dice): + return 50 + return 0 +``` + +[closures]: https://www.programiz.com/python-programming/closure +[ternary-operator]: https://www.tutorialspoint.com/ternary-operator-in-python +[lambda]: https://docs.python.org/3/howto/functional.html?highlight=lambda#small-functions-and-the-lambda-expression +[pep8]: https://peps.python.org/pep-0008/ \ No newline at end of file diff --git a/exercises/practice/yacht/.approaches/functions/snippet.txt b/exercises/practice/yacht/.approaches/functions/snippet.txt new file mode 100644 index 00000000000..34d270ad895 --- /dev/null +++ b/exercises/practice/yacht/.approaches/functions/snippet.txt @@ -0,0 +1,8 @@ +def digits(num): + return lambda dice: dice.count(num) * num +YACHT = lambda x: 50 if x.count(x[0]) == len(x) else 0 +ONES = digits(1) +FULL_HOUSE = lambda x: sum(x) if len(set(x)) == 2 and x.count(x[0]) in [2, 3] else 0 +LITTLE_STRAIGHT = lambda x: 30 if sorted(x) == [1, 2, 3, 4, 5] else 0 +def score(dice, category): + return category(dice) \ No newline at end of file diff --git a/exercises/practice/yacht/.approaches/if-structure/content.md b/exercises/practice/yacht/.approaches/if-structure/content.md new file mode 100644 index 00000000000..581f31d1928 --- /dev/null +++ b/exercises/practice/yacht/.approaches/if-structure/content.md @@ -0,0 +1,50 @@ +# If structure + +The constants here can be set to random, null, or numeric values, and an `if` structure inside the `score` function can determine the code to be executed. + +As one-liners aren't necessary here, we can spread out the code to make it look neater: +```python +ONES = 1 +TWOS = 2 +THREES = 3 +FOURS = 4 +FIVES = 5 +SIXES = 6 +FULL_HOUSE = 'FULL_HOUSE' +FOUR_OF_A_KIND = 'FOUR_OF_A_KIND' +LITTLE_STRAIGHT = 'LITTLE_STRAIGHT' +BIG_STRAIGHT = 'BIG_STRAIGHT' +CHOICE = 'CHOICE' +YACHT = 'YACHT' + +def score(dice, category): + if category in (1,2,3,4,5,6): + return dice.count(category) * category + elif category == 'FULL_HOUSE': + if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3]: + return sum(dice) or 0 + elif category == 'FOUR_OF_A_KIND': + if dice[0] == dice[3] or dice[1] == dice[4]: + return dice[1] * 4 or 0 + elif category == 'LITTLE_STRAIGHT': + if sorted(dice) == [1, 2, 3, 4, 5]: + return 30 or 0 + elif category == 'BIG_STRAIGHT': + if sorted(dice) == [2, 3, 4, 5, 6]: + return 30 or 0 + elif category == 'YACHT': + if all(num == dice[0] for num in dice): + return 50 + elif category == 'CHOICE': + return sum(dice) + return 0 +``` +Note that the code inside the `if` statements themselves can differ, but the key idea here is to use `if` and `elif` to branch out the code, and return `0` at the end if nothing else has been returned. +The `if` condition itself can be different, with people commonly checking if `category == ONES` as opposed to `category == 'ONES'` (or whatever the dummy value is). + +This may not be an ideal way to solve the exercise, as the code is rather long and convoluted. +However, it is a valid (_and fast_) solution. +Using [structural pattern matching][structural pattern matching], introduced in Python 3.10, could shorten and clarify the code in this situation. +Pulling some logic out of the `score` function and into additional "helper" functions could also help. + +[structural pattern matching]: https://peps.python.org/pep-0636/ \ No newline at end of file diff --git a/exercises/practice/yacht/.approaches/if-structure/snippet.txt b/exercises/practice/yacht/.approaches/if-structure/snippet.txt new file mode 100644 index 00000000000..fb590cc155b --- /dev/null +++ b/exercises/practice/yacht/.approaches/if-structure/snippet.txt @@ -0,0 +1,8 @@ +ONES = 1 +YACHT = 'YACHT' +def score(dice, category): + if category == 'ONES': + ... + elif category == 'FULL_HOUSE': + ... + return 0 \ No newline at end of file diff --git a/exercises/practice/yacht/.approaches/introduction.md b/exercises/practice/yacht/.approaches/introduction.md new file mode 100644 index 00000000000..9717760637d --- /dev/null +++ b/exercises/practice/yacht/.approaches/introduction.md @@ -0,0 +1,77 @@ +# Introduction +Yacht in Python can be solved in many ways. The most intuitive approach is to use an `if` structure. +Alternatively, you can create functions and set their names to the constant names. + +## General guidance +The main thing in this exercise is to map a category (_here defined as constants in the stub file_) to a function or a standalone piece of code. +While mapping generally reminds us of dictionaries, here the constants are global. +This indicates that the most idiomatic approach is not using a `dict`. +Adhering to the principles of DRY is important - don't repeat yourself if you can help it, especially in the `ONES` through `SIXES` categories! + +## Approach: functions +Each bit of functionality for each category can be encoded in a function, and the constant name set to that function. +This can be done by assigning the constant name to a `lambda` or creating a one-line function using the constant as a function name. +```python +```python +def digits(num): + return lambda dice: dice.count(num) * num +YACHT = lambda dice: 50 if dice.count(dice[0]) == len(dice) else 0 +ONES = digits(1) +TWOS = digits(2) +THREES = digits(3) +FOURS = digits(4) +FIVES = digits(5) +SIXES = digits(6) +FULL_HOUSE = lambda dice: sum(dice) if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3] else 0 +FOUR_OF_A_KIND = lambda dice: 4 * dice[1] if dice[0] == dice[3] or dice[1] == dice[4] else 0 +LITTLE_STRAIGHT = lambda dice: 30 if sorted(dice) == [1, 2, 3, 4, 5] else 0 +BIG_STRAIGHT = lambda dice: 30 if sorted(dice) == [2, 3, 4, 5, 6] else 0 +CHOICE = sum +def score(dice, category): + return category(dice) +``` +This is a very succinct way to solve the exercise, although some one-liners get a little long. +For more information on this approach, read [this document][approach-functions]. + +## Approach: if structure +The constants can be set to random, null, or numeric values, and an `if` structure inside `score` determines the code to be executed. +As one-liners aren't necessary here, we can spread out the code to make it look neater: +```python +ONES = 1 +TWOS = 2 +THREES = 3 +FOURS = 4 +FIVES = 5 +SIXES = 6 +FULL_HOUSE = 'FULL_HOUSE' +FOUR_OF_A_KIND = 'FOUR_OF_A_KIND' +LITTLE_STRAIGHT = 'LITTLE_STRAIGHT' +BIG_STRAIGHT = 'BIG_STRAIGHT' +CHOICE = 'CHOICE' +YACHT = 'YACHT' +def score(dice, category): + if category in (1,2,3,4,5,6): + return dice.count(category) * category + elif category == 'FULL_HOUSE': + if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3]: + return sum(dice) or 0 + elif category == 'FOUR_OF_A_KIND': + if dice[0] == dice[3] or dice[1] == dice[4]: + return dice[1] * 4 or 0 + elif category == 'LITTLE_STRAIGHT': + if sorted(dice) == [1, 2, 3, 4, 5]: + return 30 or 0 + elif category == 'BIG_STRAIGHT': + if sorted(dice) == [2, 3, 4, 5, 6]: + return 30 or 0 + elif category == 'YACHT': + if all(num == dice[0] for num in dice): + return 50 + elif category == 'CHOICE': + return sum(dice) + return 0 +``` +Read more on this approach [here][approach-if-structure]. + +[approach-functions]: https://exercism.org/tracks/python/exercises/yacht/approaches/functions +[approach-if-structure]: https://exercism.org/tracks/python/exercises/yacht/approaches/if-structure diff --git a/exercises/practice/yacht/.approaches/structural-pattern-matching/content.md b/exercises/practice/yacht/.approaches/structural-pattern-matching/content.md new file mode 100644 index 00000000000..b49bb6340bd --- /dev/null +++ b/exercises/practice/yacht/.approaches/structural-pattern-matching/content.md @@ -0,0 +1,55 @@ +# Structural Pattern Matching + +Another very interesting approach is to use [structural pattern matching][structural pattern matching]. +Existing in Python since 3.10, this feature allows for neater code than traditional if structures. + +By and large, we reuse the code from the [if structure approach][approach-if-structure]. +We set the constants to random values and check for them in the `match` structure. +`category` is the "subject", and in every other line, we check it against a "pattern". +```python +ONES = 1 +TWOS = 2 +THREES = 3 +FOURS = 4 +FIVES = 5 +SIXES = 6 +FULL_HOUSE = 'FULL_HOUSE' +FOUR_OF_A_KIND = 'FOUR_OF_A_KIND' +LITTLE_STRAIGHT = 'LITTLE_STRAIGHT' +BIG_STRAIGHT = 'BIG_STRAIGHT' +CHOICE = 'CHOICE' +YACHT = 'YACHT' + +def score(dice, category): + match category: + case 1 | 2 | 3 | 4 | 5 | 6: + return dice.count(category) * category + case 'FULL_HOUSE' if len(set(dice)) == 2 and dice.count(dice[0]) in [2, 3]: + return sum(dice) + case 'FOUR_OF_A_KIND' if dice[0] == dice[3] or dice[1] == dice[4]: + return dice[1] * 4 + case 'LITTLE_STRAIGHT' if sorted(dice) == [1, 2, 3, 4, 5]: + return 30 + case 'BIG_STRAIGHT' if sorted(dice) == [2, 3, 4, 5, 6]: + return 30 + case 'YACHT' if all(num == dice[0] for num in dice): + return 50 + case 'CHOICE': + return sum(dice) + case _: + return 0 +``` +For the first pattern, we utilize "or patterns", using the `|` operator. +This checks whether the subject is any of the provided patterns. + +In the next five patterns, we check an additional condition along with the pattern matching. +Finally, we use the wildcard operator `_` to match anything. +As the compiler checks the patterns (`case`s) in order, `return 0` will be executed if none of the other patterns match. + +Note that the conditions might differ, but the patterns must have hard coded values - that is, you can't say `case ONES ...` instead of `case 1 ...`. +This will capture the category and lead to unexpected behavior. + +This code is much clenaer than the corresponding `if` structure code. + +[structural pattern matching]: https://peps.python.org/pep-0636/ +[approach-if-structure]: https://exercism.org/tracks/python/exercises/yacht/approaches/if-structure \ No newline at end of file diff --git a/exercises/practice/yacht/.approaches/structural-pattern-matching/snippet.txt b/exercises/practice/yacht/.approaches/structural-pattern-matching/snippet.txt new file mode 100644 index 00000000000..4ed99824d8e --- /dev/null +++ b/exercises/practice/yacht/.approaches/structural-pattern-matching/snippet.txt @@ -0,0 +1,8 @@ +ONES = 1 +YACHT = 'YACHT' +def score(dice, category): + match category: + case 1 | 2 | 3 | 4 | 5 | 6: + return dice.count(category) * category + case _: + return 0 \ No newline at end of file From c2e991afa42befbd1bf96abb1babbeddd93fa7b9 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen <62411302+safwansamsudeen@users.noreply.github.com> Date: Mon, 5 Jun 2023 17:57:00 +0530 Subject: [PATCH 051/126] remove duplicate line --- exercises/practice/yacht/.approaches/introduction.md | 1 - 1 file changed, 1 deletion(-) diff --git a/exercises/practice/yacht/.approaches/introduction.md b/exercises/practice/yacht/.approaches/introduction.md index 9717760637d..5a37d16881b 100644 --- a/exercises/practice/yacht/.approaches/introduction.md +++ b/exercises/practice/yacht/.approaches/introduction.md @@ -12,7 +12,6 @@ Adhering to the principles of DRY is important - don't repeat yourself if you ca Each bit of functionality for each category can be encoded in a function, and the constant name set to that function. This can be done by assigning the constant name to a `lambda` or creating a one-line function using the constant as a function name. ```python -```python def digits(num): return lambda dice: dice.count(num) * num YACHT = lambda dice: 50 if dice.count(dice[0]) == len(dice) else 0 From cc3d9f2b21e739e45c2104a0f9a7e31061e44245 Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 29 Dec 2022 21:33:09 +0100 Subject: [PATCH 052/126] Started --- .../binary-octal-hexdecimal/.meta/config.json | 4 + concepts/binary-octal-hexdecimal/about.md | 252 ++++++++++++++++++ .../binary-octal-hexdecimal/introduction.md | 9 + concepts/binary-octal-hexdecimal/links.json | 10 + config.json | 5 + 5 files changed, 280 insertions(+) create mode 100644 concepts/binary-octal-hexdecimal/.meta/config.json create mode 100644 concepts/binary-octal-hexdecimal/about.md create mode 100644 concepts/binary-octal-hexdecimal/introduction.md create mode 100644 concepts/binary-octal-hexdecimal/links.json diff --git a/concepts/binary-octal-hexdecimal/.meta/config.json b/concepts/binary-octal-hexdecimal/.meta/config.json new file mode 100644 index 00000000000..80a508e68bd --- /dev/null +++ b/concepts/binary-octal-hexdecimal/.meta/config.json @@ -0,0 +1,4 @@ +{ + "blurb": "Other numerical system in python, binary (0b11), octal (0o71), and hex (0xFF)", + "authors": ["BethanyG", "meatball133"] +} diff --git a/concepts/binary-octal-hexdecimal/about.md b/concepts/binary-octal-hexdecimal/about.md new file mode 100644 index 00000000000..87c168c2cb3 --- /dev/null +++ b/concepts/binary-octal-hexdecimal/about.md @@ -0,0 +1,252 @@ +# binary, otal, hexdecimal + +Binary, octal, and hexdecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. +Binary is base 2, octal is base 8 and hexdecimal is base 16. +Normal integers are base 10 in python. +Binary, octal, and hexdecimal are all a subset of integers. +Which means that they can only represent whole numbers and support all the operations that we can do with integers. + +## Binary + +[Binary][binary] is a base 2 numeral system. +The most common numeral system is base 10. +So the digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. +Binary is base 2, so the digits are 0 and 1. +It is used to represent the on and off states of a computer. +Binary can create all the numbers that we use in base 10. + +A snipet from the base 2 system looks like this, although it contuines infinitely and doesn't stop at 128: + +| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | +| -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | +| 2 \*\* 7 | 2 \*\* 6 | 2 \*\* 5 | 2 \*\* 4 | 2 \*\* 3 | 2 \*\* 2 | 2 \*\* 1 | 2 \*\* 0 | + +So if we want to represent the number 6, it would in binary be: 110 + +| Place value | 4 | 2 | 1 | +| ------------- | --- | --- | --- | +| Binary number | 1 | 1 | 0 | + +And the operation would be: `4 + 2 + 0 = 6` + +Another example: 19 + +| Place value | 16 | 8 | 4 | 2 | 1 | +| ------------- | --- | --- | --- | --- | --- | +| Binary number | 1 | 0 | 0 | 1 | 1 | + +The binary number would be: 10011 +And the operation would be: `16 + 0 + 0 + 2 + 1 = 19` + +## Binary in Python + +In Python, we can represent binary numbers using the `0b` prefix. +If we write `0b10011`, Python will interpret it as a binary number and convert it to base 10. + +```python +# 0b10011 +>>> 0b10011 +19 + +>>> type(0b10011) + +``` + +Binary in python is a subset of integers, therefore it will act like an integer. + +If you give have a number which is not in the binary system, it will raise a `SyntaxError`. + +```python +Traceback (most recent call last): + File "c:\binary.py", line 1, in + 0b10211 +SyntaxError: invalid digit '2' in binary literal +``` + +### Operations with binary numbers + +Which means that we can do all the operations that we can do with integers. + +```python +# addition +>>> 0b10011 + 0b10011 +38 + +# multiplication +>>> 0b10011 * 0b10011 +361 +``` + +We can do operations with integers and binary numbers. + +```python +# 0b10011 +>>> 0b10011 + 19 +38 +``` + +### Representing binary numbers + +Since python will automaticly convert binary to int, do we have to use the `bin()` function. +If we want to represent a binary number. +`bin()` will return a string with the prefix `0b`. + +```python +# 0b10011 +>>> bin(0b10011) +'0b10011' +``` + +To convert a binary number to an integer, we can use the `int()` function, and pass the string and the base as arguments. + +```python +# 19 +>>> int("0b10011", 2) +``` + +Giving the wrong base will raise a `ValueError`. + +```python +Traceback (most recent call last): + File "c:\Users\carlh\fwfa.py", line 4, in + int("0b10011", 3) +ValueError: invalid literal for int() with base 3: '0b10011' +``` + +### Convering int to binary + +We can also convert an integer to binary using the `bin()` function. + +```python +# 0b10011 +>>> bin(19) +'0b10011' +``` + +### Binary methods + +There are also [methods][numeral-systems] that we can use on binary numbers. + +#### `.bit_length()` + +`.bit_length()` will return the number of bits that are needed to represent the number. +So for example `0b10011` will return 5. + +```python +>>> 0b11011.bit_length() +5 +``` + +#### `.count()` + +```exercism/note +`.count()` requires Python 3.10+. +If you are using the online editor then you don't need to worry about this. +``` + +`.bit_count()` will return the number of ones in the binary number. +So for example `bit_count` will return 3. + +```python +>>> 0b11011.bit_count() +4 +``` + +## Octal + +[Octal][octal] is a base 8 numeral system. +Meaning that the digits are 0, 1, 2, 3, 4, 5, 6, 7. + +In python, we can represent octal numbers using the `0o` prefix. +As with binary, python will automaticly convert octal to int. + +```python +# 0o123 +>>> 0o123 +83 +``` + +As with binary you can do all the operations that you can do with integers and giving a number which is not in the octal system will raise a `SyntaxError`. + +### Representing octal numbers + +To represent an octal number, we can use the `oct()` function. + +```python +# 0o123 +>>> oct(0o123) +'0o123' +``` + +To convert an octal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. + +```python +# 83 +>>> int("0o123", 8) +83 +``` + +As with binary, giving the wrong base will raise a `ValueError`. + +### Convering int to octal + +We can also convert an integer to binary using the `oct()` function. + +```python +# 0o123 +>>> oct(83) +'0o123' +``` + +### hexdecimal + +[Hexdecimal][hexdecimal] is a base 16 numeral system. +Meaning that the digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. +A is 10, B is 11, C is 12, D is 13, E is 14, F is 15. + +In python, we can represent hexdecimal numbers using the `0x` prefix. +As with binary and octal, python will automaticly convert hexdecimal to int. + +```python +# 0x123 +>>> 0x123 +291 +``` + +As with binary and octal you can do all the operations that you can do with integers and giving a number which is not in the hex system will raise a `SyntaxError`. + +### Representing hexdecimal numbers + +To represent an hexdecimal number, we can use the `hex()` function. + +```python +# 0x123 +>>> hex(0x123) +'0x123' +``` + +To convert an hexdecimal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. + +```python +# 291 +>>> int("0x123", 16) +291 +``` + +As with binary and octal, giving the wrong base will raise a `ValueError`. + +### Convering int to hexdecimal + +We can also convert an integer to binary using the `hex()` function. + +```python +# 0x123 +>>> hex(291) +'0x123' +``` + +[binary]: https://en.wikipedia.org/wiki/Binary_number +[octal]: https://en.wikipedia.org/wiki/Octal +[hexdecimal]: https://en.wikipedia.org/wiki/Hexadecimal +[numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system +[methods-int]: https://docs.python.org/3/library/stdtypes.html#additional-methods-on-integer-types diff --git a/concepts/binary-octal-hexdecimal/introduction.md b/concepts/binary-octal-hexdecimal/introduction.md new file mode 100644 index 00000000000..0dba132a24b --- /dev/null +++ b/concepts/binary-octal-hexdecimal/introduction.md @@ -0,0 +1,9 @@ +# binary, otal, hexdecimal + +Binary, octal, and hexdecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. +Binary is base 2, octal is base 8 and hexdecimal is base 16. +Normal integers are base 10 in python. +Binary, octal, and hexdecimal are all a subset of integers. +Which means that they can only represent whole numbers and support all the operations that we can do with integers. + +[numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system diff --git a/concepts/binary-octal-hexdecimal/links.json b/concepts/binary-octal-hexdecimal/links.json new file mode 100644 index 00000000000..1e7d3acd599 --- /dev/null +++ b/concepts/binary-octal-hexdecimal/links.json @@ -0,0 +1,10 @@ +[ + { + "url": "https://towardsdatascience.com/binary-hex-and-octal-in-python-20222488cee1", + "description": "Binary, octal, hex in python" + }, + { + "url": "https://en.wikipedia.org/wiki/Numeral_system", + "description": "Numeral system" + } +] \ No newline at end of file diff --git a/config.json b/config.json index 038123f69e5..17be12403a1 100644 --- a/config.json +++ b/config.json @@ -2235,6 +2235,11 @@ "slug": "binary-data", "name": "Binary Data" }, + { + "uuid": "78dbf248-a1e5-48cb-ba53-def4d92bf2a8", + "slug": "binary-octal-hexdecimal", + "name": "Binary, Octal, and Hexdecimal" + }, { "uuid": "f8e96e60-f746-4c7a-8dc9-df6b77eefdfa", "slug": "bitflags", From b0ce921e5b57bad08b543b1da658dfbec956713f Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 29 Dec 2022 21:34:39 +0100 Subject: [PATCH 053/126] fix --- concepts/binary-octal-hexdecimal/links.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/binary-octal-hexdecimal/links.json b/concepts/binary-octal-hexdecimal/links.json index 1e7d3acd599..8826182cd48 100644 --- a/concepts/binary-octal-hexdecimal/links.json +++ b/concepts/binary-octal-hexdecimal/links.json @@ -7,4 +7,4 @@ "url": "https://en.wikipedia.org/wiki/Numeral_system", "description": "Numeral system" } -] \ No newline at end of file +] From 5632f6e89f5fe53836b8c5f94258f1c12b79f531 Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 30 Dec 2022 12:07:17 +0100 Subject: [PATCH 054/126] Fixes --- concepts/binary-octal-hexdecimal/about.md | 64 ++++++++++------------- 1 file changed, 28 insertions(+), 36 deletions(-) diff --git a/concepts/binary-octal-hexdecimal/about.md b/concepts/binary-octal-hexdecimal/about.md index 87c168c2cb3..e3052de9cd2 100644 --- a/concepts/binary-octal-hexdecimal/about.md +++ b/concepts/binary-octal-hexdecimal/about.md @@ -1,21 +1,21 @@ -# binary, otal, hexdecimal +# binary, octal, hexadecimal -Binary, octal, and hexdecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. -Binary is base 2, octal is base 8 and hexdecimal is base 16. +Binary, octal, and hexadecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. +Binary is base 2, octal is base 8 and hexadecimal is base 16. Normal integers are base 10 in python. -Binary, octal, and hexdecimal are all a subset of integers. +Binary, octal, and hexadecimal are all a subset of integers. Which means that they can only represent whole numbers and support all the operations that we can do with integers. ## Binary [Binary][binary] is a base 2 numeral system. The most common numeral system is base 10. -So the digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. +In the base 10 numeral system so are the digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Binary is base 2, so the digits are 0 and 1. It is used to represent the on and off states of a computer. Binary can create all the numbers that we use in base 10. -A snipet from the base 2 system looks like this, although it contuines infinitely and doesn't stop at 128: +A snippet from the base 2 system looks like this, although it continues infinitely and doesn't stop at 128: | 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 | | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | @@ -54,7 +54,7 @@ If we write `0b10011`, Python will interpret it as a binary number and convert i Binary in python is a subset of integers, therefore it will act like an integer. -If you give have a number which is not in the binary system, it will raise a `SyntaxError`. +If you have a number which is not in the binary system, it will raise a `SyntaxError`. ```python Traceback (most recent call last): @@ -65,7 +65,7 @@ SyntaxError: invalid digit '2' in binary literal ### Operations with binary numbers -Which means that we can do all the operations that we can do with integers. +Since binary is a subset of integers, we can do all the operations that we can do with integers. ```python # addition @@ -77,22 +77,20 @@ Which means that we can do all the operations that we can do with integers. 361 ``` -We can do operations with integers and binary numbers. +We can do also have operations with both integers and binary numbers. ```python -# 0b10011 >>> 0b10011 + 19 38 ``` ### Representing binary numbers -Since python will automaticly convert binary to int, do we have to use the `bin()` function. +Since python will automatically convert binary to `int`, do we have to use the `bin()` function. If we want to represent a binary number. -`bin()` will return a string with the prefix `0b`. +`bin()` will return a `string` with the prefix `0b`. ```python -# 0b10011 >>> bin(0b10011) '0b10011' ``` @@ -100,11 +98,11 @@ If we want to represent a binary number. To convert a binary number to an integer, we can use the `int()` function, and pass the string and the base as arguments. ```python -# 19 >>> int("0b10011", 2) +19 ``` -Giving the wrong base will raise a `ValueError`. +Giving the wrong base will raise a `ValueError`: ```python Traceback (most recent call last): @@ -113,7 +111,7 @@ Traceback (most recent call last): ValueError: invalid literal for int() with base 3: '0b10011' ``` -### Convering int to binary +### Converting int to binary We can also convert an integer to binary using the `bin()` function. @@ -144,7 +142,7 @@ So for example `0b10011` will return 5. If you are using the online editor then you don't need to worry about this. ``` -`.bit_count()` will return the number of ones in the binary number. +`.bit_count()` will return the number of **ones** in the binary number. So for example `bit_count` will return 3. ```python @@ -155,10 +153,10 @@ So for example `bit_count` will return 3. ## Octal [Octal][octal] is a base 8 numeral system. -Meaning that the digits are 0, 1, 2, 3, 4, 5, 6, 7. +Meaning that the digits are: 0, 1, 2, 3, 4, 5, 6, 7. In python, we can represent octal numbers using the `0o` prefix. -As with binary, python will automaticly convert octal to int. +As with binary, python will automatically convert octal to int. ```python # 0o123 @@ -173,7 +171,6 @@ As with binary you can do all the operations that you can do with integers and g To represent an octal number, we can use the `oct()` function. ```python -# 0o123 >>> oct(0o123) '0o123' ``` @@ -181,72 +178,67 @@ To represent an octal number, we can use the `oct()` function. To convert an octal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. ```python -# 83 >>> int("0o123", 8) 83 ``` As with binary, giving the wrong base will raise a `ValueError`. -### Convering int to octal +### Converting int to octal We can also convert an integer to binary using the `oct()` function. ```python -# 0o123 >>> oct(83) '0o123' ``` -### hexdecimal +### hexadecimal -[Hexdecimal][hexdecimal] is a base 16 numeral system. +[Hexadecimal][hexadecimal] is a base 16 numeral system. Meaning that the digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. A is 10, B is 11, C is 12, D is 13, E is 14, F is 15. -In python, we can represent hexdecimal numbers using the `0x` prefix. -As with binary and octal, python will automaticly convert hexdecimal to int. +In python, we can represent hexadecimal numbers using the `0x` prefix. +As with binary and octal, python will automatically convert hexadecimal to int. ```python -# 0x123 +# 0o123 >>> 0x123 291 ``` As with binary and octal you can do all the operations that you can do with integers and giving a number which is not in the hex system will raise a `SyntaxError`. -### Representing hexdecimal numbers +### Representing hexadecimal numbers -To represent an hexdecimal number, we can use the `hex()` function. +To represent an hexadecimal number, we can use the `hex()` function. ```python -# 0x123 >>> hex(0x123) '0x123' ``` -To convert an hexdecimal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. +To convert an hexadecimal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. ```python -# 291 >>> int("0x123", 16) 291 ``` As with binary and octal, giving the wrong base will raise a `ValueError`. -### Convering int to hexdecimal +### Converting int to hexadecimal We can also convert an integer to binary using the `hex()` function. ```python -# 0x123 >>> hex(291) '0x123' ``` [binary]: https://en.wikipedia.org/wiki/Binary_number [octal]: https://en.wikipedia.org/wiki/Octal -[hexdecimal]: https://en.wikipedia.org/wiki/Hexadecimal +[hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal [numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system [methods-int]: https://docs.python.org/3/library/stdtypes.html#additional-methods-on-integer-types From df09f10f6ada4127530491db47ea5dd7ceaec03c Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 30 Dec 2022 15:46:05 +0100 Subject: [PATCH 055/126] fixes --- .../.meta/config.json | 0 .../about.md | 4 ++-- concepts/binary-octal-hexadecimal/introduction.md | 9 +++++++++ .../links.json | 0 concepts/binary-octal-hexdecimal/introduction.md | 9 --------- config.json | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) rename concepts/{binary-octal-hexdecimal => binary-octal-hexadecimal}/.meta/config.json (100%) rename concepts/{binary-octal-hexdecimal => binary-octal-hexadecimal}/about.md (98%) create mode 100644 concepts/binary-octal-hexadecimal/introduction.md rename concepts/{binary-octal-hexdecimal => binary-octal-hexadecimal}/links.json (100%) delete mode 100644 concepts/binary-octal-hexdecimal/introduction.md diff --git a/concepts/binary-octal-hexdecimal/.meta/config.json b/concepts/binary-octal-hexadecimal/.meta/config.json similarity index 100% rename from concepts/binary-octal-hexdecimal/.meta/config.json rename to concepts/binary-octal-hexadecimal/.meta/config.json diff --git a/concepts/binary-octal-hexdecimal/about.md b/concepts/binary-octal-hexadecimal/about.md similarity index 98% rename from concepts/binary-octal-hexdecimal/about.md rename to concepts/binary-octal-hexadecimal/about.md index e3052de9cd2..43ddc905c8a 100644 --- a/concepts/binary-octal-hexdecimal/about.md +++ b/concepts/binary-octal-hexadecimal/about.md @@ -1,7 +1,7 @@ # binary, octal, hexadecimal Binary, octal, and hexadecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. -Binary is base 2, octal is base 8 and hexadecimal is base 16. +Binary is base 2, octal is base 8, and hexadecimal is base 16. Normal integers are base 10 in python. Binary, octal, and hexadecimal are all a subset of integers. Which means that they can only represent whole numbers and support all the operations that we can do with integers. @@ -106,7 +106,7 @@ Giving the wrong base will raise a `ValueError`: ```python Traceback (most recent call last): - File "c:\Users\carlh\fwfa.py", line 4, in + File "c:\binary.py", line 4, in int("0b10011", 3) ValueError: invalid literal for int() with base 3: '0b10011' ``` diff --git a/concepts/binary-octal-hexadecimal/introduction.md b/concepts/binary-octal-hexadecimal/introduction.md new file mode 100644 index 00000000000..7dc63b8dcdd --- /dev/null +++ b/concepts/binary-octal-hexadecimal/introduction.md @@ -0,0 +1,9 @@ +# binary, octal, hexadecimal + +Binary, octal, and hexadecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. +Binary is base 2, octal is base 8, and hexadecimal is base 16. +Normal integers are base 10 in python. +Binary, octal, and hexadecimal are all a subset of integers. +Which means that they can only represent whole numbers and support all the operations that we can do with integers. + +[numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system diff --git a/concepts/binary-octal-hexdecimal/links.json b/concepts/binary-octal-hexadecimal/links.json similarity index 100% rename from concepts/binary-octal-hexdecimal/links.json rename to concepts/binary-octal-hexadecimal/links.json diff --git a/concepts/binary-octal-hexdecimal/introduction.md b/concepts/binary-octal-hexdecimal/introduction.md deleted file mode 100644 index 0dba132a24b..00000000000 --- a/concepts/binary-octal-hexdecimal/introduction.md +++ /dev/null @@ -1,9 +0,0 @@ -# binary, otal, hexdecimal - -Binary, octal, and hexdecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. -Binary is base 2, octal is base 8 and hexdecimal is base 16. -Normal integers are base 10 in python. -Binary, octal, and hexdecimal are all a subset of integers. -Which means that they can only represent whole numbers and support all the operations that we can do with integers. - -[numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system diff --git a/config.json b/config.json index 17be12403a1..3e292d7440b 100644 --- a/config.json +++ b/config.json @@ -2237,8 +2237,8 @@ }, { "uuid": "78dbf248-a1e5-48cb-ba53-def4d92bf2a8", - "slug": "binary-octal-hexdecimal", - "name": "Binary, Octal, and Hexdecimal" + "slug": "binary-octal-hexadecimal", + "name": "Binary, Octal, and Hexadecimal" }, { "uuid": "f8e96e60-f746-4c7a-8dc9-df6b77eefdfa", From 236eeacad93def73382daff104583f02d8267999 Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 30 Dec 2022 22:20:51 +0100 Subject: [PATCH 056/126] fixes --- concepts/binary-octal-hexadecimal/about.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/concepts/binary-octal-hexadecimal/about.md b/concepts/binary-octal-hexadecimal/about.md index 43ddc905c8a..fa6d6a6a922 100644 --- a/concepts/binary-octal-hexadecimal/about.md +++ b/concepts/binary-octal-hexadecimal/about.md @@ -95,7 +95,7 @@ If we want to represent a binary number. '0b10011' ``` -To convert a binary number to an integer, we can use the `int()` function, and pass the string and the base as arguments. +To convert a binary number to an integer, we can use the `int()` function, and pass a string with a binary and the base as arguments. ```python >>> int("0b10011", 2) @@ -175,7 +175,7 @@ To represent an octal number, we can use the `oct()` function. '0o123' ``` -To convert an octal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. +To convert an octal number to an integer, we can use the `int()` function, pass a string with a octal and the base as arguments. ```python >>> int("0o123", 8) @@ -219,7 +219,7 @@ To represent an hexadecimal number, we can use the `hex()` function. '0x123' ``` -To convert an hexadecimal number to an integer, we can use the `int()` function, and pass the string and the base as arguments. +To convert an hexadecimal number to an integer, we can use the `int()` function, pass a string with a hexadecimal and the base as arguments. ```python >>> int("0x123", 16) @@ -238,7 +238,7 @@ We can also convert an integer to binary using the `hex()` function. ``` [binary]: https://en.wikipedia.org/wiki/Binary_number -[octal]: https://en.wikipedia.org/wiki/Octal [hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal -[numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system [methods-int]: https://docs.python.org/3/library/stdtypes.html#additional-methods-on-integer-types +[numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system +[octal]: https://en.wikipedia.org/wiki/Octal From 86c2a5a4efd844e299104f4055949b05143931e9 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Mon, 5 Jun 2023 17:22:00 -0700 Subject: [PATCH 057/126] Apply suggestions from code review @meatball - as you can see, I did a tad bit of violence to this. If you have time/energy, it would be great if you could give it a re-read to make sure that its still OK. _Many thanks!_ --- .../.meta/config.json | 2 +- concepts/binary-octal-hexadecimal/about.md | 148 ++++++++---------- .../binary-octal-hexadecimal/introduction.md | 6 +- 3 files changed, 69 insertions(+), 87 deletions(-) diff --git a/concepts/binary-octal-hexadecimal/.meta/config.json b/concepts/binary-octal-hexadecimal/.meta/config.json index 80a508e68bd..6e2a15b607a 100644 --- a/concepts/binary-octal-hexadecimal/.meta/config.json +++ b/concepts/binary-octal-hexadecimal/.meta/config.json @@ -1,4 +1,4 @@ { - "blurb": "Other numerical system in python, binary (0b11), octal (0o71), and hex (0xFF)", + "blurb": "Other numerical systems in Python: binary (0b11), octal (0o71), and hex (0xFF)", "authors": ["BethanyG", "meatball133"] } diff --git a/concepts/binary-octal-hexadecimal/about.md b/concepts/binary-octal-hexadecimal/about.md index fa6d6a6a922..1106e43803c 100644 --- a/concepts/binary-octal-hexadecimal/about.md +++ b/concepts/binary-octal-hexadecimal/about.md @@ -1,19 +1,16 @@ -# binary, octal, hexadecimal +# Binary, Octal, and Hexadecimal Binary, octal, and hexadecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. Binary is base 2, octal is base 8, and hexadecimal is base 16. Normal integers are base 10 in python. -Binary, octal, and hexadecimal are all a subset of integers. -Which means that they can only represent whole numbers and support all the operations that we can do with integers. +Binary, octal, and hexadecimal are all representations of integers. +Which means that they represent positive and negative numbers (_including zero_) without fractions or decimals, and support all the operations that we can do with integers. ## Binary -[Binary][binary] is a base 2 numeral system. -The most common numeral system is base 10. -In the base 10 numeral system so are the digits: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. -Binary is base 2, so the digits are 0 and 1. -It is used to represent the on and off states of a computer. -Binary can create all the numbers that we use in base 10. +[Binary][binary] is a base 2 numeral system, using only the digits 0 and 1. +It commonly represents the 0 ("off") and 1 ("on") states of electrical flow through transistors and switches in computers, as well as the positive and negative charges in magnetic storage media. +Binary can represent all the integers that are used in base 10. A snippet from the base 2 system looks like this, although it continues infinitely and doesn't stop at 128: @@ -40,7 +37,7 @@ And the operation would be: `16 + 0 + 0 + 2 + 1 = 19` ## Binary in Python -In Python, we can represent binary numbers using the `0b` prefix. +In Python, we can represent binary literals using the `0b` prefix. If we write `0b10011`, Python will interpret it as a binary number and convert it to base 10. ```python @@ -52,9 +49,9 @@ If we write `0b10011`, Python will interpret it as a binary number and convert i ``` -Binary in python is a subset of integers, therefore it will act like an integer. +Binary in Python is just a different way of writing an integer and so the binary representation **is an integer** for all mathematical operations. -If you have a number which is not in the binary system, it will raise a `SyntaxError`. +If you write a number with a `0b` prefix that is not in the binary system, it will raise a `SyntaxError`. ```python Traceback (most recent call last): @@ -63,9 +60,9 @@ Traceback (most recent call last): SyntaxError: invalid digit '2' in binary literal ``` -### Operations with binary numbers +### Operations with Binary Numbers -Since binary is a subset of integers, we can do all the operations that we can do with integers. +Since binary numbers are integers, we can perform all operations on them that we can with integers. ```python # addition @@ -77,32 +74,38 @@ Since binary is a subset of integers, we can do all the operations that we can d 361 ``` -We can do also have operations with both integers and binary numbers. +We can also perform operations between both binary and integer representations. +However, the usual mathematical operator rules apply: dividing two binary numbers or integer numbers will return a `float`, even if the division does not result in a decimal portion. ```python >>> 0b10011 + 19 38 -``` -### Representing binary numbers +>>> 0b10011/0b10011 +1.0 + +>>> 0b10011/3 +6.333333333333333 + +### Converting to and from Binary Representation -Since python will automatically convert binary to `int`, do we have to use the `bin()` function. -If we want to represent a binary number. -`bin()` will return a `string` with the prefix `0b`. +Python will automatically convert a binary literal into `int`. + To convert an `int` into a binary representation, use the built-in [`bin()`][bin] function. +`bin()` will return a `str` of the binary equivalent with the prefix `0b` . ```python ->>> bin(0b10011) +>>> bin(19) '0b10011' ``` -To convert a binary number to an integer, we can use the `int()` function, and pass a string with a binary and the base as arguments. +To convert a binary literal to an integer, we can use the built-in `int()` function, and pass a string of the binary representation and a base argument: ```python >>> int("0b10011", 2) 19 ``` -Giving the wrong base will raise a `ValueError`: +Giving the wrong base (_or an invalid binary representation_) will raise a `ValueError`: ```python Traceback (most recent call last): @@ -111,52 +114,39 @@ Traceback (most recent call last): ValueError: invalid literal for int() with base 3: '0b10011' ``` -### Converting int to binary - -We can also convert an integer to binary using the `bin()` function. - -```python -# 0b10011 ->>> bin(19) -'0b10011' -``` - -### Binary methods +### Binary Methods -There are also [methods][numeral-systems] that we can use on binary numbers. +There are also some special [methods][numeral-systems] that we can use on binary numbers. -#### `.bit_length()` -`.bit_length()` will return the number of bits that are needed to represent the number. -So for example `0b10011` will return 5. +[`.bit_length()`][bit_length] will return the number of bits that are needed to represent the number: ```python >>> 0b11011.bit_length() 5 ``` -#### `.count()` - -```exercism/note -`.count()` requires Python 3.10+. -If you are using the online editor then you don't need to worry about this. -``` -`.bit_count()` will return the number of **ones** in the binary number. -So for example `bit_count` will return 3. +[`.bit_count()`][bit_count] will return the number of **ones** in the binary number. +For example, `bit_count()` on '0b11011' will return 4: ```python >>> 0b11011.bit_count() 4 -``` + +~~~~exercism/note +If you are working locally, `bit_count()` requires at least Python 3.10. +The Exercism online editor currently supports all features through Python 3.11. +~~~~ + ## Octal [Octal][octal] is a base 8 numeral system. -Meaning that the digits are: 0, 1, 2, 3, 4, 5, 6, 7. +It uses the digits 0, 1, 2, 3, 4, 5, 6, and 7. -In python, we can represent octal numbers using the `0o` prefix. -As with binary, python will automatically convert octal to int. +In Python, we can represent octal numbers using the `0o` prefix. +As with binary, Python automatically converts an octal representation to an `int`. ```python # 0o123 @@ -164,18 +154,20 @@ As with binary, python will automatically convert octal to int. 83 ``` -As with binary you can do all the operations that you can do with integers and giving a number which is not in the octal system will raise a `SyntaxError`. +As with binary, octal numbers **are ints** and support all integer operations. +Prefixing a number with `0o` that is not in the octal system will raise a `SyntaxError`. -### Representing octal numbers + ### Converting to and from Octal Representation + -To represent an octal number, we can use the `oct()` function. +To convert an `int` into an octal representation, you can use the built-in [`oct()`][oct] function. +This acts similarly to the `bin()` function, returning a string: ```python ->>> oct(0o123) +>>> oct(83) '0o123' -``` -To convert an octal number to an integer, we can use the `int()` function, pass a string with a octal and the base as arguments. +To convert an octal number to an integer, we can use the `int()` function, passing an octal string representation and the base (8) as arguments: ```python >>> int("0o123", 8) @@ -184,42 +176,36 @@ To convert an octal number to an integer, we can use the `int()` function, pass As with binary, giving the wrong base will raise a `ValueError`. -### Converting int to octal - -We can also convert an integer to binary using the `oct()` function. - -```python ->>> oct(83) -'0o123' -``` - -### hexadecimal +### Hexadecimal [Hexadecimal][hexadecimal] is a base 16 numeral system. -Meaning that the digits are 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. -A is 10, B is 11, C is 12, D is 13, E is 14, F is 15. +It uses the digits 0 - 9 and the letters A, B, C, D, E, and F. +A is 10, B is 11, C is 12, D is 13, E is 14, and F is 15. -In python, we can represent hexadecimal numbers using the `0x` prefix. -As with binary and octal, python will automatically convert hexadecimal to int. +We can represent hexadecimal numbers in Python using the `0x` prefix. +As with binary and octal, Python will automatically convert hexadecimal literals to `int`. ```python -# 0o123 +# 0x123 >>> 0x123 291 ``` -As with binary and octal you can do all the operations that you can do with integers and giving a number which is not in the hex system will raise a `SyntaxError`. +As with binary and octal - hexidecimal literals **are ints**, and you can perform all integer operations. +Prefixing a non-hexidecimal number with `0x` will raise a `SyntaxError`. ### Representing hexadecimal numbers -To represent an hexadecimal number, we can use the `hex()` function. +### Converting to and from Hexadecimal Representation + +To convert an `int` into a hexadecimal representation, you can use the built-in [`hex()`][hex] function. +This acts similarly to the `bin()` function, returning a string: ```python ->>> hex(0x123) +>>> hex(291) '0x123' -``` -To convert an hexadecimal number to an integer, we can use the `int()` function, pass a string with a hexadecimal and the base as arguments. +To convert a hexadecimal representation to an integer, we can use the `int()` function, passing a hexadecimal string with the base (16) as arguments: ```python >>> int("0x123", 16) @@ -228,16 +214,10 @@ To convert an hexadecimal number to an integer, we can use the `int()` function, As with binary and octal, giving the wrong base will raise a `ValueError`. -### Converting int to hexadecimal - -We can also convert an integer to binary using the `hex()` function. - -```python ->>> hex(291) -'0x123' -``` [binary]: https://en.wikipedia.org/wiki/Binary_number +[bit_count]: https://docs.python.org/3/library/stdtypes.html#int.bit_count +[bit_length]: https://docs.python.org/3/library/stdtypes.html#int.bit_length [hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal [methods-int]: https://docs.python.org/3/library/stdtypes.html#additional-methods-on-integer-types [numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system diff --git a/concepts/binary-octal-hexadecimal/introduction.md b/concepts/binary-octal-hexadecimal/introduction.md index 7dc63b8dcdd..820aac33ee7 100644 --- a/concepts/binary-octal-hexadecimal/introduction.md +++ b/concepts/binary-octal-hexadecimal/introduction.md @@ -3,7 +3,9 @@ Binary, octal, and hexadecimal (_also known as hex_) are different [numeral systems][numeral-systems] with different bases. Binary is base 2, octal is base 8, and hexadecimal is base 16. Normal integers are base 10 in python. -Binary, octal, and hexadecimal are all a subset of integers. -Which means that they can only represent whole numbers and support all the operations that we can do with integers. +Binary, octal, and hexadecimal literals are all considered `int` subtypes and Python automatically converts between them. +This means that they can only represent zero, positive, and negative numbers that do not have a fractional or decimal part. +Binary, octal, and hexidecimal numbers support all integer operations. +However, division (_as with ints_) will return a `float`. [numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system From 6967d4a35542a38308b380d0bf9ca6a1b2449ef3 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Mon, 5 Jun 2023 17:22:29 -0700 Subject: [PATCH 058/126] Update concepts/binary-octal-hexadecimal/about.md --- concepts/binary-octal-hexadecimal/about.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/concepts/binary-octal-hexadecimal/about.md b/concepts/binary-octal-hexadecimal/about.md index 1106e43803c..89515abe583 100644 --- a/concepts/binary-octal-hexadecimal/about.md +++ b/concepts/binary-octal-hexadecimal/about.md @@ -218,6 +218,8 @@ As with binary and octal, giving the wrong base will raise a `ValueError`. [binary]: https://en.wikipedia.org/wiki/Binary_number [bit_count]: https://docs.python.org/3/library/stdtypes.html#int.bit_count [bit_length]: https://docs.python.org/3/library/stdtypes.html#int.bit_length +[bit_count]: https://docs.python.org/3/library/stdtypes.html#int.bit_count +[bit_length]: https://docs.python.org/3/library/stdtypes.html#int.bit_length [hexadecimal]: https://en.wikipedia.org/wiki/Hexadecimal [methods-int]: https://docs.python.org/3/library/stdtypes.html#additional-methods-on-integer-types [numeral-systems]: https://en.wikipedia.org/wiki/Numeral_system From c997cc7f1e57c4b457f936034f07ff8fdfbc5db7 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Mon, 5 Jun 2023 17:22:49 -0700 Subject: [PATCH 059/126] Update concepts/binary-octal-hexadecimal/about.md --- concepts/binary-octal-hexadecimal/about.md | 1 - 1 file changed, 1 deletion(-) diff --git a/concepts/binary-octal-hexadecimal/about.md b/concepts/binary-octal-hexadecimal/about.md index 89515abe583..53aa6de104b 100644 --- a/concepts/binary-octal-hexadecimal/about.md +++ b/concepts/binary-octal-hexadecimal/about.md @@ -194,7 +194,6 @@ As with binary and octal, Python will automatically convert hexadecimal literals As with binary and octal - hexidecimal literals **are ints**, and you can perform all integer operations. Prefixing a non-hexidecimal number with `0x` will raise a `SyntaxError`. -### Representing hexadecimal numbers ### Converting to and from Hexadecimal Representation From 7aef5e9a8940a624f3cd4d604e99955d610058bf Mon Sep 17 00:00:00 2001 From: BethanyG Date: Tue, 6 Jun 2023 10:29:37 -0700 Subject: [PATCH 060/126] Update concepts/binary-octal-hexadecimal/about.md --- concepts/binary-octal-hexadecimal/about.md | 1 - 1 file changed, 1 deletion(-) diff --git a/concepts/binary-octal-hexadecimal/about.md b/concepts/binary-octal-hexadecimal/about.md index 53aa6de104b..667f3eb6cd7 100644 --- a/concepts/binary-octal-hexadecimal/about.md +++ b/concepts/binary-octal-hexadecimal/about.md @@ -133,7 +133,6 @@ For example, `bit_count()` on '0b11011' will return 4: ```python >>> 0b11011.bit_count() 4 - ~~~~exercism/note If you are working locally, `bit_count()` requires at least Python 3.10. The Exercism online editor currently supports all features through Python 3.11. From c93e7ad50f0089f086200d4e343abf36b228164d Mon Sep 17 00:00:00 2001 From: Carl Date: Wed, 21 Dec 2022 20:49:38 +0100 Subject: [PATCH 061/126] Start --- concepts/itertools/about.md | 337 +++++++++++++++++++++++++++++++++- concepts/itertools/links.json | 4 +- 2 files changed, 338 insertions(+), 3 deletions(-) diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index c628150d565..82e6c6161a9 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -1,2 +1,337 @@ -#TODO: Add about for this concept. +## Infinite iterators +```exercism/note +To avoid infinite loops, you can use `break` to end a loop. +``` + +### Count() + +`count(start, )` allows to print all values from the start value to infinity. +Count also has an optional step parameter, which allows to print values with a step size other than 1. + +```python +>>> import itertools +>>> for number in itertools.count(5, 2): +... if number > 20: +... break +... else: +... print(number, end=' ') +... +5 7 9 11 13 15 17 19 +``` + +Giving `count()` a negative step size will print values in a descending order. + +```python +>>> import itertools +>>> for number in itertools.count(5, -2): +... if number < -20: +... break +... else: +... print(number, end=' ') +... +5 3 1 -1 -3 -5 -7 -9 -11 -13 -15 -17 -19 +``` + +### Cycle() + +`cycle(iterable)` allows to print all values from the iterable in an infinte loop. +For example a `list`, `tuple`, `string` or `dict` can be used as an iterable. + +```python +>>> import itertools +>>> number = 0 +>>> for letter in itertools.cycle("ABC"): +... if number == 10: +... break +... else: +... print(letter, end=' ') +... number += 1 +... +A B C A B C A B C A +``` + +### Repeat() + +`repeat(object, )` allows to print the same value in an infinte loop. +Although if the optional times parameter is given, the value will be printed that many times. +Meaning that it is not an infinite loop if that parameter is given. + +```python +>>> import itertools +>>> for number in itertools.repeat(5, 3): +... print(number, end=' ') +... +5 5 5 +``` + +## Iterators terminating on the shortest input sequence + +### Accumulate() + +`accumulate(iterable, )` allows to print the accumulated values. + +perhaps skip + +### Chain() + +`chain(iterable1, iterable2...)` creates an irretator of values from the iterables in the order they are given. + +```python +>>> import itertools +>>> for number in itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9]): +... print(number, end=' ') +... +1 2 3 4 5 6 7 8 9 +``` + +Chain can also be used to concate a different amount of iterables to a list or tuple by using the `list()` or `tuple()` function. + +```python +>>> import itertools +>>> list(itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9])) +[1, 2, 3, 4, 5, 6, 7, 8, 9] +``` + +### chain.from_iterable() + +Works like chain but takes a single iterable argument and unpack that iterable into individual iterables. + +```python +>>> import itertools +>>> for number in itertools.chain.from_iterable([[1, 2, 3], [4, 5, 6], [7, 8, 9]]): +... print(number, end=' ') +... +1 2 3 4 5 6 7 8 9 +``` + +### Compress() + +`compress(iterable, selectors)` creates an irretator from the iterable where the corresponding selector is `True`. +The selector can hold bools but can also hold integers, where 0 is `False` and any other integer is `True`. + +```python +>>> import itertools +>>> for letter in itertools.compress("Exercism", [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]): +... print(letter, end=' ') +... +E r c s m +``` + +### Dropwhile() + +skip + +### Filterfalse() + +skip + +### Groupby() + +probably skip + +### Islice() + +`islice(iterable, , , )` creates an irretator of the values from the iterable, from the start index to the stop index with a step size of step. + +```python +>>> import itertools +>>> for letter in itertools.islice("Exercism", 2, 5, 2): +... print(letter, end=' ') +... +e c +``` + +### Pairwise() + +```exercism/note +`Pairwise()` requires Python 3.10+. +If you are using the online editor then you don't need to worry about this. +``` + +`Pairwise(iterable)` was intruduced in Python 3.10 and returns an iterator of overlapping pairs of values from the input iterable. + +```python +>>> import itertools +>>> for pair in itertools.pairwise("Exercism"): +... print(pair, end=' ') +... +('E', 'x') ('x', 'e') ('e', 'r') ('r', 'c') ('c', 'i') ('i', 's') ('s', 'm') +``` + +### Starmap() + +Pehaps skip + +### Takewhile() + +skip + +### Tee() + +Talk with Bethany about + +### Zip_longest() + +#### Explaning zip + +```exercism/caution +Zip in computer science(programming) is not the same as zip in computer terms. +Zip in computer terms reffers to a file format that supports compression. +While zip in computer science(programming) reffers to the `zip()` function. +``` + +`zip()` is a built in function and is not apart of the `itertools` module. +It takes any number of iterables and returns an iterator of tuples. +Where the i-th tuple contains the i-th element from each of the argument iterables. +Meaning the first tuple will contain the first element from each iterable, the second tuple will contain the second element from each iterable and so on. + +```python +>>> zipped = zip(['x', 'y', 'z'], [1, 2, 3], [True, False, True]) +>>> list(zipped) +[('x', 1, True),('y', 2, False), ('z', 3, True)] +``` + +If the iterables are not the same length, then the iterator will stop when the shortest iterable is exhausted. + +```python +>>> zipped = zip(['x', 'y', 'z'], [1, 2, 3, 4], [True, False]) +>>> list(zipped) +[('x', 1, True),('y', 2, False)] +``` + +#### Explaning zip_longest + +`zip_longest(iterator, )` is a function from the `itertools` module. +The difference between `zip_longest()` and `zip()` is that `zip_longest()` will continue until the longest iterable is exhausted. +If the iterables are not the same length the `fillvalue` will be used to fill in the missing values. +By the default the `fillvalue` is `None`. + +```python +>>> import itertools +>>> zipped = itertools.zip_longest(['x', 'y', 'z'], [1, 2, 3, 4], [True, False]) +>>> list(zipped) +[('x', 1, True),('y', 2, False), ('z', 3, None), (None, 4, None)] +``` + +An example where a fillvalue is given: + +```python +>>> import itertools +>>> zipped = itertools.zip_longest(['x', 'y', 'z'], [1, 2, 3, 4], [True, False], fillvalue='fill') +>>> list(zipped) +[('x', 1, True),('y', 2, False), ('z', 3, 'fill'), ('fill', 4, 'fill')] +``` + +## Combinatoric iterators + +### Product() + +`product(iterable1, iterable2..., )` creates an iterator of tuples where the i-th tuple contains the i-th element from each of the argument iterables. +The repeat keyword argument can be used to specify the number of times the input iterables are repeated. +By default the repeat keyword argument is 1. + +```python +>>> import itertools +>>> for product in itertools.product("ABCD", repeat=1): +... print(product, end=' ') +... +('A',) ('B',) ('C',) ('D',) +``` + +```python +>>> import itertools +>>> for product in itertools.product("ABCD", repeat=2): +... print(product, end=' ') +... +('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'A') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'A') ('C', 'B') ('C', 'C') ('C', 'D') ('D', 'A') ('D', 'B') ('D', 'C') ('D', 'D') +``` + +The last one here can be seen as doing a nested for loop. +When you increase the repeat value the number of iterations increases exponentially. +The example above is a n\*\*2 iteration. + +```python +>>> import itertools +>>> for letter1 in "ABCD": +... for letter2 in "ABCD": +... print((letter1, letter2), end=' ') +... +('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'A') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'A') ('C', 'B') ('C', 'C') ('C', 'D') ('D', 'A') ('D', 'B') ('D', 'C') ('D', 'D') +``` + +You can also give it multiple iterables. + +```python +>>> import itertools +>>> for product in itertools.product("ABCD", "xy" repeat=1): +... print(product, end=' ') +... +('A', 'x') ('A', 'y') ('B', 'x') ('B', 'y') ('C', 'x') ('C', 'y') ('D', 'x') ('D', 'y') +``` + +Here is an example of doing it wihout `product()`. +It looks similliar to the last example but since we have two iterables we need to nest the for loops. +Even though the proudct is given repeat=1. +The reasson to why it is only 2 for loops earlier was because we only had one iterable. +If we had two iterables and gave it repeat=2 we would need 4 for loops. +Since 2 \* 2 = 4. + +```python +>>> for letter1 in "ABCD": +... for letter2 in "xy": +... print((letter1, letter2), end=' ') +... +('A', 'x') ('A', 'y') ('B', 'x') ('B', 'y') ('C', 'x') ('C', 'y') ('D', 'x') ('D', 'y') +``` + +### Permutations() + +`permutations(iterable, )` creates an iterator of tuples. +It works like `product()` but it doesnt repeat values from a specific positoon from the iterable and can only take one iterable. +The "r" keyword argument can be used to specify the number of times the input iterables are repeated. +By default the "r" keyword argument is None. +If "r" is None then the length of the iterable is used. + +```python +>>> import itertools +>>> for permutation in itertools.permutations("ABCD", repeat=1): +... print(permutation, end=' ') +... +('A',) ('B',) ('C',) ('D',) +``` + +```python +>>> import itertools +>>> for permutation in itertools.permutations("ABCD", repeat=2): +... print(permutation, end=' ') +... +('A', 'B') ('A', 'C') ('A', 'D') ('B', 'A') ('B', 'C') ('B', 'D') ('C', 'A') ('C', 'B') ('C', 'D') ('D', 'A') ('D', 'B') ('D', 'C') +``` + +### Combinations() + +`combinations(iterable, r)` finds all the possible combinations of the given iterable. +The r keyword argument is used to specify the length of the tuples generated. + +```python +>>> import itertools +>>> for combination in itertools.combinations("ABCD", 2): +... print(combination, end=' ') +... +('A', 'B') ('A', 'C') ('A', 'D') ('B', 'C') ('B', 'D') ('C', 'D') +``` + +### Combinations_with_replacement() + +`combinations_with_replacement(iterable, r)` finds all the possible combinations of the given iterable. +The r keyword argument is used to specify the length of the tuples generated. +The difference between this and `combinations()` is that it can repeat values. + +```python +>>> import itertools +>>> for combination in itertools.combinations_with_replacement("ABCD", 2): +... print(combination, end=' ') +... +('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'C') ('C', 'D') ('D', 'D') +``` diff --git a/concepts/itertools/links.json b/concepts/itertools/links.json index eb5fb7c38a5..8a44906b3f8 100644 --- a/concepts/itertools/links.json +++ b/concepts/itertools/links.json @@ -1,7 +1,7 @@ [ { - "url": "http://example.com/", - "description": "TODO: add new link (above) and write a short description here of the resource." + "url": "https://docs.python.org/3/library/itertools.htm", + "description": "Offical Python documentation for the itertools module." }, { "url": "http://example.com/", From 43e5f990346c8131ac234690d9e7e3100fa6a04c Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 22 Dec 2022 16:05:04 +0100 Subject: [PATCH 062/126] Added the changes we talked about and some extras --- concepts/itertools/.meta/config.json | 2 +- concepts/itertools/about.md | 195 +++++++++++++-------------- 2 files changed, 93 insertions(+), 104 deletions(-) diff --git a/concepts/itertools/.meta/config.json b/concepts/itertools/.meta/config.json index 9b9e8da5a9b..3bf2b514ccf 100644 --- a/concepts/itertools/.meta/config.json +++ b/concepts/itertools/.meta/config.json @@ -1,5 +1,5 @@ { "blurb": "TODO: add blurb for this concept", - "authors": ["bethanyg", "cmccandless"], + "authors": ["bethanyg", "meatball133"], "contributors": [] } diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index 82e6c6161a9..e23860db98f 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -1,78 +1,5 @@ -## Infinite iterators - -```exercism/note -To avoid infinite loops, you can use `break` to end a loop. -``` - -### Count() - -`count(start, )` allows to print all values from the start value to infinity. -Count also has an optional step parameter, which allows to print values with a step size other than 1. - -```python ->>> import itertools ->>> for number in itertools.count(5, 2): -... if number > 20: -... break -... else: -... print(number, end=' ') -... -5 7 9 11 13 15 17 19 -``` - -Giving `count()` a negative step size will print values in a descending order. - -```python ->>> import itertools ->>> for number in itertools.count(5, -2): -... if number < -20: -... break -... else: -... print(number, end=' ') -... -5 3 1 -1 -3 -5 -7 -9 -11 -13 -15 -17 -19 -``` - -### Cycle() - -`cycle(iterable)` allows to print all values from the iterable in an infinte loop. -For example a `list`, `tuple`, `string` or `dict` can be used as an iterable. - -```python ->>> import itertools ->>> number = 0 ->>> for letter in itertools.cycle("ABC"): -... if number == 10: -... break -... else: -... print(letter, end=' ') -... number += 1 -... -A B C A B C A B C A -``` - -### Repeat() - -`repeat(object, )` allows to print the same value in an infinte loop. -Although if the optional times parameter is given, the value will be printed that many times. -Meaning that it is not an infinite loop if that parameter is given. - -```python ->>> import itertools ->>> for number in itertools.repeat(5, 3): -... print(number, end=' ') -... -5 5 5 -``` - ## Iterators terminating on the shortest input sequence -### Accumulate() - -`accumulate(iterable, )` allows to print the accumulated values. - -perhaps skip - ### Chain() `chain(iterable1, iterable2...)` creates an irretator of values from the iterables in the order they are given. @@ -95,11 +22,16 @@ Chain can also be used to concate a different amount of iterables to a list or t ### chain.from_iterable() -Works like chain but takes a single iterable argument and unpack that iterable into individual iterables. +Works like chain but takes a single nested iterable, unpacking that iterable into individual iterables. ```python >>> import itertools ->>> for number in itertools.chain.from_iterable([[1, 2, 3], [4, 5, 6], [7, 8, 9]]): +>>> for number in itertools.chain.from_iterable( + [ + [1, 2, 3], + [4, 5, 6], + [7, 8, 9] + ]): ... print(number, end=' ') ... 1 2 3 4 5 6 7 8 9 @@ -107,32 +39,30 @@ Works like chain but takes a single iterable argument and unpack that iterable i ### Compress() -`compress(iterable, selectors)` creates an irretator from the iterable where the corresponding selector is `True`. -The selector can hold bools but can also hold integers, where 0 is `False` and any other integer is `True`. +`compress(iterable, selectors)` creates an iterator from the input iterable where the corresponding selector is `True`. +The selector can be `True`/`False` or integers, where 0 is `False` and 1 is `True`. ```python >>> import itertools ->>> for letter in itertools.compress("Exercism", [1, 0, 1, 0, 1, 0, 1, 0, 1, 0]): +>>> for letter in itertools.compress("Exercism", [1, 0, 0, 1, 1, 0, 1, 1]): ... print(letter, end=' ') ... E r c s m ``` -### Dropwhile() - -skip - -### Filterfalse() +With `True`/`False`: -skip - -### Groupby() - -probably skip +```python +>>> import itertools +>>> for letter in itertools.compress("Exercism", [True, False, False, True, True, False, True, True]): +... print(letter, end=' ') +... +E r c s m +``` ### Islice() -`islice(iterable, , , )` creates an irretator of the values from the iterable, from the start index to the stop index with a step size of step. +`islice(iterable, start, , )` creates a new iterator from the slice (from the start index to the stop index with a step size of step). ```python >>> import itertools @@ -159,14 +89,6 @@ If you are using the online editor then you don't need to worry about this. ('E', 'x') ('x', 'e') ('e', 'r') ('r', 'c') ('c', 'i') ('i', 's') ('s', 'm') ``` -### Starmap() - -Pehaps skip - -### Takewhile() - -skip - ### Tee() Talk with Bethany about @@ -176,15 +98,13 @@ Talk with Bethany about #### Explaning zip ```exercism/caution -Zip in computer science(programming) is not the same as zip in computer terms. -Zip in computer terms reffers to a file format that supports compression. -While zip in computer science(programming) reffers to the `zip()` function. +Pythons `zip()` function should not be confused with the zip compression format. ``` `zip()` is a built in function and is not apart of the `itertools` module. It takes any number of iterables and returns an iterator of tuples. Where the i-th tuple contains the i-th element from each of the argument iterables. -Meaning the first tuple will contain the first element from each iterable, the second tuple will contain the second element from each iterable and so on. +For example, the first tuple will contain the first element from each iterable, the second tuple will contain the second element from each iterable, and so on until the shortest iterable is exhausted. ```python >>> zipped = zip(['x', 'y', 'z'], [1, 2, 3], [True, False, True]) @@ -203,8 +123,8 @@ If the iterables are not the same length, then the iterator will stop when the s #### Explaning zip_longest `zip_longest(iterator, )` is a function from the `itertools` module. -The difference between `zip_longest()` and `zip()` is that `zip_longest()` will continue until the longest iterable is exhausted. -If the iterables are not the same length the `fillvalue` will be used to fill in the missing values. +Unlink `zip()`, it will not stop when the shortest iterable is exhausted. +If the iterables are not the same length, `fillvalue` will be used to pad missing values. By the default the `fillvalue` is `None`. ```python @@ -239,6 +159,8 @@ By default the repeat keyword argument is 1. ('A',) ('B',) ('C',) ('D',) ``` +Giving a repeat value of 2: + ```python >>> import itertools >>> for product in itertools.product("ABCD", repeat=2): @@ -335,3 +257,70 @@ The difference between this and `combinations()` is that it can repeat values. ... ('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'C') ('C', 'D') ('D', 'D') ``` + +## Infinite iterators + +```exercism/note +To avoid infinite loops, you can use `break` to end a loop. +``` + +### Count() + +`count(start, )` produces all values from the start value to infinity. +Count also has an optional step parameter, which will produce values with a step size other than 1. + +```python +>>> import itertools +>>> for number in itertools.count(5, 2): +... if number > 20: +... break +... else: +... print(number, end=' ') +... +5 7 9 11 13 15 17 19 +``` + +Giving `count()` a negative step size will produces values in a descending order. + +```python +>>> import itertools +>>> for number in itertools.count(5, -2): +... if number < -20: +... break +... else: +... print(number, end=' ') +... +5 3 1 -1 -3 -5 -7 -9 -11 -13 -15 -17 -19 +``` + +### Cycle() + +`cycle(iterable)` produces all values from the iterable in an infinte loop. +A `list`, `tuple`, `string`, `dict` or any other iterable can be used. + +```python +>>> import itertools +>>> number = 0 +>>> for letter in itertools.cycle("ABC"): +... if number == 10: +... break +... else: +... print(letter, end=' ') +... number += 1 +... +A B C A B C A B C A +``` + +### Repeat() + +`repeat(object, )` produces the same value in an infinte loop. +Although if the optional times parameter is given, the value will produces that many times. +Meaning that it is not an infinite loop if that parameter is given. + +```python +>>> import itertools +>>> for number in itertools.repeat(5, 3): +... print(number, end=' ') +... +5 5 5 +``` From 99689d80c9afa1dbd7a54e4681c8f41ea56bc011 Mon Sep 17 00:00:00 2001 From: Carl Date: Fri, 23 Dec 2022 17:01:41 +0100 Subject: [PATCH 063/126] Added extra parts --- concepts/itertools/about.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index e23860db98f..4cfe5bca536 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -14,12 +14,22 @@ Chain can also be used to concate a different amount of iterables to a list or tuple by using the `list()` or `tuple()` function. +Using `list()`: + ```python >>> import itertools >>> list(itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9])) [1, 2, 3, 4, 5, 6, 7, 8, 9] ``` +Using `tuple()`: + +```python +>>> import itertools +>>> tuple(itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9])) +(1, 2, 3, 4, 5, 6, 7, 8, 9) +``` + ### chain.from_iterable() Works like chain but takes a single nested iterable, unpacking that iterable into individual iterables. From 85f23648a3540530f3ec10bc51923b25f6975baf Mon Sep 17 00:00:00 2001 From: Carl Date: Sat, 24 Dec 2022 23:34:24 +0100 Subject: [PATCH 064/126] Added blurb --- concepts/itertools/about.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index 4cfe5bca536..366515cf1aa 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -270,6 +270,10 @@ The difference between this and `combinations()` is that it can repeat values. ## Infinite iterators +Most of iterator from the `itertools` module get exhausted after a time. +But there are some that are infinite, these are known as infinte iterators. +These iterators will will keep producing values until you tell them to stop. + ```exercism/note To avoid infinite loops, you can use `break` to end a loop. ``` From 5d31c1b37d09387016f0860cb879b42e4db5b4a3 Mon Sep 17 00:00:00 2001 From: Carl Date: Sun, 25 Dec 2022 13:36:11 +0100 Subject: [PATCH 065/126] Started on resistor_color_master --- config.json | 15 ++ .../.docs/instructions.md | 54 +++++++ .../resistor-color-master/.meta/config.json | 20 +++ .../resistor-color-master/.meta/example.py | 47 ++++++ .../resistor-color-master/.meta/hi.json | 147 ++++++++++++++++++ .../resistor-color-master/.meta/template.j2 | 15 ++ .../resistor-color-master/.meta/tests.toml | 40 +++++ .../resistor_color_master.py | 49 ++++++ .../resistor_color_master_test.py | 51 ++++++ 9 files changed, 438 insertions(+) create mode 100644 exercises/practice/resistor-color-master/.docs/instructions.md create mode 100644 exercises/practice/resistor-color-master/.meta/config.json create mode 100644 exercises/practice/resistor-color-master/.meta/example.py create mode 100644 exercises/practice/resistor-color-master/.meta/hi.json create mode 100644 exercises/practice/resistor-color-master/.meta/template.j2 create mode 100644 exercises/practice/resistor-color-master/.meta/tests.toml create mode 100644 exercises/practice/resistor-color-master/resistor_color_master.py create mode 100644 exercises/practice/resistor-color-master/resistor_color_master_test.py diff --git a/config.json b/config.json index 3e292d7440b..84c5f1ea6fc 100644 --- a/config.json +++ b/config.json @@ -970,6 +970,21 @@ ], "difficulty": 3 }, + { + "slug": "resistor-color-master", + "name": "Resistor Color Master", + "uuid": "f987a5b7-96f2-49c2-99e8-aef30d23dd58", + "practices": ["list-methods"], + "prerequisites": [ + "basics", + "bools", + "lists", + "numbers", + "strings", + "comparisons" + ], + "difficulty": 3 + }, { "slug": "matrix", "name": "Matrix", diff --git a/exercises/practice/resistor-color-master/.docs/instructions.md b/exercises/practice/resistor-color-master/.docs/instructions.md new file mode 100644 index 00000000000..fcc76958a5f --- /dev/null +++ b/exercises/practice/resistor-color-master/.docs/instructions.md @@ -0,0 +1,54 @@ +# Instructions + +If you want to build something using a Raspberry Pi, you'll probably use _resistors_. +For this exercise, you need to know only three things about them: + +- Each resistor has a resistance value. +- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. + To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. +- Each band acts as a digit of a number. + For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. + In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. + The program will take 3 colors as input, and outputs the correct value, in ohms. + The color bands are encoded as follows: + +- Black: 0 +- Brown: 1 +- Red: 2 +- Orange: 3 +- Yellow: 4 +- Green: 5 +- Blue: 6 +- Violet: 7 +- Grey: 8 +- White: 9 + +In `resistor-color duo` you decoded the first two colors. +For instance: orange-orange got the main value `33`. +The third color stands for how many zeros need to be added to the main value. +The main value plus the zeros gives us a value in ohms. +For the exercise it doesn't matter what ohms really are. +For example: + +- orange-orange-black would be 33 and no zeros, which becomes 33 ohms. +- orange-orange-red would be 33 and 2 zeros, which becomes 3300 ohms. +- orange-orange-orange would be 33 and 3 zeros, which becomes 33000 ohms. + +(If Math is your thing, you may want to think of the zeros as exponents of 10. +If Math is not your thing, go with the zeros. +It really is the same thing, just in plain English instead of Math lingo.) + +This exercise is about translating the colors into a label: + +> "... ohms" + +So an input of `"orange", "orange", "black"` should return: + +> "33 ohms" + +When we get more than a thousand ohms, we say "kiloohms". +That's similar to saying "kilometer" for 1000 meters, and "kilograms" for 1000 grams. + +So an input of `"orange", "orange", "orange"` should return: + +> "33 kiloohms" diff --git a/exercises/practice/resistor-color-master/.meta/config.json b/exercises/practice/resistor-color-master/.meta/config.json new file mode 100644 index 00000000000..23a09a2cdd9 --- /dev/null +++ b/exercises/practice/resistor-color-master/.meta/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "meatball133", + "bethanyg" + ], + "files": { + "solution": [ + "resistor_color_master.py" + ], + "test": [ + "resistor_color_master_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Convert color codes, as used on resistors, to a human-readable label.", + "source": "Maud de Vries, Erik Schierboom", + "source_url": "https://github.com/exercism/problem-specifications/issues/1549" +} diff --git a/exercises/practice/resistor-color-master/.meta/example.py b/exercises/practice/resistor-color-master/.meta/example.py new file mode 100644 index 00000000000..a7dd1cd367e --- /dev/null +++ b/exercises/practice/resistor-color-master/.meta/example.py @@ -0,0 +1,47 @@ +COLORS = [ + 'black', + 'brown', + 'red', + 'orange', + 'yellow', + 'green', + 'blue', + 'violet', + 'grey', + 'white' +] + +COLORS_TOLERANCE = { + 'brown': 1, + 'red': 2, + 'green': 0.5, + 'blue': 0.25, + 'violet': 0.1, + 'grey': 0.05, + 'gold': 5, + 'silver': 10 +} + + +def label(colors): + if len(colors) == 1: + return f'0 ohms' + elif len(colors) == 4: + value = 10 * COLORS.index(colors[0]) + COLORS.index(colors[1]) + value *= 10 ** COLORS.index(colors[2]) + value, unit = color_code(value) + return f'{value} {unit}, {COLORS_TOLERANCE[colors[3]]}%' + else: + value = 10 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) + value *= 10 ** COLORS.index(colors[3]) + value, unit = color_code(value) + return f'{value} {unit}, {COLORS_TOLERANCE[colors[4]]}%' + + +def color_code(color): + if color < 1000: + return color, 'ohms' + elif color < 1000000: + return color / 1000, 'kiloohms' + else: + return color / 1000000, 'megaohms' \ No newline at end of file diff --git a/exercises/practice/resistor-color-master/.meta/hi.json b/exercises/practice/resistor-color-master/.meta/hi.json new file mode 100644 index 00000000000..b25a6b1acaf --- /dev/null +++ b/exercises/practice/resistor-color-master/.meta/hi.json @@ -0,0 +1,147 @@ +{ + "exercise": "resistor-color-master", + "cases": [ + { + "uuid": "8c4f9fb6-d477-4250-bc57-b325d2be226f", + "description": "Orange, orange, black, and red", + "property": "label", + "input": { + "colors": ["orange", "orange", "black", "red"] + }, + "expected": { + "value": 33, + "tolerance": 2, + "unit": "ohms" + } + }, + { + "uuid": "d1d4a769-9210-43cc-9a14-6af6ce4c0b00", + "description": "Blue, grey, brown, and violet", + "property": "label", + "input": { + "colors": ["blue", "grey", "brown", "violet"] + }, + "expected": { + "value": 680, + "tolerance": 0.1, + "unit": "ohms" + } + }, + { + "uuid": "6af91bc3-8275-4c38-920a-185d30feb5f3", + "description": "Red, black, red, and green", + "property": "label", + "input": { + "colors": ["red", "black", "red", "green"] + }, + "expected": { + "value": 2, + "tolerance": 0.5, + "unit": "kiloohms" + } + }, + { + "uuid": "9c4630bf-0dda-4212-baca-2f5111530b4d", + "description": "Green, brown, orange, and grey", + "property": "label", + "input": { + "colors": ["green", "brown", "orange", "grey"] + }, + "expected": { + "value": 51, + "tolerance": 0.05, + "unit": "kiloohms" + } + }, + { + "uuid": "93b7d0ec-39fb-49f3-bb88-2dd4b8c293af", + "description": "Yellow, violet, yellow, and blue", + "property": "label", + "input": { + "colors": ["yellow", "violet", "yellow", "blue"] + }, + "expected": { + "value": 470, + "tolerance": 0.25, + "unit": "kiloohms" + } + }, + { + "uuid": "5880ddf1-0dc6-4bd0-b9de-5626117cd2c7", + "description": "One black band", + "property": "label", + "input": { + "colors": ["black"] + }, + "expected": { + "value": 0, + "unit": "ohms" + } + }, + { + "uuid": "a5cfda34-3c02-4bda-b183-726791fb43b2", + "description": "Orange, orange, yellow, black, and brown", + "property": "label", + "input": { + "colors": ["orange", "orange", "yellow", "black", "brown"] + }, + "expected": { + "value": 334, + "tolerance": 1, + "unit": "ohms" + } + }, + { + "uuid": "4f0ad96c-cdab-4c84-95dd-7074e889e001", + "description": "Red, green, yellow, yellow, and brown", + "property": "label", + "input": { + "colors": ["red", "green", "yellow", "yellow", "brown"] + }, + "expected": { + "value": 2.54, + "tolerance": 1, + "unit": "megaohms" + } + }, + { + "uuid": "48c66841-208c-46a7-8992-1e84a2eda9e2", + "description": "Blue, grey, white, brown, and brown", + "property": "label", + "input": { + "colors": ["blue", "grey", "white", "brown", "brown"] + }, + "expected": { + "value": 6.89, + "tolerance": 1, + "unit": "kiloohms" + } + }, + { + "uuid": "4f3aeb0c-fd9d-4cbd-b204-554e61978f73", + "description": "Violet, orange, red, and grey", + "property": "label", + "input": { + "colors": ["violet", "orange", "red", "grey"] + }, + "expected": { + "value": 7.3, + "tolerance": 0.05, + "unit": "kiloohms" + } + }, + { + "uuid": "1ae3a17f-8bc0-449c-9831-fddfd2d91c5d", + "description": "Brown, red, orange, green, and blue", + "property": "label", + "input": { + "colors": ["brown", "red", "orange", "green", "blue"] + }, + "expected": { + "value": 12.3, + "tolerance": 0.25, + "unit": "megaohms" + } + } + ] +} diff --git a/exercises/practice/resistor-color-master/.meta/template.j2 b/exercises/practice/resistor-color-master/.meta/template.j2 new file mode 100644 index 00000000000..e9b458f34c3 --- /dev/null +++ b/exercises/practice/resistor-color-master/.meta/template.j2 @@ -0,0 +1,15 @@ +{%- import "generator_macros.j2" as macros with context -%} +{% macro test_case(case) -%} + {%- set input = case["input"] -%} + def test_{{ case["description"] | to_snake }}(self): + self.assertEqual( + {{ case["property"] | to_snake }}({{ case["input"]["colors"] }}), + "{{ case['expected']['value']}} {{ case['expected']['unit']}} {{case['expected']['tolerance']}}{{"%" if case['expected']['tolerance'] else ""}}" + ) +{%- endmacro %} +{{ macros.header()}} + +class {{ exercise | camel_case }}Test(unittest.TestCase): + {% for case in cases -%} + {{ test_case(case) }} + {% endfor %} diff --git a/exercises/practice/resistor-color-master/.meta/tests.toml b/exercises/practice/resistor-color-master/.meta/tests.toml new file mode 100644 index 00000000000..4f57723a19f --- /dev/null +++ b/exercises/practice/resistor-color-master/.meta/tests.toml @@ -0,0 +1,40 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[8c4f9fb6-d477-4250-bc57-b325d2be226f] +description = "Orange, orange, black, and red" + +[d1d4a769-9210-43cc-9a14-6af6ce4c0b00] +description = "Blue, grey, brown, and violet" + +[6af91bc3-8275-4c38-920a-185d30feb5f3] +description = "Red, black, red, and green" + +[9c4630bf-0dda-4212-baca-2f5111530b4d] +description = "Green, brown, orange, and grey" + +[5880ddf1-0dc6-4bd0-b9de-5626117cd2c7] +description = "One black band" + +[a5cfda34-3c02-4bda-b183-726791fb43b2] +description = "Orange, orange, yellow, black, and brown" + +[4f0ad96c-cdab-4c84-95dd-7074e889e001] +description = "Red, green, yellow, yellow, and brown" + +[48c66841-208c-46a7-8992-1e84a2eda9e2] +description = "Blue, grey, white, brown, and brown" + +[4f3aeb0c-fd9d-4cbd-b204-554e61978f73] +description = "Violet, orange, red, and grey" + +[1ae3a17f-8bc0-449c-9831-fddfd2d91c5d] +description = "Brown, red, orange, green, and blue" diff --git a/exercises/practice/resistor-color-master/resistor_color_master.py b/exercises/practice/resistor-color-master/resistor_color_master.py new file mode 100644 index 00000000000..83fd403e5c2 --- /dev/null +++ b/exercises/practice/resistor-color-master/resistor_color_master.py @@ -0,0 +1,49 @@ +COLORS = [ + 'black', + 'brown', + 'red', + 'orange', + 'yellow', + 'green', + 'blue', + 'violet', + 'grey', + 'white' +] + +COLORS_TOLERANCE = { + 'brown': 1, + 'red': 2, + 'green': 0.5, + 'blue': 0.25, + 'violet': 0.1, + 'grey': 0.05, + 'gold': 5, + 'silver': 10 +} + + +def label(colors): + if len(colors) == 1: + return f'0 ohms' + elif len(colors) == 4: + value = 10 * COLORS.index(colors[0]) + COLORS.index(colors[1]) + value *= 10 ** COLORS.index(colors[2]) + value, unit = color_code(value) + value = int(value) if value.is_integer() else value + return f'{value} {unit} {COLORS_TOLERANCE[colors[3]]}%' + else: + value = 100 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) + value *= 10 ** COLORS.index(colors[3]) + value, unit = color_code(value) + value = int(value) if value.is_integer() else value + return f'{value} {unit} {COLORS_TOLERANCE[colors[4]]}%' + + +def color_code(color): + if color < 1000: + return color / 1, 'ohms' + elif color < 1000000: + return color / 1000, 'kiloohms' + else: + return color / 1000000, 'megaohms' \ No newline at end of file diff --git a/exercises/practice/resistor-color-master/resistor_color_master_test.py b/exercises/practice/resistor-color-master/resistor_color_master_test.py new file mode 100644 index 00000000000..458ca7ab601 --- /dev/null +++ b/exercises/practice/resistor-color-master/resistor_color_master_test.py @@ -0,0 +1,51 @@ +import unittest + +from resistor_color_master import ( + label, +) + +# Tests adapted from `problem-specifications//canonical-data.json` + + +class ResistorColorMasterTest(unittest.TestCase): + def test_orange_orange_black_and_red(self): + self.assertEqual(label(["orange", "orange", "black", "red"]), "33 ohms 2%") + + def test_blue_grey_brown_and_violet(self): + self.assertEqual(label(["blue", "grey", "brown", "violet"]), "680 ohms 0.1%") + + def test_red_black_red_and_green(self): + self.assertEqual(label(["red", "black", "red", "green"]), "2 kiloohms 0.5%") + + def test_green_brown_orange_and_grey(self): + self.assertEqual( + label(["green", "brown", "orange", "grey"]), "51 kiloohms 0.05%" + ) + + def test_one_black_band(self): + self.assertEqual(label(["black"]), "0 ohms") + + def test_orange_orange_yellow_black_and_brown(self): + self.assertEqual( + label(["orange", "orange", "yellow", "black", "brown"]), "334 ohms 1%" + ) + + def test_red_green_yellow_yellow_and_brown(self): + self.assertEqual( + label(["red", "green", "yellow", "yellow", "brown"]), "2.54 megaohms 1%" + ) + + def test_blue_grey_white_red_and_brown(self): + self.assertEqual( + label(["blue", "grey", "white", "red", "brown"]), "6.89 kiloohms 1%" + ) + + def test_violet_orange_red_and_grey(self): + self.assertEqual( + label(["violet", "orange", "red", "grey"]), "7.3 kiloohms 0.05%" + ) + + def test_brown_red_orange_green_and_blue(self): + self.assertEqual( + label(["brown", "red", "orange", "green", "blue"]), "12.3 megaohms 0.25%" + ) From 3494dcddb522cbb259d3661b98bfdcbaa86c5e57 Mon Sep 17 00:00:00 2001 From: Carl Date: Sun, 25 Dec 2022 19:38:44 +0100 Subject: [PATCH 066/126] Fix --- config.json | 2 +- .../resistor-color-master/resistor_color_master_test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.json b/config.json index 84c5f1ea6fc..e9a513fafb8 100644 --- a/config.json +++ b/config.json @@ -973,7 +973,7 @@ { "slug": "resistor-color-master", "name": "Resistor Color Master", - "uuid": "f987a5b7-96f2-49c2-99e8-aef30d23dd58", + "uuid": "8a738365-0efa-444f-9466-a757ddaddcdb", "practices": ["list-methods"], "prerequisites": [ "basics", diff --git a/exercises/practice/resistor-color-master/resistor_color_master_test.py b/exercises/practice/resistor-color-master/resistor_color_master_test.py index 458ca7ab601..cd595fe4524 100644 --- a/exercises/practice/resistor-color-master/resistor_color_master_test.py +++ b/exercises/practice/resistor-color-master/resistor_color_master_test.py @@ -37,7 +37,7 @@ def test_red_green_yellow_yellow_and_brown(self): def test_blue_grey_white_red_and_brown(self): self.assertEqual( - label(["blue", "grey", "white", "red", "brown"]), "6.89 kiloohms 1%" + label(["blue", "grey", "white", "brown", "brown"]), "6.89 kiloohms 1%" ) def test_violet_orange_red_and_grey(self): From f168108f0e30a634e2aa01117c19b50b10a5fd12 Mon Sep 17 00:00:00 2001 From: Carl Date: Sun, 25 Dec 2022 19:41:40 +0100 Subject: [PATCH 067/126] Fixed example --- .../practice/resistor-color-master/.meta/example.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/exercises/practice/resistor-color-master/.meta/example.py b/exercises/practice/resistor-color-master/.meta/example.py index a7dd1cd367e..83fd403e5c2 100644 --- a/exercises/practice/resistor-color-master/.meta/example.py +++ b/exercises/practice/resistor-color-master/.meta/example.py @@ -30,17 +30,19 @@ def label(colors): value = 10 * COLORS.index(colors[0]) + COLORS.index(colors[1]) value *= 10 ** COLORS.index(colors[2]) value, unit = color_code(value) - return f'{value} {unit}, {COLORS_TOLERANCE[colors[3]]}%' + value = int(value) if value.is_integer() else value + return f'{value} {unit} {COLORS_TOLERANCE[colors[3]]}%' else: - value = 10 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) + value = 100 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) value *= 10 ** COLORS.index(colors[3]) value, unit = color_code(value) - return f'{value} {unit}, {COLORS_TOLERANCE[colors[4]]}%' + value = int(value) if value.is_integer() else value + return f'{value} {unit} {COLORS_TOLERANCE[colors[4]]}%' def color_code(color): if color < 1000: - return color, 'ohms' + return color / 1, 'ohms' elif color < 1000000: return color / 1000, 'kiloohms' else: From 3df9a8008e8e9d776507b5cb16766b352856dcd2 Mon Sep 17 00:00:00 2001 From: Carl Date: Sun, 25 Dec 2022 19:42:39 +0100 Subject: [PATCH 068/126] Added instructions --- .../.docs/instructions.md | 72 +++++++++++++------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/exercises/practice/resistor-color-master/.docs/instructions.md b/exercises/practice/resistor-color-master/.docs/instructions.md index fcc76958a5f..8263897d07f 100644 --- a/exercises/practice/resistor-color-master/.docs/instructions.md +++ b/exercises/practice/resistor-color-master/.docs/instructions.md @@ -1,7 +1,7 @@ -# Instructions +# Description If you want to build something using a Raspberry Pi, you'll probably use _resistors_. -For this exercise, you need to know only three things about them: +For this exercise, you need to be able to use 1, 4, and 5 bands resistor: - Each resistor has a resistance value. - Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. @@ -9,7 +9,7 @@ For this exercise, you need to know only three things about them: - Each band acts as a digit of a number. For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. - The program will take 3 colors as input, and outputs the correct value, in ohms. + The program will take 1, 4, or 5 colors as input, and outputs the correct value, in ohms. The color bands are encoded as follows: - Black: 0 @@ -23,32 +23,64 @@ For this exercise, you need to know only three things about them: - Grey: 8 - White: 9 -In `resistor-color duo` you decoded the first two colors. -For instance: orange-orange got the main value `33`. -The third color stands for how many zeros need to be added to the main value. -The main value plus the zeros gives us a value in ohms. -For the exercise it doesn't matter what ohms really are. -For example: +In `resistor-color trio` you decoded the first three colors. +For instance: orange-orange-brown got the main value `330`. +In this exercise you need to add tolerance to the mix. +Tolerance is the maximum amount that the value can be above or below the main value. +The tolerance value is always the last band. +For example, if the last band is green, the maximum tolerance will be 0.5%. +The tolerance band will have one of these values: -- orange-orange-black would be 33 and no zeros, which becomes 33 ohms. -- orange-orange-red would be 33 and 2 zeros, which becomes 3300 ohms. -- orange-orange-orange would be 33 and 3 zeros, which becomes 33000 ohms. +- Grey - 0.05% +- Violet - 0.1% +- Blue - 0.25% +- Green - 0.5% +- Brown - 1% +- Red - 2% +- Gold - 5% +- Silver - 10% -(If Math is your thing, you may want to think of the zeros as exponents of 10. -If Math is not your thing, go with the zeros. -It really is the same thing, just in plain English instead of Math lingo.) +The fourth band resistor is built up like these: + +| Band_1 | Band_2 | Band_3 | band_4 | +| ------- | ------- | ---------- | --------- | +| Value_1 | Value_2 | Multiplier | Tolerance | + +Meaning + +- orange-orange-brown-green would be 330 ohms with a 0.5% tolerance. +- orange-orange-red would-grey would be 3300 ohms with 0.005 tolerance. + +The difference between the 4 and 5 band resistor is that there is an extra band for value a more precises value. + +| Band_1 | Band_2 | Band_3 | Band_4 | band_5 | +| ------- | ------- | ------- | ---------- | --------- | +| Value_1 | Value_2 | Value_3 | Multiplier | Tolerance | + +Meaning + +- orange-orange-orange-black-green would be 330 ohms with a 0.5% tolerance. + +There will also be a one band resistor. +This resistor will only have the color black and have the value 0. This exercise is about translating the colors into a label: -> "... ohms" +> "... ohms ...%" -So an input of `"orange", "orange", "black"` should return: +So an input of `"orange", "orange", "black, green"` should return: -> "33 ohms" +> "33 ohms 0.5%" When we get more than a thousand ohms, we say "kiloohms". That's similar to saying "kilometer" for 1000 meters, and "kilograms" for 1000 grams. -So an input of `"orange", "orange", "orange"` should return: +So an input of `"orange", "orange", "orange", grey` should return: + +> "33 kiloohms 0.05%" + +When we get more than a million ohms, we say "megaohms". + +So an input of `"orange", "orange", "orange", "red"` should return: -> "33 kiloohms" +> "33 megaohms 2%" From 4e60f5829d11048b847bdc73cc5c6d39b2ef502e Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 00:26:04 +0100 Subject: [PATCH 069/126] Changes --- concepts/itertools/.meta/config.json | 4 +- concepts/itertools/about.md | 341 +----------------- concepts/itertools/links.json | 4 +- .../resistor-color-master/.meta/template.j2 | 6 +- 4 files changed, 10 insertions(+), 345 deletions(-) diff --git a/concepts/itertools/.meta/config.json b/concepts/itertools/.meta/config.json index 3bf2b514ccf..65190cc1ef5 100644 --- a/concepts/itertools/.meta/config.json +++ b/concepts/itertools/.meta/config.json @@ -1,5 +1,5 @@ { "blurb": "TODO: add blurb for this concept", - "authors": ["bethanyg", "meatball133"], + "authors": ["bethanyg", "cmccandless"], "contributors": [] -} +} \ No newline at end of file diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index 366515cf1aa..cbc5cd89d96 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -1,340 +1 @@ -## Iterators terminating on the shortest input sequence - -### Chain() - -`chain(iterable1, iterable2...)` creates an irretator of values from the iterables in the order they are given. - -```python ->>> import itertools ->>> for number in itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9]): -... print(number, end=' ') -... -1 2 3 4 5 6 7 8 9 -``` - -Chain can also be used to concate a different amount of iterables to a list or tuple by using the `list()` or `tuple()` function. - -Using `list()`: - -```python ->>> import itertools ->>> list(itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9])) -[1, 2, 3, 4, 5, 6, 7, 8, 9] -``` - -Using `tuple()`: - -```python ->>> import itertools ->>> tuple(itertools.chain([1, 2, 3], [4, 5, 6], [7, 8, 9])) -(1, 2, 3, 4, 5, 6, 7, 8, 9) -``` - -### chain.from_iterable() - -Works like chain but takes a single nested iterable, unpacking that iterable into individual iterables. - -```python ->>> import itertools ->>> for number in itertools.chain.from_iterable( - [ - [1, 2, 3], - [4, 5, 6], - [7, 8, 9] - ]): -... print(number, end=' ') -... -1 2 3 4 5 6 7 8 9 -``` - -### Compress() - -`compress(iterable, selectors)` creates an iterator from the input iterable where the corresponding selector is `True`. -The selector can be `True`/`False` or integers, where 0 is `False` and 1 is `True`. - -```python ->>> import itertools ->>> for letter in itertools.compress("Exercism", [1, 0, 0, 1, 1, 0, 1, 1]): -... print(letter, end=' ') -... -E r c s m -``` - -With `True`/`False`: - -```python ->>> import itertools ->>> for letter in itertools.compress("Exercism", [True, False, False, True, True, False, True, True]): -... print(letter, end=' ') -... -E r c s m -``` - -### Islice() - -`islice(iterable, start, , )` creates a new iterator from the slice (from the start index to the stop index with a step size of step). - -```python ->>> import itertools ->>> for letter in itertools.islice("Exercism", 2, 5, 2): -... print(letter, end=' ') -... -e c -``` - -### Pairwise() - -```exercism/note -`Pairwise()` requires Python 3.10+. -If you are using the online editor then you don't need to worry about this. -``` - -`Pairwise(iterable)` was intruduced in Python 3.10 and returns an iterator of overlapping pairs of values from the input iterable. - -```python ->>> import itertools ->>> for pair in itertools.pairwise("Exercism"): -... print(pair, end=' ') -... -('E', 'x') ('x', 'e') ('e', 'r') ('r', 'c') ('c', 'i') ('i', 's') ('s', 'm') -``` - -### Tee() - -Talk with Bethany about - -### Zip_longest() - -#### Explaning zip - -```exercism/caution -Pythons `zip()` function should not be confused with the zip compression format. -``` - -`zip()` is a built in function and is not apart of the `itertools` module. -It takes any number of iterables and returns an iterator of tuples. -Where the i-th tuple contains the i-th element from each of the argument iterables. -For example, the first tuple will contain the first element from each iterable, the second tuple will contain the second element from each iterable, and so on until the shortest iterable is exhausted. - -```python ->>> zipped = zip(['x', 'y', 'z'], [1, 2, 3], [True, False, True]) ->>> list(zipped) -[('x', 1, True),('y', 2, False), ('z', 3, True)] -``` - -If the iterables are not the same length, then the iterator will stop when the shortest iterable is exhausted. - -```python ->>> zipped = zip(['x', 'y', 'z'], [1, 2, 3, 4], [True, False]) ->>> list(zipped) -[('x', 1, True),('y', 2, False)] -``` - -#### Explaning zip_longest - -`zip_longest(iterator, )` is a function from the `itertools` module. -Unlink `zip()`, it will not stop when the shortest iterable is exhausted. -If the iterables are not the same length, `fillvalue` will be used to pad missing values. -By the default the `fillvalue` is `None`. - -```python ->>> import itertools ->>> zipped = itertools.zip_longest(['x', 'y', 'z'], [1, 2, 3, 4], [True, False]) ->>> list(zipped) -[('x', 1, True),('y', 2, False), ('z', 3, None), (None, 4, None)] -``` - -An example where a fillvalue is given: - -```python ->>> import itertools ->>> zipped = itertools.zip_longest(['x', 'y', 'z'], [1, 2, 3, 4], [True, False], fillvalue='fill') ->>> list(zipped) -[('x', 1, True),('y', 2, False), ('z', 3, 'fill'), ('fill', 4, 'fill')] -``` - -## Combinatoric iterators - -### Product() - -`product(iterable1, iterable2..., )` creates an iterator of tuples where the i-th tuple contains the i-th element from each of the argument iterables. -The repeat keyword argument can be used to specify the number of times the input iterables are repeated. -By default the repeat keyword argument is 1. - -```python ->>> import itertools ->>> for product in itertools.product("ABCD", repeat=1): -... print(product, end=' ') -... -('A',) ('B',) ('C',) ('D',) -``` - -Giving a repeat value of 2: - -```python ->>> import itertools ->>> for product in itertools.product("ABCD", repeat=2): -... print(product, end=' ') -... -('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'A') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'A') ('C', 'B') ('C', 'C') ('C', 'D') ('D', 'A') ('D', 'B') ('D', 'C') ('D', 'D') -``` - -The last one here can be seen as doing a nested for loop. -When you increase the repeat value the number of iterations increases exponentially. -The example above is a n\*\*2 iteration. - -```python ->>> import itertools ->>> for letter1 in "ABCD": -... for letter2 in "ABCD": -... print((letter1, letter2), end=' ') -... -('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'A') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'A') ('C', 'B') ('C', 'C') ('C', 'D') ('D', 'A') ('D', 'B') ('D', 'C') ('D', 'D') -``` - -You can also give it multiple iterables. - -```python ->>> import itertools ->>> for product in itertools.product("ABCD", "xy" repeat=1): -... print(product, end=' ') -... -('A', 'x') ('A', 'y') ('B', 'x') ('B', 'y') ('C', 'x') ('C', 'y') ('D', 'x') ('D', 'y') -``` - -Here is an example of doing it wihout `product()`. -It looks similliar to the last example but since we have two iterables we need to nest the for loops. -Even though the proudct is given repeat=1. -The reasson to why it is only 2 for loops earlier was because we only had one iterable. -If we had two iterables and gave it repeat=2 we would need 4 for loops. -Since 2 \* 2 = 4. - -```python ->>> for letter1 in "ABCD": -... for letter2 in "xy": -... print((letter1, letter2), end=' ') -... -('A', 'x') ('A', 'y') ('B', 'x') ('B', 'y') ('C', 'x') ('C', 'y') ('D', 'x') ('D', 'y') -``` - -### Permutations() - -`permutations(iterable, )` creates an iterator of tuples. -It works like `product()` but it doesnt repeat values from a specific positoon from the iterable and can only take one iterable. -The "r" keyword argument can be used to specify the number of times the input iterables are repeated. -By default the "r" keyword argument is None. -If "r" is None then the length of the iterable is used. - -```python ->>> import itertools ->>> for permutation in itertools.permutations("ABCD", repeat=1): -... print(permutation, end=' ') -... -('A',) ('B',) ('C',) ('D',) -``` - -```python ->>> import itertools ->>> for permutation in itertools.permutations("ABCD", repeat=2): -... print(permutation, end=' ') -... -('A', 'B') ('A', 'C') ('A', 'D') ('B', 'A') ('B', 'C') ('B', 'D') ('C', 'A') ('C', 'B') ('C', 'D') ('D', 'A') ('D', 'B') ('D', 'C') -``` - -### Combinations() - -`combinations(iterable, r)` finds all the possible combinations of the given iterable. -The r keyword argument is used to specify the length of the tuples generated. - -```python ->>> import itertools ->>> for combination in itertools.combinations("ABCD", 2): -... print(combination, end=' ') -... -('A', 'B') ('A', 'C') ('A', 'D') ('B', 'C') ('B', 'D') ('C', 'D') -``` - -### Combinations_with_replacement() - -`combinations_with_replacement(iterable, r)` finds all the possible combinations of the given iterable. -The r keyword argument is used to specify the length of the tuples generated. -The difference between this and `combinations()` is that it can repeat values. - -```python ->>> import itertools ->>> for combination in itertools.combinations_with_replacement("ABCD", 2): -... print(combination, end=' ') -... -('A', 'A') ('A', 'B') ('A', 'C') ('A', 'D') ('B', 'B') ('B', 'C') ('B', 'D') ('C', 'C') ('C', 'D') ('D', 'D') -``` - -## Infinite iterators - -Most of iterator from the `itertools` module get exhausted after a time. -But there are some that are infinite, these are known as infinte iterators. -These iterators will will keep producing values until you tell them to stop. - -```exercism/note -To avoid infinite loops, you can use `break` to end a loop. -``` - -### Count() - -`count(start, )` produces all values from the start value to infinity. -Count also has an optional step parameter, which will produce values with a step size other than 1. - -```python ->>> import itertools ->>> for number in itertools.count(5, 2): -... if number > 20: -... break -... else: -... print(number, end=' ') -... -5 7 9 11 13 15 17 19 -``` - -Giving `count()` a negative step size will produces values in a descending order. - -```python ->>> import itertools ->>> for number in itertools.count(5, -2): -... if number < -20: -... break -... else: -... print(number, end=' ') -... -5 3 1 -1 -3 -5 -7 -9 -11 -13 -15 -17 -19 -``` - -### Cycle() - -`cycle(iterable)` produces all values from the iterable in an infinte loop. -A `list`, `tuple`, `string`, `dict` or any other iterable can be used. - -```python ->>> import itertools ->>> number = 0 ->>> for letter in itertools.cycle("ABC"): -... if number == 10: -... break -... else: -... print(letter, end=' ') -... number += 1 -... -A B C A B C A B C A -``` - -### Repeat() - -`repeat(object, )` produces the same value in an infinte loop. -Although if the optional times parameter is given, the value will produces that many times. -Meaning that it is not an infinite loop if that parameter is given. - -```python ->>> import itertools ->>> for number in itertools.repeat(5, 3): -... print(number, end=' ') -... -5 5 5 -``` +#TODO: Add about for this concept. diff --git a/concepts/itertools/links.json b/concepts/itertools/links.json index 8a44906b3f8..eb5fb7c38a5 100644 --- a/concepts/itertools/links.json +++ b/concepts/itertools/links.json @@ -1,7 +1,7 @@ [ { - "url": "https://docs.python.org/3/library/itertools.htm", - "description": "Offical Python documentation for the itertools module." + "url": "http://example.com/", + "description": "TODO: add new link (above) and write a short description here of the resource." }, { "url": "http://example.com/", diff --git a/exercises/practice/resistor-color-master/.meta/template.j2 b/exercises/practice/resistor-color-master/.meta/template.j2 index e9b458f34c3..86f9580c5fe 100644 --- a/exercises/practice/resistor-color-master/.meta/template.j2 +++ b/exercises/practice/resistor-color-master/.meta/template.j2 @@ -4,7 +4,11 @@ def test_{{ case["description"] | to_snake }}(self): self.assertEqual( {{ case["property"] | to_snake }}({{ case["input"]["colors"] }}), - "{{ case['expected']['value']}} {{ case['expected']['unit']}} {{case['expected']['tolerance']}}{{"%" if case['expected']['tolerance'] else ""}}" + {%- if case['expected']['tolerance'] %} + "{{ case['expected']['value']}} {{ case['expected']['unit']}} {{case['expected']['tolerance']}}%" + {%- else -%} + "{{ case['expected']['value']}} {{ case['expected']['unit']}}" + {% endif %} ) {%- endmacro %} {{ macros.header()}} From fe65f19b1cb4892ecdd72a08d160835073af25c3 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Mon, 26 Dec 2022 00:26:59 +0100 Subject: [PATCH 070/126] Delete about.md --- concepts/itertools/about.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 concepts/itertools/about.md diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md deleted file mode 100644 index cbc5cd89d96..00000000000 --- a/concepts/itertools/about.md +++ /dev/null @@ -1 +0,0 @@ -#TODO: Add about for this concept. From 4afba06f43420b7319489d6ef0a6e226ec36b042 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Mon, 26 Dec 2022 00:27:09 +0100 Subject: [PATCH 071/126] Delete config.json --- concepts/itertools/.meta/config.json | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 concepts/itertools/.meta/config.json diff --git a/concepts/itertools/.meta/config.json b/concepts/itertools/.meta/config.json deleted file mode 100644 index 65190cc1ef5..00000000000 --- a/concepts/itertools/.meta/config.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "blurb": "TODO: add blurb for this concept", - "authors": ["bethanyg", "cmccandless"], - "contributors": [] -} \ No newline at end of file From 9374285a09f3b7556ca2b1b4ec61fd5a46929168 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 00:29:55 +0100 Subject: [PATCH 072/126] some stuff --- concepts/itertools/.meta/config.json | 5 +++++ concepts/itertools/introduction copy.md | 1 + 2 files changed, 6 insertions(+) create mode 100644 concepts/itertools/.meta/config.json create mode 100644 concepts/itertools/introduction copy.md diff --git a/concepts/itertools/.meta/config.json b/concepts/itertools/.meta/config.json new file mode 100644 index 00000000000..9b9e8da5a9b --- /dev/null +++ b/concepts/itertools/.meta/config.json @@ -0,0 +1,5 @@ +{ + "blurb": "TODO: add blurb for this concept", + "authors": ["bethanyg", "cmccandless"], + "contributors": [] +} diff --git a/concepts/itertools/introduction copy.md b/concepts/itertools/introduction copy.md new file mode 100644 index 00000000000..bbe12ffd5e9 --- /dev/null +++ b/concepts/itertools/introduction copy.md @@ -0,0 +1 @@ +#TODO: Add introduction for this concept. From b4e47d3f0747be0658daaa9b1e7423c1a5b6d951 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 00:30:37 +0100 Subject: [PATCH 073/126] some more --- concepts/itertools/{introduction copy.md => about.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename concepts/itertools/{introduction copy.md => about.md} (100%) diff --git a/concepts/itertools/introduction copy.md b/concepts/itertools/about.md similarity index 100% rename from concepts/itertools/introduction copy.md rename to concepts/itertools/about.md From ac0acdde7f03a899297275cc1da867fa436f6727 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Mon, 26 Dec 2022 00:31:42 +0100 Subject: [PATCH 074/126] Update about.md --- concepts/itertools/about.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index bbe12ffd5e9..cbc5cd89d96 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -1 +1 @@ -#TODO: Add introduction for this concept. +#TODO: Add about for this concept. From 9d73b67a7e9a6408f443eae3052a674da0c0070c Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Mon, 26 Dec 2022 00:31:53 +0100 Subject: [PATCH 075/126] Update about.md --- concepts/itertools/about.md | 1 + 1 file changed, 1 insertion(+) diff --git a/concepts/itertools/about.md b/concepts/itertools/about.md index cbc5cd89d96..c628150d565 100644 --- a/concepts/itertools/about.md +++ b/concepts/itertools/about.md @@ -1 +1,2 @@ #TODO: Add about for this concept. + From 03216728fc80b1b48f11a8b01b37ac4d9e9acd14 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 00:33:31 +0100 Subject: [PATCH 076/126] fix --- .../resistor-color-master/.meta/{hi.json => canonical-data.json} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename exercises/practice/resistor-color-master/.meta/{hi.json => canonical-data.json} (100%) diff --git a/exercises/practice/resistor-color-master/.meta/hi.json b/exercises/practice/resistor-color-master/.meta/canonical-data.json similarity index 100% rename from exercises/practice/resistor-color-master/.meta/hi.json rename to exercises/practice/resistor-color-master/.meta/canonical-data.json From 85dcb967f51b71ab62e1ae20c1faa5beabf46d14 Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 00:59:27 +0100 Subject: [PATCH 077/126] Updates --- .../resistor-color-master/.meta/template.j2 | 2 +- .../resistor_color_master.py | 49 +------------------ .../resistor_color_master_test.py | 18 +++---- 3 files changed, 11 insertions(+), 58 deletions(-) diff --git a/exercises/practice/resistor-color-master/.meta/template.j2 b/exercises/practice/resistor-color-master/.meta/template.j2 index 86f9580c5fe..b49a7f2fd1f 100644 --- a/exercises/practice/resistor-color-master/.meta/template.j2 +++ b/exercises/practice/resistor-color-master/.meta/template.j2 @@ -5,7 +5,7 @@ self.assertEqual( {{ case["property"] | to_snake }}({{ case["input"]["colors"] }}), {%- if case['expected']['tolerance'] %} - "{{ case['expected']['value']}} {{ case['expected']['unit']}} {{case['expected']['tolerance']}}%" + "{{ case['expected']['value']}} {{ case['expected']['unit']}} ±{{case['expected']['tolerance']}}%" {%- else -%} "{{ case['expected']['value']}} {{ case['expected']['unit']}}" {% endif %} diff --git a/exercises/practice/resistor-color-master/resistor_color_master.py b/exercises/practice/resistor-color-master/resistor_color_master.py index 83fd403e5c2..a4b658ecdd4 100644 --- a/exercises/practice/resistor-color-master/resistor_color_master.py +++ b/exercises/practice/resistor-color-master/resistor_color_master.py @@ -1,49 +1,2 @@ -COLORS = [ - 'black', - 'brown', - 'red', - 'orange', - 'yellow', - 'green', - 'blue', - 'violet', - 'grey', - 'white' -] - -COLORS_TOLERANCE = { - 'brown': 1, - 'red': 2, - 'green': 0.5, - 'blue': 0.25, - 'violet': 0.1, - 'grey': 0.05, - 'gold': 5, - 'silver': 10 -} - - def label(colors): - if len(colors) == 1: - return f'0 ohms' - elif len(colors) == 4: - value = 10 * COLORS.index(colors[0]) + COLORS.index(colors[1]) - value *= 10 ** COLORS.index(colors[2]) - value, unit = color_code(value) - value = int(value) if value.is_integer() else value - return f'{value} {unit} {COLORS_TOLERANCE[colors[3]]}%' - else: - value = 100 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) - value *= 10 ** COLORS.index(colors[3]) - value, unit = color_code(value) - value = int(value) if value.is_integer() else value - return f'{value} {unit} {COLORS_TOLERANCE[colors[4]]}%' - - -def color_code(color): - if color < 1000: - return color / 1, 'ohms' - elif color < 1000000: - return color / 1000, 'kiloohms' - else: - return color / 1000000, 'megaohms' \ No newline at end of file +pass diff --git a/exercises/practice/resistor-color-master/resistor_color_master_test.py b/exercises/practice/resistor-color-master/resistor_color_master_test.py index cd595fe4524..41f5a1f11a3 100644 --- a/exercises/practice/resistor-color-master/resistor_color_master_test.py +++ b/exercises/practice/resistor-color-master/resistor_color_master_test.py @@ -9,17 +9,17 @@ class ResistorColorMasterTest(unittest.TestCase): def test_orange_orange_black_and_red(self): - self.assertEqual(label(["orange", "orange", "black", "red"]), "33 ohms 2%") + self.assertEqual(label(["orange", "orange", "black", "red"]), "33 ohms ±2%") def test_blue_grey_brown_and_violet(self): - self.assertEqual(label(["blue", "grey", "brown", "violet"]), "680 ohms 0.1%") + self.assertEqual(label(["blue", "grey", "brown", "violet"]), "680 ohms ±0.1%") def test_red_black_red_and_green(self): - self.assertEqual(label(["red", "black", "red", "green"]), "2 kiloohms 0.5%") + self.assertEqual(label(["red", "black", "red", "green"]), "2 kiloohms ±0.5%") def test_green_brown_orange_and_grey(self): self.assertEqual( - label(["green", "brown", "orange", "grey"]), "51 kiloohms 0.05%" + label(["green", "brown", "orange", "grey"]), "51 kiloohms ±0.05%" ) def test_one_black_band(self): @@ -27,25 +27,25 @@ def test_one_black_band(self): def test_orange_orange_yellow_black_and_brown(self): self.assertEqual( - label(["orange", "orange", "yellow", "black", "brown"]), "334 ohms 1%" + label(["orange", "orange", "yellow", "black", "brown"]), "334 ohms ±1%" ) def test_red_green_yellow_yellow_and_brown(self): self.assertEqual( - label(["red", "green", "yellow", "yellow", "brown"]), "2.54 megaohms 1%" + label(["red", "green", "yellow", "yellow", "brown"]), "2.54 megaohms ±1%" ) def test_blue_grey_white_red_and_brown(self): self.assertEqual( - label(["blue", "grey", "white", "brown", "brown"]), "6.89 kiloohms 1%" + label(["blue", "grey", "white", "red", "brown"]), "6.89 kiloohms ±1%" ) def test_violet_orange_red_and_grey(self): self.assertEqual( - label(["violet", "orange", "red", "grey"]), "7.3 kiloohms 0.05%" + label(["violet", "orange", "red", "grey"]), "7.3 kiloohms ±0.05%" ) def test_brown_red_orange_green_and_blue(self): self.assertEqual( - label(["brown", "red", "orange", "green", "blue"]), "12.3 megaohms 0.25%" + label(["brown", "red", "orange", "green", "blue"]), "12.3 megaohms ±0.25%" ) From 0baf1fedae7fe0a501c441037b427ba50e491a9c Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 01:01:45 +0100 Subject: [PATCH 078/126] fix --- .../resistor-color-master/resistor_color_master_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/resistor-color-master/resistor_color_master_test.py b/exercises/practice/resistor-color-master/resistor_color_master_test.py index 41f5a1f11a3..27ac0f82a87 100644 --- a/exercises/practice/resistor-color-master/resistor_color_master_test.py +++ b/exercises/practice/resistor-color-master/resistor_color_master_test.py @@ -37,7 +37,7 @@ def test_red_green_yellow_yellow_and_brown(self): def test_blue_grey_white_red_and_brown(self): self.assertEqual( - label(["blue", "grey", "white", "red", "brown"]), "6.89 kiloohms ±1%" + label(["blue", "grey", "white", "brown", "brown"]), "6.89 kiloohms ±1%" ) def test_violet_orange_red_and_grey(self): From ae349aeed63ca425fe2f1a813974dee51d99c36d Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 01:03:42 +0100 Subject: [PATCH 079/126] fix --- .../practice/resistor-color-master/resistor_color_master.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/resistor-color-master/resistor_color_master.py b/exercises/practice/resistor-color-master/resistor_color_master.py index a4b658ecdd4..1d36841cf10 100644 --- a/exercises/practice/resistor-color-master/resistor_color_master.py +++ b/exercises/practice/resistor-color-master/resistor_color_master.py @@ -1,2 +1,2 @@ def label(colors): -pass + pass From 216d0ad83e2bf311dd3047f5cc21d698f85732ac Mon Sep 17 00:00:00 2001 From: Carl Date: Mon, 26 Dec 2022 01:05:51 +0100 Subject: [PATCH 080/126] Fix --- exercises/practice/resistor-color-master/.meta/example.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/exercises/practice/resistor-color-master/.meta/example.py b/exercises/practice/resistor-color-master/.meta/example.py index 83fd403e5c2..b0d1d612b9d 100644 --- a/exercises/practice/resistor-color-master/.meta/example.py +++ b/exercises/practice/resistor-color-master/.meta/example.py @@ -31,13 +31,13 @@ def label(colors): value *= 10 ** COLORS.index(colors[2]) value, unit = color_code(value) value = int(value) if value.is_integer() else value - return f'{value} {unit} {COLORS_TOLERANCE[colors[3]]}%' + return f'{value} {unit} ±{COLORS_TOLERANCE[colors[3]]}%' else: value = 100 * COLORS.index(colors[0]) + 10 * COLORS.index(colors[1]) + COLORS.index(colors[2]) value *= 10 ** COLORS.index(colors[3]) value, unit = color_code(value) value = int(value) if value.is_integer() else value - return f'{value} {unit} {COLORS_TOLERANCE[colors[4]]}%' + return f'{value} {unit} ±{COLORS_TOLERANCE[colors[4]]}%' def color_code(color): From b47657bf90ed025f33f3a7cabc82aebc52e4a5e5 Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 15 Jun 2023 21:16:37 +0200 Subject: [PATCH 081/126] Renamed the exercise --- config.json | 4 +- .../.docs/instructions.md | 76 +++++++++ .../.docs/introduction.md | 10 ++ .../resistor-color-expert/.meta/config.json | 18 +++ .../.meta/example.py | 2 +- .../.meta/tests.toml | 0 .../resistor_color_expert.py | 2 + .../resistor_color_expert_test.py | 51 ++++++ .../.docs/instructions.md | 86 ---------- .../.meta/canonical-data.json | 147 ------------------ .../resistor-color-master/.meta/config.json | 20 --- .../resistor-color-master/.meta/template.j2 | 19 --- .../resistor_color_master.py | 2 - .../resistor_color_master_test.py | 51 ------ 14 files changed, 160 insertions(+), 328 deletions(-) create mode 100644 exercises/practice/resistor-color-expert/.docs/instructions.md create mode 100644 exercises/practice/resistor-color-expert/.docs/introduction.md create mode 100644 exercises/practice/resistor-color-expert/.meta/config.json rename exercises/practice/{resistor-color-master => resistor-color-expert}/.meta/example.py (97%) rename exercises/practice/{resistor-color-master => resistor-color-expert}/.meta/tests.toml (100%) create mode 100644 exercises/practice/resistor-color-expert/resistor_color_expert.py create mode 100644 exercises/practice/resistor-color-expert/resistor_color_expert_test.py delete mode 100644 exercises/practice/resistor-color-master/.docs/instructions.md delete mode 100644 exercises/practice/resistor-color-master/.meta/canonical-data.json delete mode 100644 exercises/practice/resistor-color-master/.meta/config.json delete mode 100644 exercises/practice/resistor-color-master/.meta/template.j2 delete mode 100644 exercises/practice/resistor-color-master/resistor_color_master.py delete mode 100644 exercises/practice/resistor-color-master/resistor_color_master_test.py diff --git a/config.json b/config.json index e9a513fafb8..e8c7f2f505f 100644 --- a/config.json +++ b/config.json @@ -971,8 +971,8 @@ "difficulty": 3 }, { - "slug": "resistor-color-master", - "name": "Resistor Color Master", + "slug": "resistor-color-expert", + "name": "Resistor Color Expert", "uuid": "8a738365-0efa-444f-9466-a757ddaddcdb", "practices": ["list-methods"], "prerequisites": [ diff --git a/exercises/practice/resistor-color-expert/.docs/instructions.md b/exercises/practice/resistor-color-expert/.docs/instructions.md new file mode 100644 index 00000000000..f08801644c5 --- /dev/null +++ b/exercises/practice/resistor-color-expert/.docs/instructions.md @@ -0,0 +1,76 @@ +# Instructions + +In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. +The program will take 1, 4, or 5 colors as input, and outputs the correct value, in ohms. +The color bands are encoded as follows: + +- Black: 0 +- Brown: 1 +- Red: 2 +- Orange: 3 +- Yellow: 4 +- Green: 5 +- Blue: 6 +- Violet: 7 +- Grey: 8 +- White: 9 + +In `resistor-color trio` you decoded the first three colors. +For instance: orange-orange-brown translated to the main value `330`. +In this exercise you will need to add _tolerance_ to the mix. +Tolerance is the maximum amount that a value can be above or below the main value. +For example, if the last band is green, the maximum tolerance will be ±0.5%. + +The tolerance band will have one of these values: + +- Grey - 0.05% +- Violet - 0.1% +- Blue - 0.25% +- Green - 0.5% +- Brown - 1% +- Red - 2% +- Gold - 5% +- Silver - 10% + +The four-band resistor is built up like this: + +| Band_1 | Band_2 | Band_3 | band_4 | +| ------- | ------- | ---------- | --------- | +| Value_1 | Value_2 | Multiplier | Tolerance | + +Meaning + +- orange-orange-brown-green would be 330 ohms with a ±0.5% tolerance. +- orange-orange-red would-grey would be 3300 ohms with ±0.005% tolerance. +The difference between a four and five-band resistor is that the five-band resistor has an extra band to indicate a more precise value. + +| Band_1 | Band_2 | Band_3 | Band_4 | band_5 | +| ------- | ------- | ------- | ---------- | --------- | +| Value_1 | Value_2 | Value_3 | Multiplier | Tolerance | + +Meaning + +- orange-orange-orange-black-green would be 330 ohms with a ±0.5% tolerance. +There are also one band resistors. +This type of resistor only has the color black and has a value of 0. + +This exercise is about translating the resistor band colors into a label: + +"... ohms ...%" + +So an input of "orange", "orange", "black, green" should return: + +"33 ohms ±0.5%" + +When there are more than a thousand ohms, we say "kiloohms". + That's similar to saying "kilometer" for 1000 meters, and "kilograms" for 1000 grams. + +So an input of "orange", "orange", "orange", grey should return: + +"33 kiloohms ±0.05%" + +When there are more than a million ohms, we say "megaohms". + +So an input of "orange", "orange", "orange", "red" should return: + +"33 megaohms ±2%" diff --git a/exercises/practice/resistor-color-expert/.docs/introduction.md b/exercises/practice/resistor-color-expert/.docs/introduction.md new file mode 100644 index 00000000000..1c95695d135 --- /dev/null +++ b/exercises/practice/resistor-color-expert/.docs/introduction.md @@ -0,0 +1,10 @@ +# Introduction + +If you want to build something using a Raspberry Pi, you'll probably use _resistors_. +For this exercise, you need to be able to use 1, 4, and 5 band resistors: + +- Each resistor has a resistance value. +- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. + To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. +- Each band acts as a digit of a number. + For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. diff --git a/exercises/practice/resistor-color-expert/.meta/config.json b/exercises/practice/resistor-color-expert/.meta/config.json new file mode 100644 index 00000000000..66d1121b6a2 --- /dev/null +++ b/exercises/practice/resistor-color-expert/.meta/config.json @@ -0,0 +1,18 @@ +{ + "authors": [ + "meatball133", + "bethanyg" + ], + "files": { + "solution": [ + "resistor_color_expert.py" + ], + "test": [ + "resistor_color_expert_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Convert color codes, as used on resistors with different amounts of bands, to a human-readable label." +} diff --git a/exercises/practice/resistor-color-master/.meta/example.py b/exercises/practice/resistor-color-expert/.meta/example.py similarity index 97% rename from exercises/practice/resistor-color-master/.meta/example.py rename to exercises/practice/resistor-color-expert/.meta/example.py index b0d1d612b9d..0fd6e42fcd9 100644 --- a/exercises/practice/resistor-color-master/.meta/example.py +++ b/exercises/practice/resistor-color-expert/.meta/example.py @@ -23,7 +23,7 @@ } -def label(colors): +def resistor_label(colors): if len(colors) == 1: return f'0 ohms' elif len(colors) == 4: diff --git a/exercises/practice/resistor-color-master/.meta/tests.toml b/exercises/practice/resistor-color-expert/.meta/tests.toml similarity index 100% rename from exercises/practice/resistor-color-master/.meta/tests.toml rename to exercises/practice/resistor-color-expert/.meta/tests.toml diff --git a/exercises/practice/resistor-color-expert/resistor_color_expert.py b/exercises/practice/resistor-color-expert/resistor_color_expert.py new file mode 100644 index 00000000000..f36881c5a0e --- /dev/null +++ b/exercises/practice/resistor-color-expert/resistor_color_expert.py @@ -0,0 +1,2 @@ +def resistor_label(colors): + pass diff --git a/exercises/practice/resistor-color-expert/resistor_color_expert_test.py b/exercises/practice/resistor-color-expert/resistor_color_expert_test.py new file mode 100644 index 00000000000..8d17a36409a --- /dev/null +++ b/exercises/practice/resistor-color-expert/resistor_color_expert_test.py @@ -0,0 +1,51 @@ +import unittest + +from resistor_color_expert import ( + resistor_label, +) + +# Tests adapted from `problem-specifications//canonical-data.json` + + +class ResistorColorMasterTest(unittest.TestCase): + def test_orange_orange_black_and_red(self): + self.assertEqual(resistor_label(["orange", "orange", "black", "red"]), "33 ohms ±2%") + + def test_blue_grey_brown_and_violet(self): + self.assertEqual(resistor_label(["blue", "grey", "brown", "violet"]), "680 ohms ±0.1%") + + def test_red_black_red_and_green(self): + self.assertEqual(resistor_label(["red", "black", "red", "green"]), "2 kiloohms ±0.5%") + + def test_green_brown_orange_and_grey(self): + self.assertEqual( + resistor_label(["green", "brown", "orange", "grey"]), "51 kiloohms ±0.05%" + ) + + def test_one_black_band(self): + self.assertEqual(resistor_label(["black"]), "0 ohms") + + def test_orange_orange_yellow_black_and_brown(self): + self.assertEqual( + resistor_label(["orange", "orange", "yellow", "black", "brown"]), "334 ohms ±1%" + ) + + def test_red_green_yellow_yellow_and_brown(self): + self.assertEqual( + resistor_label(["red", "green", "yellow", "yellow", "brown"]), "2.54 megaohms ±1%" + ) + + def test_blue_grey_white_red_and_brown(self): + self.assertEqual( + resistor_label(["blue", "grey", "white", "brown", "brown"]), "6.89 kiloohms ±1%" + ) + + def test_violet_orange_red_and_grey(self): + self.assertEqual( + resistor_label(["violet", "orange", "red", "grey"]), "7.3 kiloohms ±0.05%" + ) + + def test_brown_red_orange_green_and_blue(self): + self.assertEqual( + resistor_label(["brown", "red", "orange", "green", "blue"]), "12.3 megaohms ±0.25%" + ) diff --git a/exercises/practice/resistor-color-master/.docs/instructions.md b/exercises/practice/resistor-color-master/.docs/instructions.md deleted file mode 100644 index 8263897d07f..00000000000 --- a/exercises/practice/resistor-color-master/.docs/instructions.md +++ /dev/null @@ -1,86 +0,0 @@ -# Description - -If you want to build something using a Raspberry Pi, you'll probably use _resistors_. -For this exercise, you need to be able to use 1, 4, and 5 bands resistor: - -- Each resistor has a resistance value. -- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. - To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. -- Each band acts as a digit of a number. - For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15. - In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands. - The program will take 1, 4, or 5 colors as input, and outputs the correct value, in ohms. - The color bands are encoded as follows: - -- Black: 0 -- Brown: 1 -- Red: 2 -- Orange: 3 -- Yellow: 4 -- Green: 5 -- Blue: 6 -- Violet: 7 -- Grey: 8 -- White: 9 - -In `resistor-color trio` you decoded the first three colors. -For instance: orange-orange-brown got the main value `330`. -In this exercise you need to add tolerance to the mix. -Tolerance is the maximum amount that the value can be above or below the main value. -The tolerance value is always the last band. -For example, if the last band is green, the maximum tolerance will be 0.5%. -The tolerance band will have one of these values: - -- Grey - 0.05% -- Violet - 0.1% -- Blue - 0.25% -- Green - 0.5% -- Brown - 1% -- Red - 2% -- Gold - 5% -- Silver - 10% - -The fourth band resistor is built up like these: - -| Band_1 | Band_2 | Band_3 | band_4 | -| ------- | ------- | ---------- | --------- | -| Value_1 | Value_2 | Multiplier | Tolerance | - -Meaning - -- orange-orange-brown-green would be 330 ohms with a 0.5% tolerance. -- orange-orange-red would-grey would be 3300 ohms with 0.005 tolerance. - -The difference between the 4 and 5 band resistor is that there is an extra band for value a more precises value. - -| Band_1 | Band_2 | Band_3 | Band_4 | band_5 | -| ------- | ------- | ------- | ---------- | --------- | -| Value_1 | Value_2 | Value_3 | Multiplier | Tolerance | - -Meaning - -- orange-orange-orange-black-green would be 330 ohms with a 0.5% tolerance. - -There will also be a one band resistor. -This resistor will only have the color black and have the value 0. - -This exercise is about translating the colors into a label: - -> "... ohms ...%" - -So an input of `"orange", "orange", "black, green"` should return: - -> "33 ohms 0.5%" - -When we get more than a thousand ohms, we say "kiloohms". -That's similar to saying "kilometer" for 1000 meters, and "kilograms" for 1000 grams. - -So an input of `"orange", "orange", "orange", grey` should return: - -> "33 kiloohms 0.05%" - -When we get more than a million ohms, we say "megaohms". - -So an input of `"orange", "orange", "orange", "red"` should return: - -> "33 megaohms 2%" diff --git a/exercises/practice/resistor-color-master/.meta/canonical-data.json b/exercises/practice/resistor-color-master/.meta/canonical-data.json deleted file mode 100644 index b25a6b1acaf..00000000000 --- a/exercises/practice/resistor-color-master/.meta/canonical-data.json +++ /dev/null @@ -1,147 +0,0 @@ -{ - "exercise": "resistor-color-master", - "cases": [ - { - "uuid": "8c4f9fb6-d477-4250-bc57-b325d2be226f", - "description": "Orange, orange, black, and red", - "property": "label", - "input": { - "colors": ["orange", "orange", "black", "red"] - }, - "expected": { - "value": 33, - "tolerance": 2, - "unit": "ohms" - } - }, - { - "uuid": "d1d4a769-9210-43cc-9a14-6af6ce4c0b00", - "description": "Blue, grey, brown, and violet", - "property": "label", - "input": { - "colors": ["blue", "grey", "brown", "violet"] - }, - "expected": { - "value": 680, - "tolerance": 0.1, - "unit": "ohms" - } - }, - { - "uuid": "6af91bc3-8275-4c38-920a-185d30feb5f3", - "description": "Red, black, red, and green", - "property": "label", - "input": { - "colors": ["red", "black", "red", "green"] - }, - "expected": { - "value": 2, - "tolerance": 0.5, - "unit": "kiloohms" - } - }, - { - "uuid": "9c4630bf-0dda-4212-baca-2f5111530b4d", - "description": "Green, brown, orange, and grey", - "property": "label", - "input": { - "colors": ["green", "brown", "orange", "grey"] - }, - "expected": { - "value": 51, - "tolerance": 0.05, - "unit": "kiloohms" - } - }, - { - "uuid": "93b7d0ec-39fb-49f3-bb88-2dd4b8c293af", - "description": "Yellow, violet, yellow, and blue", - "property": "label", - "input": { - "colors": ["yellow", "violet", "yellow", "blue"] - }, - "expected": { - "value": 470, - "tolerance": 0.25, - "unit": "kiloohms" - } - }, - { - "uuid": "5880ddf1-0dc6-4bd0-b9de-5626117cd2c7", - "description": "One black band", - "property": "label", - "input": { - "colors": ["black"] - }, - "expected": { - "value": 0, - "unit": "ohms" - } - }, - { - "uuid": "a5cfda34-3c02-4bda-b183-726791fb43b2", - "description": "Orange, orange, yellow, black, and brown", - "property": "label", - "input": { - "colors": ["orange", "orange", "yellow", "black", "brown"] - }, - "expected": { - "value": 334, - "tolerance": 1, - "unit": "ohms" - } - }, - { - "uuid": "4f0ad96c-cdab-4c84-95dd-7074e889e001", - "description": "Red, green, yellow, yellow, and brown", - "property": "label", - "input": { - "colors": ["red", "green", "yellow", "yellow", "brown"] - }, - "expected": { - "value": 2.54, - "tolerance": 1, - "unit": "megaohms" - } - }, - { - "uuid": "48c66841-208c-46a7-8992-1e84a2eda9e2", - "description": "Blue, grey, white, brown, and brown", - "property": "label", - "input": { - "colors": ["blue", "grey", "white", "brown", "brown"] - }, - "expected": { - "value": 6.89, - "tolerance": 1, - "unit": "kiloohms" - } - }, - { - "uuid": "4f3aeb0c-fd9d-4cbd-b204-554e61978f73", - "description": "Violet, orange, red, and grey", - "property": "label", - "input": { - "colors": ["violet", "orange", "red", "grey"] - }, - "expected": { - "value": 7.3, - "tolerance": 0.05, - "unit": "kiloohms" - } - }, - { - "uuid": "1ae3a17f-8bc0-449c-9831-fddfd2d91c5d", - "description": "Brown, red, orange, green, and blue", - "property": "label", - "input": { - "colors": ["brown", "red", "orange", "green", "blue"] - }, - "expected": { - "value": 12.3, - "tolerance": 0.25, - "unit": "megaohms" - } - } - ] -} diff --git a/exercises/practice/resistor-color-master/.meta/config.json b/exercises/practice/resistor-color-master/.meta/config.json deleted file mode 100644 index 23a09a2cdd9..00000000000 --- a/exercises/practice/resistor-color-master/.meta/config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "authors": [ - "meatball133", - "bethanyg" - ], - "files": { - "solution": [ - "resistor_color_master.py" - ], - "test": [ - "resistor_color_master_test.py" - ], - "example": [ - ".meta/example.py" - ] - }, - "blurb": "Convert color codes, as used on resistors, to a human-readable label.", - "source": "Maud de Vries, Erik Schierboom", - "source_url": "https://github.com/exercism/problem-specifications/issues/1549" -} diff --git a/exercises/practice/resistor-color-master/.meta/template.j2 b/exercises/practice/resistor-color-master/.meta/template.j2 deleted file mode 100644 index b49a7f2fd1f..00000000000 --- a/exercises/practice/resistor-color-master/.meta/template.j2 +++ /dev/null @@ -1,19 +0,0 @@ -{%- import "generator_macros.j2" as macros with context -%} -{% macro test_case(case) -%} - {%- set input = case["input"] -%} - def test_{{ case["description"] | to_snake }}(self): - self.assertEqual( - {{ case["property"] | to_snake }}({{ case["input"]["colors"] }}), - {%- if case['expected']['tolerance'] %} - "{{ case['expected']['value']}} {{ case['expected']['unit']}} ±{{case['expected']['tolerance']}}%" - {%- else -%} - "{{ case['expected']['value']}} {{ case['expected']['unit']}}" - {% endif %} - ) -{%- endmacro %} -{{ macros.header()}} - -class {{ exercise | camel_case }}Test(unittest.TestCase): - {% for case in cases -%} - {{ test_case(case) }} - {% endfor %} diff --git a/exercises/practice/resistor-color-master/resistor_color_master.py b/exercises/practice/resistor-color-master/resistor_color_master.py deleted file mode 100644 index 1d36841cf10..00000000000 --- a/exercises/practice/resistor-color-master/resistor_color_master.py +++ /dev/null @@ -1,2 +0,0 @@ -def label(colors): - pass diff --git a/exercises/practice/resistor-color-master/resistor_color_master_test.py b/exercises/practice/resistor-color-master/resistor_color_master_test.py deleted file mode 100644 index 27ac0f82a87..00000000000 --- a/exercises/practice/resistor-color-master/resistor_color_master_test.py +++ /dev/null @@ -1,51 +0,0 @@ -import unittest - -from resistor_color_master import ( - label, -) - -# Tests adapted from `problem-specifications//canonical-data.json` - - -class ResistorColorMasterTest(unittest.TestCase): - def test_orange_orange_black_and_red(self): - self.assertEqual(label(["orange", "orange", "black", "red"]), "33 ohms ±2%") - - def test_blue_grey_brown_and_violet(self): - self.assertEqual(label(["blue", "grey", "brown", "violet"]), "680 ohms ±0.1%") - - def test_red_black_red_and_green(self): - self.assertEqual(label(["red", "black", "red", "green"]), "2 kiloohms ±0.5%") - - def test_green_brown_orange_and_grey(self): - self.assertEqual( - label(["green", "brown", "orange", "grey"]), "51 kiloohms ±0.05%" - ) - - def test_one_black_band(self): - self.assertEqual(label(["black"]), "0 ohms") - - def test_orange_orange_yellow_black_and_brown(self): - self.assertEqual( - label(["orange", "orange", "yellow", "black", "brown"]), "334 ohms ±1%" - ) - - def test_red_green_yellow_yellow_and_brown(self): - self.assertEqual( - label(["red", "green", "yellow", "yellow", "brown"]), "2.54 megaohms ±1%" - ) - - def test_blue_grey_white_red_and_brown(self): - self.assertEqual( - label(["blue", "grey", "white", "brown", "brown"]), "6.89 kiloohms ±1%" - ) - - def test_violet_orange_red_and_grey(self): - self.assertEqual( - label(["violet", "orange", "red", "grey"]), "7.3 kiloohms ±0.05%" - ) - - def test_brown_red_orange_green_and_blue(self): - self.assertEqual( - label(["brown", "red", "orange", "green", "blue"]), "12.3 megaohms ±0.25%" - ) From b0d3055d9794b27b1691ef7ea5163a4f9960906e Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 15 Jun 2023 21:58:36 +0200 Subject: [PATCH 082/126] Update based on feedback --- exercises/practice/resistor-color-expert/.docs/introduction.md | 2 +- exercises/practice/resistor-color-expert/.meta/config.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/exercises/practice/resistor-color-expert/.docs/introduction.md b/exercises/practice/resistor-color-expert/.docs/introduction.md index 1c95695d135..fd9e05efc4d 100644 --- a/exercises/practice/resistor-color-expert/.docs/introduction.md +++ b/exercises/practice/resistor-color-expert/.docs/introduction.md @@ -1,7 +1,7 @@ # Introduction If you want to build something using a Raspberry Pi, you'll probably use _resistors_. -For this exercise, you need to be able to use 1, 4, and 5 band resistors: +Like the previous `Resistor Color Duo` and `Resistor Color Trio` exercises, you will be translating resistor color bands to human-readable labels. - Each resistor has a resistance value. - Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. diff --git a/exercises/practice/resistor-color-expert/.meta/config.json b/exercises/practice/resistor-color-expert/.meta/config.json index 66d1121b6a2..1450661bb0d 100644 --- a/exercises/practice/resistor-color-expert/.meta/config.json +++ b/exercises/practice/resistor-color-expert/.meta/config.json @@ -14,5 +14,6 @@ ".meta/example.py" ] }, - "blurb": "Convert color codes, as used on resistors with different amounts of bands, to a human-readable label." + "blurb": "Convert color codes as used on resistors with different bands to a human-readable label.", + "source": "Based on earlier resistor color exercises made by Erik Schierboom and Maud de Vries" } From 65a81612c8639b466019e2be4ef538aff889cede Mon Sep 17 00:00:00 2001 From: BethanyG Date: Thu, 15 Jun 2023 13:05:21 -0700 Subject: [PATCH 083/126] Update exercises/practice/resistor-color-expert/.meta/config.json --- exercises/practice/resistor-color-expert/.meta/config.json | 1 + 1 file changed, 1 insertion(+) diff --git a/exercises/practice/resistor-color-expert/.meta/config.json b/exercises/practice/resistor-color-expert/.meta/config.json index 1450661bb0d..e2f35368a54 100644 --- a/exercises/practice/resistor-color-expert/.meta/config.json +++ b/exercises/practice/resistor-color-expert/.meta/config.json @@ -16,4 +16,5 @@ }, "blurb": "Convert color codes as used on resistors with different bands to a human-readable label.", "source": "Based on earlier resistor color exercises made by Erik Schierboom and Maud de Vries" + "source_url": "https://github.com/exercism/problem-specifications/issues/1464" } From 89938cce4c8c52cf3d862fca90e26663f7cc4cf8 Mon Sep 17 00:00:00 2001 From: Carl Date: Thu, 15 Jun 2023 22:09:18 +0200 Subject: [PATCH 084/126] Fixed config.json --- exercises/practice/resistor-color-expert/.meta/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/resistor-color-expert/.meta/config.json b/exercises/practice/resistor-color-expert/.meta/config.json index e2f35368a54..edf50b4a1e1 100644 --- a/exercises/practice/resistor-color-expert/.meta/config.json +++ b/exercises/practice/resistor-color-expert/.meta/config.json @@ -15,6 +15,6 @@ ] }, "blurb": "Convert color codes as used on resistors with different bands to a human-readable label.", - "source": "Based on earlier resistor color exercises made by Erik Schierboom and Maud de Vries" + "source": "Based on earlier resistor color exercises made by Erik Schierboom and Maud de Vries", "source_url": "https://github.com/exercism/problem-specifications/issues/1464" } From 79ca2dc4ab83e1c4e508a5439dce34e2f99d5a1c Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Mon, 12 Jun 2023 09:37:58 +0530 Subject: [PATCH 085/126] author intro + two approaches --- .../practice/sublist/.approaches/config.json | 21 +++++++ .../sublist/.approaches/introduction.md | 58 +++++++++++++++++++ .../.approaches/list-manipulation/content.md | 38 ++++++++++++ .../.approaches/list-manipulation/snippet.txt | 8 +++ .../.approaches/using-strings/content.md | 27 +++++++++ .../.approaches/using-strings/snippet.txt | 8 +++ 6 files changed, 160 insertions(+) create mode 100644 exercises/practice/sublist/.approaches/config.json create mode 100644 exercises/practice/sublist/.approaches/introduction.md create mode 100644 exercises/practice/sublist/.approaches/list-manipulation/content.md create mode 100644 exercises/practice/sublist/.approaches/list-manipulation/snippet.txt create mode 100644 exercises/practice/sublist/.approaches/using-strings/content.md create mode 100644 exercises/practice/sublist/.approaches/using-strings/snippet.txt diff --git a/exercises/practice/sublist/.approaches/config.json b/exercises/practice/sublist/.approaches/config.json new file mode 100644 index 00000000000..1c5eb3838b6 --- /dev/null +++ b/exercises/practice/sublist/.approaches/config.json @@ -0,0 +1,21 @@ +{ + "introduction": { + "authors": ["safwansamsudeen"] + }, + "approaches": [ + { + "uuid": "3593cfe3-5cab-4141-b0a2-329148a66bb6", + "slug": "list-manipulations", + "title": "List manipulation", + "blurb": "Manipulate and check lists to solve the exercise", + "authors": ["safwansamsudeen"] + }, + { + "uuid": "eccd1e1e-6c88-4823-9b25-944eccaa92e7", + "slug": "using-strings", + "title": "Using strings", + "blurb": "Convert the lists to string and use string manipulation to solve the exercise", + "authors": ["safwansamsudeen"] + } + ] +} diff --git a/exercises/practice/sublist/.approaches/introduction.md b/exercises/practice/sublist/.approaches/introduction.md new file mode 100644 index 00000000000..abfcfb70c3a --- /dev/null +++ b/exercises/practice/sublist/.approaches/introduction.md @@ -0,0 +1,58 @@ +# Introduction +There are two broad ways to solve Sublist. + +## General guidance +To write the code, you need to branch out (probably with `if`) into the four different possible conditions, and return the appropriate name of the category. + +## Approach: list manipulation +The direct approach would be to manipulate and check the given lists to solve this. +This solution uses a helper function, which simplifies things, but the approach can be implemented without it. + +```python +SUBLIST = 1 +SUPERLIST = 2 +EQUAL = 3 +UNEQUAL = 4 + +def check_sub_sequences(list_one, list_two): + n1 = len(list_one) + n2 = len(list_two) + return any(list_two[i:i+n1] == list_one for i in range(n2 - n1 + 1)) + +def sublist(list_one, list_two): + if list_one == list_two: + return EQUAL + if check_sub_sequences(list_one, list_two): + return SUBLIST + if check_sub_sequences(list_two, list_one): + return SUPERLIST + return UNEQUAL +``` + +Read more on the [detail of this approach][approach-list-manipulation]. + +## Approach: using strings +Another clever approach is to convert the lists to strings and then use the `in` operator to check for sub-sequences. +Note that this approach is not as performant as the previous one. +```python +SUBLIST = 1 +SUPERLIST = 2 +EQUAL = 3 +UNEQUAL = 4 + +def sublist(list_one, list_two): + list_one_check = (str(list_one).strip("[]") + ",") + list_two_check = (str(list_two).strip("[]") + ",") + + if list_one_check == list_two_check: + return EQUAL + elif list_one_check in list_two_check: + return SUBLIST + elif list_two_check in list_one_check: + return SUPERLIST + return UNEQUAL +``` +To understand more about this approach, [read here][approach-using-strings] + +[approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/list-manipulation +[approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/using-strings \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/list-manipulation/content.md b/exercises/practice/sublist/.approaches/list-manipulation/content.md new file mode 100644 index 00000000000..ac374b730e7 --- /dev/null +++ b/exercises/practice/sublist/.approaches/list-manipulation/content.md @@ -0,0 +1,38 @@ +# List manipulation +The direct approach would be to manipulate and check the given lists to solve this. +This solution uses a helper function, which simplifies things, but the approach can be implemented without it. + +```python +SUBLIST = 1 +SUPERLIST = 2 +EQUAL = 3 +UNEQUAL = 4 + +def check_sub_sequences(list_one, list_two): + n1 = len(list_one) + n2 = len(list_two) + return any(list_two[i:i+n1] == list_one for i in range(n2 - n1 + 1)) + +def sublist(list_one, list_two): + if list_one == list_two: + return EQUAL + if check_sub_sequences(list_one, list_two): + return SUBLIST + if check_sub_sequences(list_two, list_one): + return SUPERLIST + return UNEQUAL +``` + +We first check for equality using the `==` operator, if so, then we return `EQUAL`. +A common way to do this differently would be to return `1` directly, but this is better practice as we [remove magic values][magic values]. + +After that we call `check_sub_sequences` passing in `list_one` and `list_two`. +In the helper function, we check if `any` of the possible sub-sequences in `list_two` of length `n1` (the length of the first list) are equal to the first list. +If so, then we conclude that `list_one` is a `SUBLIST` of `list_two`. + +To find whether `list_one` is a `SUPERLIST` of `list_two`, we just reverse this process - pass in the lists in the opposite order. +Thus, we check if `any` of the possible sub-sequences in `list_one` of length `n2` (the length of the second list) are equal to the second list. + +If none of the above conditions are true, we conclude that the two lists are unequal. + +[magic values]: https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/list-manipulation/snippet.txt b/exercises/practice/sublist/.approaches/list-manipulation/snippet.txt new file mode 100644 index 00000000000..290f8cdd2b8 --- /dev/null +++ b/exercises/practice/sublist/.approaches/list-manipulation/snippet.txt @@ -0,0 +1,8 @@ +def sublist(list_one, list_two): + if list_one == list_two: + return EQUAL + if check_sub_sequences(list_one, list_two): + return SUBLIST + if check_sub_sequences(list_two, list_one): + return SUPERLIST + return UNEQUAL \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/using-strings/content.md b/exercises/practice/sublist/.approaches/using-strings/content.md new file mode 100644 index 00000000000..48ac206fd9c --- /dev/null +++ b/exercises/practice/sublist/.approaches/using-strings/content.md @@ -0,0 +1,27 @@ +# Using strings + +Another clever solution is to convert the lists to strings and then use the `in` operator to check for sub-sequences. +Note that this approach is not as performant as the previous one. +```python +SUBLIST = 1 +SUPERLIST = 2 +EQUAL = 3 +UNEQUAL = 4 + +def sublist(list_one, list_two): + list_one_check = (str(list_one).strip("[]") + ",") + list_two_check = (str(list_two).strip("[]") + ",") + + if list_one_check == list_two_check: + return EQUAL + elif list_one_check in list_two_check: + return SUBLIST + elif list_two_check in list_one_check: + return SUPERLIST + return UNEQUAL +``` +Note that we can't use `.join` as it only accepts strings inside the iterable, while there the test cases have integers. + +In this approach, we convert the lists to strings, so `[1, 2, 3]` becomes `"[1, 2, 3]"`, remove the brackets `"1, 2, 3"`, and add a comma `"1, 2, 3,"` so that there's a consistent pattern of number + comma while using the `in` operator. + +We check equality and then use the `in` operator to check for `SUBLIST` or `SUPERLIST`, and finally return `UNEQUAL`. \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/using-strings/snippet.txt b/exercises/practice/sublist/.approaches/using-strings/snippet.txt new file mode 100644 index 00000000000..ff7a2563bec --- /dev/null +++ b/exercises/practice/sublist/.approaches/using-strings/snippet.txt @@ -0,0 +1,8 @@ +def sublist(list_one, list_two): + list_one_check = (str(list_one).strip("[]") + ",") + list_two_check = (str(list_two).strip("[]") + ",") + ... + elif list_one_check in list_two_check: + return SUBLIST + ... + return UNEQUAL \ No newline at end of file From 71998301caf084dea6121c1f69430bb6a75bf629 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Mon, 12 Jun 2023 09:52:35 +0530 Subject: [PATCH 086/126] minor corrections --- exercises/practice/sublist/.approaches/introduction.md | 2 +- .../practice/sublist/.approaches/using-strings/content.md | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/exercises/practice/sublist/.approaches/introduction.md b/exercises/practice/sublist/.approaches/introduction.md index abfcfb70c3a..8cd30870cca 100644 --- a/exercises/practice/sublist/.approaches/introduction.md +++ b/exercises/practice/sublist/.approaches/introduction.md @@ -55,4 +55,4 @@ def sublist(list_one, list_two): To understand more about this approach, [read here][approach-using-strings] [approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/list-manipulation -[approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/using-strings \ No newline at end of file +[approach-using-strings]: https://exercism.org/tracks/python/exercises/sublist/approaches/using-strings \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/using-strings/content.md b/exercises/practice/sublist/.approaches/using-strings/content.md index 48ac206fd9c..f49f59309cb 100644 --- a/exercises/practice/sublist/.approaches/using-strings/content.md +++ b/exercises/practice/sublist/.approaches/using-strings/content.md @@ -20,8 +20,11 @@ def sublist(list_one, list_two): return SUPERLIST return UNEQUAL ``` -Note that we can't use `.join` as it only accepts strings inside the iterable, while there the test cases have integers. +Note that we can't use directly `.join` as it only accepts strings inside the iterable, while there the test cases have integers. +However, if one wanted to use it, we could use `map` or a [generator expression][gen-exp] inside `.join`. In this approach, we convert the lists to strings, so `[1, 2, 3]` becomes `"[1, 2, 3]"`, remove the brackets `"1, 2, 3"`, and add a comma `"1, 2, 3,"` so that there's a consistent pattern of number + comma while using the `in` operator. -We check equality and then use the `in` operator to check for `SUBLIST` or `SUPERLIST`, and finally return `UNEQUAL`. \ No newline at end of file +We check equality and then use the `in` operator to check for `SUBLIST` or `SUPERLIST`, and finally return `UNEQUAL`. + +[gen-exp]: https://www.programiz.com/python-programming/generator \ No newline at end of file From 50069bc2f512855b3807a66f82e79e66a9cb556f Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Mon, 12 Jun 2023 09:54:31 +0530 Subject: [PATCH 087/126] correct config errors --- exercises/practice/sublist/.approaches/config.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/practice/sublist/.approaches/config.json b/exercises/practice/sublist/.approaches/config.json index 1c5eb3838b6..ce54db9c14e 100644 --- a/exercises/practice/sublist/.approaches/config.json +++ b/exercises/practice/sublist/.approaches/config.json @@ -4,14 +4,14 @@ }, "approaches": [ { - "uuid": "3593cfe3-5cab-4141-b0a2-329148a66bb6", - "slug": "list-manipulations", + "uuid": "db47397a-4551-49e8-8775-7e7aad79a38b", + "slug": "list-manipulation", "title": "List manipulation", "blurb": "Manipulate and check lists to solve the exercise", "authors": ["safwansamsudeen"] }, { - "uuid": "eccd1e1e-6c88-4823-9b25-944eccaa92e7", + "uuid": "61366160-c859-4d16-9085-171428209b8d", "slug": "using-strings", "title": "Using strings", "blurb": "Convert the lists to string and use string manipulation to solve the exercise", From a260525ea900c47b4d14bbe5600bf6d5428f9ced Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen Date: Thu, 15 Jun 2023 06:45:02 +0530 Subject: [PATCH 088/126] correct approach --- .../sublist/.approaches/introduction.md | 8 +++-- .../.approaches/using-strings/content.md | 33 ++++++++++++++----- .../.approaches/using-strings/snippet.txt | 4 +-- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/exercises/practice/sublist/.approaches/introduction.md b/exercises/practice/sublist/.approaches/introduction.md index 8cd30870cca..ac426baec6e 100644 --- a/exercises/practice/sublist/.approaches/introduction.md +++ b/exercises/practice/sublist/.approaches/introduction.md @@ -32,8 +32,9 @@ def sublist(list_one, list_two): Read more on the [detail of this approach][approach-list-manipulation]. ## Approach: using strings -Another clever approach is to convert the lists to strings and then use the `in` operator to check for sub-sequences. -Note that this approach is not as performant as the previous one. +Another seemingly clever approach is to convert the lists to strings and then +use the `in` operator to check for sub-sequences. +**However, this does not work.** ```python SUBLIST = 1 SUPERLIST = 2 @@ -52,7 +53,8 @@ def sublist(list_one, list_two): return SUPERLIST return UNEQUAL ``` -To understand more about this approach, [read here][approach-using-strings] +To understand more about this approach and **why it fails**, [read here] +[approach-using-strings]. [approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/list-manipulation [approach-using-strings]: https://exercism.org/tracks/python/exercises/sublist/approaches/using-strings \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/using-strings/content.md b/exercises/practice/sublist/.approaches/using-strings/content.md index f49f59309cb..ff960902dc9 100644 --- a/exercises/practice/sublist/.approaches/using-strings/content.md +++ b/exercises/practice/sublist/.approaches/using-strings/content.md @@ -1,7 +1,13 @@ # Using strings +~~~~exercism/caution +**This approach does not work, and this document exists to explain that.** +Please do not use it in your code. +~~~~ -Another clever solution is to convert the lists to strings and then use the `in` operator to check for sub-sequences. -Note that this approach is not as performant as the previous one. +Another seemingly clever solution is to convert the lists to strings and then +use the `in` operator to check for sub-sequences. +Note that this approach, even if it worked, is not as performant as the +previous one. ```python SUBLIST = 1 SUPERLIST = 2 @@ -9,8 +15,8 @@ EQUAL = 3 UNEQUAL = 4 def sublist(list_one, list_two): - list_one_check = (str(list_one).strip("[]") + ",") - list_two_check = (str(list_two).strip("[]") + ",") + list_one_check = str(list_one).strip("[]") + list_two_check = str(list_two).strip("[]") if list_one_check == list_two_check: return EQUAL @@ -20,11 +26,22 @@ def sublist(list_one, list_two): return SUPERLIST return UNEQUAL ``` -Note that we can't use directly `.join` as it only accepts strings inside the iterable, while there the test cases have integers. -However, if one wanted to use it, we could use `map` or a [generator expression][gen-exp] inside `.join`. +Let's parse the code to see what it does. +In this approach, we convert the lists to strings, so `[1, 2, 3]` becomes `"[1, 2, 3]"`, remove the brackets `"1, 2, 3"`, and add a comma `"1, 2, 3,"`. +We check equality and then use the `in` operator to check for `SUBLIST` or `SUPERLIST`, and finally return `UNEQUAL`. -In this approach, we convert the lists to strings, so `[1, 2, 3]` becomes `"[1, 2, 3]"`, remove the brackets `"1, 2, 3"`, and add a comma `"1, 2, 3,"` so that there's a consistent pattern of number + comma while using the `in` operator. +We add a comma because, say, we call `sublist` with `[1, 2]` and `[1, 22]`. `"1, 2" in "1, 22"` evaluates to `True`, so +the **function would wrongly mark it as `SUBLIST`**. -We check equality and then use the `in` operator to check for `SUBLIST` or `SUPERLIST`, and finally return `UNEQUAL`. +This test can be overridden by changing the code like this: +```python +list_one_check = str(list_one).strip("[]") + ',' +list_two_check = str(list_two).strip("[]") + ',' +``` +Yet, the test case (which doesn't exist in the Exercism test suite) `["1", "2"]` and `["5", "'1', '2',", "7"]` would +fail. + +Students can add any arbitrary string into the representation to try to "defeat" this test - `list_one_check = str +(list_one) + TOKEN`. The test suite currently test `TOKEN = ''`, but not others. [gen-exp]: https://www.programiz.com/python-programming/generator \ No newline at end of file diff --git a/exercises/practice/sublist/.approaches/using-strings/snippet.txt b/exercises/practice/sublist/.approaches/using-strings/snippet.txt index ff7a2563bec..26fc3ec0ec7 100644 --- a/exercises/practice/sublist/.approaches/using-strings/snippet.txt +++ b/exercises/practice/sublist/.approaches/using-strings/snippet.txt @@ -1,6 +1,6 @@ +# Failing approach def sublist(list_one, list_two): - list_one_check = (str(list_one).strip("[]") + ",") - list_two_check = (str(list_two).strip("[]") + ",") + list_one_check = str(list_one).strip("[]") ... elif list_one_check in list_two_check: return SUBLIST From 1cb26c6d68a24d18a78b39243414befb680c0076 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen <62411302+safwansamsudeen@users.noreply.github.com> Date: Fri, 16 Jun 2023 16:38:43 +0530 Subject: [PATCH 089/126] formatting issue --- exercises/practice/sublist/.approaches/introduction.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/exercises/practice/sublist/.approaches/introduction.md b/exercises/practice/sublist/.approaches/introduction.md index ac426baec6e..42f991ef086 100644 --- a/exercises/practice/sublist/.approaches/introduction.md +++ b/exercises/practice/sublist/.approaches/introduction.md @@ -53,8 +53,7 @@ def sublist(list_one, list_two): return SUPERLIST return UNEQUAL ``` -To understand more about this approach and **why it fails**, [read here] -[approach-using-strings]. +To understand more about this approach and **why it fails**, [read here][approach-using-strings]. [approach-list-manipulation]: https://exercism.org/tracks/python/exercises/sublist/approaches/list-manipulation -[approach-using-strings]: https://exercism.org/tracks/python/exercises/sublist/approaches/using-strings \ No newline at end of file +[approach-using-strings]: https://exercism.org/tracks/python/exercises/sublist/approaches/using-strings From f6caa44faa8fb7d0de9a54ddb5c6183e027429c6 Mon Sep 17 00:00:00 2001 From: Andras Nagy <20251272+BNAndras@users.noreply.github.com> Date: Sat, 17 Jun 2023 09:46:55 -0700 Subject: [PATCH 090/126] Remove ResistorColorMaster reference --- .../resistor-color-expert/resistor_color_expert_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/resistor-color-expert/resistor_color_expert_test.py b/exercises/practice/resistor-color-expert/resistor_color_expert_test.py index 8d17a36409a..bcf2052c021 100644 --- a/exercises/practice/resistor-color-expert/resistor_color_expert_test.py +++ b/exercises/practice/resistor-color-expert/resistor_color_expert_test.py @@ -7,7 +7,7 @@ # Tests adapted from `problem-specifications//canonical-data.json` -class ResistorColorMasterTest(unittest.TestCase): +class ResistorColorExpertTest(unittest.TestCase): def test_orange_orange_black_and_red(self): self.assertEqual(resistor_label(["orange", "orange", "black", "red"]), "33 ohms ±2%") From bfad7ef55e18c905eab2777eb1022cde4317ba10 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Tue, 4 Jul 2023 11:28:49 -0700 Subject: [PATCH 091/126] [Dictionary & Dictionary-Methods]: Updates & Edits + "Mecha Munch Management" Concept Exercise (#3445) * Updates and edits to dict, dict-methods and inventory-management. * Revised the concept for dictionaries and added the concept for dictionary methods. Added new dict-methods exercise "Mecha Munch Management" and related files. * Updates to fix CI errors and typos. * Fixed docstring indentation error in stub file. * Update tests, examplar and slight adjustements of instructions * Update syntax used * Fix spacing * Minor formatting changes * Update about.md * Update test cases * Resolved merge confilts for exercise introduction and re-arranged the task order. * Added exemplar code. * Corrected parameter naming error caught by flake8. * Added test and various other changes * Added hints and made various readability and formatting changes. * Fixed additional errors and refrences. * Removed merge conflict flag from file. * Omitted user from user cart. * Further edits from code review. * One. Final. Edit. For this round. --------- Co-authored-by: meatball Co-authored-by: meatball <69751659+meatball133@users.noreply.github.com> --- concepts/dict-methods/about.md | 388 ++++++++++-------- concepts/dict-methods/introduction.md | 26 +- concepts/dicts/about.md | 286 +++++++++++-- concepts/dicts/introduction.md | 19 +- config.json | 8 + .../.docs/instructions.md | 28 +- .../.docs/introduction.md | 117 ++++-- .../mecha-munch-management/.docs/hints.md | 56 +++ .../.docs/instructions.md | 129 ++++++ .../.docs/introduction.md | 234 +++++++++++ .../mecha-munch-management/.meta/config.json | 21 + .../mecha-munch-management/.meta/design.md | 59 +++ .../mecha-munch-management/.meta/exemplar.py | 79 ++++ .../mecha-munch-management/dict_methods.py | 65 +++ .../dict_methods_test.py | 161 ++++++++ 15 files changed, 1431 insertions(+), 245 deletions(-) create mode 100644 exercises/concept/mecha-munch-management/.docs/hints.md create mode 100644 exercises/concept/mecha-munch-management/.docs/instructions.md create mode 100644 exercises/concept/mecha-munch-management/.docs/introduction.md create mode 100644 exercises/concept/mecha-munch-management/.meta/config.json create mode 100644 exercises/concept/mecha-munch-management/.meta/design.md create mode 100644 exercises/concept/mecha-munch-management/.meta/exemplar.py create mode 100644 exercises/concept/mecha-munch-management/dict_methods.py create mode 100644 exercises/concept/mecha-munch-management/dict_methods_test.py diff --git a/concepts/dict-methods/about.md b/concepts/dict-methods/about.md index e36fc7082e1..20625b1c4f5 100644 --- a/concepts/dict-methods/about.md +++ b/concepts/dict-methods/about.md @@ -1,74 +1,85 @@ # Dictionary Methods in Python -A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a [hash table or hashmap][hashtable-wikipedia]. -In Python, it's considered a [mapping type][mapping-types-dict]. -`dicts` enable the retrieval of a value in constant time (on average), given the key. +A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. +Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. +As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. -Compared to searching for a value within a list or array (_without knowing the index position_), a dictionary uses significantly more memory, but has very rapid retrieval. -It's especially useful in scenarios where the collection of items is large and must be accessed/updated frequently. +Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). +Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. +Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. ## Dictionary Methods The `dict` class in Python provides many useful [methods][dict-methods] for working with dictionaries. Some were introduced in the concept for `dicts`. -Here are a few more - along with some techniques for iterating through and manipulating `dicts`. +Here we cover a few more - along with some techniques for iterating through and manipulating dictionaries. -To quickly populate a dictionary with various `keys` and default values, the _class method_ [`dict.fromkeys(iterable, )`][fromkeys] will iterate through the `keys` and create a new `dict`. All `values` will be set to the `default` value provided. +- `dict.setdefault()` for automatically adding keys without error. +- `dict.fromkeys(iterable, )` for creating a new `dict` from any number of iterables. +- `.keys()`, `.values()`, and `.items()` for convenient iterators. +- `sorted(.items())`. for re-ordering entries in a `dict`. +- `dict_one.update()` for updating one `dict` with overlapping values from another `dict`. +- `dict | other_dict` and `dict |= other_dict` for merging or updating two `dict`s via operators. +- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` for reversed views. +- `.popitem()` for removing and returning a `key`, `value` pair. -```python ->>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here') ->>> new_dict -{'Grassy Green': 'fill in hex color here', - 'Purple Mountains Majesty': 'fill in hex color here', - 'Misty Mountain Pink': 'fill in hex color here'} -``` - -`dict.clear()` will removed all `key:value` pairs from the dictionary, leaving it empty and ready for new entries. +### `setdefault()` for Error-Free Insertion -```python ->>> pallette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ->>> pallette_II.clear() ->>> pallette_II -{} -``` +The dictionary concept previously covered that `.get(key, )` returns an existing `value` or the `default value` if a `key` is not found in a dictionary, thereby avoiding a `KeyError`. +This works well in situations where you would rather not have extra error handling but cannot trust that a looked-for `key` will be present. -`dict.get(key, )` works similarly to `dict[key]` -- but it will return the `default` if the `key` is not in the dictionary. -If no `default` is given, the method will return `None`. +For a similarly "safe" (_without KeyError_) insertion operation, there is the `.setdefault(key, )` method. +`setdefault(key, )` will return the `value` if the `key` is found in the dictionary. +If the key is **not** found, it will _insert_ the (`key`, `default value`) pair and return the `default value` for use. ```python >>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} ->>> palette_I['Factory Stone Purple'] -Traceback (most recent call last): - line 1, in - palette_I['Factory Stone Purple'] +#Looking for the value associated with key "Rock Brown". +#The key does not exist, so it is added with the default +# value, and the value is returned. +>>> palette.setdefault('Rock Brown', '#694605') +'#694605' -KeyError: 'Factory Stone Purple' +#The (key, default value) pair has now been added to the dictionary. +>>> palette_I +{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'} +``` ->>> palette_I.get('Factory Stone Purple', 'That color was not found.') -'That color was not found.' +### Use `fromkeys()` to Populate a Dictionary ->>> palette_I.get('Factory Stone Purple', False) -False +To quickly populate a dictionary with various `keys` and default values, the _class method_ [`fromkeys(iterable, )`][fromkeys] will iterate through an iterable of `keys` and create a new `dict`. +All `values` will be set to the `default value` provided: ->>> palette_I.get('Factory Stone Purple') -None +```python +>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here') + +{'Grassy Green': 'fill in hex color here', + 'Purple Mountains Majesty': 'fill in hex color here', + 'Misty Mountain Pink': 'fill in hex color here'} ``` -`dict.popitem()` removes & returns a single `key:value` pair from the `dict`. -Pairs are returned in Last-in-First-out (LIFO) order. -If the dictionary is empty, calling `.dict.popitem` will raise a `KeyError`. +### Removing and Returning a (key, value) Pair With `.popitem()` + +`.popitem()` removes & returns a single (`key`, `value`) pair from a dictionary. +Pairs are returned in Last-in-First-out (`LIFO`) order. +If the dictionary is empty, calling `popitem()` will raise a `KeyError`: ```python ->>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd'} >>> palette_I.popitem() ('Misty Mountain Pink', '#f9c5bd') + >>> palette_I.popitem() ('Purple Mountains Majesty', '#8076a3') + >>> palette_I.popitem() ('Grassy Green', '#9bc400') ->>> palette_I.popitem() +#All (key, value) pairs have been removed. +>>> palette_I.popitem() Traceback (most recent call last): line 1, in @@ -77,25 +88,37 @@ Traceback (most recent call last): KeyError: 'popitem(): dictionary is empty' ``` -While `dict.clear()` and `dict.popitem()` are _destructive_ actions, the `.keys()`, `.values()`, and `.items()` methods return [_iterable views_][dict-views]. -These views can be used for looping over `dict` content without altering it and are _dynamic_ -- when underlying dictionary data changes, the associated view object will reflect the change. +### Iterating Over Entries in a Dictionary + +The `.keys()`, `.values()`, and `.items()` methods return [_iterable views_][dict-views] of a dictionary. +These views can be used for looping over entries without altering them. +They are also _dynamic_ -- when underlying dictionary data changes, the associated view object will reflect the change: ```python ->>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd'} + +#Using .keys() returns a list of keys. >>> palette_I.keys() dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink']) +#Using .values() returns a list of values. >>> palette_I.values() dict_values(['#9bc400', '#8076a3', '#f9c5bd']) +#Using .items() returns a list of (key, value) tuples. >>> palette_I.items() dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')]) +#Views are dynamic. Changing values in the dict +# changes all of the associated views. >>> palette_I['Purple Mountains Majesty'] = (128, 118, 163) +>>> palette_I['Deep Red'] = '#932432' + >>> palette_I.values() -dict_values(['#9bc400', (128, 118, 163), '#f9c5bd']) +dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432']) ->>> palette_I['Deep Red'] = '#932432' >>> palette_I.keys() dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red']) @@ -103,32 +126,68 @@ dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'D dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')]) ``` -`dict_one.update()` can be used to _combine_ two dictionaries. -This method will take the `key:value` pairs of `dict_two` and write them into `dict_one`. +### More on `.keys()`, `.values()`, and `.items()` + +In Python 3.7+, `dicts` preserve the order in which entries are inserted allowing First-in, First-out (_`FIFO`_), iteration using `.keys()`, `.values()`, or `.items()`. +In Python 3.8+, views are also _reversible_. +This allows keys, values, or (key, value) pairs to be iterated over in Last-in, First-out (`LIFO`) order by using `reversed(.keys())`, `reversed(.values())`, or `reversed(.items())`: ```python ->>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} ->>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ->>> palette_I.update(palette_II) ->>> palette_I +>>> palette_II = {'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple baseline': '#161748'} +>>> for item in palette_II.items(): +... print(item) ... +('Factory Stone Purple', '#7c677f') +('Green Treeline', '#478559') +('Purple baseline', '#161748') -{'Grassy Green': '#9bc400', - 'Purple Mountains Majesty': '#8076a3', - 'Misty Mountain Pink': '#f9c5bd', - 'Factory Stone Purple': '#7c677f', - 'Green Treeline': '#478559', - 'Purple baseline': '#161748'} +>>> for item in reversed(palette_II.items()): +... print (item) +... +('Purple baseline', '#161748') +('Green Treeline', '#478559') +('Factory Stone Purple', '#7c677f') +``` + +### Combining Dictionaries with `.update()` + +`.update()` can be used to _combine_ two dictionaries. +This method will take the (`key`,`value`) pairs of `` and write them into ``: + +```python +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd'} +>>> palette_II = {'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple Baseline': '#161748'} + +>>> palette_I.update(palette_II) + +#Note that new items from palette_II are added. +>>> palette_I +{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'} ``` -Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be _overwritten_ by the corresponding `value` from `dict_two`. +Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be _overwritten_ by the corresponding `value` from `dict_two`: ```python ->>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', - 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ->>> palette_III = {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163), +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd', + 'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple baseline': '#161748'} + +>>> palette_III = {'Grassy Green': (155, 196, 0), + 'Purple Mountains Majesty': (128, 118, 163), 'Misty Mountain Pink': (249, 197, 189)} >>> palette_I.update(palette_III) + +#Overlapping values in palette_I are replaced with +# values from palette_III >>> palette_I {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163), @@ -137,14 +196,21 @@ Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ``` -Python 3.9 introduces a different means of merging `dicts`: the `union` operators. -`dict | other_dict` will create a **new** `dict`, made up of the `key:value` pairs of `dict` and `other_dict`. -When both dictionaries share keys, the `other_dict` values will take precedence. -`dict |= other` will behave similar to `dict.update()`, but in this case, `other` can be either a `dict` or an iterable of `key:value` pairs. +### Merging and Updating Dictionaries Via the Union (`|`) Operators + +Python 3.9 introduces a different means of merging `dicts`: the `union` operators. +`dict_one | dict_two` will create a **new dictionary**, made up of the (`key`, `value`) pairs of `dict_one` and `dict_two`. +When both dictionaries share keys, `dict_two` values take precedence. ```python ->>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} ->>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd'} + +>>> palette_II = {'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple baseline': '#161748'} + >>> new_dict = palette_I | palette_II >>> new_dict ... @@ -154,44 +220,34 @@ When both dictionaries share keys, the `other_dict` values will take precedence. 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} - - >>> palette_III = {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163), 'Misty Mountain Pink': (249, 197, 189)} - >>> new_dict |= palette_III - >>> new_dict - ... - {'Grassy Green': (155, 196, 0), - 'Purple Mountains Majesty': (128, 118, 163), - 'Misty Mountain Pink': (249, 197, 189), - 'Factory Stone Purple': '#7c677f', - 'Green Treeline': '#478559', - 'Purple baseline': '#161748'} ``` -## Tips and Tricks - -As of Python 3.6, `dicts` preserve the order in which items are inserted, allowing ordered iteration using `.items()`. As of Python 3.8, `dict` _views_ are reversible, allowing keys, values or items to be iterated over reverse of insertion order by using `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())`. +`dict_one |= other` behaves similar to `.update()`, but in this case, `other` can be either a `dict` or an iterable of (`key`, `value`) pairs: ```python ->>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ->>> for item in palette_II.items(): -... print(item) -... -('Factory Stone Purple', '#7c677f') -('Green Treeline', '#478559') -('Purple baseline', '#161748') - ->>> for item in reversed(palette_II.items()): -... print (item) +>>> palette_III = {'Grassy Green': (155, 196, 0), + 'Purple Mountains Majesty': (128, 118, 163), + 'Misty Mountain Pink': (249, 197, 189)} +>>> new_dict |= palette_III +>>> new_dict ... -('Purple baseline', '#161748') -('Green Treeline', '#478559') -('Factory Stone Purple', '#7c677f') - +{'Grassy Green': (155, 196, 0), +'Purple Mountains Majesty': (128, 118, 163), +'Misty Mountain Pink': (249, 197, 189), +'Factory Stone Purple': '#7c677f', +'Green Treeline': '#478559', +'Purple baseline': '#161748'} ``` -While `dict` does not have a built-in sorting method, it is possible to sort a dictionary _view_ by keys or values using the built-in `sorted()` with `dict.items()`. The sorted view can then be used to create a new, sorted dictionary. Unless a _sort key_ is specified, the default sort is over dictionary keys. +### Sorting a Dictionary + +Dictionaries do not have a built-in sorting method. +However, it is possible to sort a `dict` _view_ using the built-in function `sorted()` with `.items()`. +The sorted view can then be used to create a new dictionary. +Unless a _sort key_ is specified, the default sort is over dictionary `keys`. ```python +# Default ordering for a dictionary is last in, first out (LIFO). >>> color_palette = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', @@ -200,6 +256,7 @@ While `dict` does not have a built-in sorting method, it is possible to sort a d 'Purple baseline': '#161748'} +# The default sort order for a dictionary uses the keys. >>> sorted_palette = dict(sorted(color_palette.items())) >>> sorted_palette {'Factory Stone Purple': '#7c677f', @@ -208,7 +265,10 @@ While `dict` does not have a built-in sorting method, it is possible to sort a d 'Misty Mountain Pink': '#f9c5bd', 'Purple Mountains Majesty': '#8076a3', 'Purple baseline': '#161748'} - + + +# A sort key can be provided in the form +# of an anonymous function (lambda). >>> value_sorted_palette = dict(sorted(color_palette.items(), key=lambda color: color[1])) >>> value_sorted_palette {'Purple baseline': '#161748', @@ -217,110 +277,96 @@ While `dict` does not have a built-in sorting method, it is possible to sort a d 'Purple Mountains Majesty': '#8076a3', 'Grassy Green': '#9bc400', 'Misty Mountain Pink': '#f9c5bd'} - ``` -Swapping keys and values reliably in a dictionary takes a little more work, but can be accomplished via a loop using `dict.items()`. But if the values stored in the `dict` are not unique, extra checks are required. Both methods assume that `dict` keys and values are _hashable_. - -```python +### Transposing a Dictionaries Keys and Values +Swapping keys and values reliably in a dictionary takes a little work, but can be accomplished via a `loop` using `dict.items()` or in a dictionary comprehension. +Safe swapping assumes that `dict` keys and values are both _hashable_. +```python color_reference = {'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', - 'Purple baseline': '#161748', - 'Pink highlight': '#f95d9b', - 'Bluewater lowlight': '#39a0ca', - 'Bright Red': '#DE354C', - 'Deep Red': '#932432', - 'Pure Purple': '#3C1874', - 'Purple Tinged Grey': '#283747', - 'Cloud': '#F3F3F3'} - ->>> reversed_color_reference = {} + 'Purple baseline': '#161748'} + +# Creating a new dictionary to hold the swapped entries. +>>> swapped_color_reference = {} + +# Iterating through the dictionary, using values as keys. >>> for key, value in color_reference.items(): -... reversed_color_reference[value] = key +... swapped_color_reference[value] = key ->>> reversed_color_reference +>>> swapped_color_reference {'#8076a3': 'Purple Mountains Majesty', '#f9c5bd': 'Misty Mountain Pink', '#7c677f': 'Factory Stone Purple', '#478559': 'Green Treeline', - '#161748': 'Purple baseline', - '#f95d9b': 'Pink highlight', - '#39a0ca': 'Bluewater lowlight', - '#DE354C': 'Bright Red', - '#932432': 'Deep Red', - '#3C1874': 'Pure Purple', - '#283747': 'Purple Tinged Grey', - '#F3F3F3': 'Cloud'} - - ->>> extended_color_reference = {'#8076a3': 'Purple Mountains Majesty',(128, 118, 163): 'Purple Mountains Majesty', - (21, 28, 0, 36): 'Purple Mountains Majesty','#f9c5bd': 'Misty Mountain Pink', - (249, 197, 189): 'Misty Mountain Pink',(0, 21, 24, 2): 'Misty Mountain Pink', - '#7c677f': 'Factory Stone Purple',(124, 103, 127): 'Factory Stone Purple', - (2, 19, 0, 50): 'Factory Stone Purple','#478559': 'Green Treeline', - (71, 133, 89): 'Green Treeline',(47, 0, 33, 48): 'Green Treeline', - '#161748': 'Purple baseline',(22, 23, 72): 'Purple baseline', - (69, 68, 0, 72): 'Purple baseline','#f95d9b': 'Pink highlight', - (249, 93, 155): 'Pink highlight',(0, 63, 38, 2): 'Pink highlight', - '#39a0ca': 'Bluewater lowlight',(57, 160, 202): 'Bluewater lowlight', - (72, 21, 0, 21): 'Bluewater lowlight','#DE354C': 'Bright Red', - (222, 53, 76): 'Bright Red',(0, 76, 66, 13): 'Bright Red', - '#932432': 'Deep Red',(147, 36, 50): 'Deep Red', - (0, 76, 66, 42): 'Deep Red','#3C1874': 'Pure Purple', - (60, 24, 116): 'Pure Purple',(48, 79, 0, 55): 'Pure Purple', - '#283747': 'Purple Tinged Grey',(40, 55, 71): 'Purple Tinged Grey', - (44, 23, 0, 72): 'Purple Tinged Grey','#F3F3F3': 'Cloud', - (243, 243, 243): 'Cloud',(0, 0, 0, 5): 'Cloud'} + '#161748': 'Purple baseline'} + +# A dictionary comprehension can also be used to swap entries. +>>> swapped = {value: key for key, value in + color_reference.items()} +>>> swapped +{'#8076a3': 'Purple Mountains Majesty', + '#f9c5bd': 'Misty Mountain Pink', + '#7c677f': 'Factory Stone Purple', + '#478559': 'Green Treeline', + '#161748': 'Purple baseline'} +``` + +If the values stored in the `dict` are not unique, extra checks become necessary before key and value swapping can happen: + +```python +# Things become more complicated if there are duplicates in +# potential key values.This dict is arranged by hex, RGB, and HSL +# keys, but values repeat. +>>> extended_colors = {'#8076a3': 'Purple Mountains Majesty', + (128, 118, 163): 'Purple Mountains Majesty', + (21, 28, 0, 36): 'Purple Mountains Majesty', + '#f9c5bd': 'Misty Mountain Pink', + (249, 197, 189): 'Misty Mountain Pink', + (0, 21, 24, 2): 'Misty Mountain Pink', + '#7c677f': 'Factory Stone Purple', + (124, 103, 127): 'Factory Stone Purple', + (2, 19, 0, 50): 'Factory Stone Purple', + '#478559': 'Green Treeline', + (71, 133, 89): 'Green Treeline', + (47, 0, 33, 48): 'Green Treeline'} + +# New empty dictionary for holding swapped entries. >>> consolidated_colors = {} + +# Iterating over (key, value) pairs using .items() >>> for key, value in extended_color_reference.items(): -... if value in consolidated_colors: +... if value in consolidated_colors: #Check if key has already been created. ... consolidated_colors[value].append(key) ... else: -... consolidated_colors[value] = [key] +... consolidated_colors[value] = [key] #Create a value list with the former key in it. >>> consolidated_colors {'Purple Mountains Majesty': ['#8076a3', (128, 118, 163), (21, 28, 0, 36)], 'Misty Mountain Pink': ['#f9c5bd', (249, 197, 189), (0, 21, 24, 2)], 'Factory Stone Purple': ['#7c677f', (124, 103, 127), (2, 19, 0, 50)], - 'Green Treeline': ['#478559', (71, 133, 89), (47, 0, 33, 48)], - 'Purple baseline': ['#161748', (22, 23, 72), (69, 68, 0, 72)], - 'Pink highlight': ['#f95d9b', (249, 93, 155), (0, 63, 38, 2)], - 'Bluewater lowlight': ['#39a0ca', (57, 160, 202), (72, 21, 0, 21)], - 'Bright Red': ['#DE354C', (222, 53, 76), (0, 76, 66, 13)], - 'Deep Red': ['#932432', (147, 36, 50), (0, 76, 66, 42)], - 'Pure Purple': ['#3C1874', (60, 24, 116), (48, 79, 0, 55)], - 'Purple Tinged Grey': ['#283747', (40, 55, 71), (44, 23, 0, 72)], - 'Cloud': ['#F3F3F3', (243, 243, 243), (0, 0, 0, 5)]} - + 'Green Treeline': ['#478559', (71, 133, 89), (47, 0, 33, 48)]} ``` For a detailed explanation of dictionaries and methods for working with them, the [official tutorial][dicts-docs] and the [official library reference][mapping-types-dict] are excellent starting places. -For more on sorting, see the [Sorting HOW TO][sorting-howto] in the python docs. - [Real Python][how-to-dicts] and [Finxter][fi-dict-guide] also have very thorough articles on Python dictionaries. -## Extending Dictionaries: The collections module +[Real Python][how-to-dicts] and [Finxter][fi-dict-guide] also have very thorough articles on Python dictionaries. -The [`collections`][collections-docs] module adds more functionality to Python's standard collection-based datatypes (`dictionary`, `set`, `list`, `tuple`). -A popular `dict`-oriented member of this module is the [`Counter`][counter-dicts], which automatically counts items and returns them a `dict` with the items as keys and their counts as values. -There is also the [`OrderedDict`][ordered-dicts-docs], which has methods specialized for re-arranging the order of a dictionary. -Finally, there is the [`defaultdict`][default-dicts], a subclass of the built-in `dict` module that, based on a factory method, sets a default value if a key is not found when trying to retrieve or assign the value. +For more on sorting, see the [Sorting HOW TO][sorting-howto] in the Python docs. -[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable -[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table -[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict -[dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries -[how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp -[fromkeys]: https://docs.python.org/3/library/stdtypes.html#dict.fromkeys -[collections-docs]: https://docs.python.org/3/library/collections.html -[counter-dicts]: https://docs.python.org/3/library/collections.html#collections.Counter -[ordered-dicts-docs]: https://docs.python.org/3/library/collections.html#collections.OrderedDict -[default-dicts]: https://docs.python.org/2/library/collections.html#collections.defaultdict -[dict-views]: https://docs.python.org/3/library/stdtypes.html#dict-views +[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [dict-methods]: https://docs.python.org/3/library/stdtypes.html#dict +[dict-views]: https://docs.python.org/3/library/stdtypes.html#dict-views +[dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries [fi-dict-guide]: https://blog.finxter.com/python-dictionary +[fromkeys]: https://docs.python.org/3/library/stdtypes.html#dict.fromkeys +[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table +[how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp +[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict [sorting-howto]: https://docs.python.org/3/howto/sorting.html +[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/concepts/dict-methods/introduction.md b/concepts/dict-methods/introduction.md index 52868299b9d..8a732643845 100644 --- a/concepts/dict-methods/introduction.md +++ b/concepts/dict-methods/introduction.md @@ -1,16 +1,26 @@ # Dictionary Methods in Python -A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a [hash table or hashmap][hashtable-wikipedia]. -In Python, it's considered a [mapping type][mapping-types-dict]. -`dicts` enable the retrieval of a value in constant time (on average), given the key. +A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. +Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. +As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. -Compared to searching for a value within a list or array (_without knowing the index position_), a dictionary uses significantly more memory, but has very rapid retrieval. -It's especially useful in scenarios where the collection of items is large and must be accessed/updated frequently. +Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). +Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. +Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. +The `dict` class in Python provides many useful [methods][dict-methods], some of which are introduced in the concept exercise for dictionaries. -The `dict` class in Python provides many useful [methods][dict-methods] for working with dictionaries. -Some are introduced in the concept exercise for `dicts`. -This concept tackles a few more - along with some techniques for iterating through and manipulating `dicts`. +This concept tackles a few more: +- `dict.setdefault()` for automatically adding keys when needed. +- `dict.fromkeys(iterable, )` for creating a new `dict` from any number of iterables. +- `.keys()`, `.values()`, and `.items()` for convenient iterators. +- `sorted(.items())`. for re-ordering entries in a `dict`. +- `dict_one.update()` for updating one `dict` with overlapping values from another `dict`. +- `dict | other_dict` and `dict |= other_dict` for merging or updating two `dict`s via operators. +- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` for reversed views. +- `.popitem()` for removing and returning a `key`, `value` pair. + +[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict [hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table [term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/concepts/dicts/about.md b/concepts/dicts/about.md index fb43067efe2..305abc6c821 100644 --- a/concepts/dicts/about.md +++ b/concepts/dicts/about.md @@ -1,55 +1,287 @@ # About +A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. +Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. -A dictionary (`dict`) is a [mapping type][mapping-types-dict] data structure that associates [hashable][term-hashable] `keys` to `values` -- known in other programming languages as a resizable [hash table or hashmap][hashtable-wikipedia]. - `Keys` can include `numbers`, `str`, `tuples` (of _immutable_ values), or `frozensets`, but must be hashable and unique across the dictionary. - `keys` are _immutable_ - once added to a `dict`, they can only be removed, they cannot be updated. - `values` can be of any or multiple data type(s) or structures, including other dictionaries, built-in types, custom types, or even objects like functions or classes. - `values` associated with any `key` are _mutable_, and can be replaced, updated or altered as long as the `key` entry exists. - Dictionaries enable the retrieval of a `value` in (on average) constant O(1) time, given the `key`. - Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more space in memory, but has significantly more rapid retrieval. - Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and/or updated frequently. +`Keys` must be hashable and unique across the dictionary. +Key types can include `numbers`, `str`, or `tuples` (of _immutable_ values). +They cannot contain _mutable_ data structures such as `lists`, `dict`s, or `set`s. +As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. -## Dictionary creation +`values` can be of any data type or structure. + Values can also nest _arbitrarily_, so they can include lists-of-lists, sub-dictionaries, and other custom or compound data structures. -A simple `dict` can be declared using the literal form `{: , : }`: +Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). +Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. +Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. - ```python +## Dictionary Construction +Dictionaries can be created in many different ways: + - Using the [`fromkeys()`][fromkeys] classmethod + - Creating [dictionary comprehensions][dict-comprehensions] + - Merging two dictionaries via unpacking (`**`) + - Merging dictionaries via the `|` (_update_) operator + - Using a loop to iteratively add entries to a previously created empty `dict`. +Below are the two most straightforward methods of dictionary creation. +### The `dict()` Class Constructor + +`dict()` can be used with any iterable of `key`, `value` pairs or with a series of `=` _arguments_: + +```python +#Passing a list of key,value tuples. +>>> wombat = dict([('name', 'Wombat'),('speed', 23), + ('land_animal', True)]) +{'name': 'Wombat', 'speed': 23, 'land_animal': True} + + +#Using key=value arguments. +>>> bear = dict(name="Black Bear", speed=40, land_animal=True) +{'name': 'Black Bear', 'speed': 40, 'land_animal': True} +``` + +The [documentation on `dicts`][dicts-docs] outlines additional variations and options in constructor use. + + +### Dictionary Literals + +A dictionary can also be directly entered as a _dictionary literal_, using curly brackets (`{}`) enclosing `key : value` pairs. +Entries that are enclosed in the `{}` can also appear on separate lines: + +```python +>>> whale = {"name": "Blue Whale", + "speed": 35, + "land_animal": False} +{'name': 'Blue Whale', 'speed': 35, 'land_animal': False} + +>>> wombat = {'name': 'Wombat', + 'speed': 23, + 'land_animal': True, + 'color': 'Brindle'} + +>>> wombat +{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'color': 'Brindle'} +``` + +Dictionaries can be arbitrarily nested: + +```python +animals = { + "Real" : { + "Winged" : { + "Sparrow" : {'name': 'sparrow','speed': 12, 'land_animal': True}, + "Kestrel" : {'name': 'kestrel', 'speed': 15, 'land_animal': True} + }, + "Legged" : { + "Wombat" : {'name': 'Wombat', 'speed': 23, 'land_animal': True}, + "Black Bear": {'name': 'Black Bear', 'speed': 40, 'land_animal': True}, + "Polecat" : {'name': 'Polecat', 'speed': 15, 'land_animal': True} + }, + "Other" : { + "Whale" : {'name': 'Blue Whale', 'speed': 35, 'land_animal': False}, + "Orca" : {'name': 'Orca', 'speed': 45, 'land_animal': False}, + "Snake" : {'name': 'Python', 'speed': 25, 'land_animal': True} + } + }, + + "Imaginary": { + "Winged" : { + "Dragon" : {'name': 'Fire Dragon','speed': 100, 'land_animal': True}, + "Phoenix" : {'name': 'Phoenix', 'speed': 1500, 'land_animal': True} + }, + "Legged" : { + "Sphinx" : {'name': 'Sphinx','speed': 10, 'land_animal': True}, + "Minotaur" : {'name': 'Minotaur', 'speed': 5, 'land_animal': True} + }, + "Other" : {} + } + } +``` + +## Accessing Values in a `dict` + +You can access a `value` in a dictionary using a _key_ in square brackets. +If a key does not exist, a `KeyError` is thrown: + +```python +>>> bear["speed"] +40 + +>>> bear["color"] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'color' +``` + +Accessing an entry via the `get(, )` method can avoid the `KeyError`: + +```python +>>> bear.get("color", 'not found') +'not found' +``` + +### Nested Dictionary Entries + +To access entries in nested dictionaries, use successive brackets. +If a given key is missing, the usual KeyError will be thrown: + +```python +#Using the animals nested dictionary. +>>> animals["Real"]["winged"]["Kestrel"]["speed"] +15 + +>>> animals["Imaginary"]["winged"]["Kestrel"]["speed"] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'Kestrel' +``` + +To avoid the `KeyError`, `.get()` can be used, but the calls to `.get()` must be _chained_: + +```python +#Using the animals nested dictionary. +#Note the use of parenthesis to enable placing the +# .get() calls on separate lines. +>>> (animals.get("Imaginary", {}) + .get("Legged", {}) + .get("Sphinx", {}) + .get("Color", "I have no idea!")) +'I have no idea!' +``` + +## Changing or Adding Dictionary Values + +You can change an entry `value` by assigning to its _key_: + +```python +#Assigning the value "Grizzly Bear" to the name key. +>>> bear["name"] = "Grizzly Bear" +{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True} + +>>> whale["speed"] = 25 +{'name': 'Blue Whale', 'speed': 25, 'land_animal': False} +``` + +New `key`:`value` pairs can be _added_ in the same fashion: + +```python +# Adding an new "color" key with a new "tawney" value. +>>> bear["color"] = 'tawney' +{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'} + +>>> whale["blowholes"] = 1 +{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1} +``` + + +## Removing (Pop-ing and del) Dictionary Entries + +You can use the `.pop()` method to delete a dictionary entry. +`.pop()` removes the (`key`, `value`) pair and returns the `value` for use. +Like `.get()`, `.pop()` accepts second argument (_`dict.pop(, )`_) that will be returned if the `key` is not found. +This prevents a `KeyError` being raised: + +```python +#Using .pop() removes both the key and value, returning the value. +>>> bear.pop("name") +'Grizzly Bear' + + +#The "name" key is now removed from the dictionary. +#Attempting .pop() a second time will throw a KeyError. +>>> bear.pop("name") +Traceback (most recent call last): + File "", line 1, in +KeyError: 'name' + + +#Using a default argument with .pop() will +# prevent a KeyError from a missing key. +>>> bear.pop("name", "Unknown") +'Unknown' ``` - The dictionary constructor `dict(=, =)`, but there are many more ways of creating and initializing dictionaries including the use of a _dict comprehension_ or passing additional constructor parameters as illustrated in the [Python docs][mapping-types-dict]. +You can also use the `del` statement to remove a single or multiple entries. +A `KeError` is raised if the entry to be removed is not found in the dictionary: +```python +>>> wombat = {'name': 'Wombat', + 'speed': 23, + 'land_animal': True, + 'color': 'Brindle', + 'talent': 'Singing', + 'size': 'small'} +#Remove a single entry from the dictionary. +>>> del wombat["color"] +>>> wombat +{'name': 'Wombat', 'speed': 23, 'land_animal': True, 'talent': 'Singing', 'size': 'small'} -Inserting a new `key`:`value` pair can be done with `dict[key] = value` and the value can be retrieved by using `retrieved_value = dict[key]`. -## Methods +#Remove multiple entries from the dictionary. +>>> del wombat["talent"], wombat["size"] +>>> wombat +{'name': 'Wombat', 'speed': 23, 'land_animal': True} -`dicts` implement various methods to allow easy initialization, updating and viewing. -Some useful `dict` methods: +#Attempting a deletion of a non-existent key raises a KeyError +>>> del wombat["number_of_legs"] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'number_of_legs' +``` + +## Looping through/Iterating over a Dictionary -- Retrieve a value "safely" from a dictionary by using the `.get(key, [default])` method. `.get(key, [default])` returns the value for the key **or** the _default value_ if the key is not found, instead of raising a `KeyError`. This works well in situations where you would rather not have extra error handling but cannot trust that a looked-for key will be present. -- Retrieve a value "safely" or insert a default _value_ if the key is not found using the `.setdefault(key, [default])` method. `setdefault(key, [default])` will insert the default value in the dictionary **only** if the key is not found, then it will retrieve either the **newly inserted** default value if the key was not found or the **unchanged** existing value if the key was found. -- Return various _iterable_ views of your `dict` with `.keys()`, `.values()`, `.items()` (_an iterable of (key, value) `tuples`_). +Looping through a dictionary using `for item in dict` or `while item` will iterate over only the _keys _ by default. +You can access the _values_ within the same loop by using _square brackets_: + +```python +>>> for key in bear: +>>> print((key, bear[key])) #this prints a tuple of (key, value) +('name', 'Black Bear') +('speed', 40) +('land_animal', True) +``` + +You can also use the `.items()` method, which returns (`key`, `value`) tuples: + +```python +#dict.items() forms (key, value tuples) that can be +# unpacked and iterated over. +>>> for key, value in whale.items(): +>>> print(key, ":", value) +name : Blue Whale +speed : 25 +land_animal : False +blowholes : 1 +``` + +Likewise, `.keys()` will return the `keys` and `.values()` will return the `values`. For a detailed explanation of dictionaries in Python, the [official documentation][dicts-docs] is an excellent starting place, or you can also check out the [W3-Schools][how-to-dicts] tutorial. -## Extending Dictionaries: The collections module -The [`collections`][collections-docs] module adds more functionality to Python's standard collection-based datatypes (`dictionary`, `set`, `list`, `tuple`). A popular `dict`-oriented member of this module is the [`Counter`][counter-dicts], which automatically counts items and returns them a `dict` with the items as keys and their counts as values. There is also the [`OrderedDict`][ordered-dicts-docs], which has methods specialized for re-arranging the order of a dictionary. Finally, there is the [`defaultdict`][default-dicts], a subclass of the built-in `dict` module that, based on a factory method, sets a default value if a key is not found when trying to retrieve or assign the value. +## Extending Dictionary Functionality: The Collections Module -[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable -[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table -[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict -[dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries -[how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp +The [`collections`][collections-docs] module adds specialized functionality to Python's standard collection-based datatypes (`dictionary`, `set`, `list`, `tuple`). +A popular `dict`-oriented member of this module is the [`Counter`][counter-dicts], which automatically counts items and returns them in a `dict` with the items as keys and their counts as values. +There is also the [`OrderedDict`][ordered-dicts-docs], which has methods specialized for re-arranging the order of a dictionary. +Finally, there is the [`defaultdict`][default-dicts], a subclass of the built-in `dict` module that, based on a factory method, sets a default value if a key is not found when trying to retrieve or assign to a dictionary entry. + +[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [collections-docs]: https://docs.python.org/3/library/collections.html [counter-dicts]: https://docs.python.org/3/library/collections.html#collections.Counter -[ordered-dicts-docs]: https://docs.python.org/3/library/collections.html#collections.OrderedDict [default-dicts]: https://docs.python.org/2/library/collections.html#collections.defaultdict +[dict-comprehensions]: https://www.learnbyexample.org/python-dictionary-comprehension/ +[dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries +[fromkeys]: https://www.w3schools.com/python/ref_dictionary_fromkeys.asp +[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table +[how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp +[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict +[ordered-dicts-docs]: https://docs.python.org/3/library/collections.html#collections.OrderedDict +[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/concepts/dicts/introduction.md b/concepts/dicts/introduction.md index 9a887ccfc65..367a89536fd 100644 --- a/concepts/dicts/introduction.md +++ b/concepts/dicts/introduction.md @@ -1,15 +1,22 @@ # Introduction +A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. +Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. -A dictionary (`dict`) is a [mapping type][mapping-types-dict] data structure that associates [hashable][term-hashable] `keys` to `values` -- known in other programming languages as a resizable [hash table or hashmap][hashtable-wikipedia]. - `Keys` can include `numbers`, `str`, `tuples` (of _immutable_ values), or `frozensets`, but must be hashable and unique across the dictionary. - `values` can be of any or multiple data type(s) or structures, including other dictionaries, built-in types, custom types, or even objects like functions or classes. - Dictionaries enable the retrieval of a `value` in (on average) constant O(1) time, given the `key`. - Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more space in memory, but has significantly more rapid retrieval. - Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and/or updated frequently. +`Keys` must be hashable and unique across the dictionary. +Key types can include `numbers`, `str`, or `tuples` (of _immutable_ values). +They cannot contain _mutable_ data structures such as `lists`, `dict`s, or `set`s. +As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. +`values` can be of any data type or structure. + Values can also nest _arbitrarily_, so they can include lists-of-lists, sub-dictionaries, and other custom or compound data structures. +Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). +Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. +Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. + +[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table [mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict [term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/config.json b/config.json index e8c7f2f505f..f386ef39d6c 100644 --- a/config.json +++ b/config.json @@ -144,6 +144,14 @@ "prerequisites": ["loops", "lists", "tuples"], "status": "beta" }, + { + "slug": "mecha-munch-management", + "name": "Mecha Munch Management", + "uuid": "5ac0c40c-4038-47b8-945b-8480e4a3f44c", + "concepts": ["dict-methods"], + "prerequisites": ["dicts"], + "status": "wip" + }, { "slug": "locomotive-engineer", "name": "Locomotive Engineer", diff --git a/exercises/concept/inventory-management/.docs/instructions.md b/exercises/concept/inventory-management/.docs/instructions.md index e1c1806c6ea..718b91d3e0a 100644 --- a/exercises/concept/inventory-management/.docs/instructions.md +++ b/exercises/concept/inventory-management/.docs/instructions.md @@ -4,13 +4,17 @@ In this exercise, you will be managing an inventory system. The inventory should be organized by the item name and it should keep track of the number of items available. -You will have to handle adding items to an inventory. Each time an item appears in a given list, increase the item's quantity by `1` in the inventory. Then, you will have to handle deleting items from an inventory. +You will have to handle adding items to an inventory. +Each time an item appears in a given list, the item's quantity should be increased by `1` in the inventory. +You will also have to handle deleting items from an inventory by decreasing quantities by `1` when requested. + +Finally, you will need to implement a function that will return all the key-value pairs in a given inventory as a `list` of `tuples`. -To finish, you will have to implement a function which returns all the key-value pairs in an inventory as a list of `tuples`. ## 1. Create an inventory based on a list -Implement the `create_inventory()` function that creates an "inventory" from a list of items. It should return a `dict` containing each item name paired with their respective quantity. +Implement the `create_inventory()` function that creates an "inventory" from an input list of items. +It should return a `dict` containing each item name paired with their respective quantity. ```python >>> create_inventory(["coal", "wood", "wood", "diamond", "diamond", "diamond"]) @@ -19,7 +23,7 @@ Implement the `create_inventory()` function that creates an "inventory" from a l ## 2. Add items from a list to an existing dictionary -Implement the `add_items()` function that adds a list of items to an inventory: +Implement the `add_items(, )` function that adds a list of items to the passed-in inventory: ```python >>> add_items({"coal":1}, ["wood", "iron", "coal", "wood"]) @@ -28,23 +32,26 @@ Implement the `add_items()` function that adds a list of items to an inventory: ## 3. Decrement items from the inventory -Implement the `decrement_items()` function that takes a `list` of items. The function should remove one from the available count in the inventory for each time an item appears on the `list`: +Implement the `decrement_items(, )` function that takes a `list` of items. +Your function should remove `1` from an item count for each time that item appears on the `list`: ```python >>> decrement_items({"coal":3, "diamond":1, "iron":5}, ["diamond", "coal", "iron", "iron"]) {"coal":2, "diamond":0, "iron":3} ``` -Item counts in the inventory should not fall below 0. If the number of times an item appears on the list exceeds the count available, the quantity listed for that item should remain at 0 and additional requests for removing counts should be ignored. +Item counts in the inventory should not be allowed to fall below 0. + If the number of times an item appears on the input `list` exceeds the count available, the quantity listed for that item should remain at 0. + Additional requests for removing counts should be ignored once the count falls to zero. ```python >>> decrement_items({"coal":2, "wood":1, "diamond":2}, ["coal", "coal", "wood", "wood", "diamond"]) {"coal":0, "wood":0, "diamond":1} ``` -## 4. Remove an item entirely from the inventory +## 4. Remove an entry entirely from the inventory -Implement the `remove_item(, )` function that removes an item and its count entirely from an inventory: +Implement the `remove_item(, )` function that removes an item and its count entirely from an inventory: ```python >>> remove_item({"coal":2, "wood":1, "diamond":2}, "coal") @@ -58,9 +65,10 @@ If the item is not found in the inventory, the function should return the origin {"coal":2, "wood":1, "diamond":2} ``` -## 5. Return the inventory content +## 5. Return the entire content of the inventory -Implement the `list_inventory()` function that takes an inventory and returns a list of `(item, quantity)` tuples. The list should only include the available items (with a quantity greater than zero): +Implement the `list_inventory()` function that takes an inventory and returns a list of `(item, quantity)` tuples. +The list should only include the _available_ items (_with a quantity greater than zero_): ```python >>> list_inventory({"coal":7, "wood":11, "diamond":2, "iron":7, "silver":0}) diff --git a/exercises/concept/inventory-management/.docs/introduction.md b/exercises/concept/inventory-management/.docs/introduction.md index 1b4a15dc286..2b9ef011e1b 100644 --- a/exercises/concept/inventory-management/.docs/introduction.md +++ b/exercises/concept/inventory-management/.docs/introduction.md @@ -1,50 +1,79 @@ # Introduction -A _**dictionary**_ is Python's primary mapping type that associates a _hashable key_ with a value. The lookup by key is more efficient than searching through an array, but does require more memory. +A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. +Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. -## Dict construction -Dictionaries can be created in various ways. Two simple options are the use the `dict()` class constructor or the dict literal declaration with key-value pairs. +`Keys` must be hashable and unique across the dictionary. +Key types can include `numbers`, `str`, or `tuples` (of _immutable_ values). +They cannot contain _mutable_ data structures such as `lists`, `dict`s, or `set`s. +As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. -### Use the `dict()` constructor +`values` can be of any data type or structure. + Values can also nest _arbitrarily_, so they can include lists-of-lists, sub-dictionaries, and other custom or compound data structures. + +Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). +Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. +Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. + + +## Dictionary Construction + +Dictionaries can be created in many ways. +The two most straightforward are using the `dict()`constructor or declaring a `dict` _literal_. + +### The `dict()` Class Constructor + +`dict()` (_the constructor for the dictionary class_) can be used with any iterable of `key`, `value` pairs or with a series of `=` _arguments_: ```python +#Passing a list of key,value tuples. +>>> wombat = dict([('name', 'Wombat'),('speed', 23),('land_animal', True)]) +{'name': 'Wombat', 'speed': 23, 'land_animal': True} + + +#Using key=value arguments. >>> bear = dict(name="Black Bear", speed=40, land_animal=True) {'name': 'Black Bear', 'speed': 40, 'land_animal': True} ``` -### Declare a _dict_ literal +### Dictionary Literals + +A `dict` can also be directly entered as a _dictionary literal_, using curly brackets (`{}`) enclosing `key : value` pairs: ```python >>> whale = {"name": "Blue Whale", "speed": 35, "land_animal": False} {'name': 'Blue Whale', 'speed': 35, 'land_animal': False} ``` -With the dict literal declaration keep in mind that _keys_ are of _data types_ `str` and the colon `:` is used instead of an equal sign `=`. +## Accessing Values in a Dictionary -## Accessing values - -You can access an item in a dictionary using the _key_ of the value. - -### Using _square brackets_ after the dict object +You can access an entry in a dictionary using a _key_ in square (`[]`) brackets. +If a `key` does not exist n the `dict`, a `KeyError` is thrown: ```python >>> bear["speed"] 40 + +>>> bear["color"] +Traceback (most recent call last): + File "", line 1, in +KeyError: 'color' ``` -### Using `.get()` +Accessing an entry via the `.get(, )` method can avoid the `KeyError`: ```python ->>> whale.get("name") -'Blue Whale' +>>> bear.get("color", 'not found') +'not found' ``` -## Changing values +## Changing or Adding Dictionary Values -You can easily change a value of an item using its _key_. +You can change an entry `value` by assigning to its _key_: ```python +#Assigning the value "Grizzly Bear" to the name key. >>> bear["name"] = "Grizzly Bear" {'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True} @@ -52,29 +81,71 @@ You can easily change a value of an item using its _key_. {'name': 'Blue Whale', 'speed': 25, 'land_animal': False} ``` -## Deleting values using keys +New `key`:`value` pairs can be _added_ in the same fashion: + +```python +# Adding an new "color" key with a new "tawney" value. +>>> bear["color"] = 'tawney' +{'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True, 'color': 'tawney'} -You can delete an item from a dictionary using `dict.pop()`. This will remove the (`key`, `value`) pair from the dictionary and return the `value` for use. `dict.pop()` accepts second argument, `default` that is returned if the `key` is not found (`dict.pop(, )`). Otherwise, a `KeyError` will be raised for any `key` that is missing. +>>> whale["blowholes"] = 1 +{'name': 'Blue Whale', 'speed': 25, 'land_animal': False, 'blowholes': 1} +``` + +## Removing (Pop-ing) Dictionary Entries + +You can use the `.pop()` method to delete a dictionary entry. +`.pop()` removes the (`key`, `value`) pair and returns the `value` for use. +Like `.get()`, `.pop()` accepts second argument (_`dict.pop(, )`_) that will be returned if the `key` is not found. +This prevents a `KeyError` being raised: ```python +#Using .pop() removes both the key and value, returning the value. >>> bear.pop("name") 'Grizzly Bear' ->>> bear.pop("name", "Unknown") -'Unknown' + + +#The "name" key is now removed from the dictionary. +#Attempting .pop() a second time will throw a KeyError. >>> bear.pop("name") Traceback (most recent call last): File "", line 1, in KeyError: 'name' + + +#Using a default argument with .pop() will prevent a KeyError from a missing key. +>>> bear.pop("name", "Unknown") +'Unknown' ``` -## Looping through a dictionary +## Looping through/Iterating over a Dictionary -Looping through a dictionary using `for item in dict` will iterate over the _keys_, but you can access the _values_ by using _square brackets_. +Looping through a dictionary using `for item in dict` or `while item` will iterate over only the _keys _ by default. +You can access the _values_ within the same loop by using _square brackets_: ```python >>> for key in bear: ->>> (key, bear[key]) +>>> print((key, bear[key])) #this forms a tuple of (key, value) and prints it. ('name', 'Black Bear') ('speed', 40) ('land_animal', True) ``` + +You can also use the `.items()` method, which returns (`key`, `value`) tuples automatically: + +```python +#dict.items() forms (key, value tuples) that can be unpacked and iterated over. +>>> for key, value in whale.items(): +>>> print(key, ":", value) +name : Blue Whale +speed : 25 +land_animal : False +blowholes : 1 +``` + +Likewise, the `.keys()` method will return `keys` and the `.values()` method will return the `values`. + +[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. +[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table +[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict +[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/exercises/concept/mecha-munch-management/.docs/hints.md b/exercises/concept/mecha-munch-management/.docs/hints.md new file mode 100644 index 00000000000..9edd70abfe8 --- /dev/null +++ b/exercises/concept/mecha-munch-management/.docs/hints.md @@ -0,0 +1,56 @@ +# Hints + +## General + +Remember, this is an [MVP][mvp]. +That means you don't need to get too fancy with error handling or different "edge case" scenarios. +It's OK to be simple and direct with the functions you are writing. + +The dictionary section of the [official tutorial][dicts-docs] and the mapping type [official library reference][mapping-types-dict] are excellent places to look for more help with all these methods. + + +## 1. Add Item(s) to the Users Shopping Cart + +- You will need to iterate through each item in `items_to_add`. +- You can avoid a `KeyError` when a key is missing by using a `dict` [method][set-default] that takes a _default value_ as one of its arguments. +- It is also possible to accomplish the same thing manually in the `loop` by using some checking and error handling, but the `dict` method is easier. + +## 2. Read in Items Listed in the Users Notes App + +- Remember, Python's got a method for _everything_. This one is a _classmethod_ that's an easy way to [populate a `dict`][fromkeys] with keys. +- This `dict` method returns a _new dictionary_, populated with default values. If no value is given, the default value will become `None` + +## 3. Update Recipe "Ideas" Section + +- Don't overthink this one! This can be solved in **one** `dict` method call. +- The key word here is .... [_update_][update]. + +## 4. Sort the Items in the User Cart + +- What method would you call to get an [iterable view of items][items] in the dictionary? +- If you had a `list` or a `tuple`, what [`built-in`][builtins] function might you use to sort them? +- The built-in function you want is the one that returns a _copy_, and doesn't mutate the original. + +## 5. Send User Shopping Cart to Store for Fulfillment + +- Having a fresh, empty dictionary here as the `fulfillment_cart` might be handy for adding in items. +- `Looping` through the members of the cart might be the most direct way of accessing things here. +- What method would you call to get an [iterable view of just the keys][keys] of the dictionary? +- Remember that you can get the `value` of a given key by using `[]` syntax. +- If you had a `list` or a `tuple`, what [`built-in`][builtins] function might you use to sort them? +- Remember that the `built-in` function can take an optional `reversed=true` argument. + +## 6. Update the Store Inventory to Reflect what a User Has Ordered. + +- There is a method that will give you an iterable view of (`key`, `value`) pairs from the dictionary. +- You can access an item in a _nested tuple_ using _bracket notation_: `[][]` +- Don't forget to check if an inventory count falls to zero, you'll need to add in the "Out of Stock" message. + +[builtins]: https://docs.python.org/3/library/functions.html +[dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries +[fromkeys]: https://docs.python.org/3/library/stdtypes.html#dict.fromkeys +[items]: https://docs.python.org/3/library/stdtypes.html#dict.items +[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict +[mvp]: https://en.wikipedia.org/wiki/Minimum_viable_product +[set-default]: https://docs.python.org/3/library/stdtypes.html#dict.setdefault +[update]: https://docs.python.org/3/library/stdtypes.html#dict.update diff --git a/exercises/concept/mecha-munch-management/.docs/instructions.md b/exercises/concept/mecha-munch-management/.docs/instructions.md new file mode 100644 index 00000000000..f5fa6f79012 --- /dev/null +++ b/exercises/concept/mecha-munch-management/.docs/instructions.md @@ -0,0 +1,129 @@ +# Instructions + +Mecha Munch™, a grocery shopping automation company has just hired you to work on their ordering app. +Your team is tasked with building an MVP (_[minimum viable product][mvp]_) that manages all the basic shopping cart activities, allowing users to add, remove, and sort their grocery orders. +Thankfully, a different team is handling all the money and check-out functions! + +## 1. Add Item(s) to the Users Shopping Cart + +The MVP should allow the user to add items to their shopping cart. +This could be a single item or multiple items at once. +Since this is an MVP, item quantity is indicated by _repeats_. +If a user wants to add 2 Oranges, 'Oranges' will appear twice in the input iterable. +If the user already has the item in their cart, the cart quantity should be increased by 1. +If the item is _new_ to the cart, it should be added with a quantity of 1. + +Create the function `add_items(, )` that takes a cart dictionary and any list-like iterable of items to add as arguments. +It should return a new/updated shopping cart dictionary for the user. + +```python +>>> add_items({'Banana': 3, 'Apple': 2, 'Orange': 1}, + ('Apple', 'Apple', 'Orange', 'Apple', 'Banana')) +{'Banana': 4, 'Apple': 5, 'Orange': 2} + +>>> add_items({'Banana': 3, 'Apple': 2, 'Orange': 1}, + ['Banana', 'Orange', 'Blueberries', 'Banana']) +{'Banana': 5, 'Apple': 2, 'Orange': 2, 'Blueberries': 1} +``` + +## 2. Read in Items Listed in the Users Notes App + +Uh-oh. +Looks like the product team is engaging in [feature creep][feature creep]. +They want to add extra functionality to the MVP. +The application now has to create a shopping cart by reading items off a users notes app. +Convenient for the users, but slightly more work for the team. + +Create the function `read_notes()` that can take any list-like iterable as an argument. +The function should parse the items and create a user shopping cart/dictionary. +Each item should be added with a quantity of 1. +The new user cart should then be returned. + +```python +>>> read_notes(('Banana','Apple', 'Orange')) +{'Banana': 1, 'Apple': 1, 'Orange': 1} + +>>> read_notes(['Blueberries', 'Pear', 'Orange', 'Banana', 'Apple']) +{'Blueberries' : 1, 'Pear' : 1, 'Orange' : 1, 'Banana' : 1, 'Apple' : 1} +``` + +## 3. Update Recipe "Ideas" Section + +The app has an "ideas" section that's filled with finished recipes from various cuisines. +The user can select any one of these recipes and have all its ingredients added to their shopping cart automatically. +The project manager has asked you create a way to edit these "ideas" recipes, since the content team keeps changing around ingredients and quantities. + +Create the function `update_recipes(, )` that takes an "ideas" dictionary and an iterable of recipe updates as arguments. +The function should return the new/updated "ideas" dictionary. + +```python +>>> update_recipes({'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, + 'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}}, +(('Banana Bread', {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Eggs': 2, 'Butter': 1, 'Milk': 2, 'Eggs': 3}),)) +... + +{'Banana Bread' : {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Eggs': 2, 'Butter': 1, 'Milk': 2, 'Eggs': 3}, + 'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}} + +>>> update_recipes({'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, + 'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}, + 'Pasta Primavera': {'Eggs': 1, 'Carrots': 1, 'Spinach': 2, 'Tomatoes': 3, 'Parmesan': 2, 'Milk': 1, 'Onion': 1}}, +[('Raspberry Pie', {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}), +('Pasta Primavera', {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1}), +('Blueberry Crumble', {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3})]) +... + +{'Banana Bread': {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, + 'Raspberry Pie': {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}, + 'Pasta Primavera': {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1}, + 'Blueberry Crumble': {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3}} +``` + +## 4. Sort the Items in the User Cart + +Once a user has started a cart, the app allows them to sort their items alphabetically. +This makes things easier to find, and helps when there are data-entry errors like having 'potatoes' and 'Potato' in the database. + +Create the function `sort_entries()` that takes a shopping cart/dictionary as an argument and returns a new, alphabetically sorted one. + +```python +>>> sort_entries({'Banana': 3, 'Apple': 2, 'Orange': 1}) +{'Apple': 2, 'Banana':3, 'Orange': 1} +``` + +## 5. Send User Shopping Cart to Store for Fulfillment + +The app needs to send a given users cart to the store for fulfillment. +However, the shoppers in the store need to know which store isle the item can be found in and if the item needs refrigeration. +So (_rather arbitrarily_) the "fulfillment cart" needs to be sorted in reverse alphabetical order with item quantities combined with location and refrigeration information. + +Create the function `send_to_store(, )` that takes a user shopping cart and a dictionary that has store isle number and a `True`/`False` for refrigeration needed for each item. +The function should `return` a combined "fulfillment cart" that has (quantity, isle, and refrigeration) for each item the customer is ordering. +Items should appear in _reverse_ alphabetical order. + +```python +>>> send_to_store({'Banana': 3, 'Apple': 2, 'Orange': 1, 'Milk': 2}, + {'Banana': ['Isle 5', False], 'Apple': ['Isle 4', False], 'Orange': ['Isle 4', False], 'Milk': ['Isle 2', True]}) +{'Orange': [1, 'Isle 4', False], 'Milk': [2, 'Isle 2', True], 'Banana': [3, 'Isle 5', False], 'Apple': [2, 'Isle 4', False]} +``` + +## 6. Update the Store Inventory to Reflect what a User Has Ordered. + +The app can't just place customer orders endlessly. +Eventually, the store is going to run out of various products. +So your app MVP needs to update the store inventory every time a user sends their order to the store. +Otherwise, customers will order products that aren't actually available. + +Create the function `update_store_inventory(, )` that takes a "fulfillment cart" and a store inventory. +The function should reduce the store inventory amounts by the number "ordered" in the "fulfillment cart" and then return the updated store inventory. +Where a store item count falls to 0, the count should be replaced by the message 'Out of Stock'. + +```python +>>> update_store_inventory({'Orange': [1, 'Isle 4', False], 'Milk': [2, 'Isle 2', True], 'Banana': [3, 'Isle 5', False], 'Apple': [2, 'Isle 4', False]}, +{'Banana': [15, 'Isle 5', False], 'Apple': [12, 'Isle 4', False], 'Orange': [1, 'Isle 4', False], 'Milk': [4, 'Isle 2', True]}) + +{'Banana': [12, 'Isle 5', False], 'Apple': [10, 'Isle 4', False], 'Orange': ['Out of Stock', 'Isle 4', False], 'Milk': [2, 'Isle 2', True]} +``` + +[feature creep]: https://en.wikipedia.org/wiki/Feature_creep +[mvp]: https://en.wikipedia.org/wiki/Minimum_viable_product diff --git a/exercises/concept/mecha-munch-management/.docs/introduction.md b/exercises/concept/mecha-munch-management/.docs/introduction.md new file mode 100644 index 00000000000..7088a08d98d --- /dev/null +++ b/exercises/concept/mecha-munch-management/.docs/introduction.md @@ -0,0 +1,234 @@ +# Dictionary Methods in Python + +A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. +Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. +As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. + + +Given the `key`, dictionaries enable the retrieval of a `value` in (on average) constant time (_independent of the number of entries_). +Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. +Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. + +## Dictionary Methods + +The `dict` class in Python provides many useful [methods][dict-methods] for working with dictionaries. +Some were introduced in the concept for `dicts`. +Here we cover a few more - along with some techniques for iterating through and manipulating dictionaries. + +### `setdefault()` for Error-Free Insertion + +The dictionary concept previously covered that `.get(key, )` returns an existing `value` or the `default value` if a `key` is not found in a dictionary, thereby avoiding a `KeyError`. +This works well in situations where you would rather not have extra error handling but cannot trust that a looked-for `key` will be present. + +For a similarly "safe" (_without KeyError_) insertion operation, there is the `.setdefault(key, )` method. +`setdefault(key, )` will return the `value` if the `key` is found in the dictionary. +If the key is **not** found, it will _insert_ the (`key`, `default value`) pair and return the `default value` for use. + +```python +>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} + +#Looking for the value associated with key "Rock Brown". +#The key does not exist, so it is added with the default value, and the value is returned. +>>> palette.setdefault('Rock Brown', '#694605') +'#694605' + +#The (key, default value) pair has now been added to the dictionary. +>>> palette_I +{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'} +``` + +### Use `fromkeys()` to Populate a Dictionary + +To quickly populate a dictionary with various `keys` and default values, the _class method_ [`fromkeys(iterable, )`][fromkeys] will iterate through an iterable of `keys` and create a new `dict`. +All `values` will be set to the `default value` provided: + +```python +>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here') + +{'Grassy Green': 'fill in hex color here', + 'Purple Mountains Majesty': 'fill in hex color here', + 'Misty Mountain Pink': 'fill in hex color here'} +``` + +### Iterating Over Entries in a Dictionary + +The `.keys()`, `.values()`, and `.items()` methods return [_iterable views_][dict-views] of a dictionary. + +These views can be used for looping over entries without altering them. +They are also _dynamic_ -- when underlying dictionary data changes, the associated view object will reflect the change: + +```python +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd'} + +#Using .keys() returns a list of keys. +>>> palette_I.keys() +dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink']) + +#Using .values() returns a list of values. +>>> palette_I.values() +dict_values(['#9bc400', '#8076a3', '#f9c5bd']) + +#Using .items() returns a list of (key, value) tuples. +>>> palette_I.items() +dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')]) + +#Views are dynamic. Changing values in the dict changes all of the associated views. +>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163) +>>> palette_I['Deep Red'] = '#932432' + +>>> palette_I.values() +dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432']) + +>>> palette_I.keys() +dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red']) + +>>> palette_I.items() +dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')]) +``` + +### More on `.keys()`, `.values()`, and `.items()` + +In Python 3.7+, `dicts` preserve the order in which entries are inserted allowing First-in, First-out (_`FIFO`_), iteration using `.keys()`, `.values()`, or `.items()`. +In Python 3.8+, views are also _reversible_. +This allows keys, values, or (`key`, `value`) pairs to be iterated over in Last-in, First-out (`LIFO`) order by using `reversed(.keys())`, `reversed(.values())`, or `reversed(.items())`: + +```python +>>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} + +#Iterating in insertion order +>>> for item in palette_II.items(): +... print(item) +... +('Factory Stone Purple', '#7c677f') +('Green Treeline', '#478559') +('Purple baseline', '#161748') + + +#Iterating in the reverse direction. +>>> for item in reversed(palette_II.items()): +... print (item) +... +('Purple baseline', '#161748') +('Green Treeline', '#478559') +('Factory Stone Purple', '#7c677f') +``` + +### Sorting a Dictionary + +Dictionaries do not have a built-in sorting method. +However, it is possible to sort a `dict` _view_ using the built-in function `sorted()` with `.items()`. +The sorted view can then be used to create a new dictionary. +Like iteration, the default sort is over dictionary `keys`. + +```python +# Default ordering for a dictionary is last in, first out (LIFO). +>>> color_palette = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd', + 'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple baseline': '#161748'} + + +# The default sort order for a dictionary uses the keys. +>>> sorted_palette = dict(sorted(color_palette.items())) +>>> sorted_palette +{'Factory Stone Purple': '#7c677f', + 'Grassy Green': '#9bc400', + 'Green Treeline': '#478559', + 'Misty Mountain Pink': '#f9c5bd', + 'Purple Mountains Majesty': '#8076a3', + 'Purple baseline': '#161748'} +``` + +### Combining Dictionaries with `.update()` + +`.update()` can be used to _combine_ two dictionaries. +This method will take the (`key`,`value`) pairs of `` and write them into ``: + +```python +>>> palette_I = {'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd'} +>>> palette_II = {'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple Baseline': '#161748'} + +>>> palette_I.update(palette_II) + +#Note that new items from palette_II are added. +>>> palette_I +{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'} +``` + +Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be _overwritten_ by the corresponding `value` from `dict_two`: + +```python +>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', + 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} +>>> palette_III = {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163), + 'Misty Mountain Pink': (249, 197, 189)} +>>> palette_I.update(palette_III) + +#Overlapping values in palette_I are replaced with values from palette_III +>>> palette_I +{'Grassy Green': (155, 196, 0), + 'Purple Mountains Majesty': (128, 118, 163), + 'Misty Mountain Pink': (249, 197, 189), + 'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', 'Purple baseline': '#161748'} +``` + +### Merging and Updating Dictionaries Via the Union (`|`) Operators + +Python 3.9 introduces a different means of merging `dicts`: the `union` operators. +`dict_one | dict_two` will create a **new dictionary**, made up of the (`key`, `value`) pairs of `dict_one` and `dict_two`. +When both dictionaries share keys, `dict_two` values take precedence. + +```python +>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} +>>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} +>>> new_dict = palette_I | palette_II +>>> new_dict +... +{'Grassy Green': '#9bc400', + 'Purple Mountains Majesty': '#8076a3', + 'Misty Mountain Pink': '#f9c5bd', + 'Factory Stone Purple': '#7c677f', + 'Green Treeline': '#478559', + 'Purple baseline': '#161748'} +``` + +`dict_one |= other` behaves similar to `.update()`, but in this case, `other` can be either a `dict` or an iterable of (`key`, `value`) pairs: + +```python +>>> palette_III = {'Grassy Green': (155, 196, 0), + 'Purple Mountains Majesty': (128, 118, 163), + 'Misty Mountain Pink': (249, 197, 189)} +>>> new_dict |= palette_III +>>> new_dict +... +{'Grassy Green': (155, 196, 0), +'Purple Mountains Majesty': (128, 118, 163), +'Misty Mountain Pink': (249, 197, 189), +'Factory Stone Purple': '#7c677f', +'Green Treeline': '#478559', +'Purple baseline': '#161748'} +``` + +For a detailed explanation of dictionaries and methods for working with them, the [official tutorial][dicts-docs] and the [official library reference][mapping-types-dict] are excellent starting places. + +[Real Python][how-to-dicts] and [Finxter][fi-dict-guide] also have very thorough articles on Python dictionaries. + +[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. +[dict-methods]: https://docs.python.org/3/library/stdtypes.html#dict +[dict-views]: https://docs.python.org/3/library/stdtypes.html#dict-views +[dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries +[fi-dict-guide]: https://blog.finxter.com/python-dictionary +[fromkeys]: https://docs.python.org/3/library/stdtypes.html#dict.fromkeys +[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table +[how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp +[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict +[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/exercises/concept/mecha-munch-management/.meta/config.json b/exercises/concept/mecha-munch-management/.meta/config.json new file mode 100644 index 00000000000..f09d0f29537 --- /dev/null +++ b/exercises/concept/mecha-munch-management/.meta/config.json @@ -0,0 +1,21 @@ +{ + "authors": [ + "meatball133", + "BethanyG" + ], + "contributors": [ + ], + "files": { + "solution": [ + "dict_methods.py" + ], + "test": [ + "dict_methods_test.py" + ], + "exemplar": [ + ".meta/exemplar.py" + ] + }, + "icon": "gross-store", + "blurb": "Learn about dictionary methods by building a shopping cart MVP for the Mecha Munch grocery app." +} diff --git a/exercises/concept/mecha-munch-management/.meta/design.md b/exercises/concept/mecha-munch-management/.meta/design.md new file mode 100644 index 00000000000..4c3c52a0d95 --- /dev/null +++ b/exercises/concept/mecha-munch-management/.meta/design.md @@ -0,0 +1,59 @@ +## Learning objectives + +Cover useful `dict` methods and a few techniques for operating on/manipulating `dicts`. + +- `dict.setdefault()` for automatically adding keys when needed. +- `dict.fromkeys(iterable, )` for creating a new `dict` from any number of iterables. +- `dict.keys()`, `dict.values()`, and `dict.items()` for convenient iterators. +- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` for reversed views. +- `sorted()` with `dict.items()`. for re-ordering entries in a `dict`. +- `dict_one.update()` for updating one `dict` with overlapping values from another `dict`. +- `dict | other_dict` and `dict |= other_dict` for merging or updating two `dict`s via operators. +- `dict.popitem()` for removing and returning a key, value pair. + +- Working more with the `dict` views `items()` , `keys()` or `values()`. (e.g, by sorting information using `sorted()` or by swapping `keys` and `values`, etc.) +- Knowing that Dictionaries can be _nested_, _-- e.g._ ' a dictionary of dictionaries'. +- Considerations when `updating()` or using `union` with dictionaries. + +## Out of scope + +Please take a look at the `dicts` concept exercise [design.md file](https://github.com/exercism/python/edit/main/exercises/concept/inventory-management/.meta/design.md) for `dict` features taught thus far. +While those methods can be used for solutions to this exercise, it isn't necessary to cover them again in detail. Additionally, the following is out of scope: + +- Dictionary comprehensions +- Built-in functions as they relate to this data structure (*e.g.* `len()`, or `enumerate()` +- Considerations of Mutability +- `copy()` vs `deepcopy()` +- Memory and performance characteristics. +- Related `collections` module with `Counter()` and `defaultdict()` + +## Concepts + +- `dicts` +- `dict-methods` + +## Prerequisites + +These are the concepts/concept exercises the student needs to complete/understand before solving this concept exercise. + +- `basics` +- `bools` +- `conditionals` +- `comparisons` +- `dicts` +- `lists` +- `loops` +- `numbers` +- `strings` +- `tuples` + + +## Resources to refer to + +- [Python docs: Tutorial - Dictionaries](https://docs.python.org/3/tutorial/datastructures.html#dictionaries) +- [Python docs: Mapping Type `dict`](https://docs.python.org/3/library/stdtypes.html#mapping-types-dict) +- [Real Python: Dicts](https://realpython.com/python-dicts/) +- [Digital Ocean: Understanding dictionaries in python 3](https://www.digitalocean.com/community/tutorials/understanding-dictionaries-in-python-3) +- [Stack Overflow: exchanging keys with values in a `dict` in Python](https://stackoverflow.com/questions/1031851/how-do-i-exchange-keys-with-values-in-a-dictionary) +- [kite: how to sort a dictionary by key in python](https://www.kite.com/python/answers/how-to-sort-a-dictionary-by-key-in-python) +- [medium: 16 Python Dictionary Tips](https://medium.com/python-in-plain-english/16-intermediate-level-python-dictionary-tips-tricks-and-shortcuts-1376859e1adc) _**note:** this is a good resource for ideas and writing this exericse, but is a subscription-based service, so not the best for linking to_ \ No newline at end of file diff --git a/exercises/concept/mecha-munch-management/.meta/exemplar.py b/exercises/concept/mecha-munch-management/.meta/exemplar.py new file mode 100644 index 00000000000..0390944dbbd --- /dev/null +++ b/exercises/concept/mecha-munch-management/.meta/exemplar.py @@ -0,0 +1,79 @@ +"""Functions to manage a users shopping cart items.""" + + +def add_item(current_cart, items_to_add): + """Add items to shopping cart. + + :param current_cart: dict - the current shopping cart. + :param items_to_add: iterable - items to add to the cart. + :return: dict - the updated user cart dictionary. + """ + + for item in items_to_add: + current_cart.setdefault(item, 0) + current_cart[item] += 1 + + return current_cart + + +def read_notes(notes): + """Create user cart from an iterable notes entry. + + :param notes: iterable of items to add to cart. + :return: dict - a user shopping cart dictionary. + """ + + return dict.fromkeys(notes, 1) + + +def update_recipes(ideas, recipe_updates): + """Update the recipe ideas dictionary. + + :param ideas: dict - The "recipe ideas" dict. + :param recipe_updates: dict - dictionary with updates for the ideas section. + :return: dict - updated "recipe ideas" dict. + """ + + ideas.update(recipe_updates) + return ideas + + +def sort_entries(cart): + """Sort a users shopping cart in alphabetically order. + + :param cart: dict - a users shopping cart dictionary. + :return: dict - users shopping cart sorted in alphabetical order. + """ + + return dict(sorted(cart.items())) + + +def send_to_store(cart, isle_mapping): + """Combine users order to isle and refrigeration information. + + :param cart: dict - users shopping cart dictionary. + :param isle_mapping: dict - isle and refrigeration information dictionary. + :return: dict - fulfillment dictionary ready to send to store. + """ + fulfillment_cart = {} + + for key in cart.keys(): + fulfillment_cart[key] = [cart[key]] + isle_mapping[key] + + return dict(sorted(fulfillment_cart.items(), reverse=True)) + + +def update_store_inventory(fulfillment_cart, store_inventory): + """Update store inventory levels with user order. + + :param fulfillment cart: dict - fulfillment cart to send to store. + :param store_inventory: dict - store available inventory + :return: dict - store_inventory updated. + """ + + for key, values in fulfillment_cart.items(): + store_inventory[key][0] = store_inventory[key][0] - values[0] + if store_inventory[key][0] == 0: + store_inventory[key][0] = 'Out of Stock' + + return store_inventory diff --git a/exercises/concept/mecha-munch-management/dict_methods.py b/exercises/concept/mecha-munch-management/dict_methods.py new file mode 100644 index 00000000000..d443c8bca54 --- /dev/null +++ b/exercises/concept/mecha-munch-management/dict_methods.py @@ -0,0 +1,65 @@ +"""Functions to manage a users shopping cart items.""" + + +def add_item(current_cart, items_to_add): + """Add items to shopping cart. + + :param current_cart: dict - the current shopping cart. + :param items_to_add: iterable - items to add to the cart. + :return: dict - the updated user cart dictionary. + """ + + pass + + +def read_notes(notes): + """Create user cart from an iterable notes entry. + + :param notes: iterable of items to add to cart. + :return: dict - a user shopping cart dictionary. + """ + + pass + + +def update_recipes(ideas, recipe_updates): + """Update the recipe ideas dictionary. + + :param ideas: dict - The "recipe ideas" dict. + :param recipe_updates: dict - dictionary with updates for the ideas section. + :return: dict - updated "recipe ideas" dict. + """ + + pass + + +def sort_entries(cart): + """Sort a users shopping cart in alphabetically order. + + :param cart: dict - a users shopping cart dictionary. + :return: dict - users shopping cart sorted in alphabetical order. + """ + + pass + + +def send_to_store(cart, isle_mapping): + """Combine users order to isle and refrigeration information. + + :param cart: dict - users shopping cart dictionary. + :param isle_mapping: dict - isle and refrigeration information dictionary. + :return: dict - fulfillment dictionary ready to send to store. + """ + + pass + + +def update_store_inventory(fulfillment_cart, store_inventory): + """Update store inventory levels with user order. + + :param fulfillment cart: dict - fulfillment cart to send to store. + :param store_inventory: dict - store available inventory + :return: dict - store_inventory updated. + """ + + pass diff --git a/exercises/concept/mecha-munch-management/dict_methods_test.py b/exercises/concept/mecha-munch-management/dict_methods_test.py new file mode 100644 index 00000000000..2f5828d615f --- /dev/null +++ b/exercises/concept/mecha-munch-management/dict_methods_test.py @@ -0,0 +1,161 @@ +import unittest +import pytest +from dict_methods import (add_item, + read_notes, + update_recipes, + sort_entries, + send_to_store, + update_store_inventory) + + +class MechaMunchManagementTest(unittest.TestCase): + + @pytest.mark.task(taskno=1) + def test_add_item(self): + input_data = [ + ({'Apple': 1, 'Banana': 4 }, ('Apple', 'Banana', 'Orange')), + ({'Orange': 1, 'Raspberry': 1, 'Blueberries': 10}, ['Raspberry', 'Blueberries', 'Raspberry']), + ({'Broccoli': 1, 'Banana': 1}, ('Broccoli', 'Kiwi', 'Kiwi', 'Kiwi', 'Melon', 'Apple', 'Banana', 'Banana')) + ] + + output_data = [{'Apple': 2, 'Banana': 5, 'Orange': 1}, + {'Orange': 1, 'Raspberry': 3, 'Blueberries': 11}, + {'Broccoli': 2, 'Banana': 3, 'Kiwi': 3, 'Melon': 1, 'Apple': 1}] + + for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): + with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): + error_msg=f'Expected: {output_data} but got a different shopping cart.' + self.assertEqual(add_item(input_data[0], input_data[1]), output_data, msg=error_msg) + + + @pytest.mark.task(taskno=2) + def test_read_notes(self): + input_data = [('Apple', "Banana"), ('Orange', 'Raspberry', 'Blueberries'), + ['Broccoli', 'Kiwi', 'Melon', 'Apple', 'Banana']] + + output_data = [{'Apple': 1, 'Banana': 1}, {'Orange': 1, 'Raspberry': 1, 'Blueberries': 1}, + {'Broccoli': 1, 'Kiwi': 1, 'Melon': 1, 'Apple': 1, 'Banana': 1}] + + for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): + with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): + error_msg=f'Expected: {output_data} but got a different shopping cart.' + self.assertEqual(read_notes(input_data), output_data, msg=error_msg) + + @pytest.mark.task(taskno=3) + def test_update_recipes(self): + input_data = [ + ({'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, + 'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}}, + (('Banana Bread', {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Eggs': 2, 'Butter': 1, 'Milk': 2, 'Eggs': 3}),)), + + ({'Apple Pie': {'Apple': 1, 'Pie Crust': 1, 'Cream Custard': 1}, + 'Blueberry Pie': {'Blueberries': 1, 'Pie Crust': 1, 'Cream Custard': 1}}, + (('Blueberry Pie', {'Blueberries': 2, 'Pie Crust': 1, 'Cream Custard': 1}), + ('Apple Pie', {'Apple': 1, 'Pie Crust': 1, 'Cream Custard': 1}))), + + ({'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, + 'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}, + 'Pasta Primavera': {'Eggs': 1, 'Carrots': 1, 'Spinach': 2, 'Tomatoes': 3, 'Parmesan': 2, 'Milk': 1, 'Onion': 1}}, + (('Raspberry Pie', {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}), + ('Pasta Primavera', {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1}), + ('Blueberry Crumble', {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3}))) + ] + + output_data = [ + {'Banana Bread': {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Eggs': 2, 'Butter': 1, 'Milk': 2, 'Eggs': 3}, + 'Raspberry Pie': {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}}, + {'Apple Pie': {'Apple': 1, 'Pie Crust': 1, 'Cream Custard': 1}, + 'Blueberry Pie': {'Blueberries': 2, 'Pie Crust': 1, 'Cream Custard': 1}}, + {'Banana Bread': {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, + 'Raspberry Pie': {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}, + 'Pasta Primavera': {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1}, + 'Blueberry Crumble': {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3}} + ] + + for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): + with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): + error_msg=f'Expected: {output_data} but got a different ideas instead.' + self.assertEqual(update_recipes(input_data[0], input_data[1]), output_data, msg=error_msg) + + @pytest.mark.task(taskno=4) + def test_sort_entries(self): + input_data = [ + {'Banana': 4, 'Apple': 2, 'Orange': 1, 'Pear': 12}, + {'Apple': 3, 'Orange': 5, 'Banana': 1, 'Avocado': 2}, + {'Orange': 3, 'Banana': 2, 'Apple': 1}, + {'Apple': 2, 'Raspberry': 2, 'Blueberries': 5, 'Broccoli' : 2, 'Kiwi': 1, 'Melon': 4} + ] + + output_data = [ + {'Apple': 2, 'Banana': 4, 'Orange': 1, 'Pear': 12}, + {'Avocado': 2, 'Apple': 3, 'Banana': 1, 'Orange': 5}, + {'Apple': 1, 'Orange': 3, 'Banana': 2}, + {'Apple' : 2, 'Blueberries': 5, 'Broccoli': 2, 'Kiwi': 1, 'Melon': 4, 'Raspberry': 2} + ] + + for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): + with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): + error_msg=f'Expected: {output_data} but got a different sorted list instead.' + self.assertEqual(sort_entries(input_data), output_data, msg=error_msg) + + @pytest.mark.task(taskno=5) + def test_send_to_store(self): + input_data = [ + ({'Banana': 3, 'Apple': 2, 'Orange': 1, 'Milk': 2}, + {'Banana': ['Isle 5', False], 'Apple': ['Isle 4', False], 'Orange': ['Isle 4', False], 'Milk': ['Isle 2', True]}), + + ({'Kiwi': 3, 'Juice': 5, 'Yoghurt': 2, 'Milk': 5}, + {'Kiwi': ['Isle 6', False], 'Juice': ['Isle 5', False], 'Yoghurt': ['Isle 2', True], 'Milk': ['Isle 2', True]}), + + ({'Apple': 2, 'Raspberry': 2, 'Blueberries': 5, 'Broccoli' : 2, 'Kiwi': 1, 'Melon': 4}, + {'Apple': ['Isle 1', False], 'Raspberry': ['Isle 6', False], 'Blueberries': ['Isle 6', False], + 'Broccoli': ['Isle 3', False], 'Kiwi': ['Isle 6', False], 'Melon': ['Isle 6', False]}) + ] + + output_data = [ + {'Orange': [1, 'Isle 4', False], 'Milk': [2, 'Isle 2', True], 'Banana': [3, 'Isle 5', False], 'Apple': [2, 'Isle 4', False]}, + {'Juice': [5, 'Isle 5', False], 'Yoghurt': [2, 'Isle 2', True], 'Milk': [5, 'Isle 2', True], 'Kiwi': [3, 'Isle 6', False]}, + {'Kiwi': [1, 'Isle 6', False], 'Melon': [4, 'Isle 6', False], 'Apple': [2, 'Isle 1', False], + 'Raspberry': [2, 'Isle 6', False], 'Blueberries': [5, 'Isle 6', False], 'Broccoli': [2, 'Isle 3', False]} + ] + + for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): + with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): + error_msg=f'Expected: {output_data} but got a different fulfillment_cart instead.' + self.assertEqual(send_to_store(input_data[0], input_data[1]), output_data, msg=error_msg) + + @pytest.mark.task(taskno=6) + def test_update_store_inventory(self): + input_data = [ + ({'Orange': [1, 'Isle 4', False], 'Milk': [2, 'Isle 2', True], + 'Banana': [3, 'Isle 5', False], 'Apple': [2, 'Isle 4', False]}, + {'Banana': [15, 'Isle 5', False], 'Apple': [12, 'Isle 4', False], + 'Orange': [1, 'Isle 4', False], 'Milk': [4, 'Isle 2', True]}), + + ({'Kiwi': [3, 'Isle 6', False]},{'Kiwi': [3, 'Isle 6', False], 'Juice': [5, 'Isle 5', False], + 'Yoghurt': [2, 'Isle 2', True], 'Milk': [5, 'Isle 2', True]}), + + ({'Kiwi': [1, 'Isle 6', False], 'Melon': [4, 'Isle 6', False], 'Apple': [2, 'Isle 1', False], + 'Raspberry': [2, 'Isle 6', False], 'Blueberries': [5, 'Isle 6', False], + 'Broccoli': [1, 'Isle 3', False]}, + {'Apple': [2, 'Isle 1', False], 'Raspberry': [5, 'Isle 6', False], + 'Blueberries': [10, 'Isle 6', False], 'Broccoli': [4, 'Isle 3', False], + 'Kiwi': [1, 'Isle 6', False], 'Melon': [8, 'Isle 6', False]}) + ] + + output_data = [ + {'Banana': [12, 'Isle 5', False], 'Apple': [10, 'Isle 4', False], + 'Orange': ['Out of Stock', 'Isle 4', False], 'Milk': [2, 'Isle 2', True]}, + + {'Juice': [5, 'Isle 5', False], 'Yoghurt': [2, 'Isle 2', True], + 'Milk': [5, 'Isle 2', True], 'Kiwi': ["Out of Stock", 'Isle 6', False]}, + + {'Kiwi': ['Out of Stock', 'Isle 6', False], 'Melon': [4, 'Isle 6', False], + 'Apple': ['Out of Stock', 'Isle 1', False], 'Raspberry': [3, 'Isle 6', False], + 'Blueberries': [5, 'Isle 6', False], 'Broccoli': [3, 'Isle 3', False]} + ] + + for variant, (input_data, output_data) in enumerate(zip(input_data, output_data), start=1): + with self.subTest(f'variation #{variant}', input_data=input_data, output_data=output_data): + error_msg=f'Expected: {output_data} but got a different store inventory instead.' + self.assertEqual(update_store_inventory(input_data[0], input_data[1]), output_data, msg=error_msg) From 4206810a2c6f5ace847592d6307e82577ff2ed88 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Wed, 5 Jul 2023 06:15:01 -0700 Subject: [PATCH 092/126] Concept tidy-up and typo fixes. --- concepts/dict-methods/about.md | 79 ++++++++----------- concepts/dict-methods/introduction.md | 27 ++----- concepts/dicts/about.md | 57 +++++++------ concepts/dicts/introduction.md | 2 + .../.docs/introduction.md | 57 ++++++------- 5 files changed, 97 insertions(+), 125 deletions(-) diff --git a/concepts/dict-methods/about.md b/concepts/dict-methods/about.md index 20625b1c4f5..d910d3e9168 100644 --- a/concepts/dict-methods/about.md +++ b/concepts/dict-methods/about.md @@ -1,29 +1,20 @@ # Dictionary Methods in Python -A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. -Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. -As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. - -Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). -Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. -Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. - -## Dictionary Methods - The `dict` class in Python provides many useful [methods][dict-methods] for working with dictionaries. Some were introduced in the concept for `dicts`. Here we cover a few more - along with some techniques for iterating through and manipulating dictionaries. -- `dict.setdefault()` for automatically adding keys without error. -- `dict.fromkeys(iterable, )` for creating a new `dict` from any number of iterables. -- `.keys()`, `.values()`, and `.items()` for convenient iterators. -- `sorted(.items())`. for re-ordering entries in a `dict`. -- `dict_one.update()` for updating one `dict` with overlapping values from another `dict`. -- `dict | other_dict` and `dict |= other_dict` for merging or updating two `dict`s via operators. -- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` for reversed views. -- `.popitem()` for removing and returning a `key`, `value` pair. +- `dict.setdefault()` automatically adds keys without throwing a KeyError. +- `dict.fromkeys(iterable, )` creates a new `dict` from any number of iterables. +- `.keys()`, `.values()`, and `.items()` provide convenient iterators. +- `sorted(.items())`. can easily re-order entries in a `dict`. +- `dict_one.update()` updates one `dict` with overlapping values from another `dict`. +- `dict | other_dict` and `dict |= other_dict` merges or updates two `dict`s via operators. +- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` produce _reversed_ views. +- `.popitem()` removes and returns a `key`, `value` pair. -### `setdefault()` for Error-Free Insertion + +## `setdefault()` for Error-Free Insertion The dictionary concept previously covered that `.get(key, )` returns an existing `value` or the `default value` if a `key` is not found in a dictionary, thereby avoiding a `KeyError`. This works well in situations where you would rather not have extra error handling but cannot trust that a looked-for `key` will be present. @@ -35,18 +26,17 @@ If the key is **not** found, it will _insert_ the (`key`, `default value`) pair ```python >>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} -#Looking for the value associated with key "Rock Brown". -#The key does not exist, so it is added with the default -# value, and the value is returned. +# Looking for the value associated with key "Rock Brown".The key does not exist, +# so it is added with the default value, and the value is returned. >>> palette.setdefault('Rock Brown', '#694605') '#694605' -#The (key, default value) pair has now been added to the dictionary. +# The (key, default value) pair has now been added to the dictionary. >>> palette_I {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'} ``` -### Use `fromkeys()` to Populate a Dictionary +## `fromkeys()` to Populate a Dictionary from an Iterable To quickly populate a dictionary with various `keys` and default values, the _class method_ [`fromkeys(iterable, )`][fromkeys] will iterate through an iterable of `keys` and create a new `dict`. All `values` will be set to the `default value` provided: @@ -59,7 +49,7 @@ All `values` will be set to the `default value` provided: 'Misty Mountain Pink': 'fill in hex color here'} ``` -### Removing and Returning a (key, value) Pair With `.popitem()` +## Remove and Return a (key, value) Pair With `.popitem()` `.popitem()` removes & returns a single (`key`, `value`) pair from a dictionary. Pairs are returned in Last-in-First-out (`LIFO`) order. @@ -78,7 +68,7 @@ If the dictionary is empty, calling `popitem()` will raise a `KeyError`: >>> palette_I.popitem() ('Grassy Green', '#9bc400') -#All (key, value) pairs have been removed. +# All (key, value) pairs have been removed. >>> palette_I.popitem() Traceback (most recent call last): @@ -88,30 +78,31 @@ Traceback (most recent call last): KeyError: 'popitem(): dictionary is empty' ``` -### Iterating Over Entries in a Dictionary +## Iterating Over Entries in a Dictionary Via Views The `.keys()`, `.values()`, and `.items()` methods return [_iterable views_][dict-views] of a dictionary. -These views can be used for looping over entries without altering them. -They are also _dynamic_ -- when underlying dictionary data changes, the associated view object will reflect the change: + +These views can be used to easily loop over entries without altering them. +Views are also _dynamic_ -- when underlying dictionary data changes, the associated `view object` will reflect the change: ```python >>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} -#Using .keys() returns a list of keys. +# Using .keys() returns a list of keys. >>> palette_I.keys() dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink']) -#Using .values() returns a list of values. +# Using .values() returns a list of values. >>> palette_I.values() dict_values(['#9bc400', '#8076a3', '#f9c5bd']) -#Using .items() returns a list of (key, value) tuples. +# Using .items() returns a list of (key, value) tuples. >>> palette_I.items() dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')]) -#Views are dynamic. Changing values in the dict +# Views are dynamic. Changing values in the dict # changes all of the associated views. >>> palette_I['Purple Mountains Majesty'] = (128, 118, 163) >>> palette_I['Deep Red'] = '#932432' @@ -126,11 +117,12 @@ dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'D dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')]) ``` -### More on `.keys()`, `.values()`, and `.items()` +## More on `.keys()`, `.values()`, and `.items()` + +In Python 3.7+, `dicts` preserve the order in which entries are inserted allowing First-in, First-out (_`FIFO`_), iteration when using `.keys()`, `.values()`, or `.items()`. -In Python 3.7+, `dicts` preserve the order in which entries are inserted allowing First-in, First-out (_`FIFO`_), iteration using `.keys()`, `.values()`, or `.items()`. In Python 3.8+, views are also _reversible_. -This allows keys, values, or (key, value) pairs to be iterated over in Last-in, First-out (`LIFO`) order by using `reversed(.keys())`, `reversed(.values())`, or `reversed(.items())`: +This allows keys, values, or (`key`, `value`) pairs to be iterated over in Last-in, First-out (`LIFO`) order by using `reversed(.keys())`, `reversed(.values())`, or `reversed(.items())`: ```python >>> palette_II = {'Factory Stone Purple': '#7c677f', @@ -151,7 +143,7 @@ This allows keys, values, or (key, value) pairs to be iterated over in Last-in, ('Factory Stone Purple', '#7c677f') ``` -### Combining Dictionaries with `.update()` +## Combine Dictionaries with `.update()` `.update()` can be used to _combine_ two dictionaries. This method will take the (`key`,`value`) pairs of `` and write them into ``: @@ -166,7 +158,7 @@ This method will take the (`key`,`value`) pairs of `` and write them i >>> palette_I.update(palette_II) -#Note that new items from palette_II are added. +# Note that new items from palette_II are added. >>> palette_I {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'} ``` @@ -186,7 +178,7 @@ Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be 'Misty Mountain Pink': (249, 197, 189)} >>> palette_I.update(palette_III) -#Overlapping values in palette_I are replaced with +# Overlapping values in palette_I are replaced with # values from palette_III >>> palette_I {'Grassy Green': (155, 196, 0), @@ -196,7 +188,7 @@ Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ``` -### Merging and Updating Dictionaries Via the Union (`|`) Operators +## Merge or Update Dictionaries Via the Union (`|`) Operators Python 3.9 introduces a different means of merging `dicts`: the `union` operators. `dict_one | dict_two` will create a **new dictionary**, made up of the (`key`, `value`) pairs of `dict_one` and `dict_two`. @@ -239,7 +231,7 @@ When both dictionaries share keys, `dict_two` values take precedence. 'Purple baseline': '#161748'} ``` -### Sorting a Dictionary +## Sorting a Dictionary Dictionaries do not have a built-in sorting method. However, it is possible to sort a `dict` _view_ using the built-in function `sorted()` with `.items()`. @@ -279,7 +271,7 @@ Unless a _sort key_ is specified, the default sort is over dictionary `keys`. 'Misty Mountain Pink': '#f9c5bd'} ``` -### Transposing a Dictionaries Keys and Values +## Transposing a Dictionaries Keys and Values Swapping keys and values reliably in a dictionary takes a little work, but can be accomplished via a `loop` using `dict.items()` or in a dictionary comprehension. Safe swapping assumes that `dict` keys and values are both _hashable_. @@ -359,14 +351,11 @@ For a detailed explanation of dictionaries and methods for working with them, th For more on sorting, see the [Sorting HOW TO][sorting-howto] in the Python docs. -[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [dict-methods]: https://docs.python.org/3/library/stdtypes.html#dict [dict-views]: https://docs.python.org/3/library/stdtypes.html#dict-views [dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries [fi-dict-guide]: https://blog.finxter.com/python-dictionary [fromkeys]: https://docs.python.org/3/library/stdtypes.html#dict.fromkeys -[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table [how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp [mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict [sorting-howto]: https://docs.python.org/3/howto/sorting.html -[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable diff --git a/concepts/dict-methods/introduction.md b/concepts/dict-methods/introduction.md index 8a732643845..c15fbc113de 100644 --- a/concepts/dict-methods/introduction.md +++ b/concepts/dict-methods/introduction.md @@ -1,27 +1,16 @@ # Dictionary Methods in Python -A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. -Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. -As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. - -Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). -Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. -Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. The `dict` class in Python provides many useful [methods][dict-methods], some of which are introduced in the concept exercise for dictionaries. This concept tackles a few more: -- `dict.setdefault()` for automatically adding keys when needed. -- `dict.fromkeys(iterable, )` for creating a new `dict` from any number of iterables. -- `.keys()`, `.values()`, and `.items()` for convenient iterators. -- `sorted(.items())`. for re-ordering entries in a `dict`. -- `dict_one.update()` for updating one `dict` with overlapping values from another `dict`. -- `dict | other_dict` and `dict |= other_dict` for merging or updating two `dict`s via operators. -- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` for reversed views. -- `.popitem()` for removing and returning a `key`, `value` pair. +- `dict.setdefault()` automatically adds keys without throwing a `KeyError`. +- `dict.fromkeys(iterable, )` creates a new `dict` from any number of iterables. +- `.keys()`, `.values()`, and `.items()` provide convenient iterators. +- `sorted(.items())`. can easily re-order entries in a `dict`. +- `dict_one.update()` updates one `dict` with overlapping values from another `dict`. +- `dict | other_dict` and `dict |= other_dict` merges or updates two `dict`s via operators. +- `reversed(dict.keys())`, `reversed(dict.values())`, or `reversed(dict.items())` produce _reversed_ views. +- `.popitem()` removes and returns a `key`, `value` pair. -[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. -[mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict -[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table -[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable [dict-methods]: https://docs.python.org/3/library/stdtypes.html#dict diff --git a/concepts/dicts/about.md b/concepts/dicts/about.md index 305abc6c821..c34160b2ef6 100644 --- a/concepts/dicts/about.md +++ b/concepts/dicts/about.md @@ -3,7 +3,6 @@ A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. - `Keys` must be hashable and unique across the dictionary. Key types can include `numbers`, `str`, or `tuples` (of _immutable_ values). They cannot contain _mutable_ data structures such as `lists`, `dict`s, or `set`s. @@ -14,32 +13,34 @@ As of Python 3.7, `dict` key order is guaranteed to be the order in which entrie Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. + Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. ## Dictionary Construction -Dictionaries can be created in many different ways: +Dictionaries can be created in many different ways, including: - Using the [`fromkeys()`][fromkeys] classmethod - Creating [dictionary comprehensions][dict-comprehensions] - Merging two dictionaries via unpacking (`**`) - Merging dictionaries via the `|` (_update_) operator - Using a loop to iteratively add entries to a previously created empty `dict`. -Below are the two most straightforward methods of dictionary creation. +The two most straightforward methods are the dictionary _constructor_ and the dictionary _literal_. -### The `dict()` Class Constructor +### The Dictionary Constructor -`dict()` can be used with any iterable of `key`, `value` pairs or with a series of `=` _arguments_: +`dict()` (_the constructor for the `dict` class_) can be used with any iterable of `key`, `value` pairs. + It can also be called with a series of `=` _arguments_: ```python -#Passing a list of key,value tuples. +# Passing a list of key,value tuples. >>> wombat = dict([('name', 'Wombat'),('speed', 23), ('land_animal', True)]) {'name': 'Wombat', 'speed': 23, 'land_animal': True} -#Using key=value arguments. +# Using key=value arguments. >>> bear = dict(name="Black Bear", speed=40, land_animal=True) {'name': 'Black Bear', 'speed': 40, 'land_animal': True} ``` @@ -67,6 +68,8 @@ Entries that are enclosed in the `{}` can also appear on separate lines: {'name': 'Wombat', 'speed': 23, 'land_animal': True, 'color': 'Brindle'} ``` +### Nested Dictionaries + Dictionaries can be arbitrarily nested: ```python @@ -124,13 +127,13 @@ Accessing an entry via the `get(, )` method can avoid the `K 'not found' ``` -### Nested Dictionary Entries +### Accessing Nested Dictionary Entries To access entries in nested dictionaries, use successive brackets. If a given key is missing, the usual KeyError will be thrown: ```python -#Using the animals nested dictionary. +# Using the animals nested dictionary. >>> animals["Real"]["winged"]["Kestrel"]["speed"] 15 @@ -143,8 +146,8 @@ KeyError: 'Kestrel' To avoid the `KeyError`, `.get()` can be used, but the calls to `.get()` must be _chained_: ```python -#Using the animals nested dictionary. -#Note the use of parenthesis to enable placing the +# Using the animals nested dictionary. +# Note the use of parenthesis to enable placing the # .get() calls on separate lines. >>> (animals.get("Imaginary", {}) .get("Legged", {}) @@ -158,7 +161,7 @@ To avoid the `KeyError`, `.get()` can be used, but the calls to `.get()` must be You can change an entry `value` by assigning to its _key_: ```python -#Assigning the value "Grizzly Bear" to the name key. +# Assigning the value "Grizzly Bear" to the name key. >>> bear["name"] = "Grizzly Bear" {'name': 'Grizzly Bear', 'speed': 40, 'land_animal': True} @@ -186,20 +189,20 @@ Like `.get()`, `.pop()` accepts second argument (_`dict.pop(, >> bear.pop("name") 'Grizzly Bear' -#The "name" key is now removed from the dictionary. -#Attempting .pop() a second time will throw a KeyError. +# The "name" key is now removed from the dictionary. +# Attempting .pop() a second time will throw a KeyError. >>> bear.pop("name") Traceback (most recent call last): File "", line 1, in KeyError: 'name' -#Using a default argument with .pop() will +# Using a default argument with .pop() will # prevent a KeyError from a missing key. >>> bear.pop("name", "Unknown") 'Unknown' @@ -216,29 +219,29 @@ A `KeError` is raised if the entry to be removed is not found in the dictionary: 'talent': 'Singing', 'size': 'small'} -#Remove a single entry from the dictionary. +# Remove a single entry from the dictionary. >>> del wombat["color"] >>> wombat {'name': 'Wombat', 'speed': 23, 'land_animal': True, 'talent': 'Singing', 'size': 'small'} -#Remove multiple entries from the dictionary. +# Remove multiple entries from the dictionary. >>> del wombat["talent"], wombat["size"] >>> wombat {'name': 'Wombat', 'speed': 23, 'land_animal': True} -#Attempting a deletion of a non-existent key raises a KeyError +# Attempting a deletion of a non-existent key raises a KeyError >>> del wombat["number_of_legs"] Traceback (most recent call last): File "", line 1, in KeyError: 'number_of_legs' ``` -## Looping through/Iterating over a Dictionary +## Looping Through/Iterating over a Dictionary -Looping through a dictionary using `for item in dict` or `while item` will iterate over only the _keys _ by default. -You can access the _values_ within the same loop by using _square brackets_: +Looping through a dictionary using `for item in dict` or `while item` will iterate over the _keys_ by default. +You can access _values_ within the same loop by using _square brackets_: ```python >>> for key in bear: @@ -251,7 +254,7 @@ You can access the _values_ within the same loop by using _square brackets_: You can also use the `.items()` method, which returns (`key`, `value`) tuples: ```python -#dict.items() forms (key, value tuples) that can be +# dict.items() forms (key, value tuples) that can be # unpacked and iterated over. >>> for key, value in whale.items(): >>> print(key, ":", value) @@ -269,9 +272,11 @@ For a detailed explanation of dictionaries in Python, the [official documentatio ## Extending Dictionary Functionality: The Collections Module The [`collections`][collections-docs] module adds specialized functionality to Python's standard collection-based datatypes (`dictionary`, `set`, `list`, `tuple`). -A popular `dict`-oriented member of this module is the [`Counter`][counter-dicts], which automatically counts items and returns them in a `dict` with the items as keys and their counts as values. -There is also the [`OrderedDict`][ordered-dicts-docs], which has methods specialized for re-arranging the order of a dictionary. -Finally, there is the [`defaultdict`][default-dicts], a subclass of the built-in `dict` module that, based on a factory method, sets a default value if a key is not found when trying to retrieve or assign to a dictionary entry. +Three of the most useful dictionary-based classes are: + +- [`Counter`][counter-dicts] automatically counts items and returns them in a `dict` with the items as keys and their counts as values. +- [`OrderedDict`][ordered-dicts-docs], has methods specialized for arranging the order of dictionary entries. +- [`defaultdict`][default-dicts] uses a factory method to set a default value if a `key` is not found when trying to retrieve or assign to a dictionary entry. [associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [collections-docs]: https://docs.python.org/3/library/collections.html diff --git a/concepts/dicts/introduction.md b/concepts/dicts/introduction.md index 367a89536fd..5c8a772480b 100644 --- a/concepts/dicts/introduction.md +++ b/concepts/dicts/introduction.md @@ -14,8 +14,10 @@ As of Python 3.7, `dict` key order is guaranteed to be the order in which entrie Given a `key`, dictionaries can retrieve a `value` in (on average) constant time (_independent of the number of entries_). Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. + Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. + [associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table [mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict diff --git a/exercises/concept/mecha-munch-management/.docs/introduction.md b/exercises/concept/mecha-munch-management/.docs/introduction.md index 7088a08d98d..f1c5744e69a 100644 --- a/exercises/concept/mecha-munch-management/.docs/introduction.md +++ b/exercises/concept/mecha-munch-management/.docs/introduction.md @@ -1,21 +1,10 @@ # Dictionary Methods in Python -A dictionary (`dict`) in Python is a data structure that associates [hashable][term-hashable] _keys_ to _values_ and is known in other programming languages as a resizable [hash table][hashtable-wikipedia], hashmap, or [associative array][associative-array]. -Dictionaries are Python's only built-in [mapping type][mapping-types-dict]. -As of Python 3.7, `dict` key order is guaranteed to be the order in which entries are inserted. - - -Given the `key`, dictionaries enable the retrieval of a `value` in (on average) constant time (_independent of the number of entries_). -Compared to searching for a value within a `list` or `array` (_without knowing the `index` position_), a `dict` uses significantly more memory, but has very rapid retrieval. -Dictionaries are especially useful in scenarios where the collection of items is large and must be accessed and updated frequently. - -## Dictionary Methods - The `dict` class in Python provides many useful [methods][dict-methods] for working with dictionaries. Some were introduced in the concept for `dicts`. Here we cover a few more - along with some techniques for iterating through and manipulating dictionaries. -### `setdefault()` for Error-Free Insertion +### Use `setdefault()` for Error-Free Insertion The dictionary concept previously covered that `.get(key, )` returns an existing `value` or the `default value` if a `key` is not found in a dictionary, thereby avoiding a `KeyError`. This works well in situations where you would rather not have extra error handling but cannot trust that a looked-for `key` will be present. @@ -27,17 +16,17 @@ If the key is **not** found, it will _insert_ the (`key`, `default value`) pair ```python >>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} -#Looking for the value associated with key "Rock Brown". -#The key does not exist, so it is added with the default value, and the value is returned. +# Looking for the value associated with key "Rock Brown". +# The key does not exist, so it is added with the default value, and the value is returned. >>> palette.setdefault('Rock Brown', '#694605') '#694605' -#The (key, default value) pair has now been added to the dictionary. +# The (key, default value) pair has now been added to the dictionary. >>> palette_I {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'} ``` -### Use `fromkeys()` to Populate a Dictionary +## Use `fromkeys()` to Populate a Dictionary from an Iterable To quickly populate a dictionary with various `keys` and default values, the _class method_ [`fromkeys(iterable, )`][fromkeys] will iterate through an iterable of `keys` and create a new `dict`. All `values` will be set to the `default value` provided: @@ -50,31 +39,31 @@ All `values` will be set to the `default value` provided: 'Misty Mountain Pink': 'fill in hex color here'} ``` -### Iterating Over Entries in a Dictionary +## Iterating Over Entries in a Dictionary Via Views The `.keys()`, `.values()`, and `.items()` methods return [_iterable views_][dict-views] of a dictionary. -These views can be used for looping over entries without altering them. -They are also _dynamic_ -- when underlying dictionary data changes, the associated view object will reflect the change: +These views can be used to easily loop over entries without altering them. +Views are also _dynamic_ -- when underlying dictionary data changes, the associated `view object` will reflect the change: ```python >>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'} -#Using .keys() returns a list of keys. +# Using .keys() returns a list of keys. >>> palette_I.keys() dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink']) -#Using .values() returns a list of values. +# Using .values() returns a list of values. >>> palette_I.values() dict_values(['#9bc400', '#8076a3', '#f9c5bd']) -#Using .items() returns a list of (key, value) tuples. +# Using .items() returns a list of (key, value) tuples. >>> palette_I.items() dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')]) -#Views are dynamic. Changing values in the dict changes all of the associated views. +# Views are dynamic. Changing values in the dict changes all of the associated views. >>> palette_I['Purple Mountains Majesty'] = (128, 118, 163) >>> palette_I['Deep Red'] = '#932432' @@ -88,16 +77,17 @@ dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'D dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')]) ``` -### More on `.keys()`, `.values()`, and `.items()` +## More on `.keys()`, `.values()`, and `.items()` + +In Python 3.7+, `dicts` preserve the order in which entries are inserted allowing First-in, First-out (_`FIFO`_), iteration when using `.keys()`, `.values()`, or `.items()`. -In Python 3.7+, `dicts` preserve the order in which entries are inserted allowing First-in, First-out (_`FIFO`_), iteration using `.keys()`, `.values()`, or `.items()`. In Python 3.8+, views are also _reversible_. This allows keys, values, or (`key`, `value`) pairs to be iterated over in Last-in, First-out (`LIFO`) order by using `reversed(.keys())`, `reversed(.values())`, or `reversed(.items())`: ```python >>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'} -#Iterating in insertion order +# Iterating in insertion order >>> for item in palette_II.items(): ... print(item) ... @@ -106,7 +96,7 @@ This allows keys, values, or (`key`, `value`) pairs to be iterated over in Last- ('Purple baseline', '#161748') -#Iterating in the reverse direction. +# Iterating in the reverse direction. >>> for item in reversed(palette_II.items()): ... print (item) ... @@ -115,7 +105,7 @@ This allows keys, values, or (`key`, `value`) pairs to be iterated over in Last- ('Factory Stone Purple', '#7c677f') ``` -### Sorting a Dictionary +## Sorting a Dictionary Dictionaries do not have a built-in sorting method. However, it is possible to sort a `dict` _view_ using the built-in function `sorted()` with `.items()`. @@ -143,7 +133,7 @@ Like iteration, the default sort is over dictionary `keys`. 'Purple baseline': '#161748'} ``` -### Combining Dictionaries with `.update()` +## Combining Dictionaries with `.update()` `.update()` can be used to _combine_ two dictionaries. This method will take the (`key`,`value`) pairs of `` and write them into ``: @@ -158,7 +148,7 @@ This method will take the (`key`,`value`) pairs of `` and write them i >>> palette_I.update(palette_II) -#Note that new items from palette_II are added. +# Note that new items from palette_II are added. >>> palette_I {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'} ``` @@ -172,7 +162,7 @@ Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be 'Misty Mountain Pink': (249, 197, 189)} >>> palette_I.update(palette_III) -#Overlapping values in palette_I are replaced with values from palette_III +# Overlapping values in palette_I are replaced with values from palette_III >>> palette_I {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163), @@ -181,7 +171,7 @@ Where keys in the two dictionaries _overlap_, the `value` in `dict_one` will be 'Green Treeline': '#478559', 'Purple baseline': '#161748'} ``` -### Merging and Updating Dictionaries Via the Union (`|`) Operators +## Merge or Update Dictionaries Via the Union (`|`) Operators Python 3.9 introduces a different means of merging `dicts`: the `union` operators. `dict_one | dict_two` will create a **new dictionary**, made up of the (`key`, `value`) pairs of `dict_one` and `dict_two`. @@ -222,13 +212,10 @@ For a detailed explanation of dictionaries and methods for working with them, th [Real Python][how-to-dicts] and [Finxter][fi-dict-guide] also have very thorough articles on Python dictionaries. -[associative-array]: https://en.wikipedia.org/wiki/Associative_array#:~:text=In%20computer%20science%2C%20an%20associative,a%20function%20with%20finite%20domain. [dict-methods]: https://docs.python.org/3/library/stdtypes.html#dict [dict-views]: https://docs.python.org/3/library/stdtypes.html#dict-views [dicts-docs]: https://docs.python.org/3/tutorial/datastructures.html#dictionaries [fi-dict-guide]: https://blog.finxter.com/python-dictionary [fromkeys]: https://docs.python.org/3/library/stdtypes.html#dict.fromkeys -[hashtable-wikipedia]: https://en.wikipedia.org/wiki/Hash_table [how-to-dicts]: https://www.w3schools.com/python/python_dictionaries.asp [mapping-types-dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict -[term-hashable]: https://docs.python.org/3/glossary.html#term-hashable From 7c2f95afff4da6b2a19e2176fbd16f04089861a4 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Wed, 5 Jul 2023 07:42:00 -0700 Subject: [PATCH 093/126] Code example fixes for sets and cater-waiter exercise. --- concepts/sets/about.md | 4 ++-- exercises/concept/cater-waiter/.docs/introduction.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/concepts/sets/about.md b/concepts/sets/about.md index dd567f070f4..5f272402eef 100644 --- a/concepts/sets/about.md +++ b/concepts/sets/about.md @@ -12,7 +12,7 @@ _Unlike_ sequence types (_`string`, `list` & `tuple`_), `sets` are **neither ord They're also used for fast membership testing, finding supersets & subsets of items, and performing "set math" (_calculating union, intersection, difference & symmetric difference between groups of items._). Checking membership in a `set` has only O(1) time complexity versus checking for membership in a `list` or `string`, which has worst-case O(n) time complexity. -Operations such as `.union()`, `.intersection()`, or `.diference()` have an average O(n) time complexity. +Operations such as `.union()`, `.intersection()`, or `.difference()` have an average O(n) time complexity. ## Construction @@ -52,7 +52,7 @@ set() # The list is unpacked and each distinct element is added. >>> multiple_elements_from_list = set([2, 3, 2, 3, 3, 3, 5, 7, 11, 7, 11, 13, 13]) >>> multiple_elements_from_set -{2, 3, 5, 7, 11} +{2, 3, 5, 7, 11, 13} ``` Results when using a set constructor with a string or dictionary may be surprising: diff --git a/exercises/concept/cater-waiter/.docs/introduction.md b/exercises/concept/cater-waiter/.docs/introduction.md index fa29f0560e7..905504a63bc 100644 --- a/exercises/concept/cater-waiter/.docs/introduction.md +++ b/exercises/concept/cater-waiter/.docs/introduction.md @@ -50,7 +50,7 @@ set() # The list is unpacked and each distinct element is added. >>> multiple_elements_from_list = set([2, 3, 2, 3, 3, 3, 5, 7, 11, 7, 11, 13, 13]) >>> multiple_elements_from_set -{2, 3, 5, 7, 11} +{2, 3, 5, 7, 11, 13} ``` Sets can hold heterogeneous datatypes, but all `set` elements must be _hashable_: From c79d5a72d8e57a14ee091e6ea43c6aab427ee340 Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Sat, 24 Jun 2023 23:43:42 +0200 Subject: [PATCH 094/126] Started --- concepts/string-formatting/about.md | 87 +++++++++++++---------------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/concepts/string-formatting/about.md b/concepts/string-formatting/about.md index 07306a8d8bf..46452b41639 100644 --- a/concepts/string-formatting/about.md +++ b/concepts/string-formatting/about.md @@ -2,18 +2,18 @@ ## String Formatting in Python +String formatting is the process of converting values to strings and inserting them into a string template. The [Zen of Python][zen-of-python] asserts there should be "one _obvious_ way to do something in Python". -But when it comes to string formatting, things are a little .... _less zen_. +But when it comes to string formatting, things are a little ... _less zen_. It can be surprising to find out that there are **four** main ways to perform string formatting in Python - each for a different scenario. Some of this is due to Python's long history and some of it is due to considerations like internationalization or input sanitation. We will start with the most recent additions to the string formatting toolbox and work our way backward to "old style" or "printf() style" string formatting. +## literal string interpolation: The `f-string` -## literal string interpolation: The `f-string` - - Introduced in [Python 3.6][pep-0498], [`f-strings`][f-string] (_short for "formatted-strings"_) or [literal string interpolation][string interpolation] are a way of quickly and efficiently evaluating and formatting expressions and strings to a `str` type using the `f` (or `F`) prefix before the brackets (_like so `f'{object}'`_). - They can be used with all enclosing string types as: single quote `'`, double quote `"` and with multi-lines and escaping triple quotes `'''` or `"""`. - Any variables, expressions, or other types placed inside the `{}` are first evaluated, then converted to a `str`, then concatenated with any `str` outside the curly braces. +Introduced in [Python 3.6][pep-0498], [`f-strings`][f-string] (_short for "formatted-strings"_) or [literal string interpolation][string interpolation] are a way of quickly and efficiently evaluating and formatting expressions and strings to a `str` type using the `f` (or `F`) prefix before the brackets (_like so `f'{object}'`_). +They can be used with all enclosing string types as: single-line `'` or `"` and with multi-lines `'''` or `"""`. +Any variables, expressions, or other types placed inside the `{}` are first evaluated, then converted to a `str`, then concatenated with any `str` outside the curly braces. In this example, we insert two variable values in the sentence: one `str` and one `float`: @@ -23,8 +23,8 @@ In this example, we insert two variable values in the sentence: one `str` and on ... # The f-string, using the two values. # The .2f format code truncates so the value displays as 0.12. ->>> print(f'An {name} is approximately {value:.2f}.') -'An eighth is approximately 0.12.' +>>> f'An {name} is approximately {value:.2f}.' +'An eighth is approximately 0.12.' ``` The expressions evaluated can be almost anything. @@ -37,16 +37,16 @@ Some examples: >>> waves = {'water': 1, 'light': 3, 'sound': 5} # Using the name waves in an f-string. ->>> print(f'"A dict can be represented with f-string: {waves}."') +>>> f'"A dict can be represented with f-string: {waves}."' '"A dict can be represented with f-string: {\'water\': 1, \'light\': 3, \'sound\': 5}."' # Here, we pull a value from the dictionary by using the key ->>> print(f'Tenfold the value of "light" is {waves["light"]*10}.') +>>> f'Tenfold the value of "light" is {waves["light"] * 10}.' 'Tenfold the value of "light" is 30.' ``` Replacement fields (_the `{}` in the f-string_) support output control mechanisms such as width, alignment, precision. - This is the same [format specification mini-language][format-mini-language] that is used by the `str.format()` method. +This specification is started in the [format specification mini-language][format-mini-language]. A more complex example of an `f-string` that includes output control: @@ -61,24 +61,21 @@ A more complex example of an `f-string` that includes output control: # This example includes a function, str, a nested f-string, an arithmetic expression, # precision formatting, bracket escaping and object formatting. ->>> message = f'"Have a {"NICE".lower()} day, I will {verb} you after {f"{30e8*111_000:6.{precision}e}"} light-years."{{{the_end}}}' -... ->>> print(message) +>>> f'"Have a {"NICE".lower()} day, I will {verb} you after {f"{30e8 * 111_000:6.{precision}e}"} light-years."{{{the_end}}}' '"Have a nice day, I will meet you after 3.330e+14 light-years."{[\'end\', \'of\', \'transmission\']}' - ``` There are a few limitations to be aware of. -`f-string` expressions cannot be empty, they cannot contain comments, and for Python versions earlier than Python 3.7, they cannot contain `await` or `async for` clauses: +`f-string` expressions cannot be empty, they cannot contain comments. ```python ->>> print(f"An empty expression will error: {}") +>>> f"An empty expression will error: {}" SyntaxError: f-string: empty expression not allowed >>> word = 'word' ->>> print(f"""A comment in a triple quoted f-string will error: { +>>> f"""A comment in a triple quoted f-string will error: { word # I chose a nice variable -}""") +}""" SyntaxError: f-string expression part cannot include '#' ``` @@ -92,17 +89,16 @@ Also keep in mind that using expressions inside the `f-string` brackets `{}` is ## The `str.format()` Method The [`str.format()`][str-format] method replaces placeholders within the string with values fed as arguments to the function. - The placeholders are identified with named (`{price}`), numbered (`{0}` or indexed) or even empty (_positional_) placeholders `{}`. +The placeholders are identified with named (`{price}`), numbered (`{0}` or indexed) or even empty (_positional_) placeholders `{}`. For example: ```python # A named placeholder and a positional placeholder. ->>> print('My text: {placeholder_1} and {}.'.format(12, placeholder_1='named placeholder')) -... +>>> 'My text: {placeholder_1} and {}.'.format(12, placeholder_1='named placeholder') 'My text: named placeholder and 12.' ``` -As with `f-strings`, Pythons `str.format()` supports a whole range of [mini language format specifier][format-mini-language] that can be used to align text, convert, etc. +As with `f-strings`, Pythons `str.format()` supports a whole range of [mini language format specifier][format-mini-language] that can be used to align text, convert, etc. The complete formatting specifier pattern is `{[][!][:]}`: @@ -115,25 +111,24 @@ Example of conversions for a diacritical letter: ```python # Fills in the object at index zero, converted to a string. ->>> print('An e with an umlaut: {0!s}'.format('ë')) -An e with an umlaut: ë -... +>>> 'An e with an umlaut: {0!s}'.format('ë') +'An e with an umlaut: ë' + # Fills in the object at index zero, converted to a repr. ->>> print('An e with an umlaut object representation: {0!r}'.format('ë')) -An e with an umlaut object representation: 'ë' +>>> 'An e with an umlaut object representation: {0!r}'.format('ë') +"An e with an umlaut object representation: 'ë'" ... # Fills in the object at index zero, converted to ascii ->>> print('An e with an umlaut converted into ascii: {0!a}'.format('ë')) -An e with an umlaut converted into ascii: '\xeb' +>>> 'An e with an umlaut converted into ascii: {0!a}'.format('ë') +"An e with an umlaut converted into ascii: '\xeb'" -... # Fills in the object in the first position. # Then fills in the object in the second position formatted as a repr ->>> print('She said her name is not {} but {!r}.'.format('Chloe', 'Zoë')) +>>> 'She said her name is not {} but {!r}.'.format('Chloe', 'Zoë') "She said her name is not Chloe but 'Zoë'." ``` @@ -142,13 +137,12 @@ Example of using format specifiers: ```python # Formats the object at index 0 as a decimal with zero places, # then as a right-aligned binary number in an 8 character wide field. ->>> print("The number {0:d} has a representation in binary: '{0: >8b}'.".format(42)) -The number 42 has a representation in binary: ' 101010'. +>>> "The number {0:d} has a representation in binary: '{0: >8b}'.".format(42) +"The number 42 has a representation in binary: ' 101010'." ``` More examples are shown at the end of [this documentation][summary-string-format]. - ## `%` Formatting, or `printf()` Style Formatting Use of the `%` operator for formatting is the oldest method of string formatting in Python. @@ -157,16 +151,14 @@ It comes from the C language and allows the use of positional arguments to build This method has been superseded by both `f-strings` and `str.format()`, which is why the nickname for `%` formatting is _'Old Style'_. It can be still found in python 2 and/or legacy code. While using this method will work in Python 3.x, `%` formatting is usually avoided because it can be error-prone, is less efficient, has fewer options available, and any placeholder-argument mismatch can raise an exception. - Using the `%` operator is similar to [`printf()`][printf-style-docs], so it is also sometimes called _printf formatting_. - +Using the `%` operator is similar to [`printf()`][printf-style-docs], so it is also sometimes called _printf formatting_. ```python # Assigning a variable. ->> name = "Anna-conda" +>>> name = "Anna-conda" # Building a string using % ->> print("The snake's name is %s." % name) -... +>>> "The snake's name is %s." % name "The snake's name is Anna-conda." ``` @@ -179,33 +171,30 @@ If you want to add multiple variables to a string, you need to supply a [tuple][ >>> fruit = "grapes" # Building a string using % ->>> print("Surprisingly, %ss favorite snack was %s." %(name, fruit)) -Surprisingly, Billy the Kids favorite snack was grapes. +>>> "Surprisingly, %ss favorite snack was %s." %(name, fruit) +"Surprisingly, Billy the Kids favorite snack was grapes." ``` - ## Template Strings [`string.Template()`][string.Template()] is a class from the `string` module (_as opposed to the built-in `str` type_), which is part of the Python standard library, but has to be imported for use. Template strings support `$`-based substitution and are much simpler and less capable than the other options mentioned here, but can be very useful for when complicated internationalization is needed, or outside inputs need to be sanitized. - ```python ->> from string import Template +>>> from string import Template ->>> snake_name = "Anna-Conda" +>>> name = "Anna-Conda" # Creating a Template() with placeholder text ->> template_string = Template("The snake called `$snake_name` has escaped!") +>>> template_string = Template("The snake called `$snake_name` has escaped!") # Calling .substitute() to replace the placeholder with a value. ->> template_string.substitute(snake_name=name) +>>> template_string.substitute(snake_name=name) 'The snake called `Anna-Conda` has escaped!' ``` More information about `Template` string can be found in the Python [documentation][template-string]. - ## How Do You Choose which Formatting Method to Use? With all these options and mini-languages, how do you decide what to reach for when formatting Python strings? From 5bb59595d959f6c882a1cd5ea24fa5a615dbb844 Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 05:43:34 -0700 Subject: [PATCH 095/126] Removed footer macros, regen tests, all still pass (#3435) [no important files changed] --- exercises/practice/two-fer/.meta/template.j2 | 2 -- exercises/practice/two-fer/two_fer_test.py | 4 ---- exercises/practice/word-count/.meta/template.j2 | 3 --- exercises/practice/word-count/word_count_test.py | 4 ---- exercises/practice/word-search/.meta/template.j2 | 3 --- exercises/practice/word-search/word_search_test.py | 4 ---- exercises/practice/yacht/.meta/template.j2 | 2 -- exercises/practice/yacht/yacht_test.py | 4 ---- exercises/practice/zebra-puzzle/.meta/template.j2 | 2 -- exercises/practice/zebra-puzzle/zebra_puzzle_test.py | 4 ---- exercises/practice/zipper/.meta/template.j2 | 2 -- exercises/practice/zipper/zipper_test.py | 4 ---- 12 files changed, 38 deletions(-) diff --git a/exercises/practice/two-fer/.meta/template.j2 b/exercises/practice/two-fer/.meta/template.j2 index 51634eb1055..5db1d53c7e9 100644 --- a/exercises/practice/two-fer/.meta/template.j2 +++ b/exercises/practice/two-fer/.meta/template.j2 @@ -10,5 +10,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] | to_snake }}("{{ case["input"]["name"] }}"), "{{ case["expected"] }}") {% endif %} {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/two-fer/two_fer_test.py b/exercises/practice/two-fer/two_fer_test.py index 540930daf3c..ea74f1165dd 100644 --- a/exercises/practice/two-fer/two_fer_test.py +++ b/exercises/practice/two-fer/two_fer_test.py @@ -16,7 +16,3 @@ def test_a_name_given(self): def test_another_name_given(self): self.assertEqual(two_fer("Bob"), "One for Bob, one for me.") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/word-count/.meta/template.j2 b/exercises/practice/word-count/.meta/template.j2 index 2c91fdf963d..7e41be6776a 100644 --- a/exercises/practice/word-count/.meta/template.j2 +++ b/exercises/practice/word-count/.meta/template.j2 @@ -21,6 +21,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ test_case(case) }} {% endfor %} {%- endif %} - - -{{ macros.footer() }} diff --git a/exercises/practice/word-count/word_count_test.py b/exercises/practice/word-count/word_count_test.py index b63a9eb357a..329301a38ec 100644 --- a/exercises/practice/word-count/word_count_test.py +++ b/exercises/practice/word-count/word_count_test.py @@ -121,7 +121,3 @@ def test_non_alphanumeric(self): def test_multiple_apostrophes_ignored(self): self.assertEqual(count_words("''hey''"), {"hey": 1}) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/word-search/.meta/template.j2 b/exercises/practice/word-search/.meta/template.j2 index 309a2fc1a22..952da9e9114 100644 --- a/exercises/practice/word-search/.meta/template.j2 +++ b/exercises/practice/word-search/.meta/template.j2 @@ -20,6 +20,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {%- endfor %} {% endfor %} - -{{ macros.footer() }} - diff --git a/exercises/practice/word-search/word_search_test.py b/exercises/practice/word-search/word_search_test.py index 6ee050418d8..e5a32ceed7c 100644 --- a/exercises/practice/word-search/word_search_test.py +++ b/exercises/practice/word-search/word_search_test.py @@ -310,7 +310,3 @@ def test_should_not_wrap_around_horizontally_to_find_a_word(self): def test_should_not_wrap_around_vertically_to_find_a_word(self): puzzle = WordSearch(["s", "u", "r", "a", "b", "c", "t"]) self.assertIsNone(puzzle.search("rust")) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/yacht/.meta/template.j2 b/exercises/practice/yacht/.meta/template.j2 index 4086f512fc0..80eb31f7bcb 100644 --- a/exercises/practice/yacht/.meta/template.j2 +++ b/exercises/practice/yacht/.meta/template.j2 @@ -16,5 +16,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/yacht/yacht_test.py b/exercises/practice/yacht/yacht_test.py index 5c262c88856..32b929942c1 100644 --- a/exercises/practice/yacht/yacht_test.py +++ b/exercises/practice/yacht/yacht_test.py @@ -92,7 +92,3 @@ def test_choice(self): def test_yacht_as_choice(self): self.assertEqual(yacht.score([2, 2, 2, 2, 2], yacht.CHOICE), 10) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/zebra-puzzle/.meta/template.j2 b/exercises/practice/zebra-puzzle/.meta/template.j2 index 6b068c7e401..134ccdbf485 100644 --- a/exercises/practice/zebra-puzzle/.meta/template.j2 +++ b/exercises/practice/zebra-puzzle/.meta/template.j2 @@ -6,5 +6,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def test_{{ case["description"] | to_snake }}(self): self.assertEqual({{ case["property"] | to_snake }}(), "{{ case["expected"] }}") {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py index 034d4cccf4d..4b35afb7a7c 100644 --- a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py +++ b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py @@ -14,7 +14,3 @@ def test_resident_who_drinks_water(self): def test_resident_who_owns_zebra(self): self.assertEqual(owns_zebra(), "Japanese") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/zipper/.meta/template.j2 b/exercises/practice/zipper/.meta/template.j2 index 9f239bc1510..4e5de995238 100644 --- a/exercises/practice/zipper/.meta/template.j2 +++ b/exercises/practice/zipper/.meta/template.j2 @@ -52,5 +52,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {%- for case in cases %} {{ test_case(case) }} {%- endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/zipper/zipper_test.py b/exercises/practice/zipper/zipper_test.py index 5883e80df6c..d770c92b3e7 100644 --- a/exercises/practice/zipper/zipper_test.py +++ b/exercises/practice/zipper/zipper_test.py @@ -315,7 +315,3 @@ def test_different_paths_to_same_zipper(self): expected = Zipper.from_tree(final).right().to_tree() self.assertEqual(result, expected) - - -if __name__ == "__main__": - unittest.main() From 29a64a4889f94bafbd0062d7fc5052858523b25c Mon Sep 17 00:00:00 2001 From: Isaac Good Date: Fri, 14 Jul 2023 05:53:39 -0700 Subject: [PATCH 096/126] Remove Python 2 references from the track (#3437) * Remove Python 2 references from the track * Revert unintentional whitespace changes to test files [no important files changed] --- concepts/comparisons/about.md | 2 +- concepts/string-formatting/about.md | 2 +- docs/ABOUT.md | 2 +- docs/INSTALLATION.md | 4 ++-- exercises/concept/black-jack/.docs/introduction.md | 2 +- exercises/practice/circular-buffer/.meta/example.py | 2 +- exercises/practice/pythagorean-triplet/.meta/template.j2 | 3 --- .../practice/pythagorean-triplet/pythagorean_triplet_test.py | 4 ---- exercises/practice/sublist/sublist.py | 3 +-- pylintrc | 5 ----- reference/exercise-concepts/rna-transcription.md | 2 +- 11 files changed, 9 insertions(+), 22 deletions(-) diff --git a/concepts/comparisons/about.md b/concepts/comparisons/about.md index 568b6603c1a..c2f5faaad91 100644 --- a/concepts/comparisons/about.md +++ b/concepts/comparisons/about.md @@ -82,7 +82,7 @@ False Strings (`str`) are compared [_lexicographically_][lexographic order], using their individual Unicode code points (_the result of passing each code point in the `str` to the built-in function [`ord()`][ord], which returns an `int`_). If all code points in both strings match and are _**in the same order**_, the two strings are considered equal. This comparison is done in a 'pair-wise' fashion - first-to-first, second-to-second, etc. -Unlike in Python 2.x, in Python 3.x, `str` and `bytes` cannot be directly coerced/compared. +In Python 3.x, `str` and `bytes` cannot be directly coerced/compared. ```python >>> 'Python' > 'Rust' diff --git a/concepts/string-formatting/about.md b/concepts/string-formatting/about.md index 46452b41639..f3b2756b768 100644 --- a/concepts/string-formatting/about.md +++ b/concepts/string-formatting/about.md @@ -149,7 +149,7 @@ Use of the `%` operator for formatting is the oldest method of string formatting It comes from the C language and allows the use of positional arguments to build a `str`. This method has been superseded by both `f-strings` and `str.format()`, which is why the nickname for `%` formatting is _'Old Style'_. -It can be still found in python 2 and/or legacy code. +It can be still found in Python 2 and/or legacy code. While using this method will work in Python 3.x, `%` formatting is usually avoided because it can be error-prone, is less efficient, has fewer options available, and any placeholder-argument mismatch can raise an exception. Using the `%` operator is similar to [`printf()`][printf-style-docs], so it is also sometimes called _printf formatting_. diff --git a/docs/ABOUT.md b/docs/ABOUT.md index 05c56799ac6..f0d52389bf3 100644 --- a/docs/ABOUT.md +++ b/docs/ABOUT.md @@ -22,7 +22,7 @@ The [zen of Python (PEP 20)][the zen of python] and [What is Pythonic?][what is Tests and tooling for this track currently support `3.7` - `3.10.6` (_tests_) and [`Python 3.11`][311-new-features] (_tooling_). It is highly recommended that students upgrade to at least `Python 3.8`, as some features used by this track may not be supported in earlier versions. -That being said, most of the exercises will work with `Python 3.6+`, and many are compatible with `Python 2.7+`. +That being said, most of the exercises will work with `Python 3.6+`. But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases]. We will try to note when a feature is only available in a certain version. diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index 8bf42a04529..c8eb68ca466 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -6,7 +6,7 @@ Real Python also offers a [nice guide][helpful guide] to installation on various Finally, these posts by Brett Cannon [A quick-and-dirty guide][quick-and-dirty] and [Why you should use `python -m pip`][python-m-pip], give very helpful advice on how to manage Python installations and packages. **Note for MacOS users:** prior to MacOS Monterey (12.3), `Python 2.7` came pre-installed with the operating system. -Using `Python 2.7` with Exercism or most other programs is not recommended. +Using `Python 2.7` with Exercism or most other programs is not supported. You should instead install [Python 3][Python-three downloads] via one of the methods detailed below. As of MacOS Monterey (12.3), no version of Python will be pre-installed via MacOS. @@ -20,7 +20,7 @@ Some quick links into the documentation by operating system: Exercism tests and tooling currently support `3.7` - `3.10.6` (_tests_) and [`Python 3.11`][311-new-features] (_tooling_). Exceptions to this support are noted where they occur. -Most of the exercises will work with `Python 3.6+`, and many are compatible with `Python 2.7+`. +Most of the exercises will work with `Python 3.6+`. But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases]. diff --git a/exercises/concept/black-jack/.docs/introduction.md b/exercises/concept/black-jack/.docs/introduction.md index b79091f4ffd..207229359dd 100644 --- a/exercises/concept/black-jack/.docs/introduction.md +++ b/exercises/concept/black-jack/.docs/introduction.md @@ -80,7 +80,7 @@ False Unlike numbers, strings (`str`) are compared [_lexicographically_][lexographic order], using their individual Unicode code points (_the result of passing each code point in the `str` to the built-in function [`ord()`][ord], which returns an `int`_). If all code points in both strings match and are _**in the same order**_, the two strings are considered equal. This comparison is done in a 'pair-wise' fashion - first-to-first, second-to-second, etc. -Unlike in Python 2.x, in Python 3.x, `str` and `bytes` cannot be directly coerced/compared. +In Python 3.x, `str` and `bytes` cannot be directly coerced/compared. ```python >>> 'Python' > 'Rust' diff --git a/exercises/practice/circular-buffer/.meta/example.py b/exercises/practice/circular-buffer/.meta/example.py index 8438b9839fc..538cc7bc5e2 100644 --- a/exercises/practice/circular-buffer/.meta/example.py +++ b/exercises/practice/circular-buffer/.meta/example.py @@ -25,7 +25,7 @@ def __init__(self, capacity): self.read_point = 0 self.write_point = 0 - # (protected) helper method to support python 2/3 + # (protected) helper method def _update_buffer(self, data): try: self.buffer[self.write_point] = data diff --git a/exercises/practice/pythagorean-triplet/.meta/template.j2 b/exercises/practice/pythagorean-triplet/.meta/template.j2 index b3836a54427..e52cda4e230 100644 --- a/exercises/practice/pythagorean-triplet/.meta/template.j2 +++ b/exercises/practice/pythagorean-triplet/.meta/template.j2 @@ -2,9 +2,6 @@ {{ macros.header() }} -# Python 2/3 compatibility -if not hasattr(unittest.TestCase, 'assertCountEqual'): - unittest.TestCase.assertCountEqual = unittest.TestCase.assertItemsEqual class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py index 70d501c4fbc..bb094c909d8 100644 --- a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py +++ b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py @@ -6,10 +6,6 @@ # Tests adapted from `problem-specifications//canonical-data.json` -# Python 2/3 compatibility -if not hasattr(unittest.TestCase, "assertCountEqual"): - unittest.TestCase.assertCountEqual = unittest.TestCase.assertItemsEqual - class PythagoreanTripletTest(unittest.TestCase): def test_triplets_whose_sum_is_12(self): diff --git a/exercises/practice/sublist/sublist.py b/exercises/practice/sublist/sublist.py index 428d3aa656c..35410301d53 100644 --- a/exercises/practice/sublist/sublist.py +++ b/exercises/practice/sublist/sublist.py @@ -1,8 +1,7 @@ """ This exercise stub and the test suite contain several enumerated constants. -Since Python 2 does not have the enum module, the idiomatic way to write -enumerated constants has traditionally been a NAME assigned to an arbitrary, +Enumerated constants can be done with a NAME assigned to an arbitrary, but unique value. An integer is traditionally used because it’s memory efficient. It is a common practice to export both constants and functions that work with diff --git a/pylintrc b/pylintrc index 745e6f039af..09795978bc4 100644 --- a/pylintrc +++ b/pylintrc @@ -341,11 +341,6 @@ known-standard-library= # Force import order to recognize a module as part of a third party library. known-third-party=enchant, absl -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - [CLASSES] diff --git a/reference/exercise-concepts/rna-transcription.md b/reference/exercise-concepts/rna-transcription.md index b2b12946817..004ded95110 100644 --- a/reference/exercise-concepts/rna-transcription.md +++ b/reference/exercise-concepts/rna-transcription.md @@ -2,7 +2,7 @@ ## Example implementation -Modified from the existing [example.py](https://github.com/exercism/python/blob/master/exercises/rna-transcription/example.py) to remove Python 2 compatiblity noise: +Taken from the existing [example.py](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.meta/example.py): ```python DNA_TO_RNA = str.maketrans("AGCT", "UCGA") From 21658267b4f3b626a1a6f636ecdbed3f5eb79a99 Mon Sep 17 00:00:00 2001 From: Safwan Samsudeen <62411302+safwansamsudeen@users.noreply.github.com> Date: Fri, 14 Jul 2023 18:28:10 +0530 Subject: [PATCH 097/126] Approaches for Robot Name (#3451) * add intro and config * add content * compare approaches --- .../robot-name/.approaches/config.json | 21 +++++++ .../robot-name/.approaches/introduction.md | 59 +++++++++++++++++++ .../mass-name-generation/content.md | 49 +++++++++++++++ .../mass-name-generation/snippet.txt | 8 +++ .../.approaches/name-on-the-fly/content.md | 52 ++++++++++++++++ .../.approaches/name-on-the-fly/snippet.txt | 8 +++ 6 files changed, 197 insertions(+) create mode 100644 exercises/practice/robot-name/.approaches/config.json create mode 100644 exercises/practice/robot-name/.approaches/introduction.md create mode 100644 exercises/practice/robot-name/.approaches/mass-name-generation/content.md create mode 100644 exercises/practice/robot-name/.approaches/mass-name-generation/snippet.txt create mode 100644 exercises/practice/robot-name/.approaches/name-on-the-fly/content.md create mode 100644 exercises/practice/robot-name/.approaches/name-on-the-fly/snippet.txt diff --git a/exercises/practice/robot-name/.approaches/config.json b/exercises/practice/robot-name/.approaches/config.json new file mode 100644 index 00000000000..c71235ec7e4 --- /dev/null +++ b/exercises/practice/robot-name/.approaches/config.json @@ -0,0 +1,21 @@ +{ + "introduction": { + "authors": ["safwansamsudeen"] + }, + "approaches": [ + { + "uuid": "94d82d63-0a20-44df-ad9b-14aba7c076ae", + "slug": "mass-name-generation", + "title": "Mass Name Generation", + "blurb": "Select from all possible names", + "authors": ["safwansamsudeen"] + }, + { + "uuid": "20ca6d56-ab48-46be-a04e-98736109be0a", + "slug": "name-on-the-fly", + "title": "Find name on the fly", + "blurb": "Generate name and check that it hasn't been used", + "authors": ["safwansamsudeen"] + } + ] +} diff --git a/exercises/practice/robot-name/.approaches/introduction.md b/exercises/practice/robot-name/.approaches/introduction.md new file mode 100644 index 00000000000..9dc810ed5ea --- /dev/null +++ b/exercises/practice/robot-name/.approaches/introduction.md @@ -0,0 +1,59 @@ +# Introduction +Robot Name in Python is an interesting exercise for practising randomness. + +## General Guidance +Two ways immedietely come to mind: generate all the possible names and then return them sequentially, or generate a random name and ensure that it's not been previously used. + +Randomness can be a little, well, random, so **it's very easy to have an incorrect solution and still pass the tests**. It's strongly recommended to submit your solution for Code Review. + +## Approach: mass name generation +We'd first have to generate all the possible names, shuffle them, and then use `next` (the simplest way) or maintain a `current_index` and get the name. +Here's a possible way to do it: + +```python +from itertools import product +from random import shuffle +from string import ascii_uppercase as letters + +letter_pairs = (''.join(p) for p in product(letters, letters)) +numbers = (str(i).zfill(3) for i in range(1000)) +names = [l + n for l, n in product(letter_pairs, numbers)] +shuffle(names) +NAMES = iter(names) +class Robot(object): + def __init__(self): + self.reset() + def reset(self): + self.name = next(NAMES) +``` +Note that selecting randomly from the list of all names would be incorrect, as there's a possibility of the name being repeated. +For more detail and explanation of the code, [read here][approach-mass-name-generation]. + +## Approach: name on the fly +Another approach is to generate the name on the fly and add it to a cache or a store, and checking if the generated name hasn't been used previously. + + +A possible way to implement this: +```python +from string import ascii_uppercase, digits +from random import choices + + +cache = set() + + +class Robot: + def __get_name(self): + return ''.join(choices(ascii_uppercase, k=2) + choices(digits, k=3)) + + def reset(self): + while (name := self.__get_name()) in cache: + pass + cache.add(name) + self.name = name + + def __init__(self): + self.reset() +``` + +For more detail and different ways to implement this, [read here][approach-name-on-the-fly]. \ No newline at end of file diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/content.md b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md new file mode 100644 index 00000000000..6e5fad83e95 --- /dev/null +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/content.md @@ -0,0 +1,49 @@ +# Mass Name Generation +We'd first have to generate all the possible names, shuffle them, and then use `next` (the simplest way) or maintain a `current_index` and get the name. +Note that selecting randomly from the list of all names would be incorrect, as there's a possibility of the name being repeated. + +Here's a possible way to do it: + +```python +from itertools import product +from random import shuffle +from string import ascii_uppercase + +letter_pairs = (''.join(p) for p in product(ascii_uppercase, ascii_uppercase)) +numbers = (str(i).zfill(3) for i in range(1000)) +names = [l + n for l, n in product(letter_pairs, numbers)] + +shuffle(names) +NAMES = iter(names) + +class Robot(object): + def __init__(self): + self.reset() + def reset(self): + self.name = next(NAMES) +``` + +The first few lines of the mass name generation uses [`itertools.product`][itertools-product]. +The resultant code is a simplification of: +```python +letter_pairs = (''.join((l1, l2)) for l1 in ascii_uppercase for l2 in ascii_uppercase) +numbers = (str(i).zfill(3) for i in range(1000)) +names = [l + n for l in letter_pairs for n in numbers] +``` + +After the name generation, the names are shuffled - using the [default `seed`][random-seed] in the `random` module (the current timestamp). +When the tests reseed `random`, this has no effect as the names were shuffled before that. + +We then set `NAMES` to the iterable of names, and in `reset`, set the robot's name to the `next(name)`. +If you'd like, read more on [`iter` and `next`][iter-and-next]. + +Unlike the on the fly approach, this has a relatively short "generation" time, because we're merely giving the `next` name instead of generating it. +However, this has a huge startup memory and time cost, as 676,000 strings have to be calculated and stored. +For an approximate calculation, 676,000 strings * 5 characters / string * 1 byte / character gives 3380000 bytes or 3.38 MB of RAM - and that's just the memory aspect of it. +Sounds small, but it's relatively very expensive at the beginning. + +Thus, this approach is inefficient in cases where only a small amount of names are needed _and_ the time to set/reset the robot isn't crucial. + +[random-seed]: https://docs.python.org/3/library/random.html#random.seed +[iter-and-next]: https://www.programiz.com/python-programming/methods/built-in/iter +[itertools-product]: https://www.hackerrank.com/challenges/itertools-product/problem \ No newline at end of file diff --git a/exercises/practice/robot-name/.approaches/mass-name-generation/snippet.txt b/exercises/practice/robot-name/.approaches/mass-name-generation/snippet.txt new file mode 100644 index 00000000000..341230946b2 --- /dev/null +++ b/exercises/practice/robot-name/.approaches/mass-name-generation/snippet.txt @@ -0,0 +1,8 @@ +... +names = [l + n for l, n in product(letter_pairs, numbers)] +shuffle(names) +NAMES = iter(names) + +class Robot(object): + def reset(self): + self.name = next(NAMES) \ No newline at end of file diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md new file mode 100644 index 00000000000..0aa9f9a3fab --- /dev/null +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/content.md @@ -0,0 +1,52 @@ +# Find name on the fly +We generate the name on the fly and add it to a cache or a store, and checking if the generated name hasn't been used previously. + +A possible way to implement this: +```python +from string import ascii_uppercase, digits +from random import choices + +cache = set() + + +class Robot: + def __get_name(self): + return ''.join(choices(ascii_uppercase, k=2) + choices(digits, k=3)) + + def reset(self): + while (name := self.__get_name()) in cache: + pass + cache.add(name) + self.name = name + + def __init__(self): + self.reset() +``` +We use a `set` for the cache as it has a low access time, and we don't need the preservation of order or the ability to be indexed. + +This way is merely one of the many to generate the name. +Another way might be to use `randrange` along with `zfill` for the number part, and a double `random.choice` / `random.choice` on `itertools.product` to generate the letter part. +This is the shortest way, and best utilizes the Python standard library. + +As we're using a `while` loop to check for the name generation, it's convenient to store the local `name` using the [walrus operator][walrus-operator]. +It's also possible to find the name before the loop and find it again inside the loop, but that would unnecessary repetition. +A helper method ([private][private-helper-methods] in this case) makes your code cleaner, but it's equally valid to have the code in the loop itself: +```python +def reset(self): + while (name := ''.join(choices(ascii_uppercase, k=2) + choices(digits, k=3))) in cache: + pass + cache.add(name) + self.name = name +``` + +We call `reset` from `__init__` - it's syntactically valid to do it the other way round, but it's not considered good practice to call [dunder methods][dunder-methods] directly. + +This has almost no startup time and memory, apart from declaring an empty `set`. +Note that the _generation_ time is the same as the mass generation approach, as a similar method is used. +However, as the name is generated at the time of setting/resetting, the method time itself is higher. + +In the long run, if many names are generated, this is inefficient, since collisions will start being generated more often than unique names. + +[walrus-operator]: https://realpython.com/python-walrus-operator/ +[private-helper-methods]: https://www.geeksforgeeks.org/private-methods-in-python/ +[dunder-methods]: https://dbader.org/blog/python-dunder-methods \ No newline at end of file diff --git a/exercises/practice/robot-name/.approaches/name-on-the-fly/snippet.txt b/exercises/practice/robot-name/.approaches/name-on-the-fly/snippet.txt new file mode 100644 index 00000000000..e6ab23e7be5 --- /dev/null +++ b/exercises/practice/robot-name/.approaches/name-on-the-fly/snippet.txt @@ -0,0 +1,8 @@ +cache = set() +class Robot: + def reset(self): + while (name := ''.join(choices(ascii_uppercase, k=2) + choices(digits, k=3))) in cache: + pass + cache.add(name) + self.name = name + def __init__(self): self.reset() \ No newline at end of file From 3162bd4fe3e93efb07dcc04a23f57d7067078da1 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 06:50:28 -0700 Subject: [PATCH 098/126] Synced instructions and introduction files from problem specs. (#3423) --- .../practice/accumulate/.docs/instructions.md | 8 ++---- .../binary-search/.docs/instructions.md | 2 +- .../practice/binary/.docs/instructions.md | 9 +++--- .../practice/book-store/.docs/instructions.md | 28 +++++++++---------- .../practice/bowling/.docs/instructions.md | 2 +- .../practice/darts/.docs/instructions.md | 2 +- .../error-handling/.docs/instructions.md | 8 ++---- .../practice/gigasecond/.docs/introduction.md | 4 +-- .../hexadecimal/.docs/instructions.md | 3 +- .../.docs/instructions.md | 6 ++-- .../linked-list/.docs/instructions.md | 4 +-- .../nucleotide-count/.docs/instructions.md | 6 ++-- .../practice/octal/.docs/instructions.md | 8 ++---- .../practice/pangram/.docs/instructions.md | 2 +- .../practice/pangram/.docs/introduction.md | 4 +-- .../.docs/instructions.md | 7 ++--- .../queen-attack/.docs/instructions.md | 2 +- .../roman-numerals/.docs/instructions.md | 2 +- .../saddle-points/.docs/instructions.md | 6 ++-- .../saddle-points/.docs/introduction.md | 12 ++++---- .../secret-handshake/.docs/instructions.md | 1 + .../practice/sieve/.docs/instructions.md | 4 +-- .../practice/strain/.docs/instructions.md | 15 ++++------ .../sum-of-multiples/.docs/instructions.md | 6 ++-- .../practice/trinary/.docs/instructions.md | 13 ++++----- .../practice/two-fer/.docs/instructions.md | 12 ++++---- 26 files changed, 82 insertions(+), 94 deletions(-) diff --git a/exercises/practice/accumulate/.docs/instructions.md b/exercises/practice/accumulate/.docs/instructions.md index 435e0b32469..c25a03fab18 100644 --- a/exercises/practice/accumulate/.docs/instructions.md +++ b/exercises/practice/accumulate/.docs/instructions.md @@ -1,9 +1,6 @@ # Instructions -Implement the `accumulate` operation, which, given a collection and an -operation to perform on each element of the collection, returns a new -collection containing the result of applying that operation to each element of -the input collection. +Implement the `accumulate` operation, which, given a collection and an operation to perform on each element of the collection, returns a new collection containing the result of applying that operation to each element of the input collection. Given the collection of numbers: @@ -21,6 +18,5 @@ Check out the test suite to see the expected function signature. ## Restrictions -Keep your hands off that collect/map/fmap/whatchamacallit functionality -provided by your standard library! +Keep your hands off that collect/map/fmap/whatchamacallit functionality provided by your standard library! Solve this one yourself using other basic tools instead. diff --git a/exercises/practice/binary-search/.docs/instructions.md b/exercises/practice/binary-search/.docs/instructions.md index d7f1c899229..aa1946cfb00 100644 --- a/exercises/practice/binary-search/.docs/instructions.md +++ b/exercises/practice/binary-search/.docs/instructions.md @@ -11,7 +11,7 @@ Binary search only works when a list has been sorted. The algorithm looks like this: -- Find the middle element of a sorted list and compare it with the item we're looking for. +- Find the middle element of a *sorted* list and compare it with the item we're looking for. - If the middle element is our item, then we're done! - If the middle element is greater than our item, we can eliminate that element and all the elements **after** it. - If the middle element is less than our item, we can eliminate that element and all the elements **before** it. diff --git a/exercises/practice/binary/.docs/instructions.md b/exercises/practice/binary/.docs/instructions.md index 3cfde215fc9..046fd3e0998 100644 --- a/exercises/practice/binary/.docs/instructions.md +++ b/exercises/practice/binary/.docs/instructions.md @@ -2,9 +2,9 @@ Convert a binary number, represented as a string (e.g. '101010'), to its decimal equivalent using first principles. -Implement binary to decimal conversion. Given a binary input -string, your program should produce a decimal output. The -program should handle invalid inputs. +Implement binary to decimal conversion. +Given a binary input string, your program should produce a decimal output. +The program should handle invalid inputs. ## Note @@ -15,8 +15,7 @@ program should handle invalid inputs. Decimal is a base-10 system. -A number 23 in base 10 notation can be understood -as a linear combination of powers of 10: +A number 23 in base 10 notation can be understood as a linear combination of powers of 10: - The rightmost digit gets multiplied by 10^0 = 1 - The next number gets multiplied by 10^1 = 10 diff --git a/exercises/practice/book-store/.docs/instructions.md b/exercises/practice/book-store/.docs/instructions.md index 341ad01fbd2..906eb587619 100644 --- a/exercises/practice/book-store/.docs/instructions.md +++ b/exercises/practice/book-store/.docs/instructions.md @@ -12,9 +12,9 @@ If you buy 4 different books, you get a 20% discount. If you buy all 5, you get a 25% discount. -Note: that if you buy four books, of which 3 are different titles, you get a 10% discount on the 3 that form part of a set, but the fourth book still costs $8. +Note that if you buy four books, of which 3 are different titles, you get a 10% discount on the 3 that form part of a set, but the fourth book still costs $8. -Your mission is to write a piece of code to calculate the price of any conceivable shopping basket (containing only books of the same series), giving as big a discount as possible. +Your mission is to write code to calculate the price of any conceivable shopping basket (containing only books of the same series), giving as big a discount as possible. For example, how much does this basket of books cost? @@ -26,36 +26,36 @@ For example, how much does this basket of books cost? One way of grouping these 8 books is: -- 1 group of 5 --> 25% discount (1st,2nd,3rd,4th,5th) -- +1 group of 3 --> 10% discount (1st,2nd,3rd) +- 1 group of 5 (1st, 2nd,3rd, 4th, 5th) +- 1 group of 3 (1st, 2nd, 3rd) This would give a total of: - 5 books at a 25% discount -- +3 books at a 10% discount +- 3 books at a 10% discount Resulting in: -- 5 × (8 - 2.00) = 5 × 6.00 = $30.00 -- +3 × (8 - 0.80) = 3 × 7.20 = $21.60 +- 5 × (100% - 25%) * $8 = 5 × $6.00 = $30.00, plus +- 3 × (100% - 10%) * $8 = 3 × $7.20 = $21.60 -For a total of $51.60 +Which equals $51.60. However, a different way to group these 8 books is: -- 1 group of 4 books --> 20% discount (1st,2nd,3rd,4th) -- +1 group of 4 books --> 20% discount (1st,2nd,3rd,5th) +- 1 group of 4 books (1st, 2nd, 3rd, 4th) +- 1 group of 4 books (1st, 2nd, 3rd, 5th) This would give a total of: - 4 books at a 20% discount -- +4 books at a 20% discount +- 4 books at a 20% discount Resulting in: -- 4 × (8 - 1.60) = 4 × 6.40 = $25.60 -- +4 × (8 - 1.60) = 4 × 6.40 = $25.60 +- 4 × (100% - 20%) * $8 = 4 × $6.40 = $25.60, plus +- 4 × (100% - 20%) * $8 = 4 × $6.40 = $25.60 -For a total of $51.20 +Which equals $51.20. And $51.20 is the price with the biggest discount. diff --git a/exercises/practice/bowling/.docs/instructions.md b/exercises/practice/bowling/.docs/instructions.md index 48a2fedcf42..ddce7ee4895 100644 --- a/exercises/practice/bowling/.docs/instructions.md +++ b/exercises/practice/bowling/.docs/instructions.md @@ -36,7 +36,7 @@ Frame 3 is (9 + 0) = 9 This means the current running total is 48. The tenth frame in the game is a special case. -If someone throws a strike or a spare then they get a fill ball. +If someone throws a spare or a strike then they get one or two fill balls respectively. Fill balls exist to calculate the total of the 10th frame. Scoring a strike or spare on the fill ball does not give the player more fill balls. The total value of the 10th frame is the total number of pins knocked down. diff --git a/exercises/practice/darts/.docs/instructions.md b/exercises/practice/darts/.docs/instructions.md index 7af7428a06c..70f0e53da7c 100644 --- a/exercises/practice/darts/.docs/instructions.md +++ b/exercises/practice/darts/.docs/instructions.md @@ -12,7 +12,7 @@ In our particular instance of the game, the target rewards 4 different amounts o - If the dart lands in the inner circle of the target, player earns 10 points. The outer circle has a radius of 10 units (this is equivalent to the total radius for the entire target), the middle circle a radius of 5 units, and the inner circle a radius of 1. -Of course, they are all centered at the same point (that is, the circles are [concentric][] defined by the coordinates (0, 0). +Of course, they are all centered at the same point — that is, the circles are [concentric][] defined by the coordinates (0, 0). Write a function that given a point in the target (defined by its [Cartesian coordinates][cartesian-coordinates] `x` and `y`, where `x` and `y` are [real][real-numbers]), returns the correct amount earned by a dart landing at that point. diff --git a/exercises/practice/error-handling/.docs/instructions.md b/exercises/practice/error-handling/.docs/instructions.md index 7bc1a0856ba..25dd4d2928f 100644 --- a/exercises/practice/error-handling/.docs/instructions.md +++ b/exercises/practice/error-handling/.docs/instructions.md @@ -2,9 +2,7 @@ Implement various kinds of error handling and resource management. -An important point of programming is how to handle errors and close -resources even if errors occur. +An important point of programming is how to handle errors and close resources even if errors occur. -This exercise requires you to handle various errors. Because error handling -is rather programming language specific you'll have to refer to the tests -for your track to see what's exactly required. +This exercise requires you to handle various errors. +Because error handling is rather programming language specific you'll have to refer to the tests for your track to see what's exactly required. diff --git a/exercises/practice/gigasecond/.docs/introduction.md b/exercises/practice/gigasecond/.docs/introduction.md index 74afaa994f3..18a3dc20058 100644 --- a/exercises/practice/gigasecond/.docs/introduction.md +++ b/exercises/practice/gigasecond/.docs/introduction.md @@ -13,7 +13,7 @@ Then we can use metric system prefixes for writing large numbers of seconds in m - Perhaps you and your family would travel to somewhere exotic for two megaseconds (that's two million seconds). - And if you and your spouse were married for _a thousand million_ seconds, you would celebrate your one gigasecond anniversary. -```exercism/note +~~~~exercism/note If we ever colonize Mars or some other planet, measuring time is going to get even messier. If someone says "year" do they mean a year on Earth or a year on Mars? @@ -21,4 +21,4 @@ The idea for this exercise came from the science fiction novel ["A Deepness in t In it the author uses the metric system as the basis for time measurements. [vinge-novel]: https://www.tor.com/2017/08/03/science-fiction-with-something-for-everyone-a-deepness-in-the-sky-by-vernor-vinge/ -``` +~~~~ diff --git a/exercises/practice/hexadecimal/.docs/instructions.md b/exercises/practice/hexadecimal/.docs/instructions.md index 3e5afa77c6e..a3c648e32f7 100644 --- a/exercises/practice/hexadecimal/.docs/instructions.md +++ b/exercises/practice/hexadecimal/.docs/instructions.md @@ -2,7 +2,6 @@ Convert a hexadecimal number, represented as a string (e.g. "10af8c"), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion). -On the web we use hexadecimal to represent colors, e.g. green: 008000, -teal: 008080, navy: 000080). +On the web we use hexadecimal to represent colors, e.g. green: 008000, teal: 008080, navy: 000080). The program should handle invalid hexadecimal strings. diff --git a/exercises/practice/killer-sudoku-helper/.docs/instructions.md b/exercises/practice/killer-sudoku-helper/.docs/instructions.md index 93469a09cc0..2347ab262ca 100644 --- a/exercises/practice/killer-sudoku-helper/.docs/instructions.md +++ b/exercises/practice/killer-sudoku-helper/.docs/instructions.md @@ -56,8 +56,8 @@ The screenshots above have been generated using [F-Puzzles.com](https://www.f-pu [sudoku-rules]: https://masteringsudoku.com/sudoku-rules-beginners/ [killer-guide]: https://masteringsudoku.com/killer-sudoku/ -[one-solution-img]: https://media.githubusercontent.com/media/exercism/v3-files/main/julia/killer-sudoku-helper/example1.png -[four-solutions-img]: https://media.githubusercontent.com/media/exercism/v3-files/main/julia/killer-sudoku-helper/example2.png -[not-possible-img]: https://media.githubusercontent.com/media/exercism/v3-files/main/julia/killer-sudoku-helper/example3.png +[one-solution-img]: https://exercism-v3-icons.s3.eu-west-2.amazonaws.com/images/exercises/killer-sudoku-helper/example1.png +[four-solutions-img]: https://exercism-v3-icons.s3.eu-west-2.amazonaws.com/images/exercises/killer-sudoku-helper/example2.png +[not-possible-img]: https://exercism-v3-icons.s3.eu-west-2.amazonaws.com/images/exercises/killer-sudoku-helper/example3.png [clover-puzzle]: https://app.crackingthecryptic.com/sudoku/HqTBn3Pr6R [goodliffe-video]: https://youtu.be/c_NjEbFEeW0?t=1180 diff --git a/exercises/practice/linked-list/.docs/instructions.md b/exercises/practice/linked-list/.docs/instructions.md index a47942d73db..edf4055b38c 100644 --- a/exercises/practice/linked-list/.docs/instructions.md +++ b/exercises/practice/linked-list/.docs/instructions.md @@ -13,7 +13,7 @@ Sometimes a station gets closed down, and in that case the station needs to be r The size of a route is measured not by how far the train travels, but by how many stations it stops at. -```exercism/note +~~~~exercism/note The linked list is a fundamental data structure in computer science, often used in the implementation of other data structures. As the name suggests, it is a list of nodes that are linked together. It is a list of "nodes", where each node links to its neighbor or neighbors. @@ -23,4 +23,4 @@ In a **doubly linked list** each node links to both the node that comes before, If you want to dig deeper into linked lists, check out [this article][intro-linked-list] that explains it using nice drawings. [intro-linked-list]: https://medium.com/basecs/whats-a-linked-list-anyway-part-1-d8b7e6508b9d -``` +~~~~ diff --git a/exercises/practice/nucleotide-count/.docs/instructions.md b/exercises/practice/nucleotide-count/.docs/instructions.md index 57667134b72..548d9ba5a5e 100644 --- a/exercises/practice/nucleotide-count/.docs/instructions.md +++ b/exercises/practice/nucleotide-count/.docs/instructions.md @@ -1,10 +1,12 @@ # Instructions -Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. All known life depends on DNA! +Each of us inherits from our biological parents a set of chemical instructions known as DNA that influence how our bodies are constructed. +All known life depends on DNA! > Note: You do not need to understand anything about nucleotides or DNA to complete this exercise. -DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important! +DNA is a long chain of other chemicals and the most important are the four nucleotides, adenine, cytosine, guanine and thymine. +A single DNA chain can contain billions of these four nucleotides and the order in which they occur is important! We call the order of these nucleotides in a bit of DNA a "DNA sequence". We represent a DNA sequence as an ordered collection of these four nucleotides and a common way to do that is with a string of characters such as "ATTACG" for a DNA sequence of 6 nucleotides. diff --git a/exercises/practice/octal/.docs/instructions.md b/exercises/practice/octal/.docs/instructions.md index 81f108384b0..65ce135c6ff 100644 --- a/exercises/practice/octal/.docs/instructions.md +++ b/exercises/practice/octal/.docs/instructions.md @@ -1,11 +1,9 @@ # Instructions -Convert an octal number, represented as a string (e.g. '1735263'), to its -decimal equivalent using first principles (i.e. no, you may not use built-in or -external libraries to accomplish the conversion). +Convert an octal number, represented as a string (e.g. '1735263'), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion). -Implement octal to decimal conversion. Given an octal input -string, your program should produce a decimal output. +Implement octal to decimal conversion. +Given an octal input string, your program should produce a decimal output. ## Note diff --git a/exercises/practice/pangram/.docs/instructions.md b/exercises/practice/pangram/.docs/instructions.md index d5698bc2a29..817c872d907 100644 --- a/exercises/practice/pangram/.docs/instructions.md +++ b/exercises/practice/pangram/.docs/instructions.md @@ -5,4 +5,4 @@ Your task is to figure out if a sentence is a pangram. A pangram is a sentence using every letter of the alphabet at least once. It is case insensitive, so it doesn't matter if a letter is lower-case (e.g. `k`) or upper-case (e.g. `K`). -For this exercise we only use the basic letters used in the English alphabet: `a` to `z`. +For this exercise, a sentence is a pangram if it contains each of the 26 letters in the English alphabet. diff --git a/exercises/practice/pangram/.docs/introduction.md b/exercises/practice/pangram/.docs/introduction.md index d38fa341dfa..32b6f1fc317 100644 --- a/exercises/practice/pangram/.docs/introduction.md +++ b/exercises/practice/pangram/.docs/introduction.md @@ -7,10 +7,10 @@ To give a comprehensive sense of the font, the random sentences should use **all They're running a competition to get suggestions for sentences that they can use. You're in charge of checking the submissions to see if they are valid. -```exercism/note +~~~~exercism/note Pangram comes from Greek, παν γράμμα, pan gramma, which means "every letter". The best known English pangram is: > The quick brown fox jumps over the lazy dog. -``` +~~~~ diff --git a/exercises/practice/parallel-letter-frequency/.docs/instructions.md b/exercises/practice/parallel-letter-frequency/.docs/instructions.md index a5b936c5e2a..85abcf86a42 100644 --- a/exercises/practice/parallel-letter-frequency/.docs/instructions.md +++ b/exercises/practice/parallel-letter-frequency/.docs/instructions.md @@ -2,7 +2,6 @@ Count the frequency of letters in texts using parallel computation. -Parallelism is about doing things in parallel that can also be done -sequentially. A common example is counting the frequency of letters. -Create a function that returns the total frequency of each letter in a -list of texts and that employs parallelism. +Parallelism is about doing things in parallel that can also be done sequentially. +A common example is counting the frequency of letters. +Create a function that returns the total frequency of each letter in a list of texts and that employs parallelism. diff --git a/exercises/practice/queen-attack/.docs/instructions.md b/exercises/practice/queen-attack/.docs/instructions.md index dce0fc29850..ad7ea954796 100644 --- a/exercises/practice/queen-attack/.docs/instructions.md +++ b/exercises/practice/queen-attack/.docs/instructions.md @@ -21,5 +21,5 @@ So if you are told the white queen is at `c5` (zero-indexed at column 2, row 3) a b c d e f g h ``` -You are also be able to answer whether the queens can attack each other. +You are also able to answer whether the queens can attack each other. In this case, that answer would be yes, they can, because both pieces share a diagonal. diff --git a/exercises/practice/roman-numerals/.docs/instructions.md b/exercises/practice/roman-numerals/.docs/instructions.md index bb7e909dbf2..247ea0892e0 100644 --- a/exercises/practice/roman-numerals/.docs/instructions.md +++ b/exercises/practice/roman-numerals/.docs/instructions.md @@ -36,6 +36,6 @@ In Roman numerals 1990 is MCMXC: 2000=MM 8=VIII -Learn more about [Roman numberals on Wikipedia][roman-numerals]. +Learn more about [Roman numerals on Wikipedia][roman-numerals]. [roman-numerals]: https://wiki.imperivm-romanvm.com/wiki/Roman_Numerals diff --git a/exercises/practice/saddle-points/.docs/instructions.md b/exercises/practice/saddle-points/.docs/instructions.md index d861388e437..c585568b462 100644 --- a/exercises/practice/saddle-points/.docs/instructions.md +++ b/exercises/practice/saddle-points/.docs/instructions.md @@ -5,20 +5,22 @@ Your task is to find the potential trees where you could build your tree house. The data company provides the data as grids that show the heights of the trees. The rows of the grid represent the east-west direction, and the columns represent the north-south direction. -An acceptable tree will be the the largest in its row, while being the smallest in its column. +An acceptable tree will be the largest in its row, while being the smallest in its column. A grid might not have any good trees at all. Or it might have one, or even several. Here is a grid that has exactly one candidate tree. +```text 1 2 3 4 |----------- 1 | 9 8 7 8 2 | 5 3 2 4 <--- potential tree house at row 2, column 1, for tree with height 5 3 | 6 6 7 1 +``` -- Row 2 has values 5, 3, and 1. The largest value is 5. +- Row 2 has values 5, 3, 2, and 4. The largest value is 5. - Column 1 has values 9, 5, and 6. The smallest value is 5. So the point at `[2, 1]` (row: 2, column: 1) is a great spot for a tree house. diff --git a/exercises/practice/saddle-points/.docs/introduction.md b/exercises/practice/saddle-points/.docs/introduction.md index b582efbd21d..34b2c77e0cf 100644 --- a/exercises/practice/saddle-points/.docs/introduction.md +++ b/exercises/practice/saddle-points/.docs/introduction.md @@ -1,9 +1,11 @@ # Introduction -You are planning on building a tree house in the woods near your house so that you can watch the sun rise and set. +You plan to build a tree house in the woods near your house so that you can watch the sun rise and set. -You've obtained data from a local survey company that shows the heights of all the trees in each rectangular section of the map. -You need to analyze each grid on the map to find the perfect tree for your tree house. +You've obtained data from a local survey company that show the height of every tree in each rectangular section of the map. +You need to analyze each grid on the map to find good trees for your tree house. -The best tree will be the tallest tree compared to all the other trees to the east and west, so that you have the best possible view of the sunrises and sunsets. -You don't like climbing too much, so the perfect tree will also be the shortest among all the trees to the north and to the south. +A good tree is both: + +- taller than every tree to the east and west, so that you have the best possible view of the sunrises and sunsets. +- shorter than every tree to the north and south, to minimize the amount of tree climbing. diff --git a/exercises/practice/secret-handshake/.docs/instructions.md b/exercises/practice/secret-handshake/.docs/instructions.md index 77136cf0f7b..d2120b9bf2e 100644 --- a/exercises/practice/secret-handshake/.docs/instructions.md +++ b/exercises/practice/secret-handshake/.docs/instructions.md @@ -43,5 +43,6 @@ jump, double blink ~~~~exercism/note If you aren't sure what binary is or how it works, check out [this binary tutorial][intro-to-binary]. + [intro-to-binary]: https://medium.com/basecs/bits-bytes-building-with-binary-13cb4289aafa ~~~~ diff --git a/exercises/practice/sieve/.docs/instructions.md b/exercises/practice/sieve/.docs/instructions.md index ec14620ce45..3adf1d551be 100644 --- a/exercises/practice/sieve/.docs/instructions.md +++ b/exercises/practice/sieve/.docs/instructions.md @@ -18,11 +18,11 @@ Then you repeat the following steps: You keep repeating these steps until you've gone through every number in your list. At the end, all the unmarked numbers are prime. -```exercism/note +~~~~exercism/note [Wikipedia's Sieve of Eratosthenes article][eratosthenes] has a useful graphic that explains the algorithm. The tests don't check that you've implemented the algorithm, only that you've come up with the correct list of primes. A good first test is to check that you do not use division or remainder operations. [eratosthenes]: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes -``` +~~~~ diff --git a/exercises/practice/strain/.docs/instructions.md b/exercises/practice/strain/.docs/instructions.md index 370eb2216fd..3469ae6579d 100644 --- a/exercises/practice/strain/.docs/instructions.md +++ b/exercises/practice/strain/.docs/instructions.md @@ -1,9 +1,7 @@ # Instructions -Implement the `keep` and `discard` operation on collections. Given a collection -and a predicate on the collection's elements, `keep` returns a new collection -containing those elements where the predicate is true, while `discard` returns -a new collection containing those elements where the predicate is false. +Implement the `keep` and `discard` operation on collections. +Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false. For example, given the collection of numbers: @@ -23,12 +21,9 @@ While your discard operation should produce: Note that the union of keep and discard is all the elements. -The functions may be called `keep` and `discard`, or they may need different -names in order to not clash with existing functions or concepts in your -language. +The functions may be called `keep` and `discard`, or they may need different names in order to not clash with existing functions or concepts in your language. ## Restrictions -Keep your hands off that filter/reject/whatchamacallit functionality -provided by your standard library! Solve this one yourself using other -basic tools instead. +Keep your hands off that filter/reject/whatchamacallit functionality provided by your standard library! +Solve this one yourself using other basic tools instead. diff --git a/exercises/practice/sum-of-multiples/.docs/instructions.md b/exercises/practice/sum-of-multiples/.docs/instructions.md index e9a25636e51..d69f890e9d6 100644 --- a/exercises/practice/sum-of-multiples/.docs/instructions.md +++ b/exercises/practice/sum-of-multiples/.docs/instructions.md @@ -7,12 +7,12 @@ The points awarded depend on two things: - The level (a number) that the player completed. - The base value of each magical item collected by the player during that level. -The energy points are awarded according to the following rules: +The energy points are awarded according to the following rules: 1. For each magical item, take the base value and find all the multiples of that value that are less than the level number. 2. Combine the sets of numbers. 3. Remove any duplicates. -4. Calculate the sum of all the numbers that are left. +4. Calculate the sum of all the numbers that are left. Let's look at an example: @@ -24,4 +24,4 @@ To calculate the energy points earned by the player, we need to find all the uni - Multiples of 5 less than 20: `{5, 10, 15}` - Combine the sets and remove duplicates: `{3, 5, 6, 9, 10, 12, 15, 18}` - Sum the unique multiples: `3 + 5 + 6 + 9 + 10 + 12 + 15 + 18 = 78` -- Therefore, the player earns **78** energy points for completing level 20 and finding the two magical items with base values of 3 and 5 +- Therefore, the player earns **78** energy points for completing level 20 and finding the two magical items with base values of 3 and 5. diff --git a/exercises/practice/trinary/.docs/instructions.md b/exercises/practice/trinary/.docs/instructions.md index 3638ddb74b1..d38e3b5bbf4 100644 --- a/exercises/practice/trinary/.docs/instructions.md +++ b/exercises/practice/trinary/.docs/instructions.md @@ -1,15 +1,13 @@ # Instructions -Convert a trinary number, represented as a string (e.g. '102012'), to its -decimal equivalent using first principles. +Convert a trinary number, represented as a string (e.g. '102012'), to its decimal equivalent using first principles. -The program should consider strings specifying an invalid trinary as the -value 0. +The program should consider strings specifying an invalid trinary as the value 0. Trinary numbers contain three symbols: 0, 1, and 2. -The last place in a trinary number is the 1's place. The second to last -is the 3's place, the third to last is the 9's place, etc. +The last place in a trinary number is the 1's place. +The second to last is the 3's place, the third to last is the 9's place, etc. ```shell # "102012" @@ -18,5 +16,4 @@ is the 3's place, the third to last is the 9's place, etc. 243 + 0 + 54 + 0 + 3 + 2 = 302 ``` -If your language provides a method in the standard library to perform the -conversion, pretend it doesn't exist and implement it yourself. +If your language provides a method in the standard library to perform the conversion, pretend it doesn't exist and implement it yourself. diff --git a/exercises/practice/two-fer/.docs/instructions.md b/exercises/practice/two-fer/.docs/instructions.md index a9bb4a3cd3c..37aa75297ea 100644 --- a/exercises/practice/two-fer/.docs/instructions.md +++ b/exercises/practice/two-fer/.docs/instructions.md @@ -17,9 +17,9 @@ One for you, one for me. Here are some examples: -|Name |Dialogue -|:-------|:------------------ -|Alice |One for Alice, one for me. -|Bohdan |One for Bohdan, one for me. -| |One for you, one for me. -|Zaphod |One for Zaphod, one for me. +| Name | Dialogue | +| :----- | :-------------------------- | +| Alice | One for Alice, one for me. | +| Bohdan | One for Bohdan, one for me. | +| | One for you, one for me. | +| Zaphod | One for Zaphod, one for me. | From 7a341963902183f2deea61fa9e1727c32a6452bc Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 08:45:44 -0700 Subject: [PATCH 099/126] Remove footer macros, regen tests, all still pass (#3434) [no important files changed] --- exercises/practice/knapsack/.meta/template.j2 | 2 -- exercises/practice/knapsack/knapsack_test.py | 4 ---- exercises/practice/leap/.meta/template.j2 | 2 -- exercises/practice/leap/leap_test.py | 4 ---- exercises/practice/list-ops/.meta/template.j2 | 3 --- exercises/practice/list-ops/list_ops_test.py | 4 ---- exercises/practice/matching-brackets/.meta/template.j2 | 4 ---- .../practice/matching-brackets/matching_brackets_test.py | 4 ---- exercises/practice/pangram/.meta/template.j2 | 1 - exercises/practice/pangram/pangram_test.py | 4 ---- 10 files changed, 32 deletions(-) diff --git a/exercises/practice/knapsack/.meta/template.j2 b/exercises/practice/knapsack/.meta/template.j2 index 12760c7abae..3c59a9e89cb 100644 --- a/exercises/practice/knapsack/.meta/template.j2 +++ b/exercises/practice/knapsack/.meta/template.j2 @@ -13,5 +13,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] |to_snake }}({{weight}}, {{items}}), {{expected}}) {% endif%} {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/knapsack/knapsack_test.py b/exercises/practice/knapsack/knapsack_test.py index 0a792f179c3..937df1bb0ff 100644 --- a/exercises/practice/knapsack/knapsack_test.py +++ b/exercises/practice/knapsack/knapsack_test.py @@ -100,7 +100,3 @@ def test_15_items(self): ), 1458, ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/leap/.meta/template.j2 b/exercises/practice/leap/.meta/template.j2 index 968306fcb71..66516c2b0dd 100644 --- a/exercises/practice/leap/.meta/template.j2 +++ b/exercises/practice/leap/.meta/template.j2 @@ -11,5 +11,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{- case ["expected"] }} ) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/leap/leap_test.py b/exercises/practice/leap/leap_test.py index e51aeb423a7..6ba0f949b1c 100644 --- a/exercises/practice/leap/leap_test.py +++ b/exercises/practice/leap/leap_test.py @@ -34,7 +34,3 @@ def test_year_divisible_by_400_but_not_by_125_is_still_a_leap_year(self): def test_year_divisible_by_200_not_divisible_by_400_in_common_year(self): self.assertIs(leap_year(1800), False) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/list-ops/.meta/template.j2 b/exercises/practice/list-ops/.meta/template.j2 index cc28280f174..3ce6a3033b2 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -52,6 +52,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ test_case(case) }} {% endfor %} {%- endif %} - - -{{ macros.footer() }} diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index a2a301295ac..cb015acc66c 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -98,7 +98,3 @@ def test_foldr_foldr_add_string(self): def test_reverse_reverse_mixed_types(self): self.assertEqual(reverse(["xyz", 4.0, "cat", 1]), [1, "cat", 4.0, "xyz"]) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/matching-brackets/.meta/template.j2 b/exercises/practice/matching-brackets/.meta/template.j2 index bc8f0830264..0d43598bfd5 100644 --- a/exercises/practice/matching-brackets/.meta/template.j2 +++ b/exercises/practice/matching-brackets/.meta/template.j2 @@ -8,7 +8,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {%- set expected = case["expected"] %} self.assertEqual({{ case["property"] | to_snake }}({{ "{!r}".format(value) }}), {{ expected }}) {% endfor %} - -{{ macros.footer() }} - - diff --git a/exercises/practice/matching-brackets/matching_brackets_test.py b/exercises/practice/matching-brackets/matching_brackets_test.py index fd23bd78403..fb270ae8bce 100644 --- a/exercises/practice/matching-brackets/matching_brackets_test.py +++ b/exercises/practice/matching-brackets/matching_brackets_test.py @@ -72,7 +72,3 @@ def test_complex_latex_expression(self): ), True, ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/pangram/.meta/template.j2 b/exercises/practice/pangram/.meta/template.j2 index 7e93a443548..a365b456863 100644 --- a/exercises/practice/pangram/.meta/template.j2 +++ b/exercises/practice/pangram/.meta/template.j2 @@ -22,4 +22,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ test_case(case) }} {% endfor %} {%- endif %} -{{ macros.footer() }} diff --git a/exercises/practice/pangram/pangram_test.py b/exercises/practice/pangram/pangram_test.py index 1031cb4e6a4..3f8c9aa7f38 100644 --- a/exercises/practice/pangram/pangram_test.py +++ b/exercises/practice/pangram/pangram_test.py @@ -50,7 +50,3 @@ def test_sentence_without_lower_bound(self): def test_sentence_without_upper_bound(self): self.assertIs(is_pangram("abcdefghijklmnopqrstuvwxy"), False) - - -if __name__ == "__main__": - unittest.main() From a2b8f4cebf189c88612f7d52d4464eaac553fe2d Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 09:02:04 -0700 Subject: [PATCH 100/126] Remove footer macros, regen tests, all pass still (#3432) Test File Footer Cleanup. [no important files changed] --- exercises/practice/atbash-cipher/.meta/template.j2 | 2 -- exercises/practice/atbash-cipher/atbash_cipher_test.py | 4 ---- exercises/practice/beer-song/.meta/template.j2 | 3 --- exercises/practice/beer-song/beer_song_test.py | 4 ---- exercises/practice/binary-search-tree/.meta/template.j2 | 3 --- .../practice/binary-search-tree/binary_search_tree_test.py | 4 ---- exercises/practice/bob/.meta/template.j2 | 2 -- exercises/practice/bob/bob_test.py | 4 ---- exercises/practice/book-store/.meta/template.j2 | 2 -- exercises/practice/book-store/book_store_test.py | 4 ---- 10 files changed, 32 deletions(-) diff --git a/exercises/practice/atbash-cipher/.meta/template.j2 b/exercises/practice/atbash-cipher/.meta/template.j2 index d3eb3d87621..1ad9d5759cb 100644 --- a/exercises/practice/atbash-cipher/.meta/template.j2 +++ b/exercises/practice/atbash-cipher/.meta/template.j2 @@ -11,5 +11,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/atbash-cipher/atbash_cipher_test.py b/exercises/practice/atbash-cipher/atbash_cipher_test.py index 98c1072afc7..fcc1a25e68f 100644 --- a/exercises/practice/atbash-cipher/atbash_cipher_test.py +++ b/exercises/practice/atbash-cipher/atbash_cipher_test.py @@ -61,7 +61,3 @@ def test_decode_with_no_spaces(self): self.assertEqual( decode("zmlyhgzxovrhlugvmzhgvkkrmthglmv"), "anobstacleisoftenasteppingstone" ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/beer-song/.meta/template.j2 b/exercises/practice/beer-song/.meta/template.j2 index 37e45402da9..7fd4a26de74 100644 --- a/exercises/practice/beer-song/.meta/template.j2 +++ b/exercises/practice/beer-song/.meta/template.j2 @@ -18,6 +18,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} {% endfor %} - - -{{ macros.footer() }} diff --git a/exercises/practice/beer-song/beer_song_test.py b/exercises/practice/beer-song/beer_song_test.py index 4952a374c89..2aca5bae851 100644 --- a/exercises/practice/beer-song/beer_song_test.py +++ b/exercises/practice/beer-song/beer_song_test.py @@ -369,7 +369,3 @@ def test_all_verses(self): "Go to the store and buy some more, 99 bottles of beer on the wall.", ] self.assertEqual(recite(start=99, take=100), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/binary-search-tree/.meta/template.j2 b/exercises/practice/binary-search-tree/.meta/template.j2 index 518d5ceda03..e2606ddfcca 100644 --- a/exercises/practice/binary-search-tree/.meta/template.j2 +++ b/exercises/practice/binary-search-tree/.meta/template.j2 @@ -63,6 +63,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): pass else: raise AssertionError - - -{{ macros.footer() }} diff --git a/exercises/practice/binary-search-tree/binary_search_tree_test.py b/exercises/practice/binary-search-tree/binary_search_tree_test.py index 23c1fea73b4..9a4a71933d3 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree_test.py +++ b/exercises/practice/binary-search-tree/binary_search_tree_test.py @@ -82,7 +82,3 @@ def compare_tree(self, tree_one, tree_two): pass else: raise AssertionError - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/bob/.meta/template.j2 b/exercises/practice/bob/.meta/template.j2 index ce22d1849cf..07df6e8eff7 100644 --- a/exercises/practice/bob/.meta/template.j2 +++ b/exercises/practice/bob/.meta/template.j2 @@ -9,5 +9,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {%- set expected = case["expected"] %} self.assertEqual({{case["property"]}}("{{argument}}"), "{{expected}}") {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/bob/bob_test.py b/exercises/practice/bob/bob_test.py index 40081b045f1..c033d34d8ba 100644 --- a/exercises/practice/bob/bob_test.py +++ b/exercises/practice/bob/bob_test.py @@ -98,7 +98,3 @@ def test_non_question_ending_with_whitespace(self): self.assertEqual( response("This is a statement ending with whitespace "), "Whatever." ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/book-store/.meta/template.j2 b/exercises/practice/book-store/.meta/template.j2 index 6d3a79e8ff3..735ecb6487c 100644 --- a/exercises/practice/book-store/.meta/template.j2 +++ b/exercises/practice/book-store/.meta/template.j2 @@ -20,5 +20,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ test_case(case) }} {% endfor %} {%- endif %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/book-store/book_store_test.py b/exercises/practice/book-store/book_store_test.py index 50f38bc5878..06feb75acb0 100644 --- a/exercises/practice/book-store/book_store_test.py +++ b/exercises/practice/book-store/book_store_test.py @@ -95,7 +95,3 @@ def test_two_groups_of_four_and_a_group_of_five(self): def test_shuffled_book_order(self): basket = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3] self.assertEqual(total(basket), 8120) - - -if __name__ == "__main__": - unittest.main() From e076feaa4ebfa16ac1be64cd0cefc5fc9a62888c Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 09:19:02 -0700 Subject: [PATCH 101/126] Removed footer macros, regen tests, all still pass (#3431) Removed `unittest` call from test file footers. [no important files changed] --- exercises/practice/bottle-song/.meta/template.j2 | 3 --- exercises/practice/bottle-song/bottle_song_test.py | 4 ---- exercises/practice/clock/.meta/template.j2 | 1 - exercises/practice/clock/clock_test.py | 4 ---- exercises/practice/crypto-square/.meta/template.j2 | 2 -- exercises/practice/crypto-square/crypto_square_test.py | 4 ---- exercises/practice/custom-set/.meta/template.j2 | 3 +-- exercises/practice/custom-set/custom_set_test.py | 4 ---- exercises/practice/darts/.meta/template.j2 | 2 -- exercises/practice/darts/darts_test.py | 4 ---- 10 files changed, 1 insertion(+), 30 deletions(-) diff --git a/exercises/practice/bottle-song/.meta/template.j2 b/exercises/practice/bottle-song/.meta/template.j2 index 37e45402da9..7fd4a26de74 100644 --- a/exercises/practice/bottle-song/.meta/template.j2 +++ b/exercises/practice/bottle-song/.meta/template.j2 @@ -18,6 +18,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} {% endfor %} - - -{{ macros.footer() }} diff --git a/exercises/practice/bottle-song/bottle_song_test.py b/exercises/practice/bottle-song/bottle_song_test.py index 89877dc4947..3c3108f9294 100644 --- a/exercises/practice/bottle-song/bottle_song_test.py +++ b/exercises/practice/bottle-song/bottle_song_test.py @@ -130,7 +130,3 @@ def test_all_verses(self): "There'll be no green bottles hanging on the wall.", ] self.assertEqual(recite(start=10, take=10), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/clock/.meta/template.j2 b/exercises/practice/clock/.meta/template.j2 index f786b2f1c88..c8cee7e08df 100644 --- a/exercises/practice/clock/.meta/template.j2 +++ b/exercises/practice/clock/.meta/template.j2 @@ -29,4 +29,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {%- endfor %} -{{ macros.footer() }} diff --git a/exercises/practice/clock/clock_test.py b/exercises/practice/clock/clock_test.py index fe06336676b..b2c6fe9d895 100644 --- a/exercises/practice/clock/clock_test.py +++ b/exercises/practice/clock/clock_test.py @@ -177,7 +177,3 @@ def test_clocks_with_negative_hours_and_minutes_that_wrap(self): def test_full_clock_and_zeroed_clock(self): self.assertEqual(Clock(24, 0), Clock(0, 0)) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/crypto-square/.meta/template.j2 b/exercises/practice/crypto-square/.meta/template.j2 index 5568ca09132..c33812e64c3 100644 --- a/exercises/practice/crypto-square/.meta/template.j2 +++ b/exercises/practice/crypto-square/.meta/template.j2 @@ -9,5 +9,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual(cipher_text(value), expected) {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/crypto-square/crypto_square_test.py b/exercises/practice/crypto-square/crypto_square_test.py index 3715400ca3d..553728f3fea 100644 --- a/exercises/practice/crypto-square/crypto_square_test.py +++ b/exercises/practice/crypto-square/crypto_square_test.py @@ -51,7 +51,3 @@ def test_54_character_plaintext_results_in_7_chunks_the_last_two_with_trailing_s value = "If man was meant to stay on the ground, god would have given us roots." expected = "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau " self.assertEqual(cipher_text(value), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/custom-set/.meta/template.j2 b/exercises/practice/custom-set/.meta/template.j2 index 13412265944..d70a45c298f 100644 --- a/exercises/practice/custom-set/.meta/template.j2 +++ b/exercises/practice/custom-set/.meta/template.j2 @@ -44,5 +44,4 @@ class {{ class_name }}Test(unittest.TestCase): {% endif %} {% endfor %} {% endfor %} - -{{ macros.footer() }} + \ No newline at end of file diff --git a/exercises/practice/custom-set/custom_set_test.py b/exercises/practice/custom-set/custom_set_test.py index e5e3ffd3bc0..30c945ac739 100644 --- a/exercises/practice/custom-set/custom_set_test.py +++ b/exercises/practice/custom-set/custom_set_test.py @@ -212,7 +212,3 @@ def test_union_of_non_empty_sets_contains_all_unique_elements(self): set2 = CustomSet([2, 3]) expected = CustomSet([3, 2, 1]) self.assertEqual(set1 + set2, expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/darts/.meta/template.j2 b/exercises/practice/darts/.meta/template.j2 index 09c0361b2fc..35a5c37dd30 100644 --- a/exercises/practice/darts/.meta/template.j2 +++ b/exercises/practice/darts/.meta/template.j2 @@ -6,5 +6,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def test_{{ case["description"] | to_snake }}(self): self.assertEqual({{ case["property"] }}({{ case["input"]["x"] }}, {{ case["input"]["y"] }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/darts/darts_test.py b/exercises/practice/darts/darts_test.py index e830199c9c1..94a9c5ed3cc 100644 --- a/exercises/practice/darts/darts_test.py +++ b/exercises/practice/darts/darts_test.py @@ -46,7 +46,3 @@ def test_just_outside_the_outer_circle(self): def test_asymmetric_position_between_the_inner_and_middle_circles(self): self.assertEqual(score(0.5, -4), 5) - - -if __name__ == "__main__": - unittest.main() From 4ce02b7fd8aeffdda7e037a82e39742e0acd3245 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 09:28:29 -0700 Subject: [PATCH 102/126] Removed macro footer from test file template and regenerated. (#3458) Removed `unittest` main footer. [no important files changed] --- exercises/practice/rna-transcription/.meta/template.j2 | 2 -- .../practice/rna-transcription/rna_transcription_test.py | 4 ---- 2 files changed, 6 deletions(-) diff --git a/exercises/practice/rna-transcription/.meta/template.j2 b/exercises/practice/rna-transcription/.meta/template.j2 index 6be1210ad61..ebd1675187d 100644 --- a/exercises/practice/rna-transcription/.meta/template.j2 +++ b/exercises/practice/rna-transcription/.meta/template.j2 @@ -9,5 +9,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): '{{ case["expected"] }}' ) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/rna-transcription/rna_transcription_test.py b/exercises/practice/rna-transcription/rna_transcription_test.py index aa062329593..e6c88062bf1 100644 --- a/exercises/practice/rna-transcription/rna_transcription_test.py +++ b/exercises/practice/rna-transcription/rna_transcription_test.py @@ -25,7 +25,3 @@ def test_rna_complement_of_adenine_is_uracil(self): def test_rna_complement(self): self.assertEqual(to_rna("ACGTGGTCTTAA"), "UGCACCAGAAUU") - - -if __name__ == "__main__": - unittest.main() From 425e25b8fb7ac28f8b5397ca2b8f39fcf95cfab8 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 09:41:06 -0700 Subject: [PATCH 103/126] [Ledger]: Added JinJa2 Template, Re-Synced Tests & Regenerated Test Files (#3463) * Added JinJa template, tests_toml and regenerated tests. * Added names to contributors list. [no important files changed] --- exercises/practice/ledger/.meta/config.json | 2 + exercises/practice/ledger/.meta/template.j2 | 22 +++ exercises/practice/ledger/.meta/tests.toml | 43 +++++ exercises/practice/ledger/ledger.py | 1 + exercises/practice/ledger/ledger_test.py | 200 +++++++++++--------- 5 files changed, 180 insertions(+), 88 deletions(-) create mode 100644 exercises/practice/ledger/.meta/template.j2 create mode 100644 exercises/practice/ledger/.meta/tests.toml diff --git a/exercises/practice/ledger/.meta/config.json b/exercises/practice/ledger/.meta/config.json index eeb5e2ccdf1..5b9998ba1b3 100644 --- a/exercises/practice/ledger/.meta/config.json +++ b/exercises/practice/ledger/.meta/config.json @@ -3,7 +3,9 @@ "cmccandless" ], "contributors": [ + "BethanyG", "Dog", + "IsaaG", "tqa236" ], "files": { diff --git a/exercises/practice/ledger/.meta/template.j2 b/exercises/practice/ledger/.meta/template.j2 new file mode 100644 index 00000000000..8936a2ca9a2 --- /dev/null +++ b/exercises/practice/ledger/.meta/template.j2 @@ -0,0 +1,22 @@ +{%- import "generator_macros.j2" as macros with context -%} +{{ macros.header(imports=["format_entries", "create_entry"]) }} + +class {{ exercise | camel_case }}Test(unittest.TestCase): + maxDiff = 5000 + {%- for case in cases %} + + def test_{{ case["description"] | to_snake }}(self): + currency = '{{- case["input"]["currency"] }}' + locale = '{{- case["input"]["locale"] }}' + entries = [ + {%- for entry in case["input"]["entries"] %} + create_entry('{{ entry["date"] }}', '{{ entry["description"] }}', {{ entry["amountInCents"] }}), + {%- endfor %} + ] + expected = '\n'.join([ + {%- for line in case["expected"] %} + '{{- line -}}', + {%- endfor %} + ]) + self.assertEqual(format_entries(currency, locale, entries), expected) + {%- endfor %} diff --git a/exercises/practice/ledger/.meta/tests.toml b/exercises/practice/ledger/.meta/tests.toml new file mode 100644 index 00000000000..e71dfbfcafd --- /dev/null +++ b/exercises/practice/ledger/.meta/tests.toml @@ -0,0 +1,43 @@ +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[d131ecae-a30e-436c-b8f3-858039a27234] +description = "empty ledger" + +[ce4618d2-9379-4eca-b207-9df1c4ec8aaa] +description = "one entry" + +[8d02e9cb-e6ee-4b77-9ce4-e5aec8eb5ccb] +description = "credit and debit" + +[502c4106-0371-4e7c-a7d8-9ce33f16ccb1] +description = "multiple entries on same date ordered by description" + +[29dd3659-6c2d-4380-94a8-6d96086e28e1] +description = "final order tie breaker is change" + +[9b9712a6-f779-4f5c-a759-af65615fcbb9] +description = "overlong description is truncated" + +[67318aad-af53-4f3d-aa19-1293b4d4c924] +description = "euros" + +[bdc499b6-51f5-4117-95f2-43cb6737208e] +description = "Dutch locale" + +[86591cd4-1379-4208-ae54-0ee2652b4670] +description = "Dutch locale and euros" + +[876bcec8-d7d7-4ba4-82bd-b836ac87c5d2] +description = "Dutch negative number with 3 digits before decimal point" + +[29670d1c-56be-492a-9c5e-427e4b766309] +description = "American negative number with 3 digits before decimal point" diff --git a/exercises/practice/ledger/ledger.py b/exercises/practice/ledger/ledger.py index 493109b847b..c0dcf94f738 100644 --- a/exercises/practice/ledger/ledger.py +++ b/exercises/practice/ledger/ledger.py @@ -296,3 +296,4 @@ def format_entries(currency, locale, entries): change_str = ' ' + change_str table += change_str return table + diff --git a/exercises/practice/ledger/ledger_test.py b/exercises/practice/ledger/ledger_test.py index f0de049df19..c1615666ce5 100644 --- a/exercises/practice/ledger/ledger_test.py +++ b/exercises/practice/ledger/ledger_test.py @@ -1,147 +1,171 @@ -# -*- coding: utf-8 -*- import unittest -from ledger import format_entries, create_entry +from ledger import ( + format_entries, + create_entry, +) + +# Tests adapted from `problem-specifications//canonical-data.json` class LedgerTest(unittest.TestCase): maxDiff = 5000 def test_empty_ledger(self): - currency = 'USD' - locale = 'en_US' + currency = "USD" + locale = "en_US" entries = [] - expected = 'Date | Description | Change ' + expected = "\n".join( + [ + "Date | Description | Change ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_one_entry(self): - currency = 'USD' - locale = 'en_US' + currency = "USD" + locale = "en_US" entries = [ - create_entry('2015-01-01', 'Buy present', -1000), + create_entry("2015-01-01", "Buy present", -1000), ] - expected = '\n'.join([ - 'Date | Description | Change ', - '01/01/2015 | Buy present | ($10.00)', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "01/01/2015 | Buy present | ($10.00)", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_credit_and_debit(self): - currency = 'USD' - locale = 'en_US' + currency = "USD" + locale = "en_US" entries = [ - create_entry('2015-01-02', 'Get present', 1000), - create_entry('2015-01-01', 'Buy present', -1000), + create_entry("2015-01-02", "Get present", 1000), + create_entry("2015-01-01", "Buy present", -1000), ] - expected = '\n'.join([ - 'Date | Description | Change ', - '01/01/2015 | Buy present | ($10.00)', - '01/02/2015 | Get present | $10.00 ', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "01/01/2015 | Buy present | ($10.00)", + "01/02/2015 | Get present | $10.00 ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_multiple_entries_on_same_date_ordered_by_description(self): - currency = 'USD' - locale = 'en_US' + currency = "USD" + locale = "en_US" entries = [ - create_entry('2015-01-02', 'Get present', 1000), - create_entry('2015-01-01', 'Buy present', -1000), + create_entry("2015-01-02", "Get present", 1000), + create_entry("2015-01-01", "Buy present", -1000), ] - expected = '\n'.join([ - 'Date | Description | Change ', - '01/01/2015 | Buy present | ($10.00)', - '01/02/2015 | Get present | $10.00 ', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "01/01/2015 | Buy present | ($10.00)", + "01/02/2015 | Get present | $10.00 ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_final_order_tie_breaker_is_change(self): - currency = 'USD' - locale = 'en_US' + currency = "USD" + locale = "en_US" entries = [ - create_entry('2015-01-01', 'Something', 0), - create_entry('2015-01-01', 'Something', -1), - create_entry('2015-01-01', 'Something', 1), + create_entry("2015-01-01", "Something", 0), + create_entry("2015-01-01", "Something", -1), + create_entry("2015-01-01", "Something", 1), ] - expected = '\n'.join([ - 'Date | Description | Change ', - '01/01/2015 | Something | ($0.01)', - '01/01/2015 | Something | $0.00 ', - '01/01/2015 | Something | $0.01 ', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "01/01/2015 | Something | ($0.01)", + "01/01/2015 | Something | $0.00 ", + "01/01/2015 | Something | $0.01 ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) - def test_overlong_description(self): - currency = 'USD' - locale = 'en_US' + def test_overlong_description_is_truncated(self): + currency = "USD" + locale = "en_US" entries = [ - create_entry('2015-01-01', 'Freude schoner Gotterfunken', -123456), + create_entry("2015-01-01", "Freude schoner Gotterfunken", -123456), ] - expected = '\n'.join([ - 'Date | Description | Change ', - '01/01/2015 | Freude schoner Gotterf... | ($1,234.56)', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "01/01/2015 | Freude schoner Gotterf... | ($1,234.56)", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_euros(self): - currency = 'EUR' - locale = 'en_US' + currency = "EUR" + locale = "en_US" entries = [ - create_entry('2015-01-01', 'Buy present', -1000), + create_entry("2015-01-01", "Buy present", -1000), ] - expected = '\n'.join([ - 'Date | Description | Change ', - u'01/01/2015 | Buy present | (€10.00)', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "01/01/2015 | Buy present | (€10.00)", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_dutch_locale(self): - currency = 'USD' - locale = 'nl_NL' + currency = "USD" + locale = "nl_NL" entries = [ - create_entry('2015-03-12', 'Buy present', 123456), + create_entry("2015-03-12", "Buy present", 123456), ] - expected = '\n'.join([ - 'Datum | Omschrijving | Verandering ', - '12-03-2015 | Buy present | $ 1.234,56 ', - ]) + expected = "\n".join( + [ + "Datum | Omschrijving | Verandering ", + "12-03-2015 | Buy present | $ 1.234,56 ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_dutch_locale_and_euros(self): - currency = 'EUR' - locale = 'nl_NL' + currency = "EUR" + locale = "nl_NL" entries = [ - create_entry('2015-03-12', 'Buy present', 123456), + create_entry("2015-03-12", "Buy present", 123456), ] - expected = '\n'.join([ - 'Datum | Omschrijving | Verandering ', - u'12-03-2015 | Buy present | € 1.234,56 ', - ]) + expected = "\n".join( + [ + "Datum | Omschrijving | Verandering ", + "12-03-2015 | Buy present | € 1.234,56 ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_dutch_negative_number_with_3_digits_before_decimal_point(self): - currency = 'USD' - locale = 'nl_NL' + currency = "USD" + locale = "nl_NL" entries = [ - create_entry('2015-03-12', 'Buy present', -12345), + create_entry("2015-03-12", "Buy present", -12345), ] - expected = '\n'.join([ - 'Datum | Omschrijving | Verandering ', - '12-03-2015 | Buy present | $ -123,45 ', - ]) + expected = "\n".join( + [ + "Datum | Omschrijving | Verandering ", + "12-03-2015 | Buy present | $ -123,45 ", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) def test_american_negative_number_with_3_digits_before_decimal_point(self): - currency = 'USD' - locale = 'en_US' + currency = "USD" + locale = "en_US" entries = [ - create_entry('2015-03-12', 'Buy present', -12345), + create_entry("2015-03-12", "Buy present", -12345), ] - expected = '\n'.join([ - 'Date | Description | Change ', - '03/12/2015 | Buy present | ($123.45)', - ]) + expected = "\n".join( + [ + "Date | Description | Change ", + "03/12/2015 | Buy present | ($123.45)", + ] + ) self.assertEqual(format_entries(currency, locale, entries), expected) - - -if __name__ == '__main__': - unittest.main() From 1e56253ed254f4c09389654139e257f21b7ca718 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 09:57:36 -0700 Subject: [PATCH 104/126] Synced instructions for two depricated exercises. (#3459) From 7ef38f44be1f1e0127c469e722e4a9306bacfa3b Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 09:57:50 -0700 Subject: [PATCH 105/126] Synced instructions for three active exercises. (#3460) From 37feda4d82397130ed1526a82cdc7cbf5d3e4efb Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 11:29:50 -0700 Subject: [PATCH 106/126] Remove footer macros, regen tests, all pass still (#3433) [no important files changed] --- exercises/practice/acronym/.meta/template.j2 | 1 - exercises/practice/acronym/acronym_test.py | 4 ---- exercises/practice/all-your-base/.meta/template.j2 | 1 - exercises/practice/all-your-base/all_your_base_test.py | 8 -------- exercises/practice/allergies/.meta/template.j2 | 2 -- exercises/practice/allergies/allergies_test.py | 4 ---- exercises/practice/alphametics/.meta/template.j2 | 1 - exercises/practice/alphametics/alphametics_test.py | 4 ---- exercises/practice/armstrong-numbers/.meta/template.j2 | 4 +--- .../practice/armstrong-numbers/armstrong_numbers_test.py | 4 ---- 10 files changed, 1 insertion(+), 32 deletions(-) diff --git a/exercises/practice/acronym/.meta/template.j2 b/exercises/practice/acronym/.meta/template.j2 index 1373d724d31..70c5d431ca5 100644 --- a/exercises/practice/acronym/.meta/template.j2 +++ b/exercises/practice/acronym/.meta/template.j2 @@ -13,4 +13,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} {{ test_case(case) }} {% endfor %} -{{ macros.footer() }} diff --git a/exercises/practice/acronym/acronym_test.py b/exercises/practice/acronym/acronym_test.py index c5fbbfa39eb..19e4e48662f 100644 --- a/exercises/practice/acronym/acronym_test.py +++ b/exercises/practice/acronym/acronym_test.py @@ -39,7 +39,3 @@ def test_apostrophes(self): def test_underscore_emphasis(self): self.assertEqual(abbreviate("The Road _Not_ Taken"), "TRNT") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/all-your-base/.meta/template.j2 b/exercises/practice/all-your-base/.meta/template.j2 index 20684b546c3..b19efb5b8b7 100644 --- a/exercises/practice/all-your-base/.meta/template.j2 +++ b/exercises/practice/all-your-base/.meta/template.j2 @@ -29,4 +29,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ test_case(case) }} {% endfor -%} -{{ macros.footer() }} diff --git a/exercises/practice/all-your-base/all_your_base_test.py b/exercises/practice/all-your-base/all_your_base_test.py index 04cf27dbae2..0191754acb7 100644 --- a/exercises/practice/all-your-base/all_your_base_test.py +++ b/exercises/practice/all-your-base/all_your_base_test.py @@ -101,11 +101,3 @@ def test_both_bases_are_negative(self): rebase(-2, [1], -7) self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "input base must be >= 2") - - # Utility functions - def assertRaisesWithMessage(self, exception): - return self.assertRaisesRegex(exception, r".+") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/allergies/.meta/template.j2 b/exercises/practice/allergies/.meta/template.j2 index f39a9d54a4b..a15dc176392 100644 --- a/exercises/practice/allergies/.meta/template.j2 +++ b/exercises/practice/allergies/.meta/template.j2 @@ -27,5 +27,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/allergies/allergies_test.py b/exercises/practice/allergies/allergies_test.py index 5b8d32c085d..4525db8edb4 100644 --- a/exercises/practice/allergies/allergies_test.py +++ b/exercises/practice/allergies/allergies_test.py @@ -183,7 +183,3 @@ def test_no_allergen_score_parts(self): def test_no_allergen_score_parts_without_highest_valid_score(self): self.assertEqual(Allergies(257).lst, ["eggs"]) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/alphametics/.meta/template.j2 b/exercises/practice/alphametics/.meta/template.j2 index 4841b41ee5a..73291b8a1ea 100644 --- a/exercises/practice/alphametics/.meta/template.j2 +++ b/exercises/practice/alphametics/.meta/template.j2 @@ -30,4 +30,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endif %} {% endfor %} -{{ macros.footer()}} diff --git a/exercises/practice/alphametics/alphametics_test.py b/exercises/practice/alphametics/alphametics_test.py index c1f573391bc..8853e1e71c9 100644 --- a/exercises/practice/alphametics/alphametics_test.py +++ b/exercises/practice/alphametics/alphametics_test.py @@ -106,7 +106,3 @@ def test_puzzle_with_ten_letters_and_199_addends(self): "T": 9, }, ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/armstrong-numbers/.meta/template.j2 b/exercises/practice/armstrong-numbers/.meta/template.j2 index f6ac6e765ea..d9a1cceb6d2 100644 --- a/exercises/practice/armstrong-numbers/.meta/template.j2 +++ b/exercises/practice/armstrong-numbers/.meta/template.j2 @@ -9,6 +9,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ case["expected"] }} ) - {% endfor %} - -{{ macros.footer() }} \ No newline at end of file + {% endfor %} \ No newline at end of file diff --git a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py index c3f6089e9c8..6a4bd96e839 100644 --- a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py +++ b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py @@ -34,7 +34,3 @@ def test_seven_digit_number_that_is_an_armstrong_number(self): def test_seven_digit_number_that_is_not_an_armstrong_number(self): self.assertIs(is_armstrong_number(9926314), False) - - -if __name__ == "__main__": - unittest.main() From bdc5fe9986e208985e3a127a963e541e3f7a8045 Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 11:44:32 -0700 Subject: [PATCH 107/126] Remvoed footer macros, regen tests, all still pass (#3430) [no important files changed] --- exercises/practice/diamond/.meta/template.j2 | 2 -- exercises/practice/diamond/diamond_test.py | 4 ---- exercises/practice/difference-of-squares/.meta/template.j2 | 2 -- .../difference-of-squares/difference_of_squares_test.py | 4 ---- exercises/practice/dominoes/.meta/template.j2 | 3 --- exercises/practice/dominoes/dominoes_test.py | 4 ---- exercises/practice/etl/.meta/template.j2 | 3 --- exercises/practice/etl/etl_test.py | 4 ---- exercises/practice/flatten-array/.meta/template.j2 | 3 +-- exercises/practice/flatten-array/flatten_array_test.py | 4 ---- 10 files changed, 1 insertion(+), 32 deletions(-) diff --git a/exercises/practice/diamond/.meta/template.j2 b/exercises/practice/diamond/.meta/template.j2 index e9357cc7ac1..5651fa6bc92 100644 --- a/exercises/practice/diamond/.meta/template.j2 +++ b/exercises/practice/diamond/.meta/template.j2 @@ -9,5 +9,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): result = {{expected}} self.assertEqual({{case["property"]}}("{{letter}}"), result) {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/diamond/diamond_test.py b/exercises/practice/diamond/diamond_test.py index f0e60c862d4..9ed44ee198e 100644 --- a/exercises/practice/diamond/diamond_test.py +++ b/exercises/practice/diamond/diamond_test.py @@ -87,7 +87,3 @@ def test_largest_possible_diamond(self): " A ", ] self.assertEqual(rows("Z"), result) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/difference-of-squares/.meta/template.j2 b/exercises/practice/difference-of-squares/.meta/template.j2 index 62b8d8d2187..ffac71e2840 100644 --- a/exercises/practice/difference-of-squares/.meta/template.j2 +++ b/exercises/practice/difference-of-squares/.meta/template.j2 @@ -11,5 +11,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/difference-of-squares/difference_of_squares_test.py b/exercises/practice/difference-of-squares/difference_of_squares_test.py index 8c2069e4d9a..fa39f03e551 100644 --- a/exercises/practice/difference-of-squares/difference_of_squares_test.py +++ b/exercises/practice/difference-of-squares/difference_of_squares_test.py @@ -36,7 +36,3 @@ def test_difference_of_squares_5(self): def test_difference_of_squares_100(self): self.assertEqual(difference_of_squares(100), 25164150) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/dominoes/.meta/template.j2 b/exercises/practice/dominoes/.meta/template.j2 index e75094e9900..3ec60875d02 100644 --- a/exercises/practice/dominoes/.meta/template.j2 +++ b/exercises/practice/dominoes/.meta/template.j2 @@ -64,6 +64,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def refute_correct_chain(self, input_dominoes, output_chain): msg = 'There should be no valid chain for {}'.format(input_dominoes) self.assertIsNone(output_chain, msg) - -{{ macros.footer() }} - diff --git a/exercises/practice/dominoes/dominoes_test.py b/exercises/practice/dominoes/dominoes_test.py index a62f130cc20..a9b8c90dd8c 100644 --- a/exercises/practice/dominoes/dominoes_test.py +++ b/exercises/practice/dominoes/dominoes_test.py @@ -128,7 +128,3 @@ def assert_correct_chain(self, input_dominoes, output_chain): def refute_correct_chain(self, input_dominoes, output_chain): msg = "There should be no valid chain for {}".format(input_dominoes) self.assertIsNone(output_chain, msg) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/etl/.meta/template.j2 b/exercises/practice/etl/.meta/template.j2 index 8e616d8874a..5669b6ed990 100644 --- a/exercises/practice/etl/.meta/template.j2 +++ b/exercises/practice/etl/.meta/template.j2 @@ -15,6 +15,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} {{ test_case(case) }} {% endfor %} - - -{{ macros.footer() }} diff --git a/exercises/practice/etl/etl_test.py b/exercises/practice/etl/etl_test.py index 693ecb9e867..fbd57fd289f 100644 --- a/exercises/practice/etl/etl_test.py +++ b/exercises/practice/etl/etl_test.py @@ -62,7 +62,3 @@ def test_multiple_scores_with_differing_numbers_of_letters(self): "z": 10, } self.assertEqual(transform(legacy_data), data) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/flatten-array/.meta/template.j2 b/exercises/practice/flatten-array/.meta/template.j2 index d1d93ad7113..425e92fee97 100644 --- a/exercises/practice/flatten-array/.meta/template.j2 +++ b/exercises/practice/flatten-array/.meta/template.j2 @@ -9,5 +9,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] }}(inputs), expected) {% endfor %} - -{{ macros.footer() }} + \ No newline at end of file diff --git a/exercises/practice/flatten-array/flatten_array_test.py b/exercises/practice/flatten-array/flatten_array_test.py index 1552f0edb6a..3038d1a00fb 100644 --- a/exercises/practice/flatten-array/flatten_array_test.py +++ b/exercises/practice/flatten-array/flatten_array_test.py @@ -66,7 +66,3 @@ def test_all_values_in_nested_list_are_null(self): inputs = [None, [[[None]]], None, None, [[None, None], None], None] expected = [] self.assertEqual(flatten(inputs), expected) - - -if __name__ == "__main__": - unittest.main() From feb9cf1da8aa0db92cbfc1ec45b58a708be73627 Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 11:54:43 -0700 Subject: [PATCH 108/126] Removed footer macros, regen tests all still pass (#3429) [no important files changed] --- exercises/practice/food-chain/.meta/template.j2 | 2 -- exercises/practice/food-chain/food_chain_test.py | 4 ---- exercises/practice/gigasecond/.meta/template.j2 | 3 --- exercises/practice/gigasecond/gigasecond_test.py | 4 ---- exercises/practice/grep/.meta/template.j2 | 2 -- exercises/practice/grep/grep_test.py | 4 ---- exercises/practice/house/.meta/template.j2 | 2 -- exercises/practice/house/house_test.py | 4 ---- exercises/practice/isbn-verifier/.meta/template.j2 | 2 -- exercises/practice/isbn-verifier/isbn_verifier_test.py | 4 ---- 10 files changed, 31 deletions(-) diff --git a/exercises/practice/food-chain/.meta/template.j2 b/exercises/practice/food-chain/.meta/template.j2 index e1851f7a30e..619ada74c24 100644 --- a/exercises/practice/food-chain/.meta/template.j2 +++ b/exercises/practice/food-chain/.meta/template.j2 @@ -10,5 +10,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"]}}({{start_verse}}, {{end_verse}}), {{expected}}) {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/food-chain/food_chain_test.py b/exercises/practice/food-chain/food_chain_test.py index d77953527e8..f87f4cc9a2d 100644 --- a/exercises/practice/food-chain/food_chain_test.py +++ b/exercises/practice/food-chain/food_chain_test.py @@ -180,7 +180,3 @@ def test_full_song(self): "She's dead, of course!", ], ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/gigasecond/.meta/template.j2 b/exercises/practice/gigasecond/.meta/template.j2 index 31d032a46fd..87b0a148436 100644 --- a/exercises/practice/gigasecond/.meta/template.j2 +++ b/exercises/practice/gigasecond/.meta/template.j2 @@ -9,6 +9,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def test_{{ case["description"] | to_snake }}(self): self.assertEqual({{ case["property"] }}({{ input }}), {{ expected }}) {% endfor %} - - -{{ macros.footer() }} diff --git a/exercises/practice/gigasecond/gigasecond_test.py b/exercises/practice/gigasecond/gigasecond_test.py index 76ff16a64c9..e7b5f0837f1 100644 --- a/exercises/practice/gigasecond/gigasecond_test.py +++ b/exercises/practice/gigasecond/gigasecond_test.py @@ -33,7 +33,3 @@ def test_full_time_with_day_roll_over(self): self.assertEqual( add(datetime(2015, 1, 24, 23, 59, 59)), datetime(2046, 10, 3, 1, 46, 39) ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/grep/.meta/template.j2 b/exercises/practice/grep/.meta/template.j2 index 6091fd667e5..593bbc0781e 100644 --- a/exercises/practice/grep/.meta/template.j2 +++ b/exercises/practice/grep/.meta/template.j2 @@ -48,5 +48,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/grep/grep_test.py b/exercises/practice/grep/grep_test.py index 804071542d0..87c76ac829c 100644 --- a/exercises/practice/grep/grep_test.py +++ b/exercises/practice/grep/grep_test.py @@ -290,7 +290,3 @@ def test_multiple_files_several_matches_inverted_and_match_entire_lines_flags( "paradise-lost.txt:Of Oreb, or of Sinai, didst inspire\n" "paradise-lost.txt:That Shepherd, who first taught the chosen Seed\n", ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/house/.meta/template.j2 b/exercises/practice/house/.meta/template.j2 index 9683c07a993..b855685dfda 100644 --- a/exercises/practice/house/.meta/template.j2 +++ b/exercises/practice/house/.meta/template.j2 @@ -10,5 +10,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ case["expected"] }} ) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/house/house_test.py b/exercises/practice/house/house_test.py index 0facef614fe..8247675823f 100644 --- a/exercises/practice/house/house_test.py +++ b/exercises/practice/house/house_test.py @@ -126,7 +126,3 @@ def test_full_rhyme(self): "This is the horse and the hound and the horn that belonged to the farmer sowing his corn that kept the rooster that crowed in the morn that woke the priest all shaven and shorn that married the man all tattered and torn that kissed the maiden all forlorn that milked the cow with the crumpled horn that tossed the dog that worried the cat that killed the rat that ate the malt that lay in the house that Jack built.", ], ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/isbn-verifier/.meta/template.j2 b/exercises/practice/isbn-verifier/.meta/template.j2 index ce973c491d4..47392cfb29e 100644 --- a/exercises/practice/isbn-verifier/.meta/template.j2 +++ b/exercises/practice/isbn-verifier/.meta/template.j2 @@ -7,5 +7,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def test_{{ case["description"] | to_snake }}(self): self.assertIs({{ case["property"] | to_snake }}("{{ case["input"]["isbn"] }}"), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/isbn-verifier/isbn_verifier_test.py b/exercises/practice/isbn-verifier/isbn_verifier_test.py index f2f97770d7e..22fd28922f3 100644 --- a/exercises/practice/isbn-verifier/isbn_verifier_test.py +++ b/exercises/practice/isbn-verifier/isbn_verifier_test.py @@ -64,7 +64,3 @@ def test_invalid_characters_are_not_ignored_before_checking_length(self): def test_input_is_too_long_but_contains_a_valid_isbn(self): self.assertIs(is_valid("98245726788"), False) - - -if __name__ == "__main__": - unittest.main() From 0075a6e16c9199bb4b93997e8ca2fb94b5f733cb Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 12:09:03 -0700 Subject: [PATCH 109/126] Remvoed footer macros, regen tests, all still pass (#3428) [no important files changed] --- exercises/practice/pig-latin/.meta/template.j2 | 2 -- exercises/practice/pig-latin/pig_latin_test.py | 4 ---- exercises/practice/poker/.meta/template.j2 | 2 -- exercises/practice/poker/poker_test.py | 4 ---- exercises/practice/protein-translation/.meta/template.j2 | 3 +-- .../practice/protein-translation/protein_translation_test.py | 4 ---- exercises/practice/pythagorean-triplet/.meta/template.j2 | 2 -- .../practice/pythagorean-triplet/pythagorean_triplet_test.py | 4 ---- exercises/practice/rail-fence-cipher/.meta/template.j2 | 2 -- .../practice/rail-fence-cipher/rail_fence_cipher_test.py | 4 ---- 10 files changed, 1 insertion(+), 30 deletions(-) diff --git a/exercises/practice/pig-latin/.meta/template.j2 b/exercises/practice/pig-latin/.meta/template.j2 index f516f6f1a8c..fd284824ff0 100644 --- a/exercises/practice/pig-latin/.meta/template.j2 +++ b/exercises/practice/pig-latin/.meta/template.j2 @@ -11,5 +11,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/pig-latin/pig_latin_test.py b/exercises/practice/pig-latin/pig_latin_test.py index cf666ddf3ad..cf46ae3c1fe 100644 --- a/exercises/practice/pig-latin/pig_latin_test.py +++ b/exercises/practice/pig-latin/pig_latin_test.py @@ -73,7 +73,3 @@ def test_y_as_second_letter_in_two_letter_word(self): def test_a_whole_phrase(self): self.assertEqual(translate("quick fast run"), "ickquay astfay unray") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/poker/.meta/template.j2 b/exercises/practice/poker/.meta/template.j2 index 099626a1349..86e2e8791a4 100644 --- a/exercises/practice/poker/.meta/template.j2 +++ b/exercises/practice/poker/.meta/template.j2 @@ -8,5 +8,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual( {{ case["property"] | to_snake }}({{ input["hands"] }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/poker/poker_test.py b/exercises/practice/poker/poker_test.py index f436e48120b..d0b2c52dc0f 100644 --- a/exercises/practice/poker/poker_test.py +++ b/exercises/practice/poker/poker_test.py @@ -209,7 +209,3 @@ def test_even_though_an_ace_is_usually_high_a_5_high_straight_flush_is_the_lowes self.assertEqual( best_hands(["2H 3H 4H 5H 6H", "4D AD 3D 2D 5D"]), ["2H 3H 4H 5H 6H"] ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/protein-translation/.meta/template.j2 b/exercises/practice/protein-translation/.meta/template.j2 index 5cc931bcfd5..a8391c37ffb 100644 --- a/exercises/practice/protein-translation/.meta/template.j2 +++ b/exercises/practice/protein-translation/.meta/template.j2 @@ -9,5 +9,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] }}(value), expected) {% endfor %} - -{{ macros.footer() }} + \ No newline at end of file diff --git a/exercises/practice/protein-translation/protein_translation_test.py b/exercises/practice/protein-translation/protein_translation_test.py index 046c0a43e76..4ce2d1151b5 100644 --- a/exercises/practice/protein-translation/protein_translation_test.py +++ b/exercises/practice/protein-translation/protein_translation_test.py @@ -132,7 +132,3 @@ def test_translation_stops_if_stop_codon_in_middle_of_six_codon_sequence(self): value = "UGGUGUUAUUAAUGGUUU" expected = ["Tryptophan", "Cysteine", "Tyrosine"] self.assertEqual(proteins(value), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/pythagorean-triplet/.meta/template.j2 b/exercises/practice/pythagorean-triplet/.meta/template.j2 index e52cda4e230..20d750c7743 100644 --- a/exercises/practice/pythagorean-triplet/.meta/template.j2 +++ b/exercises/practice/pythagorean-triplet/.meta/template.j2 @@ -8,5 +8,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def test_{{ case["description"] | to_snake }}(self): self.assertCountEqual({{ case["property"] | to_snake }}({{ case["input"]["n"] }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py index bb094c909d8..3536908ae88 100644 --- a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py +++ b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py @@ -49,7 +49,3 @@ def test_triplets_for_large_number(self): [7500, 10000, 12500], ], ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/rail-fence-cipher/.meta/template.j2 b/exercises/practice/rail-fence-cipher/.meta/template.j2 index 2c11e606c67..2698af337cb 100644 --- a/exercises/practice/rail-fence-cipher/.meta/template.j2 +++ b/exercises/practice/rail-fence-cipher/.meta/template.j2 @@ -12,5 +12,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py index 65743180a7c..873de5839bc 100644 --- a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py +++ b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py @@ -33,7 +33,3 @@ def test_decode_with_six_rails(self): decode("133714114238148966225439541018335470986172518171757571896261", 6), "112358132134558914423337761098715972584418167651094617711286", ) - - -if __name__ == "__main__": - unittest.main() From c594bbf55b218ae8a840a1a8ceac4a2cfdd1e130 Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 12:21:22 -0700 Subject: [PATCH 110/126] Removed footer macros, regen tests, all still pass (#3427) [no important files changed] --- exercises/practice/raindrops/.meta/template.j2 | 2 -- exercises/practice/raindrops/raindrops_test.py | 4 ---- exercises/practice/rectangles/.meta/template.j2 | 3 +-- exercises/practice/rectangles/rectangles_test.py | 4 ---- exercises/practice/resistor-color/.meta/template.j2 | 2 -- exercises/practice/resistor-color/resistor_color_test.py | 4 ---- exercises/practice/rest-api/.meta/template.j2 | 2 -- exercises/practice/rest-api/rest_api_test.py | 4 ---- exercises/practice/reverse-string/.meta/template.j2 | 2 -- exercises/practice/reverse-string/reverse_string_test.py | 4 ---- 10 files changed, 1 insertion(+), 30 deletions(-) diff --git a/exercises/practice/raindrops/.meta/template.j2 b/exercises/practice/raindrops/.meta/template.j2 index d1b0d2f8612..1e025b8bf18 100644 --- a/exercises/practice/raindrops/.meta/template.j2 +++ b/exercises/practice/raindrops/.meta/template.j2 @@ -16,5 +16,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): "{{ case["expected"] }}" ) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/raindrops/raindrops_test.py b/exercises/practice/raindrops/raindrops_test.py index 247f4daa47b..7a5969c943b 100644 --- a/exercises/practice/raindrops/raindrops_test.py +++ b/exercises/practice/raindrops/raindrops_test.py @@ -63,7 +63,3 @@ def test_the_sound_for_105_is_pling_plang_plong_as_it_has_factors_3_5_and_7(self def test_the_sound_for_3125_is_plang_as_it_has_a_factor_5(self): self.assertEqual(convert(3125), "Plang") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/rectangles/.meta/template.j2 b/exercises/practice/rectangles/.meta/template.j2 index 0d82cb8421d..c9b1f623f79 100644 --- a/exercises/practice/rectangles/.meta/template.j2 +++ b/exercises/practice/rectangles/.meta/template.j2 @@ -8,5 +8,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] }}({{ input_strings }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} + \ No newline at end of file diff --git a/exercises/practice/rectangles/rectangles_test.py b/exercises/practice/rectangles/rectangles_test.py index 59c622de769..05938fc5b3f 100644 --- a/exercises/practice/rectangles/rectangles_test.py +++ b/exercises/practice/rectangles/rectangles_test.py @@ -98,7 +98,3 @@ def test_rectangles_must_have_four_sides(self): ), 5, ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/resistor-color/.meta/template.j2 b/exercises/practice/resistor-color/.meta/template.j2 index e186e3562ec..643a3b69f9c 100644 --- a/exercises/practice/resistor-color/.meta/template.j2 +++ b/exercises/practice/resistor-color/.meta/template.j2 @@ -14,5 +14,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] | to_snake }}(), expected) {%- endif -%} {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/resistor-color/resistor_color_test.py b/exercises/practice/resistor-color/resistor_color_test.py index 62ab48625fd..631bc951e67 100644 --- a/exercises/practice/resistor-color/resistor_color_test.py +++ b/exercises/practice/resistor-color/resistor_color_test.py @@ -32,7 +32,3 @@ def test_colors(self): "white", ] self.assertEqual(colors(), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/rest-api/.meta/template.j2 b/exercises/practice/rest-api/.meta/template.j2 index 9bd4e751df7..aa7afe8f4ea 100644 --- a/exercises/practice/rest-api/.meta/template.j2 +++ b/exercises/practice/rest-api/.meta/template.j2 @@ -20,5 +20,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): expected = {{ case["expected"] }} self.assertDictEqual(json.loads(response), expected) {% endfor %}{% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/rest-api/rest_api_test.py b/exercises/practice/rest-api/rest_api_test.py index 8092aec2374..4a5c525fa8a 100644 --- a/exercises/practice/rest-api/rest_api_test.py +++ b/exercises/practice/rest-api/rest_api_test.py @@ -159,7 +159,3 @@ def test_lender_owes_borrower_same_as_new_loan(self): ] } self.assertDictEqual(json.loads(response), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/reverse-string/.meta/template.j2 b/exercises/practice/reverse-string/.meta/template.j2 index f7e1e41f3a2..f76cc28e4d5 100644 --- a/exercises/practice/reverse-string/.meta/template.j2 +++ b/exercises/practice/reverse-string/.meta/template.j2 @@ -11,5 +11,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): "{{- case ["expected"] }}" ) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/reverse-string/reverse_string_test.py b/exercises/practice/reverse-string/reverse_string_test.py index 78212b41def..a1a28dc1e6b 100644 --- a/exercises/practice/reverse-string/reverse_string_test.py +++ b/exercises/practice/reverse-string/reverse_string_test.py @@ -25,7 +25,3 @@ def test_a_palindrome(self): def test_an_even_sized_word(self): self.assertEqual(reverse("drawer"), "reward") - - -if __name__ == "__main__": - unittest.main() From 2a0a4f63425c543dcdbca8d64502bb6c5996e101 Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 12:35:55 -0700 Subject: [PATCH 111/126] Removed footer macros, regen tests, all still pass (#3426) [no important files changed] --- exercises/practice/sieve/.meta/template.j2 | 2 -- exercises/practice/sieve/sieve_test.py | 4 ---- exercises/practice/simple-cipher/.meta/template.j2 | 2 -- exercises/practice/simple-cipher/simple_cipher_test.py | 4 ---- exercises/practice/space-age/.meta/template.j2 | 3 +-- exercises/practice/space-age/space_age_test.py | 4 ---- exercises/practice/spiral-matrix/.meta/template.j2 | 2 -- exercises/practice/spiral-matrix/spiral_matrix_test.py | 4 ---- exercises/practice/sum-of-multiples/.meta/template.j2 | 2 -- exercises/practice/sum-of-multiples/sum_of_multiples_test.py | 4 ---- exercises/practice/triangle/.meta/template.j2 | 1 - exercises/practice/triangle/triangle_test.py | 4 ---- 12 files changed, 1 insertion(+), 35 deletions(-) diff --git a/exercises/practice/sieve/.meta/template.j2 b/exercises/practice/sieve/.meta/template.j2 index e26e4e4c1ce..68a9db82a60 100644 --- a/exercises/practice/sieve/.meta/template.j2 +++ b/exercises/practice/sieve/.meta/template.j2 @@ -7,5 +7,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] }}({{ case["input"]["limit"] }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/sieve/sieve_test.py b/exercises/practice/sieve/sieve_test.py index d9fa67262b3..91bb00e7ae6 100644 --- a/exercises/practice/sieve/sieve_test.py +++ b/exercises/practice/sieve/sieve_test.py @@ -194,7 +194,3 @@ def test_find_primes_up_to_1000(self): 997, ], ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/simple-cipher/.meta/template.j2 b/exercises/practice/simple-cipher/.meta/template.j2 index ca20aa30114..ce9ad3e4468 100644 --- a/exercises/practice/simple-cipher/.meta/template.j2 +++ b/exercises/practice/simple-cipher/.meta/template.j2 @@ -59,5 +59,3 @@ class {{ cases["description"] | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/simple-cipher/simple_cipher_test.py b/exercises/practice/simple-cipher/simple_cipher_test.py index 07c0c3d5b5d..8b911d734bb 100644 --- a/exercises/practice/simple-cipher/simple_cipher_test.py +++ b/exercises/practice/simple-cipher/simple_cipher_test.py @@ -64,7 +64,3 @@ def test_can_encode_messages_longer_than_the_key(self): def test_can_decode_messages_longer_than_the_key(self): cipher = Cipher("abc") self.assertEqual(cipher.decode("iboaqcnecbfcr"), "iamapandabear") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/space-age/.meta/template.j2 b/exercises/practice/space-age/.meta/template.j2 index a7822ad6495..15c8c550325 100644 --- a/exercises/practice/space-age/.meta/template.j2 +++ b/exercises/practice/space-age/.meta/template.j2 @@ -9,5 +9,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual(SpaceAge({{ seconds }}).on_{{ planet | lower }}(), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} + \ No newline at end of file diff --git a/exercises/practice/space-age/space_age_test.py b/exercises/practice/space-age/space_age_test.py index b3f91ca0673..1d248b19e33 100644 --- a/exercises/practice/space-age/space_age_test.py +++ b/exercises/practice/space-age/space_age_test.py @@ -31,7 +31,3 @@ def test_age_on_uranus(self): def test_age_on_neptune(self): self.assertEqual(SpaceAge(1821023456).on_neptune(), 0.35) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/spiral-matrix/.meta/template.j2 b/exercises/practice/spiral-matrix/.meta/template.j2 index b501e6d4147..2a73e6bccb2 100644 --- a/exercises/practice/spiral-matrix/.meta/template.j2 +++ b/exercises/practice/spiral-matrix/.meta/template.j2 @@ -7,5 +7,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] | to_snake }}({{ case["input"]["size"] }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/spiral-matrix/spiral_matrix_test.py b/exercises/practice/spiral-matrix/spiral_matrix_test.py index 1291342a892..3e6658cf547 100644 --- a/exercises/practice/spiral-matrix/spiral_matrix_test.py +++ b/exercises/practice/spiral-matrix/spiral_matrix_test.py @@ -37,7 +37,3 @@ def test_spiral_of_size_5(self): [13, 12, 11, 10, 9], ], ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/sum-of-multiples/.meta/template.j2 b/exercises/practice/sum-of-multiples/.meta/template.j2 index 6ffa327ac1a..39dab6ada1b 100644 --- a/exercises/practice/sum-of-multiples/.meta/template.j2 +++ b/exercises/practice/sum-of-multiples/.meta/template.j2 @@ -7,5 +7,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"].replace("sum", "sum_of_multiples") }}({{ case["input"]["limit"] }}, {{ case["input"]["factors"] }}), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py index f7e8bfb5409..29d0ac7244e 100644 --- a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py +++ b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py @@ -57,7 +57,3 @@ def test_solutions_using_include_exclude_must_extend_to_cardinality_greater_than self, ): self.assertEqual(sum_of_multiples(10000, [2, 3, 5, 7, 11]), 39614537) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/triangle/.meta/template.j2 b/exercises/practice/triangle/.meta/template.j2 index 8875bc51078..6d79c8c398c 100644 --- a/exercises/practice/triangle/.meta/template.j2 +++ b/exercises/practice/triangle/.meta/template.j2 @@ -9,4 +9,3 @@ class {{ case["description"] | camel_case }}Test(unittest.TestCase): {% endfor %} {% endfor %} -{{ macros.footer() }} diff --git a/exercises/practice/triangle/triangle_test.py b/exercises/practice/triangle/triangle_test.py index 2de48d3372e..f67d63fa69c 100644 --- a/exercises/practice/triangle/triangle_test.py +++ b/exercises/practice/triangle/triangle_test.py @@ -76,7 +76,3 @@ def test_may_not_violate_triangle_inequality(self): def test_sides_may_be_floats(self): self.assertIs(scalene([0.5, 0.4, 0.6]), True) - - -if __name__ == "__main__": - unittest.main() From 61bda9ef83f8e12b4e1959d8ba773e37465f9e5a Mon Sep 17 00:00:00 2001 From: Angeleah Date: Fri, 14 Jul 2023 13:17:32 -0700 Subject: [PATCH 112/126] Remove footer macros, regen tests, all still pass (#3425) * Remove footer macros, regen tests, all still pass * Regenerated tests for Scale-generator [no important files changed] --------- Co-authored-by: BethanyG --- exercises/practice/rotational-cipher/.meta/template.j2 | 2 -- .../practice/rotational-cipher/rotational_cipher_test.py | 4 ---- exercises/practice/scale-generator/.meta/template.j2 | 3 --- exercises/practice/scale-generator/scale_generator_test.py | 4 ---- exercises/practice/scrabble-score/.meta/template.j2 | 4 +--- exercises/practice/scrabble-score/scrabble_score_test.py | 4 ---- exercises/practice/secret-handshake/.meta/template.j2 | 2 -- exercises/practice/secret-handshake/secret_handshake_test.py | 4 ---- 8 files changed, 1 insertion(+), 26 deletions(-) diff --git a/exercises/practice/rotational-cipher/.meta/template.j2 b/exercises/practice/rotational-cipher/.meta/template.j2 index 5a84641528c..7db7871ea6d 100644 --- a/exercises/practice/rotational-cipher/.meta/template.j2 +++ b/exercises/practice/rotational-cipher/.meta/template.j2 @@ -10,5 +10,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): self.assertEqual({{ case["property"] }}("{{ text }}", {{ shiftKey }}), "{{ expected }}") {% endfor %} - -{{ macros.footer() }} \ No newline at end of file diff --git a/exercises/practice/rotational-cipher/rotational_cipher_test.py b/exercises/practice/rotational-cipher/rotational_cipher_test.py index 88b64d6edb4..b6e760a4ed3 100644 --- a/exercises/practice/rotational-cipher/rotational_cipher_test.py +++ b/exercises/practice/rotational-cipher/rotational_cipher_test.py @@ -40,7 +40,3 @@ def test_rotate_all_letters(self): rotate("The quick brown fox jumps over the lazy dog.", 13), "Gur dhvpx oebja sbk whzcf bire gur ynml qbt.", ) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/scale-generator/.meta/template.j2 b/exercises/practice/scale-generator/.meta/template.j2 index b65b5f09789..da566b8abe2 100644 --- a/exercises/practice/scale-generator/.meta/template.j2 +++ b/exercises/practice/scale-generator/.meta/template.j2 @@ -25,6 +25,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases %} {{ test_supercase(supercase) }} {% endfor %} - - -{{ macros.footer() }} diff --git a/exercises/practice/scale-generator/scale_generator_test.py b/exercises/practice/scale-generator/scale_generator_test.py index 7edc118c778..5757fad3168 100644 --- a/exercises/practice/scale-generator/scale_generator_test.py +++ b/exercises/practice/scale-generator/scale_generator_test.py @@ -78,7 +78,3 @@ def test_pentatonic(self): def test_enigmatic(self): expected = ["G", "G#", "B", "C#", "D#", "F", "F#", "G"] self.assertEqual(Scale("G").interval("mAMMMmm"), expected) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/scrabble-score/.meta/template.j2 b/exercises/practice/scrabble-score/.meta/template.j2 index f122b916b32..ea6c9ae2248 100644 --- a/exercises/practice/scrabble-score/.meta/template.j2 +++ b/exercises/practice/scrabble-score/.meta/template.j2 @@ -13,6 +13,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} {{ test_case(case) }} {% endfor %} - - -{{ macros.footer() }} + \ No newline at end of file diff --git a/exercises/practice/scrabble-score/scrabble_score_test.py b/exercises/practice/scrabble-score/scrabble_score_test.py index e8d7eff75ea..2ea8fd32405 100644 --- a/exercises/practice/scrabble-score/scrabble_score_test.py +++ b/exercises/practice/scrabble-score/scrabble_score_test.py @@ -40,7 +40,3 @@ def test_empty_input(self): def test_entire_alphabet_available(self): self.assertEqual(score("abcdefghijklmnopqrstuvwxyz"), 87) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/secret-handshake/.meta/template.j2 b/exercises/practice/secret-handshake/.meta/template.j2 index 459e9c9875e..f5791a8bd8a 100644 --- a/exercises/practice/secret-handshake/.meta/template.j2 +++ b/exercises/practice/secret-handshake/.meta/template.j2 @@ -6,5 +6,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): def test_{{ case["description"] | to_snake }}(self): self.assertEqual({{ case["property"] }}("{{ plugins.to_binary(case["input"]["number"]) }}"), {{ case["expected"] }}) {% endfor %} - -{{ macros.footer() }} diff --git a/exercises/practice/secret-handshake/secret_handshake_test.py b/exercises/practice/secret-handshake/secret_handshake_test.py index 959c866981a..b9e534d5fa3 100644 --- a/exercises/practice/secret-handshake/secret_handshake_test.py +++ b/exercises/practice/secret-handshake/secret_handshake_test.py @@ -44,7 +44,3 @@ def test_reverse_all_possible_actions(self): def test_do_nothing_for_zero(self): self.assertEqual(commands("00000"), []) - - -if __name__ == "__main__": - unittest.main() From c468f7c9fbac07d35cce16f328875c10de0ebb10 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 13:42:59 -0700 Subject: [PATCH 113/126] Final instruction updates of pig-latin, secret-handshake, and list-ops. (#3465) [no important files changed] --- exercises/practice/list-ops/.docs/instructions.md | 8 +++++--- exercises/practice/pig-latin/.docs/instructions.md | 3 ++- exercises/practice/secret-handshake/.meta/config.json | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/exercises/practice/list-ops/.docs/instructions.md b/exercises/practice/list-ops/.docs/instructions.md index d34533387ae..ccfc2f8b2ac 100644 --- a/exercises/practice/list-ops/.docs/instructions.md +++ b/exercises/practice/list-ops/.docs/instructions.md @@ -12,6 +12,8 @@ The precise number and names of the operations to be implemented will be track d - `filter` (*given a predicate and a list, return the list of all items for which `predicate(item)` is True*); - `length` (*given a list, return the total number of items within it*); - `map` (*given a function and a list, return the list of the results of applying `function(item)` on all items*); -- `foldl` (*given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left using `function(accumulator, item)`*); -- `foldr` (*given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right using `function(item, accumulator)`*); -- `reverse` (*given a list, return a list with all the original items, but in reversed order*); +- `foldl` (*given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left*); +- `foldr` (*given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right*); +- `reverse` (*given a list, return a list with all the original items, but in reversed order*). + +Note, the ordering in which arguments are passed to the fold functions (`foldl`, `foldr`) is significant. diff --git a/exercises/practice/pig-latin/.docs/instructions.md b/exercises/practice/pig-latin/.docs/instructions.md index c9de5ca1865..032905aa9b0 100644 --- a/exercises/practice/pig-latin/.docs/instructions.md +++ b/exercises/practice/pig-latin/.docs/instructions.md @@ -8,11 +8,12 @@ It obeys a few simple rules (below), but when it's spoken quickly it's really di - **Rule 1**: If a word begins with a vowel sound, add an "ay" sound to the end of the word. Please note that "xr" and "yt" at the beginning of a word make vowel sounds (e.g. "xray" -> "xrayay", "yttria" -> "yttriaay"). - **Rule 2**: If a word begins with a consonant sound, move it to the end of the word and then add an "ay" sound to the end of the word. - Consonant sounds can be made up of multiple consonants, a.k.a. a consonant cluster (e.g. "chair" -> "airchay"). + Consonant sounds can be made up of multiple consonants, such as the "ch" in "chair" or "st" in "stand" (e.g. "chair" -> "airchay"). - **Rule 3**: If a word starts with a consonant sound followed by "qu", move it to the end of the word, and then add an "ay" sound to the end of the word (e.g. "square" -> "aresquay"). - **Rule 4**: If a word contains a "y" after a consonant cluster or as the second letter in a two letter word it makes a vowel sound (e.g. "rhythm" -> "ythmrhay", "my" -> "ymay"). There are a few more rules for edge cases, and there are regional variants too. +Check the tests for all the details. Read more about [Pig Latin on Wikipedia][pig-latin]. diff --git a/exercises/practice/secret-handshake/.meta/config.json b/exercises/practice/secret-handshake/.meta/config.json index cca237b478e..7972aa1f5a0 100644 --- a/exercises/practice/secret-handshake/.meta/config.json +++ b/exercises/practice/secret-handshake/.meta/config.json @@ -31,5 +31,5 @@ }, "blurb": "Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.", "source": "Bert, in Mary Poppins", - "source_url": "https://www.imdb.com/title/tt0058331/quotes/qt0437047" + "source_url": "https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047" } From e7a6b0dc7dea6510a6fbaffb9aa035ef3bb1b543 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 14 Jul 2023 15:52:15 -0700 Subject: [PATCH 114/126] [JinJa2] Corrected the macro used for comments on the test file. (#3373) * Corrected the macro for comments on the test file. * Added current_date (utcnow()) variable available for template macros. * Removed unnecessary datetime import from macros file. * Regenerated all practice exercise test files to add timestamp. * Changed `datetime.now(tz=timezone.utc)` to `datetime.now(tz=timezone.utc).date()` * Second regeneration to remove `timestamp` and just keep `date` for test files. [no important files changed] --- bin/generate_tests.py | 6 ++++-- config/generator_macros.j2 | 4 +++- exercises/practice/acronym/acronym_test.py | 4 +++- exercises/practice/affine-cipher/affine_cipher_test.py | 4 +++- exercises/practice/all-your-base/all_your_base_test.py | 4 +++- exercises/practice/allergies/allergies_test.py | 4 +++- exercises/practice/alphametics/alphametics_test.py | 4 +++- exercises/practice/anagram/anagram_test.py | 4 +++- .../practice/armstrong-numbers/armstrong_numbers_test.py | 4 +++- exercises/practice/atbash-cipher/atbash_cipher_test.py | 4 +++- exercises/practice/bank-account/bank_account_test.py | 4 +++- exercises/practice/beer-song/beer_song_test.py | 4 +++- .../practice/binary-search-tree/binary_search_tree_test.py | 4 +++- exercises/practice/binary-search/binary_search_test.py | 4 +++- exercises/practice/bob/bob_test.py | 4 +++- exercises/practice/book-store/book_store_test.py | 4 +++- exercises/practice/bottle-song/bottle_song_test.py | 4 +++- exercises/practice/bowling/bowling_test.py | 4 +++- exercises/practice/change/change_test.py | 4 +++- exercises/practice/circular-buffer/circular_buffer_test.py | 4 +++- exercises/practice/clock/clock_test.py | 4 +++- .../practice/collatz-conjecture/collatz_conjecture_test.py | 4 +++- exercises/practice/complex-numbers/complex_numbers_test.py | 4 +++- exercises/practice/connect/connect_test.py | 4 +++- exercises/practice/crypto-square/crypto_square_test.py | 4 +++- exercises/practice/custom-set/custom_set_test.py | 4 +++- exercises/practice/darts/darts_test.py | 4 +++- exercises/practice/diamond/diamond_test.py | 4 +++- .../difference-of-squares/difference_of_squares_test.py | 4 +++- exercises/practice/diffie-hellman/diffie_hellman_test.py | 4 +++- exercises/practice/dnd-character/dnd_character_test.py | 4 +++- exercises/practice/dominoes/dominoes_test.py | 4 +++- exercises/practice/etl/etl_test.py | 4 +++- exercises/practice/flatten-array/flatten_array_test.py | 4 +++- exercises/practice/food-chain/food_chain_test.py | 4 +++- exercises/practice/forth/forth_test.py | 4 +++- exercises/practice/gigasecond/gigasecond_test.py | 4 +++- exercises/practice/go-counting/go_counting_test.py | 4 +++- exercises/practice/grade-school/grade_school_test.py | 4 +++- exercises/practice/grains/grains_test.py | 4 +++- exercises/practice/grep/grep_test.py | 4 +++- exercises/practice/hamming/hamming_test.py | 4 +++- exercises/practice/high-scores/high_scores_test.py | 4 +++- exercises/practice/house/house_test.py | 4 +++- exercises/practice/isbn-verifier/isbn_verifier_test.py | 4 +++- exercises/practice/isogram/isogram_test.py | 4 +++- .../killer-sudoku-helper/killer_sudoku_helper_test.py | 4 +++- .../kindergarten-garden/kindergarten_garden_test.py | 4 +++- exercises/practice/knapsack/knapsack_test.py | 4 +++- .../largest-series-product/largest_series_product_test.py | 4 +++- exercises/practice/leap/leap_test.py | 4 +++- exercises/practice/ledger/ledger_test.py | 4 +++- exercises/practice/linked-list/linked_list_test.py | 4 +++- exercises/practice/list-ops/list_ops_test.py | 4 +++- exercises/practice/luhn/luhn_test.py | 4 +++- exercises/practice/markdown/markdown_test.py | 4 +++- .../practice/matching-brackets/matching_brackets_test.py | 4 +++- exercises/practice/matrix/matrix_test.py | 4 +++- exercises/practice/meetup/meetup_test.py | 4 +++- exercises/practice/minesweeper/minesweeper_test.py | 4 +++- exercises/practice/nth-prime/nth_prime_test.py | 4 +++- exercises/practice/ocr-numbers/ocr_numbers_test.py | 4 +++- .../palindrome-products/palindrome_products_test.py | 4 +++- exercises/practice/pangram/pangram_test.py | 4 +++- .../practice/pascals-triangle/pascals_triangle_test.py | 4 +++- exercises/practice/perfect-numbers/perfect_numbers_test.py | 4 +++- exercises/practice/phone-number/phone_number_test.py | 4 +++- exercises/practice/pig-latin/pig_latin_test.py | 4 +++- exercises/practice/poker/poker_test.py | 4 +++- exercises/practice/pov/pov_test.py | 4 +++- exercises/practice/prime-factors/prime_factors_test.py | 4 +++- .../protein-translation/protein_translation_test.py | 4 +++- exercises/practice/proverb/proverb_test.py | 4 +++- .../pythagorean-triplet/pythagorean_triplet_test.py | 4 +++- exercises/practice/queen-attack/queen_attack_test.py | 4 +++- .../practice/rail-fence-cipher/rail_fence_cipher_test.py | 4 +++- exercises/practice/raindrops/raindrops_test.py | 4 +++- .../practice/rational-numbers/rational_numbers_test.py | 4 +++- exercises/practice/react/react_test.py | 4 +++- exercises/practice/rectangles/rectangles_test.py | 4 +++- .../practice/resistor-color-duo/resistor_color_duo_test.py | 4 +++- .../resistor-color-trio/resistor_color_trio_test.py | 4 +++- exercises/practice/resistor-color/resistor_color_test.py | 4 +++- exercises/practice/rest-api/rest_api_test.py | 4 +++- exercises/practice/reverse-string/reverse_string_test.py | 4 +++- .../practice/rna-transcription/rna_transcription_test.py | 4 +++- exercises/practice/robot-simulator/robot_simulator_test.py | 4 +++- exercises/practice/roman-numerals/roman_numerals_test.py | 4 +++- .../practice/rotational-cipher/rotational_cipher_test.py | 4 +++- .../run-length-encoding/run_length_encoding_test.py | 4 +++- exercises/practice/saddle-points/saddle_points_test.py | 4 +++- exercises/practice/satellite/satellite_test.py | 4 +++- exercises/practice/say/say_test.py | 4 +++- exercises/practice/scale-generator/scale_generator_test.py | 4 +++- exercises/practice/scrabble-score/scrabble_score_test.py | 4 +++- .../practice/secret-handshake/secret_handshake_test.py | 4 +++- exercises/practice/series/series_test.py | 4 +++- exercises/practice/sgf-parsing/sgf_parsing_test.py | 4 +++- exercises/practice/sieve/sieve_test.py | 4 +++- exercises/practice/simple-cipher/simple_cipher_test.py | 4 +++- exercises/practice/space-age/space_age_test.py | 4 +++- exercises/practice/spiral-matrix/spiral_matrix_test.py | 4 +++- exercises/practice/square-root/square_root_test.py | 4 +++- exercises/practice/sublist/sublist_test.py | 4 +++- .../practice/sum-of-multiples/sum_of_multiples_test.py | 4 +++- exercises/practice/tournament/tournament_test.py | 4 +++- exercises/practice/transpose/transpose_test.py | 4 +++- exercises/practice/triangle/triangle_test.py | 4 +++- exercises/practice/twelve-days/twelve_days_test.py | 4 +++- exercises/practice/two-bucket/two_bucket_test.py | 4 +++- exercises/practice/two-fer/two_fer_test.py | 4 +++- .../variable_length_quantity_test.py | 4 +++- exercises/practice/word-count/word_count_test.py | 4 +++- exercises/practice/word-search/word_search_test.py | 4 +++- exercises/practice/wordy/wordy_test.py | 4 +++- exercises/practice/yacht/yacht_test.py | 4 +++- exercises/practice/zebra-puzzle/zebra_puzzle_test.py | 4 +++- exercises/practice/zipper/zipper_test.py | 4 +++- 118 files changed, 355 insertions(+), 119 deletions(-) diff --git a/bin/generate_tests.py b/bin/generate_tests.py index 8dc74936b14..d5fc4c5c5ec 100755 --- a/bin/generate_tests.py +++ b/bin/generate_tests.py @@ -17,12 +17,13 @@ from githelp import Repo _py = sys.version_info -if _py.major < 3 or (_py.major == 3 and _py.minor < 6): - print("Python version must be at least 3.6") +if _py.major < 3 or (_py.major == 3 and _py.minor < 7): + print("Python version must be at least 3.7") sys.exit(1) import argparse from datetime import datetime +from datetime import timezone import difflib import filecmp import importlib.util @@ -393,6 +394,7 @@ def generate( env.filters["zip"] = zip env.filters["parse_datetime"] = parse_datetime env.filters["escape_invalid_escapes"] = escape_invalid_escapes + env.globals["current_date"] = datetime.now(tz=timezone.utc).date() env.tests["error_case"] = error_case result = True for exercise in sorted(Path("exercises/practice").glob(exercise_glob)): diff --git a/config/generator_macros.j2 b/config/generator_macros.j2 index 76a8c07230e..32af5d5c9fe 100644 --- a/config/generator_macros.j2 +++ b/config/generator_macros.j2 @@ -10,7 +10,9 @@ {% endmacro -%} {% macro canonical_ref() -%} -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/{{ exercise }}/canonical-data.json +# File last updated on {{ current_date }} {%- endmacro %} {% macro header(imports=[], ignore=[]) -%} diff --git a/exercises/practice/acronym/acronym_test.py b/exercises/practice/acronym/acronym_test.py index 19e4e48662f..444f60cb553 100644 --- a/exercises/practice/acronym/acronym_test.py +++ b/exercises/practice/acronym/acronym_test.py @@ -4,7 +4,9 @@ abbreviate, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/acronym/canonical-data.json +# File last updated on 2023-07-14 class AcronymTest(unittest.TestCase): diff --git a/exercises/practice/affine-cipher/affine_cipher_test.py b/exercises/practice/affine-cipher/affine_cipher_test.py index fb9cd4a1081..713e3910232 100644 --- a/exercises/practice/affine-cipher/affine_cipher_test.py +++ b/exercises/practice/affine-cipher/affine_cipher_test.py @@ -5,7 +5,9 @@ encode, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/affine-cipher/canonical-data.json +# File last updated on 2023-07-14 class AffineCipherTest(unittest.TestCase): diff --git a/exercises/practice/all-your-base/all_your_base_test.py b/exercises/practice/all-your-base/all_your_base_test.py index 0191754acb7..182237e4e1f 100644 --- a/exercises/practice/all-your-base/all_your_base_test.py +++ b/exercises/practice/all-your-base/all_your_base_test.py @@ -4,7 +4,9 @@ rebase, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/all-your-base/canonical-data.json +# File last updated on 2023-07-14 class AllYourBaseTest(unittest.TestCase): diff --git a/exercises/practice/allergies/allergies_test.py b/exercises/practice/allergies/allergies_test.py index 4525db8edb4..fa4e1c55eef 100644 --- a/exercises/practice/allergies/allergies_test.py +++ b/exercises/practice/allergies/allergies_test.py @@ -4,7 +4,9 @@ Allergies, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/allergies/canonical-data.json +# File last updated on 2023-07-14 class AllergiesTest(unittest.TestCase): diff --git a/exercises/practice/alphametics/alphametics_test.py b/exercises/practice/alphametics/alphametics_test.py index 8853e1e71c9..5557b3c8eb5 100644 --- a/exercises/practice/alphametics/alphametics_test.py +++ b/exercises/practice/alphametics/alphametics_test.py @@ -4,7 +4,9 @@ solve, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/alphametics/canonical-data.json +# File last updated on 2023-07-14 class AlphameticsTest(unittest.TestCase): diff --git a/exercises/practice/anagram/anagram_test.py b/exercises/practice/anagram/anagram_test.py index f06ad9fb53b..85087e85809 100644 --- a/exercises/practice/anagram/anagram_test.py +++ b/exercises/practice/anagram/anagram_test.py @@ -4,7 +4,9 @@ find_anagrams, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/anagram/canonical-data.json +# File last updated on 2023-07-14 class AnagramTest(unittest.TestCase): diff --git a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py index 6a4bd96e839..ed6907d884d 100644 --- a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py +++ b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py @@ -4,7 +4,9 @@ is_armstrong_number, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json +# File last updated on 2023-07-14 class ArmstrongNumbersTest(unittest.TestCase): diff --git a/exercises/practice/atbash-cipher/atbash_cipher_test.py b/exercises/practice/atbash-cipher/atbash_cipher_test.py index fcc1a25e68f..4e630e3a127 100644 --- a/exercises/practice/atbash-cipher/atbash_cipher_test.py +++ b/exercises/practice/atbash-cipher/atbash_cipher_test.py @@ -5,7 +5,9 @@ encode, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/atbash-cipher/canonical-data.json +# File last updated on 2023-07-14 class AtbashCipherTest(unittest.TestCase): diff --git a/exercises/practice/bank-account/bank_account_test.py b/exercises/practice/bank-account/bank_account_test.py index 76ddbfe404a..9e974da8fae 100644 --- a/exercises/practice/bank-account/bank_account_test.py +++ b/exercises/practice/bank-account/bank_account_test.py @@ -4,7 +4,9 @@ BankAccount, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bank-account/canonical-data.json +# File last updated on 2023-07-14 class BankAccountTest(unittest.TestCase): diff --git a/exercises/practice/beer-song/beer_song_test.py b/exercises/practice/beer-song/beer_song_test.py index 2aca5bae851..b11f11d1f5d 100644 --- a/exercises/practice/beer-song/beer_song_test.py +++ b/exercises/practice/beer-song/beer_song_test.py @@ -4,7 +4,9 @@ recite, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/beer-song/canonical-data.json +# File last updated on 2023-07-14 class BeerSongTest(unittest.TestCase): diff --git a/exercises/practice/binary-search-tree/binary_search_tree_test.py b/exercises/practice/binary-search-tree/binary_search_tree_test.py index 9a4a71933d3..479cd3411f3 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree_test.py +++ b/exercises/practice/binary-search-tree/binary_search_tree_test.py @@ -5,7 +5,9 @@ TreeNode, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search-tree/canonical-data.json +# File last updated on 2023-07-14 class BinarySearchTreeTest(unittest.TestCase): diff --git a/exercises/practice/binary-search/binary_search_test.py b/exercises/practice/binary-search/binary_search_test.py index 9f883d17678..325622ad37a 100644 --- a/exercises/practice/binary-search/binary_search_test.py +++ b/exercises/practice/binary-search/binary_search_test.py @@ -4,7 +4,9 @@ find, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search/canonical-data.json +# File last updated on 2023-07-14 class BinarySearchTest(unittest.TestCase): diff --git a/exercises/practice/bob/bob_test.py b/exercises/practice/bob/bob_test.py index c033d34d8ba..67c7f64f7d6 100644 --- a/exercises/practice/bob/bob_test.py +++ b/exercises/practice/bob/bob_test.py @@ -4,7 +4,9 @@ response, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json +# File last updated on 2023-07-14 class BobTest(unittest.TestCase): diff --git a/exercises/practice/book-store/book_store_test.py b/exercises/practice/book-store/book_store_test.py index 06feb75acb0..329e5410f2d 100644 --- a/exercises/practice/book-store/book_store_test.py +++ b/exercises/practice/book-store/book_store_test.py @@ -4,7 +4,9 @@ total, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/book-store/canonical-data.json +# File last updated on 2023-07-14 class BookStoreTest(unittest.TestCase): diff --git a/exercises/practice/bottle-song/bottle_song_test.py b/exercises/practice/bottle-song/bottle_song_test.py index 3c3108f9294..f8c33aac2b7 100644 --- a/exercises/practice/bottle-song/bottle_song_test.py +++ b/exercises/practice/bottle-song/bottle_song_test.py @@ -4,7 +4,9 @@ recite, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bottle-song/canonical-data.json +# File last updated on 2023-07-14 class BottleSongTest(unittest.TestCase): diff --git a/exercises/practice/bowling/bowling_test.py b/exercises/practice/bowling/bowling_test.py index 89d0a45f0bc..8e04a4c8143 100644 --- a/exercises/practice/bowling/bowling_test.py +++ b/exercises/practice/bowling/bowling_test.py @@ -4,7 +4,9 @@ BowlingGame, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bowling/canonical-data.json +# File last updated on 2023-07-14 class BowlingTest(unittest.TestCase): diff --git a/exercises/practice/change/change_test.py b/exercises/practice/change/change_test.py index 6b335174ef3..74fead1196b 100644 --- a/exercises/practice/change/change_test.py +++ b/exercises/practice/change/change_test.py @@ -4,7 +4,9 @@ find_fewest_coins, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/change/canonical-data.json +# File last updated on 2023-07-14 class ChangeTest(unittest.TestCase): diff --git a/exercises/practice/circular-buffer/circular_buffer_test.py b/exercises/practice/circular-buffer/circular_buffer_test.py index 403ee1b5ff6..411df16bbd4 100644 --- a/exercises/practice/circular-buffer/circular_buffer_test.py +++ b/exercises/practice/circular-buffer/circular_buffer_test.py @@ -6,7 +6,9 @@ BufferFullException, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/circular-buffer/canonical-data.json +# File last updated on 2023-07-14 class CircularBufferTest(unittest.TestCase): diff --git a/exercises/practice/clock/clock_test.py b/exercises/practice/clock/clock_test.py index b2c6fe9d895..4fb17b4b1e7 100644 --- a/exercises/practice/clock/clock_test.py +++ b/exercises/practice/clock/clock_test.py @@ -4,7 +4,9 @@ Clock, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/clock/canonical-data.json +# File last updated on 2023-07-14 class ClockTest(unittest.TestCase): diff --git a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py index b9c6df93c82..36c386ee39a 100644 --- a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py +++ b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py @@ -4,7 +4,9 @@ steps, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/collatz-conjecture/canonical-data.json +# File last updated on 2023-07-14 class CollatzConjectureTest(unittest.TestCase): diff --git a/exercises/practice/complex-numbers/complex_numbers_test.py b/exercises/practice/complex-numbers/complex_numbers_test.py index 2eca7849697..995439763a5 100644 --- a/exercises/practice/complex-numbers/complex_numbers_test.py +++ b/exercises/practice/complex-numbers/complex_numbers_test.py @@ -6,7 +6,9 @@ ComplexNumber, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/complex-numbers/canonical-data.json +# File last updated on 2023-07-14 class ComplexNumbersTest(unittest.TestCase): diff --git a/exercises/practice/connect/connect_test.py b/exercises/practice/connect/connect_test.py index 17c786c8652..a5b6f32444c 100644 --- a/exercises/practice/connect/connect_test.py +++ b/exercises/practice/connect/connect_test.py @@ -4,7 +4,9 @@ ConnectGame, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/connect/canonical-data.json +# File last updated on 2023-07-14 class ConnectTest(unittest.TestCase): diff --git a/exercises/practice/crypto-square/crypto_square_test.py b/exercises/practice/crypto-square/crypto_square_test.py index 553728f3fea..c2845ef562c 100644 --- a/exercises/practice/crypto-square/crypto_square_test.py +++ b/exercises/practice/crypto-square/crypto_square_test.py @@ -4,7 +4,9 @@ cipher_text, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/crypto-square/canonical-data.json +# File last updated on 2023-07-14 class CryptoSquareTest(unittest.TestCase): diff --git a/exercises/practice/custom-set/custom_set_test.py b/exercises/practice/custom-set/custom_set_test.py index 30c945ac739..ecad09fdba3 100644 --- a/exercises/practice/custom-set/custom_set_test.py +++ b/exercises/practice/custom-set/custom_set_test.py @@ -4,7 +4,9 @@ CustomSet, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/custom-set/canonical-data.json +# File last updated on 2023-07-14 class CustomSetTest(unittest.TestCase): diff --git a/exercises/practice/darts/darts_test.py b/exercises/practice/darts/darts_test.py index 94a9c5ed3cc..9f9a6a323e4 100644 --- a/exercises/practice/darts/darts_test.py +++ b/exercises/practice/darts/darts_test.py @@ -4,7 +4,9 @@ score, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/darts/canonical-data.json +# File last updated on 2023-07-14 class DartsTest(unittest.TestCase): diff --git a/exercises/practice/diamond/diamond_test.py b/exercises/practice/diamond/diamond_test.py index 9ed44ee198e..335b0bd7994 100644 --- a/exercises/practice/diamond/diamond_test.py +++ b/exercises/practice/diamond/diamond_test.py @@ -4,7 +4,9 @@ rows, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/diamond/canonical-data.json +# File last updated on 2023-07-14 class DiamondTest(unittest.TestCase): diff --git a/exercises/practice/difference-of-squares/difference_of_squares_test.py b/exercises/practice/difference-of-squares/difference_of_squares_test.py index fa39f03e551..d38681f742e 100644 --- a/exercises/practice/difference-of-squares/difference_of_squares_test.py +++ b/exercises/practice/difference-of-squares/difference_of_squares_test.py @@ -6,7 +6,9 @@ sum_of_squares, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/difference-of-squares/canonical-data.json +# File last updated on 2023-07-14 class DifferenceOfSquaresTest(unittest.TestCase): diff --git a/exercises/practice/diffie-hellman/diffie_hellman_test.py b/exercises/practice/diffie-hellman/diffie_hellman_test.py index 716b7ba1917..60c514d9f81 100644 --- a/exercises/practice/diffie-hellman/diffie_hellman_test.py +++ b/exercises/practice/diffie-hellman/diffie_hellman_test.py @@ -6,7 +6,9 @@ secret, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/diffie-hellman/canonical-data.json +# File last updated on 2023-07-14 class DiffieHellmanTest(unittest.TestCase): diff --git a/exercises/practice/dnd-character/dnd_character_test.py b/exercises/practice/dnd-character/dnd_character_test.py index 3f370bc4bda..d97cbfda62d 100644 --- a/exercises/practice/dnd-character/dnd_character_test.py +++ b/exercises/practice/dnd-character/dnd_character_test.py @@ -5,7 +5,9 @@ modifier, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/dnd-character/canonical-data.json +# File last updated on 2023-07-14 class DndCharacterTest(unittest.TestCase): diff --git a/exercises/practice/dominoes/dominoes_test.py b/exercises/practice/dominoes/dominoes_test.py index a9b8c90dd8c..a9d82512c2c 100644 --- a/exercises/practice/dominoes/dominoes_test.py +++ b/exercises/practice/dominoes/dominoes_test.py @@ -4,7 +4,9 @@ can_chain, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/dominoes/canonical-data.json +# File last updated on 2023-07-14 class DominoesTest(unittest.TestCase): diff --git a/exercises/practice/etl/etl_test.py b/exercises/practice/etl/etl_test.py index fbd57fd289f..b2ce956fe4e 100644 --- a/exercises/practice/etl/etl_test.py +++ b/exercises/practice/etl/etl_test.py @@ -4,7 +4,9 @@ transform, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/etl/canonical-data.json +# File last updated on 2023-07-14 class EtlTest(unittest.TestCase): diff --git a/exercises/practice/flatten-array/flatten_array_test.py b/exercises/practice/flatten-array/flatten_array_test.py index 3038d1a00fb..8271ce1d068 100644 --- a/exercises/practice/flatten-array/flatten_array_test.py +++ b/exercises/practice/flatten-array/flatten_array_test.py @@ -4,7 +4,9 @@ flatten, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/flatten-array/canonical-data.json +# File last updated on 2023-07-14 class FlattenArrayTest(unittest.TestCase): diff --git a/exercises/practice/food-chain/food_chain_test.py b/exercises/practice/food-chain/food_chain_test.py index f87f4cc9a2d..195c1ab1174 100644 --- a/exercises/practice/food-chain/food_chain_test.py +++ b/exercises/practice/food-chain/food_chain_test.py @@ -4,7 +4,9 @@ recite, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/food-chain/canonical-data.json +# File last updated on 2023-07-14 class FoodChainTest(unittest.TestCase): diff --git a/exercises/practice/forth/forth_test.py b/exercises/practice/forth/forth_test.py index f565c6455e3..07778ceb3aa 100644 --- a/exercises/practice/forth/forth_test.py +++ b/exercises/practice/forth/forth_test.py @@ -5,7 +5,9 @@ StackUnderflowError, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/forth/canonical-data.json +# File last updated on 2023-07-14 class ForthTest(unittest.TestCase): diff --git a/exercises/practice/gigasecond/gigasecond_test.py b/exercises/practice/gigasecond/gigasecond_test.py index e7b5f0837f1..c1e24d4bc44 100644 --- a/exercises/practice/gigasecond/gigasecond_test.py +++ b/exercises/practice/gigasecond/gigasecond_test.py @@ -5,7 +5,9 @@ add, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/gigasecond/canonical-data.json +# File last updated on 2023-07-14 class GigasecondTest(unittest.TestCase): diff --git a/exercises/practice/go-counting/go_counting_test.py b/exercises/practice/go-counting/go_counting_test.py index 30972ca6a20..e0920459cbe 100644 --- a/exercises/practice/go-counting/go_counting_test.py +++ b/exercises/practice/go-counting/go_counting_test.py @@ -7,7 +7,9 @@ NONE, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/go-counting/canonical-data.json +# File last updated on 2023-07-14 class GoCountingTest(unittest.TestCase): diff --git a/exercises/practice/grade-school/grade_school_test.py b/exercises/practice/grade-school/grade_school_test.py index 4672efe88ee..19509de6537 100644 --- a/exercises/practice/grade-school/grade_school_test.py +++ b/exercises/practice/grade-school/grade_school_test.py @@ -4,7 +4,9 @@ School, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/grade-school/canonical-data.json +# File last updated on 2023-07-14 class GradeSchoolTest(unittest.TestCase): diff --git a/exercises/practice/grains/grains_test.py b/exercises/practice/grains/grains_test.py index f7e277c0702..5a4de3a8774 100644 --- a/exercises/practice/grains/grains_test.py +++ b/exercises/practice/grains/grains_test.py @@ -5,7 +5,9 @@ total, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/grains/canonical-data.json +# File last updated on 2023-07-14 class GrainsTest(unittest.TestCase): diff --git a/exercises/practice/grep/grep_test.py b/exercises/practice/grep/grep_test.py index 87c76ac829c..ff81e36d8dd 100644 --- a/exercises/practice/grep/grep_test.py +++ b/exercises/practice/grep/grep_test.py @@ -4,7 +4,9 @@ grep, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/grep/canonical-data.json +# File last updated on 2023-07-14 import io from unittest import mock diff --git a/exercises/practice/hamming/hamming_test.py b/exercises/practice/hamming/hamming_test.py index 06a08b09dd8..e9fcadea9ed 100644 --- a/exercises/practice/hamming/hamming_test.py +++ b/exercises/practice/hamming/hamming_test.py @@ -4,7 +4,9 @@ distance, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/hamming/canonical-data.json +# File last updated on 2023-07-14 class HammingTest(unittest.TestCase): diff --git a/exercises/practice/high-scores/high_scores_test.py b/exercises/practice/high-scores/high_scores_test.py index f1406dd852d..ec716a489cf 100644 --- a/exercises/practice/high-scores/high_scores_test.py +++ b/exercises/practice/high-scores/high_scores_test.py @@ -4,7 +4,9 @@ HighScores, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/high-scores/canonical-data.json +# File last updated on 2023-07-14 class HighScoresTest(unittest.TestCase): diff --git a/exercises/practice/house/house_test.py b/exercises/practice/house/house_test.py index 8247675823f..6ad16a0ccb7 100644 --- a/exercises/practice/house/house_test.py +++ b/exercises/practice/house/house_test.py @@ -4,7 +4,9 @@ recite, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/house/canonical-data.json +# File last updated on 2023-07-14 class HouseTest(unittest.TestCase): diff --git a/exercises/practice/isbn-verifier/isbn_verifier_test.py b/exercises/practice/isbn-verifier/isbn_verifier_test.py index 22fd28922f3..aa3d954d228 100644 --- a/exercises/practice/isbn-verifier/isbn_verifier_test.py +++ b/exercises/practice/isbn-verifier/isbn_verifier_test.py @@ -4,7 +4,9 @@ is_valid, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/isbn-verifier/canonical-data.json +# File last updated on 2023-07-14 class IsbnVerifierTest(unittest.TestCase): diff --git a/exercises/practice/isogram/isogram_test.py b/exercises/practice/isogram/isogram_test.py index 8d00d2b5f52..99940e3ddfc 100644 --- a/exercises/practice/isogram/isogram_test.py +++ b/exercises/practice/isogram/isogram_test.py @@ -4,7 +4,9 @@ is_isogram, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/isogram/canonical-data.json +# File last updated on 2023-07-14 class IsogramTest(unittest.TestCase): diff --git a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py index b5732054653..3a7f4c0dcca 100644 --- a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py +++ b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py @@ -4,7 +4,9 @@ combinations, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/killer-sudoku-helper/canonical-data.json +# File last updated on 2023-07-14 class KillerSudokuHelperTest(unittest.TestCase): diff --git a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py index 95095cabed8..5773dfa3905 100644 --- a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py +++ b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py @@ -4,7 +4,9 @@ Garden, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/kindergarten-garden/canonical-data.json +# File last updated on 2023-07-14 class KindergartenGardenTest(unittest.TestCase): diff --git a/exercises/practice/knapsack/knapsack_test.py b/exercises/practice/knapsack/knapsack_test.py index 937df1bb0ff..20429bb263d 100644 --- a/exercises/practice/knapsack/knapsack_test.py +++ b/exercises/practice/knapsack/knapsack_test.py @@ -4,7 +4,9 @@ maximum_value, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/knapsack/canonical-data.json +# File last updated on 2023-07-14 class KnapsackTest(unittest.TestCase): diff --git a/exercises/practice/largest-series-product/largest_series_product_test.py b/exercises/practice/largest-series-product/largest_series_product_test.py index ba8ae10dc8e..8b02dfbbb7e 100644 --- a/exercises/practice/largest-series-product/largest_series_product_test.py +++ b/exercises/practice/largest-series-product/largest_series_product_test.py @@ -4,7 +4,9 @@ largest_product, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/largest-series-product/canonical-data.json +# File last updated on 2023-07-14 class LargestSeriesProductTest(unittest.TestCase): diff --git a/exercises/practice/leap/leap_test.py b/exercises/practice/leap/leap_test.py index 6ba0f949b1c..2b25b36a6a7 100644 --- a/exercises/practice/leap/leap_test.py +++ b/exercises/practice/leap/leap_test.py @@ -4,7 +4,9 @@ leap_year, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/leap/canonical-data.json +# File last updated on 2023-07-14 class LeapTest(unittest.TestCase): diff --git a/exercises/practice/ledger/ledger_test.py b/exercises/practice/ledger/ledger_test.py index c1615666ce5..2c51a4d7715 100644 --- a/exercises/practice/ledger/ledger_test.py +++ b/exercises/practice/ledger/ledger_test.py @@ -5,7 +5,9 @@ create_entry, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/ledger/canonical-data.json +# File last updated on 2023-07-14 class LedgerTest(unittest.TestCase): diff --git a/exercises/practice/linked-list/linked_list_test.py b/exercises/practice/linked-list/linked_list_test.py index 3af5bc221e4..c0b44de4d9e 100644 --- a/exercises/practice/linked-list/linked_list_test.py +++ b/exercises/practice/linked-list/linked_list_test.py @@ -4,7 +4,9 @@ LinkedList, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/linked-list/canonical-data.json +# File last updated on 2023-07-14 class LinkedListTest(unittest.TestCase): diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index cb015acc66c..7bd60f4f211 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -11,7 +11,9 @@ map as list_ops_map, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/list-ops/canonical-data.json +# File last updated on 2023-07-14 class ListOpsTest(unittest.TestCase): diff --git a/exercises/practice/luhn/luhn_test.py b/exercises/practice/luhn/luhn_test.py index bbc1f8eb1f8..dd309dd72f6 100644 --- a/exercises/practice/luhn/luhn_test.py +++ b/exercises/practice/luhn/luhn_test.py @@ -4,7 +4,9 @@ Luhn, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/luhn/canonical-data.json +# File last updated on 2023-07-14 class LuhnTest(unittest.TestCase): diff --git a/exercises/practice/markdown/markdown_test.py b/exercises/practice/markdown/markdown_test.py index 5c059c725a8..b79353cdd7a 100644 --- a/exercises/practice/markdown/markdown_test.py +++ b/exercises/practice/markdown/markdown_test.py @@ -4,7 +4,9 @@ parse, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/markdown/canonical-data.json +# File last updated on 2023-07-14 class MarkdownTest(unittest.TestCase): diff --git a/exercises/practice/matching-brackets/matching_brackets_test.py b/exercises/practice/matching-brackets/matching_brackets_test.py index fb270ae8bce..b83c341a296 100644 --- a/exercises/practice/matching-brackets/matching_brackets_test.py +++ b/exercises/practice/matching-brackets/matching_brackets_test.py @@ -4,7 +4,9 @@ is_paired, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/matching-brackets/canonical-data.json +# File last updated on 2023-07-14 class MatchingBracketsTest(unittest.TestCase): diff --git a/exercises/practice/matrix/matrix_test.py b/exercises/practice/matrix/matrix_test.py index 10820ab6c12..8573ccf9a6a 100644 --- a/exercises/practice/matrix/matrix_test.py +++ b/exercises/practice/matrix/matrix_test.py @@ -4,7 +4,9 @@ Matrix, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/matrix/canonical-data.json +# File last updated on 2023-07-14 class MatrixTest(unittest.TestCase): diff --git a/exercises/practice/meetup/meetup_test.py b/exercises/practice/meetup/meetup_test.py index 9ecc3d8a1df..a9b3721c03f 100644 --- a/exercises/practice/meetup/meetup_test.py +++ b/exercises/practice/meetup/meetup_test.py @@ -6,7 +6,9 @@ MeetupDayException, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/meetup/canonical-data.json +# File last updated on 2023-07-14 class MeetupTest(unittest.TestCase): diff --git a/exercises/practice/minesweeper/minesweeper_test.py b/exercises/practice/minesweeper/minesweeper_test.py index d5e6b78b7f4..32927a95efe 100644 --- a/exercises/practice/minesweeper/minesweeper_test.py +++ b/exercises/practice/minesweeper/minesweeper_test.py @@ -4,7 +4,9 @@ annotate, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/minesweeper/canonical-data.json +# File last updated on 2023-07-14 class MinesweeperTest(unittest.TestCase): diff --git a/exercises/practice/nth-prime/nth_prime_test.py b/exercises/practice/nth-prime/nth_prime_test.py index 2a3e1b3f2e8..50a68a05e2b 100644 --- a/exercises/practice/nth-prime/nth_prime_test.py +++ b/exercises/practice/nth-prime/nth_prime_test.py @@ -4,7 +4,9 @@ prime, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/nth-prime/canonical-data.json +# File last updated on 2023-07-14 def prime_range(n): diff --git a/exercises/practice/ocr-numbers/ocr_numbers_test.py b/exercises/practice/ocr-numbers/ocr_numbers_test.py index eeafb2fb314..d3a11134ddf 100644 --- a/exercises/practice/ocr-numbers/ocr_numbers_test.py +++ b/exercises/practice/ocr-numbers/ocr_numbers_test.py @@ -4,7 +4,9 @@ convert, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/ocr-numbers/canonical-data.json +# File last updated on 2023-07-14 class OcrNumbersTest(unittest.TestCase): diff --git a/exercises/practice/palindrome-products/palindrome_products_test.py b/exercises/practice/palindrome-products/palindrome_products_test.py index 0fd7eaece32..e748b8703c2 100644 --- a/exercises/practice/palindrome-products/palindrome_products_test.py +++ b/exercises/practice/palindrome-products/palindrome_products_test.py @@ -5,7 +5,9 @@ smallest, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/palindrome-products/canonical-data.json +# File last updated on 2023-07-14 class PalindromeProductsTest(unittest.TestCase): diff --git a/exercises/practice/pangram/pangram_test.py b/exercises/practice/pangram/pangram_test.py index 3f8c9aa7f38..2e5179acee9 100644 --- a/exercises/practice/pangram/pangram_test.py +++ b/exercises/practice/pangram/pangram_test.py @@ -4,7 +4,9 @@ is_pangram, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pangram/canonical-data.json +# File last updated on 2023-07-14 class PangramTest(unittest.TestCase): diff --git a/exercises/practice/pascals-triangle/pascals_triangle_test.py b/exercises/practice/pascals-triangle/pascals_triangle_test.py index dc7b7ce1111..a0b253af3e6 100644 --- a/exercises/practice/pascals-triangle/pascals_triangle_test.py +++ b/exercises/practice/pascals-triangle/pascals_triangle_test.py @@ -5,7 +5,9 @@ rows, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pascals-triangle/canonical-data.json +# File last updated on 2023-07-14 TRIANGLE = [ [1], diff --git a/exercises/practice/perfect-numbers/perfect_numbers_test.py b/exercises/practice/perfect-numbers/perfect_numbers_test.py index 786f92630ef..512600f12de 100644 --- a/exercises/practice/perfect-numbers/perfect_numbers_test.py +++ b/exercises/practice/perfect-numbers/perfect_numbers_test.py @@ -4,7 +4,9 @@ classify, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/perfect-numbers/canonical-data.json +# File last updated on 2023-07-14 class PerfectNumbersTest(unittest.TestCase): diff --git a/exercises/practice/phone-number/phone_number_test.py b/exercises/practice/phone-number/phone_number_test.py index 72ff3b099ac..1002c6b7a1c 100644 --- a/exercises/practice/phone-number/phone_number_test.py +++ b/exercises/practice/phone-number/phone_number_test.py @@ -4,7 +4,9 @@ PhoneNumber, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/phone-number/canonical-data.json +# File last updated on 2023-07-14 class PhoneNumberTest(unittest.TestCase): diff --git a/exercises/practice/pig-latin/pig_latin_test.py b/exercises/practice/pig-latin/pig_latin_test.py index cf46ae3c1fe..997f0284d54 100644 --- a/exercises/practice/pig-latin/pig_latin_test.py +++ b/exercises/practice/pig-latin/pig_latin_test.py @@ -4,7 +4,9 @@ translate, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json +# File last updated on 2023-07-14 class PigLatinTest(unittest.TestCase): diff --git a/exercises/practice/poker/poker_test.py b/exercises/practice/poker/poker_test.py index d0b2c52dc0f..f30462f897f 100644 --- a/exercises/practice/poker/poker_test.py +++ b/exercises/practice/poker/poker_test.py @@ -4,7 +4,9 @@ best_hands, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/poker/canonical-data.json +# File last updated on 2023-07-14 class PokerTest(unittest.TestCase): diff --git a/exercises/practice/pov/pov_test.py b/exercises/practice/pov/pov_test.py index 4bbdbaa8718..93b622d72a4 100644 --- a/exercises/practice/pov/pov_test.py +++ b/exercises/practice/pov/pov_test.py @@ -4,7 +4,9 @@ Tree, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pov/canonical-data.json +# File last updated on 2023-07-14 class PovTest(unittest.TestCase): diff --git a/exercises/practice/prime-factors/prime_factors_test.py b/exercises/practice/prime-factors/prime_factors_test.py index 02b36e7a16c..187c4f2f960 100644 --- a/exercises/practice/prime-factors/prime_factors_test.py +++ b/exercises/practice/prime-factors/prime_factors_test.py @@ -4,7 +4,9 @@ factors, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/prime-factors/canonical-data.json +# File last updated on 2023-07-14 class PrimeFactorsTest(unittest.TestCase): diff --git a/exercises/practice/protein-translation/protein_translation_test.py b/exercises/practice/protein-translation/protein_translation_test.py index 4ce2d1151b5..464d7f0ddd4 100644 --- a/exercises/practice/protein-translation/protein_translation_test.py +++ b/exercises/practice/protein-translation/protein_translation_test.py @@ -4,7 +4,9 @@ proteins, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/protein-translation/canonical-data.json +# File last updated on 2023-07-14 class ProteinTranslationTest(unittest.TestCase): diff --git a/exercises/practice/proverb/proverb_test.py b/exercises/practice/proverb/proverb_test.py index 69905dadf4a..674cc26dc04 100644 --- a/exercises/practice/proverb/proverb_test.py +++ b/exercises/practice/proverb/proverb_test.py @@ -4,7 +4,9 @@ proverb, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/proverb/canonical-data.json +# File last updated on 2023-07-14 # PLEASE TAKE NOTE: Expected result lists for these test cases use **implicit line joining.** # A new line in a result list below **does not** always equal a new list element. # Check comma placement carefully! diff --git a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py index 3536908ae88..b4b89e2d8a9 100644 --- a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py +++ b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py @@ -4,7 +4,9 @@ triplets_with_sum, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pythagorean-triplet/canonical-data.json +# File last updated on 2023-07-14 class PythagoreanTripletTest(unittest.TestCase): diff --git a/exercises/practice/queen-attack/queen_attack_test.py b/exercises/practice/queen-attack/queen_attack_test.py index 34c212af19e..52f994fc392 100644 --- a/exercises/practice/queen-attack/queen_attack_test.py +++ b/exercises/practice/queen-attack/queen_attack_test.py @@ -4,7 +4,9 @@ Queen, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/queen-attack/canonical-data.json +# File last updated on 2023-07-14 class QueenAttackTest(unittest.TestCase): diff --git a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py index 873de5839bc..fb546d4ab24 100644 --- a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py +++ b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py @@ -5,7 +5,9 @@ encode, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rail-fence-cipher/canonical-data.json +# File last updated on 2023-07-14 class RailFenceCipherTest(unittest.TestCase): diff --git a/exercises/practice/raindrops/raindrops_test.py b/exercises/practice/raindrops/raindrops_test.py index 7a5969c943b..a196eb32af1 100644 --- a/exercises/practice/raindrops/raindrops_test.py +++ b/exercises/practice/raindrops/raindrops_test.py @@ -4,7 +4,9 @@ convert, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/raindrops/canonical-data.json +# File last updated on 2023-07-14 class RaindropsTest(unittest.TestCase): diff --git a/exercises/practice/rational-numbers/rational_numbers_test.py b/exercises/practice/rational-numbers/rational_numbers_test.py index e7a50e528e8..3b1e44a6234 100644 --- a/exercises/practice/rational-numbers/rational_numbers_test.py +++ b/exercises/practice/rational-numbers/rational_numbers_test.py @@ -5,7 +5,9 @@ Rational, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rational-numbers/canonical-data.json +# File last updated on 2023-07-14 class RationalNumbersTest(unittest.TestCase): diff --git a/exercises/practice/react/react_test.py b/exercises/practice/react/react_test.py index 2ba86a80ffa..5d4f22bcc69 100644 --- a/exercises/practice/react/react_test.py +++ b/exercises/practice/react/react_test.py @@ -7,7 +7,9 @@ ComputeCell, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/react/canonical-data.json +# File last updated on 2023-07-14 class ReactTest(unittest.TestCase): diff --git a/exercises/practice/rectangles/rectangles_test.py b/exercises/practice/rectangles/rectangles_test.py index 05938fc5b3f..72cdae7cc27 100644 --- a/exercises/practice/rectangles/rectangles_test.py +++ b/exercises/practice/rectangles/rectangles_test.py @@ -4,7 +4,9 @@ rectangles, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rectangles/canonical-data.json +# File last updated on 2023-07-14 class RectanglesTest(unittest.TestCase): diff --git a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py index 72df473f071..9ace6d64b7b 100644 --- a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py +++ b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py @@ -4,7 +4,9 @@ value, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-duo/canonical-data.json +# File last updated on 2023-07-14 class ResistorColorDuoTest(unittest.TestCase): diff --git a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py index ddfdfb6930c..31901c5cfad 100644 --- a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py +++ b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py @@ -4,7 +4,9 @@ label, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-trio/canonical-data.json +# File last updated on 2023-07-14 class ResistorColorTrioTest(unittest.TestCase): diff --git a/exercises/practice/resistor-color/resistor_color_test.py b/exercises/practice/resistor-color/resistor_color_test.py index 631bc951e67..bb180385ceb 100644 --- a/exercises/practice/resistor-color/resistor_color_test.py +++ b/exercises/practice/resistor-color/resistor_color_test.py @@ -5,7 +5,9 @@ colors, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color/canonical-data.json +# File last updated on 2023-07-14 class ResistorColorTest(unittest.TestCase): diff --git a/exercises/practice/rest-api/rest_api_test.py b/exercises/practice/rest-api/rest_api_test.py index 4a5c525fa8a..4a00073ddae 100644 --- a/exercises/practice/rest-api/rest_api_test.py +++ b/exercises/practice/rest-api/rest_api_test.py @@ -4,7 +4,9 @@ RestAPI, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rest-api/canonical-data.json +# File last updated on 2023-07-14 import json diff --git a/exercises/practice/reverse-string/reverse_string_test.py b/exercises/practice/reverse-string/reverse_string_test.py index a1a28dc1e6b..cedc7f890c8 100644 --- a/exercises/practice/reverse-string/reverse_string_test.py +++ b/exercises/practice/reverse-string/reverse_string_test.py @@ -4,7 +4,9 @@ reverse, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/reverse-string/canonical-data.json +# File last updated on 2023-07-14 class ReverseStringTest(unittest.TestCase): diff --git a/exercises/practice/rna-transcription/rna_transcription_test.py b/exercises/practice/rna-transcription/rna_transcription_test.py index e6c88062bf1..2e58d06b934 100644 --- a/exercises/practice/rna-transcription/rna_transcription_test.py +++ b/exercises/practice/rna-transcription/rna_transcription_test.py @@ -4,7 +4,9 @@ to_rna, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rna-transcription/canonical-data.json +# File last updated on 2023-07-14 class RnaTranscriptionTest(unittest.TestCase): diff --git a/exercises/practice/robot-simulator/robot_simulator_test.py b/exercises/practice/robot-simulator/robot_simulator_test.py index ffb5728c301..2d545176810 100644 --- a/exercises/practice/robot-simulator/robot_simulator_test.py +++ b/exercises/practice/robot-simulator/robot_simulator_test.py @@ -8,7 +8,9 @@ WEST, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/robot-simulator/canonical-data.json +# File last updated on 2023-07-14 class RobotSimulatorTest(unittest.TestCase): diff --git a/exercises/practice/roman-numerals/roman_numerals_test.py b/exercises/practice/roman-numerals/roman_numerals_test.py index 59e5e697fa2..51ff27cb131 100644 --- a/exercises/practice/roman-numerals/roman_numerals_test.py +++ b/exercises/practice/roman-numerals/roman_numerals_test.py @@ -4,7 +4,9 @@ roman, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/roman-numerals/canonical-data.json +# File last updated on 2023-07-14 class RomanNumeralsTest(unittest.TestCase): def test_1_is_i(self): self.assertEqual(roman(1), "I") diff --git a/exercises/practice/rotational-cipher/rotational_cipher_test.py b/exercises/practice/rotational-cipher/rotational_cipher_test.py index b6e760a4ed3..21dbcf8ab72 100644 --- a/exercises/practice/rotational-cipher/rotational_cipher_test.py +++ b/exercises/practice/rotational-cipher/rotational_cipher_test.py @@ -4,7 +4,9 @@ rotate, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rotational-cipher/canonical-data.json +# File last updated on 2023-07-14 class RotationalCipherTest(unittest.TestCase): diff --git a/exercises/practice/run-length-encoding/run_length_encoding_test.py b/exercises/practice/run-length-encoding/run_length_encoding_test.py index 9ac78f6d23c..251c5f5ca88 100644 --- a/exercises/practice/run-length-encoding/run_length_encoding_test.py +++ b/exercises/practice/run-length-encoding/run_length_encoding_test.py @@ -5,7 +5,9 @@ decode, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/run-length-encoding/canonical-data.json +# File last updated on 2023-07-14 class RunLengthEncodingTest(unittest.TestCase): diff --git a/exercises/practice/saddle-points/saddle_points_test.py b/exercises/practice/saddle-points/saddle_points_test.py index 24c18e09b7f..4a33d1922bf 100644 --- a/exercises/practice/saddle-points/saddle_points_test.py +++ b/exercises/practice/saddle-points/saddle_points_test.py @@ -11,7 +11,9 @@ saddle_points, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/saddle-points/canonical-data.json +# File last updated on 2023-07-14 def sorted_points(point_list): diff --git a/exercises/practice/satellite/satellite_test.py b/exercises/practice/satellite/satellite_test.py index 2eb329c2f96..c1629a9ce41 100644 --- a/exercises/practice/satellite/satellite_test.py +++ b/exercises/practice/satellite/satellite_test.py @@ -4,7 +4,9 @@ tree_from_traversals, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/satellite/canonical-data.json +# File last updated on 2023-07-14 class SatelliteTest(unittest.TestCase): diff --git a/exercises/practice/say/say_test.py b/exercises/practice/say/say_test.py index 22deb5364cb..58f9a04a9d1 100644 --- a/exercises/practice/say/say_test.py +++ b/exercises/practice/say/say_test.py @@ -4,7 +4,9 @@ say, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/say/canonical-data.json +# File last updated on 2023-07-14 class SayTest(unittest.TestCase): diff --git a/exercises/practice/scale-generator/scale_generator_test.py b/exercises/practice/scale-generator/scale_generator_test.py index 5757fad3168..48f94f3d810 100644 --- a/exercises/practice/scale-generator/scale_generator_test.py +++ b/exercises/practice/scale-generator/scale_generator_test.py @@ -4,7 +4,9 @@ Scale, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/scale-generator/canonical-data.json +# File last updated on 2023-07-14 class ScaleGeneratorTest(unittest.TestCase): diff --git a/exercises/practice/scrabble-score/scrabble_score_test.py b/exercises/practice/scrabble-score/scrabble_score_test.py index 2ea8fd32405..1b95e627cba 100644 --- a/exercises/practice/scrabble-score/scrabble_score_test.py +++ b/exercises/practice/scrabble-score/scrabble_score_test.py @@ -4,7 +4,9 @@ score, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/scrabble-score/canonical-data.json +# File last updated on 2023-07-14 class ScrabbleScoreTest(unittest.TestCase): diff --git a/exercises/practice/secret-handshake/secret_handshake_test.py b/exercises/practice/secret-handshake/secret_handshake_test.py index b9e534d5fa3..6abf64d452d 100644 --- a/exercises/practice/secret-handshake/secret_handshake_test.py +++ b/exercises/practice/secret-handshake/secret_handshake_test.py @@ -4,7 +4,9 @@ commands, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/secret-handshake/canonical-data.json +# File last updated on 2023-07-14 class SecretHandshakeTest(unittest.TestCase): diff --git a/exercises/practice/series/series_test.py b/exercises/practice/series/series_test.py index 7f6de7a4669..9c6ee8b8c14 100644 --- a/exercises/practice/series/series_test.py +++ b/exercises/practice/series/series_test.py @@ -4,7 +4,9 @@ slices, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/series/canonical-data.json +# File last updated on 2023-07-14 class SeriesTest(unittest.TestCase): diff --git a/exercises/practice/sgf-parsing/sgf_parsing_test.py b/exercises/practice/sgf-parsing/sgf_parsing_test.py index b3d43ed09df..f7acf2b1820 100644 --- a/exercises/practice/sgf-parsing/sgf_parsing_test.py +++ b/exercises/practice/sgf-parsing/sgf_parsing_test.py @@ -5,7 +5,9 @@ SgfTree, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sgf-parsing/canonical-data.json +# File last updated on 2023-07-14 class SgfParsingTest(unittest.TestCase): diff --git a/exercises/practice/sieve/sieve_test.py b/exercises/practice/sieve/sieve_test.py index 91bb00e7ae6..487f402db69 100644 --- a/exercises/practice/sieve/sieve_test.py +++ b/exercises/practice/sieve/sieve_test.py @@ -4,7 +4,9 @@ primes, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sieve/canonical-data.json +# File last updated on 2023-07-14 class SieveTest(unittest.TestCase): diff --git a/exercises/practice/simple-cipher/simple_cipher_test.py b/exercises/practice/simple-cipher/simple_cipher_test.py index 8b911d734bb..af4e2540d08 100644 --- a/exercises/practice/simple-cipher/simple_cipher_test.py +++ b/exercises/practice/simple-cipher/simple_cipher_test.py @@ -5,7 +5,9 @@ Cipher, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/simple-cipher/canonical-data.json +# File last updated on 2023-07-14 class RandomKeyCipherTest(unittest.TestCase): diff --git a/exercises/practice/space-age/space_age_test.py b/exercises/practice/space-age/space_age_test.py index 1d248b19e33..d1dc13b517b 100644 --- a/exercises/practice/space-age/space_age_test.py +++ b/exercises/practice/space-age/space_age_test.py @@ -4,7 +4,9 @@ SpaceAge, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/space-age/canonical-data.json +# File last updated on 2023-07-14 class SpaceAgeTest(unittest.TestCase): diff --git a/exercises/practice/spiral-matrix/spiral_matrix_test.py b/exercises/practice/spiral-matrix/spiral_matrix_test.py index 3e6658cf547..fe3d1be2b8d 100644 --- a/exercises/practice/spiral-matrix/spiral_matrix_test.py +++ b/exercises/practice/spiral-matrix/spiral_matrix_test.py @@ -4,7 +4,9 @@ spiral_matrix, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/spiral-matrix/canonical-data.json +# File last updated on 2023-07-14 class SpiralMatrixTest(unittest.TestCase): diff --git a/exercises/practice/square-root/square_root_test.py b/exercises/practice/square-root/square_root_test.py index 635728fee45..1a8dda7ab2e 100644 --- a/exercises/practice/square-root/square_root_test.py +++ b/exercises/practice/square-root/square_root_test.py @@ -4,7 +4,9 @@ square_root, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/square-root/canonical-data.json +# File last updated on 2023-07-14 class SquareRootTest(unittest.TestCase): diff --git a/exercises/practice/sublist/sublist_test.py b/exercises/practice/sublist/sublist_test.py index b3dc9c7bce1..dcabff2121f 100644 --- a/exercises/practice/sublist/sublist_test.py +++ b/exercises/practice/sublist/sublist_test.py @@ -8,7 +8,9 @@ UNEQUAL, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sublist/canonical-data.json +# File last updated on 2023-07-14 class SublistTest(unittest.TestCase): diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py index 29d0ac7244e..762840fbbc3 100644 --- a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py +++ b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py @@ -4,7 +4,9 @@ sum_of_multiples, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sum-of-multiples/canonical-data.json +# File last updated on 2023-07-14 class SumOfMultiplesTest(unittest.TestCase): diff --git a/exercises/practice/tournament/tournament_test.py b/exercises/practice/tournament/tournament_test.py index 22a81667899..da8892d7dfe 100644 --- a/exercises/practice/tournament/tournament_test.py +++ b/exercises/practice/tournament/tournament_test.py @@ -4,7 +4,9 @@ tally, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/tournament/canonical-data.json +# File last updated on 2023-07-14 class TournamentTest(unittest.TestCase): diff --git a/exercises/practice/transpose/transpose_test.py b/exercises/practice/transpose/transpose_test.py index 0a0f5c024fb..31464c6c6e4 100644 --- a/exercises/practice/transpose/transpose_test.py +++ b/exercises/practice/transpose/transpose_test.py @@ -4,7 +4,9 @@ transpose, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/transpose/canonical-data.json +# File last updated on 2023-07-14 class TransposeTest(unittest.TestCase): diff --git a/exercises/practice/triangle/triangle_test.py b/exercises/practice/triangle/triangle_test.py index f67d63fa69c..7de4b34046a 100644 --- a/exercises/practice/triangle/triangle_test.py +++ b/exercises/practice/triangle/triangle_test.py @@ -6,7 +6,9 @@ scalene, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json +# File last updated on 2023-07-14 class EquilateralTriangleTest(unittest.TestCase): diff --git a/exercises/practice/twelve-days/twelve_days_test.py b/exercises/practice/twelve-days/twelve_days_test.py index ec097cddb9c..37076cf3efb 100644 --- a/exercises/practice/twelve-days/twelve_days_test.py +++ b/exercises/practice/twelve-days/twelve_days_test.py @@ -4,7 +4,9 @@ recite, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/twelve-days/canonical-data.json +# File last updated on 2023-07-14 # PLEASE TAKE NOTE: Expected result lists for these test cases use **implicit line joining.** # A new line in a result list below **does not** always equal a new list element. # Check comma placement carefully! diff --git a/exercises/practice/two-bucket/two_bucket_test.py b/exercises/practice/two-bucket/two_bucket_test.py index 7fe7fac1a7c..7ccf4135738 100644 --- a/exercises/practice/two-bucket/two_bucket_test.py +++ b/exercises/practice/two-bucket/two_bucket_test.py @@ -4,7 +4,9 @@ measure, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/two-bucket/canonical-data.json +# File last updated on 2023-07-14 class TwoBucketTest(unittest.TestCase): diff --git a/exercises/practice/two-fer/two_fer_test.py b/exercises/practice/two-fer/two_fer_test.py index ea74f1165dd..ae322272cb0 100644 --- a/exercises/practice/two-fer/two_fer_test.py +++ b/exercises/practice/two-fer/two_fer_test.py @@ -4,7 +4,9 @@ two_fer, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/two-fer/canonical-data.json +# File last updated on 2023-07-14 class TwoFerTest(unittest.TestCase): diff --git a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py index c6867dac90a..5f75ec9215f 100644 --- a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py +++ b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py @@ -5,7 +5,9 @@ encode, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/variable-length-quantity/canonical-data.json +# File last updated on 2023-07-14 class VariableLengthQuantityTest(unittest.TestCase): diff --git a/exercises/practice/word-count/word_count_test.py b/exercises/practice/word-count/word_count_test.py index 329301a38ec..783eca5a0bf 100644 --- a/exercises/practice/word-count/word_count_test.py +++ b/exercises/practice/word-count/word_count_test.py @@ -4,7 +4,9 @@ count_words, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/word-count/canonical-data.json +# File last updated on 2023-07-14 class WordCountTest(unittest.TestCase): diff --git a/exercises/practice/word-search/word_search_test.py b/exercises/practice/word-search/word_search_test.py index e5a32ceed7c..2dd3d434150 100644 --- a/exercises/practice/word-search/word_search_test.py +++ b/exercises/practice/word-search/word_search_test.py @@ -5,7 +5,9 @@ Point, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/word-search/canonical-data.json +# File last updated on 2023-07-14 class WordSearchTest(unittest.TestCase): diff --git a/exercises/practice/wordy/wordy_test.py b/exercises/practice/wordy/wordy_test.py index 3f85ed41f16..678985ff89b 100644 --- a/exercises/practice/wordy/wordy_test.py +++ b/exercises/practice/wordy/wordy_test.py @@ -4,7 +4,9 @@ answer, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/wordy/canonical-data.json +# File last updated on 2023-07-14 class WordyTest(unittest.TestCase): diff --git a/exercises/practice/yacht/yacht_test.py b/exercises/practice/yacht/yacht_test.py index 32b929942c1..cf7d72b4556 100644 --- a/exercises/practice/yacht/yacht_test.py +++ b/exercises/practice/yacht/yacht_test.py @@ -2,7 +2,9 @@ import yacht -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/yacht/canonical-data.json +# File last updated on 2023-07-14 class YachtTest(unittest.TestCase): diff --git a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py index 4b35afb7a7c..f6ea9c82a38 100644 --- a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py +++ b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py @@ -5,7 +5,9 @@ owns_zebra, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/zebra-puzzle/canonical-data.json +# File last updated on 2023-07-14 class ZebraPuzzleTest(unittest.TestCase): diff --git a/exercises/practice/zipper/zipper_test.py b/exercises/practice/zipper/zipper_test.py index d770c92b3e7..c3f3de0f6d4 100644 --- a/exercises/practice/zipper/zipper_test.py +++ b/exercises/practice/zipper/zipper_test.py @@ -4,7 +4,9 @@ Zipper, ) -# Tests adapted from `problem-specifications//canonical-data.json` +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/zipper/canonical-data.json +# File last updated on 2023-07-14 class ZipperTest(unittest.TestCase): From b49664ac66964f01b1af0da86f34dc7406e8d5a1 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Sat, 15 Jul 2023 15:27:31 -0700 Subject: [PATCH 115/126] [Tooling]: Changed Generate Script to Skip Diffing Generated Comments & Timestamp (#3466) * Changed generate script to skp diffing generated comments and timestamp at top of file. * Reordered and regenerated test files for practice exercises. [no important files changed] --- bin/generate_tests.py | 4 ++++ config/generator_macros.j2 | 4 ++-- exercises/practice/acronym/.meta/template.j2 | 1 + exercises/practice/acronym/acronym_test.py | 8 ++++---- exercises/practice/affine-cipher/affine_cipher_test.py | 8 ++++---- exercises/practice/all-your-base/all_your_base_test.py | 8 ++++---- exercises/practice/allergies/allergies_test.py | 8 ++++---- exercises/practice/alphametics/alphametics_test.py | 8 ++++---- exercises/practice/anagram/anagram_test.py | 8 ++++---- .../practice/armstrong-numbers/armstrong_numbers_test.py | 8 ++++---- exercises/practice/atbash-cipher/atbash_cipher_test.py | 8 ++++---- exercises/practice/bank-account/bank_account_test.py | 8 ++++---- exercises/practice/beer-song/beer_song_test.py | 8 ++++---- .../binary-search-tree/binary_search_tree_test.py | 8 ++++---- exercises/practice/binary-search/binary_search_test.py | 8 ++++---- exercises/practice/bob/bob_test.py | 8 ++++---- exercises/practice/book-store/book_store_test.py | 8 ++++---- exercises/practice/bottle-song/bottle_song_test.py | 8 ++++---- exercises/practice/bowling/bowling_test.py | 8 ++++---- exercises/practice/change/change_test.py | 8 ++++---- .../practice/circular-buffer/circular_buffer_test.py | 8 ++++---- exercises/practice/clock/clock_test.py | 8 ++++---- .../collatz-conjecture/collatz_conjecture_test.py | 8 ++++---- .../practice/complex-numbers/complex_numbers_test.py | 8 ++++---- exercises/practice/connect/connect_test.py | 8 ++++---- exercises/practice/crypto-square/crypto_square_test.py | 8 ++++---- exercises/practice/custom-set/custom_set_test.py | 8 ++++---- exercises/practice/darts/darts_test.py | 8 ++++---- exercises/practice/diamond/diamond_test.py | 8 ++++---- .../difference-of-squares/difference_of_squares_test.py | 8 ++++---- exercises/practice/diffie-hellman/diffie_hellman_test.py | 8 ++++---- exercises/practice/dnd-character/dnd_character_test.py | 8 ++++---- exercises/practice/dominoes/dominoes_test.py | 8 ++++---- exercises/practice/etl/etl_test.py | 8 ++++---- exercises/practice/flatten-array/flatten_array_test.py | 8 ++++---- exercises/practice/food-chain/food_chain_test.py | 8 ++++---- exercises/practice/forth/forth_test.py | 8 ++++---- exercises/practice/gigasecond/gigasecond_test.py | 9 +++++---- exercises/practice/go-counting/go_counting_test.py | 8 ++++---- exercises/practice/grade-school/grade_school_test.py | 8 ++++---- exercises/practice/grains/grains_test.py | 8 ++++---- exercises/practice/grep/grep_test.py | 8 ++++---- exercises/practice/hamming/hamming_test.py | 8 ++++---- exercises/practice/high-scores/high_scores_test.py | 8 ++++---- exercises/practice/house/house_test.py | 8 ++++---- exercises/practice/isbn-verifier/isbn_verifier_test.py | 8 ++++---- exercises/practice/isogram/isogram_test.py | 8 ++++---- .../killer-sudoku-helper/killer_sudoku_helper_test.py | 8 ++++---- .../kindergarten-garden/kindergarten_garden_test.py | 8 ++++---- exercises/practice/knapsack/knapsack_test.py | 8 ++++---- .../largest_series_product_test.py | 8 ++++---- exercises/practice/leap/leap_test.py | 8 ++++---- exercises/practice/ledger/ledger_test.py | 8 ++++---- exercises/practice/linked-list/linked_list_test.py | 8 ++++---- exercises/practice/list-ops/list_ops_test.py | 8 ++++---- exercises/practice/luhn/luhn_test.py | 8 ++++---- exercises/practice/markdown/markdown_test.py | 8 ++++---- .../practice/matching-brackets/matching_brackets_test.py | 8 ++++---- exercises/practice/matrix/matrix_test.py | 8 ++++---- exercises/practice/meetup/meetup_test.py | 9 +++++---- exercises/practice/minesweeper/minesweeper_test.py | 8 ++++---- exercises/practice/nth-prime/nth_prime_test.py | 8 ++++---- exercises/practice/ocr-numbers/ocr_numbers_test.py | 8 ++++---- .../palindrome-products/palindrome_products_test.py | 8 ++++---- exercises/practice/pangram/pangram_test.py | 8 ++++---- .../practice/pascals-triangle/pascals_triangle_test.py | 9 +++++---- .../practice/perfect-numbers/perfect_numbers_test.py | 8 ++++---- exercises/practice/phone-number/phone_number_test.py | 8 ++++---- exercises/practice/pig-latin/pig_latin_test.py | 8 ++++---- exercises/practice/poker/poker_test.py | 8 ++++---- exercises/practice/pov/pov_test.py | 8 ++++---- exercises/practice/prime-factors/prime_factors_test.py | 8 ++++---- .../protein-translation/protein_translation_test.py | 8 ++++---- exercises/practice/proverb/proverb_test.py | 7 ++++--- .../pythagorean-triplet/pythagorean_triplet_test.py | 8 ++++---- exercises/practice/queen-attack/queen_attack_test.py | 8 ++++---- .../practice/rail-fence-cipher/rail_fence_cipher_test.py | 8 ++++---- exercises/practice/raindrops/raindrops_test.py | 8 ++++---- .../practice/rational-numbers/rational_numbers_test.py | 9 +++++---- exercises/practice/react/react_test.py | 8 ++++---- exercises/practice/rectangles/rectangles_test.py | 8 ++++---- .../resistor-color-duo/resistor_color_duo_test.py | 8 ++++---- .../resistor-color-trio/resistor_color_trio_test.py | 8 ++++---- exercises/practice/resistor-color/resistor_color_test.py | 8 ++++---- exercises/practice/rest-api/rest_api_test.py | 8 ++++---- exercises/practice/reverse-string/reverse_string_test.py | 8 ++++---- .../practice/rna-transcription/rna_transcription_test.py | 8 ++++---- .../practice/robot-simulator/robot_simulator_test.py | 8 ++++---- exercises/practice/roman-numerals/roman_numerals_test.py | 8 +++++--- .../practice/rotational-cipher/rotational_cipher_test.py | 8 ++++---- .../run-length-encoding/run_length_encoding_test.py | 8 ++++---- exercises/practice/saddle-points/saddle_points_test.py | 8 ++++---- exercises/practice/satellite/satellite_test.py | 8 ++++---- exercises/practice/say/say_test.py | 8 ++++---- .../practice/scale-generator/scale_generator_test.py | 8 ++++---- exercises/practice/scrabble-score/scrabble_score_test.py | 8 ++++---- .../practice/secret-handshake/secret_handshake_test.py | 8 ++++---- exercises/practice/series/series_test.py | 8 ++++---- exercises/practice/sgf-parsing/sgf_parsing_test.py | 8 ++++---- exercises/practice/sieve/sieve_test.py | 8 ++++---- exercises/practice/simple-cipher/simple_cipher_test.py | 9 +++++---- exercises/practice/space-age/space_age_test.py | 8 ++++---- exercises/practice/spiral-matrix/spiral_matrix_test.py | 8 ++++---- exercises/practice/square-root/square_root_test.py | 8 ++++---- exercises/practice/sublist/sublist_test.py | 8 ++++---- .../practice/sum-of-multiples/sum_of_multiples_test.py | 8 ++++---- exercises/practice/tournament/tournament_test.py | 8 ++++---- exercises/practice/transpose/transpose_test.py | 8 ++++---- exercises/practice/triangle/triangle_test.py | 8 ++++---- exercises/practice/twelve-days/twelve_days_test.py | 7 ++++--- exercises/practice/two-bucket/two_bucket_test.py | 8 ++++---- exercises/practice/two-fer/two_fer_test.py | 8 ++++---- .../variable_length_quantity_test.py | 8 ++++---- exercises/practice/word-count/word_count_test.py | 8 ++++---- exercises/practice/word-search/word_search_test.py | 8 ++++---- exercises/practice/wordy/wordy_test.py | 8 ++++---- exercises/practice/yacht/yacht_test.py | 2 +- exercises/practice/zebra-puzzle/zebra_puzzle_test.py | 8 ++++---- exercises/practice/zipper/zipper_test.py | 8 ++++---- 119 files changed, 474 insertions(+), 460 deletions(-) diff --git a/bin/generate_tests.py b/bin/generate_tests.py index d5fc4c5c5ec..285c88d2e77 100755 --- a/bin/generate_tests.py +++ b/bin/generate_tests.py @@ -271,8 +271,12 @@ def check_template(slug: str, tests_path: Path, tmpfile: Path): check_ok = False if check_ok and not filecmp.cmp(tmpfile, tests_path): with tests_path.open() as f: + for line in range(5): + next(f) current_lines = f.readlines() with tmpfile.open() as f: + for line in range(4): + next(f) rendered_lines = f.readlines() diff = difflib.unified_diff( current_lines, diff --git a/config/generator_macros.j2 b/config/generator_macros.j2 index 32af5d5c9fe..37d8e45a800 100644 --- a/config/generator_macros.j2 +++ b/config/generator_macros.j2 @@ -16,6 +16,8 @@ {%- endmacro %} {% macro header(imports=[], ignore=[]) -%} +{{ canonical_ref() }} + import unittest from {{ exercise | to_snake }} import ({% if imports -%} @@ -29,8 +31,6 @@ from {{ exercise | to_snake }} import ({% if imports -%} {%- endif -%} {% endfor %} {%- endif %}) - -{{ canonical_ref() }} {%- endmacro %} {% macro utility() -%}# Utility functions diff --git a/exercises/practice/acronym/.meta/template.j2 b/exercises/practice/acronym/.meta/template.j2 index 70c5d431ca5..c2e35812b1b 100644 --- a/exercises/practice/acronym/.meta/template.j2 +++ b/exercises/practice/acronym/.meta/template.j2 @@ -1,4 +1,5 @@ {%- import "generator_macros.j2" as macros with context -%} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): diff --git a/exercises/practice/acronym/acronym_test.py b/exercises/practice/acronym/acronym_test.py index 444f60cb553..78557dd88b7 100644 --- a/exercises/practice/acronym/acronym_test.py +++ b/exercises/practice/acronym/acronym_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/acronym/canonical-data.json +# File last updated on 2023-07-15 + import unittest from acronym import ( abbreviate, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/acronym/canonical-data.json -# File last updated on 2023-07-14 - class AcronymTest(unittest.TestCase): def test_basic(self): diff --git a/exercises/practice/affine-cipher/affine_cipher_test.py b/exercises/practice/affine-cipher/affine_cipher_test.py index 713e3910232..06e6faf0da9 100644 --- a/exercises/practice/affine-cipher/affine_cipher_test.py +++ b/exercises/practice/affine-cipher/affine_cipher_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/affine-cipher/canonical-data.json +# File last updated on 2023-07-15 + import unittest from affine_cipher import ( @@ -5,10 +9,6 @@ encode, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/affine-cipher/canonical-data.json -# File last updated on 2023-07-14 - class AffineCipherTest(unittest.TestCase): def test_encode_yes(self): diff --git a/exercises/practice/all-your-base/all_your_base_test.py b/exercises/practice/all-your-base/all_your_base_test.py index 182237e4e1f..9a4ca40ccd6 100644 --- a/exercises/practice/all-your-base/all_your_base_test.py +++ b/exercises/practice/all-your-base/all_your_base_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/all-your-base/canonical-data.json +# File last updated on 2023-07-15 + import unittest from all_your_base import ( rebase, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/all-your-base/canonical-data.json -# File last updated on 2023-07-14 - class AllYourBaseTest(unittest.TestCase): def test_single_bit_one_to_decimal(self): diff --git a/exercises/practice/allergies/allergies_test.py b/exercises/practice/allergies/allergies_test.py index fa4e1c55eef..8d6d574e20d 100644 --- a/exercises/practice/allergies/allergies_test.py +++ b/exercises/practice/allergies/allergies_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/allergies/canonical-data.json +# File last updated on 2023-07-15 + import unittest from allergies import ( Allergies, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/allergies/canonical-data.json -# File last updated on 2023-07-14 - class AllergiesTest(unittest.TestCase): def test_eggs_not_allergic_to_anything(self): diff --git a/exercises/practice/alphametics/alphametics_test.py b/exercises/practice/alphametics/alphametics_test.py index 5557b3c8eb5..014df6ceb91 100644 --- a/exercises/practice/alphametics/alphametics_test.py +++ b/exercises/practice/alphametics/alphametics_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/alphametics/canonical-data.json +# File last updated on 2023-07-15 + import unittest from alphametics import ( solve, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/alphametics/canonical-data.json -# File last updated on 2023-07-14 - class AlphameticsTest(unittest.TestCase): def test_puzzle_with_three_letters(self): diff --git a/exercises/practice/anagram/anagram_test.py b/exercises/practice/anagram/anagram_test.py index 85087e85809..69145b9d4f6 100644 --- a/exercises/practice/anagram/anagram_test.py +++ b/exercises/practice/anagram/anagram_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/anagram/canonical-data.json +# File last updated on 2023-07-15 + import unittest from anagram import ( find_anagrams, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/anagram/canonical-data.json -# File last updated on 2023-07-14 - class AnagramTest(unittest.TestCase): def test_no_matches(self): diff --git a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py index ed6907d884d..49831704f07 100644 --- a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py +++ b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json +# File last updated on 2023-07-15 + import unittest from armstrong_numbers import ( is_armstrong_number, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json -# File last updated on 2023-07-14 - class ArmstrongNumbersTest(unittest.TestCase): def test_zero_is_an_armstrong_number(self): diff --git a/exercises/practice/atbash-cipher/atbash_cipher_test.py b/exercises/practice/atbash-cipher/atbash_cipher_test.py index 4e630e3a127..dded351c587 100644 --- a/exercises/practice/atbash-cipher/atbash_cipher_test.py +++ b/exercises/practice/atbash-cipher/atbash_cipher_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/atbash-cipher/canonical-data.json +# File last updated on 2023-07-15 + import unittest from atbash_cipher import ( @@ -5,10 +9,6 @@ encode, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/atbash-cipher/canonical-data.json -# File last updated on 2023-07-14 - class AtbashCipherTest(unittest.TestCase): def test_encode_yes(self): diff --git a/exercises/practice/bank-account/bank_account_test.py b/exercises/practice/bank-account/bank_account_test.py index 9e974da8fae..d58663395b4 100644 --- a/exercises/practice/bank-account/bank_account_test.py +++ b/exercises/practice/bank-account/bank_account_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bank-account/canonical-data.json +# File last updated on 2023-07-15 + import unittest from bank_account import ( BankAccount, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/bank-account/canonical-data.json -# File last updated on 2023-07-14 - class BankAccountTest(unittest.TestCase): def test_newly_opened_account_has_zero_balance(self): diff --git a/exercises/practice/beer-song/beer_song_test.py b/exercises/practice/beer-song/beer_song_test.py index b11f11d1f5d..c1391989fa2 100644 --- a/exercises/practice/beer-song/beer_song_test.py +++ b/exercises/practice/beer-song/beer_song_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/beer-song/canonical-data.json +# File last updated on 2023-07-15 + import unittest from beer_song import ( recite, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/beer-song/canonical-data.json -# File last updated on 2023-07-14 - class BeerSongTest(unittest.TestCase): def test_first_generic_verse(self): diff --git a/exercises/practice/binary-search-tree/binary_search_tree_test.py b/exercises/practice/binary-search-tree/binary_search_tree_test.py index 479cd3411f3..fdb915fe773 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree_test.py +++ b/exercises/practice/binary-search-tree/binary_search_tree_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search-tree/canonical-data.json +# File last updated on 2023-07-15 + import unittest from binary_search_tree import ( @@ -5,10 +9,6 @@ TreeNode, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search-tree/canonical-data.json -# File last updated on 2023-07-14 - class BinarySearchTreeTest(unittest.TestCase): def test_data_is_retained(self): diff --git a/exercises/practice/binary-search/binary_search_test.py b/exercises/practice/binary-search/binary_search_test.py index 325622ad37a..6d094977344 100644 --- a/exercises/practice/binary-search/binary_search_test.py +++ b/exercises/practice/binary-search/binary_search_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search/canonical-data.json +# File last updated on 2023-07-15 + import unittest from binary_search import ( find, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search/canonical-data.json -# File last updated on 2023-07-14 - class BinarySearchTest(unittest.TestCase): def test_finds_a_value_in_an_array_with_one_element(self): diff --git a/exercises/practice/bob/bob_test.py b/exercises/practice/bob/bob_test.py index 67c7f64f7d6..089636fad54 100644 --- a/exercises/practice/bob/bob_test.py +++ b/exercises/practice/bob/bob_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json +# File last updated on 2023-07-15 + import unittest from bob import ( response, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json -# File last updated on 2023-07-14 - class BobTest(unittest.TestCase): def test_stating_something(self): diff --git a/exercises/practice/book-store/book_store_test.py b/exercises/practice/book-store/book_store_test.py index 329e5410f2d..66c1b723100 100644 --- a/exercises/practice/book-store/book_store_test.py +++ b/exercises/practice/book-store/book_store_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/book-store/canonical-data.json +# File last updated on 2023-07-15 + import unittest from book_store import ( total, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/book-store/canonical-data.json -# File last updated on 2023-07-14 - class BookStoreTest(unittest.TestCase): def test_only_a_single_book(self): diff --git a/exercises/practice/bottle-song/bottle_song_test.py b/exercises/practice/bottle-song/bottle_song_test.py index f8c33aac2b7..487a46cedc5 100644 --- a/exercises/practice/bottle-song/bottle_song_test.py +++ b/exercises/practice/bottle-song/bottle_song_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bottle-song/canonical-data.json +# File last updated on 2023-07-15 + import unittest from bottle_song import ( recite, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/bottle-song/canonical-data.json -# File last updated on 2023-07-14 - class BottleSongTest(unittest.TestCase): def test_first_generic_verse(self): diff --git a/exercises/practice/bowling/bowling_test.py b/exercises/practice/bowling/bowling_test.py index 8e04a4c8143..374096e592f 100644 --- a/exercises/practice/bowling/bowling_test.py +++ b/exercises/practice/bowling/bowling_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/bowling/canonical-data.json +# File last updated on 2023-07-15 + import unittest from bowling import ( BowlingGame, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/bowling/canonical-data.json -# File last updated on 2023-07-14 - class BowlingTest(unittest.TestCase): def roll_new_game(self, rolls): diff --git a/exercises/practice/change/change_test.py b/exercises/practice/change/change_test.py index 74fead1196b..b090a3965f6 100644 --- a/exercises/practice/change/change_test.py +++ b/exercises/practice/change/change_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/change/canonical-data.json +# File last updated on 2023-07-15 + import unittest from change import ( find_fewest_coins, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/change/canonical-data.json -# File last updated on 2023-07-14 - class ChangeTest(unittest.TestCase): def test_change_for_1_cent(self): diff --git a/exercises/practice/circular-buffer/circular_buffer_test.py b/exercises/practice/circular-buffer/circular_buffer_test.py index 411df16bbd4..b96a25e15cc 100644 --- a/exercises/practice/circular-buffer/circular_buffer_test.py +++ b/exercises/practice/circular-buffer/circular_buffer_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/circular-buffer/canonical-data.json +# File last updated on 2023-07-15 + import unittest from circular_buffer import ( @@ -6,10 +10,6 @@ BufferFullException, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/circular-buffer/canonical-data.json -# File last updated on 2023-07-14 - class CircularBufferTest(unittest.TestCase): def test_reading_empty_buffer_should_fail(self): diff --git a/exercises/practice/clock/clock_test.py b/exercises/practice/clock/clock_test.py index 4fb17b4b1e7..db4bc919cfd 100644 --- a/exercises/practice/clock/clock_test.py +++ b/exercises/practice/clock/clock_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/clock/canonical-data.json +# File last updated on 2023-07-15 + import unittest from clock import ( Clock, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/clock/canonical-data.json -# File last updated on 2023-07-14 - class ClockTest(unittest.TestCase): # Create A String Representation diff --git a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py index 36c386ee39a..d18bc37719a 100644 --- a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py +++ b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/collatz-conjecture/canonical-data.json +# File last updated on 2023-07-15 + import unittest from collatz_conjecture import ( steps, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/collatz-conjecture/canonical-data.json -# File last updated on 2023-07-14 - class CollatzConjectureTest(unittest.TestCase): def test_zero_steps_for_one(self): diff --git a/exercises/practice/complex-numbers/complex_numbers_test.py b/exercises/practice/complex-numbers/complex_numbers_test.py index 995439763a5..637eb7b90d9 100644 --- a/exercises/practice/complex-numbers/complex_numbers_test.py +++ b/exercises/practice/complex-numbers/complex_numbers_test.py @@ -1,15 +1,15 @@ import math +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/complex-numbers/canonical-data.json +# File last updated on 2023-07-15 + import unittest from complex_numbers import ( ComplexNumber, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/complex-numbers/canonical-data.json -# File last updated on 2023-07-14 - class ComplexNumbersTest(unittest.TestCase): diff --git a/exercises/practice/connect/connect_test.py b/exercises/practice/connect/connect_test.py index a5b6f32444c..239944a5cb3 100644 --- a/exercises/practice/connect/connect_test.py +++ b/exercises/practice/connect/connect_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/connect/canonical-data.json +# File last updated on 2023-07-15 + import unittest from connect import ( ConnectGame, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/connect/canonical-data.json -# File last updated on 2023-07-14 - class ConnectTest(unittest.TestCase): def test_an_empty_board_has_no_winner(self): diff --git a/exercises/practice/crypto-square/crypto_square_test.py b/exercises/practice/crypto-square/crypto_square_test.py index c2845ef562c..08cfa87c7b4 100644 --- a/exercises/practice/crypto-square/crypto_square_test.py +++ b/exercises/practice/crypto-square/crypto_square_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/crypto-square/canonical-data.json +# File last updated on 2023-07-15 + import unittest from crypto_square import ( cipher_text, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/crypto-square/canonical-data.json -# File last updated on 2023-07-14 - class CryptoSquareTest(unittest.TestCase): def test_empty_plaintext_results_in_an_empty_ciphertext(self): diff --git a/exercises/practice/custom-set/custom_set_test.py b/exercises/practice/custom-set/custom_set_test.py index ecad09fdba3..5e6ab124be1 100644 --- a/exercises/practice/custom-set/custom_set_test.py +++ b/exercises/practice/custom-set/custom_set_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/custom-set/canonical-data.json +# File last updated on 2023-07-15 + import unittest from custom_set import ( CustomSet, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/custom-set/canonical-data.json -# File last updated on 2023-07-14 - class CustomSetTest(unittest.TestCase): def test_sets_with_no_elements_are_empty(self): diff --git a/exercises/practice/darts/darts_test.py b/exercises/practice/darts/darts_test.py index 9f9a6a323e4..c417dabd982 100644 --- a/exercises/practice/darts/darts_test.py +++ b/exercises/practice/darts/darts_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/darts/canonical-data.json +# File last updated on 2023-07-15 + import unittest from darts import ( score, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/darts/canonical-data.json -# File last updated on 2023-07-14 - class DartsTest(unittest.TestCase): def test_missed_target(self): diff --git a/exercises/practice/diamond/diamond_test.py b/exercises/practice/diamond/diamond_test.py index 335b0bd7994..504380af426 100644 --- a/exercises/practice/diamond/diamond_test.py +++ b/exercises/practice/diamond/diamond_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/diamond/canonical-data.json +# File last updated on 2023-07-15 + import unittest from diamond import ( rows, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/diamond/canonical-data.json -# File last updated on 2023-07-14 - class DiamondTest(unittest.TestCase): def test_degenerate_case_with_a_single_a_row(self): diff --git a/exercises/practice/difference-of-squares/difference_of_squares_test.py b/exercises/practice/difference-of-squares/difference_of_squares_test.py index d38681f742e..d75e565bef0 100644 --- a/exercises/practice/difference-of-squares/difference_of_squares_test.py +++ b/exercises/practice/difference-of-squares/difference_of_squares_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/difference-of-squares/canonical-data.json +# File last updated on 2023-07-15 + import unittest from difference_of_squares import ( @@ -6,10 +10,6 @@ sum_of_squares, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/difference-of-squares/canonical-data.json -# File last updated on 2023-07-14 - class DifferenceOfSquaresTest(unittest.TestCase): def test_square_of_sum_1(self): diff --git a/exercises/practice/diffie-hellman/diffie_hellman_test.py b/exercises/practice/diffie-hellman/diffie_hellman_test.py index 60c514d9f81..ce5819821c0 100644 --- a/exercises/practice/diffie-hellman/diffie_hellman_test.py +++ b/exercises/practice/diffie-hellman/diffie_hellman_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/diffie-hellman/canonical-data.json +# File last updated on 2023-07-15 + import unittest from diffie_hellman import ( @@ -6,10 +10,6 @@ secret, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/diffie-hellman/canonical-data.json -# File last updated on 2023-07-14 - class DiffieHellmanTest(unittest.TestCase): def test_private_key_is_greater_than_1_and_less_than_p(self): diff --git a/exercises/practice/dnd-character/dnd_character_test.py b/exercises/practice/dnd-character/dnd_character_test.py index d97cbfda62d..f158f257a80 100644 --- a/exercises/practice/dnd-character/dnd_character_test.py +++ b/exercises/practice/dnd-character/dnd_character_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/dnd-character/canonical-data.json +# File last updated on 2023-07-15 + import unittest from dnd_character import ( @@ -5,10 +9,6 @@ modifier, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/dnd-character/canonical-data.json -# File last updated on 2023-07-14 - class DndCharacterTest(unittest.TestCase): def test_ability_modifier_for_score_3_is_n4(self): diff --git a/exercises/practice/dominoes/dominoes_test.py b/exercises/practice/dominoes/dominoes_test.py index a9d82512c2c..78befc761b1 100644 --- a/exercises/practice/dominoes/dominoes_test.py +++ b/exercises/practice/dominoes/dominoes_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/dominoes/canonical-data.json +# File last updated on 2023-07-15 + import unittest from dominoes import ( can_chain, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/dominoes/canonical-data.json -# File last updated on 2023-07-14 - class DominoesTest(unittest.TestCase): def test_empty_input_empty_output(self): diff --git a/exercises/practice/etl/etl_test.py b/exercises/practice/etl/etl_test.py index b2ce956fe4e..d8e587bc79c 100644 --- a/exercises/practice/etl/etl_test.py +++ b/exercises/practice/etl/etl_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/etl/canonical-data.json +# File last updated on 2023-07-15 + import unittest from etl import ( transform, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/etl/canonical-data.json -# File last updated on 2023-07-14 - class EtlTest(unittest.TestCase): def test_single_letter(self): diff --git a/exercises/practice/flatten-array/flatten_array_test.py b/exercises/practice/flatten-array/flatten_array_test.py index 8271ce1d068..5d73db6b6e0 100644 --- a/exercises/practice/flatten-array/flatten_array_test.py +++ b/exercises/practice/flatten-array/flatten_array_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/flatten-array/canonical-data.json +# File last updated on 2023-07-15 + import unittest from flatten_array import ( flatten, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/flatten-array/canonical-data.json -# File last updated on 2023-07-14 - class FlattenArrayTest(unittest.TestCase): def test_empty(self): diff --git a/exercises/practice/food-chain/food_chain_test.py b/exercises/practice/food-chain/food_chain_test.py index 195c1ab1174..d330574c0bd 100644 --- a/exercises/practice/food-chain/food_chain_test.py +++ b/exercises/practice/food-chain/food_chain_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/food-chain/canonical-data.json +# File last updated on 2023-07-15 + import unittest from food_chain import ( recite, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/food-chain/canonical-data.json -# File last updated on 2023-07-14 - class FoodChainTest(unittest.TestCase): def test_fly(self): diff --git a/exercises/practice/forth/forth_test.py b/exercises/practice/forth/forth_test.py index 07778ceb3aa..458ce476569 100644 --- a/exercises/practice/forth/forth_test.py +++ b/exercises/practice/forth/forth_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/forth/canonical-data.json +# File last updated on 2023-07-15 + import unittest from forth import ( @@ -5,10 +9,6 @@ StackUnderflowError, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/forth/canonical-data.json -# File last updated on 2023-07-14 - class ForthTest(unittest.TestCase): def test_parsing_and_numbers_numbers_just_get_pushed_onto_the_stack(self): diff --git a/exercises/practice/gigasecond/gigasecond_test.py b/exercises/practice/gigasecond/gigasecond_test.py index c1e24d4bc44..74017949aa1 100644 --- a/exercises/practice/gigasecond/gigasecond_test.py +++ b/exercises/practice/gigasecond/gigasecond_test.py @@ -1,14 +1,15 @@ from datetime import datetime + +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/gigasecond/canonical-data.json +# File last updated on 2023-07-15 + import unittest from gigasecond import ( add, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/gigasecond/canonical-data.json -# File last updated on 2023-07-14 - class GigasecondTest(unittest.TestCase): def test_date_only_specification_of_time(self): diff --git a/exercises/practice/go-counting/go_counting_test.py b/exercises/practice/go-counting/go_counting_test.py index e0920459cbe..81886ca8762 100644 --- a/exercises/practice/go-counting/go_counting_test.py +++ b/exercises/practice/go-counting/go_counting_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/go-counting/canonical-data.json +# File last updated on 2023-07-15 + import unittest from go_counting import ( @@ -7,10 +11,6 @@ NONE, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/go-counting/canonical-data.json -# File last updated on 2023-07-14 - class GoCountingTest(unittest.TestCase): def test_black_corner_territory_on_5x5_board(self): diff --git a/exercises/practice/grade-school/grade_school_test.py b/exercises/practice/grade-school/grade_school_test.py index 19509de6537..2d2b4f5604e 100644 --- a/exercises/practice/grade-school/grade_school_test.py +++ b/exercises/practice/grade-school/grade_school_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/grade-school/canonical-data.json +# File last updated on 2023-07-15 + import unittest from grade_school import ( School, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/grade-school/canonical-data.json -# File last updated on 2023-07-14 - class GradeSchoolTest(unittest.TestCase): def test_roster_is_empty_when_no_student_is_added(self): diff --git a/exercises/practice/grains/grains_test.py b/exercises/practice/grains/grains_test.py index 5a4de3a8774..e9d72f6a46d 100644 --- a/exercises/practice/grains/grains_test.py +++ b/exercises/practice/grains/grains_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/grains/canonical-data.json +# File last updated on 2023-07-15 + import unittest from grains import ( @@ -5,10 +9,6 @@ total, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/grains/canonical-data.json -# File last updated on 2023-07-14 - class GrainsTest(unittest.TestCase): def test_grains_on_square_1(self): diff --git a/exercises/practice/grep/grep_test.py b/exercises/practice/grep/grep_test.py index ff81e36d8dd..aff476d2394 100644 --- a/exercises/practice/grep/grep_test.py +++ b/exercises/practice/grep/grep_test.py @@ -1,12 +1,12 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/grep/canonical-data.json +# File last updated on 2023-07-15 + import unittest from grep import ( grep, ) - -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/grep/canonical-data.json -# File last updated on 2023-07-14 import io from unittest import mock diff --git a/exercises/practice/hamming/hamming_test.py b/exercises/practice/hamming/hamming_test.py index e9fcadea9ed..d8d5c138a9a 100644 --- a/exercises/practice/hamming/hamming_test.py +++ b/exercises/practice/hamming/hamming_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/hamming/canonical-data.json +# File last updated on 2023-07-15 + import unittest from hamming import ( distance, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/hamming/canonical-data.json -# File last updated on 2023-07-14 - class HammingTest(unittest.TestCase): def test_empty_strands(self): diff --git a/exercises/practice/high-scores/high_scores_test.py b/exercises/practice/high-scores/high_scores_test.py index ec716a489cf..d1e4b71d6f7 100644 --- a/exercises/practice/high-scores/high_scores_test.py +++ b/exercises/practice/high-scores/high_scores_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/high-scores/canonical-data.json +# File last updated on 2023-07-15 + import unittest from high_scores import ( HighScores, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/high-scores/canonical-data.json -# File last updated on 2023-07-14 - class HighScoresTest(unittest.TestCase): def test_list_of_scores(self): diff --git a/exercises/practice/house/house_test.py b/exercises/practice/house/house_test.py index 6ad16a0ccb7..a42b3950490 100644 --- a/exercises/practice/house/house_test.py +++ b/exercises/practice/house/house_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/house/canonical-data.json +# File last updated on 2023-07-15 + import unittest from house import ( recite, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/house/canonical-data.json -# File last updated on 2023-07-14 - class HouseTest(unittest.TestCase): def test_verse_one_the_house_that_jack_built(self): diff --git a/exercises/practice/isbn-verifier/isbn_verifier_test.py b/exercises/practice/isbn-verifier/isbn_verifier_test.py index aa3d954d228..22fdd0a9b77 100644 --- a/exercises/practice/isbn-verifier/isbn_verifier_test.py +++ b/exercises/practice/isbn-verifier/isbn_verifier_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/isbn-verifier/canonical-data.json +# File last updated on 2023-07-15 + import unittest from isbn_verifier import ( is_valid, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/isbn-verifier/canonical-data.json -# File last updated on 2023-07-14 - class IsbnVerifierTest(unittest.TestCase): def test_valid_isbn(self): diff --git a/exercises/practice/isogram/isogram_test.py b/exercises/practice/isogram/isogram_test.py index 99940e3ddfc..b7427a7d446 100644 --- a/exercises/practice/isogram/isogram_test.py +++ b/exercises/practice/isogram/isogram_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/isogram/canonical-data.json +# File last updated on 2023-07-15 + import unittest from isogram import ( is_isogram, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/isogram/canonical-data.json -# File last updated on 2023-07-14 - class IsogramTest(unittest.TestCase): def test_empty_string(self): diff --git a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py index 3a7f4c0dcca..24b02c08fb5 100644 --- a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py +++ b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/killer-sudoku-helper/canonical-data.json +# File last updated on 2023-07-15 + import unittest from killer_sudoku_helper import ( combinations, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/killer-sudoku-helper/canonical-data.json -# File last updated on 2023-07-14 - class KillerSudokuHelperTest(unittest.TestCase): def test_1(self): diff --git a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py index 5773dfa3905..83d4978e145 100644 --- a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py +++ b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/kindergarten-garden/canonical-data.json +# File last updated on 2023-07-15 + import unittest from kindergarten_garden import ( Garden, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/kindergarten-garden/canonical-data.json -# File last updated on 2023-07-14 - class KindergartenGardenTest(unittest.TestCase): def test_partial_garden_garden_with_single_student(self): diff --git a/exercises/practice/knapsack/knapsack_test.py b/exercises/practice/knapsack/knapsack_test.py index 20429bb263d..a4120237840 100644 --- a/exercises/practice/knapsack/knapsack_test.py +++ b/exercises/practice/knapsack/knapsack_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/knapsack/canonical-data.json +# File last updated on 2023-07-15 + import unittest from knapsack import ( maximum_value, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/knapsack/canonical-data.json -# File last updated on 2023-07-14 - class KnapsackTest(unittest.TestCase): def test_no_items(self): diff --git a/exercises/practice/largest-series-product/largest_series_product_test.py b/exercises/practice/largest-series-product/largest_series_product_test.py index 8b02dfbbb7e..e75f022d63d 100644 --- a/exercises/practice/largest-series-product/largest_series_product_test.py +++ b/exercises/practice/largest-series-product/largest_series_product_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/largest-series-product/canonical-data.json +# File last updated on 2023-07-15 + import unittest from largest_series_product import ( largest_product, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/largest-series-product/canonical-data.json -# File last updated on 2023-07-14 - class LargestSeriesProductTest(unittest.TestCase): def test_finds_the_largest_product_if_span_equals_length(self): diff --git a/exercises/practice/leap/leap_test.py b/exercises/practice/leap/leap_test.py index 2b25b36a6a7..d8c508de5e8 100644 --- a/exercises/practice/leap/leap_test.py +++ b/exercises/practice/leap/leap_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/leap/canonical-data.json +# File last updated on 2023-07-15 + import unittest from leap import ( leap_year, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/leap/canonical-data.json -# File last updated on 2023-07-14 - class LeapTest(unittest.TestCase): def test_year_not_divisible_by_4_in_common_year(self): diff --git a/exercises/practice/ledger/ledger_test.py b/exercises/practice/ledger/ledger_test.py index 2c51a4d7715..e8432bb5181 100644 --- a/exercises/practice/ledger/ledger_test.py +++ b/exercises/practice/ledger/ledger_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/ledger/canonical-data.json +# File last updated on 2023-07-15 + import unittest from ledger import ( @@ -5,10 +9,6 @@ create_entry, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/ledger/canonical-data.json -# File last updated on 2023-07-14 - class LedgerTest(unittest.TestCase): maxDiff = 5000 diff --git a/exercises/practice/linked-list/linked_list_test.py b/exercises/practice/linked-list/linked_list_test.py index c0b44de4d9e..9a196084e6f 100644 --- a/exercises/practice/linked-list/linked_list_test.py +++ b/exercises/practice/linked-list/linked_list_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/linked-list/canonical-data.json +# File last updated on 2023-07-15 + import unittest from linked_list import ( LinkedList, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/linked-list/canonical-data.json -# File last updated on 2023-07-14 - class LinkedListTest(unittest.TestCase): def test_pop_gets_element_from_the_list(self): diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index 7bd60f4f211..4bff0080b8a 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/list-ops/canonical-data.json +# File last updated on 2023-07-15 + import unittest from list_ops import ( @@ -11,10 +15,6 @@ map as list_ops_map, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/list-ops/canonical-data.json -# File last updated on 2023-07-14 - class ListOpsTest(unittest.TestCase): def test_append_empty_lists(self): diff --git a/exercises/practice/luhn/luhn_test.py b/exercises/practice/luhn/luhn_test.py index dd309dd72f6..f6b078cca39 100644 --- a/exercises/practice/luhn/luhn_test.py +++ b/exercises/practice/luhn/luhn_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/luhn/canonical-data.json +# File last updated on 2023-07-15 + import unittest from luhn import ( Luhn, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/luhn/canonical-data.json -# File last updated on 2023-07-14 - class LuhnTest(unittest.TestCase): def test_single_digit_strings_can_not_be_valid(self): diff --git a/exercises/practice/markdown/markdown_test.py b/exercises/practice/markdown/markdown_test.py index b79353cdd7a..4501adb7872 100644 --- a/exercises/practice/markdown/markdown_test.py +++ b/exercises/practice/markdown/markdown_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/markdown/canonical-data.json +# File last updated on 2023-07-15 + import unittest from markdown import ( parse, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/markdown/canonical-data.json -# File last updated on 2023-07-14 - class MarkdownTest(unittest.TestCase): def test_parses_normal_text_as_a_paragraph(self): diff --git a/exercises/practice/matching-brackets/matching_brackets_test.py b/exercises/practice/matching-brackets/matching_brackets_test.py index b83c341a296..ae59ead1fca 100644 --- a/exercises/practice/matching-brackets/matching_brackets_test.py +++ b/exercises/practice/matching-brackets/matching_brackets_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/matching-brackets/canonical-data.json +# File last updated on 2023-07-15 + import unittest from matching_brackets import ( is_paired, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/matching-brackets/canonical-data.json -# File last updated on 2023-07-14 - class MatchingBracketsTest(unittest.TestCase): def test_paired_square_brackets(self): diff --git a/exercises/practice/matrix/matrix_test.py b/exercises/practice/matrix/matrix_test.py index 8573ccf9a6a..49e1ea90228 100644 --- a/exercises/practice/matrix/matrix_test.py +++ b/exercises/practice/matrix/matrix_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/matrix/canonical-data.json +# File last updated on 2023-07-15 + import unittest from matrix import ( Matrix, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/matrix/canonical-data.json -# File last updated on 2023-07-14 - class MatrixTest(unittest.TestCase): def test_extract_row_from_one_number_matrix(self): diff --git a/exercises/practice/meetup/meetup_test.py b/exercises/practice/meetup/meetup_test.py index a9b3721c03f..24695176bd5 100644 --- a/exercises/practice/meetup/meetup_test.py +++ b/exercises/practice/meetup/meetup_test.py @@ -1,4 +1,9 @@ from datetime import date + +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/meetup/canonical-data.json +# File last updated on 2023-07-15 + import unittest from meetup import ( @@ -6,10 +11,6 @@ MeetupDayException, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/meetup/canonical-data.json -# File last updated on 2023-07-14 - class MeetupTest(unittest.TestCase): def test_when_teenth_monday_is_the_13th_the_first_day_of_the_teenth_week(self): diff --git a/exercises/practice/minesweeper/minesweeper_test.py b/exercises/practice/minesweeper/minesweeper_test.py index 32927a95efe..763281d66e1 100644 --- a/exercises/practice/minesweeper/minesweeper_test.py +++ b/exercises/practice/minesweeper/minesweeper_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/minesweeper/canonical-data.json +# File last updated on 2023-07-15 + import unittest from minesweeper import ( annotate, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/minesweeper/canonical-data.json -# File last updated on 2023-07-14 - class MinesweeperTest(unittest.TestCase): def test_no_rows(self): diff --git a/exercises/practice/nth-prime/nth_prime_test.py b/exercises/practice/nth-prime/nth_prime_test.py index 50a68a05e2b..19c68e55f3c 100644 --- a/exercises/practice/nth-prime/nth_prime_test.py +++ b/exercises/practice/nth-prime/nth_prime_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/nth-prime/canonical-data.json +# File last updated on 2023-07-15 + import unittest from nth_prime import ( prime, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/nth-prime/canonical-data.json -# File last updated on 2023-07-14 - def prime_range(n): """Returns a list of the first n primes""" diff --git a/exercises/practice/ocr-numbers/ocr_numbers_test.py b/exercises/practice/ocr-numbers/ocr_numbers_test.py index d3a11134ddf..1b74ca2893d 100644 --- a/exercises/practice/ocr-numbers/ocr_numbers_test.py +++ b/exercises/practice/ocr-numbers/ocr_numbers_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/ocr-numbers/canonical-data.json +# File last updated on 2023-07-15 + import unittest from ocr_numbers import ( convert, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/ocr-numbers/canonical-data.json -# File last updated on 2023-07-14 - class OcrNumbersTest(unittest.TestCase): def test_recognizes_0(self): diff --git a/exercises/practice/palindrome-products/palindrome_products_test.py b/exercises/practice/palindrome-products/palindrome_products_test.py index e748b8703c2..7fc2c61bfa5 100644 --- a/exercises/practice/palindrome-products/palindrome_products_test.py +++ b/exercises/practice/palindrome-products/palindrome_products_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/palindrome-products/canonical-data.json +# File last updated on 2023-07-15 + import unittest from palindrome_products import ( @@ -5,10 +9,6 @@ smallest, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/palindrome-products/canonical-data.json -# File last updated on 2023-07-14 - class PalindromeProductsTest(unittest.TestCase): def test_find_the_smallest_palindrome_from_single_digit_factors(self): diff --git a/exercises/practice/pangram/pangram_test.py b/exercises/practice/pangram/pangram_test.py index 2e5179acee9..e441ac39586 100644 --- a/exercises/practice/pangram/pangram_test.py +++ b/exercises/practice/pangram/pangram_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pangram/canonical-data.json +# File last updated on 2023-07-15 + import unittest from pangram import ( is_pangram, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/pangram/canonical-data.json -# File last updated on 2023-07-14 - class PangramTest(unittest.TestCase): def test_empty_sentence(self): diff --git a/exercises/practice/pascals-triangle/pascals_triangle_test.py b/exercises/practice/pascals-triangle/pascals_triangle_test.py index a0b253af3e6..e7979a15a09 100644 --- a/exercises/practice/pascals-triangle/pascals_triangle_test.py +++ b/exercises/practice/pascals-triangle/pascals_triangle_test.py @@ -1,14 +1,15 @@ import sys + +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pascals-triangle/canonical-data.json +# File last updated on 2023-07-15 + import unittest from pascals_triangle import ( rows, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/pascals-triangle/canonical-data.json -# File last updated on 2023-07-14 - TRIANGLE = [ [1], [1, 1], diff --git a/exercises/practice/perfect-numbers/perfect_numbers_test.py b/exercises/practice/perfect-numbers/perfect_numbers_test.py index 512600f12de..80479076d23 100644 --- a/exercises/practice/perfect-numbers/perfect_numbers_test.py +++ b/exercises/practice/perfect-numbers/perfect_numbers_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/perfect-numbers/canonical-data.json +# File last updated on 2023-07-15 + import unittest from perfect_numbers import ( classify, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/perfect-numbers/canonical-data.json -# File last updated on 2023-07-14 - class PerfectNumbersTest(unittest.TestCase): def test_smallest_perfect_number_is_classified_correctly(self): diff --git a/exercises/practice/phone-number/phone_number_test.py b/exercises/practice/phone-number/phone_number_test.py index 1002c6b7a1c..4b887e8bbbd 100644 --- a/exercises/practice/phone-number/phone_number_test.py +++ b/exercises/practice/phone-number/phone_number_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/phone-number/canonical-data.json +# File last updated on 2023-07-15 + import unittest from phone_number import ( PhoneNumber, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/phone-number/canonical-data.json -# File last updated on 2023-07-14 - class PhoneNumberTest(unittest.TestCase): def test_cleans_the_number(self): diff --git a/exercises/practice/pig-latin/pig_latin_test.py b/exercises/practice/pig-latin/pig_latin_test.py index 997f0284d54..39894d69434 100644 --- a/exercises/practice/pig-latin/pig_latin_test.py +++ b/exercises/practice/pig-latin/pig_latin_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json +# File last updated on 2023-07-15 + import unittest from pig_latin import ( translate, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json -# File last updated on 2023-07-14 - class PigLatinTest(unittest.TestCase): def test_word_beginning_with_a(self): diff --git a/exercises/practice/poker/poker_test.py b/exercises/practice/poker/poker_test.py index f30462f897f..1b1332dad03 100644 --- a/exercises/practice/poker/poker_test.py +++ b/exercises/practice/poker/poker_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/poker/canonical-data.json +# File last updated on 2023-07-15 + import unittest from poker import ( best_hands, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/poker/canonical-data.json -# File last updated on 2023-07-14 - class PokerTest(unittest.TestCase): def test_single_hand_always_wins(self): diff --git a/exercises/practice/pov/pov_test.py b/exercises/practice/pov/pov_test.py index 93b622d72a4..c10101fa2ff 100644 --- a/exercises/practice/pov/pov_test.py +++ b/exercises/practice/pov/pov_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pov/canonical-data.json +# File last updated on 2023-07-15 + import unittest from pov import ( Tree, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/pov/canonical-data.json -# File last updated on 2023-07-14 - class PovTest(unittest.TestCase): def test_results_in_the_same_tree_if_the_input_tree_is_a_singleton(self): diff --git a/exercises/practice/prime-factors/prime_factors_test.py b/exercises/practice/prime-factors/prime_factors_test.py index 187c4f2f960..ada03fe4f74 100644 --- a/exercises/practice/prime-factors/prime_factors_test.py +++ b/exercises/practice/prime-factors/prime_factors_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/prime-factors/canonical-data.json +# File last updated on 2023-07-15 + import unittest from prime_factors import ( factors, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/prime-factors/canonical-data.json -# File last updated on 2023-07-14 - class PrimeFactorsTest(unittest.TestCase): def test_no_factors(self): diff --git a/exercises/practice/protein-translation/protein_translation_test.py b/exercises/practice/protein-translation/protein_translation_test.py index 464d7f0ddd4..e79fde21105 100644 --- a/exercises/practice/protein-translation/protein_translation_test.py +++ b/exercises/practice/protein-translation/protein_translation_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/protein-translation/canonical-data.json +# File last updated on 2023-07-15 + import unittest from protein_translation import ( proteins, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/protein-translation/canonical-data.json -# File last updated on 2023-07-14 - class ProteinTranslationTest(unittest.TestCase): def test_methionine_rna_sequence(self): diff --git a/exercises/practice/proverb/proverb_test.py b/exercises/practice/proverb/proverb_test.py index 674cc26dc04..9a86be909a0 100644 --- a/exercises/practice/proverb/proverb_test.py +++ b/exercises/practice/proverb/proverb_test.py @@ -1,12 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/proverb/canonical-data.json +# File last updated on 2023-07-15 + import unittest from proverb import ( proverb, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/proverb/canonical-data.json -# File last updated on 2023-07-14 # PLEASE TAKE NOTE: Expected result lists for these test cases use **implicit line joining.** # A new line in a result list below **does not** always equal a new list element. # Check comma placement carefully! diff --git a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py index b4b89e2d8a9..663256cf8c9 100644 --- a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py +++ b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/pythagorean-triplet/canonical-data.json +# File last updated on 2023-07-15 + import unittest from pythagorean_triplet import ( triplets_with_sum, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/pythagorean-triplet/canonical-data.json -# File last updated on 2023-07-14 - class PythagoreanTripletTest(unittest.TestCase): def test_triplets_whose_sum_is_12(self): diff --git a/exercises/practice/queen-attack/queen_attack_test.py b/exercises/practice/queen-attack/queen_attack_test.py index 52f994fc392..127d506817b 100644 --- a/exercises/practice/queen-attack/queen_attack_test.py +++ b/exercises/practice/queen-attack/queen_attack_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/queen-attack/canonical-data.json +# File last updated on 2023-07-15 + import unittest from queen_attack import ( Queen, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/queen-attack/canonical-data.json -# File last updated on 2023-07-14 - class QueenAttackTest(unittest.TestCase): # Test creation of Queens with valid and invalid positions diff --git a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py index fb546d4ab24..c2600804b71 100644 --- a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py +++ b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rail-fence-cipher/canonical-data.json +# File last updated on 2023-07-15 + import unittest from rail_fence_cipher import ( @@ -5,10 +9,6 @@ encode, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/rail-fence-cipher/canonical-data.json -# File last updated on 2023-07-14 - class RailFenceCipherTest(unittest.TestCase): def test_encode_with_two_rails(self): diff --git a/exercises/practice/raindrops/raindrops_test.py b/exercises/practice/raindrops/raindrops_test.py index a196eb32af1..089b5ded67b 100644 --- a/exercises/practice/raindrops/raindrops_test.py +++ b/exercises/practice/raindrops/raindrops_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/raindrops/canonical-data.json +# File last updated on 2023-07-15 + import unittest from raindrops import ( convert, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/raindrops/canonical-data.json -# File last updated on 2023-07-14 - class RaindropsTest(unittest.TestCase): def test_the_sound_for_1_is_1(self): diff --git a/exercises/practice/rational-numbers/rational_numbers_test.py b/exercises/practice/rational-numbers/rational_numbers_test.py index 3b1e44a6234..031361d3118 100644 --- a/exercises/practice/rational-numbers/rational_numbers_test.py +++ b/exercises/practice/rational-numbers/rational_numbers_test.py @@ -1,14 +1,15 @@ from __future__ import division + +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rational-numbers/canonical-data.json +# File last updated on 2023-07-15 + import unittest from rational_numbers import ( Rational, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/rational-numbers/canonical-data.json -# File last updated on 2023-07-14 - class RationalNumbersTest(unittest.TestCase): diff --git a/exercises/practice/react/react_test.py b/exercises/practice/react/react_test.py index 5d4f22bcc69..0a93e4d23cc 100644 --- a/exercises/practice/react/react_test.py +++ b/exercises/practice/react/react_test.py @@ -1,5 +1,9 @@ from functools import partial +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/react/canonical-data.json +# File last updated on 2023-07-15 + import unittest from react import ( @@ -7,10 +11,6 @@ ComputeCell, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/react/canonical-data.json -# File last updated on 2023-07-14 - class ReactTest(unittest.TestCase): def test_input_cells_have_a_value(self): diff --git a/exercises/practice/rectangles/rectangles_test.py b/exercises/practice/rectangles/rectangles_test.py index 72cdae7cc27..19988c7bd5b 100644 --- a/exercises/practice/rectangles/rectangles_test.py +++ b/exercises/practice/rectangles/rectangles_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rectangles/canonical-data.json +# File last updated on 2023-07-15 + import unittest from rectangles import ( rectangles, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/rectangles/canonical-data.json -# File last updated on 2023-07-14 - class RectanglesTest(unittest.TestCase): def test_no_rows(self): diff --git a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py index 9ace6d64b7b..265135639bc 100644 --- a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py +++ b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-duo/canonical-data.json +# File last updated on 2023-07-15 + import unittest from resistor_color_duo import ( value, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-duo/canonical-data.json -# File last updated on 2023-07-14 - class ResistorColorDuoTest(unittest.TestCase): def test_brown_and_black(self): diff --git a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py index 31901c5cfad..a566be48af1 100644 --- a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py +++ b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-trio/canonical-data.json +# File last updated on 2023-07-15 + import unittest from resistor_color_trio import ( label, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-trio/canonical-data.json -# File last updated on 2023-07-14 - class ResistorColorTrioTest(unittest.TestCase): def test_orange_and_orange_and_black(self): diff --git a/exercises/practice/resistor-color/resistor_color_test.py b/exercises/practice/resistor-color/resistor_color_test.py index bb180385ceb..c8648ea1d40 100644 --- a/exercises/practice/resistor-color/resistor_color_test.py +++ b/exercises/practice/resistor-color/resistor_color_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color/canonical-data.json +# File last updated on 2023-07-15 + import unittest from resistor_color import ( @@ -5,10 +9,6 @@ colors, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color/canonical-data.json -# File last updated on 2023-07-14 - class ResistorColorTest(unittest.TestCase): def test_black(self): diff --git a/exercises/practice/rest-api/rest_api_test.py b/exercises/practice/rest-api/rest_api_test.py index 4a00073ddae..72ba438426f 100644 --- a/exercises/practice/rest-api/rest_api_test.py +++ b/exercises/practice/rest-api/rest_api_test.py @@ -1,12 +1,12 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rest-api/canonical-data.json +# File last updated on 2023-07-15 + import unittest from rest_api import ( RestAPI, ) - -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/rest-api/canonical-data.json -# File last updated on 2023-07-14 import json diff --git a/exercises/practice/reverse-string/reverse_string_test.py b/exercises/practice/reverse-string/reverse_string_test.py index cedc7f890c8..8fe8df59979 100644 --- a/exercises/practice/reverse-string/reverse_string_test.py +++ b/exercises/practice/reverse-string/reverse_string_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/reverse-string/canonical-data.json +# File last updated on 2023-07-15 + import unittest from reverse_string import ( reverse, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/reverse-string/canonical-data.json -# File last updated on 2023-07-14 - class ReverseStringTest(unittest.TestCase): def test_an_empty_string(self): diff --git a/exercises/practice/rna-transcription/rna_transcription_test.py b/exercises/practice/rna-transcription/rna_transcription_test.py index 2e58d06b934..cb6cf870547 100644 --- a/exercises/practice/rna-transcription/rna_transcription_test.py +++ b/exercises/practice/rna-transcription/rna_transcription_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rna-transcription/canonical-data.json +# File last updated on 2023-07-15 + import unittest from rna_transcription import ( to_rna, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/rna-transcription/canonical-data.json -# File last updated on 2023-07-14 - class RnaTranscriptionTest(unittest.TestCase): def test_empty_rna_sequence(self): diff --git a/exercises/practice/robot-simulator/robot_simulator_test.py b/exercises/practice/robot-simulator/robot_simulator_test.py index 2d545176810..8349b7101dc 100644 --- a/exercises/practice/robot-simulator/robot_simulator_test.py +++ b/exercises/practice/robot-simulator/robot_simulator_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/robot-simulator/canonical-data.json +# File last updated on 2023-07-15 + import unittest from robot_simulator import ( @@ -8,10 +12,6 @@ WEST, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/robot-simulator/canonical-data.json -# File last updated on 2023-07-14 - class RobotSimulatorTest(unittest.TestCase): diff --git a/exercises/practice/roman-numerals/roman_numerals_test.py b/exercises/practice/roman-numerals/roman_numerals_test.py index 51ff27cb131..13b3245a215 100644 --- a/exercises/practice/roman-numerals/roman_numerals_test.py +++ b/exercises/practice/roman-numerals/roman_numerals_test.py @@ -1,12 +1,14 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/roman-numerals/canonical-data.json +# File last updated on 2023-07-15 + import unittest from roman_numerals import ( roman, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/roman-numerals/canonical-data.json -# File last updated on 2023-07-14 + class RomanNumeralsTest(unittest.TestCase): def test_1_is_i(self): self.assertEqual(roman(1), "I") diff --git a/exercises/practice/rotational-cipher/rotational_cipher_test.py b/exercises/practice/rotational-cipher/rotational_cipher_test.py index 21dbcf8ab72..802b54f9e1f 100644 --- a/exercises/practice/rotational-cipher/rotational_cipher_test.py +++ b/exercises/practice/rotational-cipher/rotational_cipher_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/rotational-cipher/canonical-data.json +# File last updated on 2023-07-15 + import unittest from rotational_cipher import ( rotate, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/rotational-cipher/canonical-data.json -# File last updated on 2023-07-14 - class RotationalCipherTest(unittest.TestCase): def test_rotate_a_by_0_same_output_as_input(self): diff --git a/exercises/practice/run-length-encoding/run_length_encoding_test.py b/exercises/practice/run-length-encoding/run_length_encoding_test.py index 251c5f5ca88..18f883a29eb 100644 --- a/exercises/practice/run-length-encoding/run_length_encoding_test.py +++ b/exercises/practice/run-length-encoding/run_length_encoding_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/run-length-encoding/canonical-data.json +# File last updated on 2023-07-15 + import unittest from run_length_encoding import ( @@ -5,10 +9,6 @@ decode, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/run-length-encoding/canonical-data.json -# File last updated on 2023-07-14 - class RunLengthEncodingTest(unittest.TestCase): def test_encode_empty_string(self): diff --git a/exercises/practice/saddle-points/saddle_points_test.py b/exercises/practice/saddle-points/saddle_points_test.py index 4a33d1922bf..fe966bae0ff 100644 --- a/exercises/practice/saddle-points/saddle_points_test.py +++ b/exercises/practice/saddle-points/saddle_points_test.py @@ -5,16 +5,16 @@ ValueError with a meaningful error message if the matrix turns out to be irregular. """ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/saddle-points/canonical-data.json +# File last updated on 2023-07-15 + import unittest from saddle_points import ( saddle_points, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/saddle-points/canonical-data.json -# File last updated on 2023-07-14 - def sorted_points(point_list): return sorted(point_list, key=lambda p: (p["row"], p["column"])) diff --git a/exercises/practice/satellite/satellite_test.py b/exercises/practice/satellite/satellite_test.py index c1629a9ce41..60a34a7d65d 100644 --- a/exercises/practice/satellite/satellite_test.py +++ b/exercises/practice/satellite/satellite_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/satellite/canonical-data.json +# File last updated on 2023-07-15 + import unittest from satellite import ( tree_from_traversals, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/satellite/canonical-data.json -# File last updated on 2023-07-14 - class SatelliteTest(unittest.TestCase): def test_empty_tree(self): diff --git a/exercises/practice/say/say_test.py b/exercises/practice/say/say_test.py index 58f9a04a9d1..6d54c85fa44 100644 --- a/exercises/practice/say/say_test.py +++ b/exercises/practice/say/say_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/say/canonical-data.json +# File last updated on 2023-07-15 + import unittest from say import ( say, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/say/canonical-data.json -# File last updated on 2023-07-14 - class SayTest(unittest.TestCase): def test_zero(self): diff --git a/exercises/practice/scale-generator/scale_generator_test.py b/exercises/practice/scale-generator/scale_generator_test.py index 48f94f3d810..cec6aa34ef3 100644 --- a/exercises/practice/scale-generator/scale_generator_test.py +++ b/exercises/practice/scale-generator/scale_generator_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/scale-generator/canonical-data.json +# File last updated on 2023-07-15 + import unittest from scale_generator import ( Scale, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/scale-generator/canonical-data.json -# File last updated on 2023-07-14 - class ScaleGeneratorTest(unittest.TestCase): diff --git a/exercises/practice/scrabble-score/scrabble_score_test.py b/exercises/practice/scrabble-score/scrabble_score_test.py index 1b95e627cba..5a5dca5c5cf 100644 --- a/exercises/practice/scrabble-score/scrabble_score_test.py +++ b/exercises/practice/scrabble-score/scrabble_score_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/scrabble-score/canonical-data.json +# File last updated on 2023-07-15 + import unittest from scrabble_score import ( score, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/scrabble-score/canonical-data.json -# File last updated on 2023-07-14 - class ScrabbleScoreTest(unittest.TestCase): def test_lowercase_letter(self): diff --git a/exercises/practice/secret-handshake/secret_handshake_test.py b/exercises/practice/secret-handshake/secret_handshake_test.py index 6abf64d452d..52f6f9116b8 100644 --- a/exercises/practice/secret-handshake/secret_handshake_test.py +++ b/exercises/practice/secret-handshake/secret_handshake_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/secret-handshake/canonical-data.json +# File last updated on 2023-07-15 + import unittest from secret_handshake import ( commands, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/secret-handshake/canonical-data.json -# File last updated on 2023-07-14 - class SecretHandshakeTest(unittest.TestCase): def test_wink_for_1(self): diff --git a/exercises/practice/series/series_test.py b/exercises/practice/series/series_test.py index 9c6ee8b8c14..938ff7956d5 100644 --- a/exercises/practice/series/series_test.py +++ b/exercises/practice/series/series_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/series/canonical-data.json +# File last updated on 2023-07-15 + import unittest from series import ( slices, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/series/canonical-data.json -# File last updated on 2023-07-14 - class SeriesTest(unittest.TestCase): def test_slices_of_one_from_one(self): diff --git a/exercises/practice/sgf-parsing/sgf_parsing_test.py b/exercises/practice/sgf-parsing/sgf_parsing_test.py index f7acf2b1820..d157e9f9201 100644 --- a/exercises/practice/sgf-parsing/sgf_parsing_test.py +++ b/exercises/practice/sgf-parsing/sgf_parsing_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sgf-parsing/canonical-data.json +# File last updated on 2023-07-15 + import unittest from sgf_parsing import ( @@ -5,10 +9,6 @@ SgfTree, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/sgf-parsing/canonical-data.json -# File last updated on 2023-07-14 - class SgfParsingTest(unittest.TestCase): def test_empty_input(self): diff --git a/exercises/practice/sieve/sieve_test.py b/exercises/practice/sieve/sieve_test.py index 487f402db69..216e71b5248 100644 --- a/exercises/practice/sieve/sieve_test.py +++ b/exercises/practice/sieve/sieve_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sieve/canonical-data.json +# File last updated on 2023-07-15 + import unittest from sieve import ( primes, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/sieve/canonical-data.json -# File last updated on 2023-07-14 - class SieveTest(unittest.TestCase): def test_no_primes_under_two(self): diff --git a/exercises/practice/simple-cipher/simple_cipher_test.py b/exercises/practice/simple-cipher/simple_cipher_test.py index af4e2540d08..0747582c781 100644 --- a/exercises/practice/simple-cipher/simple_cipher_test.py +++ b/exercises/practice/simple-cipher/simple_cipher_test.py @@ -1,14 +1,15 @@ import re + +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/simple-cipher/canonical-data.json +# File last updated on 2023-07-15 + import unittest from simple_cipher import ( Cipher, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/simple-cipher/canonical-data.json -# File last updated on 2023-07-14 - class RandomKeyCipherTest(unittest.TestCase): def test_can_encode(self): diff --git a/exercises/practice/space-age/space_age_test.py b/exercises/practice/space-age/space_age_test.py index d1dc13b517b..3b3ad508461 100644 --- a/exercises/practice/space-age/space_age_test.py +++ b/exercises/practice/space-age/space_age_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/space-age/canonical-data.json +# File last updated on 2023-07-15 + import unittest from space_age import ( SpaceAge, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/space-age/canonical-data.json -# File last updated on 2023-07-14 - class SpaceAgeTest(unittest.TestCase): def test_age_on_earth(self): diff --git a/exercises/practice/spiral-matrix/spiral_matrix_test.py b/exercises/practice/spiral-matrix/spiral_matrix_test.py index fe3d1be2b8d..fadb9935933 100644 --- a/exercises/practice/spiral-matrix/spiral_matrix_test.py +++ b/exercises/practice/spiral-matrix/spiral_matrix_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/spiral-matrix/canonical-data.json +# File last updated on 2023-07-15 + import unittest from spiral_matrix import ( spiral_matrix, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/spiral-matrix/canonical-data.json -# File last updated on 2023-07-14 - class SpiralMatrixTest(unittest.TestCase): def test_empty_spiral(self): diff --git a/exercises/practice/square-root/square_root_test.py b/exercises/practice/square-root/square_root_test.py index 1a8dda7ab2e..8376c0dcbf4 100644 --- a/exercises/practice/square-root/square_root_test.py +++ b/exercises/practice/square-root/square_root_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/square-root/canonical-data.json +# File last updated on 2023-07-15 + import unittest from square_root import ( square_root, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/square-root/canonical-data.json -# File last updated on 2023-07-14 - class SquareRootTest(unittest.TestCase): def test_root_of_1(self): diff --git a/exercises/practice/sublist/sublist_test.py b/exercises/practice/sublist/sublist_test.py index dcabff2121f..2794aa55da2 100644 --- a/exercises/practice/sublist/sublist_test.py +++ b/exercises/practice/sublist/sublist_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sublist/canonical-data.json +# File last updated on 2023-07-15 + import unittest from sublist import ( @@ -8,10 +12,6 @@ UNEQUAL, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/sublist/canonical-data.json -# File last updated on 2023-07-14 - class SublistTest(unittest.TestCase): def test_empty_lists(self): diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py index 762840fbbc3..1dc0eb943b6 100644 --- a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py +++ b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/sum-of-multiples/canonical-data.json +# File last updated on 2023-07-15 + import unittest from sum_of_multiples import ( sum_of_multiples, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/sum-of-multiples/canonical-data.json -# File last updated on 2023-07-14 - class SumOfMultiplesTest(unittest.TestCase): def test_no_multiples_within_limit(self): diff --git a/exercises/practice/tournament/tournament_test.py b/exercises/practice/tournament/tournament_test.py index da8892d7dfe..3af02b561a8 100644 --- a/exercises/practice/tournament/tournament_test.py +++ b/exercises/practice/tournament/tournament_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/tournament/canonical-data.json +# File last updated on 2023-07-15 + import unittest from tournament import ( tally, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/tournament/canonical-data.json -# File last updated on 2023-07-14 - class TournamentTest(unittest.TestCase): def test_just_the_header_if_no_input(self): diff --git a/exercises/practice/transpose/transpose_test.py b/exercises/practice/transpose/transpose_test.py index 31464c6c6e4..29cbd35a2e8 100644 --- a/exercises/practice/transpose/transpose_test.py +++ b/exercises/practice/transpose/transpose_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/transpose/canonical-data.json +# File last updated on 2023-07-15 + import unittest from transpose import ( transpose, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/transpose/canonical-data.json -# File last updated on 2023-07-14 - class TransposeTest(unittest.TestCase): def test_empty_string(self): diff --git a/exercises/practice/triangle/triangle_test.py b/exercises/practice/triangle/triangle_test.py index 7de4b34046a..5ae01bc6566 100644 --- a/exercises/practice/triangle/triangle_test.py +++ b/exercises/practice/triangle/triangle_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json +# File last updated on 2023-07-15 + import unittest from triangle import ( @@ -6,10 +10,6 @@ scalene, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json -# File last updated on 2023-07-14 - class EquilateralTriangleTest(unittest.TestCase): def test_all_sides_are_equal(self): diff --git a/exercises/practice/twelve-days/twelve_days_test.py b/exercises/practice/twelve-days/twelve_days_test.py index 37076cf3efb..6135922dff7 100644 --- a/exercises/practice/twelve-days/twelve_days_test.py +++ b/exercises/practice/twelve-days/twelve_days_test.py @@ -1,12 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/twelve-days/canonical-data.json +# File last updated on 2023-07-15 + import unittest from twelve_days import ( recite, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/twelve-days/canonical-data.json -# File last updated on 2023-07-14 # PLEASE TAKE NOTE: Expected result lists for these test cases use **implicit line joining.** # A new line in a result list below **does not** always equal a new list element. # Check comma placement carefully! diff --git a/exercises/practice/two-bucket/two_bucket_test.py b/exercises/practice/two-bucket/two_bucket_test.py index 7ccf4135738..d8d77453103 100644 --- a/exercises/practice/two-bucket/two_bucket_test.py +++ b/exercises/practice/two-bucket/two_bucket_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/two-bucket/canonical-data.json +# File last updated on 2023-07-15 + import unittest from two_bucket import ( measure, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/two-bucket/canonical-data.json -# File last updated on 2023-07-14 - class TwoBucketTest(unittest.TestCase): def test_measure_using_bucket_one_of_size_3_and_bucket_two_of_size_5_start_with_bucket_one( diff --git a/exercises/practice/two-fer/two_fer_test.py b/exercises/practice/two-fer/two_fer_test.py index ae322272cb0..31728bfe0de 100644 --- a/exercises/practice/two-fer/two_fer_test.py +++ b/exercises/practice/two-fer/two_fer_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/two-fer/canonical-data.json +# File last updated on 2023-07-15 + import unittest from two_fer import ( two_fer, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/two-fer/canonical-data.json -# File last updated on 2023-07-14 - class TwoFerTest(unittest.TestCase): def test_no_name_given(self): diff --git a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py index 5f75ec9215f..45b1cdb53e0 100644 --- a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py +++ b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/variable-length-quantity/canonical-data.json +# File last updated on 2023-07-15 + import unittest from variable_length_quantity import ( @@ -5,10 +9,6 @@ encode, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/variable-length-quantity/canonical-data.json -# File last updated on 2023-07-14 - class VariableLengthQuantityTest(unittest.TestCase): def test_zero(self): diff --git a/exercises/practice/word-count/word_count_test.py b/exercises/practice/word-count/word_count_test.py index 783eca5a0bf..0714e8504b9 100644 --- a/exercises/practice/word-count/word_count_test.py +++ b/exercises/practice/word-count/word_count_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/word-count/canonical-data.json +# File last updated on 2023-07-15 + import unittest from word_count import ( count_words, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/word-count/canonical-data.json -# File last updated on 2023-07-14 - class WordCountTest(unittest.TestCase): def test_count_one_word(self): diff --git a/exercises/practice/word-search/word_search_test.py b/exercises/practice/word-search/word_search_test.py index 2dd3d434150..a3bb890896b 100644 --- a/exercises/practice/word-search/word_search_test.py +++ b/exercises/practice/word-search/word_search_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/word-search/canonical-data.json +# File last updated on 2023-07-15 + import unittest from word_search import ( @@ -5,10 +9,6 @@ Point, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/word-search/canonical-data.json -# File last updated on 2023-07-14 - class WordSearchTest(unittest.TestCase): def test_should_accept_an_initial_game_grid_and_a_target_search_word(self): diff --git a/exercises/practice/wordy/wordy_test.py b/exercises/practice/wordy/wordy_test.py index 678985ff89b..eaf81c5fa47 100644 --- a/exercises/practice/wordy/wordy_test.py +++ b/exercises/practice/wordy/wordy_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/wordy/canonical-data.json +# File last updated on 2023-07-15 + import unittest from wordy import ( answer, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/wordy/canonical-data.json -# File last updated on 2023-07-14 - class WordyTest(unittest.TestCase): def test_just_a_number(self): diff --git a/exercises/practice/yacht/yacht_test.py b/exercises/practice/yacht/yacht_test.py index cf7d72b4556..813bc8fbe65 100644 --- a/exercises/practice/yacht/yacht_test.py +++ b/exercises/practice/yacht/yacht_test.py @@ -4,7 +4,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/yacht/canonical-data.json -# File last updated on 2023-07-14 +# File last updated on 2023-07-15 class YachtTest(unittest.TestCase): diff --git a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py index f6ea9c82a38..7c8439e0384 100644 --- a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py +++ b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/zebra-puzzle/canonical-data.json +# File last updated on 2023-07-15 + import unittest from zebra_puzzle import ( @@ -5,10 +9,6 @@ owns_zebra, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/zebra-puzzle/canonical-data.json -# File last updated on 2023-07-14 - class ZebraPuzzleTest(unittest.TestCase): def test_resident_who_drinks_water(self): diff --git a/exercises/practice/zipper/zipper_test.py b/exercises/practice/zipper/zipper_test.py index c3f3de0f6d4..e7eab6c6b5c 100644 --- a/exercises/practice/zipper/zipper_test.py +++ b/exercises/practice/zipper/zipper_test.py @@ -1,13 +1,13 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/zipper/canonical-data.json +# File last updated on 2023-07-15 + import unittest from zipper import ( Zipper, ) -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/zipper/canonical-data.json -# File last updated on 2023-07-14 - class ZipperTest(unittest.TestCase): def test_data_is_retained(self): From aa3e379ff131b0b7797517b8c8678066b15f1e71 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Sun, 16 Jul 2023 15:09:14 -0700 Subject: [PATCH 116/126] [DOCS]: Update Python Versions and Requirements (#3467) * Additional sweep to update Python versions and supported Python versions. * Fixed requirements and CONTRIBUTING. * Trying a different line skip to see if it fixes CI. CI is failing on test file generation again. * Once again re-rendering tests to see if it fixes CI. [no important files changed] --- CONTRIBUTING.md | 12 ++++++------ bin/generate_tests.py | 2 +- docs/ABOUT.md | 7 +++---- docs/INSTALLATION.md | 4 ++-- docs/LEARNING.md | 1 - docs/TESTS.md | 6 +++--- docs/TOOLS.md | 2 +- docs/TRACEBACKS.md | 2 -- exercises/practice/acronym/acronym_test.py | 2 +- .../practice/affine-cipher/affine_cipher_test.py | 2 +- .../practice/all-your-base/all_your_base_test.py | 2 +- exercises/practice/allergies/allergies_test.py | 2 +- exercises/practice/alphametics/alphametics_test.py | 2 +- exercises/practice/anagram/anagram_test.py | 2 +- .../armstrong-numbers/armstrong_numbers_test.py | 2 +- .../practice/atbash-cipher/atbash_cipher_test.py | 2 +- exercises/practice/bank-account/bank_account_test.py | 2 +- exercises/practice/beer-song/beer_song_test.py | 2 +- .../binary-search-tree/binary_search_tree_test.py | 2 +- .../practice/binary-search/binary_search_test.py | 2 +- exercises/practice/bob/bob_test.py | 2 +- exercises/practice/book-store/book_store_test.py | 2 +- exercises/practice/bottle-song/bottle_song_test.py | 2 +- exercises/practice/bowling/bowling_test.py | 2 +- exercises/practice/change/change_test.py | 2 +- .../practice/circular-buffer/circular_buffer_test.py | 2 +- exercises/practice/clock/clock_test.py | 2 +- .../collatz-conjecture/collatz_conjecture_test.py | 2 +- .../practice/complex-numbers/complex_numbers_test.py | 2 +- exercises/practice/connect/connect_test.py | 2 +- .../practice/crypto-square/crypto_square_test.py | 2 +- exercises/practice/custom-set/custom_set_test.py | 2 +- exercises/practice/darts/darts_test.py | 2 +- exercises/practice/diamond/diamond_test.py | 2 +- .../difference_of_squares_test.py | 2 +- .../practice/diffie-hellman/diffie_hellman_test.py | 2 +- .../practice/dnd-character/dnd_character_test.py | 2 +- exercises/practice/dominoes/dominoes_test.py | 2 +- exercises/practice/etl/etl_test.py | 2 +- .../practice/flatten-array/flatten_array_test.py | 2 +- exercises/practice/food-chain/food_chain_test.py | 2 +- exercises/practice/forth/forth_test.py | 2 +- exercises/practice/gigasecond/gigasecond_test.py | 2 +- exercises/practice/go-counting/go_counting_test.py | 2 +- exercises/practice/grade-school/grade_school_test.py | 2 +- exercises/practice/grains/grains_test.py | 2 +- exercises/practice/grep/grep_test.py | 2 +- exercises/practice/hamming/hamming_test.py | 2 +- exercises/practice/high-scores/high_scores_test.py | 2 +- exercises/practice/house/house_test.py | 2 +- .../practice/isbn-verifier/isbn_verifier_test.py | 2 +- exercises/practice/isogram/isogram_test.py | 2 +- .../killer_sudoku_helper_test.py | 2 +- .../kindergarten-garden/kindergarten_garden_test.py | 2 +- exercises/practice/knapsack/knapsack_test.py | 2 +- .../largest_series_product_test.py | 2 +- exercises/practice/leap/leap_test.py | 2 +- exercises/practice/ledger/ledger_test.py | 2 +- exercises/practice/linked-list/linked_list_test.py | 2 +- exercises/practice/list-ops/list_ops_test.py | 2 +- exercises/practice/luhn/luhn_test.py | 2 +- exercises/practice/markdown/markdown_test.py | 2 +- .../matching-brackets/matching_brackets_test.py | 2 +- exercises/practice/matrix/matrix_test.py | 2 +- exercises/practice/meetup/meetup_test.py | 2 +- exercises/practice/minesweeper/minesweeper_test.py | 2 +- exercises/practice/nth-prime/nth_prime_test.py | 2 +- exercises/practice/ocr-numbers/ocr_numbers_test.py | 2 +- .../palindrome-products/palindrome_products_test.py | 2 +- exercises/practice/pangram/pangram_test.py | 2 +- .../pascals-triangle/pascals_triangle_test.py | 2 +- .../practice/perfect-numbers/perfect_numbers_test.py | 2 +- exercises/practice/phone-number/phone_number_test.py | 2 +- exercises/practice/pig-latin/pig_latin_test.py | 2 +- exercises/practice/poker/poker_test.py | 2 +- exercises/practice/pov/pov_test.py | 2 +- .../practice/prime-factors/prime_factors_test.py | 2 +- .../protein-translation/protein_translation_test.py | 2 +- exercises/practice/proverb/proverb_test.py | 2 +- .../pythagorean-triplet/pythagorean_triplet_test.py | 2 +- exercises/practice/queen-attack/queen_attack_test.py | 2 +- .../rail-fence-cipher/rail_fence_cipher_test.py | 2 +- exercises/practice/raindrops/raindrops_test.py | 2 +- .../rational-numbers/rational_numbers_test.py | 2 +- exercises/practice/react/react_test.py | 2 +- exercises/practice/rectangles/rectangles_test.py | 2 +- .../resistor-color-duo/resistor_color_duo_test.py | 2 +- .../resistor-color-trio/resistor_color_trio_test.py | 2 +- .../practice/resistor-color/resistor_color_test.py | 2 +- exercises/practice/rest-api/rest_api_test.py | 2 +- .../practice/reverse-string/reverse_string_test.py | 2 +- .../rna-transcription/rna_transcription_test.py | 2 +- .../practice/robot-simulator/robot_simulator_test.py | 2 +- .../practice/roman-numerals/roman_numerals_test.py | 2 +- .../rotational-cipher/rotational_cipher_test.py | 2 +- .../run-length-encoding/run_length_encoding_test.py | 2 +- .../practice/saddle-points/saddle_points_test.py | 2 +- exercises/practice/satellite/satellite_test.py | 2 +- exercises/practice/say/say_test.py | 2 +- .../practice/scale-generator/scale_generator_test.py | 2 +- .../practice/scrabble-score/scrabble_score_test.py | 2 +- .../secret-handshake/secret_handshake_test.py | 2 +- exercises/practice/series/series_test.py | 2 +- exercises/practice/sgf-parsing/sgf_parsing_test.py | 2 +- exercises/practice/sieve/sieve_test.py | 2 +- .../practice/simple-cipher/simple_cipher_test.py | 2 +- exercises/practice/space-age/space_age_test.py | 2 +- .../practice/spiral-matrix/spiral_matrix_test.py | 2 +- exercises/practice/square-root/square_root_test.py | 2 +- exercises/practice/sublist/sublist_test.py | 2 +- .../sum-of-multiples/sum_of_multiples_test.py | 2 +- exercises/practice/tournament/tournament_test.py | 2 +- exercises/practice/transpose/transpose_test.py | 2 +- exercises/practice/triangle/triangle_test.py | 2 +- exercises/practice/twelve-days/twelve_days_test.py | 2 +- exercises/practice/two-bucket/two_bucket_test.py | 2 +- exercises/practice/two-fer/two_fer_test.py | 2 +- .../variable_length_quantity_test.py | 2 +- exercises/practice/word-count/word_count_test.py | 2 +- exercises/practice/word-search/word_search_test.py | 2 +- exercises/practice/wordy/wordy_test.py | 2 +- exercises/practice/yacht/.meta/template.j2 | 2 -- exercises/practice/yacht/yacht_test.py | 4 ---- exercises/practice/zebra-puzzle/zebra_puzzle_test.py | 2 +- exercises/practice/zipper/zipper_test.py | 2 +- requirements.txt | 3 +-- 126 files changed, 132 insertions(+), 143 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7f082a56322..0bac23e0af3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -195,12 +195,12 @@ _We know it, and trust us, we are working on fixing it._ But if you see  
-This track officially supports Python `3.7 - 3.10.6` for students completing exercises. -The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.10.6-slim`. +This track officially supports Python `3.7 - 3.11.2` for students completing exercises. +The track `test runner`, `analyzer`, and `representer` run in docker on `python:3.11.2-slim`. Although the majority of test cases are written using `unittest.TestCase`, -- All exercises should be written for compatibility with Python `3.7` - `3.10.6`. +- All exercises should be written for compatibility with Python `3.7` - `3.11.2`. - Version backward _incompatibility_ (_e.g_ an exercise using features introduced in `3.8`, `3.9`, or `3.10`) should be clearly noted in any exercise hints, links, introductions or other notes. - Here is an example of how the Python documentation handles [version-tagged  🏷 ][version-tagged-language-features] feature introduction. @@ -227,7 +227,7 @@ Although the majority of test cases are written using `unittest.TestCase`, - Any updates or changes need to be proposed/approved in `problem-specifications` first. - If Python-specific changes become necessary, they need to be appended to the canonical instructions by creating a `instructions.append.md` file in this (`exercism/Python`) repository. -- Practice Exercise **Test Suits** for many practice exercises are similarly [auto-generated](#auto-generated-files) from data in [problem specifications][problem-specifications]. +- Practice Exercise **Test Suits** for most practice exercises are similarly [auto-generated](#auto-generated-files) from data in [problem specifications][problem-specifications]. - Any changes to them need to be proposed/discussed in the `problem-specifications` repository and approved by **3 track maintainers**, since changes could potentially affect many (_or all_) exercism language tracks. - If Python-specific test changes become necessary, they can be appended to the exercise `tests.toml` file. @@ -371,6 +371,7 @@ configlet generate --spec-path path/to/problem/specifications
+ [.flake8]: https://github.com/exercism/python/blob/main/.flake8 [.style.yapf]: https://github.com/exercism/python/blob/main/.style.yapf [american-english]: https://github.com/exercism/docs/blob/main/building/markdown/style-guide.md @@ -380,6 +381,7 @@ configlet generate --spec-path path/to/problem/specifications [concept-exercise-anatomy]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md [concept-exercises]: https://github.com/exercism/docs/blob/main/building/tracks/concept-exercises.md [config-json]: https://github.com/exercism/javascript/blob/main/config.json +[config-json]: https://github.com/exercism/python/blob/main/config.json [configlet-general]: https://github.com/exercism/configlet [configlet-lint]: https://github.com/exercism/configlet#configlet-lint [configlet]: https://github.com/exercism/docs/blob/main/building/configlet/generating-documents.md @@ -429,5 +431,3 @@ configlet generate --spec-path path/to/problem/specifications [version-tagged-language-features]: https://docs.python.org/3/library/stdtypes.html#dict.popitem [website-contributing-section]: https://exercism.org/docs/building [yapf]: https://github.com/google/yapf - -[config-json]: https://github.com/exercism/python/blob/main/config.json diff --git a/bin/generate_tests.py b/bin/generate_tests.py index 285c88d2e77..33580137058 100755 --- a/bin/generate_tests.py +++ b/bin/generate_tests.py @@ -271,7 +271,7 @@ def check_template(slug: str, tests_path: Path, tmpfile: Path): check_ok = False if check_ok and not filecmp.cmp(tmpfile, tests_path): with tests_path.open() as f: - for line in range(5): + for line in range(4): next(f) current_lines = f.readlines() with tmpfile.open() as f: diff --git a/docs/ABOUT.md b/docs/ABOUT.md index f0d52389bf3..6177394a518 100644 --- a/docs/ABOUT.md +++ b/docs/ABOUT.md @@ -20,14 +20,14 @@ Code can be written and executed from the command line, in an interactive interp The [zen of Python (PEP 20)][the zen of python] and [What is Pythonic?][what is pythonic] lay out additional philosophies and perspectives on the language. -Tests and tooling for this track currently support `3.7` - `3.10.6` (_tests_) and [`Python 3.11`][311-new-features] (_tooling_). +Tests and tooling for this track currently support `3.7` - `3.11.2` (_tests_) and [`Python 3.11.2`][311-new-features] (_tooling_). It is highly recommended that students upgrade to at least `Python 3.8`, as some features used by this track may not be supported in earlier versions. -That being said, most of the exercises will work with `Python 3.6+`. +That being said, most of the exercises will work with `Python 3.6+`, or even earlier versions. But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases]. We will try to note when a feature is only available in a certain version. -Complete documentation for the current release of Python (3.11.2) can be found at [docs.python.org][python docs]. +Complete documentation for the current release of Python (3.11.x) can be found at [docs.python.org][python docs]. - [Python Tutorial][python tutorial] - [Python Library Reference][python library reference] @@ -37,7 +37,6 @@ Complete documentation for the current release of Python (3.11.2) can be found a - [Python Glossary of Terms][python glossary of terms] - [311-new-features]: https://docs.python.org/3/whatsnew/3.11.html [active-python-releases]: https://www.python.org/downloads/ [duck typing]: https://en.wikipedia.org/wiki/Duck_typing diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md index c8eb68ca466..04f9c899349 100644 --- a/docs/INSTALLATION.md +++ b/docs/INSTALLATION.md @@ -18,9 +18,9 @@ Some quick links into the documentation by operating system: We recommend reviewing some of the methods outlined in the Real Python article [Installing Python][installing-python] or the articles by Brett Cannon linked above. -Exercism tests and tooling currently support `3.7` - `3.10.6` (_tests_) and [`Python 3.11`][311-new-features] (_tooling_). +Exercism tests and tooling currently support `3.7` - `3.11.2` (_tests_) and [`Python 3.11.2`][311-new-features] (_tooling_). Exceptions to this support are noted where they occur. -Most of the exercises will work with `Python 3.6+`. +Most of the exercises will work with `Python 3.6+`, or even earlier versions. But we don't guarantee support for versions not listed under [Active Python Releases][active-python-releases]. diff --git a/docs/LEARNING.md b/docs/LEARNING.md index f9cb1b22051..50a3259eed7 100644 --- a/docs/LEARNING.md +++ b/docs/LEARNING.md @@ -37,7 +37,6 @@ Below you will find some additional jumping-off places to start your learning jo [automate the videos]: https://www.youtube.com/watch?v=1F_OgqRuSdI&list=PL0-84-yl1fUnRuXGFe_F7qSH1LEnn9LkW [googles python class]: https://developers.google.com/edu/python/introduction [mitocw600]: https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-0001-introduction-to-computer-science-and-programming-in-python-fall-2016/ -[pycharm edu]: https://www.jetbrains.com/pycharm-edu/ [python-course.eu]: https://python-course.eu/python-tutorial/ [python-for-non-programmers]: https://store.lerner.co.il/python-for-non-programmers-live [python4everyone]: https://www.py4e.com/ diff --git a/docs/TESTS.md b/docs/TESTS.md index 00ff924cd73..242555371f3 100644 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -30,14 +30,14 @@ Otherwise, the `pytest` installation will be global. ```powershell PS C:\Users\foobar> py -m pip install pytest pytest-cache pytest-subtests pytest-pylint -Successfully installed pytest-6.2.5 ... +Successfully installed pytest-7.2.2 ... ``` #### Linux / MacOS ```bash $ python3 -m pip install pytest pytest-cache pytest-subtests pytest-pylint -Successfully installed pytest-6.2.5 ... +Successfully installed pytest-7.2.2 ... ``` @@ -46,7 +46,7 @@ To check if installation was successful: ```bash $ python3 -m pytest --version -pytest 6.2.5 +pytest 7.2.2 ``` ## Running the tests diff --git a/docs/TOOLS.md b/docs/TOOLS.md index f5fdedcdf1f..20ce04ded09 100644 --- a/docs/TOOLS.md +++ b/docs/TOOLS.md @@ -30,7 +30,7 @@ If you have an editor, IDE, tool, or plugin recommendation, we encourage you to Before you start exploring, make sure that you have a recent version of Python installed. -The Exercism platform currently supports `Python 3.8` (_exercises and tests_) and `Python 3.9` (_tooling_). +The Exercism platform currently supports `Python 3.7 - 3.11.2` (_exercises and tests_) and `Python 3.11.2` (_tooling_). For more information, please refer to [Installing Python locally][Installing Python locally].
diff --git a/docs/TRACEBACKS.md b/docs/TRACEBACKS.md index 4bdf92cc67e..5914429db9d 100644 --- a/docs/TRACEBACKS.md +++ b/docs/TRACEBACKS.md @@ -632,8 +632,6 @@ print(sum) [assert]: https://realpython.com/python-assert-statement/ [assertionerror]: https://www.geeksforgeeks.org/python-assertion-error/ -[floor divison operator]: https://www.codingem.com/python-floor-division -[logging]: https://docs.python.org/3/howto/logging.html [print]: https://www.w3schools.com/python/ref_func_print.asp [pdb]: https://www.geeksforgeeks.org/python-debugger-python-pdb/ [exception-hierarchy]: https://docs.python.org/3/library/exceptions.html#exception-hierarchy diff --git a/exercises/practice/acronym/acronym_test.py b/exercises/practice/acronym/acronym_test.py index 78557dd88b7..6664ae5b20e 100644 --- a/exercises/practice/acronym/acronym_test.py +++ b/exercises/practice/acronym/acronym_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/acronym/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/affine-cipher/affine_cipher_test.py b/exercises/practice/affine-cipher/affine_cipher_test.py index 06e6faf0da9..f8e4fd59f05 100644 --- a/exercises/practice/affine-cipher/affine_cipher_test.py +++ b/exercises/practice/affine-cipher/affine_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/affine-cipher/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/all-your-base/all_your_base_test.py b/exercises/practice/all-your-base/all_your_base_test.py index 9a4ca40ccd6..c9f04e8dac9 100644 --- a/exercises/practice/all-your-base/all_your_base_test.py +++ b/exercises/practice/all-your-base/all_your_base_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/all-your-base/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/allergies/allergies_test.py b/exercises/practice/allergies/allergies_test.py index 8d6d574e20d..11f65b9b3ff 100644 --- a/exercises/practice/allergies/allergies_test.py +++ b/exercises/practice/allergies/allergies_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/allergies/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/alphametics/alphametics_test.py b/exercises/practice/alphametics/alphametics_test.py index 014df6ceb91..911e409a3d6 100644 --- a/exercises/practice/alphametics/alphametics_test.py +++ b/exercises/practice/alphametics/alphametics_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/alphametics/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/anagram/anagram_test.py b/exercises/practice/anagram/anagram_test.py index 69145b9d4f6..fddc11b4236 100644 --- a/exercises/practice/anagram/anagram_test.py +++ b/exercises/practice/anagram/anagram_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/anagram/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py index 49831704f07..e79430483e0 100644 --- a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py +++ b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/atbash-cipher/atbash_cipher_test.py b/exercises/practice/atbash-cipher/atbash_cipher_test.py index dded351c587..e6f5314cbbe 100644 --- a/exercises/practice/atbash-cipher/atbash_cipher_test.py +++ b/exercises/practice/atbash-cipher/atbash_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/atbash-cipher/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/bank-account/bank_account_test.py b/exercises/practice/bank-account/bank_account_test.py index d58663395b4..815442113e9 100644 --- a/exercises/practice/bank-account/bank_account_test.py +++ b/exercises/practice/bank-account/bank_account_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bank-account/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/beer-song/beer_song_test.py b/exercises/practice/beer-song/beer_song_test.py index c1391989fa2..8ab578a0cd9 100644 --- a/exercises/practice/beer-song/beer_song_test.py +++ b/exercises/practice/beer-song/beer_song_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/beer-song/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/binary-search-tree/binary_search_tree_test.py b/exercises/practice/binary-search-tree/binary_search_tree_test.py index fdb915fe773..8a4d0ff9a24 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree_test.py +++ b/exercises/practice/binary-search-tree/binary_search_tree_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search-tree/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/binary-search/binary_search_test.py b/exercises/practice/binary-search/binary_search_test.py index 6d094977344..b0bb4bac96c 100644 --- a/exercises/practice/binary-search/binary_search_test.py +++ b/exercises/practice/binary-search/binary_search_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/bob/bob_test.py b/exercises/practice/bob/bob_test.py index 089636fad54..63d40c0315b 100644 --- a/exercises/practice/bob/bob_test.py +++ b/exercises/practice/bob/bob_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/book-store/book_store_test.py b/exercises/practice/book-store/book_store_test.py index 66c1b723100..9d71b0cf7ec 100644 --- a/exercises/practice/book-store/book_store_test.py +++ b/exercises/practice/book-store/book_store_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/book-store/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/bottle-song/bottle_song_test.py b/exercises/practice/bottle-song/bottle_song_test.py index 487a46cedc5..e947b18f90c 100644 --- a/exercises/practice/bottle-song/bottle_song_test.py +++ b/exercises/practice/bottle-song/bottle_song_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bottle-song/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/bowling/bowling_test.py b/exercises/practice/bowling/bowling_test.py index 374096e592f..bfefd55f0a4 100644 --- a/exercises/practice/bowling/bowling_test.py +++ b/exercises/practice/bowling/bowling_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bowling/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/change/change_test.py b/exercises/practice/change/change_test.py index b090a3965f6..71664188320 100644 --- a/exercises/practice/change/change_test.py +++ b/exercises/practice/change/change_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/change/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/circular-buffer/circular_buffer_test.py b/exercises/practice/circular-buffer/circular_buffer_test.py index b96a25e15cc..077852a1d0c 100644 --- a/exercises/practice/circular-buffer/circular_buffer_test.py +++ b/exercises/practice/circular-buffer/circular_buffer_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/circular-buffer/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/clock/clock_test.py b/exercises/practice/clock/clock_test.py index db4bc919cfd..fa07e25b625 100644 --- a/exercises/practice/clock/clock_test.py +++ b/exercises/practice/clock/clock_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/clock/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py index d18bc37719a..6c1dd797603 100644 --- a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py +++ b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/collatz-conjecture/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/complex-numbers/complex_numbers_test.py b/exercises/practice/complex-numbers/complex_numbers_test.py index 637eb7b90d9..4fd9c75ed54 100644 --- a/exercises/practice/complex-numbers/complex_numbers_test.py +++ b/exercises/practice/complex-numbers/complex_numbers_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/complex-numbers/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/connect/connect_test.py b/exercises/practice/connect/connect_test.py index 239944a5cb3..18c7d8f94c7 100644 --- a/exercises/practice/connect/connect_test.py +++ b/exercises/practice/connect/connect_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/connect/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/crypto-square/crypto_square_test.py b/exercises/practice/crypto-square/crypto_square_test.py index 08cfa87c7b4..784450d366a 100644 --- a/exercises/practice/crypto-square/crypto_square_test.py +++ b/exercises/practice/crypto-square/crypto_square_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/crypto-square/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/custom-set/custom_set_test.py b/exercises/practice/custom-set/custom_set_test.py index 5e6ab124be1..e6d6bc120c8 100644 --- a/exercises/practice/custom-set/custom_set_test.py +++ b/exercises/practice/custom-set/custom_set_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/custom-set/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/darts/darts_test.py b/exercises/practice/darts/darts_test.py index c417dabd982..ed0ed9baa64 100644 --- a/exercises/practice/darts/darts_test.py +++ b/exercises/practice/darts/darts_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/darts/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/diamond/diamond_test.py b/exercises/practice/diamond/diamond_test.py index 504380af426..cf7f1bac5e5 100644 --- a/exercises/practice/diamond/diamond_test.py +++ b/exercises/practice/diamond/diamond_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/diamond/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/difference-of-squares/difference_of_squares_test.py b/exercises/practice/difference-of-squares/difference_of_squares_test.py index d75e565bef0..08b3c35922c 100644 --- a/exercises/practice/difference-of-squares/difference_of_squares_test.py +++ b/exercises/practice/difference-of-squares/difference_of_squares_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/difference-of-squares/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/diffie-hellman/diffie_hellman_test.py b/exercises/practice/diffie-hellman/diffie_hellman_test.py index ce5819821c0..01ed7116eae 100644 --- a/exercises/practice/diffie-hellman/diffie_hellman_test.py +++ b/exercises/practice/diffie-hellman/diffie_hellman_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/diffie-hellman/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/dnd-character/dnd_character_test.py b/exercises/practice/dnd-character/dnd_character_test.py index f158f257a80..16a7959834a 100644 --- a/exercises/practice/dnd-character/dnd_character_test.py +++ b/exercises/practice/dnd-character/dnd_character_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/dnd-character/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/dominoes/dominoes_test.py b/exercises/practice/dominoes/dominoes_test.py index 78befc761b1..3d87ec5e584 100644 --- a/exercises/practice/dominoes/dominoes_test.py +++ b/exercises/practice/dominoes/dominoes_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/dominoes/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/etl/etl_test.py b/exercises/practice/etl/etl_test.py index d8e587bc79c..8d9c628fe11 100644 --- a/exercises/practice/etl/etl_test.py +++ b/exercises/practice/etl/etl_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/etl/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/flatten-array/flatten_array_test.py b/exercises/practice/flatten-array/flatten_array_test.py index 5d73db6b6e0..4c69ab1f7cd 100644 --- a/exercises/practice/flatten-array/flatten_array_test.py +++ b/exercises/practice/flatten-array/flatten_array_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/flatten-array/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/food-chain/food_chain_test.py b/exercises/practice/food-chain/food_chain_test.py index d330574c0bd..1124f4f47c8 100644 --- a/exercises/practice/food-chain/food_chain_test.py +++ b/exercises/practice/food-chain/food_chain_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/food-chain/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/forth/forth_test.py b/exercises/practice/forth/forth_test.py index 458ce476569..f4aa468d303 100644 --- a/exercises/practice/forth/forth_test.py +++ b/exercises/practice/forth/forth_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/forth/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/gigasecond/gigasecond_test.py b/exercises/practice/gigasecond/gigasecond_test.py index 74017949aa1..b7ebed264eb 100644 --- a/exercises/practice/gigasecond/gigasecond_test.py +++ b/exercises/practice/gigasecond/gigasecond_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/gigasecond/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/go-counting/go_counting_test.py b/exercises/practice/go-counting/go_counting_test.py index 81886ca8762..43eaa5b246a 100644 --- a/exercises/practice/go-counting/go_counting_test.py +++ b/exercises/practice/go-counting/go_counting_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/go-counting/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/grade-school/grade_school_test.py b/exercises/practice/grade-school/grade_school_test.py index 2d2b4f5604e..3f61d1303da 100644 --- a/exercises/practice/grade-school/grade_school_test.py +++ b/exercises/practice/grade-school/grade_school_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/grade-school/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/grains/grains_test.py b/exercises/practice/grains/grains_test.py index e9d72f6a46d..5820aa4ce18 100644 --- a/exercises/practice/grains/grains_test.py +++ b/exercises/practice/grains/grains_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/grains/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/grep/grep_test.py b/exercises/practice/grep/grep_test.py index aff476d2394..d15c2f39095 100644 --- a/exercises/practice/grep/grep_test.py +++ b/exercises/practice/grep/grep_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/grep/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/hamming/hamming_test.py b/exercises/practice/hamming/hamming_test.py index d8d5c138a9a..d9171a44498 100644 --- a/exercises/practice/hamming/hamming_test.py +++ b/exercises/practice/hamming/hamming_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/hamming/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/high-scores/high_scores_test.py b/exercises/practice/high-scores/high_scores_test.py index d1e4b71d6f7..46f14477f09 100644 --- a/exercises/practice/high-scores/high_scores_test.py +++ b/exercises/practice/high-scores/high_scores_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/high-scores/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/house/house_test.py b/exercises/practice/house/house_test.py index a42b3950490..a64809f83a0 100644 --- a/exercises/practice/house/house_test.py +++ b/exercises/practice/house/house_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/house/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/isbn-verifier/isbn_verifier_test.py b/exercises/practice/isbn-verifier/isbn_verifier_test.py index 22fdd0a9b77..341afea5f3d 100644 --- a/exercises/practice/isbn-verifier/isbn_verifier_test.py +++ b/exercises/practice/isbn-verifier/isbn_verifier_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/isbn-verifier/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/isogram/isogram_test.py b/exercises/practice/isogram/isogram_test.py index b7427a7d446..09d7431d156 100644 --- a/exercises/practice/isogram/isogram_test.py +++ b/exercises/practice/isogram/isogram_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/isogram/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py index 24b02c08fb5..023687a9bc5 100644 --- a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py +++ b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/killer-sudoku-helper/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py index 83d4978e145..138cbb07920 100644 --- a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py +++ b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/kindergarten-garden/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/knapsack/knapsack_test.py b/exercises/practice/knapsack/knapsack_test.py index a4120237840..5ce2abae03c 100644 --- a/exercises/practice/knapsack/knapsack_test.py +++ b/exercises/practice/knapsack/knapsack_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/knapsack/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/largest-series-product/largest_series_product_test.py b/exercises/practice/largest-series-product/largest_series_product_test.py index e75f022d63d..3d5a90858ab 100644 --- a/exercises/practice/largest-series-product/largest_series_product_test.py +++ b/exercises/practice/largest-series-product/largest_series_product_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/largest-series-product/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/leap/leap_test.py b/exercises/practice/leap/leap_test.py index d8c508de5e8..69f5387962d 100644 --- a/exercises/practice/leap/leap_test.py +++ b/exercises/practice/leap/leap_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/leap/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/ledger/ledger_test.py b/exercises/practice/ledger/ledger_test.py index e8432bb5181..d9d1027d995 100644 --- a/exercises/practice/ledger/ledger_test.py +++ b/exercises/practice/ledger/ledger_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/ledger/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/linked-list/linked_list_test.py b/exercises/practice/linked-list/linked_list_test.py index 9a196084e6f..c73175609ac 100644 --- a/exercises/practice/linked-list/linked_list_test.py +++ b/exercises/practice/linked-list/linked_list_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/linked-list/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index 4bff0080b8a..0375d875648 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/list-ops/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/luhn/luhn_test.py b/exercises/practice/luhn/luhn_test.py index f6b078cca39..a83c3999d49 100644 --- a/exercises/practice/luhn/luhn_test.py +++ b/exercises/practice/luhn/luhn_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/luhn/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/markdown/markdown_test.py b/exercises/practice/markdown/markdown_test.py index 4501adb7872..7d474900fcf 100644 --- a/exercises/practice/markdown/markdown_test.py +++ b/exercises/practice/markdown/markdown_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/markdown/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/matching-brackets/matching_brackets_test.py b/exercises/practice/matching-brackets/matching_brackets_test.py index ae59ead1fca..e9693d23cd0 100644 --- a/exercises/practice/matching-brackets/matching_brackets_test.py +++ b/exercises/practice/matching-brackets/matching_brackets_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/matching-brackets/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/matrix/matrix_test.py b/exercises/practice/matrix/matrix_test.py index 49e1ea90228..421f5bf6f7b 100644 --- a/exercises/practice/matrix/matrix_test.py +++ b/exercises/practice/matrix/matrix_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/matrix/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/meetup/meetup_test.py b/exercises/practice/meetup/meetup_test.py index 24695176bd5..c9d5ce03448 100644 --- a/exercises/practice/meetup/meetup_test.py +++ b/exercises/practice/meetup/meetup_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/meetup/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/minesweeper/minesweeper_test.py b/exercises/practice/minesweeper/minesweeper_test.py index 763281d66e1..192cb40bc39 100644 --- a/exercises/practice/minesweeper/minesweeper_test.py +++ b/exercises/practice/minesweeper/minesweeper_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/minesweeper/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/nth-prime/nth_prime_test.py b/exercises/practice/nth-prime/nth_prime_test.py index 19c68e55f3c..ce42da6db35 100644 --- a/exercises/practice/nth-prime/nth_prime_test.py +++ b/exercises/practice/nth-prime/nth_prime_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/nth-prime/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/ocr-numbers/ocr_numbers_test.py b/exercises/practice/ocr-numbers/ocr_numbers_test.py index 1b74ca2893d..c7f058f1039 100644 --- a/exercises/practice/ocr-numbers/ocr_numbers_test.py +++ b/exercises/practice/ocr-numbers/ocr_numbers_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/ocr-numbers/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/palindrome-products/palindrome_products_test.py b/exercises/practice/palindrome-products/palindrome_products_test.py index 7fc2c61bfa5..cbe5affe206 100644 --- a/exercises/practice/palindrome-products/palindrome_products_test.py +++ b/exercises/practice/palindrome-products/palindrome_products_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/palindrome-products/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/pangram/pangram_test.py b/exercises/practice/pangram/pangram_test.py index e441ac39586..867660aaa88 100644 --- a/exercises/practice/pangram/pangram_test.py +++ b/exercises/practice/pangram/pangram_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pangram/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/pascals-triangle/pascals_triangle_test.py b/exercises/practice/pascals-triangle/pascals_triangle_test.py index e7979a15a09..972ee660ffa 100644 --- a/exercises/practice/pascals-triangle/pascals_triangle_test.py +++ b/exercises/practice/pascals-triangle/pascals_triangle_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pascals-triangle/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/perfect-numbers/perfect_numbers_test.py b/exercises/practice/perfect-numbers/perfect_numbers_test.py index 80479076d23..2f4f9a9bbcc 100644 --- a/exercises/practice/perfect-numbers/perfect_numbers_test.py +++ b/exercises/practice/perfect-numbers/perfect_numbers_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/perfect-numbers/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/phone-number/phone_number_test.py b/exercises/practice/phone-number/phone_number_test.py index 4b887e8bbbd..c7a1006eadc 100644 --- a/exercises/practice/phone-number/phone_number_test.py +++ b/exercises/practice/phone-number/phone_number_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/phone-number/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/pig-latin/pig_latin_test.py b/exercises/practice/pig-latin/pig_latin_test.py index 39894d69434..c3d0a20d362 100644 --- a/exercises/practice/pig-latin/pig_latin_test.py +++ b/exercises/practice/pig-latin/pig_latin_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/poker/poker_test.py b/exercises/practice/poker/poker_test.py index 1b1332dad03..65e64867f5d 100644 --- a/exercises/practice/poker/poker_test.py +++ b/exercises/practice/poker/poker_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/poker/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/pov/pov_test.py b/exercises/practice/pov/pov_test.py index c10101fa2ff..a43d104234d 100644 --- a/exercises/practice/pov/pov_test.py +++ b/exercises/practice/pov/pov_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pov/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/prime-factors/prime_factors_test.py b/exercises/practice/prime-factors/prime_factors_test.py index ada03fe4f74..d0554518c82 100644 --- a/exercises/practice/prime-factors/prime_factors_test.py +++ b/exercises/practice/prime-factors/prime_factors_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/prime-factors/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/protein-translation/protein_translation_test.py b/exercises/practice/protein-translation/protein_translation_test.py index e79fde21105..cb87652d0b6 100644 --- a/exercises/practice/protein-translation/protein_translation_test.py +++ b/exercises/practice/protein-translation/protein_translation_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/protein-translation/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/proverb/proverb_test.py b/exercises/practice/proverb/proverb_test.py index 9a86be909a0..6e36151bf9d 100644 --- a/exercises/practice/proverb/proverb_test.py +++ b/exercises/practice/proverb/proverb_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/proverb/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py index 663256cf8c9..c9307e4461e 100644 --- a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py +++ b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pythagorean-triplet/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/queen-attack/queen_attack_test.py b/exercises/practice/queen-attack/queen_attack_test.py index 127d506817b..15520856242 100644 --- a/exercises/practice/queen-attack/queen_attack_test.py +++ b/exercises/practice/queen-attack/queen_attack_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/queen-attack/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py index c2600804b71..e5466ee5993 100644 --- a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py +++ b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rail-fence-cipher/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/raindrops/raindrops_test.py b/exercises/practice/raindrops/raindrops_test.py index 089b5ded67b..d84dd175b82 100644 --- a/exercises/practice/raindrops/raindrops_test.py +++ b/exercises/practice/raindrops/raindrops_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/raindrops/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/rational-numbers/rational_numbers_test.py b/exercises/practice/rational-numbers/rational_numbers_test.py index 031361d3118..062b582d253 100644 --- a/exercises/practice/rational-numbers/rational_numbers_test.py +++ b/exercises/practice/rational-numbers/rational_numbers_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rational-numbers/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/react/react_test.py b/exercises/practice/react/react_test.py index 0a93e4d23cc..ec54fa94cd5 100644 --- a/exercises/practice/react/react_test.py +++ b/exercises/practice/react/react_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/react/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/rectangles/rectangles_test.py b/exercises/practice/rectangles/rectangles_test.py index 19988c7bd5b..67c4d77ed44 100644 --- a/exercises/practice/rectangles/rectangles_test.py +++ b/exercises/practice/rectangles/rectangles_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rectangles/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py index 265135639bc..b1bb371597d 100644 --- a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py +++ b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-duo/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py index a566be48af1..90f5842b23b 100644 --- a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py +++ b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-trio/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/resistor-color/resistor_color_test.py b/exercises/practice/resistor-color/resistor_color_test.py index c8648ea1d40..4847708e80f 100644 --- a/exercises/practice/resistor-color/resistor_color_test.py +++ b/exercises/practice/resistor-color/resistor_color_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/rest-api/rest_api_test.py b/exercises/practice/rest-api/rest_api_test.py index 72ba438426f..2ef7247d406 100644 --- a/exercises/practice/rest-api/rest_api_test.py +++ b/exercises/practice/rest-api/rest_api_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rest-api/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/reverse-string/reverse_string_test.py b/exercises/practice/reverse-string/reverse_string_test.py index 8fe8df59979..79b9f6829c7 100644 --- a/exercises/practice/reverse-string/reverse_string_test.py +++ b/exercises/practice/reverse-string/reverse_string_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/reverse-string/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/rna-transcription/rna_transcription_test.py b/exercises/practice/rna-transcription/rna_transcription_test.py index cb6cf870547..65bb147609f 100644 --- a/exercises/practice/rna-transcription/rna_transcription_test.py +++ b/exercises/practice/rna-transcription/rna_transcription_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rna-transcription/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/robot-simulator/robot_simulator_test.py b/exercises/practice/robot-simulator/robot_simulator_test.py index 8349b7101dc..f401e7c35bd 100644 --- a/exercises/practice/robot-simulator/robot_simulator_test.py +++ b/exercises/practice/robot-simulator/robot_simulator_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/robot-simulator/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/roman-numerals/roman_numerals_test.py b/exercises/practice/roman-numerals/roman_numerals_test.py index 13b3245a215..2b64de76cb1 100644 --- a/exercises/practice/roman-numerals/roman_numerals_test.py +++ b/exercises/practice/roman-numerals/roman_numerals_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/roman-numerals/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/rotational-cipher/rotational_cipher_test.py b/exercises/practice/rotational-cipher/rotational_cipher_test.py index 802b54f9e1f..db460f2d922 100644 --- a/exercises/practice/rotational-cipher/rotational_cipher_test.py +++ b/exercises/practice/rotational-cipher/rotational_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rotational-cipher/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/run-length-encoding/run_length_encoding_test.py b/exercises/practice/run-length-encoding/run_length_encoding_test.py index 18f883a29eb..c3cccafb0b7 100644 --- a/exercises/practice/run-length-encoding/run_length_encoding_test.py +++ b/exercises/practice/run-length-encoding/run_length_encoding_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/run-length-encoding/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/saddle-points/saddle_points_test.py b/exercises/practice/saddle-points/saddle_points_test.py index fe966bae0ff..d9723555274 100644 --- a/exercises/practice/saddle-points/saddle_points_test.py +++ b/exercises/practice/saddle-points/saddle_points_test.py @@ -7,7 +7,7 @@ """ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/saddle-points/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/satellite/satellite_test.py b/exercises/practice/satellite/satellite_test.py index 60a34a7d65d..b7b23d02e36 100644 --- a/exercises/practice/satellite/satellite_test.py +++ b/exercises/practice/satellite/satellite_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/satellite/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/say/say_test.py b/exercises/practice/say/say_test.py index 6d54c85fa44..eaf72246123 100644 --- a/exercises/practice/say/say_test.py +++ b/exercises/practice/say/say_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/say/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/scale-generator/scale_generator_test.py b/exercises/practice/scale-generator/scale_generator_test.py index cec6aa34ef3..7cef2304948 100644 --- a/exercises/practice/scale-generator/scale_generator_test.py +++ b/exercises/practice/scale-generator/scale_generator_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/scale-generator/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/scrabble-score/scrabble_score_test.py b/exercises/practice/scrabble-score/scrabble_score_test.py index 5a5dca5c5cf..aeadf63f68f 100644 --- a/exercises/practice/scrabble-score/scrabble_score_test.py +++ b/exercises/practice/scrabble-score/scrabble_score_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/scrabble-score/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/secret-handshake/secret_handshake_test.py b/exercises/practice/secret-handshake/secret_handshake_test.py index 52f6f9116b8..0f1e4887ea3 100644 --- a/exercises/practice/secret-handshake/secret_handshake_test.py +++ b/exercises/practice/secret-handshake/secret_handshake_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/secret-handshake/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/series/series_test.py b/exercises/practice/series/series_test.py index 938ff7956d5..b69e3961cd5 100644 --- a/exercises/practice/series/series_test.py +++ b/exercises/practice/series/series_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/series/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/sgf-parsing/sgf_parsing_test.py b/exercises/practice/sgf-parsing/sgf_parsing_test.py index d157e9f9201..8927a78972f 100644 --- a/exercises/practice/sgf-parsing/sgf_parsing_test.py +++ b/exercises/practice/sgf-parsing/sgf_parsing_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sgf-parsing/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/sieve/sieve_test.py b/exercises/practice/sieve/sieve_test.py index 216e71b5248..aea5ad12644 100644 --- a/exercises/practice/sieve/sieve_test.py +++ b/exercises/practice/sieve/sieve_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sieve/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/simple-cipher/simple_cipher_test.py b/exercises/practice/simple-cipher/simple_cipher_test.py index 0747582c781..b3aa2ddb99e 100644 --- a/exercises/practice/simple-cipher/simple_cipher_test.py +++ b/exercises/practice/simple-cipher/simple_cipher_test.py @@ -2,7 +2,7 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/simple-cipher/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/space-age/space_age_test.py b/exercises/practice/space-age/space_age_test.py index 3b3ad508461..e5bbad29d2d 100644 --- a/exercises/practice/space-age/space_age_test.py +++ b/exercises/practice/space-age/space_age_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/space-age/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/spiral-matrix/spiral_matrix_test.py b/exercises/practice/spiral-matrix/spiral_matrix_test.py index fadb9935933..53015c6528d 100644 --- a/exercises/practice/spiral-matrix/spiral_matrix_test.py +++ b/exercises/practice/spiral-matrix/spiral_matrix_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/spiral-matrix/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/square-root/square_root_test.py b/exercises/practice/square-root/square_root_test.py index 8376c0dcbf4..1bd1d96d439 100644 --- a/exercises/practice/square-root/square_root_test.py +++ b/exercises/practice/square-root/square_root_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/square-root/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/sublist/sublist_test.py b/exercises/practice/sublist/sublist_test.py index 2794aa55da2..bb255c77d3c 100644 --- a/exercises/practice/sublist/sublist_test.py +++ b/exercises/practice/sublist/sublist_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sublist/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py index 1dc0eb943b6..179fba71a54 100644 --- a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py +++ b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sum-of-multiples/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/tournament/tournament_test.py b/exercises/practice/tournament/tournament_test.py index 3af02b561a8..45db6055bb5 100644 --- a/exercises/practice/tournament/tournament_test.py +++ b/exercises/practice/tournament/tournament_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/tournament/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/transpose/transpose_test.py b/exercises/practice/transpose/transpose_test.py index 29cbd35a2e8..4e4bee820d9 100644 --- a/exercises/practice/transpose/transpose_test.py +++ b/exercises/practice/transpose/transpose_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/transpose/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/triangle/triangle_test.py b/exercises/practice/triangle/triangle_test.py index 5ae01bc6566..5c4263cf1ba 100644 --- a/exercises/practice/triangle/triangle_test.py +++ b/exercises/practice/triangle/triangle_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/twelve-days/twelve_days_test.py b/exercises/practice/twelve-days/twelve_days_test.py index 6135922dff7..c48ee421ac2 100644 --- a/exercises/practice/twelve-days/twelve_days_test.py +++ b/exercises/practice/twelve-days/twelve_days_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/twelve-days/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/two-bucket/two_bucket_test.py b/exercises/practice/two-bucket/two_bucket_test.py index d8d77453103..5b5841cec28 100644 --- a/exercises/practice/two-bucket/two_bucket_test.py +++ b/exercises/practice/two-bucket/two_bucket_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/two-bucket/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/two-fer/two_fer_test.py b/exercises/practice/two-fer/two_fer_test.py index 31728bfe0de..f9e9760b2c9 100644 --- a/exercises/practice/two-fer/two_fer_test.py +++ b/exercises/practice/two-fer/two_fer_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/two-fer/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py index 45b1cdb53e0..032403d34d3 100644 --- a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py +++ b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/variable-length-quantity/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/word-count/word_count_test.py b/exercises/practice/word-count/word_count_test.py index 0714e8504b9..c6203359216 100644 --- a/exercises/practice/word-count/word_count_test.py +++ b/exercises/practice/word-count/word_count_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/word-count/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/word-search/word_search_test.py b/exercises/practice/word-search/word_search_test.py index a3bb890896b..ba1c7a7761c 100644 --- a/exercises/practice/word-search/word_search_test.py +++ b/exercises/practice/word-search/word_search_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/word-search/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/wordy/wordy_test.py b/exercises/practice/wordy/wordy_test.py index eaf81c5fa47..7a32eba420b 100644 --- a/exercises/practice/wordy/wordy_test.py +++ b/exercises/practice/wordy/wordy_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/wordy/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/yacht/.meta/template.j2 b/exercises/practice/yacht/.meta/template.j2 index 80eb31f7bcb..a9e3ebc4bc3 100644 --- a/exercises/practice/yacht/.meta/template.j2 +++ b/exercises/practice/yacht/.meta/template.j2 @@ -3,8 +3,6 @@ import unittest import {{ exercise }} -{{ macros.canonical_ref() }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} def test_{{ case["description"] | to_snake }}(self): diff --git a/exercises/practice/yacht/yacht_test.py b/exercises/practice/yacht/yacht_test.py index 813bc8fbe65..58566e06078 100644 --- a/exercises/practice/yacht/yacht_test.py +++ b/exercises/practice/yacht/yacht_test.py @@ -2,10 +2,6 @@ import yacht -# These tests are auto-generated with test data from: -# https://github.com/exercism/problem-specifications/tree/main/exercises/yacht/canonical-data.json -# File last updated on 2023-07-15 - class YachtTest(unittest.TestCase): def test_yacht(self): diff --git a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py index 7c8439e0384..b64fc9069c6 100644 --- a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py +++ b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/zebra-puzzle/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/exercises/practice/zipper/zipper_test.py b/exercises/practice/zipper/zipper_test.py index e7eab6c6b5c..10358358356 100644 --- a/exercises/practice/zipper/zipper_test.py +++ b/exercises/practice/zipper/zipper_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/zipper/canonical-data.json -# File last updated on 2023-07-15 +# File last updated on 2023-07-16 import unittest diff --git a/requirements.txt b/requirements.txt index 5b97def747d..712608f8550 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,5 @@ -astroid<=2.12.0 flake8~=5.0.4 pylint~=2.17.1 black<=22.3.0 yapf~=0.32.0 -tomli>=1.1.0; python_full_version < '3.11.2' \ No newline at end of file +tomli>=1.1.0; python_full_version < '3.11.2' From 6dcb6602a9a03c4fe9de8c16ed22a0f43f6fb07f Mon Sep 17 00:00:00 2001 From: meatball <69751659+meatball133@users.noreply.github.com> Date: Mon, 17 Jul 2023 00:39:29 +0200 Subject: [PATCH 117/126] Use tildas (#3468) Replaces backticks with tildas for the admonitions. --- concepts/unpacking-and-multiple-assignment/about.md | 12 ++++++------ .../introduction.md | 4 ++-- .../locomotive-engineer/.docs/instructions.md | 8 ++++---- .../locomotive-engineer/.docs/introduction.md | 12 ++++++------ 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/concepts/unpacking-and-multiple-assignment/about.md b/concepts/unpacking-and-multiple-assignment/about.md index e8abaa528d7..1cec2f92ec9 100644 --- a/concepts/unpacking-and-multiple-assignment/about.md +++ b/concepts/unpacking-and-multiple-assignment/about.md @@ -17,9 +17,9 @@ This is often used in multiple assignment to group all "leftover" elements that It is common in Python to also exploit this unpacking/packing behavior when using or defining functions that take an arbitrary number of positional or keyword arguments. You will often see these "special" parameters defined as `def some_function(*args, **kwargs)` and the "special" arguments used as `some_function(*some_tuple, **some_dict)`. -```exercism/caution +~~~~exercism/caution `*` and `**` should not be confused with `*` and `**`. While `*` and `**` are used for multiplication and exponentiation respectively, `*` and `**` are used as packing and unpacking operators. -``` +~~~~ ## Multiple assignment @@ -69,9 +69,9 @@ Since `tuples` are immutable, you can't swap elements in a `tuple`. ## Unpacking -```exercism/note +~~~~exercism/note The examples below use `lists` but the same concepts apply to `tuples`. -``` +~~~~ In Python, it is possible to [unpack the elements of `list`/`tuple`/`dictionary`][unpacking] into distinct variables. Since values appear within `lists`/`tuples` in a specific order, they are unpacked into variables in the same order: @@ -305,13 +305,13 @@ c = 3 You can also write parameters before `*args` to allow for specific positional arguments. Individual keyword arguments then have to appear before `**kwargs`. -```exercism/caution +~~~~exercism/caution [Arguments have to be structured](https://www.python-engineer.com/courses/advancedpython/18-function-arguments/) like this: `def my_function(, *args, , **kwargs)` If you don't follow this order then you will get an error. -``` +~~~~ ```python >>> def my_function(a, b, *args): diff --git a/concepts/unpacking-and-multiple-assignment/introduction.md b/concepts/unpacking-and-multiple-assignment/introduction.md index a4675a771ed..59cab3b4ec3 100644 --- a/concepts/unpacking-and-multiple-assignment/introduction.md +++ b/concepts/unpacking-and-multiple-assignment/introduction.md @@ -17,8 +17,8 @@ This is often used in multiple assignment to group all "leftover" elements that It is common in Python to also exploit this unpacking/packing behavior when using or defining functions that take an arbitrary number of positional or keyword arguments. You will often see these "special" parameters defined as `def some_function(*args, **kwargs)` and the "special" arguments used as `some_function(*some_tuple, **some_dict)`. -```exercism/caution +~~~~exercism/caution `*` and `**` should not be confused with `*` and `**`. While `*` and `**` are used for multiplication and exponentiation respectively, `*` and `**` are used as packing and unpacking operators. -``` +~~~~ [multiple assignment]: https://www.geeksforgeeks.org/assigning-multiple-variables-in-one-line-in-python/ diff --git a/exercises/concept/locomotive-engineer/.docs/instructions.md b/exercises/concept/locomotive-engineer/.docs/instructions.md index af914e4924f..1d915c143a1 100644 --- a/exercises/concept/locomotive-engineer/.docs/instructions.md +++ b/exercises/concept/locomotive-engineer/.docs/instructions.md @@ -4,10 +4,10 @@ Your friend Linus is a Locomotive Engineer who drives cargo trains between citie Although they are amazing at handling trains, they are not amazing at handling logistics or computers. They would like to enlist your programming help organizing train details and correcting mistakes in route data. -```exercism/note +~~~~exercism/note This exercise could easily be solved using slicing, indexing, and various `dict` methods. However, we would like you to practice packing, unpacking, and multiple assignment in solving each of the tasks below. -``` +~~~~ ## 1. Create a list of all wagons @@ -75,9 +75,9 @@ The first `dict` contains the origin and destination cities the train route runs The second `dict` contains other routing details such as train speed, length, or temperature. The function should return a consolidated `dict` with all routing information. -```exercism/note +~~~~exercism/note The second `dict` can contain different/more properties than the ones shown in the example. -``` +~~~~ ```python >>> extend_route_information({"from": "Berlin", "to": "Hamburg"}, {"length": "100", "speed": "50"}) diff --git a/exercises/concept/locomotive-engineer/.docs/introduction.md b/exercises/concept/locomotive-engineer/.docs/introduction.md index e010c075768..66d9ba15810 100644 --- a/exercises/concept/locomotive-engineer/.docs/introduction.md +++ b/exercises/concept/locomotive-engineer/.docs/introduction.md @@ -5,9 +5,9 @@ Unpacked values can then be assigned to variables within the same statement, whi The special operators `*` and `**` are often used in unpacking contexts and with multiple assignment. -```exercism/caution +~~~~exercism/caution `*` and `**` should not be confused with `*` and `**`. While `*` and `**` are used for multiplication and exponentiation respectively, `*` and `**` are used as packing and unpacking operators. -``` +~~~~ ## Multiple assignment @@ -57,9 +57,9 @@ Since `tuples` are immutable, you can't swap elements in a `tuple`. ## Unpacking -```exercism/note +~~~~exercism/note The examples below use `lists` but the same concepts apply to `tuples`. -``` +~~~~ In Python, it is possible to [unpack the elements of `list`/`tuple`/`dictionary`][unpacking] into distinct variables. Since values appear within `lists`/`tuples` in a specific order, they are unpacked into variables in the same order: @@ -293,13 +293,13 @@ c = 3 You can also write parameters before `*args` to allow for specific positional arguments. Individual keyword arguments then have to appear before `**kwargs`. -```exercism/caution +~~~~exercism/caution [Arguments have to be structured](https://www.python-engineer.com/courses/advancedpython/18-function-arguments/) like this: `def my_function(, *args, , **kwargs)` If you don't follow this order then you will get an error. -``` +~~~~ ```python >>> def my_function(a, b, *args): From a093eaa69411ecb5afaf62a48552c622849a6a91 Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Tue, 18 Jul 2023 10:33:08 +0200 Subject: [PATCH 118/126] Convert `average_run_time` to an integer. (#3464) There are two reasons for this change: 1. Having the average run time as a float gives the impression of being exact, whereas the actual run time wildly varies due to a wide variety of reasons (e.g. how busy it is on the server). That fractional component will almost never actually conform the real situation. 2. jq is often used to work with track config.json config files (e.g. to add elements to it), and it will remove any trailing .0 fractional part from a number, which caused configlet lint to fail. Those JQ scripts then have to work around this by manually adding .0 to it. --- config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.json b/config.json index f386ef39d6c..ec35a0a9c33 100644 --- a/config.json +++ b/config.json @@ -16,7 +16,7 @@ "highlightjs_language": "python" }, "test_runner": { - "average_run_time": 2.0 + "average_run_time": 2 }, "files": { "solution": ["%{snake_slug}.py"], From be794198e169c8e77d39194519b48f5df077735d Mon Sep 17 00:00:00 2001 From: BethanyG Date: Fri, 21 Jul 2023 16:54:40 -0700 Subject: [PATCH 119/126] [Resistor Color Expert]: Corrected Small Typos (#3469) * Corrected small typos around resistor bands. * Due to failing CI, alterations to the test generator script were needed. The generated vs submitted diff now skips the first three lines of the file so that the generation date is not picked up and flagged as needing regeneration. Sadly, a workaround was also needed to prevent Python difflib from noting the difference anyways and producing an empty "false positive" diff. All templates and test files also needed to be altered to ensure that the first three lines of every test file will always be the autogeneration comment and date. Hopefully, this will now stop the CI failures without creating any subtle additional bugs. * Touch up to bowling template. Added back the error raising utility. * Touch up to two-bucket template to add back in error raising utility. [no important files changed] --- bin/generate_tests.py | 40 +++++++++++++------ config/complexnumbers_template.j2 | 31 ++++++++++++++ config/generator_macros.j2 | 9 ----- config/master_template.j2 | 3 +- exercises/practice/acronym/.meta/template.j2 | 5 ++- exercises/practice/acronym/acronym_test.py | 2 +- .../practice/affine-cipher/.meta/template.j2 | 5 ++- .../affine-cipher/affine_cipher_test.py | 2 +- .../practice/all-your-base/.meta/template.j2 | 5 ++- .../all-your-base/all_your_base_test.py | 2 +- .../practice/allergies/.meta/template.j2 | 2 + .../practice/allergies/allergies_test.py | 2 +- .../practice/alphametics/.meta/template.j2 | 2 + .../practice/alphametics/alphametics_test.py | 2 +- exercises/practice/anagram/.meta/template.j2 | 1 + exercises/practice/anagram/anagram_test.py | 2 +- .../armstrong-numbers/.meta/template.j2 | 2 + .../armstrong_numbers_test.py | 2 +- .../practice/atbash-cipher/.meta/template.j2 | 2 + .../atbash-cipher/atbash_cipher_test.py | 2 +- .../practice/bank-account/.meta/template.j2 | 4 +- .../bank-account/bank_account_test.py | 2 +- .../practice/beer-song/.meta/template.j2 | 2 + .../practice/beer-song/beer_song_test.py | 2 +- .../binary-search-tree/.meta/template.j2 | 7 ++-- .../binary_search_tree_test.py | 2 +- .../practice/binary-search/.meta/template.j2 | 6 ++- .../binary-search/binary_search_test.py | 2 +- exercises/practice/bob/.meta/template.j2 | 3 ++ exercises/practice/bob/bob_test.py | 2 +- .../practice/book-store/.meta/template.j2 | 5 ++- .../practice/book-store/book_store_test.py | 2 +- .../practice/bottle-song/.meta/template.j2 | 2 + .../practice/bottle-song/bottle_song_test.py | 2 +- exercises/practice/bowling/.meta/template.j2 | 8 ++-- exercises/practice/bowling/bowling_test.py | 6 +-- exercises/practice/change/.meta/template.j2 | 4 +- exercises/practice/change/change_test.py | 2 +- .../circular-buffer/.meta/template.j2 | 6 ++- .../circular-buffer/circular_buffer_test.py | 2 +- exercises/practice/clock/.meta/template.j2 | 5 ++- exercises/practice/clock/clock_test.py | 2 +- .../collatz-conjecture/.meta/template.j2 | 5 ++- .../collatz_conjecture_test.py | 2 +- .../complex-numbers/.meta/template.j2 | 5 +-- .../complex-numbers/complex_numbers_test.py | 9 +---- exercises/practice/connect/connect_test.py | 6 +-- .../practice/crypto-square/.meta/template.j2 | 2 + .../crypto-square/crypto_square_test.py | 2 +- .../practice/custom-set/.meta/template.j2 | 2 + .../practice/custom-set/custom_set_test.py | 2 +- exercises/practice/darts/.meta/template.j2 | 4 +- exercises/practice/darts/darts_test.py | 2 +- exercises/practice/diamond/.meta/template.j2 | 4 +- exercises/practice/diamond/diamond_test.py | 2 +- .../difference-of-squares/.meta/template.j2 | 4 +- .../difference_of_squares_test.py | 2 +- .../practice/diffie-hellman/.meta/template.j2 | 5 ++- .../diffie-hellman/diffie_hellman_test.py | 2 +- .../practice/dnd-character/.meta/template.j2 | 2 + .../dnd-character/dnd_character_test.py | 2 +- exercises/practice/dominoes/.meta/template.j2 | 2 + exercises/practice/dominoes/dominoes_test.py | 2 +- exercises/practice/etl/.meta/template.j2 | 5 ++- exercises/practice/etl/etl_test.py | 2 +- .../practice/flatten-array/.meta/template.j2 | 4 +- .../flatten-array/flatten_array_test.py | 2 +- .../practice/food-chain/.meta/template.j2 | 4 +- .../practice/food-chain/food_chain_test.py | 2 +- exercises/practice/forth/.meta/template.j2 | 5 ++- exercises/practice/forth/forth_test.py | 2 +- .../practice/gigasecond/.meta/template.j2 | 2 + .../practice/gigasecond/gigasecond_test.py | 5 +-- .../practice/go-counting/go_counting_test.py | 10 +---- .../practice/grade-school/.meta/template.j2 | 7 +++- .../grade-school/grade_school_test.py | 2 +- exercises/practice/grains/.meta/template.j2 | 5 ++- exercises/practice/grains/grains_test.py | 2 +- exercises/practice/grep/.meta/template.j2 | 4 +- exercises/practice/grep/grep_test.py | 4 +- exercises/practice/hamming/.meta/template.j2 | 7 +++- exercises/practice/hamming/hamming_test.py | 2 +- .../practice/hello-world/.meta/template.j2 | 1 + .../practice/hello-world/hello_world_test.py | 4 ++ .../practice/high-scores/.meta/template.j2 | 9 +++-- .../practice/high-scores/high_scores_test.py | 2 +- exercises/practice/house/.meta/template.j2 | 2 + exercises/practice/house/house_test.py | 2 +- .../practice/isbn-verifier/.meta/template.j2 | 3 +- .../isbn-verifier/isbn_verifier_test.py | 2 +- exercises/practice/isogram/.meta/template.j2 | 7 +++- exercises/practice/isogram/isogram_test.py | 2 +- .../killer-sudoku-helper/.meta/template.j2 | 5 ++- .../killer_sudoku_helper_test.py | 2 +- .../kindergarten-garden/.meta/template.j2 | 7 +++- .../kindergarten_garden_test.py | 2 +- exercises/practice/knapsack/.meta/template.j2 | 4 +- exercises/practice/knapsack/knapsack_test.py | 2 +- .../largest-series-product/.meta/template.j2 | 8 ++-- .../largest_series_product_test.py | 2 +- exercises/practice/leap/.meta/template.j2 | 4 +- exercises/practice/leap/leap_test.py | 2 +- exercises/practice/ledger/.meta/template.j2 | 2 + exercises/practice/ledger/ledger_test.py | 2 +- .../practice/linked-list/.meta/template.j2 | 5 ++- .../practice/linked-list/linked_list_test.py | 2 +- exercises/practice/list-ops/.meta/template.j2 | 5 ++- exercises/practice/list-ops/list_ops_test.py | 2 +- exercises/practice/luhn/.meta/template.j2 | 7 +++- exercises/practice/luhn/luhn_test.py | 2 +- exercises/practice/markdown/.meta/template.j2 | 4 +- exercises/practice/markdown/markdown_test.py | 2 +- .../matching-brackets/.meta/template.j2 | 4 +- .../matching_brackets_test.py | 2 +- exercises/practice/matrix/.meta/template.j2 | 11 +++-- exercises/practice/matrix/matrix_test.py | 6 +-- exercises/practice/meetup/.meta/template.j2 | 8 ++-- exercises/practice/meetup/meetup_test.py | 5 +-- .../practice/minesweeper/.meta/template.j2 | 7 +++- .../practice/minesweeper/minesweeper_test.py | 2 +- .../practice/nth-prime/.meta/template.j2 | 5 ++- .../practice/nth-prime/nth_prime_test.py | 2 +- .../practice/ocr-numbers/.meta/template.j2 | 4 +- .../practice/ocr-numbers/ocr_numbers_test.py | 2 +- .../palindrome-products/.meta/template.j2 | 5 ++- .../palindrome_products_test.py | 2 +- exercises/practice/pangram/.meta/template.j2 | 5 ++- exercises/practice/pangram/pangram_test.py | 2 +- .../pascals-triangle/.meta/template.j2 | 2 + .../pascals-triangle/pascals_triangle_test.py | 5 +-- .../perfect-numbers/.meta/template.j2 | 5 ++- .../perfect-numbers/perfect_numbers_test.py | 2 +- .../practice/phone-number/.meta/template.j2 | 3 ++ .../phone-number/phone_number_test.py | 2 +- .../practice/pig-latin/.meta/template.j2 | 4 +- .../practice/pig-latin/pig_latin_test.py | 2 +- exercises/practice/poker/.meta/template.j2 | 2 + exercises/practice/poker/poker_test.py | 2 +- exercises/practice/pov/.meta/template.j2 | 11 ++--- exercises/practice/pov/pov_test.py | 2 +- .../practice/prime-factors/.meta/template.j2 | 4 +- .../prime-factors/prime_factors_test.py | 2 +- .../protein-translation/.meta/template.j2 | 4 +- .../protein_translation_test.py | 2 +- exercises/practice/proverb/.meta/template.j2 | 3 ++ exercises/practice/proverb/proverb_test.py | 2 +- .../pythagorean-triplet/.meta/template.j2 | 3 +- .../pythagorean_triplet_test.py | 2 +- .../practice/queen-attack/.meta/template.j2 | 2 + .../queen-attack/queen_attack_test.py | 2 +- .../rail-fence-cipher/.meta/template.j2 | 4 +- .../rail_fence_cipher_test.py | 2 +- .../practice/raindrops/.meta/template.j2 | 7 +++- .../practice/raindrops/raindrops_test.py | 2 +- .../rational-numbers/.meta/template.j2 | 6 +-- .../rational-numbers/rational_numbers_test.py | 4 +- exercises/practice/react/.meta/template.j2 | 5 ++- exercises/practice/react/react_test.py | 5 +-- .../practice/rectangles/.meta/template.j2 | 4 +- .../practice/rectangles/rectangles_test.py | 2 +- .../resistor-color-duo/.meta/template.j2 | 5 ++- .../resistor_color_duo_test.py | 2 +- .../.docs/instructions.md | 9 +++-- .../resistor-color-trio/.meta/template.j2 | 5 ++- .../resistor_color_trio_test.py | 2 +- .../practice/resistor-color/.meta/template.j2 | 4 +- .../resistor-color/resistor_color_test.py | 2 +- exercises/practice/rest-api/.meta/template.j2 | 4 +- exercises/practice/rest-api/rest_api_test.py | 4 +- .../practice/reverse-string/.meta/template.j2 | 4 +- .../reverse-string/reverse_string_test.py | 2 +- .../rna-transcription/.meta/template.j2 | 2 + .../rna_transcription_test.py | 2 +- .../robot-simulator/.meta/template.j2 | 4 +- .../robot-simulator/robot_simulator_test.py | 2 +- .../practice/roman-numerals/.meta/template.j2 | 2 + .../roman-numerals/roman_numerals_test.py | 2 +- .../rotational-cipher/.meta/template.j2 | 4 +- .../rotational_cipher_test.py | 2 +- .../run-length-encoding/.meta/template.j2 | 4 +- .../run_length_encoding_test.py | 2 +- .../practice/saddle-points/.meta/template.j2 | 11 ++--- .../saddle-points/saddle_points_test.py | 9 +---- .../practice/satellite/.meta/template.j2 | 4 +- .../practice/satellite/satellite_test.py | 2 +- exercises/practice/say/.meta/template.j2 | 6 ++- exercises/practice/say/say_test.py | 2 +- .../scale-generator/.meta/template.j2 | 4 +- .../scale-generator/scale_generator_test.py | 2 +- .../practice/scrabble-score/.meta/template.j2 | 5 ++- .../scrabble-score/scrabble_score_test.py | 2 +- .../secret-handshake/.meta/template.j2 | 4 +- .../secret-handshake/secret_handshake_test.py | 2 +- exercises/practice/series/.meta/template.j2 | 4 +- exercises/practice/series/series_test.py | 2 +- .../practice/sgf-parsing/.meta/template.j2 | 4 +- .../practice/sgf-parsing/sgf_parsing_test.py | 2 +- exercises/practice/sieve/.meta/template.j2 | 4 +- exercises/practice/sieve/sieve_test.py | 2 +- .../practice/simple-cipher/.meta/template.j2 | 3 ++ .../simple-cipher/simple_cipher_test.py | 5 +-- .../practice/space-age/.meta/template.j2 | 2 + .../practice/space-age/space_age_test.py | 2 +- .../practice/spiral-matrix/.meta/template.j2 | 4 +- .../spiral-matrix/spiral_matrix_test.py | 2 +- .../practice/square-root/.meta/template.j2 | 5 ++- .../practice/square-root/square_root_test.py | 2 +- exercises/practice/sublist/.meta/template.j2 | 5 ++- exercises/practice/sublist/sublist_test.py | 2 +- .../sum-of-multiples/.meta/template.j2 | 2 + .../sum-of-multiples/sum_of_multiples_test.py | 2 +- .../practice/tournament/.meta/template.j2 | 4 +- .../practice/tournament/tournament_test.py | 2 +- .../practice/transpose/.meta/template.j2 | 4 +- .../practice/transpose/transpose_test.py | 2 +- exercises/practice/triangle/.meta/template.j2 | 2 + exercises/practice/triangle/triangle_test.py | 2 +- .../practice/twelve-days/.meta/template.j2 | 5 ++- .../practice/twelve-days/twelve_days_test.py | 2 +- .../practice/two-bucket/.meta/template.j2 | 9 +++-- .../practice/two-bucket/two_bucket_test.py | 6 +-- exercises/practice/two-fer/.meta/template.j2 | 4 +- exercises/practice/two-fer/two_fer_test.py | 2 +- .../.meta/template.j2 | 6 ++- .../variable_length_quantity_test.py | 2 +- .../practice/word-count/.meta/template.j2 | 5 ++- .../practice/word-count/word_count_test.py | 2 +- .../practice/word-search/.meta/template.j2 | 2 + .../practice/word-search/word_search_test.py | 2 +- exercises/practice/wordy/.meta/template.j2 | 5 ++- exercises/practice/wordy/wordy_test.py | 2 +- exercises/practice/yacht/.meta/template.j2 | 3 +- exercises/practice/yacht/yacht_test.py | 5 ++- .../practice/zebra-puzzle/.meta/template.j2 | 4 +- .../zebra-puzzle/zebra_puzzle_test.py | 2 +- exercises/practice/zipper/.meta/template.j2 | 8 ++-- exercises/practice/zipper/zipper_test.py | 2 +- 237 files changed, 571 insertions(+), 330 deletions(-) create mode 100644 config/complexnumbers_template.j2 diff --git a/bin/generate_tests.py b/bin/generate_tests.py index 33580137058..6c9b1c38b98 100755 --- a/bin/generate_tests.py +++ b/bin/generate_tests.py @@ -261,6 +261,19 @@ def format_file(path: Path) -> NoReturn: def check_template(slug: str, tests_path: Path, tmpfile: Path): + """Generate a new test file and diff against existing file. + + Note: The timestamp in each test file creates issues with + Python difflib, so it is skipped when being prepped + for diff. + + You can see this "skipping" on lines 281 & 283. + However, this rather crude method creates + an empty "false positive" diff. This empty diff is + then skipped in lines 293 & 294, so that it can be + considered a pass.. + """ + try: check_ok = True if not tmpfile.is_file(): @@ -271,24 +284,25 @@ def check_template(slug: str, tests_path: Path, tmpfile: Path): check_ok = False if check_ok and not filecmp.cmp(tmpfile, tests_path): with tests_path.open() as f: - for line in range(4): - next(f) - current_lines = f.readlines() + current_lines = f.readlines()[3:] with tmpfile.open() as f: - for line in range(4): - next(f) - rendered_lines = f.readlines() - diff = difflib.unified_diff( + rendered_lines = f.readlines()[3:] + + diff = list(difflib.unified_diff( current_lines, rendered_lines, fromfile=f"[current] {tests_path.name}", tofile=f"[generated] {tmpfile.name}", - ) - logger.debug(f"{slug}: ##### DIFF START #####") - for line in diff: - logger.debug(line.strip()) - logger.debug(f"{slug}: ##### DIFF END #####") - check_ok = False + lineterm="\n", + )) + if not diff: + check_ok = True + else: + logger.debug(f"{slug}: ##### DIFF START #####") + for line in diff: + logger.debug(line.strip()) + logger.debug(f"{slug}: ##### DIFF END #####") + check_ok = False if not check_ok: logger.error( f"{slug}: check failed; tests must be regenerated with bin/generate_tests.py" diff --git a/config/complexnumbers_template.j2 b/config/complexnumbers_template.j2 new file mode 100644 index 00000000000..d70c866f1c5 --- /dev/null +++ b/config/complexnumbers_template.j2 @@ -0,0 +1,31 @@ +{%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +import math +{{ macros.header(imports=imports, ignore=ignore) }} + +{%- macro test_cases_recursive(cases) -%} +{% for case in cases -%} +{% if "cases" in case %} + # {{ case["description"] }} + {{ test_cases_recursive(case["cases"]) }} +{% else %} + {{ test_case(case) }} +{% endif -%} +{% endfor -%} +{% endmacro %} + +{% if not additional_tests -%} +{%- macro additional_tests() -%} + {{ test_cases_recursive(additional_cases) }} +{% endmacro %} +{%- endif %} + +class {{ exercise | camel_case }}Test(unittest.TestCase): + {{ test_cases_recursive(cases) }} + + {% if additional_cases | length -%} + # Additional tests for this track + {{ additional_tests() }} + {%- endif %} + diff --git a/config/generator_macros.j2 b/config/generator_macros.j2 index 37d8e45a800..b1927552927 100644 --- a/config/generator_macros.j2 +++ b/config/generator_macros.j2 @@ -16,7 +16,6 @@ {%- endmacro %} {% macro header(imports=[], ignore=[]) -%} -{{ canonical_ref() }} import unittest @@ -38,14 +37,6 @@ from {{ exercise | to_snake }} import ({% if imports -%} return self.assertRaisesRegex(exception, r".+") {%- endmacro %} -{% macro footer(_has_error_case) -%} -{% if has_error_case or _has_error_case %} -{{ utility() }} -{% endif %} -if __name__ == '__main__': - unittest.main() -{%- endmacro %} - {% macro empty_set(set, list, class_name) -%} {%- if list|length > 0 -%} {{ set }} = {{ class_name }}({{ list }}) diff --git a/config/master_template.j2 b/config/master_template.j2 index 4fe2b9798b5..774771fd5d1 100644 --- a/config/master_template.j2 +++ b/config/master_template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(imports=imports, ignore=ignore) }} {%- macro test_cases_recursive(cases) -%} @@ -25,4 +27,3 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): # Additional tests for this track {{ additional_tests() }} {%- endif %} -{{ macros.footer() }} diff --git a/exercises/practice/acronym/.meta/template.j2 b/exercises/practice/acronym/.meta/template.j2 index c2e35812b1b..3480ade6319 100644 --- a/exercises/practice/acronym/.meta/template.j2 +++ b/exercises/practice/acronym/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {% macro test_case(case) -%} {%- set input = case["input"] -%} @@ -8,7 +11,7 @@ "{{ case["expected"] }}" ) {%- endmacro %} -{{ macros.header()}} + class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/acronym/acronym_test.py b/exercises/practice/acronym/acronym_test.py index 6664ae5b20e..984deef60d2 100644 --- a/exercises/practice/acronym/acronym_test.py +++ b/exercises/practice/acronym/acronym_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/acronym/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/affine-cipher/.meta/template.j2 b/exercises/practice/affine-cipher/.meta/template.j2 index 2ccc2c7f863..2e92e2b4e59 100644 --- a/exercises/practice/affine-cipher/.meta/template.j2 +++ b/exercises/practice/affine-cipher/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {% macro test_supercase(supercase) %} {% for case in supercase["cases"] -%} @@ -25,8 +28,6 @@ def test_{{ case["description"] | to_snake }}(self): {% endif -%} {%- endmacro %} -{{ macros.header() }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases -%} {{ test_supercase(supercase) }} diff --git a/exercises/practice/affine-cipher/affine_cipher_test.py b/exercises/practice/affine-cipher/affine_cipher_test.py index f8e4fd59f05..f6d7c106c33 100644 --- a/exercises/practice/affine-cipher/affine_cipher_test.py +++ b/exercises/practice/affine-cipher/affine_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/affine-cipher/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/all-your-base/.meta/template.j2 b/exercises/practice/all-your-base/.meta/template.j2 index b19efb5b8b7..682f9d9e996 100644 --- a/exercises/practice/all-your-base/.meta/template.j2 +++ b/exercises/practice/all-your-base/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {%- macro func_call(case) -%} {{ case["property"] }}( @@ -22,8 +25,6 @@ {%- endif %} {% endmacro %} -{{ macros.header() }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} {{ test_case(case) }} diff --git a/exercises/practice/all-your-base/all_your_base_test.py b/exercises/practice/all-your-base/all_your_base_test.py index c9f04e8dac9..32c0b7b924a 100644 --- a/exercises/practice/all-your-base/all_your_base_test.py +++ b/exercises/practice/all-your-base/all_your_base_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/all-your-base/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/allergies/.meta/template.j2 b/exercises/practice/allergies/.meta/template.j2 index a15dc176392..d0085deb8e0 100644 --- a/exercises/practice/allergies/.meta/template.j2 +++ b/exercises/practice/allergies/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(imports=[ exercise | camel_case ]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/allergies/allergies_test.py b/exercises/practice/allergies/allergies_test.py index 11f65b9b3ff..8e10b9d59b6 100644 --- a/exercises/practice/allergies/allergies_test.py +++ b/exercises/practice/allergies/allergies_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/allergies/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/alphametics/.meta/template.j2 b/exercises/practice/alphametics/.meta/template.j2 index 73291b8a1ea..e051fd81ac3 100644 --- a/exercises/practice/alphametics/.meta/template.j2 +++ b/exercises/practice/alphametics/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/alphametics/alphametics_test.py b/exercises/practice/alphametics/alphametics_test.py index 911e409a3d6..6279b805c59 100644 --- a/exercises/practice/alphametics/alphametics_test.py +++ b/exercises/practice/alphametics/alphametics_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/alphametics/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/anagram/.meta/template.j2 b/exercises/practice/anagram/.meta/template.j2 index 1f74aef5bc0..c402f530b45 100644 --- a/exercises/practice/anagram/.meta/template.j2 +++ b/exercises/practice/anagram/.meta/template.j2 @@ -1,4 +1,5 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} {{ macros.header() }} diff --git a/exercises/practice/anagram/anagram_test.py b/exercises/practice/anagram/anagram_test.py index fddc11b4236..5b0e9c6c4d7 100644 --- a/exercises/practice/anagram/anagram_test.py +++ b/exercises/practice/anagram/anagram_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/anagram/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/armstrong-numbers/.meta/template.j2 b/exercises/practice/armstrong-numbers/.meta/template.j2 index d9a1cceb6d2..8f917dfffc0 100644 --- a/exercises/practice/armstrong-numbers/.meta/template.j2 +++ b/exercises/practice/armstrong-numbers/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py index e79430483e0..402476671db 100644 --- a/exercises/practice/armstrong-numbers/armstrong_numbers_test.py +++ b/exercises/practice/armstrong-numbers/armstrong_numbers_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/armstrong-numbers/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/atbash-cipher/.meta/template.j2 b/exercises/practice/atbash-cipher/.meta/template.j2 index 1ad9d5759cb..39908eb4bc7 100644 --- a/exercises/practice/atbash-cipher/.meta/template.j2 +++ b/exercises/practice/atbash-cipher/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/atbash-cipher/atbash_cipher_test.py b/exercises/practice/atbash-cipher/atbash_cipher_test.py index e6f5314cbbe..f8103f81b9a 100644 --- a/exercises/practice/atbash-cipher/atbash_cipher_test.py +++ b/exercises/practice/atbash-cipher/atbash_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/atbash-cipher/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/bank-account/.meta/template.j2 b/exercises/practice/bank-account/.meta/template.j2 index f077837a0fd..3372b2f7fdc 100644 --- a/exercises/practice/bank-account/.meta/template.j2 +++ b/exercises/practice/bank-account/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["BankAccount"]) }} {% macro test_case(case) -%} def test_{{ case["description"] | to_snake }}(self): account = BankAccount() @@ -36,7 +39,6 @@ {%- endif %} {% endmacro %} -{{ macros.header(["BankAccount"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/bank-account/bank_account_test.py b/exercises/practice/bank-account/bank_account_test.py index 815442113e9..c6e6b87020d 100644 --- a/exercises/practice/bank-account/bank_account_test.py +++ b/exercises/practice/bank-account/bank_account_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bank-account/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/beer-song/.meta/template.j2 b/exercises/practice/beer-song/.meta/template.j2 index 7fd4a26de74..1a2d6022879 100644 --- a/exercises/practice/beer-song/.meta/template.j2 +++ b/exercises/practice/beer-song/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/beer-song/beer_song_test.py b/exercises/practice/beer-song/beer_song_test.py index 8ab578a0cd9..9232ca1c9bc 100644 --- a/exercises/practice/beer-song/beer_song_test.py +++ b/exercises/practice/beer-song/beer_song_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/beer-song/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/binary-search-tree/.meta/template.j2 b/exercises/practice/binary-search-tree/.meta/template.j2 index e2606ddfcca..37177a163c6 100644 --- a/exercises/practice/binary-search-tree/.meta/template.j2 +++ b/exercises/practice/binary-search-tree/.meta/template.j2 @@ -1,6 +1,9 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} -{%- macro build_tree(tree_obj) -%} +{{ macros.header (imports=["BinarySearchTree", "TreeNode"]) }} + +{% macro build_tree(tree_obj) %} {%- if tree_obj is none -%} None {%- else -%} @@ -25,8 +28,6 @@ TreeNode("{{ tree_obj["data"] }}", self.{{ assertion }}(BinarySearchTree({{ tree_data }}).{{ prop | to_snake }}(),expected) {%- endmacro -%} -{{ macros.header (imports=["BinarySearchTree", "TreeNode"]) }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {%- for case in cases %} {%- if "cases" in case %} diff --git a/exercises/practice/binary-search-tree/binary_search_tree_test.py b/exercises/practice/binary-search-tree/binary_search_tree_test.py index 8a4d0ff9a24..f44fe2d5f92 100644 --- a/exercises/practice/binary-search-tree/binary_search_tree_test.py +++ b/exercises/practice/binary-search-tree/binary_search_tree_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search-tree/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/binary-search/.meta/template.j2 b/exercises/practice/binary-search/.meta/template.j2 index f29df253194..0856646f6a9 100644 --- a/exercises/practice/binary-search/.meta/template.j2 +++ b/exercises/practice/binary-search/.meta/template.j2 @@ -1,13 +1,15 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header() }} {%- macro test_call(case) %} {{ case["property"] }}( {{ case["input"]["array"] }}, {{ case["input"]["value"] }} ) -{% endmacro -%} +{% endmacro %} -{{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/binary-search/binary_search_test.py b/exercises/practice/binary-search/binary_search_test.py index b0bb4bac96c..a47a87f9654 100644 --- a/exercises/practice/binary-search/binary_search_test.py +++ b/exercises/practice/binary-search/binary_search_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/binary-search/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/bob/.meta/template.j2 b/exercises/practice/bob/.meta/template.j2 index 07df6e8eff7..912f7e31bb0 100644 --- a/exercises/practice/bob/.meta/template.j2 +++ b/exercises/practice/bob/.meta/template.j2 @@ -1,6 +1,9 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header() }} + class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} def test_{{ case["description"] | to_snake }}(self): diff --git a/exercises/practice/bob/bob_test.py b/exercises/practice/bob/bob_test.py index 63d40c0315b..faba5f9612e 100644 --- a/exercises/practice/bob/bob_test.py +++ b/exercises/practice/bob/bob_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bob/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/book-store/.meta/template.j2 b/exercises/practice/book-store/.meta/template.j2 index 735ecb6487c..9e17ab02ee5 100644 --- a/exercises/practice/book-store/.meta/template.j2 +++ b/exercises/practice/book-store/.meta/template.j2 @@ -1,11 +1,14 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header() }} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): basket = {{ input["basket"] }} self.assertEqual({{ case["property"] }}(basket), {{ case["expected"] }}) {%- endmacro %} -{{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/book-store/book_store_test.py b/exercises/practice/book-store/book_store_test.py index 9d71b0cf7ec..87b0051faa2 100644 --- a/exercises/practice/book-store/book_store_test.py +++ b/exercises/practice/book-store/book_store_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/book-store/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/bottle-song/.meta/template.j2 b/exercises/practice/bottle-song/.meta/template.j2 index 7fd4a26de74..1a2d6022879 100644 --- a/exercises/practice/bottle-song/.meta/template.j2 +++ b/exercises/practice/bottle-song/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/bottle-song/bottle_song_test.py b/exercises/practice/bottle-song/bottle_song_test.py index e947b18f90c..998721d4bfe 100644 --- a/exercises/practice/bottle-song/bottle_song_test.py +++ b/exercises/practice/bottle-song/bottle_song_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bottle-song/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/bowling/.meta/template.j2 b/exercises/practice/bowling/.meta/template.j2 index 8234dd1c5a4..2761a8de840 100644 --- a/exercises/practice/bowling/.meta/template.j2 +++ b/exercises/practice/bowling/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["BowlingGame"]) }} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -16,7 +20,6 @@ self.assertEqual(game.score(), {{ case["expected"] }}) {% endif %} {%- endmacro %} -{{ macros.header(["BowlingGame"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): def roll_new_game(self, rolls): @@ -29,5 +32,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {{ test_case(case) }} {% endfor %} - -{{ macros.footer() }} +{{ macros.utility() }} diff --git a/exercises/practice/bowling/bowling_test.py b/exercises/practice/bowling/bowling_test.py index bfefd55f0a4..45d6b874835 100644 --- a/exercises/practice/bowling/bowling_test.py +++ b/exercises/practice/bowling/bowling_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/bowling/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-21 import unittest @@ -211,7 +211,3 @@ def test_cannot_roll_after_bonus_rolls_for_strike(self): # Utility functions def assertRaisesWithMessage(self, exception): return self.assertRaisesRegex(exception, r".+") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/change/.meta/template.j2 b/exercises/practice/change/.meta/template.j2 index 72e4382dcb8..846a9652856 100644 --- a/exercises/practice/change/.meta/template.j2 +++ b/exercises/practice/change/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/change/change_test.py b/exercises/practice/change/change_test.py index 71664188320..f8699e2f6db 100644 --- a/exercises/practice/change/change_test.py +++ b/exercises/practice/change/change_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/change/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/circular-buffer/.meta/template.j2 b/exercises/practice/circular-buffer/.meta/template.j2 index 259d953949b..a7aea897f64 100644 --- a/exercises/practice/circular-buffer/.meta/template.j2 +++ b/exercises/practice/circular-buffer/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["CircularBuffer","BufferEmptyException", "BufferFullException"]) }} + {% macro call_op(op) -%} buf.{{ op["operation"] }}( {% if "item" in op -%} @@ -6,7 +10,7 @@ buf.{{ op["operation"] }}( {%- endif -%} ) {%- endmacro -%} -{{ macros.header(["CircularBuffer","BufferEmptyException", "BufferFullException"]) }} + class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/circular-buffer/circular_buffer_test.py b/exercises/practice/circular-buffer/circular_buffer_test.py index 077852a1d0c..eb0663cf503 100644 --- a/exercises/practice/circular-buffer/circular_buffer_test.py +++ b/exercises/practice/circular-buffer/circular_buffer_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/circular-buffer/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/clock/.meta/template.j2 b/exercises/practice/clock/.meta/template.j2 index c8cee7e08df..872dce0a42b 100644 --- a/exercises/practice/clock/.meta/template.j2 +++ b/exercises/practice/clock/.meta/template.j2 @@ -1,8 +1,11 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["Clock"])}} + {%- macro clock(obj) -%} Clock({{ obj["hour"] }}, {{ obj["minute"] }}) {%- endmacro -%} -{{ macros.header(["Clock"])}} {% set cases = additional_cases + cases %} diff --git a/exercises/practice/clock/clock_test.py b/exercises/practice/clock/clock_test.py index fa07e25b625..6fde8e83e7e 100644 --- a/exercises/practice/clock/clock_test.py +++ b/exercises/practice/clock/clock_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/clock/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/collatz-conjecture/.meta/template.j2 b/exercises/practice/collatz-conjecture/.meta/template.j2 index 4dcbae8550b..988f4a4ed98 100644 --- a/exercises/practice/collatz-conjecture/.meta/template.j2 +++ b/exercises/practice/collatz-conjecture/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} def test_{{ case["description"] | to_snake }}(self): {% set expected = case["expected"] -%} @@ -15,7 +19,6 @@ ) {% endif %} {%- endmacro %} -{{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py index 6c1dd797603..306e3db7e7c 100644 --- a/exercises/practice/collatz-conjecture/collatz_conjecture_test.py +++ b/exercises/practice/collatz-conjecture/collatz_conjecture_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/collatz-conjecture/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 import unittest diff --git a/exercises/practice/complex-numbers/.meta/template.j2 b/exercises/practice/complex-numbers/.meta/template.j2 index 86b0d71d849..7c3fb7d2dd8 100644 --- a/exercises/practice/complex-numbers/.meta/template.j2 +++ b/exercises/practice/complex-numbers/.meta/template.j2 @@ -1,7 +1,6 @@ -import math +{% extends "complexnumbers_template.j2" %} -{% extends "master_template.j2" -%} -{%- set imports = ["ComplexNumber"] -%} +{% set imports = ["ComplexNumber"] %} {%- macro translate_math(item) -%} {{ item | replace("pi", "math.pi") | replace("e", "math.e") | replace("ln", "math.log") }} diff --git a/exercises/practice/complex-numbers/complex_numbers_test.py b/exercises/practice/complex-numbers/complex_numbers_test.py index 4fd9c75ed54..3ebdcfe1082 100644 --- a/exercises/practice/complex-numbers/complex_numbers_test.py +++ b/exercises/practice/complex-numbers/complex_numbers_test.py @@ -1,9 +1,8 @@ -import math - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/complex-numbers/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +import math import unittest from complex_numbers import ( @@ -191,7 +190,3 @@ def test_inequality_of_real_part(self): def test_inequality_of_imaginary_part(self): self.assertNotEqual(ComplexNumber(1, 2), ComplexNumber(1, 1)) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/connect/connect_test.py b/exercises/practice/connect/connect_test.py index 18c7d8f94c7..e7303d35131 100644 --- a/exercises/practice/connect/connect_test.py +++ b/exercises/practice/connect/connect_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/connect/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest @@ -110,7 +110,3 @@ def test_x_wins_using_a_spiral_path(self): ) winner = game.get_winner() self.assertEqual(winner, "X") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/crypto-square/.meta/template.j2 b/exercises/practice/crypto-square/.meta/template.j2 index c33812e64c3..f968f0c7477 100644 --- a/exercises/practice/crypto-square/.meta/template.j2 +++ b/exercises/practice/crypto-square/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(['cipher_text']) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/crypto-square/crypto_square_test.py b/exercises/practice/crypto-square/crypto_square_test.py index 784450d366a..97630a67501 100644 --- a/exercises/practice/crypto-square/crypto_square_test.py +++ b/exercises/practice/crypto-square/crypto_square_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/crypto-square/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/custom-set/.meta/template.j2 b/exercises/practice/custom-set/.meta/template.j2 index d70a45c298f..e7a4ee7d379 100644 --- a/exercises/practice/custom-set/.meta/template.j2 +++ b/exercises/practice/custom-set/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {% set class_name = exercise | camel_case -%} {{ macros.header([class_name]) }} diff --git a/exercises/practice/custom-set/custom_set_test.py b/exercises/practice/custom-set/custom_set_test.py index e6d6bc120c8..9ee2bd19679 100644 --- a/exercises/practice/custom-set/custom_set_test.py +++ b/exercises/practice/custom-set/custom_set_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/custom-set/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/darts/.meta/template.j2 b/exercises/practice/darts/.meta/template.j2 index 35a5c37dd30..e08c6d83c53 100644 --- a/exercises/practice/darts/.meta/template.j2 +++ b/exercises/practice/darts/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/darts/darts_test.py b/exercises/practice/darts/darts_test.py index ed0ed9baa64..5e167046177 100644 --- a/exercises/practice/darts/darts_test.py +++ b/exercises/practice/darts/darts_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/darts/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/diamond/.meta/template.j2 b/exercises/practice/diamond/.meta/template.j2 index 5651fa6bc92..0175388cc32 100644 --- a/exercises/practice/diamond/.meta/template.j2 +++ b/exercises/practice/diamond/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/diamond/diamond_test.py b/exercises/practice/diamond/diamond_test.py index cf7f1bac5e5..6a3a2295098 100644 --- a/exercises/practice/diamond/diamond_test.py +++ b/exercises/practice/diamond/diamond_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/diamond/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/difference-of-squares/.meta/template.j2 b/exercises/practice/difference-of-squares/.meta/template.j2 index ffac71e2840..db8cc69e9ca 100644 --- a/exercises/practice/difference-of-squares/.meta/template.j2 +++ b/exercises/practice/difference-of-squares/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases %} diff --git a/exercises/practice/difference-of-squares/difference_of_squares_test.py b/exercises/practice/difference-of-squares/difference_of_squares_test.py index 08b3c35922c..aa7271907ac 100644 --- a/exercises/practice/difference-of-squares/difference_of_squares_test.py +++ b/exercises/practice/difference-of-squares/difference_of_squares_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/difference-of-squares/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/diffie-hellman/.meta/template.j2 b/exercises/practice/diffie-hellman/.meta/template.j2 index b9634cdc302..378c28423d3 100644 --- a/exercises/practice/diffie-hellman/.meta/template.j2 +++ b/exercises/practice/diffie-hellman/.meta/template.j2 @@ -1,7 +1,10 @@ {%- import "generator_macros.j2" as macros with context -%} -{% set class = exercise | camel_case -%} +{{ macros.canonical_ref() }} + {{ macros.header(["private_key", "public_key", "secret"]) }} +{% set class = exercise | camel_case -%} + class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} {% set property = case["property"] | to_snake -%} diff --git a/exercises/practice/diffie-hellman/diffie_hellman_test.py b/exercises/practice/diffie-hellman/diffie_hellman_test.py index 01ed7116eae..e24c4e742a1 100644 --- a/exercises/practice/diffie-hellman/diffie_hellman_test.py +++ b/exercises/practice/diffie-hellman/diffie_hellman_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/diffie-hellman/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/dnd-character/.meta/template.j2 b/exercises/practice/dnd-character/.meta/template.j2 index adb15650537..793f3d921d9 100644 --- a/exercises/practice/dnd-character/.meta/template.j2 +++ b/exercises/practice/dnd-character/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(["Character", "modifier"]) }} {% macro test_case(supercase) -%} diff --git a/exercises/practice/dnd-character/dnd_character_test.py b/exercises/practice/dnd-character/dnd_character_test.py index 16a7959834a..e506fdb1171 100644 --- a/exercises/practice/dnd-character/dnd_character_test.py +++ b/exercises/practice/dnd-character/dnd_character_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/dnd-character/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/dominoes/.meta/template.j2 b/exercises/practice/dominoes/.meta/template.j2 index 3ec60875d02..f1f226b3c59 100644 --- a/exercises/practice/dominoes/.meta/template.j2 +++ b/exercises/practice/dominoes/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header()}} {% macro tuplify(dominoes_list) -%} diff --git a/exercises/practice/dominoes/dominoes_test.py b/exercises/practice/dominoes/dominoes_test.py index 3d87ec5e584..4407036af12 100644 --- a/exercises/practice/dominoes/dominoes_test.py +++ b/exercises/practice/dominoes/dominoes_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/dominoes/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/etl/.meta/template.j2 b/exercises/practice/etl/.meta/template.j2 index 5669b6ed990..0fc3ccb39fd 100644 --- a/exercises/practice/etl/.meta/template.j2 +++ b/exercises/practice/etl/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -9,7 +13,6 @@ {{ case["property"] | to_snake }}(legacy_data), data ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/etl/etl_test.py b/exercises/practice/etl/etl_test.py index 8d9c628fe11..d6eed70a574 100644 --- a/exercises/practice/etl/etl_test.py +++ b/exercises/practice/etl/etl_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/etl/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/flatten-array/.meta/template.j2 b/exercises/practice/flatten-array/.meta/template.j2 index 425e92fee97..0a9a631fc77 100644 --- a/exercises/practice/flatten-array/.meta/template.j2 +++ b/exercises/practice/flatten-array/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/flatten-array/flatten_array_test.py b/exercises/practice/flatten-array/flatten_array_test.py index 4c69ab1f7cd..cecb3c5633f 100644 --- a/exercises/practice/flatten-array/flatten_array_test.py +++ b/exercises/practice/flatten-array/flatten_array_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/flatten-array/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/food-chain/.meta/template.j2 b/exercises/practice/food-chain/.meta/template.j2 index 619ada74c24..bc5c61d5712 100644 --- a/exercises/practice/food-chain/.meta/template.j2 +++ b/exercises/practice/food-chain/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/food-chain/food_chain_test.py b/exercises/practice/food-chain/food_chain_test.py index 1124f4f47c8..0cd42356ab1 100644 --- a/exercises/practice/food-chain/food_chain_test.py +++ b/exercises/practice/food-chain/food_chain_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/food-chain/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/forth/.meta/template.j2 b/exercises/practice/forth/.meta/template.j2 index b6fe07e71a0..0b5dd2b89ef 100644 --- a/exercises/practice/forth/.meta/template.j2 +++ b/exercises/practice/forth/.meta/template.j2 @@ -1,6 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{% set imports = ["evaluate", "StackUnderflowError"] %} -{{ macros.header(imports=imports, ignore=ignore) }} +{{ macros.canonical_ref() }} + +{{ macros.header(imports = ["evaluate", "StackUnderflowError"])}} {% macro test_case(group, case) -%} def test_{{ group | to_snake }}_{{ case["description"] | to_snake }}(self): diff --git a/exercises/practice/forth/forth_test.py b/exercises/practice/forth/forth_test.py index f4aa468d303..f8402bdd64c 100644 --- a/exercises/practice/forth/forth_test.py +++ b/exercises/practice/forth/forth_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/forth/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/gigasecond/.meta/template.j2 b/exercises/practice/gigasecond/.meta/template.j2 index 87b0a148436..e40462e2d8b 100644 --- a/exercises/practice/gigasecond/.meta/template.j2 +++ b/exercises/practice/gigasecond/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + from datetime import datetime {{ macros.header() }} diff --git a/exercises/practice/gigasecond/gigasecond_test.py b/exercises/practice/gigasecond/gigasecond_test.py index b7ebed264eb..dd648e14bd6 100644 --- a/exercises/practice/gigasecond/gigasecond_test.py +++ b/exercises/practice/gigasecond/gigasecond_test.py @@ -1,9 +1,8 @@ -from datetime import datetime - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/gigasecond/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +from datetime import datetime import unittest from gigasecond import ( diff --git a/exercises/practice/go-counting/go_counting_test.py b/exercises/practice/go-counting/go_counting_test.py index 43eaa5b246a..aec80a1b369 100644 --- a/exercises/practice/go-counting/go_counting_test.py +++ b/exercises/practice/go-counting/go_counting_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/go-counting/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest @@ -85,11 +85,3 @@ def test_two_region_rectangular_board(self): self.assertSetEqual(territories[BLACK], {(0, 0), (2, 0)}) self.assertSetEqual(territories[WHITE], set()) self.assertSetEqual(territories[NONE], set()) - - # Utility functions - def assertRaisesWithMessage(self, exception): - return self.assertRaisesRegex(exception, r".+") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/grade-school/.meta/template.j2 b/exercises/practice/grade-school/.meta/template.j2 index 8a86c1a8df7..a97fa010db0 100644 --- a/exercises/practice/grade-school/.meta/template.j2 +++ b/exercises/practice/grade-school/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["School"]) }} + {%- macro test_case( case) -%} {%- set input = case["input"] -%} {%- set property = case["property"] -%} @@ -15,8 +19,7 @@ {% else %} self.assertEqual(school.{{ case["property"] | to_snake }}(), expected) {%- endif %} -{% endmacro -%} -{{ macros.header(["School"]) }} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/grade-school/grade_school_test.py b/exercises/practice/grade-school/grade_school_test.py index 3f61d1303da..30d91c6c57d 100644 --- a/exercises/practice/grade-school/grade_school_test.py +++ b/exercises/practice/grade-school/grade_school_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/grade-school/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/grains/.meta/template.j2 b/exercises/practice/grains/.meta/template.j2 index 5ea2b5b0f8d..18180801d68 100644 --- a/exercises/practice/grains/.meta/template.j2 +++ b/exercises/practice/grains/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {% macro test_case(case) %} {%- set input = case["input"] %} @@ -16,8 +19,6 @@ {% endif %} {%- endmacro %} -{{ macros.header()}} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} {%- if "cases" in case -%} diff --git a/exercises/practice/grains/grains_test.py b/exercises/practice/grains/grains_test.py index 5820aa4ce18..8d729fb6f8e 100644 --- a/exercises/practice/grains/grains_test.py +++ b/exercises/practice/grains/grains_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/grains/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/grep/.meta/template.j2 b/exercises/practice/grep/.meta/template.j2 index 593bbc0781e..fdb09b6dbf6 100644 --- a/exercises/practice/grep/.meta/template.j2 +++ b/exercises/practice/grep/.meta/template.j2 @@ -1,6 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + import io +{{ macros.header()}} from unittest import mock {% set filenames = comments | join("\n") | regex_find("[a-z-]*\.txt") -%} diff --git a/exercises/practice/grep/grep_test.py b/exercises/practice/grep/grep_test.py index d15c2f39095..81952884566 100644 --- a/exercises/practice/grep/grep_test.py +++ b/exercises/practice/grep/grep_test.py @@ -1,13 +1,13 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/grep/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +import io import unittest from grep import ( grep, ) -import io from unittest import mock FILE_TEXT = { diff --git a/exercises/practice/hamming/.meta/template.j2 b/exercises/practice/hamming/.meta/template.j2 index 498fbc56ce6..23efd5b73e2 100644 --- a/exercises/practice/hamming/.meta/template.j2 +++ b/exercises/practice/hamming/.meta/template.j2 @@ -1,12 +1,15 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {%- macro test_call(case) %} {{ case["property"] }}( {% for arg in case["input"].values() -%} "{{ arg }}"{{ "," if not loop.last }} {% endfor %} ) -{% endmacro -%} -{{ macros.header() }} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/hamming/hamming_test.py b/exercises/practice/hamming/hamming_test.py index d9171a44498..df58ef002d8 100644 --- a/exercises/practice/hamming/hamming_test.py +++ b/exercises/practice/hamming/hamming_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/hamming/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/hello-world/.meta/template.j2 b/exercises/practice/hello-world/.meta/template.j2 index dbcde585e9c..600120d665f 100644 --- a/exercises/practice/hello-world/.meta/template.j2 +++ b/exercises/practice/hello-world/.meta/template.j2 @@ -1,4 +1,5 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} import unittest diff --git a/exercises/practice/hello-world/hello_world_test.py b/exercises/practice/hello-world/hello_world_test.py index 245f5434fa6..15473f5557b 100644 --- a/exercises/practice/hello-world/hello_world_test.py +++ b/exercises/practice/hello-world/hello_world_test.py @@ -1,3 +1,7 @@ +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/hello-world/canonical-data.json +# File last updated on 2023-07-19 + import unittest try: diff --git a/exercises/practice/high-scores/.meta/template.j2 b/exercises/practice/high-scores/.meta/template.j2 index c32ae121aee..36e218c5f47 100644 --- a/exercises/practice/high-scores/.meta/template.j2 +++ b/exercises/practice/high-scores/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["HighScores"]) }} + {%- macro get_property(property) %} {%- if property == "scores" %} scores @@ -19,10 +23,7 @@ highscores.personal_{{ function }}() self.assertEqual(highscores.{{ get_property(property) }}, expected) {% endif -%} -{% endmacro -%} - -{{ macros.header(["HighScores"]) }} - +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {%- for case in cases -%} diff --git a/exercises/practice/high-scores/high_scores_test.py b/exercises/practice/high-scores/high_scores_test.py index 46f14477f09..6a926e32fde 100644 --- a/exercises/practice/high-scores/high_scores_test.py +++ b/exercises/practice/high-scores/high_scores_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/high-scores/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/house/.meta/template.j2 b/exercises/practice/house/.meta/template.j2 index b855685dfda..6e61bc88ecc 100644 --- a/exercises/practice/house/.meta/template.j2 +++ b/exercises/practice/house/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/house/house_test.py b/exercises/practice/house/house_test.py index a64809f83a0..d859fb4f5ea 100644 --- a/exercises/practice/house/house_test.py +++ b/exercises/practice/house/house_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/house/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/isbn-verifier/.meta/template.j2 b/exercises/practice/isbn-verifier/.meta/template.j2 index 47392cfb29e..eae9dbc1148 100644 --- a/exercises/practice/isbn-verifier/.meta/template.j2 +++ b/exercises/practice/isbn-verifier/.meta/template.j2 @@ -1,6 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} -{{ macros.header() }} +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/isbn-verifier/isbn_verifier_test.py b/exercises/practice/isbn-verifier/isbn_verifier_test.py index 341afea5f3d..dbcddf19d48 100644 --- a/exercises/practice/isbn-verifier/isbn_verifier_test.py +++ b/exercises/practice/isbn-verifier/isbn_verifier_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/isbn-verifier/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/isogram/.meta/template.j2 b/exercises/practice/isogram/.meta/template.j2 index fbec4a93a84..d75c2f49044 100644 --- a/exercises/practice/isogram/.meta/template.j2 +++ b/exercises/practice/isogram/.meta/template.j2 @@ -1,12 +1,15 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {%- macro test_call(case) %} {{ case["property"] | to_snake }}( {% for arg in case["input"].values() -%} "{{ arg }}"{{ "," if not loop.last }} {% endfor %} ) -{% endmacro -%} -{{ macros.header() }} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {# All test cases in this exercise are nested, so use two for loops -#} diff --git a/exercises/practice/isogram/isogram_test.py b/exercises/practice/isogram/isogram_test.py index 09d7431d156..c65984f6e64 100644 --- a/exercises/practice/isogram/isogram_test.py +++ b/exercises/practice/isogram/isogram_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/isogram/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/killer-sudoku-helper/.meta/template.j2 b/exercises/practice/killer-sudoku-helper/.meta/template.j2 index c107933784f..43fca4aa994 100644 --- a/exercises/practice/killer-sudoku-helper/.meta/template.j2 +++ b/exercises/practice/killer-sudoku-helper/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -8,7 +12,6 @@ {{ case["input"]["cage"]["exclude"] }}), {{ case["expected"] }}) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases[0]["cases"] -%} diff --git a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py index 023687a9bc5..2479bfc8958 100644 --- a/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py +++ b/exercises/practice/killer-sudoku-helper/killer_sudoku_helper_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/killer-sudoku-helper/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/kindergarten-garden/.meta/template.j2 b/exercises/practice/kindergarten-garden/.meta/template.j2 index f1dc54254de..4ba100bbe6e 100644 --- a/exercises/practice/kindergarten-garden/.meta/template.j2 +++ b/exercises/practice/kindergarten-garden/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["Garden"]) }} + {%- macro test_case(group_name, case) -%} {%- set input = case["input"] -%} def test_{{ group_name | to_snake }}_ @@ -16,8 +20,7 @@ "{{ val | camel_case }}"{{- "," if not loop.last }} {% endfor %}] ) -{% endmacro -%} -{{ macros.header(["Garden"]) }} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for casegroup in cases %} diff --git a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py index 138cbb07920..fd4d0222388 100644 --- a/exercises/practice/kindergarten-garden/kindergarten_garden_test.py +++ b/exercises/practice/kindergarten-garden/kindergarten_garden_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/kindergarten-garden/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/knapsack/.meta/template.j2 b/exercises/practice/knapsack/.meta/template.j2 index 3c59a9e89cb..e4282e9ce30 100644 --- a/exercises/practice/knapsack/.meta/template.j2 +++ b/exercises/practice/knapsack/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/knapsack/knapsack_test.py b/exercises/practice/knapsack/knapsack_test.py index 5ce2abae03c..011f7ba8324 100644 --- a/exercises/practice/knapsack/knapsack_test.py +++ b/exercises/practice/knapsack/knapsack_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/knapsack/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/largest-series-product/.meta/template.j2 b/exercises/practice/largest-series-product/.meta/template.j2 index 7da257f4c2e..07fe947fb56 100644 --- a/exercises/practice/largest-series-product/.meta/template.j2 +++ b/exercises/practice/largest-series-product/.meta/template.j2 @@ -1,9 +1,11 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {%- macro test_call(case) -%} {{ case["property"] | to_snake }}("{{ case["input"]["digits"] }}", {{ case["input"]["span"] }}) -{%- endmacro -%} - -{{ macros.header() }} +{%- endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/largest-series-product/largest_series_product_test.py b/exercises/practice/largest-series-product/largest_series_product_test.py index 3d5a90858ab..e5056236736 100644 --- a/exercises/practice/largest-series-product/largest_series_product_test.py +++ b/exercises/practice/largest-series-product/largest_series_product_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/largest-series-product/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/leap/.meta/template.j2 b/exercises/practice/leap/.meta/template.j2 index 66516c2b0dd..d3607dcd3e3 100644 --- a/exercises/practice/leap/.meta/template.j2 +++ b/exercises/practice/leap/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/leap/leap_test.py b/exercises/practice/leap/leap_test.py index 69f5387962d..6a1d732c987 100644 --- a/exercises/practice/leap/leap_test.py +++ b/exercises/practice/leap/leap_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/leap/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/ledger/.meta/template.j2 b/exercises/practice/ledger/.meta/template.j2 index 8936a2ca9a2..a3dbcf26f70 100644 --- a/exercises/practice/ledger/.meta/template.j2 +++ b/exercises/practice/ledger/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(imports=["format_entries", "create_entry"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/ledger/ledger_test.py b/exercises/practice/ledger/ledger_test.py index d9d1027d995..cc37167146d 100644 --- a/exercises/practice/ledger/ledger_test.py +++ b/exercises/practice/ledger/ledger_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/ledger/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/linked-list/.meta/template.j2 b/exercises/practice/linked-list/.meta/template.j2 index a753efc3df4..604c5f5163c 100644 --- a/exercises/practice/linked-list/.meta/template.j2 +++ b/exercises/practice/linked-list/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["LinkedList"]) }} + {% macro test_case(case) -%} def test_{{ case["description"] | to_snake }}(self): lst = LinkedList() @@ -45,7 +49,6 @@ {%- endif %} {%- endmacro %} -{{ macros.header(["LinkedList"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/linked-list/linked_list_test.py b/exercises/practice/linked-list/linked_list_test.py index c73175609ac..6724a1ebcef 100644 --- a/exercises/practice/linked-list/linked_list_test.py +++ b/exercises/practice/linked-list/linked_list_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/linked-list/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/list-ops/.meta/template.j2 b/exercises/practice/list-ops/.meta/template.j2 index 3ce6a3033b2..2e0a1bdd639 100644 --- a/exercises/practice/list-ops/.meta/template.j2 +++ b/exercises/practice/list-ops/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(imports=["append", "concat", "foldl", "foldr", "length", "reverse", "filter as list_ops_filter", "map as list_ops_map"]) }} + {% macro lambdify(function) -%} {% set function = function.replace("(", "", 1).replace(")", "", 1).replace(" ->", ":") %} {% set function = function.replace("modulo", "%") %} @@ -36,7 +40,6 @@ {{ stringify(case["expected"]) }} ) {%- endmacro %} -{{ macros.header(imports=["append", "concat", "foldl", "foldr", "length", "reverse", "filter as list_ops_filter", "map as list_ops_map"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for casegroup in cases -%} diff --git a/exercises/practice/list-ops/list_ops_test.py b/exercises/practice/list-ops/list_ops_test.py index 0375d875648..ea0d2136599 100644 --- a/exercises/practice/list-ops/list_ops_test.py +++ b/exercises/practice/list-ops/list_ops_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/list-ops/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/luhn/.meta/template.j2 b/exercises/practice/luhn/.meta/template.j2 index af8489b3c89..568d26efc61 100644 --- a/exercises/practice/luhn/.meta/template.j2 +++ b/exercises/practice/luhn/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["Luhn"]) }} + {%- macro test_case(group_name, case) -%} {%- set input = case["input"] -%} def test_{{ group_name | to_snake }}_ @@ -16,8 +20,7 @@ "{{ val | camel_case }}", {% endfor %}] ) -{% endmacro -%} -{{ macros.header(["Luhn"]) }} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/luhn/luhn_test.py b/exercises/practice/luhn/luhn_test.py index a83c3999d49..58234eb7d55 100644 --- a/exercises/practice/luhn/luhn_test.py +++ b/exercises/practice/luhn/luhn_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/luhn/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/markdown/.meta/template.j2 b/exercises/practice/markdown/.meta/template.j2 index da2a037cec8..e0b5f717c7b 100644 --- a/exercises/practice/markdown/.meta/template.j2 +++ b/exercises/practice/markdown/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/markdown/markdown_test.py b/exercises/practice/markdown/markdown_test.py index 7d474900fcf..ad6d243a635 100644 --- a/exercises/practice/markdown/markdown_test.py +++ b/exercises/practice/markdown/markdown_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/markdown/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/matching-brackets/.meta/template.j2 b/exercises/practice/matching-brackets/.meta/template.j2 index 0d43598bfd5..53abdc8efbe 100644 --- a/exercises/practice/matching-brackets/.meta/template.j2 +++ b/exercises/practice/matching-brackets/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/matching-brackets/matching_brackets_test.py b/exercises/practice/matching-brackets/matching_brackets_test.py index e9693d23cd0..a8321d94ad1 100644 --- a/exercises/practice/matching-brackets/matching_brackets_test.py +++ b/exercises/practice/matching-brackets/matching_brackets_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/matching-brackets/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/matrix/.meta/template.j2 b/exercises/practice/matrix/.meta/template.j2 index ae1c08c3b68..090f7d85c88 100644 --- a/exercises/practice/matrix/.meta/template.j2 +++ b/exercises/practice/matrix/.meta/template.j2 @@ -1,16 +1,15 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["Matrix"])}} + {%- macro testcase(case) %} def test_{{ case["description"] | to_snake }}(self): matrix = Matrix("{{ case["input"]["string"] | replace('\n', '\\n') }}") self.assertEqual(matrix.{{ case["property"] | to_snake }}({{ case["input"]["index"]}} ), {{ case["expected"] }}) -{% endmacro -%} -{{ macros.header(["Matrix"])}} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {%- for case in cases -%} {{- testcase(case) -}} {% endfor %} - - -if __name__ == '__main__': - unittest.main() diff --git a/exercises/practice/matrix/matrix_test.py b/exercises/practice/matrix/matrix_test.py index 421f5bf6f7b..6f5ce7da5fe 100644 --- a/exercises/practice/matrix/matrix_test.py +++ b/exercises/practice/matrix/matrix_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/matrix/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest @@ -41,7 +41,3 @@ def test_can_extract_column_from_non_square_matrix_with_no_corresponding_row(sel def test_extract_column_where_numbers_have_different_widths(self): matrix = Matrix("89 1903 3\n18 3 1\n9 4 800") self.assertEqual(matrix.column(2), [1903, 3, 4]) - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/meetup/.meta/template.j2 b/exercises/practice/meetup/.meta/template.j2 index 39d9cf8db84..8078c5a3a34 100644 --- a/exercises/practice/meetup/.meta/template.j2 +++ b/exercises/practice/meetup/.meta/template.j2 @@ -1,4 +1,9 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +from datetime import date +{{ macros.header(imports=["meetup", "MeetupDayException"]) }} + {% macro test_case(case) -%} def test_{{ case["description"] | to_snake }}(self): {%- set input = namespace() %} @@ -18,9 +23,6 @@ {% endif %} {%- endmacro %} -from datetime import date -{{ macros.header(imports=["meetup", "MeetupDayException"]) }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} {{ test_case(case) }} diff --git a/exercises/practice/meetup/meetup_test.py b/exercises/practice/meetup/meetup_test.py index c9d5ce03448..ec9e22b556d 100644 --- a/exercises/practice/meetup/meetup_test.py +++ b/exercises/practice/meetup/meetup_test.py @@ -1,9 +1,8 @@ -from datetime import date - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/meetup/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +from datetime import date import unittest from meetup import ( diff --git a/exercises/practice/minesweeper/.meta/template.j2 b/exercises/practice/minesweeper/.meta/template.j2 index b34be795739..68570a9fd4b 100644 --- a/exercises/practice/minesweeper/.meta/template.j2 +++ b/exercises/practice/minesweeper/.meta/template.j2 @@ -1,8 +1,11 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {%- macro test_call(case) -%} {{ case["property"] | to_snake }}({{ case["input"]["minefield"] }}) -{%- endmacro -%} -{{ macros.header() }} +{%- endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/minesweeper/minesweeper_test.py b/exercises/practice/minesweeper/minesweeper_test.py index 192cb40bc39..f6ffab43609 100644 --- a/exercises/practice/minesweeper/minesweeper_test.py +++ b/exercises/practice/minesweeper/minesweeper_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/minesweeper/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/nth-prime/.meta/template.j2 b/exercises/practice/nth-prime/.meta/template.j2 index 453ade58894..ab3d42adff7 100644 --- a/exercises/practice/nth-prime/.meta/template.j2 +++ b/exercises/practice/nth-prime/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -14,7 +18,6 @@ ) {%- endif %} {%- endmacro %} -{{ macros.header()}} def prime_range(n): """Returns a list of the first n primes""" diff --git a/exercises/practice/nth-prime/nth_prime_test.py b/exercises/practice/nth-prime/nth_prime_test.py index ce42da6db35..6f30f30aa0f 100644 --- a/exercises/practice/nth-prime/nth_prime_test.py +++ b/exercises/practice/nth-prime/nth_prime_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/nth-prime/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/ocr-numbers/.meta/template.j2 b/exercises/practice/ocr-numbers/.meta/template.j2 index c829331802b..94286b1ef8b 100644 --- a/exercises/practice/ocr-numbers/.meta/template.j2 +++ b/exercises/practice/ocr-numbers/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/ocr-numbers/ocr_numbers_test.py b/exercises/practice/ocr-numbers/ocr_numbers_test.py index c7f058f1039..3d24adc557c 100644 --- a/exercises/practice/ocr-numbers/ocr_numbers_test.py +++ b/exercises/practice/ocr-numbers/ocr_numbers_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/ocr-numbers/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/palindrome-products/.meta/template.j2 b/exercises/practice/palindrome-products/.meta/template.j2 index 634adaf53fc..f1862fc0c88 100644 --- a/exercises/practice/palindrome-products/.meta/template.j2 +++ b/exercises/practice/palindrome-products/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {%- macro value_factor_unpacking(case) -%} {%- set input = case["input"] -%} @@ -24,8 +27,6 @@ {%- endif %} {% endmacro %} -{{ macros.header() }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} {{ test_case(case) }} diff --git a/exercises/practice/palindrome-products/palindrome_products_test.py b/exercises/practice/palindrome-products/palindrome_products_test.py index cbe5affe206..e9339b5d25d 100644 --- a/exercises/practice/palindrome-products/palindrome_products_test.py +++ b/exercises/practice/palindrome-products/palindrome_products_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/palindrome-products/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/pangram/.meta/template.j2 b/exercises/practice/pangram/.meta/template.j2 index a365b456863..df38b578777 100644 --- a/exercises/practice/pangram/.meta/template.j2 +++ b/exercises/practice/pangram/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -7,7 +11,6 @@ {{ case["expected"] }} ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {# All test cases in this exercise are nested, so use two for loops -#} diff --git a/exercises/practice/pangram/pangram_test.py b/exercises/practice/pangram/pangram_test.py index 867660aaa88..09e303d4407 100644 --- a/exercises/practice/pangram/pangram_test.py +++ b/exercises/practice/pangram/pangram_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pangram/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/pascals-triangle/.meta/template.j2 b/exercises/practice/pascals-triangle/.meta/template.j2 index 0041fd53c2b..936db7587c8 100644 --- a/exercises/practice/pascals-triangle/.meta/template.j2 +++ b/exercises/practice/pascals-triangle/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + import sys {{ macros.header() }} diff --git a/exercises/practice/pascals-triangle/pascals_triangle_test.py b/exercises/practice/pascals-triangle/pascals_triangle_test.py index 972ee660ffa..21f68895522 100644 --- a/exercises/practice/pascals-triangle/pascals_triangle_test.py +++ b/exercises/practice/pascals-triangle/pascals_triangle_test.py @@ -1,9 +1,8 @@ -import sys - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pascals-triangle/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +import sys import unittest from pascals_triangle import ( diff --git a/exercises/practice/perfect-numbers/.meta/template.j2 b/exercises/practice/perfect-numbers/.meta/template.j2 index c92e39ca402..e6cd0310043 100644 --- a/exercises/practice/perfect-numbers/.meta/template.j2 +++ b/exercises/practice/perfect-numbers/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -14,7 +18,6 @@ ) {% endif %} {%- endmacro %} -{{ macros.header()}} {% for case in cases -%} class {{ case["description"] | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/perfect-numbers/perfect_numbers_test.py b/exercises/practice/perfect-numbers/perfect_numbers_test.py index 2f4f9a9bbcc..eef8661cef1 100644 --- a/exercises/practice/perfect-numbers/perfect_numbers_test.py +++ b/exercises/practice/perfect-numbers/perfect_numbers_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/perfect-numbers/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/phone-number/.meta/template.j2 b/exercises/practice/phone-number/.meta/template.j2 index 2b2826217c1..faff6e206a9 100644 --- a/exercises/practice/phone-number/.meta/template.j2 +++ b/exercises/practice/phone-number/.meta/template.j2 @@ -1,7 +1,10 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {% set class = exercise | camel_case -%} {{ macros.header([class]) }} + class {{ class }}Test(unittest.TestCase): {% for case in cases -%} def test_{{ case["description"] | to_snake }}(self): diff --git a/exercises/practice/phone-number/phone_number_test.py b/exercises/practice/phone-number/phone_number_test.py index c7a1006eadc..2b018dfaaf3 100644 --- a/exercises/practice/phone-number/phone_number_test.py +++ b/exercises/practice/phone-number/phone_number_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/phone-number/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/pig-latin/.meta/template.j2 b/exercises/practice/pig-latin/.meta/template.j2 index fd284824ff0..5badcb774fd 100644 --- a/exercises/practice/pig-latin/.meta/template.j2 +++ b/exercises/practice/pig-latin/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases %} diff --git a/exercises/practice/pig-latin/pig_latin_test.py b/exercises/practice/pig-latin/pig_latin_test.py index c3d0a20d362..e5a441eb6b9 100644 --- a/exercises/practice/pig-latin/pig_latin_test.py +++ b/exercises/practice/pig-latin/pig_latin_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pig-latin/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/poker/.meta/template.j2 b/exercises/practice/poker/.meta/template.j2 index 86e2e8791a4..730d54dd69f 100644 --- a/exercises/practice/poker/.meta/template.j2 +++ b/exercises/practice/poker/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/poker/poker_test.py b/exercises/practice/poker/poker_test.py index 65e64867f5d..c80aad6f059 100644 --- a/exercises/practice/poker/poker_test.py +++ b/exercises/practice/poker/poker_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/poker/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/pov/.meta/template.j2 b/exercises/practice/pov/.meta/template.j2 index aee59684a19..00d1f005a37 100644 --- a/exercises/practice/pov/.meta/template.j2 +++ b/exercises/practice/pov/.meta/template.j2 @@ -1,6 +1,9 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} -{%- macro test_case(case) %} +{{ macros.header(["Tree"]) }} + +{% macro test_case(case) %} def test_{{ case["description"] | to_snake }}(self): tree = {{ write_tree(case["input"]["tree"]) }} {% if case["property"] == "fromPov" -%} @@ -8,7 +11,7 @@ {%- elif case["property"] == "pathTo" -%} {{ test_path_to(case) }} {%- endif -%} -{% endmacro -%} +{% endmacro %} {%- macro test_from_pov(case) -%} {% if case["expected"] -%} @@ -20,7 +23,7 @@ self.assertEqual(type(err.exception), ValueError) self.assertEqual(err.exception.args[0], "Tree could not be reoriented") {% endif -%} -{% endmacro -%} +{% endmacro %} {%- macro test_path_to(case) -%} {% if case["expected"] -%} @@ -47,8 +50,6 @@ ]{% endif %}) {%- endmacro -%} -{{ macros.header(["Tree"]) }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases -%} {%- for case in supercase["cases"] %} diff --git a/exercises/practice/pov/pov_test.py b/exercises/practice/pov/pov_test.py index a43d104234d..2436ebc2db9 100644 --- a/exercises/practice/pov/pov_test.py +++ b/exercises/practice/pov/pov_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pov/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/prime-factors/.meta/template.j2 b/exercises/practice/prime-factors/.meta/template.j2 index 4178af79aac..cc9a9fe3841 100644 --- a/exercises/practice/prime-factors/.meta/template.j2 +++ b/exercises/practice/prime-factors/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/prime-factors/prime_factors_test.py b/exercises/practice/prime-factors/prime_factors_test.py index d0554518c82..4f6865036e5 100644 --- a/exercises/practice/prime-factors/prime_factors_test.py +++ b/exercises/practice/prime-factors/prime_factors_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/prime-factors/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/protein-translation/.meta/template.j2 b/exercises/practice/protein-translation/.meta/template.j2 index a8391c37ffb..e0b591609f1 100644 --- a/exercises/practice/protein-translation/.meta/template.j2 +++ b/exercises/practice/protein-translation/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/protein-translation/protein_translation_test.py b/exercises/practice/protein-translation/protein_translation_test.py index cb87652d0b6..91e6324b6e3 100644 --- a/exercises/practice/protein-translation/protein_translation_test.py +++ b/exercises/practice/protein-translation/protein_translation_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/protein-translation/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/proverb/.meta/template.j2 b/exercises/practice/proverb/.meta/template.j2 index cf50a261903..333a2d47d73 100644 --- a/exercises/practice/proverb/.meta/template.j2 +++ b/exercises/practice/proverb/.meta/template.j2 @@ -1,5 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(imports=["proverb"]) }} + {{ "# PLEASE TAKE NOTE: Expected result lists for these test cases use **implicit line joining.**" }} {{ "# A new line in a result list below **does not** always equal a new list element." }} {{ "# Check comma placement carefully!" }} diff --git a/exercises/practice/proverb/proverb_test.py b/exercises/practice/proverb/proverb_test.py index 6e36151bf9d..8c09283c020 100644 --- a/exercises/practice/proverb/proverb_test.py +++ b/exercises/practice/proverb/proverb_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/proverb/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/pythagorean-triplet/.meta/template.j2 b/exercises/practice/pythagorean-triplet/.meta/template.j2 index 20d750c7743..96fa266789d 100644 --- a/exercises/practice/pythagorean-triplet/.meta/template.j2 +++ b/exercises/practice/pythagorean-triplet/.meta/template.j2 @@ -1,6 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} -{{ macros.header() }} +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py index c9307e4461e..91137932245 100644 --- a/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py +++ b/exercises/practice/pythagorean-triplet/pythagorean_triplet_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/pythagorean-triplet/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/queen-attack/.meta/template.j2 b/exercises/practice/queen-attack/.meta/template.j2 index 6a08c5251e2..b8be7aeaafa 100644 --- a/exercises/practice/queen-attack/.meta/template.j2 +++ b/exercises/practice/queen-attack/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(imports=['Queen']) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/queen-attack/queen_attack_test.py b/exercises/practice/queen-attack/queen_attack_test.py index 15520856242..e1289aebcef 100644 --- a/exercises/practice/queen-attack/queen_attack_test.py +++ b/exercises/practice/queen-attack/queen_attack_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/queen-attack/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/rail-fence-cipher/.meta/template.j2 b/exercises/practice/rail-fence-cipher/.meta/template.j2 index 2698af337cb..4df5b2c66d4 100644 --- a/exercises/practice/rail-fence-cipher/.meta/template.j2 +++ b/exercises/practice/rail-fence-cipher/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases %} diff --git a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py index e5466ee5993..f82066ca274 100644 --- a/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py +++ b/exercises/practice/rail-fence-cipher/rail_fence_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rail-fence-cipher/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/raindrops/.meta/template.j2 b/exercises/practice/raindrops/.meta/template.j2 index 1e025b8bf18..c84975c9bbb 100644 --- a/exercises/practice/raindrops/.meta/template.j2 +++ b/exercises/practice/raindrops/.meta/template.j2 @@ -1,12 +1,15 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {%- macro test_call(case) %} {{ case["property"] | to_snake }}( {% for arg in case["input"].values() -%} {{ arg }}{{- "," if not loop.last }} {% endfor %} ) -{% endmacro -%} -{{ macros.header() }} +{% endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/raindrops/raindrops_test.py b/exercises/practice/raindrops/raindrops_test.py index d84dd175b82..b07e70dc24a 100644 --- a/exercises/practice/raindrops/raindrops_test.py +++ b/exercises/practice/raindrops/raindrops_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/raindrops/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/rational-numbers/.meta/template.j2 b/exercises/practice/rational-numbers/.meta/template.j2 index 026bd1de48c..eb640c95757 100644 --- a/exercises/practice/rational-numbers/.meta/template.j2 +++ b/exercises/practice/rational-numbers/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(imports=["Rational"]) }} {%- set operators = { "add": "+", @@ -82,9 +85,6 @@ {%- endmacro %} -from __future__ import division -{{ macros.header(imports=["Rational"]) }} - class {{ exercise | camel_case }}Test(unittest.TestCase): {% for mathtypescases in cases %} # Tests of type: {{ mathtypescases["description"] }} diff --git a/exercises/practice/rational-numbers/rational_numbers_test.py b/exercises/practice/rational-numbers/rational_numbers_test.py index 062b582d253..181bb128bf2 100644 --- a/exercises/practice/rational-numbers/rational_numbers_test.py +++ b/exercises/practice/rational-numbers/rational_numbers_test.py @@ -1,8 +1,6 @@ -from __future__ import division - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rational-numbers/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/react/.meta/template.j2 b/exercises/practice/react/.meta/template.j2 index f9fb637c433..f46e0f39e3d 100644 --- a/exercises/practice/react/.meta/template.j2 +++ b/exercises/practice/react/.meta/template.j2 @@ -1,5 +1,9 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + from functools import partial +{{ macros.header(["InputCell", "ComputeCell"])}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} {%- set callback = [] -%} @@ -48,7 +52,6 @@ from functools import partial {%- endif %} {% endfor -%} {%- endmacro %} -{{ macros.header(["InputCell", "ComputeCell"])}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/react/react_test.py b/exercises/practice/react/react_test.py index ec54fa94cd5..1f917e40b41 100644 --- a/exercises/practice/react/react_test.py +++ b/exercises/practice/react/react_test.py @@ -1,9 +1,8 @@ -from functools import partial - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/react/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +from functools import partial import unittest from react import ( diff --git a/exercises/practice/rectangles/.meta/template.j2 b/exercises/practice/rectangles/.meta/template.j2 index c9b1f623f79..0061968aa25 100644 --- a/exercises/practice/rectangles/.meta/template.j2 +++ b/exercises/practice/rectangles/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/rectangles/rectangles_test.py b/exercises/practice/rectangles/rectangles_test.py index 67c4d77ed44..89de9f28647 100644 --- a/exercises/practice/rectangles/rectangles_test.py +++ b/exercises/practice/rectangles/rectangles_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rectangles/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/resistor-color-duo/.meta/template.j2 b/exercises/practice/resistor-color-duo/.meta/template.j2 index cabf271cae5..ac0a560ac0e 100644 --- a/exercises/practice/resistor-color-duo/.meta/template.j2 +++ b/exercises/practice/resistor-color-duo/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -7,7 +11,6 @@ {{ case["expected"] }} ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py index b1bb371597d..5a67016d894 100644 --- a/exercises/practice/resistor-color-duo/resistor_color_duo_test.py +++ b/exercises/practice/resistor-color-duo/resistor_color_duo_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-duo/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/resistor-color-expert/.docs/instructions.md b/exercises/practice/resistor-color-expert/.docs/instructions.md index f08801644c5..d76c567b5d0 100644 --- a/exercises/practice/resistor-color-expert/.docs/instructions.md +++ b/exercises/practice/resistor-color-expert/.docs/instructions.md @@ -41,7 +41,8 @@ The four-band resistor is built up like this: Meaning - orange-orange-brown-green would be 330 ohms with a ±0.5% tolerance. -- orange-orange-red would-grey would be 3300 ohms with ±0.005% tolerance. +- orange-orange-red-grey would be 3300 ohms with ±0.05% tolerance. + The difference between a four and five-band resistor is that the five-band resistor has an extra band to indicate a more precise value. | Band_1 | Band_2 | Band_3 | Band_4 | band_5 | @@ -50,9 +51,11 @@ The difference between a four and five-band resistor is that the five-band resis Meaning -- orange-orange-orange-black-green would be 330 ohms with a ±0.5% tolerance. +- orange-orange-orange-black-green would be 333 ohms with a ±0.5% tolerance. +- orange-red-orange-blue-violet would be 323M ohms with a ±0.10 tolerance. + There are also one band resistors. -This type of resistor only has the color black and has a value of 0. +One band resistors only have the color black with a value of 0. This exercise is about translating the resistor band colors into a label: diff --git a/exercises/practice/resistor-color-trio/.meta/template.j2 b/exercises/practice/resistor-color-trio/.meta/template.j2 index 54814bed31d..aa458450031 100644 --- a/exercises/practice/resistor-color-trio/.meta/template.j2 +++ b/exercises/practice/resistor-color-trio/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -7,7 +11,6 @@ "{{ case['expected']['value']}} {{ case['expected']['unit']}}" ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py index 90f5842b23b..05f794281d3 100644 --- a/exercises/practice/resistor-color-trio/resistor_color_trio_test.py +++ b/exercises/practice/resistor-color-trio/resistor_color_trio_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color-trio/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/resistor-color/.meta/template.j2 b/exercises/practice/resistor-color/.meta/template.j2 index 643a3b69f9c..0a6830e8ca2 100644 --- a/exercises/practice/resistor-color/.meta/template.j2 +++ b/exercises/practice/resistor-color/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/resistor-color/resistor_color_test.py b/exercises/practice/resistor-color/resistor_color_test.py index 4847708e80f..d86d7553215 100644 --- a/exercises/practice/resistor-color/resistor_color_test.py +++ b/exercises/practice/resistor-color/resistor_color_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/resistor-color/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/rest-api/.meta/template.j2 b/exercises/practice/rest-api/.meta/template.j2 index aa7afe8f4ea..a467adb569d 100644 --- a/exercises/practice/rest-api/.meta/template.j2 +++ b/exercises/practice/rest-api/.meta/template.j2 @@ -1,6 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header(imports=["RestAPI"]) }} +{{ macros.canonical_ref() }} + import json +{{ macros.header(imports=["RestAPI"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for casegroup in cases -%}{%- for case in casegroup["cases"] -%} diff --git a/exercises/practice/rest-api/rest_api_test.py b/exercises/practice/rest-api/rest_api_test.py index 2ef7247d406..6d0bd213a15 100644 --- a/exercises/practice/rest-api/rest_api_test.py +++ b/exercises/practice/rest-api/rest_api_test.py @@ -1,13 +1,13 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rest-api/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 +import json import unittest from rest_api import ( RestAPI, ) -import json class RestApiTest(unittest.TestCase): diff --git a/exercises/practice/reverse-string/.meta/template.j2 b/exercises/practice/reverse-string/.meta/template.j2 index f76cc28e4d5..bf60c0643e8 100644 --- a/exercises/practice/reverse-string/.meta/template.j2 +++ b/exercises/practice/reverse-string/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/reverse-string/reverse_string_test.py b/exercises/practice/reverse-string/reverse_string_test.py index 79b9f6829c7..0c3298704cc 100644 --- a/exercises/practice/reverse-string/reverse_string_test.py +++ b/exercises/practice/reverse-string/reverse_string_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/reverse-string/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/rna-transcription/.meta/template.j2 b/exercises/practice/rna-transcription/.meta/template.j2 index ebd1675187d..04caf39d50f 100644 --- a/exercises/practice/rna-transcription/.meta/template.j2 +++ b/exercises/practice/rna-transcription/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/rna-transcription/rna_transcription_test.py b/exercises/practice/rna-transcription/rna_transcription_test.py index 65bb147609f..766f20299e2 100644 --- a/exercises/practice/rna-transcription/rna_transcription_test.py +++ b/exercises/practice/rna-transcription/rna_transcription_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rna-transcription/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/robot-simulator/.meta/template.j2 b/exercises/practice/robot-simulator/.meta/template.j2 index e7297734377..787ff40bb63 100644 --- a/exercises/practice/robot-simulator/.meta/template.j2 +++ b/exercises/practice/robot-simulator/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(imports=["Robot", "NORTH", "EAST", "SOUTH", "WEST"]) }} {% macro test_case(case) -%} {%- set input = case["input"] -%} @@ -15,7 +18,6 @@ self.assertEqual(robot.direction, {{case["expected"]["direction"] | upper }}) {%- endmacro %} -{{ macros.header(imports=["Robot", "NORTH", "EAST", "SOUTH", "WEST"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases %} diff --git a/exercises/practice/robot-simulator/robot_simulator_test.py b/exercises/practice/robot-simulator/robot_simulator_test.py index f401e7c35bd..69825c11186 100644 --- a/exercises/practice/robot-simulator/robot_simulator_test.py +++ b/exercises/practice/robot-simulator/robot_simulator_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/robot-simulator/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/roman-numerals/.meta/template.j2 b/exercises/practice/roman-numerals/.meta/template.j2 index f85f619fa70..a972569f0f3 100644 --- a/exercises/practice/roman-numerals/.meta/template.j2 +++ b/exercises/practice/roman-numerals/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(["roman"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/roman-numerals/roman_numerals_test.py b/exercises/practice/roman-numerals/roman_numerals_test.py index 2b64de76cb1..d2120f9b151 100644 --- a/exercises/practice/roman-numerals/roman_numerals_test.py +++ b/exercises/practice/roman-numerals/roman_numerals_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/roman-numerals/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/rotational-cipher/.meta/template.j2 b/exercises/practice/rotational-cipher/.meta/template.j2 index 7db7871ea6d..94a54cf6a86 100644 --- a/exercises/practice/rotational-cipher/.meta/template.j2 +++ b/exercises/practice/rotational-cipher/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/rotational-cipher/rotational_cipher_test.py b/exercises/practice/rotational-cipher/rotational_cipher_test.py index db460f2d922..ca22735ef9b 100644 --- a/exercises/practice/rotational-cipher/rotational_cipher_test.py +++ b/exercises/practice/rotational-cipher/rotational_cipher_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/rotational-cipher/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/run-length-encoding/.meta/template.j2 b/exercises/practice/run-length-encoding/.meta/template.j2 index 54a4a5be613..6bd93167bc3 100644 --- a/exercises/practice/run-length-encoding/.meta/template.j2 +++ b/exercises/practice/run-length-encoding/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(['encode','decode'])}} {% macro test_case(case, tmod) -%} {%- set input = case["input"] -%} @@ -13,7 +16,6 @@ ) {%- endmacro %} -{{ macros.header(['encode','decode'])}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases -%} diff --git a/exercises/practice/run-length-encoding/run_length_encoding_test.py b/exercises/practice/run-length-encoding/run_length_encoding_test.py index c3cccafb0b7..8d65cb62e23 100644 --- a/exercises/practice/run-length-encoding/run_length_encoding_test.py +++ b/exercises/practice/run-length-encoding/run_length_encoding_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/run-length-encoding/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/saddle-points/.meta/template.j2 b/exercises/practice/saddle-points/.meta/template.j2 index 35e4ed56b9b..d04e6d0e883 100644 --- a/exercises/practice/saddle-points/.meta/template.j2 +++ b/exercises/practice/saddle-points/.meta/template.j2 @@ -1,11 +1,7 @@ -"""Tests for the saddle-points exercise +{%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} -Implementation note: -The saddle_points function must validate the input matrix and raise a -ValueError with a meaningful error message if the matrix turns out to be -irregular. -""" -{% import "generator_macros.j2" as macros with context -%} +{{ macros.header()}} {% macro test_case(case) -%} {%- set input = case["input"] -%} @@ -29,7 +25,6 @@ irregular. {% endif -%} {% endmacro -%} -{{ macros.header()}} def sorted_points(point_list): return sorted(point_list, key=lambda p: (p["row"], p["column"])) diff --git a/exercises/practice/saddle-points/saddle_points_test.py b/exercises/practice/saddle-points/saddle_points_test.py index d9723555274..78ddf2484d9 100644 --- a/exercises/practice/saddle-points/saddle_points_test.py +++ b/exercises/practice/saddle-points/saddle_points_test.py @@ -1,13 +1,6 @@ -"""Tests for the saddle-points exercise - -Implementation note: -The saddle_points function must validate the input matrix and raise a -ValueError with a meaningful error message if the matrix turns out to be -irregular. -""" # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/saddle-points/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/satellite/.meta/template.j2 b/exercises/practice/satellite/.meta/template.j2 index 3bd41df23aa..d8ee854568a 100644 --- a/exercises/practice/satellite/.meta/template.j2 +++ b/exercises/practice/satellite/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/satellite/satellite_test.py b/exercises/practice/satellite/satellite_test.py index b7b23d02e36..f44a5384798 100644 --- a/exercises/practice/satellite/satellite_test.py +++ b/exercises/practice/satellite/satellite_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/satellite/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/say/.meta/template.j2 b/exercises/practice/say/.meta/template.j2 index 77fa67a1ca3..81d61a694c7 100644 --- a/exercises/practice/say/.meta/template.j2 +++ b/exercises/practice/say/.meta/template.j2 @@ -1,12 +1,14 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {%- macro test_call(case) %} {{ case["property"] }}( {{ case["input"]["number"] }} ) -{% endmacro -%} +{% endmacro %} -{{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/say/say_test.py b/exercises/practice/say/say_test.py index eaf72246123..1b9cbdea929 100644 --- a/exercises/practice/say/say_test.py +++ b/exercises/practice/say/say_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/say/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/scale-generator/.meta/template.j2 b/exercises/practice/scale-generator/.meta/template.j2 index da566b8abe2..d802db09b4f 100644 --- a/exercises/practice/scale-generator/.meta/template.j2 +++ b/exercises/practice/scale-generator/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["Scale"])}} {% macro test_case(case) -%} {%- set tonic = case["input"]["tonic"] -%} @@ -19,7 +22,6 @@ {% endfor %} {%- endmacro %} -{{ macros.header(["Scale"])}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for supercase in cases %} diff --git a/exercises/practice/scale-generator/scale_generator_test.py b/exercises/practice/scale-generator/scale_generator_test.py index 7cef2304948..c2346119b6d 100644 --- a/exercises/practice/scale-generator/scale_generator_test.py +++ b/exercises/practice/scale-generator/scale_generator_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/scale-generator/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/scrabble-score/.meta/template.j2 b/exercises/practice/scrabble-score/.meta/template.j2 index ea6c9ae2248..0688c940fdd 100644 --- a/exercises/practice/scrabble-score/.meta/template.j2 +++ b/exercises/practice/scrabble-score/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -7,7 +11,6 @@ {{ case["expected"] }} ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/scrabble-score/scrabble_score_test.py b/exercises/practice/scrabble-score/scrabble_score_test.py index aeadf63f68f..7121cf640e1 100644 --- a/exercises/practice/scrabble-score/scrabble_score_test.py +++ b/exercises/practice/scrabble-score/scrabble_score_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/scrabble-score/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/secret-handshake/.meta/template.j2 b/exercises/practice/secret-handshake/.meta/template.j2 index f5791a8bd8a..b45136a57c2 100644 --- a/exercises/practice/secret-handshake/.meta/template.j2 +++ b/exercises/practice/secret-handshake/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/secret-handshake/secret_handshake_test.py b/exercises/practice/secret-handshake/secret_handshake_test.py index 0f1e4887ea3..544da4e2718 100644 --- a/exercises/practice/secret-handshake/secret_handshake_test.py +++ b/exercises/practice/secret-handshake/secret_handshake_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/secret-handshake/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/series/.meta/template.j2 b/exercises/practice/series/.meta/template.j2 index 2e7f60e4fd2..c9ac185ab0c 100644 --- a/exercises/practice/series/.meta/template.j2 +++ b/exercises/practice/series/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/series/series_test.py b/exercises/practice/series/series_test.py index b69e3961cd5..5e0a33d9932 100644 --- a/exercises/practice/series/series_test.py +++ b/exercises/practice/series/series_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/series/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/sgf-parsing/.meta/template.j2 b/exercises/practice/sgf-parsing/.meta/template.j2 index 7017a436480..3e968bec534 100644 --- a/exercises/practice/sgf-parsing/.meta/template.j2 +++ b/exercises/practice/sgf-parsing/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(["parse","SgfTree"])}} {% macro escape_sequences(string) -%} {{ string | replace("\\", "\\\\") | replace("\n", "\\n") | replace("\t", "\\t") }} @@ -43,7 +46,6 @@ {% endfor -%} } {%- endmacro -%} -{{ macros.header(["parse","SgfTree"])}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/sgf-parsing/sgf_parsing_test.py b/exercises/practice/sgf-parsing/sgf_parsing_test.py index 8927a78972f..c33a5dbecff 100644 --- a/exercises/practice/sgf-parsing/sgf_parsing_test.py +++ b/exercises/practice/sgf-parsing/sgf_parsing_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sgf-parsing/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/sieve/.meta/template.j2 b/exercises/practice/sieve/.meta/template.j2 index 68a9db82a60..d12df86bb15 100644 --- a/exercises/practice/sieve/.meta/template.j2 +++ b/exercises/practice/sieve/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/sieve/sieve_test.py b/exercises/practice/sieve/sieve_test.py index aea5ad12644..d9b88558316 100644 --- a/exercises/practice/sieve/sieve_test.py +++ b/exercises/practice/sieve/sieve_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sieve/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/simple-cipher/.meta/template.j2 b/exercises/practice/simple-cipher/.meta/template.j2 index ce9ad3e4468..fa7483a5590 100644 --- a/exercises/practice/simple-cipher/.meta/template.j2 +++ b/exercises/practice/simple-cipher/.meta/template.j2 @@ -1,6 +1,9 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + import re {{ macros.header(imports=['Cipher']) }} + {%- macro convert_js(s) -%} {{ s | regex_replace("\\.substring\\((\\d+), ([^)]+)\\)", "[\\1:\\2]") | diff --git a/exercises/practice/simple-cipher/simple_cipher_test.py b/exercises/practice/simple-cipher/simple_cipher_test.py index b3aa2ddb99e..bc1efa9f86d 100644 --- a/exercises/practice/simple-cipher/simple_cipher_test.py +++ b/exercises/practice/simple-cipher/simple_cipher_test.py @@ -1,9 +1,8 @@ -import re - # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/simple-cipher/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-20 +import re import unittest from simple_cipher import ( diff --git a/exercises/practice/space-age/.meta/template.j2 b/exercises/practice/space-age/.meta/template.j2 index 15c8c550325..d939487f8a3 100644 --- a/exercises/practice/space-age/.meta/template.j2 +++ b/exercises/practice/space-age/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(["SpaceAge"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/space-age/space_age_test.py b/exercises/practice/space-age/space_age_test.py index e5bbad29d2d..ddde365d6bf 100644 --- a/exercises/practice/space-age/space_age_test.py +++ b/exercises/practice/space-age/space_age_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/space-age/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/spiral-matrix/.meta/template.j2 b/exercises/practice/spiral-matrix/.meta/template.j2 index 2a73e6bccb2..552b48831cf 100644 --- a/exercises/practice/spiral-matrix/.meta/template.j2 +++ b/exercises/practice/spiral-matrix/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/spiral-matrix/spiral_matrix_test.py b/exercises/practice/spiral-matrix/spiral_matrix_test.py index 53015c6528d..49174455977 100644 --- a/exercises/practice/spiral-matrix/spiral_matrix_test.py +++ b/exercises/practice/spiral-matrix/spiral_matrix_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/spiral-matrix/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/square-root/.meta/template.j2 b/exercises/practice/square-root/.meta/template.j2 index 9334317859f..9038eb171a0 100644 --- a/exercises/practice/square-root/.meta/template.j2 +++ b/exercises/practice/square-root/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -7,7 +11,6 @@ {{ case["expected"] }} ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/square-root/square_root_test.py b/exercises/practice/square-root/square_root_test.py index 1bd1d96d439..8f94940f552 100644 --- a/exercises/practice/square-root/square_root_test.py +++ b/exercises/practice/square-root/square_root_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/square-root/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/sublist/.meta/template.j2 b/exercises/practice/sublist/.meta/template.j2 index 00c111f3fc7..ecd410bdaa1 100644 --- a/exercises/practice/sublist/.meta/template.j2 +++ b/exercises/practice/sublist/.meta/template.j2 @@ -1,10 +1,13 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header(imports=["sublist", "SUBLIST", "SUPERLIST", "EQUAL", "UNEQUAL"]) }} + {% macro test_case(case) -%} def test_{{ case["description"] | to_snake }}(self): self.assertEqual({{ case["property"] }}({{ case["input"]["listOne"] }}, {{ case["input"]["listTwo"] }}), {{ case["expected"] | upper }}) {%- endmacro %} -{{ macros.header(imports=["sublist", "SUBLIST", "SUPERLIST", "EQUAL", "UNEQUAL"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/sublist/sublist_test.py b/exercises/practice/sublist/sublist_test.py index bb255c77d3c..af9a7799c10 100644 --- a/exercises/practice/sublist/sublist_test.py +++ b/exercises/practice/sublist/sublist_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sublist/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/sum-of-multiples/.meta/template.j2 b/exercises/practice/sum-of-multiples/.meta/template.j2 index 39dab6ada1b..03574ec7e8a 100644 --- a/exercises/practice/sum-of-multiples/.meta/template.j2 +++ b/exercises/practice/sum-of-multiples/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(["sum_of_multiples"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py index 179fba71a54..0057ee7a7f5 100644 --- a/exercises/practice/sum-of-multiples/sum_of_multiples_test.py +++ b/exercises/practice/sum-of-multiples/sum_of_multiples_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/sum-of-multiples/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/tournament/.meta/template.j2 b/exercises/practice/tournament/.meta/template.j2 index 30ca2e94cd0..055b3a89d72 100644 --- a/exercises/practice/tournament/.meta/template.j2 +++ b/exercises/practice/tournament/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases %} diff --git a/exercises/practice/tournament/tournament_test.py b/exercises/practice/tournament/tournament_test.py index 45db6055bb5..622983525dd 100644 --- a/exercises/practice/tournament/tournament_test.py +++ b/exercises/practice/tournament/tournament_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/tournament/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/transpose/.meta/template.j2 b/exercises/practice/transpose/.meta/template.j2 index ef724132e8c..e622947b106 100644 --- a/exercises/practice/transpose/.meta/template.j2 +++ b/exercises/practice/transpose/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/transpose/transpose_test.py b/exercises/practice/transpose/transpose_test.py index 4e4bee820d9..d3ab85ff9ff 100644 --- a/exercises/practice/transpose/transpose_test.py +++ b/exercises/practice/transpose/transpose_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/transpose/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/triangle/.meta/template.j2 b/exercises/practice/triangle/.meta/template.j2 index 6d79c8c398c..b196cfc717f 100644 --- a/exercises/practice/triangle/.meta/template.j2 +++ b/exercises/practice/triangle/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(["equilateral", "isosceles", "scalene"]) }} {% for case in cases -%} diff --git a/exercises/practice/triangle/triangle_test.py b/exercises/practice/triangle/triangle_test.py index 5c4263cf1ba..b279c83c325 100644 --- a/exercises/practice/triangle/triangle_test.py +++ b/exercises/practice/triangle/triangle_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/triangle/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/twelve-days/.meta/template.j2 b/exercises/practice/twelve-days/.meta/template.j2 index e90fe713074..2baa27d2c42 100644 --- a/exercises/practice/twelve-days/.meta/template.j2 +++ b/exercises/practice/twelve-days/.meta/template.j2 @@ -1,5 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {{ "# PLEASE TAKE NOTE: Expected result lists for these test cases use **implicit line joining.**" }} {{ "# A new line in a result list below **does not** always equal a new list element." }} {{ "# Check comma placement carefully!" }} diff --git a/exercises/practice/twelve-days/twelve_days_test.py b/exercises/practice/twelve-days/twelve_days_test.py index c48ee421ac2..b18c35e7302 100644 --- a/exercises/practice/twelve-days/twelve_days_test.py +++ b/exercises/practice/twelve-days/twelve_days_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/twelve-days/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/two-bucket/.meta/template.j2 b/exercises/practice/two-bucket/.meta/template.j2 index 02843791272..2cd31976eaa 100644 --- a/exercises/practice/two-bucket/.meta/template.j2 +++ b/exercises/practice/two-bucket/.meta/template.j2 @@ -1,11 +1,14 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {%- macro test_call(case) -%} {{ case["property"] }}({{ case["input"]["bucketOne"] }}, {{ case["input"]["bucketTwo"] }}, {{ case["input"]["goal"] }}, "{{ case["input"]["startBucket"] }}") -{%- endmacro -%} -{{ macros.header() }} +{%- endmacro %} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} @@ -24,4 +27,4 @@ class {{ exercise | camel_case }}Test(unittest.TestCase): {% endfor %} -{{ macros.footer() }} +{{ macros.utility() }} \ No newline at end of file diff --git a/exercises/practice/two-bucket/two_bucket_test.py b/exercises/practice/two-bucket/two_bucket_test.py index 5b5841cec28..b7d1cc01953 100644 --- a/exercises/practice/two-bucket/two_bucket_test.py +++ b/exercises/practice/two-bucket/two_bucket_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/two-bucket/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-21 import unittest @@ -54,7 +54,3 @@ def test_goal_larger_than_both_buckets_is_impossible(self): # Utility functions def assertRaisesWithMessage(self, exception): return self.assertRaisesRegex(exception, r".+") - - -if __name__ == "__main__": - unittest.main() diff --git a/exercises/practice/two-fer/.meta/template.j2 b/exercises/practice/two-fer/.meta/template.j2 index 5db1d53c7e9..794d09ad19c 100644 --- a/exercises/practice/two-fer/.meta/template.j2 +++ b/exercises/practice/two-fer/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/two-fer/two_fer_test.py b/exercises/practice/two-fer/two_fer_test.py index f9e9760b2c9..fa032f08e3f 100644 --- a/exercises/practice/two-fer/two_fer_test.py +++ b/exercises/practice/two-fer/two_fer_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/two-fer/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/variable-length-quantity/.meta/template.j2 b/exercises/practice/variable-length-quantity/.meta/template.j2 index 10b43cbdcc2..c95696ad483 100644 --- a/exercises/practice/variable-length-quantity/.meta/template.j2 +++ b/exercises/practice/variable-length-quantity/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} {%- macro list_int_to_hex(integers) %} [ @@ -6,9 +9,8 @@ {{ "0x{:x}".format(integer) }}{{- "," if not loop.last }} {% endfor %} ] -{% endmacro -%} +{% endmacro %} -{{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py index 032403d34d3..baeb2365430 100644 --- a/exercises/practice/variable-length-quantity/variable_length_quantity_test.py +++ b/exercises/practice/variable-length-quantity/variable_length_quantity_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/variable-length-quantity/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/word-count/.meta/template.j2 b/exercises/practice/word-count/.meta/template.j2 index 7e41be6776a..7f3a6223912 100644 --- a/exercises/practice/word-count/.meta/template.j2 +++ b/exercises/practice/word-count/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} {%- set input = case["input"] -%} def test_{{ case["description"] | to_snake }}(self): @@ -7,7 +11,6 @@ {{ case["expected"] }} ) {%- endmacro %} -{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/word-count/word_count_test.py b/exercises/practice/word-count/word_count_test.py index c6203359216..1bf0bdf6dc7 100644 --- a/exercises/practice/word-count/word_count_test.py +++ b/exercises/practice/word-count/word_count_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/word-count/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/word-search/.meta/template.j2 b/exercises/practice/word-search/.meta/template.j2 index 952da9e9114..14051f12b3b 100644 --- a/exercises/practice/word-search/.meta/template.j2 +++ b/exercises/practice/word-search/.meta/template.j2 @@ -1,4 +1,6 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + {{ macros.header(imports=["WordSearch", "Point"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/word-search/word_search_test.py b/exercises/practice/word-search/word_search_test.py index ba1c7a7761c..d0cbd191d99 100644 --- a/exercises/practice/word-search/word_search_test.py +++ b/exercises/practice/word-search/word_search_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/word-search/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/wordy/.meta/template.j2 b/exercises/practice/wordy/.meta/template.j2 index 00b70a8bb16..74ab335ff92 100644 --- a/exercises/practice/wordy/.meta/template.j2 +++ b/exercises/practice/wordy/.meta/template.j2 @@ -1,4 +1,8 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header()}} + {% macro test_case(case) -%} def test_{{ case["description"] | to_snake }}(self): {%- set question = case["input"]["question"] %} @@ -11,7 +15,6 @@ self.assertEqual({{ case["property"] }}("{{ question }}"), {{ case["expected"] }}) {%- endif %} {%- endmacro %} -{{ macros.header() }} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/wordy/wordy_test.py b/exercises/practice/wordy/wordy_test.py index 7a32eba420b..ffcaf49aed4 100644 --- a/exercises/practice/wordy/wordy_test.py +++ b/exercises/practice/wordy/wordy_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/wordy/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/yacht/.meta/template.j2 b/exercises/practice/yacht/.meta/template.j2 index a9e3ebc4bc3..af604a42f90 100644 --- a/exercises/practice/yacht/.meta/template.j2 +++ b/exercises/practice/yacht/.meta/template.j2 @@ -1,6 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -import unittest +{{ macros.canonical_ref() }} +import unittest import {{ exercise }} class {{ exercise | camel_case }}Test(unittest.TestCase): diff --git a/exercises/practice/yacht/yacht_test.py b/exercises/practice/yacht/yacht_test.py index 58566e06078..fd2f87ad1f1 100644 --- a/exercises/practice/yacht/yacht_test.py +++ b/exercises/practice/yacht/yacht_test.py @@ -1,5 +1,8 @@ -import unittest +# These tests are auto-generated with test data from: +# https://github.com/exercism/problem-specifications/tree/main/exercises/yacht/canonical-data.json +# File last updated on 2023-07-19 +import unittest import yacht diff --git a/exercises/practice/zebra-puzzle/.meta/template.j2 b/exercises/practice/zebra-puzzle/.meta/template.j2 index 134ccdbf485..493b7ba7ee4 100644 --- a/exercises/practice/zebra-puzzle/.meta/template.j2 +++ b/exercises/practice/zebra-puzzle/.meta/template.j2 @@ -1,5 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} -{{ macros.header() }} +{{ macros.canonical_ref() }} + +{{ macros.header()}} class {{ exercise | camel_case }}Test(unittest.TestCase): {% for case in cases -%} diff --git a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py index b64fc9069c6..fd2a331b185 100644 --- a/exercises/practice/zebra-puzzle/zebra_puzzle_test.py +++ b/exercises/practice/zebra-puzzle/zebra_puzzle_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/zebra-puzzle/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest diff --git a/exercises/practice/zipper/.meta/template.j2 b/exercises/practice/zipper/.meta/template.j2 index 4e5de995238..5d291d77f0a 100644 --- a/exercises/practice/zipper/.meta/template.j2 +++ b/exercises/practice/zipper/.meta/template.j2 @@ -1,4 +1,7 @@ {%- import "generator_macros.j2" as macros with context -%} +{{ macros.canonical_ref() }} + +{{ macros.header (imports=["Zipper"]) }} {%- macro test_case(case) %} {%- set input = case["input"] -%} @@ -9,7 +12,7 @@ {%- else %} {{ expected_value(input, expected) }} {%- endif %} -{%- endmacro -%} +{% endmacro %} {%- macro expected_value(input, expected) -%} initial = {{ input["initialTree"] }} @@ -44,9 +47,8 @@ {%- for op in operations -%} .{{ op["operation"] }}({{ op["item"] }}) {%- endfor %} -{%- endmacro -%} +{%- endmacro %} -{{ macros.header (imports=["Zipper"]) }} class {{ exercise | camel_case }}Test(unittest.TestCase): {%- for case in cases %} diff --git a/exercises/practice/zipper/zipper_test.py b/exercises/practice/zipper/zipper_test.py index 10358358356..702f6ccbcf9 100644 --- a/exercises/practice/zipper/zipper_test.py +++ b/exercises/practice/zipper/zipper_test.py @@ -1,6 +1,6 @@ # These tests are auto-generated with test data from: # https://github.com/exercism/problem-specifications/tree/main/exercises/zipper/canonical-data.json -# File last updated on 2023-07-16 +# File last updated on 2023-07-19 import unittest From c56ebb929e94b62814b63f24cba421203bf7f425 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Sun, 23 Jul 2023 08:11:00 -0700 Subject: [PATCH 120/126] Removed Yacht from bools association and pushed it to later in track. (#3471) --- config.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/config.json b/config.json index ec35a0a9c33..7f6c13dc155 100644 --- a/config.json +++ b/config.json @@ -691,14 +691,6 @@ "unpacking-and-multiple-assignment"], "difficulty": 2 }, - { - "slug": "yacht", - "name": "Yacht", - "uuid": "22f937e5-52a7-4956-9dde-61c985251a6b", - "practices": ["bools"], - "prerequisites": ["basics", "bools", "numbers"], - "difficulty": 2 - }, { "slug": "robot-name", "name": "Robot Name", @@ -866,6 +858,14 @@ ], "difficulty": 2 }, + { + "slug": "yacht", + "name": "Yacht", + "uuid": "22f937e5-52a7-4956-9dde-61c985251a6b", + "practices": ["enums"], + "prerequisites": ["basics", "bools", "numbers", "classes"], + "difficulty": 2 + }, { "slug": "sublist", "name": "Sublist", From 4da9d964d2281f7dc4314b6826dc7700fe123ffd Mon Sep 17 00:00:00 2001 From: BethanyG Date: Tue, 25 Jul 2023 10:25:51 -0700 Subject: [PATCH 121/126] Roadmap Updates (#3474) * Updates to tree and concept status. * Adjusted links to exercises and issues. * WIP fixes. * Fix Beta in Locomotive Engineer. * Renamed dataclasses and named tuples. --- .../.meta/config.json | 0 .../about.md | 0 .../introduction.md | 0 .../links.json | 0 config.json | 4 +- reference/track_exercises_overview.md | 519 ++++++++++-------- 6 files changed, 293 insertions(+), 230 deletions(-) rename concepts/{dataclasses-and-namedtuples => dataclasses}/.meta/config.json (100%) rename concepts/{dataclasses-and-namedtuples => dataclasses}/about.md (100%) rename concepts/{dataclasses-and-namedtuples => dataclasses}/introduction.md (100%) rename concepts/{dataclasses-and-namedtuples => dataclasses}/links.json (100%) diff --git a/concepts/dataclasses-and-namedtuples/.meta/config.json b/concepts/dataclasses/.meta/config.json similarity index 100% rename from concepts/dataclasses-and-namedtuples/.meta/config.json rename to concepts/dataclasses/.meta/config.json diff --git a/concepts/dataclasses-and-namedtuples/about.md b/concepts/dataclasses/about.md similarity index 100% rename from concepts/dataclasses-and-namedtuples/about.md rename to concepts/dataclasses/about.md diff --git a/concepts/dataclasses-and-namedtuples/introduction.md b/concepts/dataclasses/introduction.md similarity index 100% rename from concepts/dataclasses-and-namedtuples/introduction.md rename to concepts/dataclasses/introduction.md diff --git a/concepts/dataclasses-and-namedtuples/links.json b/concepts/dataclasses/links.json similarity index 100% rename from concepts/dataclasses-and-namedtuples/links.json rename to concepts/dataclasses/links.json diff --git a/config.json b/config.json index 7f6c13dc155..36f517f9495 100644 --- a/config.json +++ b/config.json @@ -2335,8 +2335,8 @@ }, { "uuid": "ba20a459-99ac-4643-b386-8b90e9c94328", - "slug": "dataclasses-and-namedtuples", - "name": "Dataclasses And Namedtuples" + "slug": "dataclasses", + "name": "Dataclasses" }, { "uuid": "48ef77af-50f5-466e-a537-bcd016550058", diff --git a/reference/track_exercises_overview.md b/reference/track_exercises_overview.md index f7a04168033..761f2c47644 100644 --- a/reference/track_exercises_overview.md +++ b/reference/track_exercises_overview.md @@ -11,126 +11,128 @@ Practice Exercises with Difficulty, Solutions, and Mentor Notes
-| Exercise | Difficulty | Solutions | Prereqs | Practices | Mentor Notes | Jinja?      | Approaches? | -| ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------- | -| [**Hello World**](https://github.com/exercism/python/blob/main/exercises/practice/hello-world/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/hello-world/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/hello-world/solutions?passed_head_tests=true) | NONE | `basics` | | ✅ | ❌ | -| [Acronym](https://github.com/exercism/python/blob/main/exercises/practice/acronym/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/acronym/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/acronym/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L337) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L330) | [acronym](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/acronym/) | ✅ | ❌ | -| [Affine Cipher](https://github.com/exercism/python/blob/main/exercises/practice/affine-cipher/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/affine-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/affine-cipher/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1174) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1173) | | ✅ | ❌ | -| [All Your Base](https://github.com/exercism/python/blob/main/exercises/practice/all-your-base/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/all-your-base/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/all-your-base/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1394) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1393) | | ✅ | ❌ | -| [Allergies](https://github.com/exercism/python/blob/main/exercises/practice/allergies/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/allergies/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/allergies/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L701) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L700) | [allergies](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/allergies/) | ✅ | ❌ | -| [Alphametics](https://github.com/exercism/python/blob/main/exercises/practice/alphametics/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/alphametics/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/alphametics/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1935) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1934) | | ✅ | ❌ | -| [Anagram](https://github.com/exercism/python/blob/main/exercises/practice/anagram/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/anagram/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/anagram/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L577) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L576) | | ✅ | ❌ | -| [Armstrong Numbers](https://github.com/exercism/python/blob/main/exercises/practice/armstrong-numbers/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/armstrong-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/armstrong-numbers/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L512) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L511) | | ✅ | ❌ | -| [Atbash Cipher](https://github.com/exercism/python/blob/main/exercises/practice/atbash-cipher/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/atbash-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/atbash-cipher/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1102) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1101) | | ✅ | ❌ | -| [Bank Account](https://github.com/exercism/python/blob/main/exercises/practice/bank-account/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bank-account/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/bank-account/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2207) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2206) | | ❌ | ❌ | -| [Binary Search Tree](https://github.com/exercism/python/blob/main/exercises/practice/binary-search-tree/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/binary-search-tree/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/binary-search-tree/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1157) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1156) | | ✅ | ❌ | -| [Binary Search](https://github.com/exercism/python/blob/main/exercises/practice/binary-search/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/binary-search/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/binary-search/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1192) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1191) | [binary-search](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/binary-search/) | ✅ | ❌ | -| [Bob](https://github.com/exercism/python/blob/main/exercises/practice/bob/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bob/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/bob/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L715) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L714) | [bob](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/bob/) | ✅ | ✅ | -| [Book Store](https://github.com/exercism/python/blob/main/exercises/practice/book-store/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/book-store/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/book-store/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L445) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L437) | | ✅ | ❌ | -| [Bottle Song](https://github.com/exercism/python/blob/main/exercises/practice/bottle-song/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bottle-song/.meta/example.py)┋[most⭐](https://exercism.org/tracks/python/exercises/bottle-song/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/main/config.json/#LC1012) | [config.json](https://github.com/exercism/python/blob/main/config.json#LC1012) | | ✅ | ❌ | -| [Bowling](https://github.com/exercism/python/blob/main/exercises/practice/bowling/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bowling/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/bowling/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1553) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1552) | | ✅ | ❌ | -| [Change](https://github.com/exercism/python/blob/main/exercises/practice/change/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/change/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/change/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1412) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1411) | | ✅ | ❌ | -| [Circular Buffer](https://github.com/exercism/python/blob/main/exercises/practice/circular-buffer/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/circular-buffer/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/circular-buffer/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1475) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1469) | | ✅ | ❌ | -| [Clock](https://github.com/exercism/python/blob/main/exercises/practice/clock/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/clock/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/clock/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L394) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L389) | [clock](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/clock/) | ✅ | ❌ | -| [Collatz Conjecture](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/collatz-conjecture/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L593) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L592) | | ✅ | ❌ | -| [Complex Numbers](https://github.com/exercism/python/blob/main/exercises/practice/complex-numbers/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/complex-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/complex-numbers/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L799) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L792) | | ✅ | ❌ | -| [Connect](https://github.com/exercism/python/blob/main/exercises/practice/connect/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/connect/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/connect/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L960) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L959) | | ✅ | ❌ | -| [Crypto Square](https://github.com/exercism/python/blob/main/exercises/practice/crypto-square/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/crypto-square/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/crypto-square/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1263) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1262) | | ✅ | ❌ | -| [Darts](https://github.com/exercism/python/blob/main/exercises/practice/darts/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/darts/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/darts/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2199) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2198) | | ✅ | ❌ | -| [Diamond](https://github.com/exercism/python/blob/main/exercises/practice/diamond/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/diamond/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/diamond/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1696) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1695) | | ✅ | ❌ | -| [Difference Of Squares](https://github.com/exercism/python/blob/main/exercises/practice/difference-of-squares/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/difference-of-squares/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/difference-of-squares/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L601) | NONE | | ✅ | ❌ | -| [Diffie Hellman](https://github.com/exercism/python/blob/main/exercises/practice/diffie-hellman/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/diffie-hellman/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/diffie-hellman/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1956) | NONE | | ✅ | ❌ | -| [Dnd Character](https://github.com/exercism/python/blob/main/exercises/practice/dnd-character/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/dnd-character/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/dnd-character/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2078) | NONE | | ✅ | ❌ | -| [Dominoes](https://github.com/exercism/python/blob/main/exercises/practice/dominoes/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/dominoes/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/dominoes/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1767) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1755) | | ✅ | ❌ | -| [Dot Dsl](https://github.com/exercism/python/blob/main/exercises/practice/dot-dsl/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/dot-dsl/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/dot-dsl/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1434) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1427) | | ❌ | ❌ | -| [Etl](https://github.com/exercism/python/blob/main/exercises/practice/etl/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/etl/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/etl/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1118) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1117) | | ✅ | ❌ | -| [Flatten Array](https://github.com/exercism/python/blob/main/exercises/practice/flatten-array/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/flatten-array/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/flatten-array/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1126) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1125) | | ✅ | ❌ | -| [Food Chain](https://github.com/exercism/python/blob/main/exercises/practice/food-chain/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/food-chain/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/food-chain/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1737) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1731) | | ✅ | ❌ | -| [Forth](https://github.com/exercism/python/blob/main/exercises/practice/forth/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/forth/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/forth/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1571) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1570) | | ✅ | ❌ | -| [Gigasecond](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/gigasecond/solutions?passed_head_tests=true) | | NONE | | ✅ | ❌ | -| [Go Counting](https://github.com/exercism/python/blob/main/exercises/practice/go-counting/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/go-counting/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/go-counting/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L868) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L867) | | ✅ | ❌ | -| [Grade School](https://github.com/exercism/python/blob/main/exercises/practice/grade-school/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/grade-school/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/grade-school/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L364) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L363) | [grade-school](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/grade-school/) | ✅ | ❌ | -| [Grains](https://github.com/exercism/python/blob/main/exercises/practice/grains/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/grains/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/grains/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L678) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L677) | | ✅ | ✅ | -| [Grep](https://github.com/exercism/python/blob/main/exercises/practice/grep/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/grep/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/grep/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1536) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1528) | | ✅ | ❌ | -| [Hamming](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/hamming/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L259) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L254) | [hamming](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/hamming/) | ✅ | ❌ | -| [Hangman](https://github.com/exercism/python/blob/main/exercises/practice/hangman/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/hangman/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/hangman/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2221) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2220) | | ❌ | ❌ | -| [High Scores](https://github.com/exercism/python/blob/main/exercises/practice/high-scores/.docs/instructions.md) | 🔹 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/high-scores/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/high-scores/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L226) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L225) | [high-scores](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/high-scores/) | ✅ | ❌ | -| [House](https://github.com/exercism/python/blob/main/exercises/practice/house/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/house/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/house/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1279) | NONE | | ✅ | ❌ | -| [Isbn Verifier](https://github.com/exercism/python/blob/main/exercises/practice/isbn-verifier/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/isbn-verifier/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/isbn-verifier/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L609) | NONE | | ✅ | ❌ | -| [Isogram](https://github.com/exercism/python/blob/main/exercises/practice/isogram/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/isogram/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/isogram/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L273) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L272) | [isogram](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/isogram/) | ✅ | ✅ | -| [Kindergarten Garden](https://github.com/exercism/python/blob/main/exercises/practice/kindergarten-garden/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/kindergarten-garden/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/kindergarten-garden/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L350) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L344) | [kindergarten-garden](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/kindergarten-garden/) | ✅ | ❌ | -| [Knapsack](https://github.com/exercism/python/blob/main/exercises/practice/knapsack/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/knapsack/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/knapsack/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1453) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1452) | | ✅ | ❌ | -| [Largest Series Product](https://github.com/exercism/python/blob/main/exercises/practice/largest-series-product/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/largest-series-product/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/largest-series-product/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L945) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L939) | | ✅ | ❌ | -| [Leap](https://github.com/exercism/python/blob/main/exercises/practice/leap/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/leap/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/leap/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2103) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2102) | [leap](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/leap/) | ✅ | ✅ | -| [Ledger](https://github.com/exercism/python/blob/main/exercises/practice/ledger/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/ledger/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/ledger/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1590) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1589) | | ❌ | ❌ | -| [Linked List](https://github.com/exercism/python/blob/main/exercises/practice/linked-list/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/linked-list/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/linked-list/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1379) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1371) | | ❌ | ❌ | -| [List Ops](https://github.com/exercism/python/blob/main/exercises/practice/list-ops/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/list-ops/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/list-ops/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1294) | NONE | | ✅ | ❌ | -| [Luhn](https://github.com/exercism/python/blob/main/exercises/practice/luhn/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/luhn/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/luhn/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L372) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L371) | [luhn](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/luhn/) | ✅ | ❌ | -| [Markdown](https://github.com/exercism/python/blob/main/exercises/practice/markdown/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/markdown/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/markdown/solutions?passed_head_tests=true) | | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L401) | [markdown](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/markdown/) | ✅ | ❌ | -| [Matching Brackets](https://github.com/exercism/python/blob/main/exercises/practice/matching-brackets/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/matching-brackets/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/matching-brackets/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L728) | NONE | [matching-brackets](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/matching-brackets/) | ✅ | ❌ | -| [Matrix](https://github.com/exercism/python/blob/main/exercises/practice/matrix/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/matrix/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/matrix/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1714) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1713) | [matrix](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/matrix/) | ✅ | ❌ | -| [Meetup](https://github.com/exercism/python/blob/main/exercises/practice/meetup/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/meetup/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/meetup/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L818) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L812) | | ✅ | ❌ | -| [Minesweeper](https://github.com/exercism/python/blob/main/exercises/practice/minesweeper/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/minesweeper/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/minesweeper/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L981) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L980) | | ✅ | ❌ | -| [Nth Prime](https://github.com/exercism/python/blob/main/exercises/practice/nth-prime/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/nth-prime/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/nth-prime/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1814) | NONE | | ✅ | ❌ | -| [Ocr Numbers](https://github.com/exercism/python/blob/main/exercises/practice/ocr-numbers/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/ocr-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/ocr-numbers/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L997) | NONE | | ✅ | ❌ | -| [Paasio](https://github.com/exercism/python/blob/main/exercises/practice/paasio/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/paasio/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/paasio/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1917) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1906) | | ❌ | ❌ | -| [Palindrome Products](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/palindrome-products/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L626) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L625) | | ✅ | ❌ | -| [Pangram](https://github.com/exercism/python/blob/main/exercises/practice/pangram/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pangram/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pangram/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L463) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L462) | | ✅ | ✅ | -| [Perfect Numbers](https://github.com/exercism/python/blob/main/exercises/practice/perfect-numbers/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/perfect-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/perfect-numbers/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L527) | NONE | | ✅ | ❌ | -| [Phone Number](https://github.com/exercism/python/blob/main/exercises/practice/phone-number/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/phone-number/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/phone-number/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L547) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L542) | | ✅ | ❌ | -| [Pig Latin](https://github.com/exercism/python/blob/main/exercises/practice/pig-latin/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pig-latin/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pig-latin/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1832) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1831) | | ✅ | ✅ | -| [Poker](https://github.com/exercism/python/blob/main/exercises/practice/poker/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/poker/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/poker/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1016) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1015) | | ✅ | ❌ | -| [Pov](https://github.com/exercism/python/blob/main/exercises/practice/pov/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pov/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pov/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1677) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1676) | | ✅ | ❌ | -| [Prime Factors](https://github.com/exercism/python/blob/main/exercises/practice/prime-factors/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/prime-factors/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/prime-factors/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L686) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L685) | | ✅ | ❌ | -| [Protein Translation](https://github.com/exercism/python/blob/main/exercises/practice/protein-translation/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/protein-translation/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/protein-translation/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L496) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L495) | | ✅ | ❌ | -| [Proverb](https://github.com/exercism/python/blob/main/exercises/practice/proverb/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/proverb/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/proverb/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/main/config.json#LC661) | [config.json](https://github.com/exercism/python/blob/main/config.json#L661) | | ✅ | ❌ | -| [Pythagorean Triplet](https://github.com/exercism/python/blob/main/exercises/practice/pythagorean-triplet/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pythagorean-triplet/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pythagorean-triplet/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L745) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L744) | | ✅ | ❌ | -| [Queen Attack](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/queen-attack/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1302) | NONE | | ✅ | ❌ | -| [Rail Fence Cipher](https://github.com/exercism/python/blob/main/exercises/practice/rail-fence-cipher/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rail-fence-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rail-fence-cipher/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1849) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1848) | | ✅ | ❌ | -| [Raindrops](https://github.com/exercism/python/blob/main/exercises/practice/raindrops/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/raindrops/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/raindrops/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L210) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L209) | [raindrops](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/raindrops/) | ✅ | ❌ | -| [Rational Numbers](https://github.com/exercism/python/blob/main/exercises/practice/rational-numbers/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rational-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rational-numbers/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2240) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2239) | | ✅ | ❌ | -| [React](https://github.com/exercism/python/blob/main/exercises/practice/react/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/react/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/react/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L890) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L884) | | ❌ | ❌ | -| [Rectangles](https://github.com/exercism/python/blob/main/exercises/practice/rectangles/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rectangles/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rectangles/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1032) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1031) | | ✅ | ❌ | -| [Resistor Color Trio](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-trio/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-trio/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/resistor-color-trio/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/main/config.json#LC631) | [config.json](https://github.com/exercism/python/blob/main/config.json#L631) | | ✅ | ❌ | -| [Resistor Color Duo](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-duo/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-duo/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/resistor-color-duo/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2119) | NONE | | ✅ | ❌ | -| [Resistor Color](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/resistor-color/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2111) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2110) | | ✅ | ❌ | -| [Rest Api](https://github.com/exercism/python/blob/main/exercises/practice/rest-api/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rest-api/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rest-api/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1795) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1787) | | ✅ | ❌ | -| [Reverse String](https://github.com/exercism/python/blob/main/exercises/practice/reverse-string/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/reverse-string/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/reverse-string/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2133) | NONE | [reverse-string](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/reverse-string/) | ✅ | ❌ | -| [Rna Transcription](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rna-transcription/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2149) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2148) | | ✅ | ✅ | -| [Robot Name](https://github.com/exercism/python/blob/main/exercises/practice/robot-name/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/robot-name/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/robot-name/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L479) | NONE | | ❌ | ❌ | -| [Robot Simulator](https://github.com/exercism/python/blob/main/exercises/practice/robot-simulator/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/robot-simulator/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/robot-simulator/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1324) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1315) | | ✅ | ❌ | -| [Roman Numerals](https://github.com/exercism/python/blob/main/exercises/practice/roman-numerals/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/roman-numerals/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/roman-numerals/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1340) | NONE | | ✅ | ❌ | -| [Rotational Cipher](https://github.com/exercism/python/blob/main/exercises/practice/rotational-cipher/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rotational-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rotational-cipher/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1209) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1208) | | ✅ | ❌ | -| [Run Length Encoding](https://github.com/exercism/python/blob/main/exercises/practice/run-length-encoding/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/run-length-encoding/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/run-length-encoding/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1493) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1492) | | ✅ | ❌ | -| [Saddle Points](https://github.com/exercism/python/blob/main/exercises/practice/saddle-points/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/saddle-points/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/saddle-points/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L649) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L643) | | ✅ | ❌ | -| [Satellite](https://github.com/exercism/python/blob/main/exercises/practice/satellite/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/satellite/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/satellite/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1640) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1634) | | ✅ | ❌ | -| [Say](https://github.com/exercism/python/blob/main/exercises/practice/say/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/say/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/say/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1052) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1051) | | ✅ | ❌ | -| [Scale Generator](https://github.com/exercism/python/blob/main/exercises/practice/scale-generator/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/scale-generator/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/scale-generator/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1084) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1083) | | ✅ | ❌ | -| [Scrabble Score](https://github.com/exercism/python/blob/main/exercises/practice/scrabble-score/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/scrabble-score/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/scrabble-score/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L316) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L315) | [scrabble-score](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/scrabble-score/) | ✅ | ❌ | -| [Secret Handshake](https://github.com/exercism/python/blob/main/exercises/practice/secret-handshake/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/secret-handshake/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/secret-handshake/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L924) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L923) | | ✅ | ❌ | -| [Series](https://github.com/exercism/python/blob/main/exercises/practice/series/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/series/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/series/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L562) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L561) | | ✅ | ❌ | -| [Sgf Parsing](https://github.com/exercism/python/blob/main/exercises/practice/sgf-parsing/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sgf-parsing/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sgf-parsing/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2261) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2255) | | ✅ | ❌ | -| [Sieve](https://github.com/exercism/python/blob/main/exercises/practice/sieve/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sieve/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sieve/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L836) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L835) | | ✅ | ❌ | -| [Simple Cipher](https://github.com/exercism/python/blob/main/exercises/practice/simple-cipher/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/simple-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/simple-cipher/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L761) | NONE | | ✅ | ❌ | -| [Simple Linked List](https://github.com/exercism/python/blob/main/exercises/practice/simple-linked-list/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/simple-linked-list/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/simple-linked-list/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1357) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1356) | | ❌ | ❌ | -| [Space Age](https://github.com/exercism/python/blob/main/exercises/practice/space-age/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/space-age/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/space-age/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2164) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2163) | | ✅ | ❌ | -| [Spiral Matrix](https://github.com/exercism/python/blob/main/exercises/practice/spiral-matrix/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/spiral-matrix/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/spiral-matrix/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1714) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1713) | | ✅ | ❌ | -| [Sublist](https://github.com/exercism/python/blob/main/exercises/practice/sublist/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sublist/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sublist/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1141) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1140) | | ✅ | ❌ | -| [Sum Of Multiples](https://github.com/exercism/python/blob/main/exercises/practice/sum-of-multiples/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sum-of-multiples/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sum-of-multiples/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L778) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L777) | [sum-of-multiples](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/sum-of-multiples/) | ✅ | ❌ | -| [Tournament](https://github.com/exercism/python/blob/main/exercises/practice/tournament/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/tournament/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/tournament/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L421) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L409) | | ✅ | ❌ | -| [Transpose](https://github.com/exercism/python/blob/main/exercises/practice/transpose/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/transpose/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/transpose/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1511) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1510) | | ✅ | ❌ | -| [Tree Building](https://github.com/exercism/python/blob/main/exercises/practice/tree-building/.docs/instructions.md) | 🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/tree-building/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/tree-building/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L852) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L851) | | ❌ | ❌ | -| [Triangle](https://github.com/exercism/python/blob/main/exercises/practice/triangle/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/triangle/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/triangle/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L664) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L663) | | ✅ | ❌ | -| [Twelve Days](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/twelve-days/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L281) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L280) | [twelve-days](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/twelve-days/) | ✅ | ❌ | -| [Two Bucket](https://github.com/exercism/python/blob/main/exercises/practice/two-bucket/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/two-bucket/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/two-bucket/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1244) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1243) | | ✅ | ❌ | -| [Two Fer](https://github.com/exercism/python/blob/main/exercises/practice/two-fer/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/two-fer/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/two-fer/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L202) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L201) | [two-fer](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/two-fer/) | ✅ | ❌ | -| [Variable Length Quantity](https://github.com/exercism/python/blob/main/exercises/practice/variable-length-quantity/.docs/instructions.md) | 🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/variable-length-quantity/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/variable-length-quantity/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1226) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1225) | | ✅ | ❌ | -| [Word Count](https://github.com/exercism/python/blob/main/exercises/practice/word-count/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/word-count/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/word-count/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L302) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L296) | [word-count](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/word-count/) | ✅ | ❌ | -| [Word Search](https://github.com/exercism/python/blob/main/exercises/practice/word-search/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/word-search/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/word-search/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1616) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1606) | | ✅ | ❌ | -| [Wordy](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.docs/instructions.md) | 🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/wordy/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1069) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1068) | | ✅ | ✅ | -| [Yacht](https://github.com/exercism/python/blob/main/exercises/practice/yacht/.docs/instructions.md) | 🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/yacht/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/yacht/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2180) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2179) | | ✅ | ❌ | -| [Zebra Puzzle](https://github.com/exercism/python/blob/main/exercises/practice/zebra-puzzle/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/zebra-puzzle/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/zebra-puzzle/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1866) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1865) | | ✅ | ❌ | -| [Zipper](https://github.com/exercism/python/blob/main/exercises/practice/zipper/.docs/instructions.md) | 🔹🔹🔹🔹🔹🔹 | [example](https://github.com/exercism/python/blob/main/exercises/practice/zipper/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/zipper/solutions?passed_head_tests=true) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1659) | [config.json](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1658) | | ✅ | ❌ | +| Exercise | Difficulty | Solutions | Prereqs | Practices | Hints? | Approaches? | Mentor Notes | Appends? | Jinja? | +|-------------------------------------------------------------------------------------------------------------------------------------------- |:----------: |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |---------------------------------------------------------------------------------------------------------- |---------------------------------------------------------------------------------------------------------- |-------------------------------------------------------------------------------------------------------- |------------------------------------------------------------------------------------------------------- |------------------------------------------------------------------------------------------------------ |---------------------------------------------------------------------------------------------------------------------------- |----------------------------------------------------------------------------------------------------------------- | +| [**Hello World**](https://github.com/exercism/python/blob/main/exercises/practice/hello-world/.docs/instructions.md) | 1 | NA | NONE | NONE | NA | NA | NA | NA | NA | +| [Acronym](https://github.com/exercism/python/blob/main/exercises/practice/acronym/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/acronym/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/acronym/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L337) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L330) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/acronym/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/acronym/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/acronym/.meta/template.j2) | +| [Affine Cipher](https://github.com/exercism/python/blob/main/exercises/practice/affine-cipher/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/affine-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/affine-cipher/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1174) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1173) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/affine-cipher/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/affine-cipher/.meta/template.j2) | +| [All Your Base](https://github.com/exercism/python/blob/main/exercises/practice/all-your-base/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/all-your-base/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/all-your-base/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1394) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1393) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/all-your-base/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/all-your-base/.meta/template.j2) | +| [Allergies](https://github.com/exercism/python/blob/main/exercises/practice/allergies/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/allergies/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/allergies/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L701) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L700) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/allergies/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/allergies/.meta/template.j2) | +| [Alphametics](https://github.com/exercism/python/blob/main/exercises/practice/alphametics/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/alphametics/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/alphametics/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1935) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1934) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/alphametics/.meta/template.j2) | +| [Anagram](https://github.com/exercism/python/blob/main/exercises/practice/anagram/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/anagram/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/anagram/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L577) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L576) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/anagram/.meta/template.j2) | +| [Armstrong Numbers](https://github.com/exercism/python/blob/main/exercises/practice/armstrong-numbers/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/armstrong-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/armstrong-numbers/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L512) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L511) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/armstrong-numbers/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/armstrong-numbers/.meta/template.j2) | +| [Atbash Cipher](https://github.com/exercism/python/blob/main/exercises/practice/atbash-cipher/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/atbash-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/atbash-cipher/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1102) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1101) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/atbash-cipher/.meta/template.j2) | +| [Bank Account](https://github.com/exercism/python/blob/main/exercises/practice/bank-account/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bank-account/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/bank-account/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2207) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2206) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bank-account/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bank-account/.meta/template.j2) | +| [Binary Search Tree](https://github.com/exercism/python/blob/main/exercises/practice/binary-search-tree/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/binary-search-tree/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/binary-search-tree/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1157) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1156) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/binary-search-tree/.meta/template.j2) | +| [Binary Search](https://github.com/exercism/python/blob/main/exercises/practice/binary-search/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/binary-search/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/binary-search/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1192) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1191) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/binary-search/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/binary-search/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/binary-search/.meta/template.j2) | +| [Bob](https://github.com/exercism/python/blob/main/exercises/practice/bob/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bob/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/bob/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L715) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L714) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bob/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/bob/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bob/.meta/template.j2) | +| [Book Store](https://github.com/exercism/python/blob/main/exercises/practice/book-store/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/book-store/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/book-store/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L445) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L437) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/book-store/.meta/template.j2) | +| [Bottle Song](https://github.com/exercism/python/blob/main/exercises/practice/bottle-song/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bottle-song/.meta/example.py)┋[most⭐](https://exercism.org/tracks/python/exercises/bottle-song/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json/#LC1012) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#LC1012) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bottle-song/.meta/template.j2) | +| [Bowling](https://github.com/exercism/python/blob/main/exercises/practice/bowling/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/bowling/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/bowling/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1553) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1552) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bowling/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/bowling/.meta/template.j2) | +| [Change](https://github.com/exercism/python/blob/main/exercises/practice/change/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/change/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/change/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1412) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1411) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/change/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/change/.meta/template.j2) | +| [Circular Buffer](https://github.com/exercism/python/blob/main/exercises/practice/circular-buffer/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/circular-buffer/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/circular-buffer/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1475) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1469) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/circular-buffer/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/circular-buffer/.meta/template.j2) | +| [Clock](https://github.com/exercism/python/blob/main/exercises/practice/clock/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/clock/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/clock/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L394) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L389) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/clock/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/clock/.meta/template.j2) | +| [Collatz Conjecture](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/collatz-conjecture/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L593) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L592) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.approaches/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/collatz-conjecture/.meta/template.j2) | +| [Complex Numbers](https://github.com/exercism/python/blob/main/exercises/practice/complex-numbers/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/complex-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/complex-numbers/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L799) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L792) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/complex-numbers/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/complex-numbers/.meta/template.j2) | +| [Connect](https://github.com/exercism/python/blob/main/exercises/practice/connect/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/connect/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/connect/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L960) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L959) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/connect/.meta/template.j2) | +| [Crypto Square](https://github.com/exercism/python/blob/main/exercises/practice/crypto-square/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/crypto-square/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/crypto-square/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1263) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1262) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/crypto-square/.meta/template.j2) | +| [Darts](https://github.com/exercism/python/blob/main/exercises/practice/darts/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/darts/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/darts/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2199) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2198) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/darts/.docs/hints.md) | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/darts/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/darts/.meta/template.j2) | +| [Diamond](https://github.com/exercism/python/blob/main/exercises/practice/diamond/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/diamond/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/diamond/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1696) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1695) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/diamond/.meta/template.j2) | +| [Difference Of Squares](https://github.com/exercism/python/blob/main/exercises/practice/difference-of-squares/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/difference-of-squares/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/difference-of-squares/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L601) | NONE | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/difference-of-squares/.meta/template.j2) | +| [Dnd Character](https://github.com/exercism/python/blob/main/exercises/practice/dnd-character/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/dnd-character/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/dnd-character/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2078) | NONE | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/dnd-character/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/dnd-character/.meta/template.j2) | +| [Dominoes](https://github.com/exercism/python/blob/main/exercises/practice/dominoes/.docs/instructions.md) | 7 | [example](https://github.com/exercism/python/blob/main/exercises/practice/dominoes/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/dominoes/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1767) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1755) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/dominoes/.meta/template.j2) | +| [Dot Dsl](https://github.com/exercism/python/blob/main/exercises/practice/dot-dsl/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/dot-dsl/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/dot-dsl/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1434) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1427) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/dot-dsl/.docs/instructions.append.md) | | +| [Etl](https://github.com/exercism/python/blob/main/exercises/practice/etl/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/etl/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/etl/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1118) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1117) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/etl/.meta/template.j2) | +| [Flatten Array](https://github.com/exercism/python/blob/main/exercises/practice/flatten-array/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/flatten-array/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/flatten-array/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1126) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1125) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/flatten-array/.meta/template.j2) | +| [Food Chain](https://github.com/exercism/python/blob/main/exercises/practice/food-chain/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/food-chain/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/food-chain/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1737) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1731) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/food-chain/.meta/template.j2) | +| [Forth](https://github.com/exercism/python/blob/main/exercises/practice/forth/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/forth/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/forth/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1571) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1570) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/forth/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/forth/.meta/template.j2) | +| [Gigasecond](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/gigasecond/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L450) | NONE | [✔](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.docs/hints.md) | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/gigasecond/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/gigasecond/.meta/template.j2) | +| [Go Counting](https://github.com/exercism/python/blob/main/exercises/practice/go-counting/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/go-counting/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/go-counting/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L868) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L867) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/go-counting/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/go-counting/.meta/template.j2) | +| [Grade School](https://github.com/exercism/python/blob/main/exercises/practice/grade-school/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/grade-school/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/grade-school/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L364) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L363) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/grade-school/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/grade-school/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/grade-school/.meta/template.j2) | +| [Grains](https://github.com/exercism/python/blob/main/exercises/practice/grains/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/grains/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/grains/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L678) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L677) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/grains/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/grains/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/grains/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/grains/.meta/template.j2) | +| [Grep](https://github.com/exercism/python/blob/main/exercises/practice/grep/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/grep/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/grep/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1536) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1528) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/grep/.meta/template.j2) | +| [Hamming](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/hamming/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L259) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L254) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/hamming/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/hamming/.meta/template.j2) | +| [Hangman](https://github.com/exercism/python/blob/main/exercises/practice/hangman/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/hangman/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/hangman/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2221) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2220) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/hangman/.docs/instructions.append.md) | | +| [High Scores](https://github.com/exercism/python/blob/main/exercises/practice/high-scores/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/high-scores/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/high-scores/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L226) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L225) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/high-scores/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/high-scores/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/high-scores/.meta/template.j2) | +| [House](https://github.com/exercism/python/blob/main/exercises/practice/house/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/house/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/house/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1279) | NONE | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/house/.meta/template.j2) | +| [Isbn Verifier](https://github.com/exercism/python/blob/main/exercises/practice/isbn-verifier/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/isbn-verifier/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/isbn-verifier/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L609) | NONE | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/isbn-verifier/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/isbn-verifier/.meta/template.j2) | +| [Isogram](https://github.com/exercism/python/blob/main/exercises/practice/isogram/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/isogram/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/isogram/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L273) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L272) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/isogram/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/isogram/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/isogram/.meta/template.j2) | +| [Isogram](https://github.com/exercism/python/blob/main/exercises/practice/killer-sudoku-helper/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/killer-sudoku-helper/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/killer-sudodu-helper/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L1385) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L1384) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/killer-sudoku-helper/.meta/template.j2) | +| [Kindergarten Garden](https://github.com/exercism/python/blob/main/exercises/practice/kindergarten-garden/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/kindergarten-garden/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/kindergarten-garden/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L350) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L344) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/kindergarten-garden/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/kindergarten-garden/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/kindergarten-garden/.meta/template.j2) | +| [Knapsack](https://github.com/exercism/python/blob/main/exercises/practice/knapsack/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/knapsack/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/knapsack/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1453) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1452) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/knapsack/.meta/template.j2) | +| [Largest Series Product](https://github.com/exercism/python/blob/main/exercises/practice/largest-series-product/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/largest-series-product/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/largest-series-product/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L945) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L939) | | ✔ | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/largest-series-product/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/largest-series-product/.meta/template.j2) | +| [Leap](https://github.com/exercism/python/blob/main/exercises/practice/leap/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/leap/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/leap/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2103) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2102) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/leap/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/leap/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/leap/.meta/template.j2) | +| [Ledger](https://github.com/exercism/python/blob/main/exercises/practice/ledger/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/ledger/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/ledger/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1590) | | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/ledger/.meta/template.j2) | +| [Linked List](https://github.com/exercism/python/blob/main/exercises/practice/linked-list/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/linked-list/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/linked-list/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1379) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1371) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/linked-list/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/linked-list/.meta/template.j2) | +| [List Ops](https://github.com/exercism/python/blob/main/exercises/practice/list-ops/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/list-ops/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/list-ops/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1294) | NONE | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/list-ops/.meta/template.j2) | +| [Luhn](https://github.com/exercism/python/blob/main/exercises/practice/luhn/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/luhn/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/luhn/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L372) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L371) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/luhn/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/luhn/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/luhn/.meta/template.j2) | +| [Markdown](https://github.com/exercism/python/blob/main/exercises/practice/markdown/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/markdown/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/markdown/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L1418) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L1417) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/markdown/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/markdown/.meta/template.j2) | +| [Matching Brackets](https://github.com/exercism/python/blob/main/exercises/practice/matching-brackets/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/matching-brackets/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/matching-brackets/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L728) | NONE | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/matching-brackets/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/matching-brackets/.meta/template.j2) | +| [Matrix](https://github.com/exercism/python/blob/main/exercises/practice/matrix/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/matrix/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/matrix/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1714) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1713) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/matrix/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/matrix/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/matrix/.meta/template.j2) | +| [Meetup](https://github.com/exercism/python/blob/main/exercises/practice/meetup/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/meetup/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/meetup/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L818) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L812) | | ✔ | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/meetup/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/meetup/.meta/template.j2) | +| [Minesweeper](https://github.com/exercism/python/blob/main/exercises/practice/minesweeper/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/minesweeper/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/minesweeper/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L981) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L980) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/minesweeper/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/minesweeper/.meta/template.j2) | +| [Nth Prime](https://github.com/exercism/python/blob/main/exercises/practice/nth-prime/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/nth-prime/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/nth-prime/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1814) | NONE | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/nth-prime/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/nth-prime/.meta/template.j2) | +| [Ocr Numbers](https://github.com/exercism/python/blob/main/exercises/practice/ocr-numbers/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/ocr-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/ocr-numbers/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L997) | NONE | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/ocr-numbers/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/ocr-numbers/.meta/template.j2) | +| [Paasio](https://github.com/exercism/python/blob/main/exercises/practice/paasio/.docs/instructions.md) | 7 | [example](https://github.com/exercism/python/blob/main/exercises/practice/paasio/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/paasio/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1917) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1906) | | | | | | +| [Palindrome Products](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/palindrome-products/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L626) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L625) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/palindrome-products/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/palindrome-products/.meta/template.j2) | +| [Pangram](https://github.com/exercism/python/blob/main/exercises/practice/pangram/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pangram/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pangram/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L463) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L462) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pangram/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/pangram/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pangram/.meta/template.j2) | +| [Pascals Triangle](https://github.com/exercism/python/blob/main/exercises/practice/pascals-triangle/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pascals-triangle/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pascals-triangle/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L1300) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L1299) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pascals-triangle/.docs/hints.md) | ✔ | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pascals-triangle/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pascals-triangle/.meta/template.j2) | +| [Perfect Numbers](https://github.com/exercism/python/blob/main/exercises/practice/perfect-numbers/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/perfect-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/perfect-numbers/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L527) | NONE | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/perfect-numbers/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/perfect-numbers/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/perfect-numbers/.meta/template.j2) | +| [Phone Number](https://github.com/exercism/python/blob/main/exercises/practice/phone-number/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/phone-number/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/phone-number/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L547) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L542) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/phone-numbers/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/phone-number/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/phone-number/.meta/template.j2) | +| [Pig Latin](https://github.com/exercism/python/blob/main/exercises/practice/pig-latin/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pig-latin/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pig-latin/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1832) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1831) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pig-latin/.approaches/) | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pig-latin/.meta/template.j2) | +| [Poker](https://github.com/exercism/python/blob/main/exercises/practice/poker/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/poker/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/poker/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1016) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1015) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/poker/.meta/template.j2) | +| [Pov](https://github.com/exercism/python/blob/main/exercises/practice/pov/.docs/instructions.md) | 9 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pov/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pov/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1677) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1676) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pov/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pov/.meta/template.j2) | +| [Prime Factors](https://github.com/exercism/python/blob/main/exercises/practice/prime-factors/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/prime-factors/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/prime-factors/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L686) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L685) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/prime-factors/.meta/template.j2) | +| [Protein Translation](https://github.com/exercism/python/blob/main/exercises/practice/protein-translation/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/protein-translation/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/protein-translation/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L496) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L495) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/protein-translation/.meta/template.j2) | +| [Proverb](https://github.com/exercism/python/blob/main/exercises/practice/proverb/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/proverb/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/proverb/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#LC661) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L661) | | ✔ | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/proverb/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/proverb/.meta/template.j2) | +| [Pythagorean Triplet](https://github.com/exercism/python/blob/main/exercises/practice/pythagorean-triplet/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/pythagorean-triplet/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/pythagorean-triplet/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L745) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L744) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pythagorean-triplet/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/pythagorean-triplet/.meta/template.j2) | +| [Queen Attack](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/queen-attack/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1302) | NONE | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/queen-attack/.meta/template.j2) | +| [Rail Fence Cipher](https://github.com/exercism/python/blob/main/exercises/practice/rail-fence-cipher/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rail-fence-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rail-fence-cipher/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1849) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1848) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rail-fence-cipher/.meta/template.j2) | +| [Raindrops](https://github.com/exercism/python/blob/main/exercises/practice/raindrops/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/raindrops/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/raindrops/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L210) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L209) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/raindrops/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/raindrops/.meta/template.j2) | +| [Rational Numbers](https://github.com/exercism/python/blob/main/exercises/practice/rational-numbers/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rational-numbers/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rational-numbers/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2240) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2239) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rational-numbers/.meta/template.j2) | +| [React](https://github.com/exercism/python/blob/main/exercises/practice/react/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/react/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/react/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L890) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L884) | | | | | | +| [Rectangles](https://github.com/exercism/python/blob/main/exercises/practice/rectangles/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rectangles/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rectangles/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1032) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1031) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rectangles/.meta/template.j2) | +| [Resistor Color Trio](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-trio/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-trio/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/resistor-color-trio/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#LC631) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L631) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-trio/.meta/template.j2) | +| [Resistor Color Duo](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-duo/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-duo/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/resistor-color-duo/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2119) | NONE | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color-duo/.meta/template.j2) | +| [Resistor Color](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/resistor-color/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2111) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2110) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/resistor-color/.meta/template.j2) | +| [Rest Api](https://github.com/exercism/python/blob/main/exercises/practice/rest-api/.docs/instructions.md) | 8 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rest-api/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rest-api/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1795) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1787) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rest-api/.meta/template.j2) | +| [Reverse String](https://github.com/exercism/python/blob/main/exercises/practice/reverse-string/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/reverse-string/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/reverse-string/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2133) | NONE | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/reverse-string/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/reverse-string/.meta/template.j2) | +| [Rna Transcription](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rna-transcription/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2149) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2148) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/rna-transcription/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rna-transcription/.meta/template.j2) | +| [Robot Name](https://github.com/exercism/python/blob/main/exercises/practice/robot-name/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/robot-name/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/robot-name/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L479) | NONE | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/robot-name/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/robot-name/) | | | +| [Robot Simulator](https://github.com/exercism/python/blob/main/exercises/practice/robot-simulator/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/robot-simulator/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/robot-simulator/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1324) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1315) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/robot-simulator/.meta/template.j2) | +| [Roman Numerals](https://github.com/exercism/python/blob/main/exercises/practice/roman-numerals/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/roman-numerals/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/roman-numerals/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1340) | NONE | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/roman-numerals/.meta/template.j2) | +| [Rotational Cipher](https://github.com/exercism/python/blob/main/exercises/practice/rotational-cipher/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/rotational-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/rotational-cipher/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1209) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1208) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rotational-cipher/.approaches/) | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/rotational-cipher/.meta/template.j2) | +| [Run Length Encoding](https://github.com/exercism/python/blob/main/exercises/practice/run-length-encoding/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/run-length-encoding/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/run-length-encoding/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1493) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1492) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/run-length-encoding/.meta/template.j2) | +| [Saddle Points](https://github.com/exercism/python/blob/main/exercises/practice/saddle-points/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/saddle-points/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/saddle-points/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L649) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L643) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/saddle-points/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/saddle-points/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/saddle-points/.meta/template.j2) | +| [Satellite](https://github.com/exercism/python/blob/main/exercises/practice/satellite/.docs/instructions.md) | 7 | [example](https://github.com/exercism/python/blob/main/exercises/practice/satellite/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/satellite/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1640) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1634) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/satellite/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/satellite/.meta/template.j2) | +| [Say](https://github.com/exercism/python/blob/main/exercises/practice/say/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/say/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/say/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1052) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1051) | | ✔ | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/say/.meta/template.j2) | +| [Scale Generator](https://github.com/exercism/python/blob/main/exercises/practice/scale-generator/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/scale-generator/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/scale-generator/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1084) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1083) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/scale-generator/.meta/template.j2) | +| [Scrabble Score](https://github.com/exercism/python/blob/main/exercises/practice/scrabble-score/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/scrabble-score/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/scrabble-score/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L316) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L315) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/scrabble-score/.approaches/) | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/scrabble-score/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/scrabble-score/.meta/template.j2) | +| [Secret Handshake](https://github.com/exercism/python/blob/main/exercises/practice/secret-handshake/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/secret-handshake/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/secret-handshake/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L924) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L923) | | ✔ | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/secret-handshake/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/secret-handshake/.meta/template.j2) | +| [Series](https://github.com/exercism/python/blob/main/exercises/practice/series/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/series/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/series/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L562) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L561) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/series/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/series/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/series/.meta/template.j2) | +| [Sgf Parsing](https://github.com/exercism/python/blob/main/exercises/practice/sgf-parsing/.docs/instructions.md) | 7 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sgf-parsing/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sgf-parsing/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2261) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2255) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sgf-parsing/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sgf-parsing/.meta/template.j2) | +| [Sieve](https://github.com/exercism/python/blob/main/exercises/practice/sieve/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sieve/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sieve/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L836) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L835) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sieve/.meta/template.j2) | +| [Simple Cipher](https://github.com/exercism/python/blob/main/exercises/practice/simple-cipher/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/simple-cipher/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/simple-cipher/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L761) | NONE | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/simple-cipher/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/simple-cipher/.meta/template.j2) | +| [Simple Linked List](https://github.com/exercism/python/blob/main/exercises/practice/simple-linked-list/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/simple-linked-list/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/simple-linked-list/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1357) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1356) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/simple-linked-list/.docs/hints.md) | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/simple-linked-list/.docs/instructions.append.md) | | +| [Space Age](https://github.com/exercism/python/blob/main/exercises/practice/space-age/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/space-age/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/space-age/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2164) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2163) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/space-age/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/space-age/.meta/template.j2) | +| [Spiral Matrix](https://github.com/exercism/python/blob/main/exercises/practice/spiral-matrix/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/spiral-matrix/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/spiral-matrix/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1714) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1713) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/spiral-matrix/.meta/template.j2) | +| [Spiral Matrix](https://github.com/exercism/python/blob/main/exercises/practice/square-root/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/square-root/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/square-root/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L609) | [⚙⚙](https://github.com/exercism/python/blob/main/config.json#L608) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/square-root/.meta/template.j2) | +| [Sublist](https://github.com/exercism/python/blob/main/exercises/practice/sublist/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sublist/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sublist/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1141) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1140) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sublist/.approaches/) | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sublist/.meta/template.j2) | +| [Sum Of Multiples](https://github.com/exercism/python/blob/main/exercises/practice/sum-of-multiples/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/sum-of-multiples/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/sum-of-multiples/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L778) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L777) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/sum-of-multiples/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sum-of-multiples/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/sum-of-multiples/.meta/template.j2) | +| [Tournament](https://github.com/exercism/python/blob/main/exercises/practice/tournament/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/tournament/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/tournament/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L421) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L409) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/tournament/.meta/template.j2) | +| [Transpose](https://github.com/exercism/python/blob/main/exercises/practice/transpose/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/transpose/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/transpose/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1511) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1510) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/transpose/.meta/template.j2) | +| [Tree Building](https://github.com/exercism/python/blob/main/exercises/practice/tree-building/.docs/instructions.md) | 3 | [example](https://github.com/exercism/python/blob/main/exercises/practice/tree-building/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/tree-building/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L852) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L851) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/tree-building/.docs/instructions.append.md) | | +| [Triangle](https://github.com/exercism/python/blob/main/exercises/practice/triangle/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/triangle/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/triangle/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L664) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L663) | | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/triangle/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/triangle/.meta/template.j2) | +| [Twelve Days](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/twelve-days/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L281) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L280) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.docs/hints.md) | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/twelve-days/) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/twelve-days/.meta/template.j2) | +| [Two Bucket](https://github.com/exercism/python/blob/main/exercises/practice/two-bucket/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/two-bucket/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/two-bucket/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1244) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1243) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/two-bucket/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/two-bucket/.meta/template.j2) | +| [Two Fer](https://github.com/exercism/python/blob/main/exercises/practice/two-fer/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/two-fer/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/two-fer/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L202) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L201) | | | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/two-fer/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/two-fer/.meta/template.j2) | +| [Variable Length Quantity](https://github.com/exercism/python/blob/main/exercises/practice/variable-length-quantity/.docs/instructions.md) | 4 | [example](https://github.com/exercism/python/blob/main/exercises/practice/variable-length-quantity/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/variable-length-quantity/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1226) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1225) | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/variable-length-quantity/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/variable-length-quantity/.meta/template.j2) | +| [Word Count](https://github.com/exercism/python/blob/main/exercises/practice/word-count/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/word-count/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/word-count/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L302) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L296) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/word-count/.docs/hints.md) | ✔ | [✔](https://github.com/exercism/website-copy/tree/main/tracks/python/exercises/word-count/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/word-count/.meta/template.j2) | +| [Word Search](https://github.com/exercism/python/blob/main/exercises/practice/word-search/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/word-search/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/word-search/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1616) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1606) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/word-search/.meta/template.j2) | +| [Wordy](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.docs/instructions.md) | 1 | [example](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/wordy/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1069) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1068) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.approaches/) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.docs/instructions.append.md) | [✔](https://github.com/exercism/python/blob/main/exercises/practice/wordy/.meta/template.j2) | +| [Yacht](https://github.com/exercism/python/blob/main/exercises/practice/yacht/.docs/instructions.md) | 2 | [example](https://github.com/exercism/python/blob/main/exercises/practice/yacht/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/yacht/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2180) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L2179) | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/yacht/.approaches/) | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/yacht/.meta/template.j2) | +| [Zebra Puzzle](https://github.com/exercism/python/blob/main/exercises/practice/zebra-puzzle/.docs/instructions.md) | 5 | [example](https://github.com/exercism/python/blob/main/exercises/practice/zebra-puzzle/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/zebra-puzzle/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1866) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1865) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/zebra-puzzle/.meta/template.j2) | +| [Zipper](https://github.com/exercism/python/blob/main/exercises/practice/zipper/.docs/instructions.md) | 6 | [example](https://github.com/exercism/python/blob/main/exercises/practice/zipper/.meta/example.py)┋[most⭐](https://exercism.io/tracks/python/exercises/zipper/solutions?passed_head_tests=true) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1659) | [⚙⚙](https://github.com/exercism/python/blob/64396fd483c6c6770c1313b71cb4d972e5ab9819/config.json#L1658) | | | | | [✔](https://github.com/exercism/python/blob/main/exercises/practice/zipper/.meta/template.j2) |
@@ -138,17 +140,17 @@ | Exercise | Difficulty | | -------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | -| [Accumulate](https://github.com/exercism/python/blob/main/exercises/practice/accumulate/.docs/instructions.md) | 🔹🔹 | -| [Beer Song](https://github.com/exercism/python/blob/main/exercises/practice/beer-song/.docs/instructions.md) | 🔹🔹🔹 | -| [Binary](https://github.com/exercism/python/blob/main/exercises/practice/binary/.docs/instructions.md) | 🔹🔹🔹 | -| [Error Handling](https://github.com/exercism/python/blob/main/exercises/practice/error-handling/.docs/instructions.md) | 🔹🔹🔹 | -| [Hexadecimal](https://github.com/exercism/python/blob/main/exercises/practice/hexadecimal/.docs/instructions.md) | 🔹🔹🔹 | -| [Nucleotide Count](https://github.com/exercism/python/blob/main/exercises/practice/nucleotide-count/.docs/instructions.md) | 🔹🔹 | -| [Parallel Letter Frequency](https://github.com/exercism/python/blob/main/exercises/practice/parallel-letter-frequency/.docs/instructions.md) | 🔹🔹🔹 | -| [Pascal's Triangle](https://github.com/exercism/python/blob/main/exercises/practice/pascals-triangle/.docs/instructions.md) | 🔹🔹🔹 | -| [Point Mutations](https://github.com/exercism/python/blob/main/exercises/practice/point-mutations/.docs/instructions.md) | 🔹🔹🔹 | -| [Trinary](https://github.com/exercism/python/blob/main/exercises/practice/trinary/.docs/instructions.md) | 🔹🔹🔹🔹 | -| [Custom Set](https://github.com/exercism/python/blob/main/exercises/practice/custom-set/.docs/instructions.md) | 🔹🔹🔹🔹🔹 | +| [Accumulate](https://github.com/exercism/python/blob/main/exercises/practice/accumulate/.docs/instructions.md) | 2 | +| [Beer Song](https://github.com/exercism/python/blob/main/exercises/practice/beer-song/.docs/instructions.md) | 3 | +| [Binary](https://github.com/exercism/python/blob/main/exercises/practice/binary/.docs/instructions.md) |3 | +| [Diffie-Hellman](https://github.com/exercism/python/blob/main/exercises/practice/diffie-hellman/.docs/instructions.md) |3 | +| [Error Handling](https://github.com/exercism/python/blob/main/exercises/practice/error-handling/.docs/instructions.md) | 3 | +| [Hexadecimal](https://github.com/exercism/python/blob/main/exercises/practice/hexadecimal/.docs/instructions.md) | 3 | +| [Nucleotide Count](https://github.com/exercism/python/blob/main/exercises/practice/nucleotide-count/.docs/instructions.md) | 2 | +| [Parallel Letter Frequency](https://github.com/exercism/python/blob/main/exercises/practice/parallel-letter-frequency/.docs/instructions.md) | 3 | +| [Point Mutations](https://github.com/exercism/python/blob/main/exercises/practice/point-mutations/.docs/instructions.md) |3 | +| [Trinary](https://github.com/exercism/python/blob/main/exercises/practice/trinary/.docs/instructions.md) | 4 | +| [Custom Set](https://github.com/exercism/python/blob/main/exercises/practice/custom-set/.docs/instructions.md) | 5 |
@@ -198,99 +200,125 @@
-| Status | Concept | About&Intro | Exercise | Design Doc or Issue | Stub
Docstring Level | -| :--------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------: | :---------------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------- | :---------------------- | -| | [basics](https://github.com/exercism/python/blob/main/concepts/basics) | | [Guidos Gorgeous Lasagna](https://github.com/exercism/python/tree/main/tree/main/exercises/concept/guidos-gorgeous-lasagna) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/guidos-gorgeous-lasagna/.meta) | Full | -| | [bools](https://github.com/exercism/python/blob/main/concepts/bools) | | [Ghost Gobble Arcade Game](https://github.com/exercism/python/tree/main/tree/main/exercises/concept/ghost-gobble-arcade-game) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/ghost-gobble-arcade-game/.meta) | Full | -| | [numbers](https://github.com/exercism/python/blob/main/concepts/numbers) | | [Currency Exchange](https://github.com/exercism/python/tree/main/exercises/concept/currency-exchange) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/currency-exchange/.meta) | Full | -| | [complex-numbers](https://github.com/exercism/python/blob/main/concepts/complex-numbers) | | ~ | [#2208](https://github.com/exercism/v3/issues/2208) | TBD | -| | [conditionals](https://github.com/exercism/python/blob/main/concepts/conditionals) | | [Meltdown Mitigation ](https://github.com/exercism/python/tree/main/exercises/concept/meltdown-mitigation) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/meltdown-mitigation/.meta) | Full | -| | [comparisons](https://github.com/exercism/python/blob/main/concepts/comparisons) | | [Black Jack](https://github.com/exercism/python/tree/main/exercises/concept/black-jack) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/black-jack/.meta) | Full | -| | [strings](https://github.com/exercism/python/blob/main/concepts/strings) | | [Litte Sister's Vocab](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-vocab) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-vocab/.meta) | Full | -| | [string-methods](https://github.com/exercism/python/blob/main/concepts/string-methods) | | [Litte Sister's Essay](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-essay) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-essay/.meta) | Full | -| | [string-formatting](https://github.com/exercism/python/blob/main/concepts/string-formatting) | | [Pretty Leaflet ](https://github.com/exercism/python/tree/main/exercises/concept/pretty-leaflet) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/pretty-leaflet/.meta) | Full | -| | [lists](https://github.com/exercism/python/blob/main/concepts/lists) | | [Card Games](https://github.com/exercism/python/tree/main/exercises/concept/card-games) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/card-games/.meta) | Full | -| | [list-methods](https://github.com/exercism/python/blob/main/concepts/list-methods) | | [Chaitanas Colossal Coaster](https://github.com/exercism/python/tree/main/exercises/concept/chaitanas-colossal-coaster) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/chaitanas-colossal-coaster/.meta) | Full | -| | [loops](https://github.com/exercism/python/blob/main/concepts/loops) | | [Making the Grade](https://github.com/exercism/python/tree/main/exercises/concept/making-the-grade) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/making-the-grade/.meta) | Full | -| | [tuples](https://github.com/exercism/python/blob/main/concepts/tuples) | | [Tisbury Treasure Hunt](https://github.com/exercism/python/tree/main/exercises/concept/tisbury-treasure-hunt) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/tisbury-treasure-hunt/.meta) | Full | -| | [sequences](https://github.com/exercism/python/blob/main/concepts/sequences) | | ~ | [#2290](https://github.com/exercism/python/issues/2290) | TBD | -| | [dicts](https://github.com/exercism/python/blob/main/concepts/dicts) | | [Inventory Management](https://github.com/exercism/python/tree/main/exercises/concept/inventory-management) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/inventory-management) | Full | -| | [dict-methods](https://github.com/exercism/python/blob/main/concepts/dict-methods) | | ~ | [#2348](https://github.com/exercism/python/issues/2348) | | -| | [sets](https://github.com/exercism/python/blob/main/concepts/sets) | | [Cater Waiter ](https://github.com/exercism/python/tree/main/exercises/concept/cater-waiter) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/cater-waiter/.meta) | Full | -| | [list-comprehensions](https://github.com/exercism/python/blob/main/concepts/list-comprehensions) | | ~ | [#2295](https://github.com/exercism/python/issues/2295) | | -| | [other-comprehensions](https://github.com/exercism/python/blob/main/concepts/other-comprehensions) | | ~ | [#2294](https://github.com/exercism/python/issues/2294) | | -| | [classes](https://github.com/exercism/python/blob/main/concepts/classes) | | [Ellen's Alien Game](https://github.com/exercism/python/tree/main/exercises/concept/ellens-alien-game) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/ellens-alien-game/.meta) | Minimal | -| | [generators](https://github.com/exercism/python/blob/main/concepts/generators) | | Plane Tickets | [PR#2729](https://github.com/exercism/python/pull/2729)/[#2293](https://github.com/exercism/python/issues/2293) | Minimal | -| | [generator-expressions](https://github.com/exercism/python/blob/main/concepts/generator-expressions) | | ~ | [#2292](https://github.com/exercism/python/issues/2292) | | -| | [iterators](https://github.com/exercism/python/blob/main/concepts/iterators) | | ~ | [#2367](https://github.com/exercism/python/issues/2367) | TBD | -| | [functions](https://github.com/exercism/python/blob/main/concepts/functions) | | ~ | [#2353](https://github.com/exercism/python/issues/2353) | | -| | [unpacking-and-multiple-assignment](https://github.com/exercism/python/blob/main/concepts/unpacking-and-multiple-assignment) | | ~ | [#2360](https://github.com/exercism/python/issues/2360) | | -| | [raising-and-handling-errors](https://github.com/exercism/python/blob/main/concepts/raising-and-handling-errors) | | ~ | TBD | | -| | [itertools](https://github.com/exercism/python/blob/main/concepts/itertools) | | ~ | [#2368](https://github.com/exercism/python/issues/2368) | | -| | [with-statement](https://github.com/exercism/python/blob/main/concepts/with-statement) | | ~ | [#2369](https://github.com/exercism/python/issues/2369) | | -| | [enums](https://github.com/exercism/python/blob/main/concepts/enums) | | [Log Levels](https://github.com/exercism/python/tree/main/exercises/concept/log-levels) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/log-levels) | Minimal | -| | [none](https://github.com/exercism/python/blob/main/concepts/none) | | [Restaurant Rozalynn](https://github.com/exercism/python/tree/main/exercises/concept/restaurant-rozalynn) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/restaurant-rozalynn/.meta) | Minimal | -| | [decorators](https://github.com/exercism/python/blob/main/concepts/decorators) | | ~ | [#2356](https://github.com/exercism/python/issues/2356) | | -| | [rich-comparisons](https://github.com/exercism/python/blob/main/concepts/rich-comparisons) | | ~ | [#2287](https://github.com/exercism/python/issues/2287) | | -| | [function-arguments](https://github.com/exercism/python/blob/main/concepts/function-arguments) | | ~ | [#2354](https://github.com/exercism/python/issues/2354) | | -| | [class-customization](https://github.com/exercism/python/blob/main/concepts/class-customization) | | ~ | [#2350](https://github.com/exercism/python/issues/2350) | | -| | [class-inheritance](https://github.com/exercism/python/blob/main/concepts/class-inheritance) | | ~ | [#2351](https://github.com/exercism/python/issues/2351) | | -| | [user-defined-errors](https://github.com/exercism/python/blob/main/concepts/user-defined-errors) | | ~ | TBD | | -| | [context-manager-customization](https://github.com/exercism/python/blob/main/concepts/context-manager-customization) | | ~ | [#2370](https://github.com/exercism/python/issues/2370) | | -| | [higher-order-functions](https://github.com/exercism/python/blob/main/concepts/higher-order-functions) | | ~ | [#2355](https://github.com/exercism/python/issues/2355) | | -| | [functional-tools](https://github.com/exercism/python/blob/main/concepts/functional-tools) | | ~ | [#2359](https://github.com/exercism/python/issues/2359) | | -| | [functools](https://github.com/exercism/python/blob/main/concepts/functools) | | ~ | [#2366](https://github.com/exercism/python/issues/2366) | | -| | [anonymous-functions](https://github.com/exercism/python/blob/main/concepts) | | ~ | [#2357](https://github.com/exercism/python/issues/2357) | | -| | [descriptors](https://github.com/exercism/python/blob/main/concepts/descriptors) | | ~ | [#2365](https://github.com/exercism/python/issues/2365) | | -| | [aliasing](https://github.com/exercism/python/blob/main/concepts) | | ~ | TBD | | -| | [binary data](https://github.com/exercism/python/blob/main/concepts/binary-data) | | ~ | TBD | | -| | [bitflags](https://github.com/exercism/python/blob/main/concepts/bitflags) | | ~ | TBD | | -| | [bitwise-operators](https://github.com/exercism/python/blob/main/concepts/bitwise-operators) | | ~ | TBD | | -| | [bytes](https://github.com/exercism/python/blob/main/concepts/bytes) | | ~ | TBD | | -| | [class-composition](https://github.com/exercism/python/blob/main/concepts/class-composition) | | ~ | [#2352](https://github.com/exercism/python/issues/2352) | | -| | [class-interfaces](https://github.com/exercism/python/blob/main/concepts/class-interfaces) | | ~ | TBD | | -| | [collections](https://github.com/exercism/python/blob/main/concepts/collections) | | ~ | TBD | | -| | [dataclasses-and-namedtuples](https://github.com/exercism/python/blob/main/concepts/dataclasses-and-namedtuples) | | ~ | [#2361](https://github.com/exercism/python/issues/2361) | | -| | [import](https://github.com/exercism/python/blob/main/concepts/import) | | ~ | ON HOLD | | -| | [memoryview](https://github.com/exercism/python/blob/main/concepts/memoryview) | | ~ | TBD | | -| | [operator-overloading](https://github.com/exercism/python/blob/main/concepts/operator-overloading) | | ~ | TBD | | -| | [regular-expressions](https://github.com/exercism/python/blob/main/concepts/regular-expressions) | | ~ | TBD | | -| | [string-methods-splitting](https://github.com/exercism/python/blob/main/concepts/string-methods-splitting) | | ~ | TBD | | -| | [testing](https://github.com/exercism/python/blob/main/concepts/testing) | | ~ | TBD | | -| | [text-processing](https://github.com/exercism/python/blob/main/concepts/text-processing) | | ~ | TBD | | -| | [type-hinting](https://github.com/exercism/python/blob/main/concepts/type-hinting) | | ~ | TBD | | -| | [unicode-regular-expressions](https://github.com/exercism/python/blob/main/concepts/unicode-regular-expressions) | | ~ | TBD | | -| | [walrus-operator](https://github.com/exercism/python/blob/main/concepts/walrus-operator) | | ~ | TBD | | +## Implemented & Planned Concept Exercises + +

= live on exercism.org        + = drafted but not live

+

= planned or in progress    + = future

+ +
+ +| Status | Concept | About&Intro | Exercise | Design Doc or Issue | Stub
Docstring Level | +| :--------------------------------------------: | :----------------------------------------------------------- | :--------------------------------------------: | :----------------------------------------------------------- | :----------------------------------------------------------- | :---------------------- | +| | [basics](https://github.com/exercism/python/blob/main/concepts/basics) | | [Guidos Gorgeous Lasagna](https://github.com/exercism/python/tree/main/tree/main/exercises/concept/guidos-gorgeous-lasagna) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/guidos-gorgeous-lasagna/.meta) | Full | +| | [bools](https://github.com/exercism/python/blob/main/concepts/bools) | | [Ghost Gobble Arcade Game](https://github.com/exercism/python/tree/main/tree/main/exercises/concept/ghost-gobble-arcade-game) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/ghost-gobble-arcade-game/.meta) | Full | +| | [numbers](https://github.com/exercism/python/blob/main/concepts/numbers) | | [Currency Exchange](https://github.com/exercism/python/tree/main/exercises/concept/currency-exchange) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/currency-exchange/.meta) | Full | +| | [complex-numbers](https://github.com/exercism/python/blob/main/concepts/complex-numbers) | | ~ | [#2208](https://github.com/exercism/v3/issues/2208) | TBD | +| | [conditionals](https://github.com/exercism/python/blob/main/concepts/conditionals) | | [Meltdown Mitigation ](https://github.com/exercism/python/tree/main/exercises/concept/meltdown-mitigation) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/meltdown-mitigation/.meta) | Full | +| | [comparisons](https://github.com/exercism/python/blob/main/concepts/comparisons) | | [Black Jack](https://github.com/exercism/python/tree/main/exercises/concept/black-jack) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/black-jack/.meta) | Full | +| | [strings](https://github.com/exercism/python/blob/main/concepts/strings) | | [Litte Sister's Vocab](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-vocab) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-vocab/.meta) | Full | +| | [string-methods](https://github.com/exercism/python/blob/main/concepts/string-methods) | | [Litte Sister's Essay](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-essay) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/little-sisters-essay/.meta) | Full | +| | [string-formatting](https://github.com/exercism/python/blob/main/concepts/string-formatting) | | TBD (_rewrite_) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/pretty-leaflet/.meta) | Full | +| | [lists](https://github.com/exercism/python/blob/main/concepts/lists) | | [Card Games](https://github.com/exercism/python/tree/main/exercises/concept/card-games) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/card-games/.meta) | Full | +| | [list-methods](https://github.com/exercism/python/blob/main/concepts/list-methods) | | [Chaitanas Colossal Coaster](https://github.com/exercism/python/tree/main/exercises/concept/chaitanas-colossal-coaster) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/chaitanas-colossal-coaster/.meta) | Full | +| | [loops](https://github.com/exercism/python/blob/main/concepts/loops) | | [Making the Grade](https://github.com/exercism/python/tree/main/exercises/concept/making-the-grade) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/making-the-grade/.meta) | Full | +| | [tuples](https://github.com/exercism/python/blob/main/concepts/tuples) | | [Tisbury Treasure Hunt](https://github.com/exercism/python/tree/main/exercises/concept/tisbury-treasure-hunt) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/tisbury-treasure-hunt/.meta) | Full | +| | [sequences](https://github.com/exercism/python/blob/main/concepts/sequences) | | [Thalias Tram Troubles]() | [#2290](https://github.com/exercism/python/issues/2290) | TBD | +| | [dicts](https://github.com/exercism/python/blob/main/concepts/dicts) | | [Inventory Management](https://github.com/exercism/python/tree/main/exercises/concept/inventory-management) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/inventory-management) | Full | +| | [dict-methods](https://github.com/exercism/python/blob/main/concepts/dict-methods) | | [Mecha Munch Management](https://github.com/exercism/python/tree/main/exercises/concept/mecha-munch-management) | [.meta folder](https://github.com/exercism/python/tree/main/exercises/concept/mecha-munch-management/.meta) | Full | +| | [sets](https://github.com/exercism/python/blob/main/concepts/sets) | | [Cater Waiter ](https://github.com/exercism/python/tree/main/exercises/concept/cater-waiter) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/cater-waiter/.meta) | Full | +| | [list-comprehensions](https://github.com/exercism/python/blob/main/concepts/list-comprehensions) | | ~ | [#2295](https://github.com/exercism/python/issues/2295) | | +| | [other-comprehensions](https://github.com/exercism/python/blob/main/concepts/other-comprehensions) | | ~ | [#2294](https://github.com/exercism/python/issues/2294) | | +| | [classes](https://github.com/exercism/python/blob/main/concepts/classes) | | [Ellen's Alien Game](https://github.com/exercism/python/tree/main/exercises/concept/ellens-alien-game) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/ellens-alien-game/.meta) | Minimal | +| | [generators](https://github.com/exercism/python/blob/main/concepts/generators) | | [Plane Tickets](https://github.com/exercism/python/tree/main/exercises/concept/plane-tickets) | [.meta folder (WIP)](https://github.com/exercism/python/tree/main/exercises/concept/plane-tickets/.meta) | Minimal | +| | [generator-expressions](https://github.com/exercism/python/blob/main/concepts/generator-expressions) | | ~ | [#2292](https://github.com/exercism/python/issues/2292) | | +| | [iterators](https://github.com/exercism/python/blob/main/concepts/iterators) | | ~ | [#2367](https://github.com/exercism/python/issues/2367) | TBD | +| | [functions](https://github.com/exercism/python/blob/main/concepts/functions) | | ~ | [#2353](https://github.com/exercism/python/issues/2353) | | +| | [unpacking-and-multiple-assignment](https://github.com/exercism/python/blob/main/concepts/unpacking-and-multiple-assignment) | | [Locomotive Engineer](https://exercism.org/tracks/python/exercises/locomotive-engineer) | [.meta folder](https://github.com/exercism/python/tree/main/exercises/concept/locomotive-engineer/.meta) | Full | +| | [raising-and-handling-errors](https://github.com/exercism/python/blob/main/concepts/raising-and-handling-errors) | | ~ | TB | | +| | [itertools](https://github.com/exercism/python/blob/main/concepts/itertools) | | Ice Cream Stand | [#2368](https://github.com/exercism/python/issues/2368) & [PR #3288](https://github.com/exercism/python/pull/3288) | Minimal | +| | [with-statement](https://github.com/exercism/python/blob/main/concepts/with-statement) | | ~ | [#2369](https://github.com/exercism/python/issues/2369) | | +| | [enums](https://github.com/exercism/python/blob/main/concepts/enums) | | [Log Levels](https://github.com/exercism/python/tree/main/exercises/concept/log-levels) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/log-levels) | Minimal | +| | [none](https://github.com/exercism/python/blob/main/concepts/none) | | [Restaurant Rozalynn](https://github.com/exercism/python/tree/main/exercises/concept/restaurant-rozalynn) | [`.meta`folder](https://github.com/exercism/python/tree/main/exercises/concept/restaurant-rozalynn/.meta) | Minimal | +| | [decorators](https://github.com/exercism/python/blob/main/concepts/decorators) | | ~ | [#2356](https://github.com/exercism/python/issues/2356) | | +| | [rich-comparisons](https://github.com/exercism/python/blob/main/concepts/rich-comparisons) | | ~ | [#2287](https://github.com/exercism/python/issues/2287) | | +| | [function-arguments](https://github.com/exercism/python/blob/main/concepts/function-arguments) | | ~ | [#2354](https://github.com/exercism/python/issues/2354) | | +| | [class-customization](https://github.com/exercism/python/blob/main/concepts/class-customization) | | ~ | [#2350](https://github.com/exercism/python/issues/2350) | | +| | [class-inheritance](https://github.com/exercism/python/blob/main/concepts/class-inheritance) | | ~ | [#2351](https://github.com/exercism/python/issues/2351) | | +| | [user-defined-errors](https://github.com/exercism/python/blob/main/concepts/user-defined-errors) | | ~ | TBD | | +| | [context-manager-customization](https://github.com/exercism/python/blob/main/concepts/context-manager-customization) | | ~ | [#2370](https://github.com/exercism/python/issues/2370) | | +| | [higher-order-functions](https://github.com/exercism/python/blob/main/concepts/higher-order-functions) | | ~ | [#2355](https://github.com/exercism/python/issues/2355) | | +| | [functional-tools](https://github.com/exercism/python/blob/main/concepts/functional-tools) | | ~ | [#2359](https://github.com/exercism/python/issues/2359) | | +| | [functools](https://github.com/exercism/python/blob/main/concepts/functools) | | ~ | [#2366](https://github.com/exercism/python/issues/2366) | | +| | [anonymous-functions](https://github.com/exercism/python/blob/main/concepts) | | ~ | [#2357](https://github.com/exercism/python/issues/2357) | | +| | [descriptors](https://github.com/exercism/python/blob/main/concepts/descriptors) | | ~ | [#2365](https://github.com/exercism/python/issues/2365) | | +| | [aliasing](https://github.com/exercism/python/blob/main/concepts) | | ~ | TBD | | +| | [binary data](https://github.com/exercism/python/blob/main/concepts/binary-data) | | ~ | TBD | | +| | [bitflags](https://github.com/exercism/python/blob/main/concepts/bitflags) | | ~ | TBD | | +| | [bitwise-operators](https://github.com/exercism/python/blob/main/concepts/bitwise-operators) | | ~ | TBD | | +| | [bytes](https://github.com/exercism/python/blob/main/concepts/bytes) | | ~ | TBD | | +| | [class-composition](https://github.com/exercism/python/blob/main/concepts/class-composition) | | ~ | [#2352](https://github.com/exercism/python/issues/2352) | | +| | [class-interfaces](https://github.com/exercism/python/blob/main/concepts/class-interfaces) | | ~ | TBD | | +| | [collections](https://github.com/exercism/python/blob/main/concepts/collections) | | ~ | TBD | | +| | [dataclasses](https://github.com/exercism/python/blob/main/concepts/dataclasses) | | ~ | [#2361](https://github.com/exercism/python/issues/2361) | | +| | [import](https://github.com/exercism/python/blob/main/concepts/import) | | ~ | ON HOLD | | +| | [memoryview](https://github.com/exercism/python/blob/main/concepts/memoryview) | | ~ | TBD | | +| | [operator-overloading](https://github.com/exercism/python/blob/main/concepts/operator-overloading) | | ~ | TBD | | +| | [regular-expressions](https://github.com/exercism/python/blob/main/concepts/regular-expressions) | | ~ | TBD | | +| | [string-methods-splitting](https://github.com/exercism/python/blob/main/concepts/string-methods-splitting) | | ~ | TBD | | +| | [testing](https://github.com/exercism/python/blob/main/concepts/testing) | | ~ | TBD | | +| | [text-processing](https://github.com/exercism/python/blob/main/concepts/text-processing) | | ~ | TBD | | +| | [type-hinting](https://github.com/exercism/python/blob/main/concepts/type-hinting) | | ~ | TBD | | +| | [unicode-regular-expressions](https://github.com/exercism/python/blob/main/concepts/unicode-regular-expressions) | | ~ | TBD | | +| | [walrus-operator](https://github.com/exercism/python/blob/main/concepts/walrus-operator) | | ~ | TBD | |

+ ## Concept Exercise Tree ```mermaid flowchart TD %%{init: {"theme": "base", "themeVariables": { "fontFamily": "Victor Mono, San Francisco, Roboto", "fontSize" : "18px", "primaryColor": "#D9D7FF", "nodeBorder": "#9F80DF", "lineColor": "#AFAC6A"}}}%% +classDef TBD-F fill:#C4D7FF,stroke:#97ACF5,stroke-width:4px,stroke-dasharray: 5 5, color: #5055C4; classDef TBD fill:#D9D7FF,stroke:#9F80DF,stroke-width:4px,stroke-dasharray: 5 5, color: #734CC4; classDef Beta fill:#F5DE90,stroke:#F6B303,stroke-width:2px, color:#525952; classDef WIP fill:#DEE8BB,stroke:#AFAC6A,stroke-width:4px,stroke-dasharray: 5 5, #908D49; %%concepts & exercise names (node labels) +aliasing((TBD-F
aliasing)):::TBD-F +array((TBD-F
array)):::TBD-F Basics((Guidos Gorgeous Lasagna
Basics)):::Beta +binary-data((TBD-F
binary-data>)):::TBD-F +bitwise-operations((TBD-F
bitwise-
operations
)):::TBD-F bools((Ghost Gobble
Arcade Game

bools)):::Beta +calendar((TBD-F
calendar)):::TBD-F classes((Ellen's Alien Game
Classes)):::Beta Class-customization((TBD
Class Customization)):::TBD +Class-composition((TBD-F
Class Composition)):::TBD-F Class-inheritance((TBD
Class Inheritance)):::TBD Class-interfaces((TBD
Class Interfaces)):::TBD -conditionals((Meltdown Mitigation
Conditionals)):::Beta +collections((TBD
Collections Module)):::TBD comparisons((Black Jack
comparisons)):::Beta +conditionals((Meltdown Mitigation
Conditionals)):::Beta + context-manager-customization((TBD
Context Manager
Customization
)):::TBD +copy((copy
copy)):::TBD-F +datetime((TBD
datetime)):::TBD decorators((TBD
Decorators)):::TBD +decimal((TBD-F
decimal)):::TBD-F descriptors((TBD
Descriptors)):::TBD list-comprehensions(("TBD
List Comprehensions")):::TBD other-comprehensions((TBD
Other Comprehensions)):::TBD +dataclasses((TBD-F
dataclasses)):::TBD-F dicts((Inventory
Management
dicts)):::Beta -dict-methods((TBD
Dict-Methods)):::TBD +dict-methods((Mecha
Munch Management

Dict-Methods)):::WIP enums((Log Levels
Enums)):::WIP -functions((TBD
Functions)):::WIP +enumerate((TBD
enumerate)):::TBD +ExceptionGroup((TBD-F
ExceptionGroup)):::TBD-F +fractions((TBD-F
fractions)):::TBD-F +functions((Exercise TBD
Functions)):::WIP function-arguments((TBD
Function Arguments)):::TBD functional-tools((TBD
Functional Tools)):::TBD functools((TBD
Functools Module)):::TBD @@ -298,64 +326,99 @@ generators((Plane Tickets
Generators)):::TBD generator-expressions((TBD
Generator Expressions)):::TBD higher-order-functions((TBD
Higher Order
Functions
)):::TBD anonymous-functions((TBD
Anonymous Functions
AKA Lambdas
)):::TBD +imports((TBD-F
imports)):::TBD-F iterators((TBD
iterators)):::TBD -itertools((TBD
itertools)):::TBD +itertools((Ice Cream Stand
itertools)):::WIP lists((Card Games
lists)):::Beta list-methods((Chaitana's
Colossal Coaster

list-methods)):::Beta +logging((TBD-F
Logging)):::TBD-F loops((Making the Grade
loops)):::Beta +math((TBD-F
math)):::TBD-F +cmath((TBD-F
cmath)):::TBD-F +memoryview((TBD-F
memoryview)):::TBD-F none((Restaurant Rozalynn
none)):::WIP numbers(("Currency Exchange
(ints & floats)")):::Beta -complex-numbers(("TBD (Bowling Game??)
complex-numbers
")):::TBD +complex-numbers(("TBD
(Bowling Game??)
complex-numbers
")):::TBD +binary-octal-hexadecimal(("WIP
Binary, Octal, &
Hexadecimal
")):::WIP +operator-overloading((TBD-F
operator-
overloading
)):::TBD-F raising-and-handling-errors((TBD
Raising &
Handling Errors
)):::TBD +regular-expressions((TBD
Regular Expressions)):::TBD +unicode-regular-expressions((TBD-F
Unicode Regex)):::TBD-F +random((TBD-F
random)):::TBD-F rich-comparisons((TBD
Rich Comparisons)):::TBD -sequences((TBD
sequences)):::TBD +statistics((TBD-F
statistics)):::TBD-F +secrets((TBD-F
secrets)):::TBD-F +sequences((Thalias
Tram Troubles

sequences)):::WIP sets((Cater-Waiter
sets)):::Beta strings((Little Sister's
Vocab

strings)):::Beta -string-formatting((Pretty Leaflet
String Formatting)):::WIP +string-formatting(("TBD (rewrite)
String Formatting")):::WIP string-methods((Little Sister's
Essay

String Methods)):::Beta -tuples((Tisbury
Treasure Hunt

tuples)):::Beta -unpacking-and-multiple-assignment((TBD
Unpacking
& Multi-assignment
)):::TBD +structural-pattern-matching((TBD
Structural
Pattern Matching
)):::TBD +tuples((Tisbury Treasure Hunt
tuples)):::Beta +type-annotation(("TBD-F
Type Annotation
(type hints)
")):::TBD-F +type-aliases((TBD-F
Type Aliases)):::TBD-F +unicode-data((TBD-F
unicode data)):::TBD-F +unpacking-and-multiple-assignment((Locomotive Engineer
Unpacking &
Multi-assignment
)):::Beta user-defined-errors((TBD
User Definied Errors)):::TBD +walrus-operator((TBD-F
Walrus Operator)):::TBD-F with(("TBD
with
(Context Managers)
")):::TBD +unittest(("TBD-F
unittest
(testing)
")):::TBD-F +doctests(("TBD-F
doctests")):::TBD-F +zip(("TBD
iterating with zip()")):::TBD %%exercise prerequisites (node relations) -Basics --> strings & numbers & bools & loops -Basics --> functions -bools --> conditionals -classes ---> iterators & Class-inheritance & Class-customization -conditionals --> strings & comparisons & loops +Basics --> strings & bools +Basics --> numbers & loops +binary-data --> memoryview +bools --> conditionals & bitwise-operations +classes ---> iterators & dataclasses & Class-inheritance & Class-customization +Class-customization --> type-annotation & Class-composition +conditionals --> strings & comparisons comparisons --> loops -loops --> tuples & with -loops --> itertools & functions +datetime --> calendar +decorators --> Class-customization +loops --> regular-expressions & tuples & imports +loops --> functions & with +regular-expressions --> structural-pattern-matching & unicode-regular-expressions list-comprehensions --> other-comprehensions -Class-customization --> rich-comparisons -Class-customization --> enums & decorators +Class-customization --> unittest & enums & rich-comparisons & logging +unittest --> doctests +Class-customization --> operator-overloading Class-inheritance --> user-defined-errors & descriptors & Class-interfaces Class-inheritance ----> context-manager-customization -other-comprehensions ---> generators -dicts --> dict-methods -functions --> function-arguments & higher-order-functions & functional-tools +other-comprehensions ---> walrus-operator & generators +dicts --> dict-methods & copy +functions --> function-arguments & higher-order-functions +functions --> functional-tools function-arguments --> none functional-tools --> functools generators --> generator-expressions -higher-order-functions ---> decorators +higher-order-functions --> decorators higher-order-functions --> anonymous-functions +imports --> itertools & datetime & aliasing iterators --> generators -lists --> string-formatting & dicts & list-methods & list-comprehensions & sequences -numbers --> complex-numbers -sequences --> iterators -sets --> classes -strings --> string-methods & string-formatting & lists -strings --> raising-and-handling-errors -tuples --> sequences & sets & classes & unpacking-and-multiple-assignment +lists --> string-formatting & dicts & list-methods & list-comprehensions & array & sequences +numbers --> bitwise-operations & complex-numbers & fractions & decimal & binary-octal-hexadecimal & random & math & statistics +complex-numbers --> cmath +random --> secrets +sequences --> binary-data & iterators & enumerate +sets --> classes & collections +strings ----> string-formatting +strings --> raising-and-handling-errors & lists & string-methods & unicode-data & regular-expressions +tuples --> sequences & classes +tuples --> zip & unpacking-and-multiple-assignment +tuples ---> sets +tuples --> itertools +type-annotation --> type-aliases +user-defined-errors --> ExceptionGroup with --> context-manager-customization click Basics "https://exercism.org/tracks/python/exercises/guidos-gorgeous-lasagna" "basics" click bools "https://exercism.org/tracks/python/exercises/ghost-gobble-arcade-game" "bools" click classes "https://exercism.org/tracks/python/exercises/ellens-alien-game" "classes" -click Class-customization "https://github.com/exercism/python/tree/main/concepts/class-customization" "Class-customization" -click Class-inheritance "https://github.com/exercism/python/tree/main/concepts/class-inheritance" "Class-inheritance" +click Class-customization "https://github.com/exercism/python/issues/3094" "Class-customization" +click Class-inheritance "https://github.com/exercism/python/issues/3096" "Class-inheritance" click Class-interfaces "https://github.com/exercism/python/tree/main/concepts/class-interfaces" "Class-interfaces" click conditionals "https://exercism.org/tracks/python/exercises/meltdown-mitigation" "conditionals" click comparisons "https://exercism.org/tracks/python/exercises/black-jack" "comparisons" @@ -366,13 +429,13 @@ click list-comprehensions "https://github.com/exercism/python/issues/2295" "list click other-comprehensions "https://github.com/exercism/python/issues/2294" "other-comprehensions" click conditionals "https://exercism.org/tracks/python/exercises/meltdown-mitigation" "conditionals" click dicts "https://exercism.org/tracks/python/exercises/inventory-management" "dicts" -click dict-methods "https://github.com/exercism/python/issues/2348" "dict-methods" +click dict-methods "https://github.com/exercism/python/tree/main/exercises/concept/mecha-munch-management" "dict-methods" click enums "https://github.com/exercism/python/tree/main/exercises/concept/restaurant-rozalynn" "enums" click functions "https://github.com/exercism/python/issues/2353" "functions" click function-arguments "https://github.com/exercism/python/issues/2354" "function-arguments" click functional-tools "https://github.com/exercism/python/issues/2359" "functional-tools" click functools "https://github.com/exercism/python/issues/2366" "functools" -click generators "https://github.com/exercism/python/issues/2293" "generators" +click generators "https://github.com/exercism/python/tree/main/exercises/concept/plane-tickets" "generators" click generator-expressions "https://github.com/exercism/python/issues/2292" "generator-expressions" click higher-order-functions "https://github.com/exercism/python/issues/2355" "higher-order-functions" click anonymous-functions "https://github.com/exercism/python/issues/2357" "anonymous-functions" @@ -392,7 +455,7 @@ click strings "https://exercism.org/tracks/python/exercises/little-sisters-vocab click string-formatting "https://github.com/exercism/python/tree/main/exercises/concept/pretty-leaflet" "string-formatting" click string-methods "https://exercism.org/tracks/python/exercises/little-sisters-essay" "string-methods" click tuples "https://exercism.org/tracks/python/exercises/tisbury-treasure-hunt" "tuples" -click unpacking-and-multiple-assignment "https://github.com/exercism/python/issues/2360" "unpacking-and-multiple-assignment" +click unpacking-and-multiple-assignment "https://github.com/exercism/python/tree/main/exercises/concept/locomotive-engineer" "unpacking-and-multiple-assignment" click user-defined-errors "https://github.com/exercism/python/tree/main/concepts/user-defined-errors" "user-defined-errors" click with "https://github.com/exercism/python/issues/2369" "with" ``` From a225ea98b41ab6cc332fcaee06ee4508efb0147a Mon Sep 17 00:00:00 2001 From: Srini Maiya <75990547+SriniMaiya@users.noreply.github.com> Date: Wed, 26 Jul 2023 18:04:07 +0200 Subject: [PATCH 122/126] Typo in writing 999 billion .... 999 thousand 999 (#3476) Missing a 9 in the unit's digit. Does not match the desciption given at instructions.md of "It's fine to stop at "trillion". --- exercises/practice/say/.docs/instructions.append.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/practice/say/.docs/instructions.append.md b/exercises/practice/say/.docs/instructions.append.md index aed8f067747..43365a7397a 100644 --- a/exercises/practice/say/.docs/instructions.append.md +++ b/exercises/practice/say/.docs/instructions.append.md @@ -12,6 +12,6 @@ To raise a `ValueError` with a message, write the message as an argument to the # if the number is negative raise ValueError("input out of range") -# if the number is larger than 999,999,999,99 +# if the number is larger than 999,999,999,999 raise ValueError("input out of range") ``` From 053e71e2e3accca27f92d9cbd39dd5645d9ba36f Mon Sep 17 00:00:00 2001 From: Erik Schierboom Date: Wed, 26 Jul 2023 19:47:54 +0200 Subject: [PATCH 123/126] simple-linked-list: use AWS hosted images (#3475) * simple-linked-list: use AWS hosted images * Apply suggestions from code review --------- Co-authored-by: BethanyG --- exercises/practice/simple-linked-list/.docs/hints.md | 2 +- .../practice/simple-linked-list/.docs/instructions.append.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/exercises/practice/simple-linked-list/.docs/hints.md b/exercises/practice/simple-linked-list/.docs/hints.md index 4fd7f9ace08..1ecef83ea24 100644 --- a/exercises/practice/simple-linked-list/.docs/hints.md +++ b/exercises/practice/simple-linked-list/.docs/hints.md @@ -5,7 +5,7 @@ - This challenge is about creating a [_stack_][Baeldung: The Stack Data Structure] using a [singly linked list][singly linked list]. - Unlike stacks underpinned with `lists`, `collections.deque`, or `queue.LifoQueue`, we ask you create custom `Node` and `LinkedList` [`classes`][classes tutorial] to store and link elements. -![Diagram representing a stack implemented with a linked list. A circle with a dashed border named New_Node is to the far left-hand side, with two dotted arrow lines pointing right-ward. New_Node reads "(becomes head) - New_Node - next = node_6". The top dotted arrow line is labeled "push" and points to Node_6, above and to the right. Node_6 reads "(current) head - Node_6 - next = node_5". The bottom dotted arrow line is labeled "pop" and points to a box that reads "gets removed on pop()". Node_6 has a solid arrow that points rightward to Node_5, which reads "Node_5 - next = node_4". Node_5 has a solid arrow pointing rightward to Node_4, which reads "Node_4 - next = node_3". Node_4 has a solid arrow pointing rightward to Node_3, which reads "Node_3 - next = node_2". Node_3 has a solid arrow pointing rightward to Node_2, which reads "Node_2 - next = node_1". Node_2 has a solid arrow pointing rightward to Node_1, which reads "(current) tail - Node_1 - next = None". Node_1 has a dotted arrow pointing rightward to a node that says "None".](https://media.githubusercontent.com/media/exercism/v3-files/main/python/simple-linked-list/linked-list.svg) +![Diagram representing a stack implemented with a linked list. A circle with a dashed border named New_Node is to the far left-hand side, with two dotted arrow lines pointing right-ward. New_Node reads "(becomes head) - New_Node - next = node_6". The top dotted arrow line is labeled "push" and points to Node_6, above and to the right. Node_6 reads "(current) head - Node_6 - next = node_5". The bottom dotted arrow line is labeled "pop" and points to a box that reads "gets removed on pop()". Node_6 has a solid arrow that points rightward to Node_5, which reads "Node_5 - next = node_4". Node_5 has a solid arrow pointing rightward to Node_4, which reads "Node_4 - next = node_3". This pattern continues until Node_1, which reads "(current) tail - Node_1 - next = None". Node_1 has a dotted arrow pointing rightward to a node that says "None".](https://exercism-v3-icons.s3.eu-west-2.amazonaws.com/images/tracks/python/simple-linked-list/linked-list.svg) - [Real Python: Linked Lists][Real Python Linked Lists], [Towards Data Science: Demystifying the Linked List][towards data science demystifying the linked list], and [ADS Stack in Python][Koder Dojo Coding an ADS Stack in Python] can be helpful to review for details on implementation. - Your `LinkedList` should accept a `list` argument to its _constructor_, but should not use a `list` to store nodes or elements. diff --git a/exercises/practice/simple-linked-list/.docs/instructions.append.md b/exercises/practice/simple-linked-list/.docs/instructions.append.md index 8e565516c46..41db11df966 100644 --- a/exercises/practice/simple-linked-list/.docs/instructions.append.md +++ b/exercises/practice/simple-linked-list/.docs/instructions.append.md @@ -4,12 +4,12 @@ While `stacks` and `queues` can be implemented using `lists`, `collections.deque`, `queue.LifoQueue`, and `multiprocessing.Queue`, this exercise expects a ["Last in, First Out" (`LIFO`) stack][Baeldung: The Stack Data Structure] (_interactive example [here][LIFO Stack]_) using a _custom-made_ [singly linked list][singly linked list]. -![Diagram representing a stack implemented with a linked list. A circle with a dashed border named New_Node is to the far left-hand side, with two dotted arrow lines pointing right-ward. New_Node reads "(becomes head) - New_Node - next = node_6". The top dotted arrow line is labeled "push" and points to Node_6, above and to the right. Node_6 reads "(current) head - Node_6 - next = node_5". The bottom dotted arrow line is labeled "pop" and points to a box that reads "gets removed on pop()". Node_6 has a solid arrow that points rightward to Node_5, which reads "Node_5 - next = node_4". Node_5 has a solid arrow pointing rightward to Node_4, which reads "Node_4 - next = node_3". Node_4 has a solid arrow pointing rightward to Node_3, which reads "Node_3 - next = node_2". Node_3 has a solid arrow pointing rightward to Node_2, which reads "Node_2 - next = node_1". Node_2 has a solid arrow pointing rightward to Node_1, which reads "(current) tail - Node_1 - next = None". Node_1 has a dotted arrow pointing rightward to a node that says "None".](https://media.githubusercontent.com/media/exercism/v3-files/main/python/simple-linked-list/linked-list.svg) +![Diagram representing a stack implemented with a linked list. A circle with a dashed border named New_Node is to the far left-hand side, with two dotted arrow lines pointing right-ward. New_Node reads "(becomes head) - New_Node - next = node_6". The top dotted arrow line is labeled "push" and points to Node_6, above and to the right. Node_6 reads "(current) head - Node_6 - next = node_5". The bottom dotted arrow line is labeled "pop" and points to a box that reads "gets removed on pop()". Node_6 has a solid arrow that points rightward to Node_5, which reads "Node_5 - next = node_4". Node_5 has a solid arrow pointing rightward to Node_4, which reads "Node_4 - next = node_3". This pattern continues until Node_1, which reads "(current) tail - Node_1 - next = None". Node_1 has a dotted arrow pointing rightward to a node that says "None".](https://exercism-v3-icons.s3.eu-west-2.amazonaws.com/images/tracks/python/simple-linked-list/linked-list.svg) This should not be confused with a [`LIFO` stack using a dynamic array or list][LIFO Stack Array], which may use a `list` underneath. Dynamic array based `stacks` have a different `head` position and different time complexity (Big-O) and memory footprint. -![Diagram representing a stack implemented with an array/dynamic array. A box with a dashed border named New_Node is to the far right-hand side, with two dotted arrow lines pointing left-ward. New_Node reads "(becomes head) - New_Node". The top dotted arrow line is labeled "append" and points to Node_6, above and to the left. Node_6 reads "(current) head - Node_6". The bottom dotted arrow line is labeled "pop" and points to a box with a dotted outline that reads "gets removed on pop()". Node_6 has a solid arrow that points leftward to Node_5. Node_5 has a solid arrow pointing leftward to Node_4. Node_4 has a solid arrow pointing leftward to Node_3. Node_3 has a solid arrow pointing rightward to Node_2. Node_2 has a solid arrow pointing rightward to Node_1, which reads "(current) tail - Node_1".](https://media.githubusercontent.com/media/exercism/v3-files/main/python/simple-linked-list/linked_list_array.svg) +![Diagram representing a stack implemented with an array/dynamic array. A box with a dashed border named New_Node is to the far right-hand side, with two dotted arrow lines pointing left-ward. New_Node reads "(becomes head) - New_Node". The top dotted arrow line is labeled "append" and points to Node_6, above and to the left. Node_6 reads "(current) head - Node_6". The bottom dotted arrow line is labeled "pop" and points to a box with a dotted outline that reads "gets removed on pop()". Node_6 has a solid arrow that points leftward to Node_5. Node_5 has a solid arrow pointing leftward to Node_4. This pattern continues until Node_1, which reads "(current) tail - Node_1".](https://exercism-v3-icons.s3.eu-west-2.amazonaws.com/images/tracks/python/simple-linked-list/linked_list_array.svg) See these two Stack Overflow questions for some considerations: [Array-Based vs List-Based Stacks and Queues][Stack Overflow: Array-Based vs List-Based Stacks and Queues] and [Differences between Array Stack, Linked Stack, and Stack][Stack Overflow: What is the difference between Array Stack, Linked Stack, and Stack]. From 6ac3e06d89dbf0ddf3947d772d143214141d4024 Mon Sep 17 00:00:00 2001 From: Andrew Lawendy <22712035+AndrewLawendy@users.noreply.github.com> Date: Sat, 29 Jul 2023 16:23:51 +0300 Subject: [PATCH 124/126] [Gigasecond]: Large Number Formatting Instruction Append and Hints File (#3473) * docs(gigasecond): init dig deeper * docs(gigasecond): add scientific notation reference * docs: :memo: add config.json * docs(config): :fire: remove approaches * docs(approaches): :fire: remove info from approaches * docs(instructions): :sparkles: add info in append * docs(hints): :sparkles: add info * docs: :bug: fix underscores notation example * Reformatted for display [no important files changed] --------- Co-authored-by: BethanyG --- exercises/practice/gigasecond/.docs/hints.md | 14 ++++++++++++-- .../gigasecond/.docs/instructions.append.md | 16 ++++++++++++++-- exercises/practice/gigasecond/.meta/config.json | 3 ++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/exercises/practice/gigasecond/.docs/hints.md b/exercises/practice/gigasecond/.docs/hints.md index 0375a753afe..d4891ef8eb2 100644 --- a/exercises/practice/gigasecond/.docs/hints.md +++ b/exercises/practice/gigasecond/.docs/hints.md @@ -1,6 +1,16 @@ # Hints -## General -- Your code should parse a datetime object, add a gigasecond's worth of time to it, and then return the result as a datetime object. +## General + +- Your function should parse the passed-in [datetime object][dtatetime], add a gigasecond's worth of time to it, and then return the result. - If you're having trouble, remember to take a look at the provided test cases under the Tests tab. These will help you figure out what the expected inputs and outputs of your function(s) should be. + +- Most of the time, code is read rather than written, and a big number can be a challenge to read. Here are a couple of approaches to making big numbers in your code more readable: + + - Using underscores (`_`) in numeric literals can help offset thousands, hundred-thousands, millions, etc. (_**ie:** `1_000_000` or `10_100_201_330` is far more readable than `1000000` or `10100201330`._) See [PEP-0515][underscores_notation] for more information. + + - Scientific notation can be more compact and easier to scan when there are very large numbers (_**ie:** `1e6`, 1 is multiplied by 10 raised to the power of 6, which equals `1000000`_). For more information, see this reference on [scientific notation][scientific_notation]. + +[scientific_notation]: https://python-reference.readthedocs.io/en/latest/docs/float/scientific.html +[underscores_notation]: https://peps.python.org/pep-0515/#:~:text=The%20syntax%20would%20be%20the,width%20of%2010%20with%20*%20separator. diff --git a/exercises/practice/gigasecond/.docs/instructions.append.md b/exercises/practice/gigasecond/.docs/instructions.append.md index 832fec734c8..ccb6f2d05bb 100644 --- a/exercises/practice/gigasecond/.docs/instructions.append.md +++ b/exercises/practice/gigasecond/.docs/instructions.append.md @@ -1,5 +1,15 @@ # Instructions append +## Reading and Writing Long Numbers + +Code is more often _read_ than it is written, and reading a big/long number within other text can be a challenge. +Here are two approaches to making numbers more readable: + +1. Using underscores in Numeric Literals. `1_000_000` is more readable than `1000000`, and `10_100_201_330` is easier to scan than `10100201330`. For more information, see [PEP-0515][underscores_notation]. + +2. Using exponential notation or scientific notation. The e (or E) character followed by an integer represents the power of 10 by which the number preceding the e should be multiplied (_**ie:** `1e6`, 1 is multiplied by 10 raised to the power of 6, which equals `1000000`_). For more details, check out this reference on [scientific notation][scientific_notation]. + + ## Dates and Times in Python This exercise explores objects from Python's `datetime` module: @@ -8,6 +18,8 @@ This exercise explores objects from Python's `datetime` module: - [datetime objects][datetime.datetime] - [timedelta objects][datetime.timedelta] -[datetime]: https://docs.python.org/3.9/library/datetime.html#module-datetime [datetime.datetime]: https://docs.python.org/3.9/library/datetime.html#datetime.datetime -[datetime.timedelta]: https://docs.python.org/3.9/library/datetime.html#timedelta-objects \ No newline at end of file +[datetime.timedelta]: https://docs.python.org/3.9/library/datetime.html#timedelta-objects +[datetime]: https://docs.python.org/3.9/library/datetime.html#module-datetime +[scientific_notation]: https://python-reference.readthedocs.io/en/latest/docs/float/scientific.html +[underscores_notation]: https://peps.python.org/pep-0515/#:~:text=The%20syntax%20would%20be%20the,width%20of%2010%20with%20*%20separator. diff --git a/exercises/practice/gigasecond/.meta/config.json b/exercises/practice/gigasecond/.meta/config.json index 59b2d30cc9e..76af3dac048 100644 --- a/exercises/practice/gigasecond/.meta/config.json +++ b/exercises/practice/gigasecond/.meta/config.json @@ -15,7 +15,8 @@ "pheanex", "sjakobi", "tqa236", - "yawpitch" + "yawpitch", + "AndrewLawendy" ], "files": { "solution": [ From a5d6a9066e55ab188fe80b6e3248c10e95f94fe8 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Sat, 29 Jul 2023 07:18:26 -0700 Subject: [PATCH 125/126] Update hints.md (#3479) Corrected broken/mis-spelled datetime.datetime reflink. --- exercises/practice/gigasecond/.docs/hints.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/exercises/practice/gigasecond/.docs/hints.md b/exercises/practice/gigasecond/.docs/hints.md index d4891ef8eb2..57f40ceee8b 100644 --- a/exercises/practice/gigasecond/.docs/hints.md +++ b/exercises/practice/gigasecond/.docs/hints.md @@ -2,7 +2,7 @@ ## General -- Your function should parse the passed-in [datetime object][dtatetime], add a gigasecond's worth of time to it, and then return the result. +- Your function should parse the passed-in [datetime object][datetime.datetime], add a gigasecond's worth of time to it, and then return the result. - If you're having trouble, remember to take a look at the provided test cases under the Tests tab. These will help you figure out what the expected inputs and outputs of your function(s) should be. @@ -12,5 +12,7 @@ - Scientific notation can be more compact and easier to scan when there are very large numbers (_**ie:** `1e6`, 1 is multiplied by 10 raised to the power of 6, which equals `1000000`_). For more information, see this reference on [scientific notation][scientific_notation]. +[datetime.datetime]: https://docs.python.org/3.9/library/datetime.html#datetime.datetime [scientific_notation]: https://python-reference.readthedocs.io/en/latest/docs/float/scientific.html [underscores_notation]: https://peps.python.org/pep-0515/#:~:text=The%20syntax%20would%20be%20the,width%20of%2010%20with%20*%20separator. + From 6c9a7ea0f4f6d4d09aa5997bcfea374422aa0805 Mon Sep 17 00:00:00 2001 From: BethanyG Date: Sat, 29 Jul 2023 07:29:34 -0700 Subject: [PATCH 126/126] Correct typo in reflink for hints file. (#3481) Seeing if a second attempt might help with #3480 --- exercises/practice/gigasecond/.docs/hints.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/exercises/practice/gigasecond/.docs/hints.md b/exercises/practice/gigasecond/.docs/hints.md index 57f40ceee8b..30a36d1be94 100644 --- a/exercises/practice/gigasecond/.docs/hints.md +++ b/exercises/practice/gigasecond/.docs/hints.md @@ -2,7 +2,7 @@ ## General -- Your function should parse the passed-in [datetime object][datetime.datetime], add a gigasecond's worth of time to it, and then return the result. +- Your function should parse the passed-in [datetime object][datetime], add a gigasecond's worth of time to it, and then return the result. - If you're having trouble, remember to take a look at the provided test cases under the Tests tab. These will help you figure out what the expected inputs and outputs of your function(s) should be. @@ -12,7 +12,6 @@ - Scientific notation can be more compact and easier to scan when there are very large numbers (_**ie:** `1e6`, 1 is multiplied by 10 raised to the power of 6, which equals `1000000`_). For more information, see this reference on [scientific notation][scientific_notation]. -[datetime.datetime]: https://docs.python.org/3.9/library/datetime.html#datetime.datetime +[datetime]: https://docs.python.org/3.9/library/datetime.html#datetime.datetime [scientific_notation]: https://python-reference.readthedocs.io/en/latest/docs/float/scientific.html [underscores_notation]: https://peps.python.org/pep-0515/#:~:text=The%20syntax%20would%20be%20the,width%20of%2010%20with%20*%20separator. -