From 2ee1856d7f3546bd97c3e1c39d51ef0231348560 Mon Sep 17 00:00:00 2001 From: Daniel Siepmann Date: Mon, 25 Mar 2024 10:14:17 +0100 Subject: [PATCH] Add new exercises for python --- python/leap/.exercism/config.json | 38 +++++++ python/leap/.exercism/metadata.json | 1 + python/leap/HELP.md | 130 ++++++++++++++++++++++++ python/leap/README.md | 53 ++++++++++ python/leap/leap.py | 2 + python/leap/leap_test.py | 38 +++++++ python/triangle/.exercism/config.json | 36 +++++++ python/triangle/.exercism/metadata.json | 1 + python/triangle/HELP.md | 130 ++++++++++++++++++++++++ python/triangle/README.md | 60 +++++++++++ python/triangle/triangle.py | 10 ++ python/triangle/triangle_test.py | 80 +++++++++++++++ 12 files changed, 579 insertions(+) create mode 100644 python/leap/.exercism/config.json create mode 100644 python/leap/.exercism/metadata.json create mode 100644 python/leap/HELP.md create mode 100644 python/leap/README.md create mode 100644 python/leap/leap.py create mode 100644 python/leap/leap_test.py create mode 100644 python/triangle/.exercism/config.json create mode 100644 python/triangle/.exercism/metadata.json create mode 100644 python/triangle/HELP.md create mode 100644 python/triangle/README.md create mode 100644 python/triangle/triangle.py create mode 100644 python/triangle/triangle_test.py diff --git a/python/leap/.exercism/config.json b/python/leap/.exercism/config.json new file mode 100644 index 0000000..1c35f22 --- /dev/null +++ b/python/leap/.exercism/config.json @@ -0,0 +1,38 @@ +{ + "authors": [], + "contributors": [ + "AnAccountForReportingBugs", + "behrtam", + "BethanyG", + "betojulio", + "cmccandless", + "cruxicheiros", + "Dog", + "fluxusfrequency", + "iandexter", + "ikhadykin", + "kytrinyx", + "lowks", + "N-Parsons", + "olufotebig", + "pheanex", + "sambryant4", + "sjakobi", + "tqa236", + "yawpitch" + ], + "files": { + "solution": [ + "leap.py" + ], + "test": [ + "leap_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Determine whether a given year is a leap year.", + "source": "CodeRanch Cattle Drive, Assignment 3", + "source_url": "https://coderanch.com/t/718816/Leap" +} diff --git a/python/leap/.exercism/metadata.json b/python/leap/.exercism/metadata.json new file mode 100644 index 0000000..48fc611 --- /dev/null +++ b/python/leap/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"python","exercise":"leap","id":"fd4b50a0ebbe49dc8e0b0c15b5551cfc","url":"https://exercism.org/tracks/python/exercises/leap","handle":"DanielSiepmann","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/python/leap/HELP.md b/python/leap/HELP.md new file mode 100644 index 0000000..13ed4ec --- /dev/null +++ b/python/leap/HELP.md @@ -0,0 +1,130 @@ +# Help + +## Running the tests + +We use [pytest][pytest: Getting Started Guide] as our website test runner. +You will need to install `pytest` on your development machine if you want to run tests for the Python track locally. +You should also install the following `pytest` plugins: + +- [pytest-cache][pytest-cache] +- [pytest-subtests][pytest-subtests] + +Extended information can be found in our website [Python testing guide][Python track tests page]. + + +### Running Tests + +To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_). +Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded. + +Linux/MacOS +```bash +$ cd {path/to/exercise-folder-location} +``` + +Windows +```powershell +PS C:\Users\foobar> cd {path\to\exercise-folder-location} +``` + +
+ +Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file: + +Linux/MacOS +```bash +$ python3 -m pytest -o markers=task {exercise_test.py} +==================== 7 passed in 0.08s ==================== +``` + +Windows +```powershell +PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py} +==================== 7 passed in 0.08s ==================== +``` + + +### Common options +- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_) +- `-v` : enable verbose output. +- `-x` : stop running tests on first failure. +- `--ff` : run failures from previous test before running other test cases. + +For additional options, use `python3 -m pytest -h` or `py -m pytest -h`. + + +### Fixing warnings + +If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax: + +```bash +PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html +``` + +To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file. +We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini]. + +You can also create your own `pytest.ini` file with the following content: + +```ini +[pytest] +markers = + task: A concept exercise task. +``` + +Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings. +More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers]. + +Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats]. + + +### Extending your IDE or Code Editor + +Many IDEs and code editors have built-in support for using `pytest` and other code quality tools. +Some community-sourced options can be found on our [Python track tools page][Python track tools page]. + +[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html +[Python track tools page]: https://exercism.org/docs/tracks/python/tools +[Python track tests page]: https://exercism.org/docs/tracks/python/tests +[pytest-cache]:http://pythonhosted.org/pytest-cache/ +[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests +[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini +[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats +[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks +[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers + +## Submitting your solution + +You can submit your solution using the `exercism submit leap.py` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Python track's documentation](https://exercism.org/docs/tracks/python) +- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +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. +- [Python Community Forums](https://discuss.python.org/) +- [Free Code Camp Community Forums](https://forum.freecodecamp.org/) +- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help) +- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually. + +Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already. + If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question. \ No newline at end of file diff --git a/python/leap/README.md b/python/leap/README.md new file mode 100644 index 0000000..e41fdaf --- /dev/null +++ b/python/leap/README.md @@ -0,0 +1,53 @@ +# Leap + +Welcome to Leap on Exercism's Python Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +A leap year (in the Gregorian calendar) occurs: + +- In every year that is evenly divisible by 4. +- Unless the year is evenly divisible by 100, in which case it's only a leap year if the year is also evenly divisible by 400. + +Some examples: + +- 1997 was not a leap year as it's not divisible by 4. +- 1900 was not a leap year as it's not divisible by 400. +- 2000 was a leap year! + +~~~~exercism/note +For a delightful, four-minute explanation of the whole phenomenon of leap years, check out [this YouTube video](https://www.youtube.com/watch?v=xX96xng7sAE). +~~~~ + +## Instructions + +Your task is to determine whether a given year is a leap year. + +## Source + +### Contributed to by + +- @AnAccountForReportingBugs +- @behrtam +- @BethanyG +- @betojulio +- @cmccandless +- @cruxicheiros +- @Dog +- @fluxusfrequency +- @iandexter +- @ikhadykin +- @kytrinyx +- @lowks +- @N-Parsons +- @olufotebig +- @pheanex +- @sambryant4 +- @sjakobi +- @tqa236 +- @yawpitch + +### Based on + +CodeRanch Cattle Drive, Assignment 3 - https://coderanch.com/t/718816/Leap \ No newline at end of file diff --git a/python/leap/leap.py b/python/leap/leap.py new file mode 100644 index 0000000..50fd034 --- /dev/null +++ b/python/leap/leap.py @@ -0,0 +1,2 @@ +def leap_year(year): + pass diff --git a/python/leap/leap_test.py b/python/leap/leap_test.py new file mode 100644 index 0000000..6a1d732 --- /dev/null +++ b/python/leap/leap_test.py @@ -0,0 +1,38 @@ +# 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-19 + +import unittest + +from leap import ( + leap_year, +) + + +class LeapTest(unittest.TestCase): + def test_year_not_divisible_by_4_in_common_year(self): + self.assertIs(leap_year(2015), False) + + def test_year_divisible_by_2_not_divisible_by_4_in_common_year(self): + self.assertIs(leap_year(1970), False) + + def test_year_divisible_by_4_not_divisible_by_100_in_leap_year(self): + self.assertIs(leap_year(1996), True) + + def test_year_divisible_by_4_and_5_is_still_a_leap_year(self): + self.assertIs(leap_year(1960), True) + + def test_year_divisible_by_100_not_divisible_by_400_in_common_year(self): + self.assertIs(leap_year(2100), False) + + def test_year_divisible_by_100_but_not_by_3_is_still_not_a_leap_year(self): + self.assertIs(leap_year(1900), False) + + def test_year_divisible_by_400_is_leap_year(self): + self.assertIs(leap_year(2000), True) + + def test_year_divisible_by_400_but_not_by_125_is_still_a_leap_year(self): + self.assertIs(leap_year(2400), True) + + def test_year_divisible_by_200_not_divisible_by_400_in_common_year(self): + self.assertIs(leap_year(1800), False) diff --git a/python/triangle/.exercism/config.json b/python/triangle/.exercism/config.json new file mode 100644 index 0000000..041bf28 --- /dev/null +++ b/python/triangle/.exercism/config.json @@ -0,0 +1,36 @@ +{ + "authors": [], + "contributors": [ + "behrtam", + "BethanyG", + "cmccandless", + "Dog", + "ikhadykin", + "kytrinyx", + "lowks", + "mpatibandla", + "N-Parsons", + "Nishant23", + "pheanex", + "rozuur", + "sjakobi", + "Stigjb", + "tqa236", + "xitanggg", + "YuriyCherniy" + ], + "files": { + "solution": [ + "triangle.py" + ], + "test": [ + "triangle_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Determine if a triangle is equilateral, isosceles, or scalene.", + "source": "The Ruby Koans triangle project, parts 1 & 2", + "source_url": "https://web.archive.org/web/20220831105330/http://rubykoans.com" +} diff --git a/python/triangle/.exercism/metadata.json b/python/triangle/.exercism/metadata.json new file mode 100644 index 0000000..c4076e3 --- /dev/null +++ b/python/triangle/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"python","exercise":"triangle","id":"0cf58530790e46efaaeaed5ed8256e34","url":"https://exercism.org/tracks/python/exercises/triangle","handle":"DanielSiepmann","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/python/triangle/HELP.md b/python/triangle/HELP.md new file mode 100644 index 0000000..2d9233f --- /dev/null +++ b/python/triangle/HELP.md @@ -0,0 +1,130 @@ +# Help + +## Running the tests + +We use [pytest][pytest: Getting Started Guide] as our website test runner. +You will need to install `pytest` on your development machine if you want to run tests for the Python track locally. +You should also install the following `pytest` plugins: + +- [pytest-cache][pytest-cache] +- [pytest-subtests][pytest-subtests] + +Extended information can be found in our website [Python testing guide][Python track tests page]. + + +### Running Tests + +To run the included tests, navigate to the folder where the exercise is stored using `cd` in your terminal (_replace `{exercise-folder-location}` below with your path_). +Test files usually end in `_test.py`, and are the same tests that run on the website when a solution is uploaded. + +Linux/MacOS +```bash +$ cd {path/to/exercise-folder-location} +``` + +Windows +```powershell +PS C:\Users\foobar> cd {path\to\exercise-folder-location} +``` + +
+ +Next, run the `pytest` command in your terminal, replacing `{exercise_test.py}` with the name of the test file: + +Linux/MacOS +```bash +$ python3 -m pytest -o markers=task {exercise_test.py} +==================== 7 passed in 0.08s ==================== +``` + +Windows +```powershell +PS C:\Users\foobar> py -m pytest -o markers=task {exercise_test.py} +==================== 7 passed in 0.08s ==================== +``` + + +### Common options +- `-o` : override default `pytest.ini` (_you can use this to avoid marker warnings_) +- `-v` : enable verbose output. +- `-x` : stop running tests on first failure. +- `--ff` : run failures from previous test before running other test cases. + +For additional options, use `python3 -m pytest -h` or `py -m pytest -h`. + + +### Fixing warnings + +If you do not use `pytest -o markers=task` when invoking `pytest`, you might receive a `PytestUnknownMarkWarning` for tests that use our new syntax: + +```bash +PytestUnknownMarkWarning: Unknown pytest.mark.task - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html +``` + +To avoid typing `pytest -o markers=task` for every test you run, you can use a `pytest.ini` configuration file. +We have made one that can be downloaded from the top level of the Python track directory: [pytest.ini][pytest.ini]. + +You can also create your own `pytest.ini` file with the following content: + +```ini +[pytest] +markers = + task: A concept exercise task. +``` + +Placing the `pytest.ini` file in the _root_ or _working_ directory for your Python track exercises will register the marks and stop the warnings. +More information on pytest marks can be found in the `pytest` documentation on [marking test functions][pytest: marking test functions with attributes] and the `pytest` documentation on [working with custom markers][pytest: working with custom markers]. + +Information on customizing pytest configurations can be found in the `pytest` documentation on [configuration file formats][pytest: configuration file formats]. + + +### Extending your IDE or Code Editor + +Many IDEs and code editors have built-in support for using `pytest` and other code quality tools. +Some community-sourced options can be found on our [Python track tools page][Python track tools page]. + +[Pytest: Getting Started Guide]: https://docs.pytest.org/en/latest/getting-started.html +[Python track tools page]: https://exercism.org/docs/tracks/python/tools +[Python track tests page]: https://exercism.org/docs/tracks/python/tests +[pytest-cache]:http://pythonhosted.org/pytest-cache/ +[pytest-subtests]:https://github.com/pytest-dev/pytest-subtests +[pytest.ini]: https://github.com/exercism/python/blob/main/pytest.ini +[pytest: configuration file formats]: https://docs.pytest.org/en/6.2.x/customize.html#configuration-file-formats +[pytest: marking test functions with attributes]: https://docs.pytest.org/en/6.2.x/mark.html#raising-errors-on-unknown-marks +[pytest: working with custom markers]: https://docs.pytest.org/en/6.2.x/example/markers.html#working-with-custom-markers + +## Submitting your solution + +You can submit your solution using the `exercism submit triangle.py` command. +This command will upload your solution to the Exercism website and print the solution page's URL. + +It's possible to submit an incomplete solution which allows you to: + +- See how others have completed the exercise +- Request help from a mentor + +## Need to get help? + +If you'd like help solving the exercise, check the following pages: + +- The [Python track's documentation](https://exercism.org/docs/tracks/python) +- The [Python track's programming category on the forum](https://forum.exercism.org/c/programming/python) +- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5) +- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs) + +Should those resources not suffice, you could submit your (incomplete) solution to request mentoring. + +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. +- [Python Community Forums](https://discuss.python.org/) +- [Free Code Camp Community Forums](https://forum.freecodecamp.org/) +- [CodeNewbie Community Help Tag](https://community.codenewbie.org/t/help) +- [Pythontutor](http://pythontutor.com/) for stepping through small code snippets visually. + +Additionally, [StackOverflow](http://stackoverflow.com/questions/tagged/python) is a good spot to search for your problem/question to see if it has been answered already. + If not - you can always [ask](https://stackoverflow.com/help/how-to-ask) or [answer](https://stackoverflow.com/help/how-to-answer) someone else's question. \ No newline at end of file diff --git a/python/triangle/README.md b/python/triangle/README.md new file mode 100644 index 0000000..961c673 --- /dev/null +++ b/python/triangle/README.md @@ -0,0 +1,60 @@ +# Triangle + +Welcome to Triangle on Exercism's Python Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Instructions + +Determine if a triangle is equilateral, isosceles, or scalene. + +An _equilateral_ triangle has all three sides the same length. + +An _isosceles_ triangle has at least two sides the same length. +(It is sometimes specified as having exactly two sides the same length, but for the purposes of this exercise we'll say at least two.) + +A _scalene_ triangle has all sides of different lengths. + +## Note + +For a shape to be a triangle at all, all sides have to be of length > 0, and the sum of the lengths of any two sides must be greater than or equal to the length of the third side. + +In equations: + +Let `a`, `b`, and `c` be sides of the triangle. +Then all three of the following expressions must be true: + +```text +a + b ≥ c +b + c ≥ a +a + c ≥ b +``` + +See [Triangle Inequality][triangle-inequality] + +[triangle-inequality]: https://en.wikipedia.org/wiki/Triangle_inequality + +## Source + +### Contributed to by + +- @behrtam +- @BethanyG +- @cmccandless +- @Dog +- @ikhadykin +- @kytrinyx +- @lowks +- @mpatibandla +- @N-Parsons +- @Nishant23 +- @pheanex +- @rozuur +- @sjakobi +- @Stigjb +- @tqa236 +- @xitanggg +- @YuriyCherniy + +### Based on + +The Ruby Koans triangle project, parts 1 & 2 - https://web.archive.org/web/20220831105330/http://rubykoans.com \ No newline at end of file diff --git a/python/triangle/triangle.py b/python/triangle/triangle.py new file mode 100644 index 0000000..3d088c7 --- /dev/null +++ b/python/triangle/triangle.py @@ -0,0 +1,10 @@ +def equilateral(sides): + pass + + +def isosceles(sides): + pass + + +def scalene(sides): + pass diff --git a/python/triangle/triangle_test.py b/python/triangle/triangle_test.py new file mode 100644 index 0000000..b279c83 --- /dev/null +++ b/python/triangle/triangle_test.py @@ -0,0 +1,80 @@ +# 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-19 + +import unittest + +from triangle import ( + equilateral, + isosceles, + scalene, +) + + +class EquilateralTriangleTest(unittest.TestCase): + def test_all_sides_are_equal(self): + self.assertIs(equilateral([2, 2, 2]), True) + + def test_any_side_is_unequal(self): + self.assertIs(equilateral([2, 3, 2]), False) + + def test_no_sides_are_equal(self): + self.assertIs(equilateral([5, 4, 6]), False) + + def test_all_zero_sides_is_not_a_triangle(self): + self.assertIs(equilateral([0, 0, 0]), False) + + def test_sides_may_be_floats(self): + self.assertIs(equilateral([0.5, 0.5, 0.5]), True) + + +class IsoscelesTriangleTest(unittest.TestCase): + def test_last_two_sides_are_equal(self): + self.assertIs(isosceles([3, 4, 4]), True) + + def test_first_two_sides_are_equal(self): + self.assertIs(isosceles([4, 4, 3]), True) + + def test_first_and_last_sides_are_equal(self): + self.assertIs(isosceles([4, 3, 4]), True) + + def test_equilateral_triangles_are_also_isosceles(self): + self.assertIs(isosceles([4, 4, 4]), True) + + def test_no_sides_are_equal(self): + self.assertIs(isosceles([2, 3, 4]), False) + + def test_first_triangle_inequality_violation(self): + self.assertIs(isosceles([1, 1, 3]), False) + + def test_second_triangle_inequality_violation(self): + self.assertIs(isosceles([1, 3, 1]), False) + + def test_third_triangle_inequality_violation(self): + self.assertIs(isosceles([3, 1, 1]), False) + + def test_sides_may_be_floats(self): + self.assertIs(isosceles([0.5, 0.4, 0.5]), True) + + +class ScaleneTriangleTest(unittest.TestCase): + def test_no_sides_are_equal(self): + self.assertIs(scalene([5, 4, 6]), True) + + def test_all_sides_are_equal(self): + self.assertIs(scalene([4, 4, 4]), False) + + def test_first_and_second_sides_are_equal(self): + self.assertIs(scalene([4, 4, 3]), False) + + def test_first_and_third_sides_are_equal(self): + self.assertIs(scalene([3, 4, 3]), False) + + def test_second_and_third_sides_are_equal(self): + self.assertIs(scalene([4, 3, 3]), False) + + def test_may_not_violate_triangle_inequality(self): + self.assertIs(scalene([7, 3, 2]), False) + + def test_sides_may_be_floats(self): + self.assertIs(scalene([0.5, 0.4, 0.6]), True)