├── .github └── workflows │ └── python-app.yml ├── .gitignore ├── .pylintrc ├── LICENSE.md ├── Makefile ├── README.md ├── mypy.ini ├── poetry.lock ├── pyproject.toml ├── scripts ├── get_input.sh ├── hooks │ └── pre-commit └── local-setup.sh ├── src ├── __init__.py ├── binary_search.py ├── boyer_moore.py ├── breadth_first_search.py ├── bubble_sort.py ├── counting_sort.py ├── depth_first_search.py ├── djikstra.py ├── euclid.py ├── heap_sort.py ├── insert_sort.py ├── merge_sort.py ├── quick_select.py ├── quick_sort.py └── select_sort.py └── tests ├── __init__.py ├── test_binary_search.py ├── test_boyer_moore.py ├── test_breadth_first_search.py ├── test_bubble_sort.py ├── test_counting_sort.py ├── test_depth_first_search.py ├── test_dijkstra.py ├── test_euclid.py ├── test_heap_sort.py ├── test_insert_sort.py ├── test_merge_sort.py ├── test_quick_select.py ├── test_quick_sort.py └── test_select_sort.py /.github/workflows/python-app.yml: -------------------------------------------------------------------------------- 1 | name: deploy 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | 7 | permissions: 8 | contents: read 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up Python 3.10 18 | uses: actions/setup-python@v3 19 | with: 20 | python-version: "3.10" 21 | - name: Install dependencies 22 | run: | 23 | python -m pip install --upgrade pip 24 | pip install poetry 25 | poetry install 26 | - name: Check style, format and lint 27 | run: | 28 | poetry run mypy . 29 | poetry run black --check . 30 | poetry run flake8 . 31 | poetry run pylint ./* 32 | - name: Tests 33 | run: | 34 | PYTHONPATH=. poetry run pytest -n auto 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # CoC settings 2 | .vim 3 | 4 | # Testmon 5 | .testmondata 6 | 7 | # Byte-compiled / optimized / DLL files 8 | __pycache__/ 9 | *.py[cod] 10 | *$py.class 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | build/ 18 | develop-eggs/ 19 | dist/ 20 | downloads/ 21 | eggs/ 22 | .eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | wheels/ 29 | pip-wheel-metadata/ 30 | share/python-wheels/ 31 | *.egg-info/ 32 | .installed.cfg 33 | *.egg 34 | MANIFEST 35 | 36 | # PyInstaller 37 | # Usually these files are written by a python script from a template 38 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 39 | *.manifest 40 | *.spec 41 | 42 | # Installer logs 43 | pip-log.txt 44 | pip-delete-this-directory.txt 45 | 46 | # Unit test / coverage reports 47 | htmlcov/ 48 | .tox/ 49 | .nox/ 50 | .coverage 51 | .coverage.* 52 | .cache 53 | nosetests.xml 54 | coverage.xml 55 | *.cover 56 | *.py,cover 57 | .hypothesis/ 58 | .pytest_cache/ 59 | 60 | # Translations 61 | *.mo 62 | *.pot 63 | 64 | # Django stuff: 65 | *.log 66 | local_settings.py 67 | db.sqlite3 68 | db.sqlite3-journal 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | docs/_build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # IPython 87 | profile_default/ 88 | ipython_config.py 89 | 90 | # pyenv 91 | .python-version 92 | 93 | # pipenv 94 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 95 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 96 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 97 | # install all needed dependencies. 98 | #Pipfile.lock 99 | 100 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 101 | __pypackages__/ 102 | 103 | # Celery stuff 104 | celerybeat-schedule 105 | celerybeat.pid 106 | 107 | # SageMath parsed files 108 | *.sage.py 109 | 110 | # Environments 111 | .env 112 | .venv 113 | env/ 114 | venv/ 115 | ENV/ 116 | env.bak/ 117 | venv.bak/ 118 | 119 | # Spyder project settings 120 | .spyderproject 121 | .spyproject 122 | 123 | # Rope project settings 124 | .ropeproject 125 | 126 | # mkdocs documentation 127 | /site 128 | 129 | # mypy 130 | .mypy_cache/ 131 | .dmypy.json 132 | dmypy.json 133 | 134 | # Pyre type checker 135 | .pyre/ 136 | 137 | .idea/ 138 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | disable= 3 | C0114,C0115,C0116, # missing-module-docstring 4 | R0903,C0301,R0913,E0001,C0206, 5 | E0611,W0122,W0511,W0102 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 4-digit year, Company or Person's Name 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. 4 | 5 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 6 | 7 | Source: http://opensource.org/licenses/ISC 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := help 2 | 3 | .PHONY: help 4 | help: ## Show this help. 5 | @grep -E '^\S+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | \ 6 | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}' 7 | 8 | .PHONY: local-setup 9 | local-setup: ## Set up the local environment (e.g. install git hooks) 10 | scripts/local-setup.sh 11 | 12 | .PHONY: install 13 | install: ## Install all dependencies 14 | poetry install 15 | 16 | .PHONY: update 17 | update: ## Update dependencies 18 | poetry update 19 | 20 | .PHONY: check-typing 21 | check-typing: ## Run a static analyzer over the code to find issues 22 | poetry run mypy . 23 | 24 | .PHONY: check-format 25 | check-format: 26 | poetry run black --check . 27 | 28 | .PHONY: check-style 29 | check-style: 30 | poetry run flake8 . 31 | poetry run pylint ./* 32 | 33 | .PHONY: reformat 34 | reformat: ## Format python code 35 | poetry run black . 36 | poetry run pyupgrade --py310-plus **/*.py 37 | 38 | .PHONY: test 39 | test: ## Run all available tests 40 | PYTHONPATH=. poetry run pytest -n auto 41 | 42 | .PHONY: pre-commit 43 | pre-commit: check-format check-typing check-style test 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Top 25 Algorithms Every Programmer Should Know ![status](https://github.com/pmareke/top-25-algorithms-every-programmer-should-know/actions/workflows/python-app.yml/badge.svg) 2 | 3 | - [X] [Binary Search](https://en.wikipedia.org/wiki/Binary_search_algorithm). 4 | - [X] [Breadth First Search (BFS)](https://en.wikipedia.org/wiki/Breadth-first_search). 5 | - [X] [Depth First Search (DFS)](https://en.wikipedia.org/wiki/Depth-first_search). 6 | - [X] [Merge Sort](https://en.wikipedia.org/wiki/Merge_sort). 7 | - [X] [Quicksort](https://en.wikipedia.org/wiki/Quicksort). 8 | - [X] [Dijkstra](https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm). 9 | - [X] [Quickselect](https://en.wikipedia.org/wiki/Quickselect). 10 | - [X] [Selection Sort](https://en.wikipedia.org/wiki/Selection_sort). 11 | - [X] [Insertion Sort](https://en.wikipedia.org/wiki/Insertion_sort). 12 | - [X] [Bubble Sort](https://en.wikipedia.org/wiki/Bubble_sort). 13 | - [X] [Heap Sort](https://en.wikipedia.org/wiki/Heapsort). 14 | - [X] [Euclid](https://en.wikipedia.org/wiki/Euclidean_algorithm). 15 | - [X] [Boyer–Moore Majority Vote](https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm). 16 | - [X] [Counting Sort](https://en.wikipedia.org/wiki/Counting_sort). 17 | - [ ] [Kadane](https://en.wikipedia.org/wiki/Maximum_subarray_problem). 18 | - [ ] [Kruskal's](https://en.wikipedia.org/wiki/Kruskal%27s_algorithm). 19 | - [ ] [Floyd Warshall](https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm). 20 | - [ ] [Bellman Ford](). 21 | - [ ] [Lee](). 22 | - [ ] [Flood Fill](). 23 | - [ ] [Union Find](). 24 | - [ ] [Topological Sort](). 25 | - [ ] [KMP](). 26 | - [ ] [Kahn’s Topological Sort](). 27 | - [ ] [Huffman Coding Compression](). 28 | -------------------------------------------------------------------------------- /mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | python_version = 3.10 3 | mypy_path = . 4 | disable_error_code = override,attr-defined 5 | check_untyped_defs = true 6 | disallow_any_explicit = true 7 | 8 | # None and Optional handling 9 | no_implicit_optional = true 10 | 11 | # Configuring warnings 12 | warn_redundant_casts = true 13 | warn_unused_ignores = false 14 | warn_no_return = true 15 | warn_return_any = true 16 | warn_unreachable = true 17 | 18 | # Miscellaneous strictness flags 19 | implicit_reexport = true 20 | strict_equality = true 21 | 22 | # Configuring error messages 23 | show_error_context = true 24 | show_column_numbers = true 25 | show_error_codes = true 26 | pretty = false 27 | show_absolute_path = false 28 | 29 | disallow_untyped_defs = true 30 | 31 | [mypy-expects.*] 32 | ignore_missing_imports = True 33 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "astroid" 3 | version = "2.12.13" 4 | description = "An abstract syntax tree for Python with inference support." 5 | category = "dev" 6 | optional = false 7 | python-versions = ">=3.7.2" 8 | 9 | [package.dependencies] 10 | lazy-object-proxy = ">=1.4.0" 11 | wrapt = [ 12 | {version = ">=1.11,<2", markers = "python_version < \"3.11\""}, 13 | {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, 14 | ] 15 | 16 | [[package]] 17 | name = "attrs" 18 | version = "22.2.0" 19 | description = "Classes Without Boilerplate" 20 | category = "dev" 21 | optional = false 22 | python-versions = ">=3.6" 23 | 24 | [package.extras] 25 | cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] 26 | dev = ["attrs[docs,tests]"] 27 | docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] 28 | tests = ["attrs[tests-no-zope]", "zope.interface"] 29 | tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] 30 | 31 | [[package]] 32 | name = "black" 33 | version = "22.12.0" 34 | description = "The uncompromising code formatter." 35 | category = "main" 36 | optional = false 37 | python-versions = ">=3.7" 38 | 39 | [package.dependencies] 40 | click = ">=8.0.0" 41 | mypy-extensions = ">=0.4.3" 42 | pathspec = ">=0.9.0" 43 | platformdirs = ">=2" 44 | tomli = {version = ">=1.1.0", markers = "python_full_version < \"3.11.0a7\""} 45 | 46 | [package.extras] 47 | colorama = ["colorama (>=0.4.3)"] 48 | d = ["aiohttp (>=3.7.4)"] 49 | jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] 50 | uvloop = ["uvloop (>=0.15.2)"] 51 | 52 | [[package]] 53 | name = "click" 54 | version = "8.1.3" 55 | description = "Composable command line interface toolkit" 56 | category = "main" 57 | optional = false 58 | python-versions = ">=3.7" 59 | 60 | [package.dependencies] 61 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 62 | 63 | [[package]] 64 | name = "colorama" 65 | version = "0.4.6" 66 | description = "Cross-platform colored terminal text." 67 | category = "main" 68 | optional = false 69 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" 70 | 71 | [[package]] 72 | name = "dill" 73 | version = "0.3.6" 74 | description = "serialize all of python" 75 | category = "dev" 76 | optional = false 77 | python-versions = ">=3.7" 78 | 79 | [package.extras] 80 | graph = ["objgraph (>=1.7.2)"] 81 | 82 | [[package]] 83 | name = "exceptiongroup" 84 | version = "1.1.0" 85 | description = "Backport of PEP 654 (exception groups)" 86 | category = "dev" 87 | optional = false 88 | python-versions = ">=3.7" 89 | 90 | [package.extras] 91 | test = ["pytest (>=6)"] 92 | 93 | [[package]] 94 | name = "execnet" 95 | version = "1.9.0" 96 | description = "execnet: rapid multi-Python deployment" 97 | category = "dev" 98 | optional = false 99 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 100 | 101 | [package.extras] 102 | testing = ["pre-commit"] 103 | 104 | [[package]] 105 | name = "expects" 106 | version = "0.9.0" 107 | description = "Expressive and extensible TDD/BDD assertion library for Python" 108 | category = "dev" 109 | optional = false 110 | python-versions = "*" 111 | 112 | [[package]] 113 | name = "flake8" 114 | version = "5.0.4" 115 | description = "the modular source code checker: pep8 pyflakes and co" 116 | category = "dev" 117 | optional = false 118 | python-versions = ">=3.6.1" 119 | 120 | [package.dependencies] 121 | mccabe = ">=0.7.0,<0.8.0" 122 | pycodestyle = ">=2.9.0,<2.10.0" 123 | pyflakes = ">=2.5.0,<2.6.0" 124 | 125 | [[package]] 126 | name = "flake8-pyproject" 127 | version = "1.2.2" 128 | description = "Flake8 plug-in loading the configuration from pyproject.toml" 129 | category = "dev" 130 | optional = false 131 | python-versions = ">= 3.6" 132 | 133 | [package.dependencies] 134 | Flake8 = ">=5" 135 | TOMLi = {version = "*", markers = "python_version < \"3.11\""} 136 | 137 | [package.extras] 138 | dev = ["pyTest", "pyTest-cov"] 139 | 140 | [[package]] 141 | name = "iniconfig" 142 | version = "1.1.1" 143 | description = "iniconfig: brain-dead simple config-ini parsing" 144 | category = "dev" 145 | optional = false 146 | python-versions = "*" 147 | 148 | [[package]] 149 | name = "isort" 150 | version = "5.11.4" 151 | description = "A Python utility / library to sort Python imports." 152 | category = "dev" 153 | optional = false 154 | python-versions = ">=3.7.0" 155 | 156 | [package.extras] 157 | colors = ["colorama (>=0.4.3,<0.5.0)"] 158 | pipfile-deprecated-finder = ["pipreqs", "requirementslib"] 159 | plugins = ["setuptools"] 160 | requirements-deprecated-finder = ["pip-api", "pipreqs"] 161 | 162 | [[package]] 163 | name = "lazy-object-proxy" 164 | version = "1.8.0" 165 | description = "A fast and thorough lazy object proxy." 166 | category = "dev" 167 | optional = false 168 | python-versions = ">=3.7" 169 | 170 | [[package]] 171 | name = "mccabe" 172 | version = "0.7.0" 173 | description = "McCabe checker, plugin for flake8" 174 | category = "dev" 175 | optional = false 176 | python-versions = ">=3.6" 177 | 178 | [[package]] 179 | name = "mypy" 180 | version = "0.971" 181 | description = "Optional static typing for Python" 182 | category = "dev" 183 | optional = false 184 | python-versions = ">=3.6" 185 | 186 | [package.dependencies] 187 | mypy-extensions = ">=0.4.3" 188 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 189 | typing-extensions = ">=3.10" 190 | 191 | [package.extras] 192 | dmypy = ["psutil (>=4.0)"] 193 | python2 = ["typed-ast (>=1.4.0,<2)"] 194 | reports = ["lxml"] 195 | 196 | [[package]] 197 | name = "mypy-extensions" 198 | version = "0.4.3" 199 | description = "Experimental type system extensions for programs checked with the mypy typechecker." 200 | category = "main" 201 | optional = false 202 | python-versions = "*" 203 | 204 | [[package]] 205 | name = "packaging" 206 | version = "22.0" 207 | description = "Core utilities for Python packages" 208 | category = "dev" 209 | optional = false 210 | python-versions = ">=3.7" 211 | 212 | [[package]] 213 | name = "pathspec" 214 | version = "0.10.3" 215 | description = "Utility library for gitignore style pattern matching of file paths." 216 | category = "main" 217 | optional = false 218 | python-versions = ">=3.7" 219 | 220 | [[package]] 221 | name = "platformdirs" 222 | version = "2.6.2" 223 | description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." 224 | category = "main" 225 | optional = false 226 | python-versions = ">=3.7" 227 | 228 | [package.extras] 229 | docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"] 230 | test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] 231 | 232 | [[package]] 233 | name = "pluggy" 234 | version = "1.0.0" 235 | description = "plugin and hook calling mechanisms for python" 236 | category = "dev" 237 | optional = false 238 | python-versions = ">=3.6" 239 | 240 | [package.extras] 241 | dev = ["pre-commit", "tox"] 242 | testing = ["pytest", "pytest-benchmark"] 243 | 244 | [[package]] 245 | name = "py" 246 | version = "1.11.0" 247 | description = "library with cross-python path, ini-parsing, io, code, log facilities" 248 | category = "dev" 249 | optional = false 250 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 251 | 252 | [[package]] 253 | name = "pycodestyle" 254 | version = "2.9.1" 255 | description = "Python style guide checker" 256 | category = "dev" 257 | optional = false 258 | python-versions = ">=3.6" 259 | 260 | [[package]] 261 | name = "pyflakes" 262 | version = "2.5.0" 263 | description = "passive checker of Python programs" 264 | category = "dev" 265 | optional = false 266 | python-versions = ">=3.6" 267 | 268 | [[package]] 269 | name = "pylint" 270 | version = "2.15.9" 271 | description = "python code static checker" 272 | category = "dev" 273 | optional = false 274 | python-versions = ">=3.7.2" 275 | 276 | [package.dependencies] 277 | astroid = ">=2.12.13,<=2.14.0-dev0" 278 | colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} 279 | dill = [ 280 | {version = ">=0.2", markers = "python_version < \"3.11\""}, 281 | {version = ">=0.3.6", markers = "python_version >= \"3.11\""}, 282 | ] 283 | isort = ">=4.2.5,<6" 284 | mccabe = ">=0.6,<0.8" 285 | platformdirs = ">=2.2.0" 286 | tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} 287 | tomlkit = ">=0.10.1" 288 | 289 | [package.extras] 290 | spelling = ["pyenchant (>=3.2,<4.0)"] 291 | testutils = ["gitpython (>3)"] 292 | 293 | [[package]] 294 | name = "pytest" 295 | version = "7.2.0" 296 | description = "pytest: simple powerful testing with Python" 297 | category = "dev" 298 | optional = false 299 | python-versions = ">=3.7" 300 | 301 | [package.dependencies] 302 | attrs = ">=19.2.0" 303 | colorama = {version = "*", markers = "sys_platform == \"win32\""} 304 | exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} 305 | iniconfig = "*" 306 | packaging = "*" 307 | pluggy = ">=0.12,<2.0" 308 | tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} 309 | 310 | [package.extras] 311 | testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] 312 | 313 | [[package]] 314 | name = "pytest-forked" 315 | version = "1.4.0" 316 | description = "run tests in isolated forked subprocesses" 317 | category = "dev" 318 | optional = false 319 | python-versions = ">=3.6" 320 | 321 | [package.dependencies] 322 | py = "*" 323 | pytest = ">=3.10" 324 | 325 | [[package]] 326 | name = "pytest-xdist" 327 | version = "2.5.0" 328 | description = "pytest xdist plugin for distributed testing and loop-on-failing modes" 329 | category = "dev" 330 | optional = false 331 | python-versions = ">=3.6" 332 | 333 | [package.dependencies] 334 | execnet = ">=1.1" 335 | pytest = ">=6.2.0" 336 | pytest-forked = "*" 337 | 338 | [package.extras] 339 | psutil = ["psutil (>=3.0)"] 340 | setproctitle = ["setproctitle"] 341 | testing = ["filelock"] 342 | 343 | [[package]] 344 | name = "pyupgrade" 345 | version = "3.3.1" 346 | description = "A tool to automatically upgrade syntax for newer versions." 347 | category = "dev" 348 | optional = false 349 | python-versions = ">=3.7" 350 | 351 | [package.dependencies] 352 | tokenize-rt = ">=3.2.0" 353 | 354 | [[package]] 355 | name = "tokenize-rt" 356 | version = "5.0.0" 357 | description = "A wrapper around the stdlib `tokenize` which roundtrips." 358 | category = "dev" 359 | optional = false 360 | python-versions = ">=3.7" 361 | 362 | [[package]] 363 | name = "toml" 364 | version = "0.10.2" 365 | description = "Python Library for Tom's Obvious, Minimal Language" 366 | category = "dev" 367 | optional = false 368 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 369 | 370 | [[package]] 371 | name = "tomli" 372 | version = "2.0.1" 373 | description = "A lil' TOML parser" 374 | category = "main" 375 | optional = false 376 | python-versions = ">=3.7" 377 | 378 | [[package]] 379 | name = "tomlkit" 380 | version = "0.11.6" 381 | description = "Style preserving TOML library" 382 | category = "dev" 383 | optional = false 384 | python-versions = ">=3.6" 385 | 386 | [[package]] 387 | name = "typing-extensions" 388 | version = "4.4.0" 389 | description = "Backported and Experimental Type Hints for Python 3.7+" 390 | category = "dev" 391 | optional = false 392 | python-versions = ">=3.7" 393 | 394 | [[package]] 395 | name = "wrapt" 396 | version = "1.14.1" 397 | description = "Module for decorators, wrappers and monkey patching." 398 | category = "dev" 399 | optional = false 400 | python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" 401 | 402 | [[package]] 403 | name = "yapf" 404 | version = "0.32.0" 405 | description = "A formatter for Python code." 406 | category = "dev" 407 | optional = false 408 | python-versions = "*" 409 | 410 | [metadata] 411 | lock-version = "1.1" 412 | python-versions = "^3.10" 413 | content-hash = "a2353f80685bbaea15b014401c54f8ab369dc7bcc644e32870cca159aba0f08a" 414 | 415 | [metadata.files] 416 | astroid = [ 417 | {file = "astroid-2.12.13-py3-none-any.whl", hash = "sha256:10e0ad5f7b79c435179d0d0f0df69998c4eef4597534aae44910db060baeb907"}, 418 | {file = "astroid-2.12.13.tar.gz", hash = "sha256:1493fe8bd3dfd73dc35bd53c9d5b6e49ead98497c47b2307662556a5692d29d7"}, 419 | ] 420 | attrs = [ 421 | {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, 422 | {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, 423 | ] 424 | black = [ 425 | {file = "black-22.12.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eedd20838bd5d75b80c9f5487dbcb06836a43833a37846cf1d8c1cc01cef59d"}, 426 | {file = "black-22.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:159a46a4947f73387b4d83e87ea006dbb2337eab6c879620a3ba52699b1f4351"}, 427 | {file = "black-22.12.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d30b212bffeb1e252b31dd269dfae69dd17e06d92b87ad26e23890f3efea366f"}, 428 | {file = "black-22.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:7412e75863aa5c5411886804678b7d083c7c28421210180d67dfd8cf1221e1f4"}, 429 | {file = "black-22.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c116eed0efb9ff870ded8b62fe9f28dd61ef6e9ddd28d83d7d264a38417dcee2"}, 430 | {file = "black-22.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f58cbe16dfe8c12b7434e50ff889fa479072096d79f0a7f25e4ab8e94cd8350"}, 431 | {file = "black-22.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d86c9f3db9b1bf6761244bc0b3572a546f5fe37917a044e02f3166d5aafa7d"}, 432 | {file = "black-22.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:82d9fe8fee3401e02e79767016b4907820a7dc28d70d137eb397b92ef3cc5bfc"}, 433 | {file = "black-22.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:101c69b23df9b44247bd88e1d7e90154336ac4992502d4197bdac35dd7ee3320"}, 434 | {file = "black-22.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:559c7a1ba9a006226f09e4916060982fd27334ae1998e7a38b3f33a37f7a2148"}, 435 | {file = "black-22.12.0-py3-none-any.whl", hash = "sha256:436cc9167dd28040ad90d3b404aec22cedf24a6e4d7de221bec2730ec0c97bcf"}, 436 | {file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"}, 437 | ] 438 | click = [ 439 | {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, 440 | {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, 441 | ] 442 | colorama = [ 443 | {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, 444 | {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, 445 | ] 446 | dill = [ 447 | {file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"}, 448 | {file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"}, 449 | ] 450 | exceptiongroup = [ 451 | {file = "exceptiongroup-1.1.0-py3-none-any.whl", hash = "sha256:327cbda3da756e2de031a3107b81ab7b3770a602c4d16ca618298c526f4bec1e"}, 452 | {file = "exceptiongroup-1.1.0.tar.gz", hash = "sha256:bcb67d800a4497e1b404c2dd44fca47d3b7a5e5433dbab67f96c1a685cdfdf23"}, 453 | ] 454 | execnet = [ 455 | {file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"}, 456 | {file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"}, 457 | ] 458 | expects = [ 459 | {file = "expects-0.9.0.tar.gz", hash = "sha256:419902ccafe81b7e9559eeb6b7a07ef9d5c5604eddb93000f0642b3b2d594f4c"}, 460 | ] 461 | flake8 = [ 462 | {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, 463 | {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, 464 | ] 465 | flake8-pyproject = [ 466 | {file = "flake8_pyproject-1.2.2-py3-none-any.whl", hash = "sha256:52d412219e7db6227faa654675b1435947b11d49b453f3eced760f19bdd6f06a"}, 467 | ] 468 | iniconfig = [ 469 | {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, 470 | {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"}, 471 | ] 472 | isort = [ 473 | {file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"}, 474 | {file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"}, 475 | ] 476 | lazy-object-proxy = [ 477 | {file = "lazy-object-proxy-1.8.0.tar.gz", hash = "sha256:c219a00245af0f6fa4e95901ed28044544f50152840c5b6a3e7b2568db34d156"}, 478 | {file = "lazy_object_proxy-1.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4fd031589121ad46e293629b39604031d354043bb5cdf83da4e93c2d7f3389fe"}, 479 | {file = "lazy_object_proxy-1.8.0-cp310-cp310-win32.whl", hash = "sha256:b70d6e7a332eb0217e7872a73926ad4fdc14f846e85ad6749ad111084e76df25"}, 480 | {file = "lazy_object_proxy-1.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:eb329f8d8145379bf5dbe722182410fe8863d186e51bf034d2075eb8d85ee25b"}, 481 | {file = "lazy_object_proxy-1.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4e2d9f764f1befd8bdc97673261b8bb888764dfdbd7a4d8f55e4fbcabb8c3fb7"}, 482 | {file = "lazy_object_proxy-1.8.0-cp311-cp311-win32.whl", hash = "sha256:e20bfa6db17a39c706d24f82df8352488d2943a3b7ce7d4c22579cb89ca8896e"}, 483 | {file = "lazy_object_proxy-1.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:14010b49a2f56ec4943b6cf925f597b534ee2fe1f0738c84b3bce0c1a11ff10d"}, 484 | {file = "lazy_object_proxy-1.8.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6850e4aeca6d0df35bb06e05c8b934ff7c533734eb51d0ceb2d63696f1e6030c"}, 485 | {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win32.whl", hash = "sha256:5b51d6f3bfeb289dfd4e95de2ecd464cd51982fe6f00e2be1d0bf94864d58acd"}, 486 | {file = "lazy_object_proxy-1.8.0-cp37-cp37m-win_amd64.whl", hash = "sha256:6f593f26c470a379cf7f5bc6db6b5f1722353e7bf937b8d0d0b3fba911998858"}, 487 | {file = "lazy_object_proxy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c1c7c0433154bb7c54185714c6929acc0ba04ee1b167314a779b9025517eada"}, 488 | {file = "lazy_object_proxy-1.8.0-cp38-cp38-win32.whl", hash = "sha256:d176f392dbbdaacccf15919c77f526edf11a34aece58b55ab58539807b85436f"}, 489 | {file = "lazy_object_proxy-1.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:afcaa24e48bb23b3be31e329deb3f1858f1f1df86aea3d70cb5c8578bfe5261c"}, 490 | {file = "lazy_object_proxy-1.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:71d9ae8a82203511a6f60ca5a1b9f8ad201cac0fc75038b2dc5fa519589c9288"}, 491 | {file = "lazy_object_proxy-1.8.0-cp39-cp39-win32.whl", hash = "sha256:8f6ce2118a90efa7f62dd38c7dbfffd42f468b180287b748626293bf12ed468f"}, 492 | {file = "lazy_object_proxy-1.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:eac3a9a5ef13b332c059772fd40b4b1c3d45a3a2b05e33a361dee48e54a4dad0"}, 493 | {file = "lazy_object_proxy-1.8.0-pp37-pypy37_pp73-any.whl", hash = "sha256:ae032743794fba4d171b5b67310d69176287b5bf82a21f588282406a79498891"}, 494 | {file = "lazy_object_proxy-1.8.0-pp38-pypy38_pp73-any.whl", hash = "sha256:7e1561626c49cb394268edd00501b289053a652ed762c58e1081224c8d881cec"}, 495 | {file = "lazy_object_proxy-1.8.0-pp39-pypy39_pp73-any.whl", hash = "sha256:ce58b2b3734c73e68f0e30e4e725264d4d6be95818ec0a0be4bb6bf9a7e79aa8"}, 496 | ] 497 | mccabe = [ 498 | {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, 499 | {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, 500 | ] 501 | mypy = [ 502 | {file = "mypy-0.971-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f2899a3cbd394da157194f913a931edfd4be5f274a88041c9dc2d9cdcb1c315c"}, 503 | {file = "mypy-0.971-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98e02d56ebe93981c41211c05adb630d1d26c14195d04d95e49cd97dbc046dc5"}, 504 | {file = "mypy-0.971-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19830b7dba7d5356d3e26e2427a2ec91c994cd92d983142cbd025ebe81d69cf3"}, 505 | {file = "mypy-0.971-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:02ef476f6dcb86e6f502ae39a16b93285fef97e7f1ff22932b657d1ef1f28655"}, 506 | {file = "mypy-0.971-cp310-cp310-win_amd64.whl", hash = "sha256:25c5750ba5609a0c7550b73a33deb314ecfb559c350bb050b655505e8aed4103"}, 507 | {file = "mypy-0.971-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d3348e7eb2eea2472db611486846742d5d52d1290576de99d59edeb7cd4a42ca"}, 508 | {file = "mypy-0.971-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3fa7a477b9900be9b7dd4bab30a12759e5abe9586574ceb944bc29cddf8f0417"}, 509 | {file = "mypy-0.971-cp36-cp36m-win_amd64.whl", hash = "sha256:2ad53cf9c3adc43cf3bea0a7d01a2f2e86db9fe7596dfecb4496a5dda63cbb09"}, 510 | {file = "mypy-0.971-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:855048b6feb6dfe09d3353466004490b1872887150c5bb5caad7838b57328cc8"}, 511 | {file = "mypy-0.971-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:23488a14a83bca6e54402c2e6435467a4138785df93ec85aeff64c6170077fb0"}, 512 | {file = "mypy-0.971-cp37-cp37m-win_amd64.whl", hash = "sha256:4b21e5b1a70dfb972490035128f305c39bc4bc253f34e96a4adf9127cf943eb2"}, 513 | {file = "mypy-0.971-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9796a2ba7b4b538649caa5cecd398d873f4022ed2333ffde58eaf604c4d2cb27"}, 514 | {file = "mypy-0.971-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a361d92635ad4ada1b1b2d3630fc2f53f2127d51cf2def9db83cba32e47c856"}, 515 | {file = "mypy-0.971-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b793b899f7cf563b1e7044a5c97361196b938e92f0a4343a5d27966a53d2ec71"}, 516 | {file = "mypy-0.971-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d1ea5d12c8e2d266b5fb8c7a5d2e9c0219fedfeb493b7ed60cd350322384ac27"}, 517 | {file = "mypy-0.971-cp38-cp38-win_amd64.whl", hash = "sha256:23c7ff43fff4b0df93a186581885c8512bc50fc4d4910e0f838e35d6bb6b5e58"}, 518 | {file = "mypy-0.971-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1f7656b69974a6933e987ee8ffb951d836272d6c0f81d727f1d0e2696074d9e6"}, 519 | {file = "mypy-0.971-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d2022bfadb7a5c2ef410d6a7c9763188afdb7f3533f22a0a32be10d571ee4bbe"}, 520 | {file = "mypy-0.971-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef943c72a786b0f8d90fd76e9b39ce81fb7171172daf84bf43eaf937e9f220a9"}, 521 | {file = "mypy-0.971-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d744f72eb39f69312bc6c2abf8ff6656973120e2eb3f3ec4f758ed47e414a4bf"}, 522 | {file = "mypy-0.971-cp39-cp39-win_amd64.whl", hash = "sha256:77a514ea15d3007d33a9e2157b0ba9c267496acf12a7f2b9b9f8446337aac5b0"}, 523 | {file = "mypy-0.971-py3-none-any.whl", hash = "sha256:0d054ef16b071149917085f51f89555a576e2618d5d9dd70bd6eea6410af3ac9"}, 524 | {file = "mypy-0.971.tar.gz", hash = "sha256:40b0f21484238269ae6a57200c807d80debc6459d444c0489a102d7c6a75fa56"}, 525 | ] 526 | mypy-extensions = [ 527 | {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, 528 | {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, 529 | ] 530 | packaging = [ 531 | {file = "packaging-22.0-py3-none-any.whl", hash = "sha256:957e2148ba0e1a3b282772e791ef1d8083648bc131c8ab0c1feba110ce1146c3"}, 532 | {file = "packaging-22.0.tar.gz", hash = "sha256:2198ec20bd4c017b8f9717e00f0c8714076fc2fd93816750ab48e2c41de2cfd3"}, 533 | ] 534 | pathspec = [ 535 | {file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"}, 536 | {file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"}, 537 | ] 538 | platformdirs = [ 539 | {file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"}, 540 | {file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"}, 541 | ] 542 | pluggy = [ 543 | {file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"}, 544 | {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, 545 | ] 546 | py = [ 547 | {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, 548 | {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, 549 | ] 550 | pycodestyle = [ 551 | {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, 552 | {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, 553 | ] 554 | pyflakes = [ 555 | {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, 556 | {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, 557 | ] 558 | pylint = [ 559 | {file = "pylint-2.15.9-py3-none-any.whl", hash = "sha256:349c8cd36aede4d50a0754a8c0218b43323d13d5d88f4b2952ddfe3e169681eb"}, 560 | {file = "pylint-2.15.9.tar.gz", hash = "sha256:18783cca3cfee5b83c6c5d10b3cdb66c6594520ffae61890858fe8d932e1c6b4"}, 561 | ] 562 | pytest = [ 563 | {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, 564 | {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, 565 | ] 566 | pytest-forked = [ 567 | {file = "pytest-forked-1.4.0.tar.gz", hash = "sha256:8b67587c8f98cbbadfdd804539ed5455b6ed03802203485dd2f53c1422d7440e"}, 568 | {file = "pytest_forked-1.4.0-py3-none-any.whl", hash = "sha256:bbbb6717efc886b9d64537b41fb1497cfaf3c9601276be8da2cccfea5a3c8ad8"}, 569 | ] 570 | pytest-xdist = [ 571 | {file = "pytest-xdist-2.5.0.tar.gz", hash = "sha256:4580deca3ff04ddb2ac53eba39d76cb5dd5edeac050cb6fbc768b0dd712b4edf"}, 572 | {file = "pytest_xdist-2.5.0-py3-none-any.whl", hash = "sha256:6fe5c74fec98906deb8f2d2b616b5c782022744978e7bd4695d39c8f42d0ce65"}, 573 | ] 574 | pyupgrade = [ 575 | {file = "pyupgrade-3.3.1-py2.py3-none-any.whl", hash = "sha256:3b93641963df022d605c78aeae4b5956a5296ea24701eafaef9c487527b77e60"}, 576 | {file = "pyupgrade-3.3.1.tar.gz", hash = "sha256:f88bce38b0ba92c2a9a5063c8629e456e8d919b67d2d42c7ecab82ff196f9813"}, 577 | ] 578 | tokenize-rt = [ 579 | {file = "tokenize_rt-5.0.0-py2.py3-none-any.whl", hash = "sha256:c67772c662c6b3dc65edf66808577968fb10badfc2042e3027196bed4daf9e5a"}, 580 | {file = "tokenize_rt-5.0.0.tar.gz", hash = "sha256:3160bc0c3e8491312d0485171dea861fc160a240f5f5766b72a1165408d10740"}, 581 | ] 582 | toml = [ 583 | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, 584 | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, 585 | ] 586 | tomli = [ 587 | {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, 588 | {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, 589 | ] 590 | tomlkit = [ 591 | {file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"}, 592 | {file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"}, 593 | ] 594 | typing-extensions = [ 595 | {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, 596 | {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, 597 | ] 598 | wrapt = [ 599 | {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, 600 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, 601 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, 602 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, 603 | {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, 604 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, 605 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, 606 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, 607 | {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, 608 | {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, 609 | {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, 610 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, 611 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, 612 | {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, 613 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, 614 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, 615 | {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, 616 | {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, 617 | {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, 618 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, 619 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, 620 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, 621 | {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, 622 | {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, 623 | {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, 624 | {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, 625 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, 626 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, 627 | {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, 628 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, 629 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, 630 | {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, 631 | {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, 632 | {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, 633 | {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, 634 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, 635 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, 636 | {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, 637 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, 638 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, 639 | {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, 640 | {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, 641 | {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, 642 | {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, 643 | {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, 644 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, 645 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, 646 | {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, 647 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, 648 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, 649 | {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, 650 | {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, 651 | {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, 652 | {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, 653 | {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, 654 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, 655 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, 656 | {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, 657 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, 658 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, 659 | {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, 660 | {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, 661 | {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, 662 | {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, 663 | ] 664 | yapf = [ 665 | {file = "yapf-0.32.0-py2.py3-none-any.whl", hash = "sha256:8fea849025584e486fd06d6ba2bed717f396080fd3cc236ba10cb97c4c51cf32"}, 666 | {file = "yapf-0.32.0.tar.gz", hash = "sha256:a3f5085d37ef7e3e004c4ba9f9b3e40c54ff1901cd111f05145ae313a7c67d1b"}, 667 | ] 668 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "y" 3 | version = "0.1.0" 4 | description = "Top 25 Algorithms Every Programmer Should Know" 5 | authors = ["Pedro Lopez Mareque "] 6 | license = "MIT" 7 | readme = "README.md" 8 | 9 | [tool.poetry.dependencies] 10 | python = "^3.10" 11 | 12 | [tool.poetry.group.dev.dependencies] 13 | black = "^22.12.0" 14 | toml = "^0.10.2" 15 | mypy = "^0.971" 16 | flake8 = "^5.0.4" 17 | Flake8-pyproject = "^1.1.0" 18 | expects = "^0.9.0" 19 | pylint = "^2.15.2" 20 | pytest = "^7.1.3" 21 | pytest-xdist = "^2.5.0" 22 | pyupgrade = "^3.3.1" 23 | 24 | [tool.flake8] 25 | ignore= ["E501", "E124","E203", "W291", "W503", "W504", "E302", "E303"] 26 | 27 | [tool.pyright] 28 | venvPath="/home/pmareke/.cache/pypoetry/virtualenvs" 29 | venv="y-ELsKAsHX-py3.10" 30 | 31 | [build-system] 32 | requires = ["poetry-core"] 33 | build-backend = "poetry.core.masonry.api" 34 | -------------------------------------------------------------------------------- /scripts/get_input.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | get_input () { 4 | header="Cookie:$ADVENT_OF_CODE_COOKIE" 5 | 6 | curl --header $header https://adventofcode.com/2022/day/$1/input > "inputs/$1.in" 7 | } 8 | 9 | get_input $1 10 | -------------------------------------------------------------------------------- /scripts/hooks/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | exec < /dev/tty 5 | 6 | make pre-commit 7 | -------------------------------------------------------------------------------- /scripts/local-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | function main { 5 | install_git_hooks 6 | } 7 | 8 | function install_git_hooks { 9 | echo "Installing git hooks..." 10 | git config core.hooksPath scripts/hooks 11 | git config blame.ignoreRevsFile .git-blame-ignore-revs 12 | } 13 | 14 | main 15 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmareke/top-25-algorithms-every-programmer-should-know/a67f53a58c53026eeecc5b1248f3c5437864fa8f/src/__init__.py -------------------------------------------------------------------------------- /src/binary_search.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Generic 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # Given a sorted array of N integers and a target value, 7 | # determine if the target exists in the array in logarithmic 8 | # time using the binary search algorithm. 9 | # 10 | # If target exists in the array, print the index of it. 11 | # 12 | # Complexity: O(log N) -> log2(N) 13 | class BinarySearch(Generic[T]): 14 | @staticmethod 15 | def solve(stack: list[T], target: T) -> int: 16 | steps = 0 17 | left = 0 18 | right = len(stack) - 1 19 | while left <= right: 20 | steps += 1 21 | middle = int((left + right) / 2) 22 | if stack[middle] == target: 23 | return steps 24 | if stack[middle] > target: 25 | right = middle - 1 26 | if stack[middle] < target: 27 | left = middle + 1 28 | return steps 29 | -------------------------------------------------------------------------------- /src/boyer_moore.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Generic 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # BoyerMoore is an algorithm for finding the majority of a sequence. 7 | # 8 | # First it finds a majority element. 9 | # Second pass verify that the element found in the first pass really is a majority. 10 | # 11 | # Time Complexity: O(N). 12 | # Space Complexity: O(1). 13 | class BoyerMoore(Generic[T]): 14 | @staticmethod 15 | def solve(items: list[T]) -> T | None: 16 | candidate: T | None = None 17 | votes = 0 18 | for item in items: 19 | if not votes: 20 | candidate = item 21 | votes += 1 if item == candidate else -1 22 | 23 | count = sum(1 for i in range(len(items)) if items[i] == candidate) 24 | 25 | if count > len(items) // 2: 26 | return candidate 27 | return None 28 | -------------------------------------------------------------------------------- /src/breadth_first_search.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | from typing import Deque, TypeVar, Generic 3 | 4 | T = TypeVar("T", str, int) 5 | 6 | 7 | # Breadth–first search (BFS) is an algorithm for traversing or 8 | # searching tree or graph data structures. 9 | # 10 | # It starts at the tree root (or some arbitrary node of a graph, 11 | # sometimes referred to as a ‘search key’) and explores the 12 | # neighbor nodes first before moving to the next-level neighbors. 13 | # 14 | # Complexity: O(|V|+|E|) where V is a number of vertices in the graph 15 | # and E is a number of edges in the graph. 16 | class BreadthFirstSearch(Generic[T]): 17 | @staticmethod 18 | def solve(tree: dict[T, list[T]], root: T, target: T) -> int: 19 | queue: Deque[T] = deque() 20 | queue.append(root) 21 | visited = set() 22 | steps = 0 23 | while queue: 24 | steps += 1 25 | current = queue.popleft() 26 | if current == target: 27 | return steps 28 | visited.add(current) 29 | children = tree.get(current) 30 | if children: 31 | queue.extend([child for child in children if child not in visited]) 32 | return steps 33 | -------------------------------------------------------------------------------- /src/bubble_sort.py: -------------------------------------------------------------------------------- 1 | from typing import Generic, TypeVar 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # BubbleSort is an in-place comparison sorting algorithm. 7 | # 8 | # It repeatedly steps through the input list element by element, 9 | # comparing the current element with the one after it, 10 | # swapping their values if needed. 11 | # 12 | # Complexity: O(n^2). 13 | class BubbleSort(Generic[T]): 14 | def solve(self, items: list[T]) -> list[T]: 15 | size = len(items) 16 | swapped = False 17 | for idx in range(size - 1): 18 | for idy in range(0, size - idx - 1): 19 | if items[idy] > items[idy + 1]: 20 | swapped = True 21 | items[idy], items[idy + 1] = items[idy + 1], items[idy] 22 | if not swapped: 23 | return items 24 | return items 25 | -------------------------------------------------------------------------------- /src/counting_sort.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Generic 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # CountingSort is an integer sorting algorithm. 7 | # 8 | # It operates by counting the number of objects that possess 9 | # distinct key values, and applying prefix sum on those counts 10 | # to determine the positions of each key value in the output sequence. 11 | # 12 | # Complexity: O(n+k). 13 | class CountingSort(Generic[T]): 14 | MAX_RANGE = 256 15 | 16 | def solve(self, items: list[T]) -> list[T]: 17 | default_value = 0 if isinstance(items[0], int) else "" 18 | sorted_items = [default_value for _ in range(len(items))] 19 | count = [default_value for _ in range(self.MAX_RANGE)] 20 | 21 | for item in items: 22 | count[item] += 1 # type: ignore 23 | for index in range(self.MAX_RANGE): 24 | count[index] += count[index - 1] # type: ignore 25 | for item in items: 26 | sorted_items[count[item] - 1] = item # type: ignore 27 | count[item] -= 1 # type: ignore 28 | 29 | return sorted_items # type: ignore 30 | -------------------------------------------------------------------------------- /src/depth_first_search.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | from dataclasses import dataclass 3 | from typing import Deque, TypeVar, Generic 4 | 5 | T = TypeVar("T", str, int) 6 | 7 | 8 | # Depth-first search (DFS) is an algorithm for traversing or searching 9 | # tree or graph data structures. 10 | # 11 | # The algorithm starts at the root node (selecting some arbitrary node 12 | # as the root node in the case of a graph) and explores as far as 13 | # possible along each branch before backtracking. 14 | # 15 | # Complexity: O(|V|+|E|) where V is a number of vertices in the graph 16 | # and E is a number of edges in the graph. 17 | @dataclass 18 | class DepthFirstSearch(Generic[T]): 19 | tree: dict[T, list[T]] 20 | root: T 21 | target: T 22 | 23 | def solve(self) -> int: 24 | path = self._dfs(self.tree, self.root, self.target, []) 25 | return path.index(self.target) + 1 26 | 27 | def _dfs( 28 | self, tree: dict[T, list[T]], root: T, target: T, path: list[T] 29 | ) -> list[T]: 30 | queue: Deque[T] = deque() 31 | queue.append(root) 32 | path = [] 33 | while queue: 34 | current = queue.popleft() 35 | if current == target: 36 | path.append(current) 37 | return path 38 | path.append(current) 39 | children = tree.get(current) 40 | if children: 41 | for child in children: 42 | path.extend(self._dfs(tree, child, target, path)) 43 | return path 44 | -------------------------------------------------------------------------------- /src/djikstra.py: -------------------------------------------------------------------------------- 1 | # Dijkstra is an algorithm for finding the shortest 2 | # paths between nodes in a graph. 3 | # 4 | # For a given source node in the graph, 5 | # the algorithm finds the shortest path between that node 6 | # and every other. 7 | # 8 | # Complexity: (|V|+|E|)log2|V| where |V| is the number of nodes 9 | from collections import defaultdict 10 | from dataclasses import dataclass 11 | import math 12 | 13 | 14 | @dataclass 15 | class Item: 16 | distance: float 17 | neightbords: list[str] 18 | 19 | 20 | class Djikstra: 21 | @staticmethod 22 | def solve(graph: dict[str, dict[str, int]], source: str, target: str) -> int: 23 | solutions: dict[str, Item] = defaultdict() 24 | solutions[source] = Item(0, []) 25 | 26 | while True: 27 | parent: list[str] = [] 28 | nearest = "" 29 | distance = math.inf 30 | 31 | for solution in solutions.keys(): 32 | if not solutions[solution]: 33 | continue 34 | ndist = solutions[solution].distance 35 | neighbours = graph[solution] 36 | 37 | for neighbour in neighbours.keys(): 38 | if solutions.get(neighbour): 39 | continue 40 | 41 | new_distance = neighbours[neighbour] + ndist 42 | 43 | if new_distance < distance: 44 | parent = solutions[solution].neightbords 45 | nearest = neighbour 46 | distance = new_distance 47 | 48 | if distance == math.inf: 49 | break 50 | 51 | solutions[nearest] = Item(distance, [*parent, nearest]) 52 | 53 | return int(solutions[target].distance) 54 | -------------------------------------------------------------------------------- /src/euclid.py: -------------------------------------------------------------------------------- 1 | # Euclid It's an efficient method for finding the 2 | # GCD(Greatest Common Divisor) of two integers. 3 | # 4 | # Complexity: O(log(min(a, b)). 5 | class Euclid: 6 | def solve(self, first_number: int, second_number: int) -> int: 7 | if first_number == 0: 8 | return second_number 9 | return self.solve(second_number % first_number, first_number) 10 | -------------------------------------------------------------------------------- /src/heap_sort.py: -------------------------------------------------------------------------------- 1 | from typing import Generic, TypeVar 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # HeapSort is an in-place comparison sorting algorithm. 7 | # 8 | # It divides its input into a sorted and an unsorted region, 9 | # and it iteratively shrinks the unsorted region by extracting 10 | # the largest element from it and inserting it into the sorted region. 11 | # 12 | # Complexity: O(n * log(n)). 13 | class HeapSort(Generic[T]): 14 | def solve(self, items: list[T]) -> list[T]: 15 | size = len(items) 16 | index = (size - 2) // 2 17 | 18 | while index >= 0: 19 | self._heap(items, index, size) 20 | index -= 1 21 | 22 | while size: 23 | items[size - 1] = self._pop(items, size) 24 | size -= 1 25 | return items 26 | 27 | def _heap(self, items: list[T], index: int, size: int) -> None: 28 | left = self._left(index) 29 | right = self._right(index) 30 | largest = index 31 | if left < size and items[left] > items[index]: 32 | largest = left 33 | if right < size and items[right] > items[largest]: 34 | largest = right 35 | if largest != index: 36 | self._swap(items, index, largest) 37 | self._heap(items, largest, size) 38 | 39 | def _pop(self, items: list[T], size: int) -> T: 40 | top = items[0] 41 | items[0] = items[size - 1] 42 | self._heap(items, 0, size - 1) 43 | return top 44 | 45 | @staticmethod 46 | def _left(index: int) -> int: 47 | return 2 * index + 1 48 | 49 | @staticmethod 50 | def _right(index: int) -> int: 51 | return 2 * index + 2 52 | 53 | @staticmethod 54 | def _swap(items: list[T], idx: int, idy: int) -> None: 55 | temp = items[idx] 56 | items[idx] = items[idy] 57 | items[idy] = temp 58 | -------------------------------------------------------------------------------- /src/insert_sort.py: -------------------------------------------------------------------------------- 1 | from typing import Generic, TypeVar 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | # InsertSort is an in-place comparison sorting algorithm. 6 | # 7 | # At each array-position, it checks the value there against 8 | # the largest value in the sorted list. 9 | # 10 | # If larger, it leaves the element in place and moves to the next. 11 | # If smaller, it finds the correct position within the sorted list, 12 | # and inserts into that correct position. 13 | # 14 | # Complexity: O(n^2). 15 | 16 | 17 | class InsertSort(Generic[T]): 18 | def solve(self, items: list[T]) -> list[T]: 19 | size = len(items) 20 | for idx in range(1, size): 21 | key = items[idx] 22 | idy = idx - 1 23 | while idy >= 0 and key < items[idy]: 24 | items[idy + 1] = items[idy] 25 | idy -= 1 26 | items[idy + 1] = key 27 | return items 28 | -------------------------------------------------------------------------------- /src/merge_sort.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Generic 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | class MergeSort(Generic[T]): 7 | def solve(self, array: list[T] = []) -> list[T]: 8 | if len(array) <= 1: 9 | return array 10 | middle = int(len(array) / 2) 11 | left = array[:middle] 12 | right = array[middle:] 13 | return self._merge(self.solve(left), self.solve(right)) 14 | 15 | @staticmethod 16 | def _merge(left: list[T], right: list[T]) -> list[T]: 17 | result: list[T] = [] 18 | while left and right: 19 | if left[0] < right[0]: 20 | result.append(left.pop(0)) 21 | continue 22 | if left[0] >= right[0]: 23 | result.append(right.pop(0)) 24 | continue 25 | return [*result, *left, *right] # type: ignore 26 | -------------------------------------------------------------------------------- /src/quick_select.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Generic 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # QuickSelect is a selection algorithm. 7 | # 8 | # It is essentially the Quicksort Algorithm, 9 | # except that one only needs to recursively 10 | # call only one side of the partition to be re-partitioned. 11 | # 12 | # This changes the best case runtime from O(nlogn) to O(n). 13 | # 14 | # Complexity: O(n^2). 15 | class QuickSelect(Generic[T]): 16 | def solve(self, items: list[T], index: int) -> T: 17 | return self._quick_select(items, 0, len(items) - 1, index) 18 | 19 | def _quick_select(self, items: list[T], lidx: int, ridx: int, index: int) -> T: 20 | if ridx == lidx: 21 | return items[lidx] 22 | 23 | pivot_index = 0 24 | items[lidx], items[pivot_index] = items[pivot_index], items[lidx] 25 | new_ldix = lidx 26 | 27 | for idx in range(lidx + 1, ridx + 1): 28 | if items[idx] < items[lidx]: 29 | new_ldix += 1 30 | items[new_ldix], items[idx] = items[idx], items[new_ldix] 31 | 32 | items[new_ldix], items[lidx] = items[lidx], items[new_ldix] 33 | 34 | if index < new_ldix: 35 | return self._quick_select(items, lidx, new_ldix - 1, index) 36 | return self._quick_select(items, new_ldix + 1, ridx, index) 37 | -------------------------------------------------------------------------------- /src/quick_sort.py: -------------------------------------------------------------------------------- 1 | from typing import TypeVar, Generic 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # Quicksort is a divide-and-conquer algorithm. 7 | # 8 | # It works by selecting a 'pivot' element from the array 9 | # and partitioning the other elements into two sub-arrays, 10 | # according to whether they are less than or greater than the pivot. 11 | # 12 | # Complexity: O(n^2). 13 | class QuickSort(Generic[T]): 14 | def solve(self, array: list[T] = []) -> list[T]: 15 | if len(array) <= 1: 16 | return array 17 | pivot = array[0] 18 | left: list[T] = [] 19 | right: list[T] = [] 20 | for idx in range(1, len(array)): 21 | item = array[idx] 22 | if item < pivot: 23 | left.append(item) 24 | continue 25 | if item >= pivot: 26 | right.append(item) 27 | continue 28 | return [*self.solve(left), pivot, *self.solve(right)] 29 | -------------------------------------------------------------------------------- /src/select_sort.py: -------------------------------------------------------------------------------- 1 | from typing import Generic, TypeVar 2 | 3 | T = TypeVar("T", str, int) 4 | 5 | 6 | # SelectSort is an in-place comparison sorting algorithm. 7 | # 8 | # It works sorting an array by repeatedly finding the minimum element 9 | # and putting it at the beginning 10 | # 11 | # Complexity: O(n^2). 12 | class SelectSort(Generic[T]): 13 | def solve(self, items: list[T]) -> list[T]: 14 | size = len(items) 15 | for idx in range(size): 16 | min_index = idx 17 | for idy in range(idx + 1, size): 18 | if items[idy] < items[min_index]: 19 | min_index = idy 20 | items[idx], items[min_index] = items[min_index], items[idx] 21 | return items 22 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pmareke/top-25-algorithms-every-programmer-should-know/a67f53a58c53026eeecc5b1248f3c5437864fa8f/tests/__init__.py -------------------------------------------------------------------------------- /tests/test_binary_search.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | from expects import equal, expect 4 | 5 | from src.binary_search import BinarySearch 6 | 7 | 8 | class TestBinarySearch: 9 | def test_worst_scenario(self) -> None: 10 | stack = [chr(97 + index) for index in range(16)] 11 | 12 | steps = BinarySearch.solve(stack, "a") 13 | 14 | expected_steps = int(math.sqrt(len(stack))) 15 | expect(steps).to(equal(expected_steps)) 16 | 17 | def test_best_scenario(self) -> None: 18 | stack = list(range(16)) 19 | 20 | steps = BinarySearch.solve(stack, 7) 21 | 22 | expect(steps).to(equal(1)) 23 | 24 | def test_search_the_last_element_in_the_list(self) -> None: 25 | stack = [chr(97 + index) for index in range(16)] 26 | steps = BinarySearch.solve(stack, "p") 27 | print(stack) 28 | 29 | expect(steps).to(equal(5)) 30 | -------------------------------------------------------------------------------- /tests/test_boyer_moore.py: -------------------------------------------------------------------------------- 1 | from expects import be_none, equal, expect 2 | 3 | from src.boyer_moore import BoyerMoore 4 | 5 | 6 | class TestBoyerMooreSort: 7 | def test_find_the_mayority_number(self) -> None: 8 | array = [10, 5, 1, 3, 1, 10, 1, 1, 1, 1] 9 | boyer_moore = BoyerMoore() 10 | 11 | most_frequent = boyer_moore.solve(array) # type: ignore 12 | 13 | expect(most_frequent).to(equal(1)) 14 | 15 | def test_return_none_if_there_is_no_mayority(self) -> None: 16 | array = [1, 2, 3] 17 | boyer_moore = BoyerMoore() 18 | 19 | most_frequent = boyer_moore.solve(array) # type: ignore 20 | 21 | expect(most_frequent).to(be_none) 22 | 23 | def test_find_the_mayority_letter(self) -> None: 24 | array = ["z", "h", "z"] 25 | boyer_moore = BoyerMoore() 26 | 27 | most_frequent = boyer_moore.solve(array) 28 | 29 | expect(most_frequent).to(equal("z")) 30 | -------------------------------------------------------------------------------- /tests/test_breadth_first_search.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.breadth_first_search import BreadthFirstSearch 4 | 5 | 6 | class TestBreadthFirstSearch: 7 | def test_worst_scenario(self) -> None: 8 | tree = {1: [2, 3], 2: [4, 5], 3: [6, 7]} 9 | root = list(tree.keys())[0] 10 | path = BreadthFirstSearch.solve(tree, root, 7) 11 | 12 | expect(path).to(equal(7)) 13 | 14 | def test_best_scenario(self) -> None: 15 | tree = {"a": ["b", "c"], "b": ["d", "e"], "c": ["f", "g"]} 16 | root = list(tree.keys())[0] 17 | path = BreadthFirstSearch.solve(tree, root, "a") 18 | 19 | expect(path).to(equal(1)) 20 | 21 | def test_search_in_the_middle_of_the_tree(self) -> None: 22 | tree = {"a": ["b", "c"], "b": ["d", "e"], "c": ["f", "g"]} 23 | root = list(tree.keys())[0] 24 | path = BreadthFirstSearch.solve(tree, root, "e") 25 | 26 | expect(path).to(equal(5)) 27 | -------------------------------------------------------------------------------- /tests/test_bubble_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.bubble_sort import BubbleSort 4 | 5 | 6 | class TestBubbleSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | bubble_sort = BubbleSort() 10 | 11 | sorted_array = bubble_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | 15 | def test_sort_an_array_of_letters(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | bubble_sort = BubbleSort() 18 | 19 | sorted_array = bubble_sort.solve(array) 20 | 21 | expect(sorted_array).to(equal(["a", "f", "h", "x", "z"])) 22 | -------------------------------------------------------------------------------- /tests/test_counting_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.counting_sort import CountingSort 4 | 5 | 6 | class TestCountingSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | select_sort = CountingSort() 10 | 11 | sorted_array = select_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | -------------------------------------------------------------------------------- /tests/test_depth_first_search.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.depth_first_search import DepthFirstSearch 4 | 5 | 6 | class TestDepthFirstSearch: 7 | def test_worst_scenario(self) -> None: 8 | tree = {1: [2, 3], 2: [4, 5], 3: [6, 7]} 9 | root = list(tree.keys())[0] 10 | dfs = DepthFirstSearch(tree, root, 7) 11 | 12 | path = dfs.solve() 13 | 14 | expect(path).to(equal(7)) 15 | 16 | def test_best_scenario(self) -> None: 17 | tree = {"a": ["b", "c"], "b": ["d", "e"], "c": ["f", "g"]} 18 | root = list(tree.keys())[0] 19 | dfs = DepthFirstSearch(tree, root, "a") 20 | 21 | path = dfs.solve() 22 | 23 | expect(path).to(equal(1)) 24 | 25 | def test_search_in_the_middle_of_the_tree(self) -> None: 26 | tree = {"a": ["b", "c"], "b": ["d", "e"], "c": ["f", "g"]} 27 | root = list(tree.keys())[0] 28 | dfs = DepthFirstSearch(tree, root, "e") 29 | 30 | path = dfs.solve() 31 | 32 | expect(path).to(equal(4)) 33 | -------------------------------------------------------------------------------- /tests/test_dijkstra.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | import pytest 3 | 4 | from src.djikstra import Djikstra 5 | 6 | 7 | class TestDijkstra: 8 | @pytest.fixture 9 | def graph(self) -> dict[str, dict[str, int]]: 10 | return { 11 | "a": {"e": 1, "b": 1, "g": 3}, 12 | "b": {"a": 1, "c": 1}, 13 | "c": {"b": 1, "d": 1}, 14 | "d": {"c": 1, "e": 1}, 15 | "e": {"d": 1, "a": 1}, 16 | "f": {"g": 1, "h": 1}, 17 | "g": {"a": 3, "f": 1}, 18 | "h": {"f": 1}, 19 | } 20 | 21 | @pytest.mark.parametrize( 22 | "source,target,distance", 23 | [ 24 | ("h", "a", 5), 25 | ("a", "h", 5), 26 | ("c", "f", 6), 27 | ], 28 | ) 29 | def test_find_shortest_path( 30 | self, graph: dict[str, dict[str, int]], source: str, target: str, distance: int 31 | ) -> None: 32 | shortest_path = Djikstra.solve(graph, source, target) 33 | 34 | expect(shortest_path).to(equal(distance)) 35 | -------------------------------------------------------------------------------- /tests/test_euclid.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from expects import equal, expect 3 | from src.euclid import Euclid 4 | 5 | 6 | class TestEuclid: 7 | @pytest.mark.parametrize( 8 | "first_number,second_number,result", 9 | [ 10 | (10, 15, 5), 11 | (35, 10, 5), 12 | (31, 2, 1), 13 | ], 14 | ) 15 | def test_find_gcd(self, first_number: int, second_number: int, result: int) -> None: 16 | euclid = Euclid() 17 | gcd = euclid.solve(first_number, second_number) 18 | 19 | expect(gcd).to(equal(result)) 20 | -------------------------------------------------------------------------------- /tests/test_heap_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.heap_sort import HeapSort 4 | 5 | 6 | class TestHeapSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | heap_sort = HeapSort() 10 | 11 | sorted_array = heap_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | 15 | def test_sort_an_array_of_letters(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | heap_sort = HeapSort() 18 | 19 | sorted_array = heap_sort.solve(array) 20 | 21 | expect(sorted_array).to(equal(["a", "f", "h", "x", "z"])) 22 | -------------------------------------------------------------------------------- /tests/test_insert_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.insert_sort import InsertSort 4 | 5 | 6 | class TestInsertSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | insert_sort = InsertSort() 10 | 11 | sorted_array = insert_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | 15 | def test_sort_an_array_of_letters(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | insert_sort = InsertSort() 18 | 19 | sorted_array = insert_sort.solve(array) 20 | 21 | expect(sorted_array).to(equal(["a", "f", "h", "x", "z"])) 22 | -------------------------------------------------------------------------------- /tests/test_merge_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.merge_sort import MergeSort 4 | 5 | 6 | class TestMergeSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | merge_sort = MergeSort() 10 | 11 | sorted_array = merge_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | 15 | def test_sort_an_array_of_letters(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | merge_sort = MergeSort() 18 | 19 | sorted_array = merge_sort.solve(array) 20 | 21 | expect(sorted_array).to(equal(["a", "f", "h", "x", "z"])) 22 | -------------------------------------------------------------------------------- /tests/test_quick_select.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.quick_select import QuickSelect 4 | 5 | 6 | class TestQuickSelect: 7 | def test_sort_an_array_and_find_the_k_smallest_element(self) -> None: 8 | array = [10, 5, 1, 3] 9 | quick_select = QuickSelect() 10 | 11 | index = quick_select.solve(array, 2) # type: ignore 12 | 13 | expect(index).to(equal(5)) 14 | 15 | def test_sort_an_array_of_letters_and_find_the_k_smallest_element(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | quick_select = QuickSelect() 18 | 19 | index = quick_select.solve(array, 0) 20 | 21 | expect(index).to(equal("a")) 22 | -------------------------------------------------------------------------------- /tests/test_quick_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.quick_sort import QuickSort 4 | 5 | 6 | class TestQuickSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | quick_sort = QuickSort() 10 | 11 | sorted_array = quick_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | 15 | def test_sort_an_array_of_letters(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | quick_sort = QuickSort() 18 | 19 | sorted_array = quick_sort.solve(array) 20 | 21 | expect(sorted_array).to(equal(["a", "f", "h", "x", "z"])) 22 | -------------------------------------------------------------------------------- /tests/test_select_sort.py: -------------------------------------------------------------------------------- 1 | from expects import equal, expect 2 | 3 | from src.select_sort import SelectSort 4 | 5 | 6 | class TestSelectSort: 7 | def test_sort_an_array(self) -> None: 8 | array = [10, 5, 1, 3] 9 | select_sort = SelectSort() 10 | 11 | sorted_array = select_sort.solve(array) # type: ignore 12 | 13 | expect(sorted_array).to(equal([1, 3, 5, 10])) 14 | 15 | def test_sort_an_array_of_letters(self) -> None: 16 | array = ["z", "h", "a", "f", "x"] 17 | select_sort = SelectSort() 18 | 19 | sorted_array = select_sort.solve(array) 20 | 21 | expect(sorted_array).to(equal(["a", "f", "h", "x", "z"])) 22 | --------------------------------------------------------------------------------