From 7ceddcbd79d88bc9aa3174fb6459f264df37e0d3 Mon Sep 17 00:00:00 2001 From: Pavel Sapegin Date: Fri, 19 Dec 2025 11:41:44 +0300 Subject: [PATCH 1/9] Add MIT License to the project --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bbf5c56 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Pavel Sapegin + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 67c2c182e4bb36a8bf177df9d1691ef2675036c8 Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 11:28:38 +0300 Subject: [PATCH 2/9] Change names and fix work in binsearch --- src/bin_search.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bin_search.py b/src/bin_search.py index 713abfc..c7b1bfb 100644 --- a/src/bin_search.py +++ b/src/bin_search.py @@ -1,6 +1,6 @@ -def binSearch(xs: list[int], x: int): +def binsearch(xs: list[int], x: int): left, right = 0, len(xs) - 1 - while left < right: + while left <= right: mid = (left + right) // 2 if xs[mid] == x: return mid @@ -9,3 +9,5 @@ def binSearch(xs: list[int], x: int): else: right = mid - 1 return -1 + + From bff0f81dd5f486247adccc067ade9bacbc93b828 Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 11:39:55 +0300 Subject: [PATCH 3/9] Change names and fix work checksum function --- src/checksum.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/checksum.py b/src/checksum.py index 74b4fb0..81a591d 100644 --- a/src/checksum.py +++ b/src/checksum.py @@ -1,14 +1,23 @@ -def modulo11Checksum(ISBNNumber: str): +def modulo11checksum(isbnnumber: str): + chars = [ + char.upper() for char in isbnnumber if char.isdigit() or char.upper() == "X" + ] - digits = [int(char) for char in ISBNNumber if char.isdigit()] - - checkDigit = digits[-1] + if len(chars) != 10: + return False total = 0 - for i in range(len(digits) - 1): - weight = 10 - digit = digits[i] - total += digit * weight + weight = 10 + for i in range(len(chars)): + if chars[i] == "X" and i == 9: + total += 10 + elif chars[i] == "X" and i != 9: + return False + else: + total += int(chars[i]) * weight + + weight -= 1 + + return total % 11 == 0 + - checksum = total + checkDigit - return checksum % 11 == 0 From ceae043dbb2787fd493b052a1972d1f391d1eb44 Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 11:43:04 +0300 Subject: [PATCH 4/9] Create .gitignore --- .gitignore | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e15106e --- /dev/null +++ b/.gitignore @@ -0,0 +1,216 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[codz] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py.cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +# Pipfile.lock + +# UV +# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# uv.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +# poetry.lock +# poetry.toml + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python. +# https://pdm-project.org/en/latest/usage/project/#working-with-version-control +# pdm.lock +# pdm.toml +.pdm-python +.pdm-build/ + +# pixi +# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control. +# pixi.lock +# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one +# in the .venv directory. It is recommended not to include this directory in version control. +.pixi + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# Redis +*.rdb +*.aof +*.pid + +# RabbitMQ +mnesia/ +rabbitmq/ +rabbitmq-data/ + +# ActiveMQ +activemq-data/ + +# SageMath parsed files +*.sage.py + +# Environments +.env +.envrc +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +# .idea/ + +# Abstra +# Abstra is an AI-powered process automation framework. +# Ignore directories containing user credentials, local state, and settings. +# Learn more at https://abstra.io/docs +.abstra/ + +# Visual Studio Code +# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore +# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +# and can be added to the global gitignore or merged into this file. However, if you prefer, +# you could uncomment the following to ignore the entire vscode folder +# .vscode/ + +# Ruff stuff: +.ruff_cache/ + +# PyPI configuration file +.pypirc + +# Marimo +marimo/_static/ +marimo/_lsp/ +__marimo__/ + +# Streamlit +.streamlit/secrets.toml From 2eecf1a9933fda3012a513958946deb69993c95c Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 11:55:21 +0300 Subject: [PATCH 5/9] Add more tests for binary search --- test/test_bin_searh.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/test/test_bin_searh.py b/test/test_bin_searh.py index d18d85b..3a51ff0 100644 --- a/test/test_bin_searh.py +++ b/test/test_bin_searh.py @@ -1,13 +1,31 @@ -from src.bin_search import binSearch +import pytest +from src.bin_search import binsearch -def test_middle(): - assert binSearch([1, 2, 3, 4, 5], 4) == 3 +@pytest.mark.parametrize(["arr","x","expected"],[ + ([1,2,3,4,5],2,1), + ([6,7,8,9,10],8,2), + ([11,12,13,14,15],14,3), +]) +def test_standard_cases(arr,x,expected): + assert binsearch(arr,x) == expected -def test_start(): - assert binSearch([1, 2, 3, 4], 2) == 1 +@pytest.mark.parametrize(["arr","x","expected"],[ + ([10,20,30,40,50],10,0), + ([50,60,80,90,100],100,4) +]) +def test_border_cases(arr,x,expected): + assert binsearch(arr,x) == expected + +@pytest.mark.parametrize(["arr","x"],[ + ([1,2,3,4,5],12), + ([6,7,8,9,12],43) +]) +def test_not_exists(arr,x): + assert binsearch(arr,x) == -1 + +def test_empty(): + assert binsearch([],123) == -1 -def test_not_in_list(): - assert binSearch([1, 2, 3, 4], 5) == -1 From f3b35e1f608668402dd02c50defb21cba93f3057 Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 12:13:37 +0300 Subject: [PATCH 6/9] Write more tests for checksum --- test/test_checksum.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/test/test_checksum.py b/test/test_checksum.py index f64a64c..3f61e8f 100644 --- a/test/test_checksum.py +++ b/test/test_checksum.py @@ -1,9 +1,22 @@ -from src.checksum import modulo11Checksum +import pytest +from src.checksum import modulo11checksum -def test_good(): - assert modulo11Checksum("2-266-11156-8") +@pytest.mark.parametrize( + "isbnnum", ["2266111566", "0-393-04002-X", " sadasdsadsada0-13-110362-8"] +) +def test_standard_cases_true(isbnnum): + assert modulo11checksum(isbnnum) is True -def test_bad(): - assert not modulo11Checksum("2-266-11156-3") + +@pytest.mark.parametrize( + "isbnnum", ["2266111563", "1-57231-999-1", " asasasa-97859504129-6-9"] +) +def test_standard_cases_false(isbnnum): + assert modulo11checksum(isbnnum) is False + + +@pytest.mark.parametrize("isbnnum", ["5038502", "0-0615-3", " asasasa-29-6-9"]) +def test_inccorect_input(isbnnum): + assert modulo11checksum(isbnnum) is False From a189f3bce544ec3f19cfff569e84f76823511f09 Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 12:26:15 +0300 Subject: [PATCH 7/9] Realize app for using checksum --- src/checksum.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/checksum.py b/src/checksum.py index 81a591d..6b6a75d 100644 --- a/src/checksum.py +++ b/src/checksum.py @@ -4,7 +4,7 @@ def modulo11checksum(isbnnumber: str): ] if len(chars) != 10: - return False + raise ValueError(f"Некорректная длина, нужно 10 символов вместо {len(chars)}") total = 0 weight = 10 @@ -21,3 +21,21 @@ def modulo11checksum(isbnnumber: str): return total % 11 == 0 +if __name__ == "__main__": + while True: + try: + print("\nВведите ваш номер ISBN-10 для проверки корректности") + print("Если хотите выйти, введите -1:") + user_input = input() + if user_input == "-1": + break + + if len(user_input) == 0: + print("Ошибка, введена пустая строка") + continue + + result = modulo11checksum(user_input) + print("correct" if result else "incorrect") + + except ValueError as ex: + print(f"Inccorect, ошибка: {ex}") From 28b8f85b4638d097e94c6db9198ce87f4353111d Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 12:27:50 +0300 Subject: [PATCH 8/9] Add .python-version --- .python-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 .python-version diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..4e0cbc8 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +Python 3.12.3 From 97a39aa42d6826420e7b3778227b6b6a10711601 Mon Sep 17 00:00:00 2001 From: PavelSapegin Date: Fri, 19 Dec 2025 12:38:00 +0300 Subject: [PATCH 9/9] Rewrite test with exceptions --- test/test_checksum.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/test_checksum.py b/test/test_checksum.py index 3f61e8f..cafd605 100644 --- a/test/test_checksum.py +++ b/test/test_checksum.py @@ -4,14 +4,14 @@ @pytest.mark.parametrize( - "isbnnum", ["2266111566", "0-393-04002-X", " sadasdsadsada0-13-110362-8"] + "isbnnum", ["2266111566", "0-393-04002-X", "0-13-110362-8"] ) def test_standard_cases_true(isbnnum): assert modulo11checksum(isbnnum) is True @pytest.mark.parametrize( - "isbnnum", ["2266111563", "1-57231-999-1", " asasasa-97859504129-6-9"] + "isbnnum", ["2266111563", "1-57231-999-1", "97504129-6-9"] ) def test_standard_cases_false(isbnnum): assert modulo11checksum(isbnnum) is False @@ -19,4 +19,5 @@ def test_standard_cases_false(isbnnum): @pytest.mark.parametrize("isbnnum", ["5038502", "0-0615-3", " asasasa-29-6-9"]) def test_inccorect_input(isbnnum): - assert modulo11checksum(isbnnum) is False + with pytest.raises(ValueError): + modulo11checksum(isbnnum)