From 0334a3b057f5d109f31536b015fb6416405c0111 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sun, 25 Jun 2023 00:40:17 -0700 Subject: [PATCH 1/6] python: create symlinks to them with the orginal python package names --- python/card-games | 1 + python/cater-waiter | 1 + python/chaitanas-colossal-coaster | 1 + python/currency-exchange | 1 + python/ellens-alien-game | 1 + python/for_each | 1 + python/ghost-gobble-arcade-game | 1 + python/guidos-gorgeous-lasagna | 1 + python/inventory-management | 1 + python/little-sisters-essay | 1 + python/little-sisters-vocab | 1 + python/making-the-grade | 1 + python/meltdown-mitigation | 1 + python/tisbury-treasure-hunt | 1 + python/update_readmes | 7 +++---- 15 files changed, 17 insertions(+), 4 deletions(-) create mode 120000 python/card-games create mode 120000 python/cater-waiter create mode 120000 python/chaitanas-colossal-coaster create mode 120000 python/currency-exchange create mode 120000 python/ellens-alien-game create mode 120000 python/ghost-gobble-arcade-game create mode 120000 python/guidos-gorgeous-lasagna create mode 120000 python/inventory-management create mode 120000 python/little-sisters-essay create mode 120000 python/little-sisters-vocab create mode 120000 python/making-the-grade create mode 120000 python/meltdown-mitigation create mode 120000 python/tisbury-treasure-hunt diff --git a/python/card-games b/python/card-games new file mode 120000 index 00000000..2a9f4ebe --- /dev/null +++ b/python/card-games @@ -0,0 +1 @@ +card_games \ No newline at end of file diff --git a/python/cater-waiter b/python/cater-waiter new file mode 120000 index 00000000..a33e228c --- /dev/null +++ b/python/cater-waiter @@ -0,0 +1 @@ +cater_waiter \ No newline at end of file diff --git a/python/chaitanas-colossal-coaster b/python/chaitanas-colossal-coaster new file mode 120000 index 00000000..e038150f --- /dev/null +++ b/python/chaitanas-colossal-coaster @@ -0,0 +1 @@ +chaitanas_colossal_coaster \ No newline at end of file diff --git a/python/currency-exchange b/python/currency-exchange new file mode 120000 index 00000000..90b3f287 --- /dev/null +++ b/python/currency-exchange @@ -0,0 +1 @@ +currency_exchange \ No newline at end of file diff --git a/python/ellens-alien-game b/python/ellens-alien-game new file mode 120000 index 00000000..2280a1e1 --- /dev/null +++ b/python/ellens-alien-game @@ -0,0 +1 @@ +ellens_alien_game \ No newline at end of file diff --git a/python/for_each b/python/for_each index 717b1149..b0c5ca6b 100755 --- a/python/for_each +++ b/python/for_each @@ -5,6 +5,7 @@ declare pkg_name declare d time for d in ./*; do + [[ ${d} =~ .*-.* ]] && continue [[ -d ${d} ]] || continue cd "${d}" || continue printf "[dir: %s]\n\n" "${PWD}" diff --git a/python/ghost-gobble-arcade-game b/python/ghost-gobble-arcade-game new file mode 120000 index 00000000..270db13e --- /dev/null +++ b/python/ghost-gobble-arcade-game @@ -0,0 +1 @@ +ghost_gobble_arcade_game \ No newline at end of file diff --git a/python/guidos-gorgeous-lasagna b/python/guidos-gorgeous-lasagna new file mode 120000 index 00000000..92bd56f9 --- /dev/null +++ b/python/guidos-gorgeous-lasagna @@ -0,0 +1 @@ +guidos_gorgeous_lasagna \ No newline at end of file diff --git a/python/inventory-management b/python/inventory-management new file mode 120000 index 00000000..1e8c773b --- /dev/null +++ b/python/inventory-management @@ -0,0 +1 @@ +inventory_management \ No newline at end of file diff --git a/python/little-sisters-essay b/python/little-sisters-essay new file mode 120000 index 00000000..0324f9c8 --- /dev/null +++ b/python/little-sisters-essay @@ -0,0 +1 @@ +little_sisters_essay \ No newline at end of file diff --git a/python/little-sisters-vocab b/python/little-sisters-vocab new file mode 120000 index 00000000..f2ed02e1 --- /dev/null +++ b/python/little-sisters-vocab @@ -0,0 +1 @@ +little_sisters_vocab \ No newline at end of file diff --git a/python/making-the-grade b/python/making-the-grade new file mode 120000 index 00000000..af9b665e --- /dev/null +++ b/python/making-the-grade @@ -0,0 +1 @@ +making_the_grade \ No newline at end of file diff --git a/python/meltdown-mitigation b/python/meltdown-mitigation new file mode 120000 index 00000000..3ecfc196 --- /dev/null +++ b/python/meltdown-mitigation @@ -0,0 +1 @@ +meltdown_mitigation \ No newline at end of file diff --git a/python/tisbury-treasure-hunt b/python/tisbury-treasure-hunt new file mode 120000 index 00000000..2414a3d7 --- /dev/null +++ b/python/tisbury-treasure-hunt @@ -0,0 +1 @@ +tisbury_treasure_hunt \ No newline at end of file diff --git a/python/update_readmes b/python/update_readmes index ad14bc29..1b4cba80 100755 --- a/python/update_readmes +++ b/python/update_readmes @@ -52,9 +52,8 @@ printf "\n" git add __init__.py .coveragerc printf "\n" -git mv -v "../${project_dir}" "../${project_dir//-/_}" -printf "\n" +cd .. -project_dir="${project_dir//-/_}" -cd "../${project_dir//-/_}" || exit +ln -sv "${project_dir//_/-}" "${project_dir}" +git add "./${project_dir//_/-}" printf "\n" From bc1ff6bc70bf419824140b149c551a5af32834d0 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sun, 25 Jun 2023 00:13:10 -0700 Subject: [PATCH 2/6] python/word-count: download exercise --- python/word-count/.exercism/config.json | 38 +++++++ python/word-count/.exercism/metadata.json | 1 + python/word-count/HELP.md | 129 ++++++++++++++++++++++ python/word-count/HINTS.md | 44 ++++++++ python/word-count/README.md | 91 +++++++++++++++ python/word-count/word_count.py | 2 + python/word-count/word_count_test.py | 127 +++++++++++++++++++++ 7 files changed, 432 insertions(+) create mode 100644 python/word-count/.exercism/config.json create mode 100644 python/word-count/.exercism/metadata.json create mode 100644 python/word-count/HELP.md create mode 100644 python/word-count/HINTS.md create mode 100644 python/word-count/README.md create mode 100644 python/word-count/word_count.py create mode 100644 python/word-count/word_count_test.py diff --git a/python/word-count/.exercism/config.json b/python/word-count/.exercism/config.json new file mode 100644 index 00000000..c7134476 --- /dev/null +++ b/python/word-count/.exercism/config.json @@ -0,0 +1,38 @@ +{ + "authors": [], + "contributors": [ + "behrtam", + "c4llmeco4ch", + "cmccandless", + "Dog", + "gabriel376", + "Grociu", + "guygastineau", + "ikhadykin", + "jackattack24", + "kytrinyx", + "lowks", + "N-Parsons", + "pheanex", + "rivergillis", + "samdec11", + "sjakobi", + "tqa236", + "wobh", + "yawpitch", + "ZacharyRSmith" + ], + "files": { + "solution": [ + "word_count.py" + ], + "test": [ + "word_count_test.py" + ], + "example": [ + ".meta/example.py" + ] + }, + "blurb": "Given a phrase, count the occurrences of each word in that phrase.", + "source": "This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour." +} diff --git a/python/word-count/.exercism/metadata.json b/python/word-count/.exercism/metadata.json new file mode 100644 index 00000000..d7888585 --- /dev/null +++ b/python/word-count/.exercism/metadata.json @@ -0,0 +1 @@ +{"track":"python","exercise":"word-count","id":"5c663edf31b64941a3930befca2c34dc","url":"https://exercism.org/tracks/python/exercises/word-count","handle":"vpayno","is_requester":true,"auto_approve":false} \ No newline at end of file diff --git a/python/word-count/HELP.md b/python/word-count/HELP.md new file mode 100644 index 00000000..9da31680 --- /dev/null +++ b/python/word-count/HELP.md @@ -0,0 +1,129 @@ +# 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 word_count.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) +- [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/word-count/HINTS.md b/python/word-count/HINTS.md new file mode 100644 index 00000000..f48d1b50 --- /dev/null +++ b/python/word-count/HINTS.md @@ -0,0 +1,44 @@ +# Hints + +## General + +This exercise has many potential solutions and many paths you can take along the way. +No path is manifestly "better" than another, although a particular path may be more interesting or better suited to what you want to learn or explore right now. +Some paths may trade speed for clarity, others might take up more memory but be more scalable or maintainable. +We encourage you to try out more than one strategy to see what happens. + +_______ +- Python has a robust set of tools to work with strings. [`str.split`][str.split] [`str.replace`][str.replace] [`str.lower`][str.lower] and [`str.strip`][str.strip] can be particularly helpful with this challenge. +- String methods can be chained together (_as long as the method returns a `str`_)) +- While `str.split()` is very _specific_, `str.strip()` behaves differently, and allows multiple combinations. +- The [`string`][string] module (as opposed to `str`) has some constants that can be useful for filtering and comparison when processing strings. +________ + +- [Dictionaries][dict] can be helpful for tabulating when items (keys) appear more than once in a string. +- [`dict.setdefault()`][dict.setdefault] can help in processing when a key might be missing from a dictionary. +- The [Collections][collections] module implements some really useful subtypes to the core `dict` (dictionary), purpose-built to do things like [tally][collections.counter]. +________ +- Exploring the [`re`][re] module and regular expressions can be fun, but is by no means necessary to solve this challenge. +- [Regex101][regex101] is very helpful for experimenting with regular expression logic. +- Both [`re.sub`][re.sub] and [`re.findall`][re.findall] can be interesting strategies to employ. +________ +- [Comprehensions][comprehensions] can often "flatten" loops where items are being appended to a list or inserted into a dictionary. +- [Generator expressions][generator expressions] can often "stand in" for a list comprehension when an iterable is needed. + Generator expressions are evaluated in a "lazy" fashion, and take up less space in memory than a corresponding list comprehension. + + +[collections.counter]: https://docs.python.org/3/library/collections.html#collections.Counter +[collections]: https://docs.python.org/3/library/collections.html#module-collections +[comprehensions]: https://treyhunner.com/2015/12/python-list-comprehensions-now-in-color/ +[dict.setdefault]: https://docs.python.org/3/library/stdtypes.html#dict.setdefault +[dict]: https://docs.python.org/3/library/stdtypes.html#mapping-types-dict +[generator expressions]: https://dbader.org/blog/python-generator-expressions +[re.findall]: https://docs.python.org/3/library/re.html?highlight=re#re.findall +[re.sub]: https://docs.python.org/3/library/re.html?highlight=re#re.sub +[re]: https://docs.python.org/3/library/re.html?highlight=re#module-re +[regex101]: https://regex101.com/ +[str.lower]: https://docs.python.org/3/library/stdtypes.html#str.lower +[str.replace]: https://docs.python.org/3/library/stdtypes.html#str.replace +[str.split]: https://docs.python.org/3/library/stdtypes.html#str.split +[str.strip]: https://docs.python.org/3/library/stdtypes.html#str.strip +[string]: https://docs.python.org/3/library/string.html \ No newline at end of file diff --git a/python/word-count/README.md b/python/word-count/README.md new file mode 100644 index 00000000..a26db7e9 --- /dev/null +++ b/python/word-count/README.md @@ -0,0 +1,91 @@ +# Word Count + +Welcome to Word Count on Exercism's Python Track. +If you need help running the tests or submitting your code, check out `HELP.md`. +If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :) + +## 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. + +## Instructions + +Your task is to count how many times each word occurs in a subtitle of a drama. + +The subtitles from these dramas use only ASCII characters. + +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. + +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. + +Numbers are considered words. +If the subtitles say _It costs 100 dollars._ then _100_ will be its own word. + +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 +123: 1 +agent: 1 +cried: 1 +fled: 1 +i: 1 +password: 2 +so: 1 +special: 1 +that's: 1 +the: 2 +``` + +## Source + +### Contributed to by + +- @behrtam +- @c4llmeco4ch +- @cmccandless +- @Dog +- @gabriel376 +- @Grociu +- @guygastineau +- @ikhadykin +- @jackattack24 +- @kytrinyx +- @lowks +- @N-Parsons +- @pheanex +- @rivergillis +- @samdec11 +- @sjakobi +- @tqa236 +- @wobh +- @yawpitch +- @ZacharyRSmith + +### Based on + +This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour. \ No newline at end of file diff --git a/python/word-count/word_count.py b/python/word-count/word_count.py new file mode 100644 index 00000000..02564a17 --- /dev/null +++ b/python/word-count/word_count.py @@ -0,0 +1,2 @@ +def count_words(sentence): + pass diff --git a/python/word-count/word_count_test.py b/python/word-count/word_count_test.py new file mode 100644 index 00000000..b63a9eb3 --- /dev/null +++ b/python/word-count/word_count_test.py @@ -0,0 +1,127 @@ +import unittest + +from word_count import ( + count_words, +) + +# Tests adapted from `problem-specifications//canonical-data.json` + + +class WordCountTest(unittest.TestCase): + def test_count_one_word(self): + self.assertEqual(count_words("word"), {"word": 1}) + + def test_count_one_of_each_word(self): + self.assertEqual(count_words("one of each"), {"one": 1, "of": 1, "each": 1}) + + def test_multiple_occurrences_of_a_word(self): + self.assertEqual( + count_words("one fish two fish red fish blue fish"), + {"one": 1, "fish": 4, "two": 1, "red": 1, "blue": 1}, + ) + + def test_handles_cramped_lists(self): + self.assertEqual(count_words("one,two,three"), {"one": 1, "two": 1, "three": 1}) + + def test_handles_expanded_lists(self): + self.assertEqual( + count_words("one,\ntwo,\nthree"), {"one": 1, "two": 1, "three": 1} + ) + + def test_ignore_punctuation(self): + self.assertEqual( + count_words("car: carpet as java: javascript!!&@$%^&"), + {"car": 1, "carpet": 1, "as": 1, "java": 1, "javascript": 1}, + ) + + def test_include_numbers(self): + self.assertEqual( + count_words("testing, 1, 2 testing"), {"testing": 2, "1": 1, "2": 1} + ) + + def test_normalize_case(self): + self.assertEqual(count_words("go Go GO Stop stop"), {"go": 3, "stop": 2}) + + def test_with_apostrophes(self): + self.assertEqual( + count_words("'First: don't laugh. Then: don't cry. You're getting it.'"), + { + "first": 1, + "don't": 2, + "laugh": 1, + "then": 1, + "cry": 1, + "you're": 1, + "getting": 1, + "it": 1, + }, + ) + + def test_with_quotations(self): + self.assertEqual( + count_words("Joe can't tell between 'large' and large."), + {"joe": 1, "can't": 1, "tell": 1, "between": 1, "large": 2, "and": 1}, + ) + + def test_substrings_from_the_beginning(self): + self.assertEqual( + count_words("Joe can't tell between app, apple and a."), + { + "joe": 1, + "can't": 1, + "tell": 1, + "between": 1, + "app": 1, + "apple": 1, + "and": 1, + "a": 1, + }, + ) + + def test_multiple_spaces_not_detected_as_a_word(self): + self.assertEqual( + count_words(" multiple whitespaces"), {"multiple": 1, "whitespaces": 1} + ) + + def test_alternating_word_separators_not_detected_as_a_word(self): + self.assertEqual( + count_words(",\n,one,\n ,two \n 'three'"), {"one": 1, "two": 1, "three": 1} + ) + + def test_quotation_for_word_with_apostrophe(self): + self.assertEqual(count_words("can, can't, 'can't'"), {"can": 1, "can't": 2}) + + # Additional tests for this track + + def test_tabs(self): + self.assertEqual( + count_words( + "rah rah ah ah ah roma roma ma ga ga oh la la want your bad romance" + ), + { + "rah": 2, + "ah": 3, + "roma": 2, + "ma": 1, + "ga": 2, + "oh": 1, + "la": 2, + "want": 1, + "your": 1, + "bad": 1, + "romance": 1, + }, + ) + + def test_non_alphanumeric(self): + self.assertEqual( + count_words("hey,my_spacebar_is_broken"), + {"hey": 1, "my": 1, "spacebar": 1, "is": 1, "broken": 1}, + ) + + def test_multiple_apostrophes_ignored(self): + self.assertEqual(count_words("''hey''"), {"hey": 1}) + + +if __name__ == "__main__": + unittest.main() From 389ffb22da8345b1868521da1b594dd934d685b0 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sun, 25 Jun 2023 00:32:02 -0700 Subject: [PATCH 3/6] python/word-count: 1st iteration --- python/README.md | 1 + python/word-count | 1 + python/word_count/.coverage | Bin 0 -> 53248 bytes python/word_count/.coverage.xml | 21 ++ python/word_count/.coveragerc | 2 + .../.exercism/config.json | 0 .../.exercism/metadata.json | 0 python/{word-count => word_count}/HELP.md | 0 python/{word-count => word_count}/HINTS.md | 0 python/{word-count => word_count}/README.md | 7 +- python/word_count/__init__.py | 0 python/word_count/run-tests-python.txt | 191 ++++++++++++++++++ .../{word-count => word_count}/word_count.py | 0 python/word_count/word_count.py,cover | 2 + .../word_count_test.py | 0 15 files changed, 224 insertions(+), 1 deletion(-) create mode 120000 python/word-count create mode 100644 python/word_count/.coverage create mode 100644 python/word_count/.coverage.xml create mode 100644 python/word_count/.coveragerc rename python/{word-count => word_count}/.exercism/config.json (100%) rename python/{word-count => word_count}/.exercism/metadata.json (100%) rename python/{word-count => word_count}/HELP.md (100%) rename python/{word-count => word_count}/HINTS.md (100%) rename python/{word-count => word_count}/README.md (95%) create mode 100644 python/word_count/__init__.py create mode 100644 python/word_count/run-tests-python.txt rename python/{word-count => word_count}/word_count.py (100%) create mode 100644 python/word_count/word_count.py,cover rename python/{word-count => word_count}/word_count_test.py (100%) diff --git a/python/README.md b/python/README.md index c1aa28db..2bb809df 100644 --- a/python/README.md +++ b/python/README.md @@ -30,3 +30,4 @@ - [cater-waiter](./cater-waiter/README.md) - [locomotive-engineer](./locomotive-engineer/README.md) - [ellens-alien-game](./ellens-alien-game/README.md) +- [word-count](./word-count/README.md) diff --git a/python/word-count b/python/word-count new file mode 120000 index 00000000..dd2d387f --- /dev/null +++ b/python/word-count @@ -0,0 +1 @@ +word_count \ No newline at end of file diff --git a/python/word_count/.coverage b/python/word_count/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..3f40bdaddcadc2ca04eb0f708539982576a6a3ac GIT binary patch literal 53248 zcmeI)O>Y`U7zglO<->t zY;&k8l1i2;_0W6O&yakSev+Je%B9b&VFUyCUkTH1#l4ZC>c;7%g?2 z@F335drh}Zxgyo2A_jr$$zUX&s8KCWkX$WN=aD%;g($b{a|*GSWUq=qbyT2yM}?*q zdv3d0s6P9(kSlL)+7~KrlMEbstk1QE4osVJw?hRvI%sq4TY>bQo(gM1PFm<_s^@uR zS{rDu9%<2c{kWNa=ti#gg*sQxFjDPn8(3qsbR)dk)=*iGxj~Oj&g5D%I@8S89KNmEU!wW)(&o7P}9wqZZ!lS6)7rGM<8O|+C=TJ1y zj+uIjAp;(0LMI8Srf)UcxUy6S(dz5ge5}P06Dk@YG#8}FIz!*#p%QW%9DS++*;NP0 zSu-uX?LeZ?Y2>rzquoWJGYNraW3pQqZ)bDmogMpWJ`SU#w~{}(xe!Ww@|tNhJ>@AG z4ufTk+4AAeqUI#&nvG;Bp2;RK<0~z(i)w=Uxs(9r_w*2|lqKb1Bnhk! z>M(R^S>4qY%!_`&ki)k6*h|B1nR^mFP ziwjTl$292D@kKkHC;fJ^Uhy()N~O7<2Pa?0Od^y~RA^9!G(<0znHHLy0gT;*dPD_ z2tWV=5P$##AOHafKmY;|SSEo&W+$KgBY?U8|J*7)U#144Ef9bJ1Rwwb2tWV=5P$## zAOL}PTi}7cYK?Ezd)ia=(}5iMy54o8X0l5^=@K|@=) zI(q0wGrRPA3FiL)3#;_v-F89kApijgKmY;|fB*y_009U<00K)T@L+X(EC2s}|L6Pv z^rQdSAOHafKmY;|fB*y_009U<00IzLVgbJYkMI9W+`(uX1Rwwb2tWV=5P$##AOHaf zK!5~r{~uuh0SG_<0uX=z1Rwwb2tWV=5LkWz-2Y$xK1K^6009U<00Izz00bZa0SG_< z0=WN=7=Qo-AOHafKmY;|fB*y_009UrzX0z4FMl7Sg%E%M1Rwwb2tWV=5P$##AOHcr m|8JLGS@ggL0SG_<0uX=z1Rwwb2tWV=5P-n)31sYyRs0Xc3|12W literal 0 HcmV?d00001 diff --git a/python/word_count/.coverage.xml b/python/word_count/.coverage.xml new file mode 100644 index 00000000..d199e265 --- /dev/null +++ b/python/word_count/.coverage.xml @@ -0,0 +1,21 @@ + + + + + + /home/vpayno/git_vpayno/exercism-workspace/python/word_count + + + + + + + + + + + + + + + diff --git a/python/word_count/.coveragerc b/python/word_count/.coveragerc new file mode 100644 index 00000000..883531db --- /dev/null +++ b/python/word_count/.coveragerc @@ -0,0 +1,2 @@ +[run] +omit = __init__.py, *_test.py diff --git a/python/word-count/.exercism/config.json b/python/word_count/.exercism/config.json similarity index 100% rename from python/word-count/.exercism/config.json rename to python/word_count/.exercism/config.json diff --git a/python/word-count/.exercism/metadata.json b/python/word_count/.exercism/metadata.json similarity index 100% rename from python/word-count/.exercism/metadata.json rename to python/word_count/.exercism/metadata.json diff --git a/python/word-count/HELP.md b/python/word_count/HELP.md similarity index 100% rename from python/word-count/HELP.md rename to python/word_count/HELP.md diff --git a/python/word-count/HINTS.md b/python/word_count/HINTS.md similarity index 100% rename from python/word-count/HINTS.md rename to python/word_count/HINTS.md diff --git a/python/word-count/README.md b/python/word_count/README.md similarity index 95% rename from python/word-count/README.md rename to python/word_count/README.md index a26db7e9..303622d9 100644 --- a/python/word-count/README.md +++ b/python/word_count/README.md @@ -88,4 +88,9 @@ the: 2 ### Based on -This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour. \ No newline at end of file +This is a classic toy problem, but we were reminded of it by seeing it in the Go Tour. + +### My Solution + +- [my solution](./word_count.py) +- [run-tests](./run-tests-python.txt) diff --git a/python/word_count/__init__.py b/python/word_count/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/word_count/run-tests-python.txt b/python/word_count/run-tests-python.txt new file mode 100644 index 00000000..74364362 --- /dev/null +++ b/python/word_count/run-tests-python.txt @@ -0,0 +1,191 @@ +Running automated test file(s): + + +=============================================================================== + +Running: pylint --ignore-patterns (__init__|.*_test).py . + +real 0m0.438s +user 0m0.352s +sys 0m0.088s + +=============================================================================== + +Running: ruff check --ignore E501 ./__init__.py ./word_count.py ./word_count_test.py + +real 0m0.082s +user 0m0.036s +sys 0m0.049s + +=============================================================================== + +Running: pyright --stats . +Found 3 source files +pyright 1.1.315 +0 errors, 0 warnings, 0 informations +Completed in 0.635sec + +Analysis stats +Total files parsed and bound: 32 +Total files checked: 3 + +Timing stats +Find Source Files: 0sec +Read Source Files: 0sec +Tokenize: 0.04sec +Parse: 0.06sec +Resolve Imports: 0.04sec +Bind: 0.08sec +Check: 0.08sec +Detect Cycles: 0sec + +real 0m1.608s +user 0m1.430s +sys 0m0.161s + +=============================================================================== + +Running: bandit --verbose --recursive . +[main] INFO profile include tests: None +[main] INFO profile exclude tests: None +[main] INFO cli include tests: None +[main] INFO cli exclude tests: None +[main] INFO running on Python 3.11.3 +Run started:2023-06-25 07:43:58.115760 +Files in scope (3): + ./__init__.py (score: {SEVERITY: 0, CONFIDENCE: 0}) + ./word_count.py (score: {SEVERITY: 0, CONFIDENCE: 0}) + ./word_count_test.py (score: {SEVERITY: 0, CONFIDENCE: 0}) +Files excluded (16): + ./.coverage + ./.coverage.xml + ./.coveragerc + ./.exercism/config.json + ./.exercism/metadata.json + ./.mypy_cache/.gitignore + ./.mypy_cache/3.11/@plugins_snapshot.json + ./.mypy_cache/CACHEDIR.TAG + ./HELP.md + ./HINTS.md + ./README.md + ./__pycache__/__init__.cpython-311.pyc + ./__pycache__/word_count.cpython-311.pyc + ./__pycache__/word_count_test.cpython-311-pytest-7.3.1.pyc + ./run-tests-python.txt + ./word_count.py,cover + +Test results: + No issues identified. + +Code scanned: + Total lines of code: 104 + Total lines skipped (#nosec): 0 + Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0 + +Run metrics: + Total issues (by severity): + Undefined: 0 + Low: 0 + Medium: 0 + High: 0 + Total issues (by confidence): + Undefined: 0 + Low: 0 + Medium: 0 + High: 0 +Files skipped (0): + +real 0m0.230s +user 0m0.181s +sys 0m0.050s + +=============================================================================== + +Running: refurb . + +real 0m1.301s +user 0m1.233s +sys 0m0.069s + +=============================================================================== + +==> .coveragerc <== +[run] +omit = __init__.py, *_test.py + +Running: pytest --verbose --cov=. --cov-branch --cov-report=term-missing --cov-report=xml:.coverage.xml -p no:randomly +============================= test session starts ============================== +platform linux -- Python 3.11.3, pytest-7.3.1, pluggy-1.0.0 -- /home/vpayno/.pyenv/versions/3.11.3/bin/python +cachedir: .pytest_cache +rootdir: /home/vpayno/git_vpayno/exercism-workspace/python +configfile: pytest.ini +plugins: anyio-3.6.2, libtmux-0.21.1, pylama-8.4.1, cov-4.0.0, datafiles-3.0.0, docker-1.0.1, subprocess-1.5.0, typeguard-2.13.3 +collecting ... /home/vpayno/.pyenv/versions/3.11.3/lib/python3.11/site-packages/coverage/control.py:858: CoverageWarning: No data was collected. (no-data-collected) + self._warn("No data was collected.", slug="no-data-collected") +collected 0 items / 1 error + +==================================== ERRORS ==================================== +________________ ERROR collecting word_count/word_count_test.py ________________ +ImportError while importing test module '/home/vpayno/git_vpayno/exercism-workspace/python/word_count/word_count_test.py'. +Hint: make sure your test modules/packages have valid Python names. +Traceback: +../../../../.pyenv/versions/3.11.3/lib/python3.11/importlib/__init__.py:126: in import_module + return _bootstrap._gcd_import(name[level:], package, level) +word_count_test.py:3: in + from word_count import ( +E ImportError: cannot import name 'count_words' from 'word_count' (/home/vpayno/git_vpayno/exercism-workspace/python/word_count/__init__.py) + +---------- coverage: platform linux, python 3.11.3-final-0 ----------- +Name Stmts Miss Cover Missing +--------------------------------------------- +word_count.py 2 2 0% 1-2 +--------------------------------------------- +TOTAL 2 2 0% +Coverage XML written to file .coverage.xml + +=========================== short test summary info ============================ +ERROR word_count_test.py +!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!! +=============================== 1 error in 0.07s =============================== + +real 0m0.954s +user 0m0.822s +sys 0m0.121s + +=============================================================================== + +Running: coverage report --show-missing +Name Stmts Miss Cover Missing +--------------------------------------------- +word_count.py 2 2 0% 1-2 +--------------------------------------------- +TOTAL 2 2 0% + +real 0m0.135s +user 0m0.088s +sys 0m0.047s + +=============================================================================== + +coverage annotate +The annotate command will be removed in a future version. +Get in touch if you still use it: ned@nedbatchelder.com + +real 0m0.142s +user 0m0.097s +sys 0m0.046s + +tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' +! def count_words(sentence): +! pass + +=============================================================================== + +Running: misspell ./__init__.py ./word_count.py ./word_count_test.py + +real 0m0.021s +user 0m0.017s +sys 0m0.015s + +=============================================================================== + diff --git a/python/word-count/word_count.py b/python/word_count/word_count.py similarity index 100% rename from python/word-count/word_count.py rename to python/word_count/word_count.py diff --git a/python/word_count/word_count.py,cover b/python/word_count/word_count.py,cover new file mode 100644 index 00000000..2730be6f --- /dev/null +++ b/python/word_count/word_count.py,cover @@ -0,0 +1,2 @@ +! def count_words(sentence): +! pass diff --git a/python/word-count/word_count_test.py b/python/word_count/word_count_test.py similarity index 100% rename from python/word-count/word_count_test.py rename to python/word_count/word_count_test.py From b5e71c1347a736001fe85bed814e8040418a6fef Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sun, 25 Jun 2023 23:35:07 -0700 Subject: [PATCH 4/6] python/word-count: 1st iteration --- python/word-count | 2 +- python/word_count/.coverage.xml | 21 --- python/word_count/word_count.py | 2 - python/word_count/word_count.py,cover | 2 - python/{word_count => wordcount}/.coverage | Bin 53248 -> 53247 bytes python/wordcount/.coverage.xml | 33 +++++ python/{word_count => wordcount}/.coveragerc | 0 .../.exercism/config.json | 0 .../.exercism/metadata.json | 0 python/{word_count => wordcount}/HELP.md | 0 python/{word_count => wordcount}/HINTS.md | 0 python/{word_count => wordcount}/README.md | 0 python/{word_count => wordcount}/__init__.py | 0 .../run-tests-python.txt | 138 +++++++++--------- python/wordcount/word_count.py | 37 +++++ python/wordcount/word_count.py,cover | 37 +++++ .../word_count_test.py | 2 +- 17 files changed, 180 insertions(+), 94 deletions(-) delete mode 100644 python/word_count/.coverage.xml delete mode 100644 python/word_count/word_count.py delete mode 100644 python/word_count/word_count.py,cover rename python/{word_count => wordcount}/.coverage (97%) create mode 100644 python/wordcount/.coverage.xml rename python/{word_count => wordcount}/.coveragerc (100%) rename python/{word_count => wordcount}/.exercism/config.json (100%) rename python/{word_count => wordcount}/.exercism/metadata.json (100%) rename python/{word_count => wordcount}/HELP.md (100%) rename python/{word_count => wordcount}/HINTS.md (100%) rename python/{word_count => wordcount}/README.md (100%) rename python/{word_count => wordcount}/__init__.py (100%) rename python/{word_count => wordcount}/run-tests-python.txt (55%) create mode 100644 python/wordcount/word_count.py create mode 100644 python/wordcount/word_count.py,cover rename python/{word_count => wordcount}/word_count_test.py (97%) diff --git a/python/word-count b/python/word-count index dd2d387f..265bebac 120000 --- a/python/word-count +++ b/python/word-count @@ -1 +1 @@ -word_count \ No newline at end of file +wordcount \ No newline at end of file diff --git a/python/word_count/.coverage.xml b/python/word_count/.coverage.xml deleted file mode 100644 index d199e265..00000000 --- a/python/word_count/.coverage.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - /home/vpayno/git_vpayno/exercism-workspace/python/word_count - - - - - - - - - - - - - - - diff --git a/python/word_count/word_count.py b/python/word_count/word_count.py deleted file mode 100644 index 02564a17..00000000 --- a/python/word_count/word_count.py +++ /dev/null @@ -1,2 +0,0 @@ -def count_words(sentence): - pass diff --git a/python/word_count/word_count.py,cover b/python/word_count/word_count.py,cover deleted file mode 100644 index 2730be6f..00000000 --- a/python/word_count/word_count.py,cover +++ /dev/null @@ -1,2 +0,0 @@ -! def count_words(sentence): -! pass diff --git a/python/word_count/.coverage b/python/wordcount/.coverage similarity index 97% rename from python/word_count/.coverage rename to python/wordcount/.coverage index 3f40bdaddcadc2ca04eb0f708539982576a6a3ac..71047eb42ec0987915e17f862834cc4ca354384f 100644 GIT binary patch delta 644 zcmXxgF=!M)6b9hgo!Namdw2WaChHD+vS#79E+95GsbiO%oml0 zV57D1Y4`T{cQ+FghKas+3~x(}*5snTqe^l14`Ij{b8y9QRmQz3NFOj}0Q zX840&_j!RNpAt_>$LY*y)u63t#h_?YY>*e! zG{|y-K}%7zsI;hIkannUpfaj0kW#p4DUt?BN`XO~5E(=<^?jpRM4mxVkudNA;s(O= zT@C37-xbwJVPIka35W4VnYY5VPE?5oH}S? z)mE!kMSI06FJh}KZ(6k!mbF%7m3A6dDyuJ*)|OorS|zEpx)UdXrH*Yii+rn~@~pf- VSP72@dTG72aB051l-1j_=6`bLWr6?z delta 121 zcmexApSfWH^9B|LHb(yU4E*mm3kp2tpZs256v+R|!2fl#V8d&EQ7&d_&a%{^;>`R! zUIqpRM*a;9{2PEum+`atF|sf;Do)<+Z^jru`K`a?W;Tb_{H%T~jf$Kw!Fch-%nb@K MyqP88H$NjU03Y}z#Q*>R diff --git a/python/wordcount/.coverage.xml b/python/wordcount/.coverage.xml new file mode 100644 index 00000000..ae6dcd80 --- /dev/null +++ b/python/wordcount/.coverage.xml @@ -0,0 +1,33 @@ + + + + + + /home/vpayno/git_vpayno/exercism-workspace/python/wordcount + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/word_count/.coveragerc b/python/wordcount/.coveragerc similarity index 100% rename from python/word_count/.coveragerc rename to python/wordcount/.coveragerc diff --git a/python/word_count/.exercism/config.json b/python/wordcount/.exercism/config.json similarity index 100% rename from python/word_count/.exercism/config.json rename to python/wordcount/.exercism/config.json diff --git a/python/word_count/.exercism/metadata.json b/python/wordcount/.exercism/metadata.json similarity index 100% rename from python/word_count/.exercism/metadata.json rename to python/wordcount/.exercism/metadata.json diff --git a/python/word_count/HELP.md b/python/wordcount/HELP.md similarity index 100% rename from python/word_count/HELP.md rename to python/wordcount/HELP.md diff --git a/python/word_count/HINTS.md b/python/wordcount/HINTS.md similarity index 100% rename from python/word_count/HINTS.md rename to python/wordcount/HINTS.md diff --git a/python/word_count/README.md b/python/wordcount/README.md similarity index 100% rename from python/word_count/README.md rename to python/wordcount/README.md diff --git a/python/word_count/__init__.py b/python/wordcount/__init__.py similarity index 100% rename from python/word_count/__init__.py rename to python/wordcount/__init__.py diff --git a/python/word_count/run-tests-python.txt b/python/wordcount/run-tests-python.txt similarity index 55% rename from python/word_count/run-tests-python.txt rename to python/wordcount/run-tests-python.txt index 74364362..4ed42e53 100644 --- a/python/word_count/run-tests-python.txt +++ b/python/wordcount/run-tests-python.txt @@ -5,17 +5,17 @@ Running automated test file(s): Running: pylint --ignore-patterns (__init__|.*_test).py . -real 0m0.438s -user 0m0.352s -sys 0m0.088s +real 0m0.447s +user 0m0.373s +sys 0m0.071s =============================================================================== Running: ruff check --ignore E501 ./__init__.py ./word_count.py ./word_count_test.py -real 0m0.082s -user 0m0.036s -sys 0m0.049s +real 0m0.065s +user 0m0.026s +sys 0m0.040s =============================================================================== @@ -23,25 +23,25 @@ Running: pyright --stats . Found 3 source files pyright 1.1.315 0 errors, 0 warnings, 0 informations -Completed in 0.635sec +Completed in 0.73sec Analysis stats -Total files parsed and bound: 32 +Total files parsed and bound: 35 Total files checked: 3 Timing stats Find Source Files: 0sec -Read Source Files: 0sec -Tokenize: 0.04sec -Parse: 0.06sec -Resolve Imports: 0.04sec -Bind: 0.08sec -Check: 0.08sec +Read Source Files: 0.01sec +Tokenize: 0.05sec +Parse: 0.07sec +Resolve Imports: 0.06sec +Bind: 0.09sec +Check: 0.11sec Detect Cycles: 0sec -real 0m1.608s -user 0m1.430s -sys 0m0.161s +real 0m1.560s +user 0m1.559s +sys 0m0.149s =============================================================================== @@ -51,7 +51,7 @@ Running: bandit --verbose --recursive . [main] INFO cli include tests: None [main] INFO cli exclude tests: None [main] INFO running on Python 3.11.3 -Run started:2023-06-25 07:43:58.115760 +Run started:2023-06-26 06:33:57.719077 Files in scope (3): ./__init__.py (score: {SEVERITY: 0, CONFIDENCE: 0}) ./word_count.py (score: {SEVERITY: 0, CONFIDENCE: 0}) @@ -78,7 +78,7 @@ Test results: No issues identified. Code scanned: - Total lines of code: 104 + Total lines of code: 121 Total lines skipped (#nosec): 0 Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0 @@ -95,17 +95,17 @@ Run metrics: High: 0 Files skipped (0): -real 0m0.230s -user 0m0.181s -sys 0m0.050s +real 0m0.212s +user 0m0.160s +sys 0m0.053s =============================================================================== Running: refurb . -real 0m1.301s -user 0m1.233s -sys 0m0.069s +real 0m1.323s +user 0m1.248s +sys 0m0.076s =============================================================================== @@ -120,50 +120,53 @@ cachedir: .pytest_cache rootdir: /home/vpayno/git_vpayno/exercism-workspace/python configfile: pytest.ini plugins: anyio-3.6.2, libtmux-0.21.1, pylama-8.4.1, cov-4.0.0, datafiles-3.0.0, docker-1.0.1, subprocess-1.5.0, typeguard-2.13.3 -collecting ... /home/vpayno/.pyenv/versions/3.11.3/lib/python3.11/site-packages/coverage/control.py:858: CoverageWarning: No data was collected. (no-data-collected) - self._warn("No data was collected.", slug="no-data-collected") -collected 0 items / 1 error - -==================================== ERRORS ==================================== -________________ ERROR collecting word_count/word_count_test.py ________________ -ImportError while importing test module '/home/vpayno/git_vpayno/exercism-workspace/python/word_count/word_count_test.py'. -Hint: make sure your test modules/packages have valid Python names. -Traceback: -../../../../.pyenv/versions/3.11.3/lib/python3.11/importlib/__init__.py:126: in import_module - return _bootstrap._gcd_import(name[level:], package, level) -word_count_test.py:3: in - from word_count import ( -E ImportError: cannot import name 'count_words' from 'word_count' (/home/vpayno/git_vpayno/exercism-workspace/python/word_count/__init__.py) +collecting ... collected 17 items + +word_count_test.py::WordCountTest::test_alternating_word_separators_not_detected_as_a_word PASSED [ 5%] +word_count_test.py::WordCountTest::test_count_one_of_each_word PASSED [ 11%] +word_count_test.py::WordCountTest::test_count_one_word PASSED [ 17%] +word_count_test.py::WordCountTest::test_handles_cramped_lists PASSED [ 23%] +word_count_test.py::WordCountTest::test_handles_expanded_lists PASSED [ 29%] +word_count_test.py::WordCountTest::test_ignore_punctuation PASSED [ 35%] +word_count_test.py::WordCountTest::test_include_numbers PASSED [ 41%] +word_count_test.py::WordCountTest::test_multiple_apostrophes_ignored PASSED [ 47%] +word_count_test.py::WordCountTest::test_multiple_occurrences_of_a_word PASSED [ 52%] +word_count_test.py::WordCountTest::test_multiple_spaces_not_detected_as_a_word PASSED [ 58%] +word_count_test.py::WordCountTest::test_non_alphanumeric PASSED [ 64%] +word_count_test.py::WordCountTest::test_normalize_case PASSED [ 70%] +word_count_test.py::WordCountTest::test_quotation_for_word_with_apostrophe PASSED [ 76%] +word_count_test.py::WordCountTest::test_substrings_from_the_beginning PASSED [ 82%] +word_count_test.py::WordCountTest::test_tabs PASSED [ 88%] +word_count_test.py::WordCountTest::test_with_apostrophes PASSED [ 94%] +word_count_test.py::WordCountTest::test_with_quotations PASSED [100%] ---------- coverage: platform linux, python 3.11.3-final-0 ----------- -Name Stmts Miss Cover Missing ---------------------------------------------- -word_count.py 2 2 0% 1-2 ---------------------------------------------- -TOTAL 2 2 0% +Name Stmts Miss Branch BrPart Cover Missing +----------------------------------------------------------- +word_count.py 14 0 6 0 100% +----------------------------------------------------------- +TOTAL 14 0 6 0 100% Coverage XML written to file .coverage.xml -=========================== short test summary info ============================ -ERROR word_count_test.py -!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!! -=============================== 1 error in 0.07s =============================== -real 0m0.954s -user 0m0.822s -sys 0m0.121s +============================== 17 passed in 0.05s ============================== + +real 0m0.936s +user 0m0.809s +sys 0m0.128s =============================================================================== Running: coverage report --show-missing -Name Stmts Miss Cover Missing ---------------------------------------------- -word_count.py 2 2 0% 1-2 ---------------------------------------------- -TOTAL 2 2 0% - -real 0m0.135s -user 0m0.088s -sys 0m0.047s +Name Stmts Miss Branch BrPart Cover Missing +----------------------------------------------------------- +word_count.py 14 0 6 0 100% +----------------------------------------------------------- +TOTAL 14 0 6 0 100% + +real 0m0.138s +user 0m0.089s +sys 0m0.049s =============================================================================== @@ -171,21 +174,22 @@ coverage annotate The annotate command will be removed in a future version. Get in touch if you still use it: ned@nedbatchelder.com -real 0m0.142s -user 0m0.097s -sys 0m0.046s +real 0m0.136s +user 0m0.094s +sys 0m0.043s tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' -! def count_words(sentence): -! pass + +> def count_words(sentence: str) -> Dict[str, int]: +> """Counts the number of times each word in a string is used. =============================================================================== Running: misspell ./__init__.py ./word_count.py ./word_count_test.py real 0m0.021s -user 0m0.017s -sys 0m0.015s +user 0m0.021s +sys 0m0.009s =============================================================================== diff --git a/python/wordcount/word_count.py b/python/wordcount/word_count.py new file mode 100644 index 00000000..7f93827b --- /dev/null +++ b/python/wordcount/word_count.py @@ -0,0 +1,37 @@ +"""Word Count Python Exercism""" + + +import re +from typing import Dict + + +def count_words(sentence: str) -> Dict[str, int]: + """Counts the number of times each word in a string is used. + + :param sentence: str - string we're going to count + :return: Dict[str, int] - current round and the two that follow. + """ + counts: Dict[str, int] = {} + + # remove surrounding quotes + sentence = sentence.strip("'") + + # replace punctuation and funny characters with spaces + sentence = re.sub(r"[,.;:_!&@$%^&]", " ", sentence) + + for line in sentence.splitlines(): + for word in line.split(" "): + # skip empty words + if not word: + continue + + # lower case the dict key + word = word.lower() + + # remove surrounding quotes + word = word.strip("'") + + # increment the word count in the dictionary + counts[word] = 1 + counts.setdefault(word, 0) + + return counts diff --git a/python/wordcount/word_count.py,cover b/python/wordcount/word_count.py,cover new file mode 100644 index 00000000..cde399b7 --- /dev/null +++ b/python/wordcount/word_count.py,cover @@ -0,0 +1,37 @@ +> """Word Count Python Exercism""" + + +> import re +> from typing import Dict + + +> def count_words(sentence: str) -> Dict[str, int]: +> """Counts the number of times each word in a string is used. + +> :param sentence: str - string we're going to count +> :return: Dict[str, int] - current round and the two that follow. +> """ +> counts: Dict[str, int] = {} + + # remove surrounding quotes +> sentence = sentence.strip("'") + + # replace punctuation and funny characters with spaces +> sentence = re.sub(r"[,.;:_!&@$%^&]", " ", sentence) + +> for line in sentence.splitlines(): +> for word in line.split(" "): + # skip empty words +> if not word: +> continue + + # lower case the dict key +> word = word.lower() + + # remove surrounding quotes +> word = word.strip("'") + + # increment the word count in the dictionary +> counts[word] = 1 + counts.setdefault(word, 0) + +> return counts diff --git a/python/word_count/word_count_test.py b/python/wordcount/word_count_test.py similarity index 97% rename from python/word_count/word_count_test.py rename to python/wordcount/word_count_test.py index b63a9eb3..f1899543 100644 --- a/python/word_count/word_count_test.py +++ b/python/wordcount/word_count_test.py @@ -96,7 +96,7 @@ def test_quotation_for_word_with_apostrophe(self): def test_tabs(self): self.assertEqual( count_words( - "rah rah ah ah ah roma roma ma ga ga oh la la want your bad romance" + "rah rah ah ah ah roma roma ma ga ga oh la la want your bad romance" ), { "rah": 2, From 150b07fe0a06e6c9fe2cdeda336ac50ff7365c11 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sun, 25 Jun 2023 23:48:04 -0700 Subject: [PATCH 5/6] python/word-count: 2nd iteration - update tests file --- python/wordcount/.coverage | Bin 53247 -> 53247 bytes python/wordcount/.coverage.xml | 11 ++-- python/wordcount/run-tests-python.txt | 72 +++++++++++++------------- python/wordcount/word_count.py | 3 ++ python/wordcount/word_count.py,cover | 3 ++ python/wordcount/word_count_test.py | 2 +- 6 files changed, 49 insertions(+), 42 deletions(-) diff --git a/python/wordcount/.coverage b/python/wordcount/.coverage index 71047eb42ec0987915e17f862834cc4ca354384f..c029a643c8c926635b6a74c6615be094a694e392 100644 GIT binary patch delta 345 zcmXxeEo{P26b4YBflK-6*V5NC@1;$eG--+ zSzHH~i#zhvrB#>K(b`)9ifv~&I6vKcC*F2hr_{r;Fw0!$nD!4-e_#RX@4qQU_sc6h}G zYrJELH@u+04Aa}Yc2;)h-oCv9QD&4V&3sXkjzl{5M6q#2QH-Y&M`WVmQ+goMrY{P0 MPt;Ojb^2Pk|EQuWG5`Po delta 341 zcmXxeAxy(S7{zg#hP~ao_4T&PUD~9iNmD_Bz#%43Sf;1ZXyk%MHt5cxAgLz9VK8Vk z8e2EEuUGfW|CzUM!hI9Ih1<~ZwjOQITb-P719PfW5L6u&g3@6wC`xESULX;qIVi{+ z;=W{<32cR_z@>2#2dhSg2H Pj8$IRjE`zRcGt;2;*=?w diff --git a/python/wordcount/.coverage.xml b/python/wordcount/.coverage.xml index ae6dcd80..9e5ab788 100644 --- a/python/wordcount/.coverage.xml +++ b/python/wordcount/.coverage.xml @@ -1,5 +1,5 @@ - + @@ -17,14 +17,15 @@ - - + - + + - + + diff --git a/python/wordcount/run-tests-python.txt b/python/wordcount/run-tests-python.txt index 4ed42e53..35a132b9 100644 --- a/python/wordcount/run-tests-python.txt +++ b/python/wordcount/run-tests-python.txt @@ -5,17 +5,17 @@ Running automated test file(s): Running: pylint --ignore-patterns (__init__|.*_test).py . -real 0m0.447s -user 0m0.373s -sys 0m0.071s +real 0m0.417s +user 0m0.344s +sys 0m0.074s =============================================================================== Running: ruff check --ignore E501 ./__init__.py ./word_count.py ./word_count_test.py -real 0m0.065s -user 0m0.026s -sys 0m0.040s +real 0m0.064s +user 0m0.032s +sys 0m0.034s =============================================================================== @@ -23,7 +23,7 @@ Running: pyright --stats . Found 3 source files pyright 1.1.315 0 errors, 0 warnings, 0 informations -Completed in 0.73sec +Completed in 0.715sec Analysis stats Total files parsed and bound: 35 @@ -33,15 +33,15 @@ Timing stats Find Source Files: 0sec Read Source Files: 0.01sec Tokenize: 0.05sec -Parse: 0.07sec -Resolve Imports: 0.06sec -Bind: 0.09sec +Parse: 0.08sec +Resolve Imports: 0.05sec +Bind: 0.08sec Check: 0.11sec Detect Cycles: 0sec -real 0m1.560s -user 0m1.559s -sys 0m0.149s +real 0m1.627s +user 0m1.580s +sys 0m0.150s =============================================================================== @@ -51,7 +51,7 @@ Running: bandit --verbose --recursive . [main] INFO cli include tests: None [main] INFO cli exclude tests: None [main] INFO running on Python 3.11.3 -Run started:2023-06-26 06:33:57.719077 +Run started:2023-06-26 06:47:01.992774 Files in scope (3): ./__init__.py (score: {SEVERITY: 0, CONFIDENCE: 0}) ./word_count.py (score: {SEVERITY: 0, CONFIDENCE: 0}) @@ -78,7 +78,7 @@ Test results: No issues identified. Code scanned: - Total lines of code: 121 + Total lines of code: 122 Total lines skipped (#nosec): 0 Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0 @@ -95,17 +95,17 @@ Run metrics: High: 0 Files skipped (0): -real 0m0.212s -user 0m0.160s -sys 0m0.053s +real 0m0.235s +user 0m0.184s +sys 0m0.052s =============================================================================== Running: refurb . -real 0m1.323s -user 0m1.248s -sys 0m0.076s +real 0m1.320s +user 0m1.249s +sys 0m0.072s =============================================================================== @@ -143,30 +143,30 @@ word_count_test.py::WordCountTest::test_with_quotations PASSED [100%] ---------- coverage: platform linux, python 3.11.3-final-0 ----------- Name Stmts Miss Branch BrPart Cover Missing ----------------------------------------------------------- -word_count.py 14 0 6 0 100% +word_count.py 15 0 6 0 100% ----------------------------------------------------------- -TOTAL 14 0 6 0 100% +TOTAL 15 0 6 0 100% Coverage XML written to file .coverage.xml ============================== 17 passed in 0.05s ============================== real 0m0.936s -user 0m0.809s -sys 0m0.128s +user 0m0.829s +sys 0m0.108s =============================================================================== Running: coverage report --show-missing Name Stmts Miss Branch BrPart Cover Missing ----------------------------------------------------------- -word_count.py 14 0 6 0 100% +word_count.py 15 0 6 0 100% ----------------------------------------------------------- -TOTAL 14 0 6 0 100% +TOTAL 15 0 6 0 100% -real 0m0.138s -user 0m0.089s -sys 0m0.049s +real 0m0.145s +user 0m0.094s +sys 0m0.051s =============================================================================== @@ -174,9 +174,9 @@ coverage annotate The annotate command will be removed in a future version. Get in touch if you still use it: ned@nedbatchelder.com -real 0m0.136s -user 0m0.094s -sys 0m0.043s +real 0m0.130s +user 0m0.096s +sys 0m0.034s tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' @@ -187,9 +187,9 @@ tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' Running: misspell ./__init__.py ./word_count.py ./word_count_test.py -real 0m0.021s -user 0m0.021s -sys 0m0.009s +real 0m0.024s +user 0m0.023s +sys 0m0.011s =============================================================================== diff --git a/python/wordcount/word_count.py b/python/wordcount/word_count.py index 7f93827b..bf1791d1 100644 --- a/python/wordcount/word_count.py +++ b/python/wordcount/word_count.py @@ -16,6 +16,9 @@ def count_words(sentence: str) -> Dict[str, int]: # remove surrounding quotes sentence = sentence.strip("'") + # replace tabs with spaces + sentence = sentence.expandtabs(tabsize=1) + # replace punctuation and funny characters with spaces sentence = re.sub(r"[,.;:_!&@$%^&]", " ", sentence) diff --git a/python/wordcount/word_count.py,cover b/python/wordcount/word_count.py,cover index cde399b7..1773ac17 100644 --- a/python/wordcount/word_count.py,cover +++ b/python/wordcount/word_count.py,cover @@ -16,6 +16,9 @@ # remove surrounding quotes > sentence = sentence.strip("'") + # replace tabs with spaces +> sentence = sentence.expandtabs(tabsize=1) + # replace punctuation and funny characters with spaces > sentence = re.sub(r"[,.;:_!&@$%^&]", " ", sentence) diff --git a/python/wordcount/word_count_test.py b/python/wordcount/word_count_test.py index f1899543..b63a9eb3 100644 --- a/python/wordcount/word_count_test.py +++ b/python/wordcount/word_count_test.py @@ -96,7 +96,7 @@ def test_quotation_for_word_with_apostrophe(self): def test_tabs(self): self.assertEqual( count_words( - "rah rah ah ah ah roma roma ma ga ga oh la la want your bad romance" + "rah rah ah ah ah roma roma ma ga ga oh la la want your bad romance" ), { "rah": 2, From 2d68d4b8acfcbe992dd97879f7b7a5241d87fe94 Mon Sep 17 00:00:00 2001 From: Victor Payno Date: Sun, 25 Jun 2023 23:51:47 -0700 Subject: [PATCH 6/6] python/word-count: 3rd iteration --- python/wordcount/.coverage | Bin 53247 -> 53247 bytes python/wordcount/.coverage.xml | 27 +++++----- python/wordcount/run-tests-python.txt | 68 +++++++++++++------------- python/wordcount/word_count.py | 5 +- python/wordcount/word_count.py,cover | 5 +- 5 files changed, 54 insertions(+), 51 deletions(-) diff --git a/python/wordcount/.coverage b/python/wordcount/.coverage index c029a643c8c926635b6a74c6615be094a694e392..e6553f0b668173e388a8d7d42ad742d27fb161b5 100644 GIT binary patch delta 479 zcmXxgFHFNw5C-seUEl5P-`90(Y2Kqvnlxz|3@8M%Xfzs)MlNXNg5E5Sq?$~k(MWZ9FqqMYO6eZ0Wc|jq= zR5W8`mI6ka5e~>{%CIR-4lp!k7)v8YVra;S64Hz?qSb(fkciQM6hpVeA9zQN7i{p1C*0r>54giUZgGt(Ty)Dk^-1tE zU7zo0RW-3z`zqYhMxvrzi1K1CGF2$b>`atq!BIIxHk}@2CL&|UqQs0uQ8L`?vO63` ZT0(>aQCEmaw@ReC`VO!9s{Y!Y2LGJuJ|E&3kE+CQX_qQ%i8@X*3!Q7P+921l?I2Ni{*D(MW>E z)|Kw=&i!)S|4h9z_0F4faB}RP{ljKR;uL$zJ*8~B8!2P7hEhh;(wb2>lrVHhF{3gB zMp;pGLQN}%DQS6vrUgSA3K@ka#mEW@7)eI=#EKH~8Dm5qBbdl#cmX*K*YhuCDBJbz zFhX>r^8arHJJ2y|!Uiru5xj7fLCKEMn zDyo~cNOy^-GO?(va8@0OOu0HsFGbocM1>ATmsz2NNfwCa2Sj7!i-O4$dBO1WQO5sS CnlF+7 diff --git a/python/wordcount/.coverage.xml b/python/wordcount/.coverage.xml index 9e5ab788..bdf234f3 100644 --- a/python/wordcount/.coverage.xml +++ b/python/wordcount/.coverage.xml @@ -1,5 +1,5 @@ - + @@ -13,19 +13,20 @@ - - - - - - + + + + + + - - - - - - + + + + + + + diff --git a/python/wordcount/run-tests-python.txt b/python/wordcount/run-tests-python.txt index 35a132b9..250318d5 100644 --- a/python/wordcount/run-tests-python.txt +++ b/python/wordcount/run-tests-python.txt @@ -5,17 +5,17 @@ Running automated test file(s): Running: pylint --ignore-patterns (__init__|.*_test).py . -real 0m0.417s -user 0m0.344s -sys 0m0.074s +real 0m0.412s +user 0m0.348s +sys 0m0.066s =============================================================================== Running: ruff check --ignore E501 ./__init__.py ./word_count.py ./word_count_test.py real 0m0.064s -user 0m0.032s -sys 0m0.034s +user 0m0.030s +sys 0m0.036s =============================================================================== @@ -23,7 +23,7 @@ Running: pyright --stats . Found 3 source files pyright 1.1.315 0 errors, 0 warnings, 0 informations -Completed in 0.715sec +Completed in 0.687sec Analysis stats Total files parsed and bound: 35 @@ -33,15 +33,15 @@ Timing stats Find Source Files: 0sec Read Source Files: 0.01sec Tokenize: 0.05sec -Parse: 0.08sec -Resolve Imports: 0.05sec +Parse: 0.06sec +Resolve Imports: 0.04sec Bind: 0.08sec Check: 0.11sec Detect Cycles: 0sec -real 0m1.627s -user 0m1.580s -sys 0m0.150s +real 0m1.309s +user 0m1.460s +sys 0m0.145s =============================================================================== @@ -51,7 +51,7 @@ Running: bandit --verbose --recursive . [main] INFO cli include tests: None [main] INFO cli exclude tests: None [main] INFO running on Python 3.11.3 -Run started:2023-06-26 06:47:01.992774 +Run started:2023-06-26 06:51:23.040683 Files in scope (3): ./__init__.py (score: {SEVERITY: 0, CONFIDENCE: 0}) ./word_count.py (score: {SEVERITY: 0, CONFIDENCE: 0}) @@ -78,7 +78,7 @@ Test results: No issues identified. Code scanned: - Total lines of code: 122 + Total lines of code: 123 Total lines skipped (#nosec): 0 Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0 @@ -95,17 +95,17 @@ Run metrics: High: 0 Files skipped (0): -real 0m0.235s +real 0m0.234s user 0m0.184s -sys 0m0.052s +sys 0m0.051s =============================================================================== Running: refurb . -real 0m1.320s -user 0m1.249s -sys 0m0.072s +real 0m1.312s +user 0m1.233s +sys 0m0.080s =============================================================================== @@ -143,30 +143,30 @@ word_count_test.py::WordCountTest::test_with_quotations PASSED [100%] ---------- coverage: platform linux, python 3.11.3-final-0 ----------- Name Stmts Miss Branch BrPart Cover Missing ----------------------------------------------------------- -word_count.py 15 0 6 0 100% +word_count.py 16 0 6 0 100% ----------------------------------------------------------- -TOTAL 15 0 6 0 100% +TOTAL 16 0 6 0 100% Coverage XML written to file .coverage.xml ============================== 17 passed in 0.05s ============================== -real 0m0.936s -user 0m0.829s -sys 0m0.108s +real 0m0.945s +user 0m0.832s +sys 0m0.113s =============================================================================== Running: coverage report --show-missing Name Stmts Miss Branch BrPart Cover Missing ----------------------------------------------------------- -word_count.py 15 0 6 0 100% +word_count.py 16 0 6 0 100% ----------------------------------------------------------- -TOTAL 15 0 6 0 100% +TOTAL 16 0 6 0 100% -real 0m0.145s -user 0m0.094s -sys 0m0.051s +real 0m0.147s +user 0m0.103s +sys 0m0.045s =============================================================================== @@ -174,9 +174,9 @@ coverage annotate The annotate command will be removed in a future version. Get in touch if you still use it: ned@nedbatchelder.com -real 0m0.130s -user 0m0.096s -sys 0m0.034s +real 0m0.127s +user 0m0.080s +sys 0m0.047s tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' @@ -187,9 +187,9 @@ tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' Running: misspell ./__init__.py ./word_count.py ./word_count_test.py -real 0m0.024s -user 0m0.023s -sys 0m0.011s +real 0m0.020s +user 0m0.026s +sys 0m0.005s =============================================================================== diff --git a/python/wordcount/word_count.py b/python/wordcount/word_count.py index bf1791d1..497db8ec 100644 --- a/python/wordcount/word_count.py +++ b/python/wordcount/word_count.py @@ -2,6 +2,7 @@ import re +from collections import defaultdict from typing import Dict @@ -11,7 +12,7 @@ def count_words(sentence: str) -> Dict[str, int]: :param sentence: str - string we're going to count :return: Dict[str, int] - current round and the two that follow. """ - counts: Dict[str, int] = {} + counts: Dict[str, int] = defaultdict(int) # remove surrounding quotes sentence = sentence.strip("'") @@ -35,6 +36,6 @@ def count_words(sentence: str) -> Dict[str, int]: word = word.strip("'") # increment the word count in the dictionary - counts[word] = 1 + counts.setdefault(word, 0) + counts[word] += 1 return counts diff --git a/python/wordcount/word_count.py,cover b/python/wordcount/word_count.py,cover index 1773ac17..3c59e0df 100644 --- a/python/wordcount/word_count.py,cover +++ b/python/wordcount/word_count.py,cover @@ -2,6 +2,7 @@ > import re +> from collections import defaultdict > from typing import Dict @@ -11,7 +12,7 @@ > :param sentence: str - string we're going to count > :return: Dict[str, int] - current round and the two that follow. > """ -> counts: Dict[str, int] = {} +> counts: Dict[str, int] = defaultdict(int) # remove surrounding quotes > sentence = sentence.strip("'") @@ -35,6 +36,6 @@ > word = word.strip("'") # increment the word count in the dictionary -> counts[word] = 1 + counts.setdefault(word, 0) +> counts[word] += 1 > return counts