diff --git a/python/README.md b/python/README.md index 653a6d7f..c0caa7ad 100644 --- a/python/README.md +++ b/python/README.md @@ -42,3 +42,4 @@ - [raindrops](./raindrops/README.md) - [reverse-string](./reverse-string/README.md) - [roman-numerals](./roman-numerals/README.md) +- [scrabble-score](./scrabble-score/README.md) diff --git a/python/scrabble-score/.coverage b/python/scrabble-score/.coverage new file mode 100644 index 00000000..142d50dc --- /dev/null +++ b/python/scrabble-score/.coverage @@ -0,0 +1 @@ +!coverage.py: This is a private format, don't read it directly!{"arcs":{"/home/vpayno/git_vpayno/exercism-workspace/python/scrabble-score/test/__init__.py":[[0,0],[0,-1]],"/home/vpayno/git_vpayno/exercism-workspace/python/scrabble-score/scrabble_score.py":[[0,1],[1,4],[4,34],[34,-1],[34,41],[41,42],[42,44],[44,46],[46,-34],[4,11],[11,13],[13,14],[14,16],[16,18],[18,19],[19,31],[31,-4],[14,15],[15,31],[16,17],[17,31],[18,20],[20,21],[21,31],[20,22],[22,24],[24,25],[25,31],[22,23],[23,31],[24,26],[26,27],[27,31]]}} \ No newline at end of file diff --git a/python/scrabble-score/.coverage.xml b/python/scrabble-score/.coverage.xml new file mode 100644 index 00000000..28d9d186 --- /dev/null +++ b/python/scrabble-score/.coverage.xml @@ -0,0 +1,53 @@ + + + + + + /home/vpayno/git_vpayno/exercism-workspace/python/scrabble-score + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/scrabble-score/.coveragerc b/python/scrabble-score/.coveragerc new file mode 100644 index 00000000..883531db --- /dev/null +++ b/python/scrabble-score/.coveragerc @@ -0,0 +1,2 @@ +[run] +omit = __init__.py, *_test.py diff --git a/python/scrabble-score/.pylintrc b/python/scrabble-score/.pylintrc new file mode 120000 index 00000000..30b33b52 --- /dev/null +++ b/python/scrabble-score/.pylintrc @@ -0,0 +1 @@ +../.pylintrc \ No newline at end of file diff --git a/python/scrabble-score/README.md b/python/scrabble-score/README.md index 84117a2e..9ff5191a 100644 --- a/python/scrabble-score/README.md +++ b/python/scrabble-score/README.md @@ -64,4 +64,9 @@ And to total: ### Based on -Inspired by the Extreme Startup game - https://github.com/rchatley/extreme_startup \ No newline at end of file +Inspired by the Extreme Startup game - https://github.com/rchatley/extreme_startup + +### My Solution + +- [my solution](./scrabble_score.py) +- [run-tests](./run-tests-python.txt) diff --git a/python/scrabble-score/pytest.ini b/python/scrabble-score/pytest.ini new file mode 100644 index 00000000..8dc12a49 --- /dev/null +++ b/python/scrabble-score/pytest.ini @@ -0,0 +1,5 @@ +[pytest] +pythonpath = . +addopts = --doctest-modules +markers = + task: exercise task/step diff --git a/python/scrabble-score/run-tests-python.txt b/python/scrabble-score/run-tests-python.txt new file mode 100644 index 00000000..0e38855a --- /dev/null +++ b/python/scrabble-score/run-tests-python.txt @@ -0,0 +1,506 @@ +Running automated test file(s): + + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-pylint + +Running Python Lint - PyLint + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: pylint --version + +pylint 3.0.3 +astroid 3.0.2 +Python 3.12.1 (main, Dec 28 2023, 08:22:05) [GCC 10.2.1 20210110] + +real 0m0.269s +user 0m0.182s +sys 0m0.091s + + + ============================================================================== + +Running: pylint ./src + + +-------------------------------------------------------------------- +Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00) + + +real 0m0.483s +user 0m0.386s +sys 0m0.101s + + + ============================================================================== + +Exit code: 0 + +real 0m1.809s +user 0m1.347s +sys 0m0.484s + +real 0m1.812s +user 0m1.348s +sys 0m0.485s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-ruff + +Running Python Lint - Ruff + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: ruff --version + +ruff 0.3.5 + +real 0m0.110s +user 0m0.035s +sys 0m0.078s + + + ============================================================================== + +Running: ruff check --ignore E501 ./src + +All checks passed! + +real 0m0.137s +user 0m0.056s +sys 0m0.088s + + + ============================================================================== + +Exit code: 0 + +real 0m1.335s +user 0m0.817s +sys 0m0.552s + +real 0m1.338s +user 0m0.818s +sys 0m0.553s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-pyright + +Running Python Lint - PyRight + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: pyright --version + +pyright 1.1.358 + +real 0m0.711s +user 0m0.522s +sys 0m0.141s + + + ============================================================================== + +Running: pyright --stats ./src + +Found 2 source files +pyright 1.1.358 +0 errors, 0 warnings, 0 informations +Completed in 0.649sec + +Analysis stats +Total files parsed and bound: 20 +Total files checked: 2 + +Timing stats +Find Source Files: 0sec +Read Source Files: 0.01sec +Tokenize: 0.04sec +Parse: 0.06sec +Resolve Imports: 0.05sec +Bind: 0.05sec +Check: 0.12sec +Detect Cycles: 0sec + +real 0m1.305s +user 0m1.350s +sys 0m0.219s + + + ============================================================================== + +Exit code: 0 + +real 0m3.065s +user 0m2.582s +sys 0m0.721s + +real 0m3.069s +user 0m2.583s +sys 0m0.725s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-bandit + +Running Python Lint - Bandit + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: bandit --version + +bandit 1.7.7 + python version = 3.12.1 (main, Dec 28 2023, 08:22:05) [GCC 10.2.1 20210110] + +real 0m0.325s +user 0m0.237s +sys 0m0.092s + + + ============================================================================== + +Running: bandit --verbose --recursive ./src + +[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.12.1 +Run started:2024-04-13 20:28:27.780535 +Files in scope (2): + ./src/scrabble_score/__init__.py (score: {SEVERITY: 0, CONFIDENCE: 0}) + ./src/scrabble_score/scrabble_score.py (score: {SEVERITY: 0, CONFIDENCE: 0}) +Files excluded (2): + ./src/scrabble_score/__pycache__/__init__.cpython-312.pyc + ./src/scrabble_score/__pycache__/scrabble_score.cpython-312.pyc + +Test results: + No issues identified. + +Code scanned: + Total lines of code: 34 + 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.236s +user 0m0.176s +sys 0m0.062s + + + ============================================================================== + +Exit code: 0 + +real 0m1.645s +user 0m1.142s +sys 0m0.526s + +real 0m1.647s +user 0m1.143s +sys 0m0.527s + +=============================================================================== + +Running: ../../.github/citools/python/python-lint-refurb + +Running Python Lint - Refurb + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: refurb --version + +Refurb: v1.26.0 +Mypy: v1.9.0 + +real 0m0.234s +user 0m0.158s +sys 0m0.079s + + + ============================================================================== + +Running: refurb --quiet --ignore 183 ./src + + +real 0m1.201s +user 0m1.088s +sys 0m0.117s + + + ============================================================================== + +Exit code: 0 + +real 0m3.674s +user 0m3.091s +sys 0m0.610s + +real 0m3.677s +user 0m3.093s +sys 0m0.611s + +=============================================================================== + +Running: ../../.github/citools/python/python-test-with-doctests + +Running Python DocTests + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +PYTHONPATH="./src" + + ============================================================================== + +Running: python -m doctest -v ./src/scrabble_score/__init__.py ./src/scrabble_score/scrabble_score.py + +1 items had no tests: + __init__ +0 tests in 1 items. +0 passed and 0 failed. +Test passed. +3 items had no tests: + scrabble_score + scrabble_score.score + scrabble_score.score_letter +0 tests in 3 items. +0 passed and 0 failed. +Test passed. + +real 0m0.130s +user 0m0.076s +sys 0m0.056s + + + ============================================================================== + +Exit code: 0 + +real 0m1.101s +user 0m0.769s +sys 0m0.354s + +real 0m1.103s +user 0m0.771s +sys 0m0.354s + +=============================================================================== + +Running: ../../.github/citools/python/python-test-with-coverage + +Running Python Tests With Coverage + +Python versions: + + Python 3.12.1 + pyenv 2.3.36-21-g7e550e31 + pip 24.0 from /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/pip (python 3.12) + PDM, version 2.13.2 + + + ============================================================================== + +Running: rm -rf ./coverage + + +real 0m0.001s +user 0m0.000s +sys 0m0.001s + + + ============================================================================== + +Running: pytest --version + +pytest 7.4.3 + +real 0m0.867s +user 0m0.946s +sys 0m0.815s + + + ============================================================================== + +PYTHONPATH="./src" + + ============================================================================== + +Running: pytest --verbose --cov=. --cov-branch --cov-report=term-missing --cov-report=xml:.coverage.xml -p no:randomly ./test + +============================= test session starts ============================== +platform linux -- Python 3.12.1, pytest-7.4.3, pluggy-1.3.0 -- /home/vpayno/.pyenv/versions/3.12.1/bin/python +cachedir: .pytest_cache +hypothesis profile 'default' -> database=DirectoryBasedExampleDatabase(PosixPath('/home/vpayno/git_vpayno/exercism-workspace/python/scrabble-score/.hypothesis/examples')) +rootdir: /home/vpayno/git_vpayno/exercism-workspace/python/scrabble-score +configfile: pytest.ini +plugins: anyio-4.2.0, libtmux-0.25.0, pylama-8.4.1, cov-4.1.0, datafiles-3.0.0, docker-2.0.1, subprocess-1.5.0, typeguard-4.1.5, hypothesis-6.98.17, snapshot-0.9.0 +collecting ... collected 11 items + +test/scrabble_score_test.py::ScrabbleScoreTest::test_empty_input PASSED [ 9%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_english_like_word PASSED [ 18%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_entire_alphabet_available PASSED [ 27%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_long_mixed_case_word PASSED [ 36%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_lowercase_letter PASSED [ 45%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_medium_valuable_word PASSED [ 54%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_medium_word PASSED [ 63%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_short_valuable_word PASSED [ 72%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_short_word PASSED [ 81%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_uppercase_letter PASSED [ 90%] +test/scrabble_score_test.py::ScrabbleScoreTest::test_valuable_letter PASSED [100%] + +=============================== warnings summary =============================== +../../../../.pyenv/versions/3.12.1/lib/python3.12/site-packages/coverage/pytracer.py:164 + /home/vpayno/.pyenv/versions/3.12.1/lib/python3.12/site-packages/coverage/pytracer.py:164: DeprecationWarning: currentThread() is deprecated, use current_thread() instead + self.thread = self.threading.currentThread() + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html + +---------- coverage: platform linux, python 3.12.1-final-0 ----------- +Name Stmts Miss Branch BrPart Cover Missing +--------------------------------------------------------------- +scrabble_score.py 26 3 0 0 88% 28-29 +test/__init__.py 0 0 0 0 100% +--------------------------------------------------------------- +TOTAL 26 3 0 0 88% +Coverage XML written to file .coverage.xml + +======================== 11 passed, 1 warning in 0.94s ========================= + +real 0m1.897s +user 0m1.741s +sys 0m0.158s + + + ============================================================================== + +Running: coverage report --show-missing + +Name Stmts Miss Branch BrPart Cover Missing +--------------------------------------------------------------- +scrabble_score.py 26 3 0 0 88% 28-29 +test/__init__.py 0 0 0 0 100% +--------------------------------------------------------------- +TOTAL 26 3 0 0 88% + +real 0m0.150s +user 0m0.092s +sys 0m0.060s + + + ============================================================================== + +Running: coverage annotate + + +real 0m0.175s +user 0m0.095s +sys 0m0.084s + + + ============================================================================== + +Line Coverage: 88.5% +Branch Coverage: 100.0% + + ============================================================================== + +Exit code: 0 + +real 0m4.092s +user 0m3.586s +sys 0m1.428s + +real 0m4.094s +user 0m3.588s +sys 0m1.429s + +=============================================================================== + +tail -n 10000 ./*,cover | grep -E -C 3 '^> def |^! ' + +> def score_letter(letter: str) -> int: +> """Scores an individual scrabble letter. +-- +> result = 10 +! case _: +! result = 0 + +-- + +> def score(word: str) -> int: +> """Generate the score of a scrabble word. + +=============================================================================== + +Running: misspell ./src/scrabble_score/__init__.py ./src/scrabble_score/scrabble_score.py + +real 0m0.019s +user 0m0.019s +sys 0m0.011s + +=============================================================================== + diff --git a/python/scrabble-score/scrabble_score.py b/python/scrabble-score/scrabble_score.py index 59adad6a..800d5333 100644 --- a/python/scrabble-score/scrabble_score.py +++ b/python/scrabble-score/scrabble_score.py @@ -1,2 +1,46 @@ -def score(word): - pass +"""Python Scrabble Score Exercism""" + + +def score_letter(letter: str) -> int: + """Scores an individual scrabble letter. + + :param letter: lowercase character + :result: numeric score + """ + + result: int = 0 + + match letter: + case "a" | "e" | "i" | "o" | "u" | "l" | "n" | "r" | "s" | "t": + result = 1 + case "d" | "g": + result = 2 + case "b" | "c" | "m" | "p": + result = 3 + case "f" | "h" | "v" | "w" | "y": + result = 4 + case "k": + result = 5 + case "j" | "x": + result = 8 + case "q" | "z": + result = 10 + case _: + result = 0 + + return result + + +def score(word: str) -> int: + """Generate the score of a scrabble word. + + :param word: string of letters + :return: numerical score + """ + + result: int = 0 + chars: list[str] = [*word.lower()] + + result = sum(map(score_letter, chars)) + + return result diff --git a/python/scrabble-score/scrabble_score.py,cover b/python/scrabble-score/scrabble_score.py,cover new file mode 100644 index 00000000..8656db42 --- /dev/null +++ b/python/scrabble-score/scrabble_score.py,cover @@ -0,0 +1,46 @@ +> """Python Scrabble Score Exercism""" + + +> def score_letter(letter: str) -> int: +> """Scores an individual scrabble letter. + +> :param letter: lowercase character +> :result: numeric score +> """ + +> result: int = 0 + +> match letter: +> case "a" | "e" | "i" | "o" | "u" | "l" | "n" | "r" | "s" | "t": +> result = 1 +> case "d" | "g": +> result = 2 +> case "b" | "c" | "m" | "p": +> result = 3 +> case "f" | "h" | "v" | "w" | "y": +> result = 4 +> case "k": +> result = 5 +> case "j" | "x": +> result = 8 +> case "q" | "z": +> result = 10 +! case _: +! result = 0 + +> return result + + +> def score(word: str) -> int: +> """Generate the score of a scrabble word. + +> :param word: string of letters +> :return: numerical score +> """ + +> result: int = 0 +> chars: list[str] = [*word.lower()] + +> result = sum(map(score_letter, chars)) + +> return result diff --git a/python/scrabble-score/src/scrabble_score/__init__.py b/python/scrabble-score/src/scrabble_score/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/scrabble-score/src/scrabble_score/scrabble_score.py b/python/scrabble-score/src/scrabble_score/scrabble_score.py new file mode 120000 index 00000000..c3eb0419 --- /dev/null +++ b/python/scrabble-score/src/scrabble_score/scrabble_score.py @@ -0,0 +1 @@ +../../scrabble_score.py \ No newline at end of file diff --git a/python/scrabble-score/test/__init__.py b/python/scrabble-score/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/python/scrabble-score/test/__init__.py,cover b/python/scrabble-score/test/__init__.py,cover new file mode 100644 index 00000000..e69de29b diff --git a/python/scrabble-score/test/scrabble_score_test.py b/python/scrabble-score/test/scrabble_score_test.py new file mode 120000 index 00000000..3917a32e --- /dev/null +++ b/python/scrabble-score/test/scrabble_score_test.py @@ -0,0 +1 @@ +../scrabble_score_test.py \ No newline at end of file