From cad08c40f1c9e404c5605c5be14076a6529d4d9a Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sat, 13 Apr 2024 08:17:30 -0700 Subject: [PATCH] python/roman-numerals: download exercise --- python/roman-numerals/.exercism/config.json | 32 +++++ python/roman-numerals/.exercism/metadata.json | 1 + python/roman-numerals/HELP.md | 130 ++++++++++++++++++ python/roman-numerals/README.md | 99 +++++++++++++ python/roman-numerals/roman_numerals.py | 3 + python/roman-numerals/roman_numerals_test.py | 89 ++++++++++++ 6 files changed, 354 insertions(+) create mode 100644 python/roman-numerals/.exercism/config.json create mode 100644 python/roman-numerals/.exercism/metadata.json create mode 100644 python/roman-numerals/HELP.md create mode 100644 python/roman-numerals/README.md create mode 100644 python/roman-numerals/roman_numerals.py create mode 100644 python/roman-numerals/roman_numerals_test.py diff --git a/python/roman-numerals/.exercism/config.json b/python/roman-numerals/.exercism/config.json new file mode 100644 index 00000000..e66d34f2 --- /dev/null +++ b/python/roman-numerals/.exercism/config.json @@ -0,0 +1,32 @@ +{ + "authors": [], + "contributors": [ + "behrtam", + "BethanyG", + "cmccandless", + "Dog", + "dotrungkien", + "ikhadykin", + "kytrinyx", + "lowks", + "mpatibandla", + "N-Parsons", + "pheanex", + "sjakobi", + "tqa236" + ], + "files": { + "solution": [ + "roman_numerals.py" + ], + "test": [ + "roman_numerals_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Convert modern Arabic numbers into Roman numerals.", + "source": "The Roman Numeral Kata", + "source_url": "https://codingdojo.org/kata/RomanNumerals/" +} diff --git a/python/roman-numerals/.exercism/metadata.json b/python/roman-numerals/.exercism/metadata.json new file mode 100644 index 00000000..59a72636 --- /dev/null +++ b/python/roman-numerals/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"python","exercise":"roman-numerals","id":"b2e3805eaf16476da723e98d3992cf85","url":"https://exercism.org/tracks/python/exercises/roman-numerals","handle":"vpayno","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/python/roman-numerals/HELP.md b/python/roman-numerals/HELP.md new file mode 100644 index 00000000..59ab8968 --- /dev/null +++ b/python/roman-numerals/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 roman_numerals.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/roman-numerals/README.md b/python/roman-numerals/README.md new file mode 100644 index 00000000..56dffd2d --- /dev/null +++ b/python/roman-numerals/README.md @@ -0,0 +1,99 @@ +# Roman Numerals + +Welcome to Roman Numerals on Exercism's Python Track. +If you need help running the tests or submitting your code, check out `HELP.md`. + +## Introduction + +Today, most people in the world use Arabic numerals (0–9). +But if you travelled back two thousand years, you'd find that most Europeans were using Roman numerals instead. + +To write a Roman numeral we use the following Latin letters, each of which has a value: + +| M | D | C | L | X | V | I | +| ---- | --- | --- | --- | --- | --- | --- | +| 1000 | 500 | 100 | 50 | 10 | 5 | 1 | + +A Roman numeral is a sequence of these letters, and its value is the sum of the letters' values. +For example, `XVIII` has the value 18 (`10 + 5 + 1 + 1 + 1 = 18`). + +There's one rule that makes things trickier though, and that's that **the same letter cannot be used more than three times in succession**. +That means that we can't express numbers such as 4 with the seemingly natural `IIII`. +Instead, for those numbers, we use a subtraction method between two letters. +So we think of `4` not as `1 + 1 + 1 + 1` but instead as `5 - 1`. +And slightly confusingly to our modern thinking, we write the smaller number first. +This applies only in the following cases: 4 (`IV`), 9 (`IX`), 40 (`XL`), 90 (`XC`), 400 (`CD`) and 900 (`CM`). + +Order matters in Roman numerals! +Letters (and the special compounds above) must be ordered by decreasing value from left to right. + +Here are some examples: + +```text + 105 => CV +---- => -- + 100 => C ++ 5 => V +``` + +```text + 106 => CVI +---- => -- + 100 => C ++ 5 => V ++ 1 => I +``` + +```text + 104 => CIV +---- => --- + 100 => C ++ 4 => IV +``` + +And a final more complex example: + +```text + 1996 => MCMXCVI +----- => ------- + 1000 => M ++ 900 => CM ++ 90 => XC ++ 5 => V ++ 1 => I +``` + +## Instructions + +Your task is to convert a number from Arabic numerals to Roman numerals. + +For this exercise, we are only concerned about traditional Roman numerals, in which the largest number is MMMCMXCIX (or 3,999). + +~~~~exercism/note +There are lots of different ways to convert between Arabic and Roman numerals. +We recommend taking a naive approach first to familiarise yourself with the concept of Roman numerals and then search for more efficient methods. + +Make sure to check out our Deep Dive video at the end to explore the different approaches you can take! +~~~~ + +## Source + +### Contributed to by + +- @behrtam +- @BethanyG +- @cmccandless +- @Dog +- @dotrungkien +- @ikhadykin +- @kytrinyx +- @lowks +- @mpatibandla +- @N-Parsons +- @pheanex +- @sjakobi +- @tqa236 + +### Based on + +The Roman Numeral Kata - https://codingdojo.org/kata/RomanNumerals/ \ No newline at end of file diff --git a/python/roman-numerals/roman_numerals.py b/python/roman-numerals/roman_numerals.py new file mode 100644 index 00000000..96f266dc --- /dev/null +++ b/python/roman-numerals/roman_numerals.py @@ -0,0 +1,3 @@ +def roman(number): + pass + diff --git a/python/roman-numerals/roman_numerals_test.py b/python/roman-numerals/roman_numerals_test.py new file mode 100644 index 00000000..d2120f9b --- /dev/null +++ b/python/roman-numerals/roman_numerals_test.py @@ -0,0 +1,89 @@ +# 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-19 + +import unittest + +from roman_numerals import ( + roman, +) + + +class RomanNumeralsTest(unittest.TestCase): + def test_1_is_i(self): + self.assertEqual(roman(1), "I") + + def test_2_is_ii(self): + self.assertEqual(roman(2), "II") + + def test_3_is_iii(self): + self.assertEqual(roman(3), "III") + + def test_4_is_iv(self): + self.assertEqual(roman(4), "IV") + + def test_5_is_v(self): + self.assertEqual(roman(5), "V") + + def test_6_is_vi(self): + self.assertEqual(roman(6), "VI") + + def test_9_is_ix(self): + self.assertEqual(roman(9), "IX") + + def test_16_is_xvi(self): + self.assertEqual(roman(16), "XVI") + + def test_27_is_xxvii(self): + self.assertEqual(roman(27), "XXVII") + + def test_48_is_xlviii(self): + self.assertEqual(roman(48), "XLVIII") + + def test_49_is_xlix(self): + self.assertEqual(roman(49), "XLIX") + + def test_59_is_lix(self): + self.assertEqual(roman(59), "LIX") + + def test_66_is_lxvi(self): + self.assertEqual(roman(66), "LXVI") + + def test_93_is_xciii(self): + self.assertEqual(roman(93), "XCIII") + + def test_141_is_cxli(self): + self.assertEqual(roman(141), "CXLI") + + def test_163_is_clxiii(self): + self.assertEqual(roman(163), "CLXIII") + + def test_166_is_clxvi(self): + self.assertEqual(roman(166), "CLXVI") + + def test_402_is_cdii(self): + self.assertEqual(roman(402), "CDII") + + def test_575_is_dlxxv(self): + self.assertEqual(roman(575), "DLXXV") + + def test_666_is_dclxvi(self): + self.assertEqual(roman(666), "DCLXVI") + + def test_911_is_cmxi(self): + self.assertEqual(roman(911), "CMXI") + + def test_1024_is_mxxiv(self): + self.assertEqual(roman(1024), "MXXIV") + + def test_1666_is_mdclxvi(self): + self.assertEqual(roman(1666), "MDCLXVI") + + def test_3000_is_mmm(self): + self.assertEqual(roman(3000), "MMM") + + def test_3001_is_mmmi(self): + self.assertEqual(roman(3001), "MMMI") + + def test_3999_is_mmmcmxcix(self): + self.assertEqual(roman(3999), "MMMCMXCIX")