diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a0d05a6..e83c732 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,30 +1,22 @@ -# .github/workflows/test.yml -name: Python Tests - -on: - push: - branches: [ main, master ] - pull_request: - branches: [ main, master ] - +name: Tests +on: push jobs: - test: + build: runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: '3.13' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - pip install pytest - - - name: Run tests - run: pytest -v \ No newline at end of file + - uses: actions/checkout@v4 + - name: Install Python + uses: actions/setup-python@v5 + with: + python-version: "3.13.3" + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ruff + pip install pytest + - name: Run Ruff + run: | + ruff check --output-format=github + - name: Run unit-tests + run: | + python -m pytest test/* \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..456fd8e --- /dev/null +++ b/.gitignore @@ -0,0 +1,177 @@ +# Created by https://www.toptal.com/developers/gitignore/api/python +# Edit at https://www.toptal.com/developers/gitignore?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/s +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 + +# 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 + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.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/ + +### Python Patch ### +# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration +poetry.toml + +# ruff +.ruff_cache/ + +# LSP config files +pyrightconfig.json + +# End of https://www.toptal.com/developers/gitignore/api/python diff --git a/src/.gitignore b/src/.gitignore index ad4a1f1..456fd8e 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -12,6 +12,7 @@ __pycache__/ # Distribution / packaging .Python +build/s build/ develop-eggs/ dist/ diff --git a/src/__init__.py b/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/conftest.py b/src/conftest.py new file mode 100644 index 0000000..b0726d1 --- /dev/null +++ b/src/conftest.py @@ -0,0 +1,7 @@ +import pytest +import random + +@pytest.fixture +def rndm(): + rndm_array = [random.randint(-100, 100) for i in range(10)] + return rndm_array \ No newline at end of file diff --git a/src/pyramid_sort_alg.py b/src/pyramid_sort_alg.py new file mode 100644 index 0000000..960d677 --- /dev/null +++ b/src/pyramid_sort_alg.py @@ -0,0 +1,28 @@ +def build_subroot(arr, ln, i_root): + main_root = i_root + + left_root = 2 * i_root + 1 + right_root = 2 * i_root + 2 + + if left_root < ln and arr[left_root] > arr[main_root]: + main_root = left_root + + if right_root < ln and arr[right_root] > arr[main_root]: + main_root = right_root + + if main_root != i_root: + arr[i_root], arr[main_root] = arr[main_root], arr[i_root] + build_subroot(arr, ln, main_root) + + +def build_pyramid(arr): + ln = len(arr) + + for i in range(ln // 2 - 1, -1, -1): # index main_root + build_subroot(arr, ln, i) + + for d in range(ln - 1, 0, -1): # decline lenght + arr[d], arr[0] = arr[0], arr[d] + build_subroot(arr, d, 0) + + return arr diff --git a/test/__init__.py b/test/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/conftest.py b/test/conftest.py new file mode 100644 index 0000000..b0726d1 --- /dev/null +++ b/test/conftest.py @@ -0,0 +1,7 @@ +import pytest +import random + +@pytest.fixture +def rndm(): + rndm_array = [random.randint(-100, 100) for i in range(10)] + return rndm_array \ No newline at end of file diff --git a/test/pyramid_sort_test.py b/test/pyramid_sort_test.py new file mode 100644 index 0000000..2fd55d6 --- /dev/null +++ b/test/pyramid_sort_test.py @@ -0,0 +1,37 @@ +from src.pyramid_sort_alg import build_pyramid +from src.conftest import rndm # noqa F401 +import pytest + + +# обычные unit-тесты + +test_array = [0, 9, 3, 5] + + +def test_first(): + assert build_pyramid(test_array) == [0, 3, 5, 9] + + +second_array = [766, 1, 9023, 63, 4248] + + +def test_second(): + assert build_pyramid(second_array) != [9023, 1, 766, 4248, 63] + + +# крайние случаи + + +@pytest.mark.parametrize( + ["array", "expected"], + [([], []), ([0], [0]), ([-1, 2, -3], [-3, -1, 2]), ([1, 2, 1], [1, 1, 2])], +) +def test_with_expected(array, expected): + assert build_pyramid(array) == expected + + +# property-based + + +def test_random_array(rndm): # noqa F811 + assert build_pyramid(rndm) == sorted(rndm)