mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-25 10:28:39 +00:00
Merge branch 'master' into split_workload
This commit is contained in:
commit
2952ae8ac1
@ -1,4 +0,0 @@
|
|||||||
[report]
|
|
||||||
sort = Cover
|
|
||||||
omit =
|
|
||||||
.env/*
|
|
6
.github/CODEOWNERS
vendored
6
.github/CODEOWNERS
vendored
@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
# /divide_and_conquer/
|
# /divide_and_conquer/
|
||||||
|
|
||||||
/dynamic_programming/ @Kush1101
|
# /dynamic_programming/
|
||||||
|
|
||||||
# /file_transfer/
|
# /file_transfer/
|
||||||
|
|
||||||
@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
# /machine_learning/
|
# /machine_learning/
|
||||||
|
|
||||||
/maths/ @Kush1101
|
# /maths/
|
||||||
|
|
||||||
# /matrix/
|
# /matrix/
|
||||||
|
|
||||||
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
# /other/ @cclauss # TODO: Uncomment this line after Hacktoberfest
|
# /other/ @cclauss # TODO: Uncomment this line after Hacktoberfest
|
||||||
|
|
||||||
/project_euler/ @dhruvmanila @Kush1101
|
/project_euler/ @dhruvmanila
|
||||||
|
|
||||||
# /quantum/
|
# /quantum/
|
||||||
|
|
||||||
|
7
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
7
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -17,10 +17,3 @@ body:
|
|||||||
implementations.
|
implementations.
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Would you like to work on this feature?
|
|
||||||
options:
|
|
||||||
- label: Yes, I want to work on this feature!
|
|
||||||
required: false
|
|
||||||
|
19
.github/ISSUE_TEMPLATE/other.yml
vendored
Normal file
19
.github/ISSUE_TEMPLATE/other.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name: Other
|
||||||
|
description: Use this for any other issues. PLEASE do not create blank issues
|
||||||
|
labels: ["awaiting triage"]
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
id: issuedescription
|
||||||
|
attributes:
|
||||||
|
label: What would you like to share?
|
||||||
|
description: Provide a clear and concise explanation of your issue.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: extrainfo
|
||||||
|
attributes:
|
||||||
|
label: Additional information
|
||||||
|
description: Is there anything else we should know about this issue?
|
||||||
|
validations:
|
||||||
|
required: false
|
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@ -16,5 +16,5 @@
|
|||||||
* [ ] All functions and variable names follow Python naming conventions.
|
* [ ] All functions and variable names follow Python naming conventions.
|
||||||
* [ ] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html).
|
* [ ] All function parameters and return values are annotated with Python [type hints](https://docs.python.org/3/library/typing.html).
|
||||||
* [ ] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing.
|
* [ ] All functions have [doctests](https://docs.python.org/3/library/doctest.html) that pass the automated testing.
|
||||||
* [ ] All new algorithms have a URL in its comments that points to Wikipedia or other similar explanation.
|
* [ ] All new algorithms include at least one URL that points to Wikipedia or another similar explanation.
|
||||||
* [ ] If this pull request resolves one or more open issues then the commit message contains `Fixes: #{$ISSUE_NO}`.
|
* [ ] If this pull request resolves one or more open issues then the description above includes the issue number(s) with a [closing keyword](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue): "Fixes #ISSUE-NUMBER".
|
||||||
|
4
.github/stale.yml
vendored
4
.github/stale.yml
vendored
@ -45,7 +45,7 @@ pulls:
|
|||||||
closeComment: >
|
closeComment: >
|
||||||
Please reopen this pull request once you commit the changes requested
|
Please reopen this pull request once you commit the changes requested
|
||||||
or make improvements on the code. If this is not the case and you need
|
or make improvements on the code. If this is not the case and you need
|
||||||
some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms)
|
some help, feel free to seek help from our [Gitter](https://gitter.im/TheAlgorithms/community)
|
||||||
or ping one of the reviewers. Thank you for your contributions!
|
or ping one of the reviewers. Thank you for your contributions!
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
@ -59,5 +59,5 @@ issues:
|
|||||||
closeComment: >
|
closeComment: >
|
||||||
Please reopen this issue once you add more information and updates here.
|
Please reopen this issue once you add more information and updates here.
|
||||||
If this is not the case and you need some help, feel free to seek help
|
If this is not the case and you need some help, feel free to seek help
|
||||||
from our [Gitter](https://gitter.im/TheAlgorithms) or ping one of the
|
from our [Gitter](https://gitter.im/TheAlgorithms/community) or ping one of the
|
||||||
reviewers. Thank you for your contributions!
|
reviewers. Thank you for your contributions!
|
||||||
|
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-python@v4
|
- uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.x
|
python-version: 3.11
|
||||||
- uses: actions/cache@v3
|
- uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
path: ~/.cache/pip
|
||||||
@ -22,6 +22,12 @@ jobs:
|
|||||||
python -m pip install --upgrade pip setuptools six wheel
|
python -m pip install --upgrade pip setuptools six wheel
|
||||||
python -m pip install pytest-cov -r requirements.txt
|
python -m pip install pytest-cov -r requirements.txt
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. .
|
# TODO: #8818 Re-enable quantum tests
|
||||||
|
run: pytest
|
||||||
|
--ignore=quantum/q_fourier_transform.py
|
||||||
|
--ignore=project_euler/
|
||||||
|
--ignore=scripts/validate_solutions.py
|
||||||
|
--cov-report=term-missing:skip-covered
|
||||||
|
--cov=. .
|
||||||
- if: ${{ success() }}
|
- if: ${{ success() }}
|
||||||
run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md
|
run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md
|
||||||
|
16
.github/workflows/ruff.yml
vendored
Normal file
16
.github/workflows/ruff.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# https://beta.ruff.rs
|
||||||
|
name: ruff
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
ruff:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: pip install --user ruff
|
||||||
|
- run: ruff --format=github .
|
@ -1,69 +1,41 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.3.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-executables-have-shebangs
|
- id: check-executables-have-shebangs
|
||||||
|
- id: check-toml
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
types: [python]
|
types: [python]
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
exclude: |
|
|
||||||
(?x)^(
|
|
||||||
data_structures/heap/binomial_heap.py
|
|
||||||
)$
|
|
||||||
- id: requirements-txt-fixer
|
- id: requirements-txt-fixer
|
||||||
|
|
||||||
|
- repo: https://github.com/MarcoGorelli/auto-walrus
|
||||||
|
rev: v0.2.2
|
||||||
|
hooks:
|
||||||
|
- id: auto-walrus
|
||||||
|
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.0.277
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.8.0
|
rev: 23.3.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/isort
|
|
||||||
rev: 5.10.1
|
|
||||||
hooks:
|
|
||||||
- id: isort
|
|
||||||
args:
|
|
||||||
- --profile=black
|
|
||||||
|
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
|
||||||
rev: v2.38.2
|
|
||||||
hooks:
|
|
||||||
- id: pyupgrade
|
|
||||||
args:
|
|
||||||
- --py310-plus
|
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/flake8
|
|
||||||
rev: 5.0.4
|
|
||||||
hooks:
|
|
||||||
- id: flake8
|
|
||||||
args:
|
|
||||||
- --ignore=E203,W503
|
|
||||||
- --max-complexity=25
|
|
||||||
- --max-line-length=88
|
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
||||||
rev: v0.981
|
|
||||||
hooks:
|
|
||||||
- id: mypy
|
|
||||||
args:
|
|
||||||
- --ignore-missing-imports
|
|
||||||
- --install-types # See mirrors-mypy README.md
|
|
||||||
- --non-interactive
|
|
||||||
additional_dependencies: [types-requests]
|
|
||||||
|
|
||||||
- repo: https://github.com/codespell-project/codespell
|
- repo: https://github.com/codespell-project/codespell
|
||||||
rev: v2.2.1
|
rev: v2.2.5
|
||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
args:
|
additional_dependencies:
|
||||||
- --ignore-words-list=ans,crate,damon,fo,followings,hist,iff,mater,secant,som,sur,tim,zar
|
- tomli
|
||||||
- --skip="./.*,./strings/dictionary.txt,./strings/words.txt,./project_euler/problem_022/p022_names.txt"
|
|
||||||
exclude: |
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||||
(?x)^(
|
rev: "0.13.0"
|
||||||
strings/dictionary.txt |
|
hooks:
|
||||||
strings/words.txt |
|
- id: pyproject-fmt
|
||||||
project_euler/problem_022/p022_names.txt
|
|
||||||
)$
|
|
||||||
|
|
||||||
- repo: local
|
- repo: local
|
||||||
hooks:
|
hooks:
|
||||||
@ -72,3 +44,18 @@ repos:
|
|||||||
entry: ./scripts/validate_filenames.py
|
entry: ./scripts/validate_filenames.py
|
||||||
language: script
|
language: script
|
||||||
pass_filenames: false
|
pass_filenames: false
|
||||||
|
|
||||||
|
- repo: https://github.com/abravalheri/validate-pyproject
|
||||||
|
rev: v0.13
|
||||||
|
hooks:
|
||||||
|
- id: validate-pyproject
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
|
rev: v1.4.1
|
||||||
|
hooks:
|
||||||
|
- id: mypy
|
||||||
|
args:
|
||||||
|
- --ignore-missing-imports
|
||||||
|
- --install-types # See mirrors-mypy README.md
|
||||||
|
- --non-interactive
|
||||||
|
additional_dependencies: [types-requests]
|
||||||
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"githubPullRequests.ignoredPullRequestBranches": [
|
||||||
|
"master"
|
||||||
|
]
|
||||||
|
}
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
## Before contributing
|
## Before contributing
|
||||||
|
|
||||||
Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms).
|
Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Before sending your pull requests, make sure that you __read the whole guidelines__. If you have any doubt on the contributing guide, please feel free to [state it clearly in an issue](https://github.com/TheAlgorithms/Python/issues/new) or ask the community in [Gitter](https://gitter.im/TheAlgorithms/community).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
### Contributor
|
### Contributor
|
||||||
|
|
||||||
We are very happy that you consider implementing algorithms and data structures for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that:
|
We are very happy that you are considering implementing algorithms and data structures for others! This repository is referenced and used by learners from all over the globe. Being one of our contributors, you agree and confirm that:
|
||||||
|
|
||||||
- You did your work - no plagiarism allowed
|
- You did your work - no plagiarism allowed
|
||||||
- Any plagiarized work will not be merged.
|
- Any plagiarized work will not be merged.
|
||||||
@ -25,7 +25,12 @@ We appreciate any contribution, from fixing a grammar mistake in a comment to im
|
|||||||
|
|
||||||
Your contribution will be tested by our [automated testing on GitHub Actions](https://github.com/TheAlgorithms/Python/actions) to save time and mental energy. After you have submitted your pull request, you should see the GitHub Actions tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the GitHub Actions output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help.
|
Your contribution will be tested by our [automated testing on GitHub Actions](https://github.com/TheAlgorithms/Python/actions) to save time and mental energy. After you have submitted your pull request, you should see the GitHub Actions tests start to run at the bottom of your submission page. If those tests fail, then click on the ___details___ button try to read through the GitHub Actions output to understand the failure. If you do not understand, please leave a comment on your submission page and a community member will try to help.
|
||||||
|
|
||||||
Please help us keep our issue list small by adding fixes: #{$ISSUE_NO} to the commit message of pull requests that resolve open issues. GitHub will use this tag to auto-close the issue when the PR is merged.
|
Please help us keep our issue list small by adding `Fixes #{$ISSUE_NUMBER}` to the description of pull requests that resolve open issues.
|
||||||
|
For example, if your pull request fixes issue #10, then please add the following to its description:
|
||||||
|
```
|
||||||
|
Fixes #10
|
||||||
|
```
|
||||||
|
GitHub will use this tag to [auto-close the issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) if and when the PR is merged.
|
||||||
|
|
||||||
#### What is an Algorithm?
|
#### What is an Algorithm?
|
||||||
|
|
||||||
@ -66,7 +71,7 @@ pre-commit run --all-files --show-diff-on-failure
|
|||||||
|
|
||||||
We want your work to be readable by others; therefore, we encourage you to note the following:
|
We want your work to be readable by others; therefore, we encourage you to note the following:
|
||||||
|
|
||||||
- Please write in Python 3.9+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will.
|
- Please write in Python 3.11+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will.
|
||||||
- Please focus hard on the naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments.
|
- Please focus hard on the naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments.
|
||||||
- Single letter variable names are *old school* so please avoid them unless their life only spans a few lines.
|
- Single letter variable names are *old school* so please avoid them unless their life only spans a few lines.
|
||||||
- Expand acronyms because `gcd()` is hard to understand but `greatest_common_divisor()` is not.
|
- Expand acronyms because `gcd()` is hard to understand but `greatest_common_divisor()` is not.
|
||||||
@ -81,11 +86,11 @@ We want your work to be readable by others; therefore, we encourage you to note
|
|||||||
black .
|
black .
|
||||||
```
|
```
|
||||||
|
|
||||||
- All submissions will need to pass the test `flake8 . --ignore=E203,W503 --max-line-length=88` before they will be accepted so if possible, try this test locally on your Python file(s) before submitting your pull request.
|
- All submissions will need to pass the test `ruff .` before they will be accepted so if possible, try this test locally on your Python file(s) before submitting your pull request.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 -m pip install flake8 # only required the first time
|
python3 -m pip install ruff # only required the first time
|
||||||
flake8 . --ignore=E203,W503 --max-line-length=88 --show-source
|
ruff .
|
||||||
```
|
```
|
||||||
|
|
||||||
- Original code submission require docstrings or comments to describe your work.
|
- Original code submission require docstrings or comments to describe your work.
|
||||||
@ -176,7 +181,7 @@ We want your work to be readable by others; therefore, we encourage you to note
|
|||||||
|
|
||||||
- Most importantly,
|
- Most importantly,
|
||||||
- __Be consistent in the use of these guidelines when submitting.__
|
- __Be consistent in the use of these guidelines when submitting.__
|
||||||
- __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms) __now!__
|
- __Join__ us on [Discord](https://discord.com/invite/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community) __now!__
|
||||||
- Happy coding!
|
- Happy coding!
|
||||||
|
|
||||||
Writer [@poyea](https://github.com/poyea), Jun 2019.
|
Writer [@poyea](https://github.com/poyea), Jun 2019.
|
||||||
|
209
DIRECTORY.md
209
DIRECTORY.md
@ -22,14 +22,18 @@
|
|||||||
* [All Permutations](backtracking/all_permutations.py)
|
* [All Permutations](backtracking/all_permutations.py)
|
||||||
* [All Subsequences](backtracking/all_subsequences.py)
|
* [All Subsequences](backtracking/all_subsequences.py)
|
||||||
* [Coloring](backtracking/coloring.py)
|
* [Coloring](backtracking/coloring.py)
|
||||||
|
* [Combination Sum](backtracking/combination_sum.py)
|
||||||
* [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py)
|
* [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py)
|
||||||
* [Knight Tour](backtracking/knight_tour.py)
|
* [Knight Tour](backtracking/knight_tour.py)
|
||||||
* [Minimax](backtracking/minimax.py)
|
* [Minimax](backtracking/minimax.py)
|
||||||
|
* [Minmax](backtracking/minmax.py)
|
||||||
* [N Queens](backtracking/n_queens.py)
|
* [N Queens](backtracking/n_queens.py)
|
||||||
* [N Queens Math](backtracking/n_queens_math.py)
|
* [N Queens Math](backtracking/n_queens_math.py)
|
||||||
|
* [Power Sum](backtracking/power_sum.py)
|
||||||
* [Rat In Maze](backtracking/rat_in_maze.py)
|
* [Rat In Maze](backtracking/rat_in_maze.py)
|
||||||
* [Sudoku](backtracking/sudoku.py)
|
* [Sudoku](backtracking/sudoku.py)
|
||||||
* [Sum Of Subsets](backtracking/sum_of_subsets.py)
|
* [Sum Of Subsets](backtracking/sum_of_subsets.py)
|
||||||
|
* [Word Search](backtracking/word_search.py)
|
||||||
|
|
||||||
## Bit Manipulation
|
## Bit Manipulation
|
||||||
* [Binary And Operator](bit_manipulation/binary_and_operator.py)
|
* [Binary And Operator](bit_manipulation/binary_and_operator.py)
|
||||||
@ -42,6 +46,11 @@
|
|||||||
* [Count 1S Brian Kernighan Method](bit_manipulation/count_1s_brian_kernighan_method.py)
|
* [Count 1S Brian Kernighan Method](bit_manipulation/count_1s_brian_kernighan_method.py)
|
||||||
* [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py)
|
* [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py)
|
||||||
* [Gray Code Sequence](bit_manipulation/gray_code_sequence.py)
|
* [Gray Code Sequence](bit_manipulation/gray_code_sequence.py)
|
||||||
|
* [Highest Set Bit](bit_manipulation/highest_set_bit.py)
|
||||||
|
* [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py)
|
||||||
|
* [Is Even](bit_manipulation/is_even.py)
|
||||||
|
* [Is Power Of Two](bit_manipulation/is_power_of_two.py)
|
||||||
|
* [Numbers Different Signs](bit_manipulation/numbers_different_signs.py)
|
||||||
* [Reverse Bits](bit_manipulation/reverse_bits.py)
|
* [Reverse Bits](bit_manipulation/reverse_bits.py)
|
||||||
* [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py)
|
* [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py)
|
||||||
|
|
||||||
@ -51,7 +60,14 @@
|
|||||||
* [Modular Division](blockchain/modular_division.py)
|
* [Modular Division](blockchain/modular_division.py)
|
||||||
|
|
||||||
## Boolean Algebra
|
## Boolean Algebra
|
||||||
|
* [And Gate](boolean_algebra/and_gate.py)
|
||||||
|
* [Nand Gate](boolean_algebra/nand_gate.py)
|
||||||
|
* [Norgate](boolean_algebra/norgate.py)
|
||||||
|
* [Not Gate](boolean_algebra/not_gate.py)
|
||||||
|
* [Or Gate](boolean_algebra/or_gate.py)
|
||||||
* [Quine Mc Cluskey](boolean_algebra/quine_mc_cluskey.py)
|
* [Quine Mc Cluskey](boolean_algebra/quine_mc_cluskey.py)
|
||||||
|
* [Xnor Gate](boolean_algebra/xnor_gate.py)
|
||||||
|
* [Xor Gate](boolean_algebra/xor_gate.py)
|
||||||
|
|
||||||
## Cellular Automata
|
## Cellular Automata
|
||||||
* [Conways Game Of Life](cellular_automata/conways_game_of_life.py)
|
* [Conways Game Of Life](cellular_automata/conways_game_of_life.py)
|
||||||
@ -63,6 +79,7 @@
|
|||||||
* [A1Z26](ciphers/a1z26.py)
|
* [A1Z26](ciphers/a1z26.py)
|
||||||
* [Affine Cipher](ciphers/affine_cipher.py)
|
* [Affine Cipher](ciphers/affine_cipher.py)
|
||||||
* [Atbash](ciphers/atbash.py)
|
* [Atbash](ciphers/atbash.py)
|
||||||
|
* [Autokey](ciphers/autokey.py)
|
||||||
* [Baconian Cipher](ciphers/baconian_cipher.py)
|
* [Baconian Cipher](ciphers/baconian_cipher.py)
|
||||||
* [Base16](ciphers/base16.py)
|
* [Base16](ciphers/base16.py)
|
||||||
* [Base32](ciphers/base32.py)
|
* [Base32](ciphers/base32.py)
|
||||||
@ -107,6 +124,7 @@
|
|||||||
* [Huffman](compression/huffman.py)
|
* [Huffman](compression/huffman.py)
|
||||||
* [Lempel Ziv](compression/lempel_ziv.py)
|
* [Lempel Ziv](compression/lempel_ziv.py)
|
||||||
* [Lempel Ziv Decompress](compression/lempel_ziv_decompress.py)
|
* [Lempel Ziv Decompress](compression/lempel_ziv_decompress.py)
|
||||||
|
* [Lz77](compression/lz77.py)
|
||||||
* [Peak Signal To Noise Ratio](compression/peak_signal_to_noise_ratio.py)
|
* [Peak Signal To Noise Ratio](compression/peak_signal_to_noise_ratio.py)
|
||||||
* [Run Length Encoding](compression/run_length_encoding.py)
|
* [Run Length Encoding](compression/run_length_encoding.py)
|
||||||
|
|
||||||
@ -120,6 +138,7 @@
|
|||||||
* [Pooling Functions](computer_vision/pooling_functions.py)
|
* [Pooling Functions](computer_vision/pooling_functions.py)
|
||||||
|
|
||||||
## Conversions
|
## Conversions
|
||||||
|
* [Astronomical Length Scale Conversion](conversions/astronomical_length_scale_conversion.py)
|
||||||
* [Binary To Decimal](conversions/binary_to_decimal.py)
|
* [Binary To Decimal](conversions/binary_to_decimal.py)
|
||||||
* [Binary To Hexadecimal](conversions/binary_to_hexadecimal.py)
|
* [Binary To Hexadecimal](conversions/binary_to_hexadecimal.py)
|
||||||
* [Binary To Octal](conversions/binary_to_octal.py)
|
* [Binary To Octal](conversions/binary_to_octal.py)
|
||||||
@ -128,6 +147,7 @@
|
|||||||
* [Decimal To Binary Recursion](conversions/decimal_to_binary_recursion.py)
|
* [Decimal To Binary Recursion](conversions/decimal_to_binary_recursion.py)
|
||||||
* [Decimal To Hexadecimal](conversions/decimal_to_hexadecimal.py)
|
* [Decimal To Hexadecimal](conversions/decimal_to_hexadecimal.py)
|
||||||
* [Decimal To Octal](conversions/decimal_to_octal.py)
|
* [Decimal To Octal](conversions/decimal_to_octal.py)
|
||||||
|
* [Energy Conversions](conversions/energy_conversions.py)
|
||||||
* [Excel Title To Column](conversions/excel_title_to_column.py)
|
* [Excel Title To Column](conversions/excel_title_to_column.py)
|
||||||
* [Hex To Bin](conversions/hex_to_bin.py)
|
* [Hex To Bin](conversions/hex_to_bin.py)
|
||||||
* [Hexadecimal To Decimal](conversions/hexadecimal_to_decimal.py)
|
* [Hexadecimal To Decimal](conversions/hexadecimal_to_decimal.py)
|
||||||
@ -139,19 +159,30 @@
|
|||||||
* [Pressure Conversions](conversions/pressure_conversions.py)
|
* [Pressure Conversions](conversions/pressure_conversions.py)
|
||||||
* [Rgb Hsv Conversion](conversions/rgb_hsv_conversion.py)
|
* [Rgb Hsv Conversion](conversions/rgb_hsv_conversion.py)
|
||||||
* [Roman Numerals](conversions/roman_numerals.py)
|
* [Roman Numerals](conversions/roman_numerals.py)
|
||||||
|
* [Speed Conversions](conversions/speed_conversions.py)
|
||||||
* [Temperature Conversions](conversions/temperature_conversions.py)
|
* [Temperature Conversions](conversions/temperature_conversions.py)
|
||||||
* [Volume Conversions](conversions/volume_conversions.py)
|
* [Volume Conversions](conversions/volume_conversions.py)
|
||||||
* [Weight Conversion](conversions/weight_conversion.py)
|
* [Weight Conversion](conversions/weight_conversion.py)
|
||||||
|
|
||||||
## Data Structures
|
## Data Structures
|
||||||
|
* Arrays
|
||||||
|
* [Permutations](data_structures/arrays/permutations.py)
|
||||||
|
* [Prefix Sum](data_structures/arrays/prefix_sum.py)
|
||||||
|
* [Product Sum](data_structures/arrays/product_sum.py)
|
||||||
* Binary Tree
|
* Binary Tree
|
||||||
* [Avl Tree](data_structures/binary_tree/avl_tree.py)
|
* [Avl Tree](data_structures/binary_tree/avl_tree.py)
|
||||||
* [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py)
|
* [Basic Binary Tree](data_structures/binary_tree/basic_binary_tree.py)
|
||||||
* [Binary Search Tree](data_structures/binary_tree/binary_search_tree.py)
|
* [Binary Search Tree](data_structures/binary_tree/binary_search_tree.py)
|
||||||
* [Binary Search Tree Recursive](data_structures/binary_tree/binary_search_tree_recursive.py)
|
* [Binary Search Tree Recursive](data_structures/binary_tree/binary_search_tree_recursive.py)
|
||||||
* [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py)
|
* [Binary Tree Mirror](data_structures/binary_tree/binary_tree_mirror.py)
|
||||||
|
* [Binary Tree Node Sum](data_structures/binary_tree/binary_tree_node_sum.py)
|
||||||
|
* [Binary Tree Path Sum](data_structures/binary_tree/binary_tree_path_sum.py)
|
||||||
* [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py)
|
* [Binary Tree Traversals](data_structures/binary_tree/binary_tree_traversals.py)
|
||||||
|
* [Diff Views Of Binary Tree](data_structures/binary_tree/diff_views_of_binary_tree.py)
|
||||||
|
* [Distribute Coins](data_structures/binary_tree/distribute_coins.py)
|
||||||
* [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py)
|
* [Fenwick Tree](data_structures/binary_tree/fenwick_tree.py)
|
||||||
|
* [Inorder Tree Traversal 2022](data_structures/binary_tree/inorder_tree_traversal_2022.py)
|
||||||
|
* [Is Bst](data_structures/binary_tree/is_bst.py)
|
||||||
* [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py)
|
* [Lazy Segment Tree](data_structures/binary_tree/lazy_segment_tree.py)
|
||||||
* [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py)
|
* [Lowest Common Ancestor](data_structures/binary_tree/lowest_common_ancestor.py)
|
||||||
* [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py)
|
* [Maximum Fenwick Tree](data_structures/binary_tree/maximum_fenwick_tree.py)
|
||||||
@ -167,12 +198,16 @@
|
|||||||
* [Alternate Disjoint Set](data_structures/disjoint_set/alternate_disjoint_set.py)
|
* [Alternate Disjoint Set](data_structures/disjoint_set/alternate_disjoint_set.py)
|
||||||
* [Disjoint Set](data_structures/disjoint_set/disjoint_set.py)
|
* [Disjoint Set](data_structures/disjoint_set/disjoint_set.py)
|
||||||
* Hashing
|
* Hashing
|
||||||
|
* [Bloom Filter](data_structures/hashing/bloom_filter.py)
|
||||||
* [Double Hash](data_structures/hashing/double_hash.py)
|
* [Double Hash](data_structures/hashing/double_hash.py)
|
||||||
|
* [Hash Map](data_structures/hashing/hash_map.py)
|
||||||
* [Hash Table](data_structures/hashing/hash_table.py)
|
* [Hash Table](data_structures/hashing/hash_table.py)
|
||||||
* [Hash Table With Linked List](data_structures/hashing/hash_table_with_linked_list.py)
|
* [Hash Table With Linked List](data_structures/hashing/hash_table_with_linked_list.py)
|
||||||
* Number Theory
|
* Number Theory
|
||||||
* [Prime Numbers](data_structures/hashing/number_theory/prime_numbers.py)
|
* [Prime Numbers](data_structures/hashing/number_theory/prime_numbers.py)
|
||||||
* [Quadratic Probing](data_structures/hashing/quadratic_probing.py)
|
* [Quadratic Probing](data_structures/hashing/quadratic_probing.py)
|
||||||
|
* Tests
|
||||||
|
* [Test Hash Map](data_structures/hashing/tests/test_hash_map.py)
|
||||||
* Heap
|
* Heap
|
||||||
* [Binomial Heap](data_structures/heap/binomial_heap.py)
|
* [Binomial Heap](data_structures/heap/binomial_heap.py)
|
||||||
* [Heap](data_structures/heap/heap.py)
|
* [Heap](data_structures/heap/heap.py)
|
||||||
@ -201,6 +236,7 @@
|
|||||||
* [Double Ended Queue](data_structures/queue/double_ended_queue.py)
|
* [Double Ended Queue](data_structures/queue/double_ended_queue.py)
|
||||||
* [Linked Queue](data_structures/queue/linked_queue.py)
|
* [Linked Queue](data_structures/queue/linked_queue.py)
|
||||||
* [Priority Queue Using List](data_structures/queue/priority_queue_using_list.py)
|
* [Priority Queue Using List](data_structures/queue/priority_queue_using_list.py)
|
||||||
|
* [Queue By Two Stacks](data_structures/queue/queue_by_two_stacks.py)
|
||||||
* [Queue On List](data_structures/queue/queue_on_list.py)
|
* [Queue On List](data_structures/queue/queue_on_list.py)
|
||||||
* [Queue On Pseudo Stack](data_structures/queue/queue_on_pseudo_stack.py)
|
* [Queue On Pseudo Stack](data_structures/queue/queue_on_pseudo_stack.py)
|
||||||
* Stacks
|
* Stacks
|
||||||
@ -217,6 +253,7 @@
|
|||||||
* [Stack With Singly Linked List](data_structures/stacks/stack_with_singly_linked_list.py)
|
* [Stack With Singly Linked List](data_structures/stacks/stack_with_singly_linked_list.py)
|
||||||
* [Stock Span Problem](data_structures/stacks/stock_span_problem.py)
|
* [Stock Span Problem](data_structures/stacks/stock_span_problem.py)
|
||||||
* Trie
|
* Trie
|
||||||
|
* [Radix Tree](data_structures/trie/radix_tree.py)
|
||||||
* [Trie](data_structures/trie/trie.py)
|
* [Trie](data_structures/trie/trie.py)
|
||||||
|
|
||||||
## Digital Image Processing
|
## Digital Image Processing
|
||||||
@ -256,7 +293,7 @@
|
|||||||
* [Inversions](divide_and_conquer/inversions.py)
|
* [Inversions](divide_and_conquer/inversions.py)
|
||||||
* [Kth Order Statistic](divide_and_conquer/kth_order_statistic.py)
|
* [Kth Order Statistic](divide_and_conquer/kth_order_statistic.py)
|
||||||
* [Max Difference Pair](divide_and_conquer/max_difference_pair.py)
|
* [Max Difference Pair](divide_and_conquer/max_difference_pair.py)
|
||||||
* [Max Subarray Sum](divide_and_conquer/max_subarray_sum.py)
|
* [Max Subarray](divide_and_conquer/max_subarray.py)
|
||||||
* [Mergesort](divide_and_conquer/mergesort.py)
|
* [Mergesort](divide_and_conquer/mergesort.py)
|
||||||
* [Peak](divide_and_conquer/peak.py)
|
* [Peak](divide_and_conquer/peak.py)
|
||||||
* [Power](divide_and_conquer/power.py)
|
* [Power](divide_and_conquer/power.py)
|
||||||
@ -268,38 +305,56 @@
|
|||||||
* [Bitmask](dynamic_programming/bitmask.py)
|
* [Bitmask](dynamic_programming/bitmask.py)
|
||||||
* [Catalan Numbers](dynamic_programming/catalan_numbers.py)
|
* [Catalan Numbers](dynamic_programming/catalan_numbers.py)
|
||||||
* [Climbing Stairs](dynamic_programming/climbing_stairs.py)
|
* [Climbing Stairs](dynamic_programming/climbing_stairs.py)
|
||||||
|
* [Combination Sum Iv](dynamic_programming/combination_sum_iv.py)
|
||||||
* [Edit Distance](dynamic_programming/edit_distance.py)
|
* [Edit Distance](dynamic_programming/edit_distance.py)
|
||||||
* [Factorial](dynamic_programming/factorial.py)
|
* [Factorial](dynamic_programming/factorial.py)
|
||||||
* [Fast Fibonacci](dynamic_programming/fast_fibonacci.py)
|
* [Fast Fibonacci](dynamic_programming/fast_fibonacci.py)
|
||||||
* [Fibonacci](dynamic_programming/fibonacci.py)
|
* [Fibonacci](dynamic_programming/fibonacci.py)
|
||||||
|
* [Fizz Buzz](dynamic_programming/fizz_buzz.py)
|
||||||
* [Floyd Warshall](dynamic_programming/floyd_warshall.py)
|
* [Floyd Warshall](dynamic_programming/floyd_warshall.py)
|
||||||
* [Fractional Knapsack](dynamic_programming/fractional_knapsack.py)
|
|
||||||
* [Fractional Knapsack 2](dynamic_programming/fractional_knapsack_2.py)
|
|
||||||
* [Integer Partition](dynamic_programming/integer_partition.py)
|
* [Integer Partition](dynamic_programming/integer_partition.py)
|
||||||
* [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py)
|
* [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py)
|
||||||
|
* [K Means Clustering Tensorflow](dynamic_programming/k_means_clustering_tensorflow.py)
|
||||||
* [Knapsack](dynamic_programming/knapsack.py)
|
* [Knapsack](dynamic_programming/knapsack.py)
|
||||||
* [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py)
|
* [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py)
|
||||||
|
* [Longest Common Substring](dynamic_programming/longest_common_substring.py)
|
||||||
* [Longest Increasing Subsequence](dynamic_programming/longest_increasing_subsequence.py)
|
* [Longest Increasing Subsequence](dynamic_programming/longest_increasing_subsequence.py)
|
||||||
* [Longest Increasing Subsequence O(Nlogn)](dynamic_programming/longest_increasing_subsequence_o(nlogn).py)
|
* [Longest Increasing Subsequence O(Nlogn)](dynamic_programming/longest_increasing_subsequence_o(nlogn).py)
|
||||||
* [Longest Sub Array](dynamic_programming/longest_sub_array.py)
|
* [Longest Sub Array](dynamic_programming/longest_sub_array.py)
|
||||||
* [Matrix Chain Order](dynamic_programming/matrix_chain_order.py)
|
* [Matrix Chain Order](dynamic_programming/matrix_chain_order.py)
|
||||||
* [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py)
|
* [Max Non Adjacent Sum](dynamic_programming/max_non_adjacent_sum.py)
|
||||||
* [Max Sub Array](dynamic_programming/max_sub_array.py)
|
* [Max Product Subarray](dynamic_programming/max_product_subarray.py)
|
||||||
* [Max Sum Contiguous Subsequence](dynamic_programming/max_sum_contiguous_subsequence.py)
|
* [Max Subarray Sum](dynamic_programming/max_subarray_sum.py)
|
||||||
|
* [Min Distance Up Bottom](dynamic_programming/min_distance_up_bottom.py)
|
||||||
* [Minimum Coin Change](dynamic_programming/minimum_coin_change.py)
|
* [Minimum Coin Change](dynamic_programming/minimum_coin_change.py)
|
||||||
* [Minimum Cost Path](dynamic_programming/minimum_cost_path.py)
|
* [Minimum Cost Path](dynamic_programming/minimum_cost_path.py)
|
||||||
* [Minimum Partition](dynamic_programming/minimum_partition.py)
|
* [Minimum Partition](dynamic_programming/minimum_partition.py)
|
||||||
|
* [Minimum Size Subarray Sum](dynamic_programming/minimum_size_subarray_sum.py)
|
||||||
|
* [Minimum Squares To Represent A Number](dynamic_programming/minimum_squares_to_represent_a_number.py)
|
||||||
* [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py)
|
* [Minimum Steps To One](dynamic_programming/minimum_steps_to_one.py)
|
||||||
|
* [Minimum Tickets Cost](dynamic_programming/minimum_tickets_cost.py)
|
||||||
* [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py)
|
* [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py)
|
||||||
|
* [Palindrome Partitioning](dynamic_programming/palindrome_partitioning.py)
|
||||||
* [Rod Cutting](dynamic_programming/rod_cutting.py)
|
* [Rod Cutting](dynamic_programming/rod_cutting.py)
|
||||||
* [Subset Generation](dynamic_programming/subset_generation.py)
|
* [Subset Generation](dynamic_programming/subset_generation.py)
|
||||||
* [Sum Of Subset](dynamic_programming/sum_of_subset.py)
|
* [Sum Of Subset](dynamic_programming/sum_of_subset.py)
|
||||||
|
* [Viterbi](dynamic_programming/viterbi.py)
|
||||||
|
* [Word Break](dynamic_programming/word_break.py)
|
||||||
|
|
||||||
## Electronics
|
## Electronics
|
||||||
|
* [Apparent Power](electronics/apparent_power.py)
|
||||||
|
* [Builtin Voltage](electronics/builtin_voltage.py)
|
||||||
* [Carrier Concentration](electronics/carrier_concentration.py)
|
* [Carrier Concentration](electronics/carrier_concentration.py)
|
||||||
|
* [Circular Convolution](electronics/circular_convolution.py)
|
||||||
* [Coulombs Law](electronics/coulombs_law.py)
|
* [Coulombs Law](electronics/coulombs_law.py)
|
||||||
|
* [Electric Conductivity](electronics/electric_conductivity.py)
|
||||||
* [Electric Power](electronics/electric_power.py)
|
* [Electric Power](electronics/electric_power.py)
|
||||||
|
* [Electrical Impedance](electronics/electrical_impedance.py)
|
||||||
|
* [Ind Reactance](electronics/ind_reactance.py)
|
||||||
* [Ohms Law](electronics/ohms_law.py)
|
* [Ohms Law](electronics/ohms_law.py)
|
||||||
|
* [Real And Reactive Power](electronics/real_and_reactive_power.py)
|
||||||
|
* [Resistor Equivalence](electronics/resistor_equivalence.py)
|
||||||
|
* [Resonant Frequency](electronics/resonant_frequency.py)
|
||||||
|
|
||||||
## File Transfer
|
## File Transfer
|
||||||
* [Receive File](file_transfer/receive_file.py)
|
* [Receive File](file_transfer/receive_file.py)
|
||||||
@ -310,6 +365,8 @@
|
|||||||
## Financial
|
## Financial
|
||||||
* [Equated Monthly Installments](financial/equated_monthly_installments.py)
|
* [Equated Monthly Installments](financial/equated_monthly_installments.py)
|
||||||
* [Interest](financial/interest.py)
|
* [Interest](financial/interest.py)
|
||||||
|
* [Present Value](financial/present_value.py)
|
||||||
|
* [Price Plus Tax](financial/price_plus_tax.py)
|
||||||
|
|
||||||
## Fractals
|
## Fractals
|
||||||
* [Julia Sets](fractals/julia_sets.py)
|
* [Julia Sets](fractals/julia_sets.py)
|
||||||
@ -336,14 +393,15 @@
|
|||||||
* [Articulation Points](graphs/articulation_points.py)
|
* [Articulation Points](graphs/articulation_points.py)
|
||||||
* [Basic Graphs](graphs/basic_graphs.py)
|
* [Basic Graphs](graphs/basic_graphs.py)
|
||||||
* [Bellman Ford](graphs/bellman_ford.py)
|
* [Bellman Ford](graphs/bellman_ford.py)
|
||||||
* [Bfs Shortest Path](graphs/bfs_shortest_path.py)
|
* [Bi Directional Dijkstra](graphs/bi_directional_dijkstra.py)
|
||||||
* [Bfs Zero One Shortest Path](graphs/bfs_zero_one_shortest_path.py)
|
|
||||||
* [Bidirectional A Star](graphs/bidirectional_a_star.py)
|
* [Bidirectional A Star](graphs/bidirectional_a_star.py)
|
||||||
* [Bidirectional Breadth First Search](graphs/bidirectional_breadth_first_search.py)
|
* [Bidirectional Breadth First Search](graphs/bidirectional_breadth_first_search.py)
|
||||||
* [Boruvka](graphs/boruvka.py)
|
* [Boruvka](graphs/boruvka.py)
|
||||||
* [Breadth First Search](graphs/breadth_first_search.py)
|
* [Breadth First Search](graphs/breadth_first_search.py)
|
||||||
* [Breadth First Search 2](graphs/breadth_first_search_2.py)
|
* [Breadth First Search 2](graphs/breadth_first_search_2.py)
|
||||||
* [Breadth First Search Shortest Path](graphs/breadth_first_search_shortest_path.py)
|
* [Breadth First Search Shortest Path](graphs/breadth_first_search_shortest_path.py)
|
||||||
|
* [Breadth First Search Shortest Path 2](graphs/breadth_first_search_shortest_path_2.py)
|
||||||
|
* [Breadth First Search Zero One Shortest Path](graphs/breadth_first_search_zero_one_shortest_path.py)
|
||||||
* [Check Bipartite Graph Bfs](graphs/check_bipartite_graph_bfs.py)
|
* [Check Bipartite Graph Bfs](graphs/check_bipartite_graph_bfs.py)
|
||||||
* [Check Bipartite Graph Dfs](graphs/check_bipartite_graph_dfs.py)
|
* [Check Bipartite Graph Dfs](graphs/check_bipartite_graph_dfs.py)
|
||||||
* [Check Cycle](graphs/check_cycle.py)
|
* [Check Cycle](graphs/check_cycle.py)
|
||||||
@ -353,6 +411,8 @@
|
|||||||
* [Dijkstra](graphs/dijkstra.py)
|
* [Dijkstra](graphs/dijkstra.py)
|
||||||
* [Dijkstra 2](graphs/dijkstra_2.py)
|
* [Dijkstra 2](graphs/dijkstra_2.py)
|
||||||
* [Dijkstra Algorithm](graphs/dijkstra_algorithm.py)
|
* [Dijkstra Algorithm](graphs/dijkstra_algorithm.py)
|
||||||
|
* [Dijkstra Alternate](graphs/dijkstra_alternate.py)
|
||||||
|
* [Dijkstra Binary Grid](graphs/dijkstra_binary_grid.py)
|
||||||
* [Dinic](graphs/dinic.py)
|
* [Dinic](graphs/dinic.py)
|
||||||
* [Directed And Undirected (Weighted) Graph](graphs/directed_and_undirected_(weighted)_graph.py)
|
* [Directed And Undirected (Weighted) Graph](graphs/directed_and_undirected_(weighted)_graph.py)
|
||||||
* [Edmonds Karp Multiple Source And Sink](graphs/edmonds_karp_multiple_source_and_sink.py)
|
* [Edmonds Karp Multiple Source And Sink](graphs/edmonds_karp_multiple_source_and_sink.py)
|
||||||
@ -362,8 +422,9 @@
|
|||||||
* [Frequent Pattern Graph Miner](graphs/frequent_pattern_graph_miner.py)
|
* [Frequent Pattern Graph Miner](graphs/frequent_pattern_graph_miner.py)
|
||||||
* [G Topological Sort](graphs/g_topological_sort.py)
|
* [G Topological Sort](graphs/g_topological_sort.py)
|
||||||
* [Gale Shapley Bigraph](graphs/gale_shapley_bigraph.py)
|
* [Gale Shapley Bigraph](graphs/gale_shapley_bigraph.py)
|
||||||
|
* [Graph Adjacency List](graphs/graph_adjacency_list.py)
|
||||||
|
* [Graph Adjacency Matrix](graphs/graph_adjacency_matrix.py)
|
||||||
* [Graph List](graphs/graph_list.py)
|
* [Graph List](graphs/graph_list.py)
|
||||||
* [Graph Matrix](graphs/graph_matrix.py)
|
|
||||||
* [Graphs Floyd Warshall](graphs/graphs_floyd_warshall.py)
|
* [Graphs Floyd Warshall](graphs/graphs_floyd_warshall.py)
|
||||||
* [Greedy Best First](graphs/greedy_best_first.py)
|
* [Greedy Best First](graphs/greedy_best_first.py)
|
||||||
* [Greedy Min Vertex Cover](graphs/greedy_min_vertex_cover.py)
|
* [Greedy Min Vertex Cover](graphs/greedy_min_vertex_cover.py)
|
||||||
@ -390,12 +451,16 @@
|
|||||||
* [Test Min Spanning Tree Prim](graphs/tests/test_min_spanning_tree_prim.py)
|
* [Test Min Spanning Tree Prim](graphs/tests/test_min_spanning_tree_prim.py)
|
||||||
|
|
||||||
## Greedy Methods
|
## Greedy Methods
|
||||||
|
* [Fractional Knapsack](greedy_methods/fractional_knapsack.py)
|
||||||
|
* [Fractional Knapsack 2](greedy_methods/fractional_knapsack_2.py)
|
||||||
|
* [Minimum Waiting Time](greedy_methods/minimum_waiting_time.py)
|
||||||
* [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py)
|
* [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py)
|
||||||
|
|
||||||
## Hashes
|
## Hashes
|
||||||
* [Adler32](hashes/adler32.py)
|
* [Adler32](hashes/adler32.py)
|
||||||
* [Chaos Machine](hashes/chaos_machine.py)
|
* [Chaos Machine](hashes/chaos_machine.py)
|
||||||
* [Djb2](hashes/djb2.py)
|
* [Djb2](hashes/djb2.py)
|
||||||
|
* [Elf](hashes/elf.py)
|
||||||
* [Enigma Machine](hashes/enigma_machine.py)
|
* [Enigma Machine](hashes/enigma_machine.py)
|
||||||
* [Hamming Code](hashes/hamming_code.py)
|
* [Hamming Code](hashes/hamming_code.py)
|
||||||
* [Luhn](hashes/luhn.py)
|
* [Luhn](hashes/luhn.py)
|
||||||
@ -407,6 +472,7 @@
|
|||||||
## Knapsack
|
## Knapsack
|
||||||
* [Greedy Knapsack](knapsack/greedy_knapsack.py)
|
* [Greedy Knapsack](knapsack/greedy_knapsack.py)
|
||||||
* [Knapsack](knapsack/knapsack.py)
|
* [Knapsack](knapsack/knapsack.py)
|
||||||
|
* [Recursive Approach Knapsack](knapsack/recursive_approach_knapsack.py)
|
||||||
* Tests
|
* Tests
|
||||||
* [Test Greedy Knapsack](knapsack/tests/test_greedy_knapsack.py)
|
* [Test Greedy Knapsack](knapsack/tests/test_greedy_knapsack.py)
|
||||||
* [Test Knapsack](knapsack/tests/test_knapsack.py)
|
* [Test Knapsack](knapsack/tests/test_knapsack.py)
|
||||||
@ -417,19 +483,22 @@
|
|||||||
* [Lib](linear_algebra/src/lib.py)
|
* [Lib](linear_algebra/src/lib.py)
|
||||||
* [Polynom For Points](linear_algebra/src/polynom_for_points.py)
|
* [Polynom For Points](linear_algebra/src/polynom_for_points.py)
|
||||||
* [Power Iteration](linear_algebra/src/power_iteration.py)
|
* [Power Iteration](linear_algebra/src/power_iteration.py)
|
||||||
|
* [Rank Of Matrix](linear_algebra/src/rank_of_matrix.py)
|
||||||
* [Rayleigh Quotient](linear_algebra/src/rayleigh_quotient.py)
|
* [Rayleigh Quotient](linear_algebra/src/rayleigh_quotient.py)
|
||||||
* [Schur Complement](linear_algebra/src/schur_complement.py)
|
* [Schur Complement](linear_algebra/src/schur_complement.py)
|
||||||
* [Test Linear Algebra](linear_algebra/src/test_linear_algebra.py)
|
* [Test Linear Algebra](linear_algebra/src/test_linear_algebra.py)
|
||||||
* [Transformations 2D](linear_algebra/src/transformations_2d.py)
|
* [Transformations 2D](linear_algebra/src/transformations_2d.py)
|
||||||
|
|
||||||
|
## Linear Programming
|
||||||
|
* [Simplex](linear_programming/simplex.py)
|
||||||
|
|
||||||
## Machine Learning
|
## Machine Learning
|
||||||
* [Astar](machine_learning/astar.py)
|
* [Astar](machine_learning/astar.py)
|
||||||
* [Data Transformations](machine_learning/data_transformations.py)
|
* [Data Transformations](machine_learning/data_transformations.py)
|
||||||
* [Decision Tree](machine_learning/decision_tree.py)
|
* [Decision Tree](machine_learning/decision_tree.py)
|
||||||
|
* [Dimensionality Reduction](machine_learning/dimensionality_reduction.py)
|
||||||
* Forecasting
|
* Forecasting
|
||||||
* [Run](machine_learning/forecasting/run.py)
|
* [Run](machine_learning/forecasting/run.py)
|
||||||
* [Gaussian Naive Bayes](machine_learning/gaussian_naive_bayes.py)
|
|
||||||
* [Gradient Boosting Regressor](machine_learning/gradient_boosting_regressor.py)
|
|
||||||
* [Gradient Descent](machine_learning/gradient_descent.py)
|
* [Gradient Descent](machine_learning/gradient_descent.py)
|
||||||
* [K Means Clust](machine_learning/k_means_clust.py)
|
* [K Means Clust](machine_learning/k_means_clust.py)
|
||||||
* [K Nearest Neighbours](machine_learning/k_nearest_neighbours.py)
|
* [K Nearest Neighbours](machine_learning/k_nearest_neighbours.py)
|
||||||
@ -443,25 +512,26 @@
|
|||||||
* [Lstm Prediction](machine_learning/lstm/lstm_prediction.py)
|
* [Lstm Prediction](machine_learning/lstm/lstm_prediction.py)
|
||||||
* [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py)
|
* [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py)
|
||||||
* [Polymonial Regression](machine_learning/polymonial_regression.py)
|
* [Polymonial Regression](machine_learning/polymonial_regression.py)
|
||||||
* [Random Forest Classifier](machine_learning/random_forest_classifier.py)
|
|
||||||
* [Random Forest Regressor](machine_learning/random_forest_regressor.py)
|
|
||||||
* [Scoring Functions](machine_learning/scoring_functions.py)
|
* [Scoring Functions](machine_learning/scoring_functions.py)
|
||||||
|
* [Self Organizing Map](machine_learning/self_organizing_map.py)
|
||||||
* [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py)
|
* [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py)
|
||||||
* [Similarity Search](machine_learning/similarity_search.py)
|
* [Similarity Search](machine_learning/similarity_search.py)
|
||||||
* [Support Vector Machines](machine_learning/support_vector_machines.py)
|
* [Support Vector Machines](machine_learning/support_vector_machines.py)
|
||||||
* [Word Frequency Functions](machine_learning/word_frequency_functions.py)
|
* [Word Frequency Functions](machine_learning/word_frequency_functions.py)
|
||||||
|
* [Xgboost Classifier](machine_learning/xgboost_classifier.py)
|
||||||
|
* [Xgboost Regressor](machine_learning/xgboost_regressor.py)
|
||||||
|
|
||||||
## Maths
|
## Maths
|
||||||
* [3N Plus 1](maths/3n_plus_1.py)
|
|
||||||
* [Abs](maths/abs.py)
|
* [Abs](maths/abs.py)
|
||||||
* [Abs Max](maths/abs_max.py)
|
|
||||||
* [Abs Min](maths/abs_min.py)
|
|
||||||
* [Add](maths/add.py)
|
* [Add](maths/add.py)
|
||||||
|
* [Addition Without Arithmetic](maths/addition_without_arithmetic.py)
|
||||||
* [Aliquot Sum](maths/aliquot_sum.py)
|
* [Aliquot Sum](maths/aliquot_sum.py)
|
||||||
* [Allocation Number](maths/allocation_number.py)
|
* [Allocation Number](maths/allocation_number.py)
|
||||||
|
* [Arc Length](maths/arc_length.py)
|
||||||
* [Area](maths/area.py)
|
* [Area](maths/area.py)
|
||||||
* [Area Under Curve](maths/area_under_curve.py)
|
* [Area Under Curve](maths/area_under_curve.py)
|
||||||
* [Armstrong Numbers](maths/armstrong_numbers.py)
|
* [Armstrong Numbers](maths/armstrong_numbers.py)
|
||||||
|
* [Automorphic Number](maths/automorphic_number.py)
|
||||||
* [Average Absolute Deviation](maths/average_absolute_deviation.py)
|
* [Average Absolute Deviation](maths/average_absolute_deviation.py)
|
||||||
* [Average Mean](maths/average_mean.py)
|
* [Average Mean](maths/average_mean.py)
|
||||||
* [Average Median](maths/average_median.py)
|
* [Average Median](maths/average_median.py)
|
||||||
@ -475,14 +545,19 @@
|
|||||||
* [Binomial Coefficient](maths/binomial_coefficient.py)
|
* [Binomial Coefficient](maths/binomial_coefficient.py)
|
||||||
* [Binomial Distribution](maths/binomial_distribution.py)
|
* [Binomial Distribution](maths/binomial_distribution.py)
|
||||||
* [Bisection](maths/bisection.py)
|
* [Bisection](maths/bisection.py)
|
||||||
|
* [Carmichael Number](maths/carmichael_number.py)
|
||||||
|
* [Catalan Number](maths/catalan_number.py)
|
||||||
* [Ceil](maths/ceil.py)
|
* [Ceil](maths/ceil.py)
|
||||||
* [Check Polygon](maths/check_polygon.py)
|
* [Check Polygon](maths/check_polygon.py)
|
||||||
* [Chudnovsky Algorithm](maths/chudnovsky_algorithm.py)
|
* [Chudnovsky Algorithm](maths/chudnovsky_algorithm.py)
|
||||||
* [Collatz Sequence](maths/collatz_sequence.py)
|
* [Collatz Sequence](maths/collatz_sequence.py)
|
||||||
* [Combinations](maths/combinations.py)
|
* [Combinations](maths/combinations.py)
|
||||||
* [Decimal Isolate](maths/decimal_isolate.py)
|
* [Decimal Isolate](maths/decimal_isolate.py)
|
||||||
|
* [Decimal To Fraction](maths/decimal_to_fraction.py)
|
||||||
|
* [Dodecahedron](maths/dodecahedron.py)
|
||||||
* [Double Factorial Iterative](maths/double_factorial_iterative.py)
|
* [Double Factorial Iterative](maths/double_factorial_iterative.py)
|
||||||
* [Double Factorial Recursive](maths/double_factorial_recursive.py)
|
* [Double Factorial Recursive](maths/double_factorial_recursive.py)
|
||||||
|
* [Dual Number Automatic Differentiation](maths/dual_number_automatic_differentiation.py)
|
||||||
* [Entropy](maths/entropy.py)
|
* [Entropy](maths/entropy.py)
|
||||||
* [Euclidean Distance](maths/euclidean_distance.py)
|
* [Euclidean Distance](maths/euclidean_distance.py)
|
||||||
* [Euclidean Gcd](maths/euclidean_gcd.py)
|
* [Euclidean Gcd](maths/euclidean_gcd.py)
|
||||||
@ -490,8 +565,7 @@
|
|||||||
* [Euler Modified](maths/euler_modified.py)
|
* [Euler Modified](maths/euler_modified.py)
|
||||||
* [Eulers Totient](maths/eulers_totient.py)
|
* [Eulers Totient](maths/eulers_totient.py)
|
||||||
* [Extended Euclidean Algorithm](maths/extended_euclidean_algorithm.py)
|
* [Extended Euclidean Algorithm](maths/extended_euclidean_algorithm.py)
|
||||||
* [Factorial Iterative](maths/factorial_iterative.py)
|
* [Factorial](maths/factorial.py)
|
||||||
* [Factorial Recursive](maths/factorial_recursive.py)
|
|
||||||
* [Factors](maths/factors.py)
|
* [Factors](maths/factors.py)
|
||||||
* [Fermat Little Theorem](maths/fermat_little_theorem.py)
|
* [Fermat Little Theorem](maths/fermat_little_theorem.py)
|
||||||
* [Fibonacci](maths/fibonacci.py)
|
* [Fibonacci](maths/fibonacci.py)
|
||||||
@ -503,24 +577,30 @@
|
|||||||
* [Gamma](maths/gamma.py)
|
* [Gamma](maths/gamma.py)
|
||||||
* [Gamma Recursive](maths/gamma_recursive.py)
|
* [Gamma Recursive](maths/gamma_recursive.py)
|
||||||
* [Gaussian](maths/gaussian.py)
|
* [Gaussian](maths/gaussian.py)
|
||||||
|
* [Gaussian Error Linear Unit](maths/gaussian_error_linear_unit.py)
|
||||||
|
* [Gcd Of N Numbers](maths/gcd_of_n_numbers.py)
|
||||||
* [Greatest Common Divisor](maths/greatest_common_divisor.py)
|
* [Greatest Common Divisor](maths/greatest_common_divisor.py)
|
||||||
* [Greedy Coin Change](maths/greedy_coin_change.py)
|
* [Greedy Coin Change](maths/greedy_coin_change.py)
|
||||||
* [Hamming Numbers](maths/hamming_numbers.py)
|
* [Hamming Numbers](maths/hamming_numbers.py)
|
||||||
* [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py)
|
* [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py)
|
||||||
|
* [Hexagonal Number](maths/hexagonal_number.py)
|
||||||
* [Integration By Simpson Approx](maths/integration_by_simpson_approx.py)
|
* [Integration By Simpson Approx](maths/integration_by_simpson_approx.py)
|
||||||
|
* [Is Int Palindrome](maths/is_int_palindrome.py)
|
||||||
* [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py)
|
* [Is Ip V4 Address Valid](maths/is_ip_v4_address_valid.py)
|
||||||
* [Is Square Free](maths/is_square_free.py)
|
* [Is Square Free](maths/is_square_free.py)
|
||||||
* [Jaccard Similarity](maths/jaccard_similarity.py)
|
* [Jaccard Similarity](maths/jaccard_similarity.py)
|
||||||
* [Kadanes](maths/kadanes.py)
|
* [Juggler Sequence](maths/juggler_sequence.py)
|
||||||
* [Karatsuba](maths/karatsuba.py)
|
* [Karatsuba](maths/karatsuba.py)
|
||||||
* [Krishnamurthy Number](maths/krishnamurthy_number.py)
|
* [Krishnamurthy Number](maths/krishnamurthy_number.py)
|
||||||
* [Kth Lexicographic Permutation](maths/kth_lexicographic_permutation.py)
|
* [Kth Lexicographic Permutation](maths/kth_lexicographic_permutation.py)
|
||||||
* [Largest Of Very Large Numbers](maths/largest_of_very_large_numbers.py)
|
* [Largest Of Very Large Numbers](maths/largest_of_very_large_numbers.py)
|
||||||
* [Largest Subarray Sum](maths/largest_subarray_sum.py)
|
|
||||||
* [Least Common Multiple](maths/least_common_multiple.py)
|
* [Least Common Multiple](maths/least_common_multiple.py)
|
||||||
* [Line Length](maths/line_length.py)
|
* [Line Length](maths/line_length.py)
|
||||||
|
* [Liouville Lambda](maths/liouville_lambda.py)
|
||||||
* [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py)
|
* [Lucas Lehmer Primality Test](maths/lucas_lehmer_primality_test.py)
|
||||||
* [Lucas Series](maths/lucas_series.py)
|
* [Lucas Series](maths/lucas_series.py)
|
||||||
|
* [Maclaurin Series](maths/maclaurin_series.py)
|
||||||
|
* [Manhattan Distance](maths/manhattan_distance.py)
|
||||||
* [Matrix Exponentiation](maths/matrix_exponentiation.py)
|
* [Matrix Exponentiation](maths/matrix_exponentiation.py)
|
||||||
* [Max Sum Sliding Window](maths/max_sum_sliding_window.py)
|
* [Max Sum Sliding Window](maths/max_sum_sliding_window.py)
|
||||||
* [Median Of Two Arrays](maths/median_of_two_arrays.py)
|
* [Median Of Two Arrays](maths/median_of_two_arrays.py)
|
||||||
@ -533,20 +613,26 @@
|
|||||||
* [Newton Raphson](maths/newton_raphson.py)
|
* [Newton Raphson](maths/newton_raphson.py)
|
||||||
* [Number Of Digits](maths/number_of_digits.py)
|
* [Number Of Digits](maths/number_of_digits.py)
|
||||||
* [Numerical Integration](maths/numerical_integration.py)
|
* [Numerical Integration](maths/numerical_integration.py)
|
||||||
|
* [Odd Sieve](maths/odd_sieve.py)
|
||||||
* [Perfect Cube](maths/perfect_cube.py)
|
* [Perfect Cube](maths/perfect_cube.py)
|
||||||
* [Perfect Number](maths/perfect_number.py)
|
* [Perfect Number](maths/perfect_number.py)
|
||||||
* [Perfect Square](maths/perfect_square.py)
|
* [Perfect Square](maths/perfect_square.py)
|
||||||
* [Persistence](maths/persistence.py)
|
* [Persistence](maths/persistence.py)
|
||||||
|
* [Pi Generator](maths/pi_generator.py)
|
||||||
* [Pi Monte Carlo Estimation](maths/pi_monte_carlo_estimation.py)
|
* [Pi Monte Carlo Estimation](maths/pi_monte_carlo_estimation.py)
|
||||||
* [Points Are Collinear 3D](maths/points_are_collinear_3d.py)
|
* [Points Are Collinear 3D](maths/points_are_collinear_3d.py)
|
||||||
* [Pollard Rho](maths/pollard_rho.py)
|
* [Pollard Rho](maths/pollard_rho.py)
|
||||||
* [Polynomial Evaluation](maths/polynomial_evaluation.py)
|
* [Polynomial Evaluation](maths/polynomial_evaluation.py)
|
||||||
|
* Polynomials
|
||||||
|
* [Single Indeterminate Operations](maths/polynomials/single_indeterminate_operations.py)
|
||||||
* [Power Using Recursion](maths/power_using_recursion.py)
|
* [Power Using Recursion](maths/power_using_recursion.py)
|
||||||
* [Prime Check](maths/prime_check.py)
|
* [Prime Check](maths/prime_check.py)
|
||||||
* [Prime Factors](maths/prime_factors.py)
|
* [Prime Factors](maths/prime_factors.py)
|
||||||
* [Prime Numbers](maths/prime_numbers.py)
|
* [Prime Numbers](maths/prime_numbers.py)
|
||||||
* [Prime Sieve Eratosthenes](maths/prime_sieve_eratosthenes.py)
|
* [Prime Sieve Eratosthenes](maths/prime_sieve_eratosthenes.py)
|
||||||
* [Primelib](maths/primelib.py)
|
* [Primelib](maths/primelib.py)
|
||||||
|
* [Print Multiplication Table](maths/print_multiplication_table.py)
|
||||||
|
* [Pronic Number](maths/pronic_number.py)
|
||||||
* [Proth Number](maths/proth_number.py)
|
* [Proth Number](maths/proth_number.py)
|
||||||
* [Pythagoras](maths/pythagoras.py)
|
* [Pythagoras](maths/pythagoras.py)
|
||||||
* [Qr Decomposition](maths/qr_decomposition.py)
|
* [Qr Decomposition](maths/qr_decomposition.py)
|
||||||
@ -554,6 +640,7 @@
|
|||||||
* [Radians](maths/radians.py)
|
* [Radians](maths/radians.py)
|
||||||
* [Radix2 Fft](maths/radix2_fft.py)
|
* [Radix2 Fft](maths/radix2_fft.py)
|
||||||
* [Relu](maths/relu.py)
|
* [Relu](maths/relu.py)
|
||||||
|
* [Remove Digit](maths/remove_digit.py)
|
||||||
* [Runge Kutta](maths/runge_kutta.py)
|
* [Runge Kutta](maths/runge_kutta.py)
|
||||||
* [Segmented Sieve](maths/segmented_sieve.py)
|
* [Segmented Sieve](maths/segmented_sieve.py)
|
||||||
* Series
|
* Series
|
||||||
@ -566,7 +653,10 @@
|
|||||||
* [P Series](maths/series/p_series.py)
|
* [P Series](maths/series/p_series.py)
|
||||||
* [Sieve Of Eratosthenes](maths/sieve_of_eratosthenes.py)
|
* [Sieve Of Eratosthenes](maths/sieve_of_eratosthenes.py)
|
||||||
* [Sigmoid](maths/sigmoid.py)
|
* [Sigmoid](maths/sigmoid.py)
|
||||||
|
* [Sigmoid Linear Unit](maths/sigmoid_linear_unit.py)
|
||||||
|
* [Signum](maths/signum.py)
|
||||||
* [Simpson Rule](maths/simpson_rule.py)
|
* [Simpson Rule](maths/simpson_rule.py)
|
||||||
|
* [Simultaneous Linear Equation Solver](maths/simultaneous_linear_equation_solver.py)
|
||||||
* [Sin](maths/sin.py)
|
* [Sin](maths/sin.py)
|
||||||
* [Sock Merchant](maths/sock_merchant.py)
|
* [Sock Merchant](maths/sock_merchant.py)
|
||||||
* [Softmax](maths/softmax.py)
|
* [Softmax](maths/softmax.py)
|
||||||
@ -574,22 +664,34 @@
|
|||||||
* [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py)
|
* [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py)
|
||||||
* [Sum Of Digits](maths/sum_of_digits.py)
|
* [Sum Of Digits](maths/sum_of_digits.py)
|
||||||
* [Sum Of Geometric Progression](maths/sum_of_geometric_progression.py)
|
* [Sum Of Geometric Progression](maths/sum_of_geometric_progression.py)
|
||||||
|
* [Sum Of Harmonic Series](maths/sum_of_harmonic_series.py)
|
||||||
|
* [Sumset](maths/sumset.py)
|
||||||
* [Sylvester Sequence](maths/sylvester_sequence.py)
|
* [Sylvester Sequence](maths/sylvester_sequence.py)
|
||||||
|
* [Tanh](maths/tanh.py)
|
||||||
* [Test Prime Check](maths/test_prime_check.py)
|
* [Test Prime Check](maths/test_prime_check.py)
|
||||||
* [Trapezoidal Rule](maths/trapezoidal_rule.py)
|
* [Trapezoidal Rule](maths/trapezoidal_rule.py)
|
||||||
* [Triplet Sum](maths/triplet_sum.py)
|
* [Triplet Sum](maths/triplet_sum.py)
|
||||||
|
* [Twin Prime](maths/twin_prime.py)
|
||||||
* [Two Pointer](maths/two_pointer.py)
|
* [Two Pointer](maths/two_pointer.py)
|
||||||
* [Two Sum](maths/two_sum.py)
|
* [Two Sum](maths/two_sum.py)
|
||||||
* [Ugly Numbers](maths/ugly_numbers.py)
|
* [Ugly Numbers](maths/ugly_numbers.py)
|
||||||
* [Volume](maths/volume.py)
|
* [Volume](maths/volume.py)
|
||||||
|
* [Weird Number](maths/weird_number.py)
|
||||||
* [Zellers Congruence](maths/zellers_congruence.py)
|
* [Zellers Congruence](maths/zellers_congruence.py)
|
||||||
|
|
||||||
## Matrix
|
## Matrix
|
||||||
|
* [Binary Search Matrix](matrix/binary_search_matrix.py)
|
||||||
* [Count Islands In Matrix](matrix/count_islands_in_matrix.py)
|
* [Count Islands In Matrix](matrix/count_islands_in_matrix.py)
|
||||||
|
* [Count Negative Numbers In Sorted Matrix](matrix/count_negative_numbers_in_sorted_matrix.py)
|
||||||
|
* [Count Paths](matrix/count_paths.py)
|
||||||
|
* [Cramers Rule 2X2](matrix/cramers_rule_2x2.py)
|
||||||
* [Inverse Of Matrix](matrix/inverse_of_matrix.py)
|
* [Inverse Of Matrix](matrix/inverse_of_matrix.py)
|
||||||
|
* [Largest Square Area In Matrix](matrix/largest_square_area_in_matrix.py)
|
||||||
* [Matrix Class](matrix/matrix_class.py)
|
* [Matrix Class](matrix/matrix_class.py)
|
||||||
* [Matrix Operation](matrix/matrix_operation.py)
|
* [Matrix Operation](matrix/matrix_operation.py)
|
||||||
|
* [Max Area Of Island](matrix/max_area_of_island.py)
|
||||||
* [Nth Fibonacci Using Matrix Exponentiation](matrix/nth_fibonacci_using_matrix_exponentiation.py)
|
* [Nth Fibonacci Using Matrix Exponentiation](matrix/nth_fibonacci_using_matrix_exponentiation.py)
|
||||||
|
* [Pascal Triangle](matrix/pascal_triangle.py)
|
||||||
* [Rotate Matrix](matrix/rotate_matrix.py)
|
* [Rotate Matrix](matrix/rotate_matrix.py)
|
||||||
* [Searching In Sorted Matrix](matrix/searching_in_sorted_matrix.py)
|
* [Searching In Sorted Matrix](matrix/searching_in_sorted_matrix.py)
|
||||||
* [Sherman Morrison](matrix/sherman_morrison.py)
|
* [Sherman Morrison](matrix/sherman_morrison.py)
|
||||||
@ -603,14 +705,17 @@
|
|||||||
|
|
||||||
## Neural Network
|
## Neural Network
|
||||||
* [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py)
|
* [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py)
|
||||||
|
* Activation Functions
|
||||||
|
* [Exponential Linear Unit](neural_network/activation_functions/exponential_linear_unit.py)
|
||||||
* [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py)
|
* [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py)
|
||||||
* [Convolution Neural Network](neural_network/convolution_neural_network.py)
|
* [Convolution Neural Network](neural_network/convolution_neural_network.py)
|
||||||
|
* [Input Data](neural_network/input_data.py)
|
||||||
* [Perceptron](neural_network/perceptron.py)
|
* [Perceptron](neural_network/perceptron.py)
|
||||||
|
* [Simple Neural Network](neural_network/simple_neural_network.py)
|
||||||
|
|
||||||
## Other
|
## Other
|
||||||
* [Activity Selection](other/activity_selection.py)
|
* [Activity Selection](other/activity_selection.py)
|
||||||
* [Alternative List Arrange](other/alternative_list_arrange.py)
|
* [Alternative List Arrange](other/alternative_list_arrange.py)
|
||||||
* [Check Strong Password](other/check_strong_password.py)
|
|
||||||
* [Davisb Putnamb Logemannb Loveland](other/davisb_putnamb_logemannb_loveland.py)
|
* [Davisb Putnamb Logemannb Loveland](other/davisb_putnamb_logemannb_loveland.py)
|
||||||
* [Dijkstra Bankers Algorithm](other/dijkstra_bankers_algorithm.py)
|
* [Dijkstra Bankers Algorithm](other/dijkstra_bankers_algorithm.py)
|
||||||
* [Doomsday](other/doomsday.py)
|
* [Doomsday](other/doomsday.py)
|
||||||
@ -618,23 +723,40 @@
|
|||||||
* [Gauss Easter](other/gauss_easter.py)
|
* [Gauss Easter](other/gauss_easter.py)
|
||||||
* [Graham Scan](other/graham_scan.py)
|
* [Graham Scan](other/graham_scan.py)
|
||||||
* [Greedy](other/greedy.py)
|
* [Greedy](other/greedy.py)
|
||||||
|
* [Guess The Number Search](other/guess_the_number_search.py)
|
||||||
|
* [H Index](other/h_index.py)
|
||||||
* [Least Recently Used](other/least_recently_used.py)
|
* [Least Recently Used](other/least_recently_used.py)
|
||||||
* [Lfu Cache](other/lfu_cache.py)
|
* [Lfu Cache](other/lfu_cache.py)
|
||||||
* [Linear Congruential Generator](other/linear_congruential_generator.py)
|
* [Linear Congruential Generator](other/linear_congruential_generator.py)
|
||||||
* [Lru Cache](other/lru_cache.py)
|
* [Lru Cache](other/lru_cache.py)
|
||||||
* [Magicdiamondpattern](other/magicdiamondpattern.py)
|
* [Magicdiamondpattern](other/magicdiamondpattern.py)
|
||||||
* [Maximum Subarray](other/maximum_subarray.py)
|
* [Maximum Subsequence](other/maximum_subsequence.py)
|
||||||
* [Nested Brackets](other/nested_brackets.py)
|
* [Nested Brackets](other/nested_brackets.py)
|
||||||
* [Password Generator](other/password_generator.py)
|
* [Number Container System](other/number_container_system.py)
|
||||||
|
* [Password](other/password.py)
|
||||||
|
* [Quine](other/quine.py)
|
||||||
* [Scoring Algorithm](other/scoring_algorithm.py)
|
* [Scoring Algorithm](other/scoring_algorithm.py)
|
||||||
* [Sdes](other/sdes.py)
|
* [Sdes](other/sdes.py)
|
||||||
* [Tower Of Hanoi](other/tower_of_hanoi.py)
|
* [Tower Of Hanoi](other/tower_of_hanoi.py)
|
||||||
|
|
||||||
## Physics
|
## Physics
|
||||||
|
* [Archimedes Principle](physics/archimedes_principle.py)
|
||||||
|
* [Casimir Effect](physics/casimir_effect.py)
|
||||||
|
* [Centripetal Force](physics/centripetal_force.py)
|
||||||
|
* [Grahams Law](physics/grahams_law.py)
|
||||||
* [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py)
|
* [Horizontal Projectile Motion](physics/horizontal_projectile_motion.py)
|
||||||
|
* [Hubble Parameter](physics/hubble_parameter.py)
|
||||||
|
* [Ideal Gas Law](physics/ideal_gas_law.py)
|
||||||
|
* [Kinetic Energy](physics/kinetic_energy.py)
|
||||||
* [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py)
|
* [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py)
|
||||||
|
* [Malus Law](physics/malus_law.py)
|
||||||
* [N Body Simulation](physics/n_body_simulation.py)
|
* [N Body Simulation](physics/n_body_simulation.py)
|
||||||
|
* [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py)
|
||||||
* [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py)
|
* [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py)
|
||||||
|
* [Potential Energy](physics/potential_energy.py)
|
||||||
|
* [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py)
|
||||||
|
* [Shear Stress](physics/shear_stress.py)
|
||||||
|
* [Speed Of Sound](physics/speed_of_sound.py)
|
||||||
|
|
||||||
## Project Euler
|
## Project Euler
|
||||||
* Problem 001
|
* Problem 001
|
||||||
@ -814,6 +936,8 @@
|
|||||||
* Problem 072
|
* Problem 072
|
||||||
* [Sol1](project_euler/problem_072/sol1.py)
|
* [Sol1](project_euler/problem_072/sol1.py)
|
||||||
* [Sol2](project_euler/problem_072/sol2.py)
|
* [Sol2](project_euler/problem_072/sol2.py)
|
||||||
|
* Problem 073
|
||||||
|
* [Sol1](project_euler/problem_073/sol1.py)
|
||||||
* Problem 074
|
* Problem 074
|
||||||
* [Sol1](project_euler/problem_074/sol1.py)
|
* [Sol1](project_euler/problem_074/sol1.py)
|
||||||
* [Sol2](project_euler/problem_074/sol2.py)
|
* [Sol2](project_euler/problem_074/sol2.py)
|
||||||
@ -825,10 +949,14 @@
|
|||||||
* [Sol1](project_euler/problem_077/sol1.py)
|
* [Sol1](project_euler/problem_077/sol1.py)
|
||||||
* Problem 078
|
* Problem 078
|
||||||
* [Sol1](project_euler/problem_078/sol1.py)
|
* [Sol1](project_euler/problem_078/sol1.py)
|
||||||
|
* Problem 079
|
||||||
|
* [Sol1](project_euler/problem_079/sol1.py)
|
||||||
* Problem 080
|
* Problem 080
|
||||||
* [Sol1](project_euler/problem_080/sol1.py)
|
* [Sol1](project_euler/problem_080/sol1.py)
|
||||||
* Problem 081
|
* Problem 081
|
||||||
* [Sol1](project_euler/problem_081/sol1.py)
|
* [Sol1](project_euler/problem_081/sol1.py)
|
||||||
|
* Problem 082
|
||||||
|
* [Sol1](project_euler/problem_082/sol1.py)
|
||||||
* Problem 085
|
* Problem 085
|
||||||
* [Sol1](project_euler/problem_085/sol1.py)
|
* [Sol1](project_euler/problem_085/sol1.py)
|
||||||
* Problem 086
|
* Problem 086
|
||||||
@ -841,16 +969,20 @@
|
|||||||
* [Sol1](project_euler/problem_091/sol1.py)
|
* [Sol1](project_euler/problem_091/sol1.py)
|
||||||
* Problem 092
|
* Problem 092
|
||||||
* [Sol1](project_euler/problem_092/sol1.py)
|
* [Sol1](project_euler/problem_092/sol1.py)
|
||||||
|
* Problem 094
|
||||||
|
* [Sol1](project_euler/problem_094/sol1.py)
|
||||||
* Problem 097
|
* Problem 097
|
||||||
* [Sol1](project_euler/problem_097/sol1.py)
|
* [Sol1](project_euler/problem_097/sol1.py)
|
||||||
* Problem 099
|
* Problem 099
|
||||||
* [Sol1](project_euler/problem_099/sol1.py)
|
* [Sol1](project_euler/problem_099/sol1.py)
|
||||||
|
* Problem 100
|
||||||
|
* [Sol1](project_euler/problem_100/sol1.py)
|
||||||
* Problem 101
|
* Problem 101
|
||||||
* [Sol1](project_euler/problem_101/sol1.py)
|
* [Sol1](project_euler/problem_101/sol1.py)
|
||||||
* Problem 102
|
* Problem 102
|
||||||
* [Sol1](project_euler/problem_102/sol1.py)
|
* [Sol1](project_euler/problem_102/sol1.py)
|
||||||
* Problem 104
|
* Problem 104
|
||||||
* [Sol](project_euler/problem_104/sol.py)
|
* [Sol1](project_euler/problem_104/sol1.py)
|
||||||
* Problem 107
|
* Problem 107
|
||||||
* [Sol1](project_euler/problem_107/sol1.py)
|
* [Sol1](project_euler/problem_107/sol1.py)
|
||||||
* Problem 109
|
* Problem 109
|
||||||
@ -865,6 +997,8 @@
|
|||||||
* [Sol1](project_euler/problem_115/sol1.py)
|
* [Sol1](project_euler/problem_115/sol1.py)
|
||||||
* Problem 116
|
* Problem 116
|
||||||
* [Sol1](project_euler/problem_116/sol1.py)
|
* [Sol1](project_euler/problem_116/sol1.py)
|
||||||
|
* Problem 117
|
||||||
|
* [Sol1](project_euler/problem_117/sol1.py)
|
||||||
* Problem 119
|
* Problem 119
|
||||||
* [Sol1](project_euler/problem_119/sol1.py)
|
* [Sol1](project_euler/problem_119/sol1.py)
|
||||||
* Problem 120
|
* Problem 120
|
||||||
@ -877,6 +1011,8 @@
|
|||||||
* [Sol1](project_euler/problem_125/sol1.py)
|
* [Sol1](project_euler/problem_125/sol1.py)
|
||||||
* Problem 129
|
* Problem 129
|
||||||
* [Sol1](project_euler/problem_129/sol1.py)
|
* [Sol1](project_euler/problem_129/sol1.py)
|
||||||
|
* Problem 131
|
||||||
|
* [Sol1](project_euler/problem_131/sol1.py)
|
||||||
* Problem 135
|
* Problem 135
|
||||||
* [Sol1](project_euler/problem_135/sol1.py)
|
* [Sol1](project_euler/problem_135/sol1.py)
|
||||||
* Problem 144
|
* Problem 144
|
||||||
@ -889,6 +1025,8 @@
|
|||||||
* [Sol1](project_euler/problem_174/sol1.py)
|
* [Sol1](project_euler/problem_174/sol1.py)
|
||||||
* Problem 180
|
* Problem 180
|
||||||
* [Sol1](project_euler/problem_180/sol1.py)
|
* [Sol1](project_euler/problem_180/sol1.py)
|
||||||
|
* Problem 187
|
||||||
|
* [Sol1](project_euler/problem_187/sol1.py)
|
||||||
* Problem 188
|
* Problem 188
|
||||||
* [Sol1](project_euler/problem_188/sol1.py)
|
* [Sol1](project_euler/problem_188/sol1.py)
|
||||||
* Problem 191
|
* Problem 191
|
||||||
@ -913,18 +1051,27 @@
|
|||||||
* [Sol1](project_euler/problem_587/sol1.py)
|
* [Sol1](project_euler/problem_587/sol1.py)
|
||||||
* Problem 686
|
* Problem 686
|
||||||
* [Sol1](project_euler/problem_686/sol1.py)
|
* [Sol1](project_euler/problem_686/sol1.py)
|
||||||
|
* Problem 800
|
||||||
|
* [Sol1](project_euler/problem_800/sol1.py)
|
||||||
|
|
||||||
## Quantum
|
## Quantum
|
||||||
|
* [Bb84](quantum/bb84.py)
|
||||||
* [Deutsch Jozsa](quantum/deutsch_jozsa.py)
|
* [Deutsch Jozsa](quantum/deutsch_jozsa.py)
|
||||||
* [Half Adder](quantum/half_adder.py)
|
* [Half Adder](quantum/half_adder.py)
|
||||||
* [Not Gate](quantum/not_gate.py)
|
* [Not Gate](quantum/not_gate.py)
|
||||||
|
* [Q Fourier Transform](quantum/q_fourier_transform.py)
|
||||||
|
* [Q Full Adder](quantum/q_full_adder.py)
|
||||||
* [Quantum Entanglement](quantum/quantum_entanglement.py)
|
* [Quantum Entanglement](quantum/quantum_entanglement.py)
|
||||||
|
* [Quantum Random](quantum/quantum_random.py)
|
||||||
|
* [Quantum Teleportation](quantum/quantum_teleportation.py)
|
||||||
* [Ripple Adder Classic](quantum/ripple_adder_classic.py)
|
* [Ripple Adder Classic](quantum/ripple_adder_classic.py)
|
||||||
* [Single Qubit Measure](quantum/single_qubit_measure.py)
|
* [Single Qubit Measure](quantum/single_qubit_measure.py)
|
||||||
|
* [Superdense Coding](quantum/superdense_coding.py)
|
||||||
|
|
||||||
## Scheduling
|
## Scheduling
|
||||||
* [First Come First Served](scheduling/first_come_first_served.py)
|
* [First Come First Served](scheduling/first_come_first_served.py)
|
||||||
* [Highest Response Ratio Next](scheduling/highest_response_ratio_next.py)
|
* [Highest Response Ratio Next](scheduling/highest_response_ratio_next.py)
|
||||||
|
* [Job Sequencing With Deadline](scheduling/job_sequencing_with_deadline.py)
|
||||||
* [Multi Level Feedback Queue](scheduling/multi_level_feedback_queue.py)
|
* [Multi Level Feedback Queue](scheduling/multi_level_feedback_queue.py)
|
||||||
* [Non Preemptive Shortest Job First](scheduling/non_preemptive_shortest_job_first.py)
|
* [Non Preemptive Shortest Job First](scheduling/non_preemptive_shortest_job_first.py)
|
||||||
* [Round Robin](scheduling/round_robin.py)
|
* [Round Robin](scheduling/round_robin.py)
|
||||||
@ -950,6 +1097,7 @@
|
|||||||
|
|
||||||
## Sorts
|
## Sorts
|
||||||
* [Bead Sort](sorts/bead_sort.py)
|
* [Bead Sort](sorts/bead_sort.py)
|
||||||
|
* [Binary Insertion Sort](sorts/binary_insertion_sort.py)
|
||||||
* [Bitonic Sort](sorts/bitonic_sort.py)
|
* [Bitonic Sort](sorts/bitonic_sort.py)
|
||||||
* [Bogo Sort](sorts/bogo_sort.py)
|
* [Bogo Sort](sorts/bogo_sort.py)
|
||||||
* [Bubble Sort](sorts/bubble_sort.py)
|
* [Bubble Sort](sorts/bubble_sort.py)
|
||||||
@ -1005,11 +1153,11 @@
|
|||||||
* [Alternative String Arrange](strings/alternative_string_arrange.py)
|
* [Alternative String Arrange](strings/alternative_string_arrange.py)
|
||||||
* [Anagrams](strings/anagrams.py)
|
* [Anagrams](strings/anagrams.py)
|
||||||
* [Autocomplete Using Trie](strings/autocomplete_using_trie.py)
|
* [Autocomplete Using Trie](strings/autocomplete_using_trie.py)
|
||||||
|
* [Barcode Validator](strings/barcode_validator.py)
|
||||||
* [Boyer Moore Search](strings/boyer_moore_search.py)
|
* [Boyer Moore Search](strings/boyer_moore_search.py)
|
||||||
* [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py)
|
* [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py)
|
||||||
* [Capitalize](strings/capitalize.py)
|
* [Capitalize](strings/capitalize.py)
|
||||||
* [Check Anagrams](strings/check_anagrams.py)
|
* [Check Anagrams](strings/check_anagrams.py)
|
||||||
* [Check Pangram](strings/check_pangram.py)
|
|
||||||
* [Credit Card Validator](strings/credit_card_validator.py)
|
* [Credit Card Validator](strings/credit_card_validator.py)
|
||||||
* [Detecting English Programmatically](strings/detecting_english_programmatically.py)
|
* [Detecting English Programmatically](strings/detecting_english_programmatically.py)
|
||||||
* [Dna](strings/dna.py)
|
* [Dna](strings/dna.py)
|
||||||
@ -1017,7 +1165,10 @@
|
|||||||
* [Hamming Distance](strings/hamming_distance.py)
|
* [Hamming Distance](strings/hamming_distance.py)
|
||||||
* [Indian Phone Validator](strings/indian_phone_validator.py)
|
* [Indian Phone Validator](strings/indian_phone_validator.py)
|
||||||
* [Is Contains Unique Chars](strings/is_contains_unique_chars.py)
|
* [Is Contains Unique Chars](strings/is_contains_unique_chars.py)
|
||||||
* [Is Palindrome](strings/is_palindrome.py)
|
* [Is Isogram](strings/is_isogram.py)
|
||||||
|
* [Is Pangram](strings/is_pangram.py)
|
||||||
|
* [Is Spain National Id](strings/is_spain_national_id.py)
|
||||||
|
* [Is Srilankan Phone Number](strings/is_srilankan_phone_number.py)
|
||||||
* [Jaro Winkler](strings/jaro_winkler.py)
|
* [Jaro Winkler](strings/jaro_winkler.py)
|
||||||
* [Join](strings/join.py)
|
* [Join](strings/join.py)
|
||||||
* [Knuth Morris Pratt](strings/knuth_morris_pratt.py)
|
* [Knuth Morris Pratt](strings/knuth_morris_pratt.py)
|
||||||
@ -1034,7 +1185,11 @@
|
|||||||
* [Reverse Letters](strings/reverse_letters.py)
|
* [Reverse Letters](strings/reverse_letters.py)
|
||||||
* [Reverse Long Words](strings/reverse_long_words.py)
|
* [Reverse Long Words](strings/reverse_long_words.py)
|
||||||
* [Reverse Words](strings/reverse_words.py)
|
* [Reverse Words](strings/reverse_words.py)
|
||||||
|
* [Snake Case To Camel Pascal Case](strings/snake_case_to_camel_pascal_case.py)
|
||||||
* [Split](strings/split.py)
|
* [Split](strings/split.py)
|
||||||
|
* [String Switch Case](strings/string_switch_case.py)
|
||||||
|
* [Text Justification](strings/text_justification.py)
|
||||||
|
* [Top K Frequent Words](strings/top_k_frequent_words.py)
|
||||||
* [Upper](strings/upper.py)
|
* [Upper](strings/upper.py)
|
||||||
* [Wave](strings/wave.py)
|
* [Wave](strings/wave.py)
|
||||||
* [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py)
|
* [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py)
|
||||||
@ -1044,6 +1199,7 @@
|
|||||||
|
|
||||||
## Web Programming
|
## Web Programming
|
||||||
* [Co2 Emission](web_programming/co2_emission.py)
|
* [Co2 Emission](web_programming/co2_emission.py)
|
||||||
|
* [Convert Number To Words](web_programming/convert_number_to_words.py)
|
||||||
* [Covid Stats Via Xpath](web_programming/covid_stats_via_xpath.py)
|
* [Covid Stats Via Xpath](web_programming/covid_stats_via_xpath.py)
|
||||||
* [Crawl Google Results](web_programming/crawl_google_results.py)
|
* [Crawl Google Results](web_programming/crawl_google_results.py)
|
||||||
* [Crawl Google Scholar Citation](web_programming/crawl_google_scholar_citation.py)
|
* [Crawl Google Scholar Citation](web_programming/crawl_google_scholar_citation.py)
|
||||||
@ -1053,12 +1209,12 @@
|
|||||||
* [Daily Horoscope](web_programming/daily_horoscope.py)
|
* [Daily Horoscope](web_programming/daily_horoscope.py)
|
||||||
* [Download Images From Google Query](web_programming/download_images_from_google_query.py)
|
* [Download Images From Google Query](web_programming/download_images_from_google_query.py)
|
||||||
* [Emails From Url](web_programming/emails_from_url.py)
|
* [Emails From Url](web_programming/emails_from_url.py)
|
||||||
* [Fetch Anime And Play](web_programming/fetch_anime_and_play.py)
|
|
||||||
* [Fetch Bbc News](web_programming/fetch_bbc_news.py)
|
* [Fetch Bbc News](web_programming/fetch_bbc_news.py)
|
||||||
* [Fetch Github Info](web_programming/fetch_github_info.py)
|
* [Fetch Github Info](web_programming/fetch_github_info.py)
|
||||||
* [Fetch Jobs](web_programming/fetch_jobs.py)
|
* [Fetch Jobs](web_programming/fetch_jobs.py)
|
||||||
* [Fetch Quotes](web_programming/fetch_quotes.py)
|
* [Fetch Quotes](web_programming/fetch_quotes.py)
|
||||||
* [Fetch Well Rx Price](web_programming/fetch_well_rx_price.py)
|
* [Fetch Well Rx Price](web_programming/fetch_well_rx_price.py)
|
||||||
|
* [Get Amazon Product Data](web_programming/get_amazon_product_data.py)
|
||||||
* [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py)
|
* [Get Imdb Top 250 Movies Csv](web_programming/get_imdb_top_250_movies_csv.py)
|
||||||
* [Get Imdbtop](web_programming/get_imdbtop.py)
|
* [Get Imdbtop](web_programming/get_imdbtop.py)
|
||||||
* [Get Top Hn Posts](web_programming/get_top_hn_posts.py)
|
* [Get Top Hn Posts](web_programming/get_top_hn_posts.py)
|
||||||
@ -1068,6 +1224,7 @@
|
|||||||
* [Instagram Pic](web_programming/instagram_pic.py)
|
* [Instagram Pic](web_programming/instagram_pic.py)
|
||||||
* [Instagram Video](web_programming/instagram_video.py)
|
* [Instagram Video](web_programming/instagram_video.py)
|
||||||
* [Nasa Data](web_programming/nasa_data.py)
|
* [Nasa Data](web_programming/nasa_data.py)
|
||||||
|
* [Open Google Results](web_programming/open_google_results.py)
|
||||||
* [Random Anime Character](web_programming/random_anime_character.py)
|
* [Random Anime Character](web_programming/random_anime_character.py)
|
||||||
* [Recaptcha Verification](web_programming/recaptcha_verification.py)
|
* [Recaptcha Verification](web_programming/recaptcha_verification.py)
|
||||||
* [Reddit](web_programming/reddit.py)
|
* [Reddit](web_programming/reddit.py)
|
||||||
|
13
README.md
13
README.md
@ -16,16 +16,13 @@
|
|||||||
<a href="https://discord.gg/c7MnfGFGa6">
|
<a href="https://discord.gg/c7MnfGFGa6">
|
||||||
<img src="https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square" height="20" alt="Discord chat">
|
<img src="https://img.shields.io/discord/808045925556682782.svg?logo=discord&colorB=7289DA&style=flat-square" height="20" alt="Discord chat">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://gitter.im/TheAlgorithms">
|
<a href="https://gitter.im/TheAlgorithms/community">
|
||||||
<img src="https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square" height="20" alt="Gitter chat">
|
<img src="https://img.shields.io/badge/Chat-Gitter-ff69b4.svg?label=Chat&logo=gitter&style=flat-square" height="20" alt="Gitter chat">
|
||||||
</a>
|
</a>
|
||||||
<!-- Second row: -->
|
<!-- Second row: -->
|
||||||
<br>
|
<br>
|
||||||
<a href="https://github.com/TheAlgorithms/Python/actions">
|
<a href="https://github.com/TheAlgorithms/Python/actions">
|
||||||
<img src="https://img.shields.io/github/workflow/status/TheAlgorithms/Python/build?label=CI&logo=github&style=flat-square" height="20" alt="GitHub Workflow Status">
|
<img src="https://img.shields.io/github/actions/workflow/status/TheAlgorithms/Python/build.yml?branch=master&label=CI&logo=github&style=flat-square" height="20" alt="GitHub Workflow Status">
|
||||||
</a>
|
|
||||||
<a href="https://lgtm.com/projects/g/TheAlgorithms/Python/alerts">
|
|
||||||
<img src="https://img.shields.io/lgtm/alerts/github/TheAlgorithms/Python.svg?label=LGTM&logo=LGTM&style=flat-square" height="20" alt="LGTM">
|
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/pre-commit/pre-commit">
|
<a href="https://github.com/pre-commit/pre-commit">
|
||||||
<img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" height="20" alt="pre-commit">
|
<img src="https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white&style=flat-square" height="20" alt="pre-commit">
|
||||||
@ -37,7 +34,7 @@
|
|||||||
<h3>All algorithms implemented in Python - for education</h3>
|
<h3>All algorithms implemented in Python - for education</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
Implementations are for learning purposes only. As they may be less efficient than the implementations in the Python standard library, use them at your discretion.
|
Implementations are for learning purposes only. They may be less efficient than the implementations in the Python standard library. Use them at your discretion.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
@ -45,8 +42,8 @@ Read through our [Contribution Guidelines](CONTRIBUTING.md) before you contribut
|
|||||||
|
|
||||||
## Community Channels
|
## Community Channels
|
||||||
|
|
||||||
We're on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms)! Community channels are great for you to ask questions and get help. Please join us!
|
We are on [Discord](https://discord.gg/c7MnfGFGa6) and [Gitter](https://gitter.im/TheAlgorithms/community)! Community channels are a great way for you to ask questions and get help. Please join us!
|
||||||
|
|
||||||
## List of Algorithms
|
## List of Algorithms
|
||||||
|
|
||||||
See our [directory](DIRECTORY.md) for easier navigation and better overview of the project.
|
See our [directory](DIRECTORY.md) for easier navigation and a better overview of the project.
|
||||||
|
@ -8,7 +8,7 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float:
|
|||||||
1.0000000149011612
|
1.0000000149011612
|
||||||
>>> bisection(lambda x: x ** 3 - 1, 2, 1000)
|
>>> bisection(lambda x: x ** 3 - 1, 2, 1000)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: could not find root in given interval.
|
ValueError: could not find root in given interval.
|
||||||
>>> bisection(lambda x: x ** 2 - 4 * x + 3, 0, 2)
|
>>> bisection(lambda x: x ** 2 - 4 * x + 3, 0, 2)
|
||||||
1.0
|
1.0
|
||||||
@ -16,7 +16,7 @@ def bisection(function: Callable[[float], float], a: float, b: float) -> float:
|
|||||||
3.0
|
3.0
|
||||||
>>> bisection(lambda x: x ** 2 - 4 * x + 3, 4, 1000)
|
>>> bisection(lambda x: x ** 2 - 4 * x + 3, 4, 1000)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: could not find root in given interval.
|
ValueError: could not find root in given interval.
|
||||||
"""
|
"""
|
||||||
start: float = a
|
start: float = a
|
||||||
|
@ -33,11 +33,11 @@ def retroactive_resolution(
|
|||||||
|
|
||||||
x: NDArray[float64] = np.zeros((rows, 1), dtype=float)
|
x: NDArray[float64] = np.zeros((rows, 1), dtype=float)
|
||||||
for row in reversed(range(rows)):
|
for row in reversed(range(rows)):
|
||||||
sum = 0
|
total = 0
|
||||||
for col in range(row + 1, columns):
|
for col in range(row + 1, columns):
|
||||||
sum += coefficients[row, col] * x[col]
|
total += coefficients[row, col] * x[col]
|
||||||
|
|
||||||
x[row, 0] = (vector[row] - sum) / coefficients[row, row]
|
x[row, 0] = (vector[row] - total) / coefficients[row, row]
|
||||||
|
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ def intersection(function: Callable[[float], float], x0: float, x1: float) -> fl
|
|||||||
0.9999999999954654
|
0.9999999999954654
|
||||||
>>> intersection(lambda x: x ** 3 - 1, 5, 5)
|
>>> intersection(lambda x: x ** 3 - 1, 5, 5)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ZeroDivisionError: float division by zero, could not find root
|
ZeroDivisionError: float division by zero, could not find root
|
||||||
>>> intersection(lambda x: x ** 3 - 1, 100, 200)
|
>>> intersection(lambda x: x ** 3 - 1, 100, 200)
|
||||||
1.0000000000003888
|
1.0000000000003888
|
||||||
@ -24,7 +24,7 @@ def intersection(function: Callable[[float], float], x0: float, x1: float) -> fl
|
|||||||
0.0
|
0.0
|
||||||
>>> intersection(math.cos, -math.pi, math.pi)
|
>>> intersection(math.cos, -math.pi, math.pi)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ZeroDivisionError: float division by zero, could not find root
|
ZeroDivisionError: float division by zero, could not find root
|
||||||
"""
|
"""
|
||||||
x_n: float = x0
|
x_n: float = x0
|
||||||
|
@ -42,16 +42,18 @@ def jacobi_iteration_method(
|
|||||||
>>> iterations = 3
|
>>> iterations = 3
|
||||||
>>> jacobi_iteration_method(coefficient, constant, init_val, iterations)
|
>>> jacobi_iteration_method(coefficient, constant, init_val, iterations)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Coefficient matrix dimensions must be nxn but received 2x3
|
ValueError: Coefficient matrix dimensions must be nxn but received 2x3
|
||||||
|
|
||||||
>>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]])
|
>>> coefficient = np.array([[4, 1, 1], [1, 5, 2], [1, 2, 4]])
|
||||||
>>> constant = np.array([[2], [-6]])
|
>>> constant = np.array([[2], [-6]])
|
||||||
>>> init_val = [0.5, -0.5, -0.5]
|
>>> init_val = [0.5, -0.5, -0.5]
|
||||||
>>> iterations = 3
|
>>> iterations = 3
|
||||||
>>> jacobi_iteration_method(coefficient, constant, init_val, iterations)
|
>>> jacobi_iteration_method(
|
||||||
|
... coefficient, constant, init_val, iterations
|
||||||
|
... ) # doctest: +NORMALIZE_WHITESPACE
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Coefficient and constant matrices dimensions must be nxn and nx1 but
|
ValueError: Coefficient and constant matrices dimensions must be nxn and nx1 but
|
||||||
received 3x3 and 2x1
|
received 3x3 and 2x1
|
||||||
|
|
||||||
@ -59,9 +61,11 @@ def jacobi_iteration_method(
|
|||||||
>>> constant = np.array([[2], [-6], [-4]])
|
>>> constant = np.array([[2], [-6], [-4]])
|
||||||
>>> init_val = [0.5, -0.5]
|
>>> init_val = [0.5, -0.5]
|
||||||
>>> iterations = 3
|
>>> iterations = 3
|
||||||
>>> jacobi_iteration_method(coefficient, constant, init_val, iterations)
|
>>> jacobi_iteration_method(
|
||||||
|
... coefficient, constant, init_val, iterations
|
||||||
|
... ) # doctest: +NORMALIZE_WHITESPACE
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Number of initial values must be equal to number of rows in coefficient
|
ValueError: Number of initial values must be equal to number of rows in coefficient
|
||||||
matrix but received 2 and 3
|
matrix but received 2 and 3
|
||||||
|
|
||||||
@ -71,7 +75,7 @@ def jacobi_iteration_method(
|
|||||||
>>> iterations = 0
|
>>> iterations = 0
|
||||||
>>> jacobi_iteration_method(coefficient, constant, init_val, iterations)
|
>>> jacobi_iteration_method(coefficient, constant, init_val, iterations)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Iterations must be at least 1
|
ValueError: Iterations must be at least 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -79,24 +83,26 @@ def jacobi_iteration_method(
|
|||||||
rows2, cols2 = constant_matrix.shape
|
rows2, cols2 = constant_matrix.shape
|
||||||
|
|
||||||
if rows1 != cols1:
|
if rows1 != cols1:
|
||||||
raise ValueError(
|
msg = f"Coefficient matrix dimensions must be nxn but received {rows1}x{cols1}"
|
||||||
f"Coefficient matrix dimensions must be nxn but received {rows1}x{cols1}"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
if cols2 != 1:
|
if cols2 != 1:
|
||||||
raise ValueError(f"Constant matrix must be nx1 but received {rows2}x{cols2}")
|
msg = f"Constant matrix must be nx1 but received {rows2}x{cols2}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if rows1 != rows2:
|
if rows1 != rows2:
|
||||||
raise ValueError(
|
msg = (
|
||||||
f"""Coefficient and constant matrices dimensions must be nxn and nx1 but
|
"Coefficient and constant matrices dimensions must be nxn and nx1 but "
|
||||||
received {rows1}x{cols1} and {rows2}x{cols2}"""
|
f"received {rows1}x{cols1} and {rows2}x{cols2}"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if len(init_val) != rows1:
|
if len(init_val) != rows1:
|
||||||
raise ValueError(
|
msg = (
|
||||||
f"""Number of initial values must be equal to number of rows in coefficient
|
"Number of initial values must be equal to number of rows in coefficient "
|
||||||
matrix but received {len(init_val)} and {rows1}"""
|
f"matrix but received {len(init_val)} and {rows1}"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if iterations <= 0:
|
if iterations <= 0:
|
||||||
raise ValueError("Iterations must be at least 1")
|
raise ValueError("Iterations must be at least 1")
|
||||||
@ -110,7 +116,7 @@ def jacobi_iteration_method(
|
|||||||
strictly_diagonally_dominant(table)
|
strictly_diagonally_dominant(table)
|
||||||
|
|
||||||
# Iterates the whole matrix for given number of times
|
# Iterates the whole matrix for given number of times
|
||||||
for i in range(iterations):
|
for _ in range(iterations):
|
||||||
new_val = []
|
new_val = []
|
||||||
for row in range(rows):
|
for row in range(rows):
|
||||||
temp = 0
|
temp = 0
|
||||||
@ -138,7 +144,7 @@ def strictly_diagonally_dominant(table: NDArray[float64]) -> bool:
|
|||||||
>>> table = np.array([[4, 1, 1, 2], [1, 5, 2, -6], [1, 2, 3, -4]])
|
>>> table = np.array([[4, 1, 1, 2], [1, 5, 2, -6], [1, 2, 3, -4]])
|
||||||
>>> strictly_diagonally_dominant(table)
|
>>> strictly_diagonally_dominant(table)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Coefficient matrix is not strictly diagonally dominant
|
ValueError: Coefficient matrix is not strictly diagonally dominant
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -147,14 +153,14 @@ def strictly_diagonally_dominant(table: NDArray[float64]) -> bool:
|
|||||||
is_diagonally_dominant = True
|
is_diagonally_dominant = True
|
||||||
|
|
||||||
for i in range(0, rows):
|
for i in range(0, rows):
|
||||||
sum = 0
|
total = 0
|
||||||
for j in range(0, cols - 1):
|
for j in range(0, cols - 1):
|
||||||
if i == j:
|
if i == j:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
sum += table[i][j]
|
total += table[i][j]
|
||||||
|
|
||||||
if table[i][i] <= sum:
|
if table[i][i] <= total:
|
||||||
raise ValueError("Coefficient matrix is not strictly diagonally dominant")
|
raise ValueError("Coefficient matrix is not strictly diagonally dominant")
|
||||||
|
|
||||||
return is_diagonally_dominant
|
return is_diagonally_dominant
|
||||||
|
@ -1,62 +1,102 @@
|
|||||||
"""Lower-Upper (LU) Decomposition.
|
"""
|
||||||
|
Lower–upper (LU) decomposition factors a matrix as a product of a lower
|
||||||
|
triangular matrix and an upper triangular matrix. A square matrix has an LU
|
||||||
|
decomposition under the following conditions:
|
||||||
|
- If the matrix is invertible, then it has an LU decomposition if and only
|
||||||
|
if all of its leading principal minors are non-zero (see
|
||||||
|
https://en.wikipedia.org/wiki/Minor_(linear_algebra) for an explanation of
|
||||||
|
leading principal minors of a matrix).
|
||||||
|
- If the matrix is singular (i.e., not invertible) and it has a rank of k
|
||||||
|
(i.e., it has k linearly independent columns), then it has an LU
|
||||||
|
decomposition if its first k leading principal minors are non-zero.
|
||||||
|
|
||||||
Reference:
|
This algorithm will simply attempt to perform LU decomposition on any square
|
||||||
- https://en.wikipedia.org/wiki/LU_decomposition
|
matrix and raise an error if no such decomposition exists.
|
||||||
|
|
||||||
|
Reference: https://en.wikipedia.org/wiki/LU_decomposition
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import numpy.typing as NDArray
|
|
||||||
from numpy import float64
|
|
||||||
|
|
||||||
|
|
||||||
def lower_upper_decomposition(
|
def lower_upper_decomposition(table: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
|
||||||
table: NDArray[float64],
|
"""
|
||||||
) -> tuple[NDArray[float64], NDArray[float64]]:
|
Perform LU decomposition on a given matrix and raises an error if the matrix
|
||||||
"""Lower-Upper (LU) Decomposition
|
isn't square or if no such decomposition exists
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
>>> matrix = np.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]])
|
>>> matrix = np.array([[2, -2, 1], [0, 1, 2], [5, 3, 1]])
|
||||||
>>> outcome = lower_upper_decomposition(matrix)
|
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||||
>>> outcome[0]
|
>>> lower_mat
|
||||||
array([[1. , 0. , 0. ],
|
array([[1. , 0. , 0. ],
|
||||||
[0. , 1. , 0. ],
|
[0. , 1. , 0. ],
|
||||||
[2.5, 8. , 1. ]])
|
[2.5, 8. , 1. ]])
|
||||||
>>> outcome[1]
|
>>> upper_mat
|
||||||
array([[ 2. , -2. , 1. ],
|
array([[ 2. , -2. , 1. ],
|
||||||
[ 0. , 1. , 2. ],
|
[ 0. , 1. , 2. ],
|
||||||
[ 0. , 0. , -17.5]])
|
[ 0. , 0. , -17.5]])
|
||||||
|
|
||||||
|
>>> matrix = np.array([[4, 3], [6, 3]])
|
||||||
|
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||||
|
>>> lower_mat
|
||||||
|
array([[1. , 0. ],
|
||||||
|
[1.5, 1. ]])
|
||||||
|
>>> upper_mat
|
||||||
|
array([[ 4. , 3. ],
|
||||||
|
[ 0. , -1.5]])
|
||||||
|
|
||||||
|
# Matrix is not square
|
||||||
>>> matrix = np.array([[2, -2, 1], [0, 1, 2]])
|
>>> matrix = np.array([[2, -2, 1], [0, 1, 2]])
|
||||||
>>> lower_upper_decomposition(matrix)
|
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: 'table' has to be of square shaped array but got a 2x3 array:
|
ValueError: 'table' has to be of square shaped array but got a 2x3 array:
|
||||||
[[ 2 -2 1]
|
[[ 2 -2 1]
|
||||||
[ 0 1 2]]
|
[ 0 1 2]]
|
||||||
|
|
||||||
|
# Matrix is invertible, but its first leading principal minor is 0
|
||||||
|
>>> matrix = np.array([[0, 1], [1, 0]])
|
||||||
|
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ArithmeticError: No LU decomposition exists
|
||||||
|
|
||||||
|
# Matrix is singular, but its first leading principal minor is 1
|
||||||
|
>>> matrix = np.array([[1, 0], [1, 0]])
|
||||||
|
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||||
|
>>> lower_mat
|
||||||
|
array([[1., 0.],
|
||||||
|
[1., 1.]])
|
||||||
|
>>> upper_mat
|
||||||
|
array([[1., 0.],
|
||||||
|
[0., 0.]])
|
||||||
|
|
||||||
|
# Matrix is singular, but its first leading principal minor is 0
|
||||||
|
>>> matrix = np.array([[0, 1], [0, 1]])
|
||||||
|
>>> lower_mat, upper_mat = lower_upper_decomposition(matrix)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ArithmeticError: No LU decomposition exists
|
||||||
"""
|
"""
|
||||||
# Table that contains our data
|
# Ensure that table is a square array
|
||||||
# Table has to be a square array so we need to check first
|
|
||||||
rows, columns = np.shape(table)
|
rows, columns = np.shape(table)
|
||||||
if rows != columns:
|
if rows != columns:
|
||||||
raise ValueError(
|
msg = (
|
||||||
f"'table' has to be of square shaped array but got a {rows}x{columns} "
|
"'table' has to be of square shaped array but got a "
|
||||||
+ f"array:\n{table}"
|
f"{rows}x{columns} array:\n{table}"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
lower = np.zeros((rows, columns))
|
lower = np.zeros((rows, columns))
|
||||||
upper = np.zeros((rows, columns))
|
upper = np.zeros((rows, columns))
|
||||||
for i in range(columns):
|
for i in range(columns):
|
||||||
for j in range(i):
|
for j in range(i):
|
||||||
total = 0
|
total = sum(lower[i][k] * upper[k][j] for k in range(j))
|
||||||
for k in range(j):
|
if upper[j][j] == 0:
|
||||||
total += lower[i][k] * upper[k][j]
|
raise ArithmeticError("No LU decomposition exists")
|
||||||
lower[i][j] = (table[i][j] - total) / upper[j][j]
|
lower[i][j] = (table[i][j] - total) / upper[j][j]
|
||||||
lower[i][i] = 1
|
lower[i][i] = 1
|
||||||
for j in range(i, columns):
|
for j in range(i, columns):
|
||||||
total = 0
|
total = sum(lower[i][k] * upper[k][j] for k in range(j))
|
||||||
for k in range(i):
|
|
||||||
total += lower[i][k] * upper[k][j]
|
|
||||||
upper[i][j] = table[i][j] - total
|
upper[i][j] = table[i][j] - total
|
||||||
return lower, upper
|
return lower, upper
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ def ucal(u: float, p: int) -> float:
|
|||||||
def main() -> None:
|
def main() -> None:
|
||||||
n = int(input("enter the numbers of values: "))
|
n = int(input("enter the numbers of values: "))
|
||||||
y: list[list[float]] = []
|
y: list[list[float]] = []
|
||||||
for i in range(n):
|
for _ in range(n):
|
||||||
y.append([])
|
y.append([])
|
||||||
for i in range(n):
|
for i in range(n):
|
||||||
for j in range(n):
|
for j in range(n):
|
||||||
|
@ -28,7 +28,7 @@ def newton(
|
|||||||
1.5707963267948966
|
1.5707963267948966
|
||||||
>>> newton(math.cos, lambda x: -math.sin(x), 0)
|
>>> newton(math.cos, lambda x: -math.sin(x), 0)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ZeroDivisionError: Could not find root
|
ZeroDivisionError: Could not find root
|
||||||
"""
|
"""
|
||||||
prev_guess = float(starting_int)
|
prev_guess = float(starting_int)
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from math import * # noqa: F401, F403
|
from math import * # noqa: F403
|
||||||
|
|
||||||
from sympy import diff
|
from sympy import diff
|
||||||
|
|
||||||
@ -25,9 +25,11 @@ def newton_raphson(
|
|||||||
"""
|
"""
|
||||||
x = a
|
x = a
|
||||||
while True:
|
while True:
|
||||||
x = Decimal(x) - (Decimal(eval(func)) / Decimal(eval(str(diff(func)))))
|
x = Decimal(x) - (
|
||||||
|
Decimal(eval(func)) / Decimal(eval(str(diff(func)))) # noqa: S307
|
||||||
|
)
|
||||||
# This number dictates the accuracy of the answer
|
# This number dictates the accuracy of the answer
|
||||||
if abs(eval(func)) < precision:
|
if abs(eval(func)) < precision: # noqa: S307
|
||||||
return float(x)
|
return float(x)
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
# Newton's Method - https://en.wikipedia.org/wiki/Newton's_method
|
# Newton's Method - https://en.wikipedia.org/wiki/Newton's_method
|
||||||
|
|
||||||
from sympy import diff, lambdify, symbols
|
from sympy import diff, lambdify, symbols
|
||||||
from sympy.functions import * # noqa: F401, F403
|
from sympy.functions import * # noqa: F403
|
||||||
|
|
||||||
|
|
||||||
def newton_raphson(
|
def newton_raphson(
|
||||||
@ -32,7 +32,7 @@ def newton_raphson(
|
|||||||
1.2186556186174883e-10
|
1.2186556186174883e-10
|
||||||
>>> newton_raphson('cos(x)', 0)
|
>>> newton_raphson('cos(x)', 0)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ZeroDivisionError: Could not find root
|
ZeroDivisionError: Could not find root
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -59,7 +59,6 @@ def newton_raphson(
|
|||||||
|
|
||||||
# Let's Execute
|
# Let's Execute
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
# Find root of trigonometric function
|
# Find root of trigonometric function
|
||||||
# Find value of pi
|
# Find value of pi
|
||||||
print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}")
|
print(f"The root of sin(x) = 0 is {newton_raphson('sin(x)', 2)}")
|
||||||
|
@ -20,7 +20,7 @@ def secant_method(lower_bound: float, upper_bound: float, repeats: int) -> float
|
|||||||
"""
|
"""
|
||||||
x0 = lower_bound
|
x0 = lower_bound
|
||||||
x1 = upper_bound
|
x1 = upper_bound
|
||||||
for i in range(0, repeats):
|
for _ in range(0, repeats):
|
||||||
x0, x1 = x1, x1 - (f(x1) * (x1 - x0)) / (f(x1) - f(x0))
|
x0, x1 = x1, x1 - (f(x1) * (x1 - x0)) / (f(x1) - f(x0))
|
||||||
return x1
|
return x1
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ Alternatively you can use scipy.signal.butter, which should yield the same resul
|
|||||||
|
|
||||||
|
|
||||||
def make_lowpass(
|
def make_lowpass(
|
||||||
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)
|
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates a low-pass filter
|
Creates a low-pass filter
|
||||||
@ -39,7 +39,7 @@ def make_lowpass(
|
|||||||
|
|
||||||
|
|
||||||
def make_highpass(
|
def make_highpass(
|
||||||
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)
|
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates a high-pass filter
|
Creates a high-pass filter
|
||||||
@ -67,7 +67,7 @@ def make_highpass(
|
|||||||
|
|
||||||
|
|
||||||
def make_bandpass(
|
def make_bandpass(
|
||||||
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)
|
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates a band-pass filter
|
Creates a band-pass filter
|
||||||
@ -96,7 +96,7 @@ def make_bandpass(
|
|||||||
|
|
||||||
|
|
||||||
def make_allpass(
|
def make_allpass(
|
||||||
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2)
|
frequency: int, samplerate: int, q_factor: float = 1 / sqrt(2) # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates an all-pass filter
|
Creates an all-pass filter
|
||||||
@ -121,7 +121,10 @@ def make_allpass(
|
|||||||
|
|
||||||
|
|
||||||
def make_peak(
|
def make_peak(
|
||||||
frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)
|
frequency: int,
|
||||||
|
samplerate: int,
|
||||||
|
gain_db: float,
|
||||||
|
q_factor: float = 1 / sqrt(2), # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates a peak filter
|
Creates a peak filter
|
||||||
@ -150,7 +153,10 @@ def make_peak(
|
|||||||
|
|
||||||
|
|
||||||
def make_lowshelf(
|
def make_lowshelf(
|
||||||
frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)
|
frequency: int,
|
||||||
|
samplerate: int,
|
||||||
|
gain_db: float,
|
||||||
|
q_factor: float = 1 / sqrt(2), # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates a low-shelf filter
|
Creates a low-shelf filter
|
||||||
@ -184,7 +190,10 @@ def make_lowshelf(
|
|||||||
|
|
||||||
|
|
||||||
def make_highshelf(
|
def make_highshelf(
|
||||||
frequency: int, samplerate: int, gain_db: float, q_factor: float = 1 / sqrt(2)
|
frequency: int,
|
||||||
|
samplerate: int,
|
||||||
|
gain_db: float,
|
||||||
|
q_factor: float = 1 / sqrt(2), # noqa: B008
|
||||||
) -> IIRFilter:
|
) -> IIRFilter:
|
||||||
"""
|
"""
|
||||||
Creates a high-shelf filter
|
Creates a high-shelf filter
|
||||||
|
61
audio_filters/equal_loudness_filter.py.broken.txt
Normal file
61
audio_filters/equal_loudness_filter.py.broken.txt
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
from json import loads
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from yulewalker import yulewalk
|
||||||
|
|
||||||
|
from audio_filters.butterworth_filter import make_highpass
|
||||||
|
from audio_filters.iir_filter import IIRFilter
|
||||||
|
|
||||||
|
data = loads((Path(__file__).resolve().parent / "loudness_curve.json").read_text())
|
||||||
|
|
||||||
|
|
||||||
|
class EqualLoudnessFilter:
|
||||||
|
r"""
|
||||||
|
An equal-loudness filter which compensates for the human ear's non-linear response
|
||||||
|
to sound.
|
||||||
|
This filter corrects this by cascading a yulewalk filter and a butterworth filter.
|
||||||
|
|
||||||
|
Designed for use with samplerate of 44.1kHz and above. If you're using a lower
|
||||||
|
samplerate, use with caution.
|
||||||
|
|
||||||
|
Code based on matlab implementation at https://bit.ly/3eqh2HU
|
||||||
|
(url shortened for ruff)
|
||||||
|
|
||||||
|
Target curve: https://i.imgur.com/3g2VfaM.png
|
||||||
|
Yulewalk response: https://i.imgur.com/J9LnJ4C.png
|
||||||
|
Butterworth and overall response: https://i.imgur.com/3g2VfaM.png
|
||||||
|
|
||||||
|
Images and original matlab implementation by David Robinson, 2001
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, samplerate: int = 44100) -> None:
|
||||||
|
self.yulewalk_filter = IIRFilter(10)
|
||||||
|
self.butterworth_filter = make_highpass(150, samplerate)
|
||||||
|
|
||||||
|
# pad the data to nyquist
|
||||||
|
curve_freqs = np.array(data["frequencies"] + [max(20000.0, samplerate / 2)])
|
||||||
|
curve_gains = np.array(data["gains"] + [140])
|
||||||
|
|
||||||
|
# Convert to angular frequency
|
||||||
|
freqs_normalized = curve_freqs / samplerate * 2
|
||||||
|
# Invert the curve and normalize to 0dB
|
||||||
|
gains_normalized = np.power(10, (np.min(curve_gains) - curve_gains) / 20)
|
||||||
|
|
||||||
|
# Scipy's `yulewalk` function is a stub, so we're using the
|
||||||
|
# `yulewalker` library instead.
|
||||||
|
# This function computes the coefficients using a least-squares
|
||||||
|
# fit to the specified curve.
|
||||||
|
ya, yb = yulewalk(10, freqs_normalized, gains_normalized)
|
||||||
|
self.yulewalk_filter.set_coefficients(ya, yb)
|
||||||
|
|
||||||
|
def process(self, sample: float) -> float:
|
||||||
|
"""
|
||||||
|
Process a single sample through both filters
|
||||||
|
|
||||||
|
>>> filt = EqualLoudnessFilter()
|
||||||
|
>>> filt.process(0.0)
|
||||||
|
0.0
|
||||||
|
"""
|
||||||
|
tmp = self.yulewalk_filter.process(sample)
|
||||||
|
return self.butterworth_filter.process(tmp)
|
@ -47,19 +47,21 @@ class IIRFilter:
|
|||||||
>>> filt.set_coefficients(a_coeffs, b_coeffs)
|
>>> filt.set_coefficients(a_coeffs, b_coeffs)
|
||||||
"""
|
"""
|
||||||
if len(a_coeffs) < self.order:
|
if len(a_coeffs) < self.order:
|
||||||
a_coeffs = [1.0] + a_coeffs
|
a_coeffs = [1.0, *a_coeffs]
|
||||||
|
|
||||||
if len(a_coeffs) != self.order + 1:
|
if len(a_coeffs) != self.order + 1:
|
||||||
raise ValueError(
|
msg = (
|
||||||
f"Expected a_coeffs to have {self.order + 1} elements for {self.order}"
|
f"Expected a_coeffs to have {self.order + 1} elements "
|
||||||
f"-order filter, got {len(a_coeffs)}"
|
f"for {self.order}-order filter, got {len(a_coeffs)}"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
if len(b_coeffs) != self.order + 1:
|
if len(b_coeffs) != self.order + 1:
|
||||||
raise ValueError(
|
msg = (
|
||||||
f"Expected b_coeffs to have {self.order + 1} elements for {self.order}"
|
f"Expected b_coeffs to have {self.order + 1} elements "
|
||||||
f"-order filter, got {len(a_coeffs)}"
|
f"for {self.order}-order filter, got {len(a_coeffs)}"
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
self.a_coeffs = a_coeffs
|
self.a_coeffs = a_coeffs
|
||||||
self.b_coeffs = b_coeffs
|
self.b_coeffs = b_coeffs
|
||||||
|
76
audio_filters/loudness_curve.json
Normal file
76
audio_filters/loudness_curve.json
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"_comment": "The following is a representative average of the Equal Loudness Contours as measured by Robinson and Dadson, 1956",
|
||||||
|
"_doi": "10.1088/0508-3443/7/5/302",
|
||||||
|
"frequencies": [
|
||||||
|
0,
|
||||||
|
20,
|
||||||
|
30,
|
||||||
|
40,
|
||||||
|
50,
|
||||||
|
60,
|
||||||
|
70,
|
||||||
|
80,
|
||||||
|
90,
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
300,
|
||||||
|
400,
|
||||||
|
500,
|
||||||
|
600,
|
||||||
|
700,
|
||||||
|
800,
|
||||||
|
900,
|
||||||
|
1000,
|
||||||
|
1500,
|
||||||
|
2000,
|
||||||
|
2500,
|
||||||
|
3000,
|
||||||
|
3700,
|
||||||
|
4000,
|
||||||
|
5000,
|
||||||
|
6000,
|
||||||
|
7000,
|
||||||
|
8000,
|
||||||
|
9000,
|
||||||
|
10000,
|
||||||
|
12000,
|
||||||
|
15000,
|
||||||
|
20000
|
||||||
|
],
|
||||||
|
"gains": [
|
||||||
|
120,
|
||||||
|
113,
|
||||||
|
103,
|
||||||
|
97,
|
||||||
|
93,
|
||||||
|
91,
|
||||||
|
89,
|
||||||
|
87,
|
||||||
|
86,
|
||||||
|
85,
|
||||||
|
78,
|
||||||
|
76,
|
||||||
|
76,
|
||||||
|
76,
|
||||||
|
76,
|
||||||
|
77,
|
||||||
|
78,
|
||||||
|
79.5,
|
||||||
|
80,
|
||||||
|
79,
|
||||||
|
77,
|
||||||
|
74,
|
||||||
|
71.5,
|
||||||
|
70,
|
||||||
|
70.5,
|
||||||
|
74,
|
||||||
|
79,
|
||||||
|
84,
|
||||||
|
86,
|
||||||
|
86,
|
||||||
|
85,
|
||||||
|
95,
|
||||||
|
110,
|
||||||
|
125
|
||||||
|
]
|
||||||
|
}
|
@ -34,7 +34,7 @@ def get_bounds(
|
|||||||
return lowest, highest
|
return lowest, highest
|
||||||
|
|
||||||
|
|
||||||
def show_frequency_response(filter: FilterType, samplerate: int) -> None:
|
def show_frequency_response(filter_type: FilterType, samplerate: int) -> None:
|
||||||
"""
|
"""
|
||||||
Show frequency response of a filter
|
Show frequency response of a filter
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ def show_frequency_response(filter: FilterType, samplerate: int) -> None:
|
|||||||
|
|
||||||
size = 512
|
size = 512
|
||||||
inputs = [1] + [0] * (size - 1)
|
inputs = [1] + [0] * (size - 1)
|
||||||
outputs = [filter.process(item) for item in inputs]
|
outputs = [filter_type.process(item) for item in inputs]
|
||||||
|
|
||||||
filler = [0] * (samplerate - size) # zero-padding
|
filler = [0] * (samplerate - size) # zero-padding
|
||||||
outputs += filler
|
outputs += filler
|
||||||
@ -66,7 +66,7 @@ def show_frequency_response(filter: FilterType, samplerate: int) -> None:
|
|||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
def show_phase_response(filter: FilterType, samplerate: int) -> None:
|
def show_phase_response(filter_type: FilterType, samplerate: int) -> None:
|
||||||
"""
|
"""
|
||||||
Show phase response of a filter
|
Show phase response of a filter
|
||||||
|
|
||||||
@ -77,7 +77,7 @@ def show_phase_response(filter: FilterType, samplerate: int) -> None:
|
|||||||
|
|
||||||
size = 512
|
size = 512
|
||||||
inputs = [1] + [0] * (size - 1)
|
inputs = [1] + [0] * (size - 1)
|
||||||
outputs = [filter.process(item) for item in inputs]
|
outputs = [filter_type.process(item) for item in inputs]
|
||||||
|
|
||||||
filler = [0] * (samplerate - size) # zero-padding
|
filler = [0] * (samplerate - size) # zero-padding
|
||||||
outputs += filler
|
outputs += filler
|
||||||
|
66
backtracking/combination_sum.py
Normal file
66
backtracking/combination_sum.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
"""
|
||||||
|
In the Combination Sum problem, we are given a list consisting of distinct integers.
|
||||||
|
We need to find all the combinations whose sum equals to target given.
|
||||||
|
We can use an element more than one.
|
||||||
|
|
||||||
|
Time complexity(Average Case): O(n!)
|
||||||
|
|
||||||
|
Constraints:
|
||||||
|
1 <= candidates.length <= 30
|
||||||
|
2 <= candidates[i] <= 40
|
||||||
|
All elements of candidates are distinct.
|
||||||
|
1 <= target <= 40
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def backtrack(
|
||||||
|
candidates: list, path: list, answer: list, target: int, previous_index: int
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
A recursive function that searches for possible combinations. Backtracks in case
|
||||||
|
of a bigger current combination value than the target value.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
previous_index: Last index from the previous search
|
||||||
|
target: The value we need to obtain by summing our integers in the path list.
|
||||||
|
answer: A list of possible combinations
|
||||||
|
path: Current combination
|
||||||
|
candidates: A list of integers we can use.
|
||||||
|
"""
|
||||||
|
if target == 0:
|
||||||
|
answer.append(path.copy())
|
||||||
|
else:
|
||||||
|
for index in range(previous_index, len(candidates)):
|
||||||
|
if target >= candidates[index]:
|
||||||
|
path.append(candidates[index])
|
||||||
|
backtrack(candidates, path, answer, target - candidates[index], index)
|
||||||
|
path.pop(len(path) - 1)
|
||||||
|
|
||||||
|
|
||||||
|
def combination_sum(candidates: list, target: int) -> list:
|
||||||
|
"""
|
||||||
|
>>> combination_sum([2, 3, 5], 8)
|
||||||
|
[[2, 2, 2, 2], [2, 3, 3], [3, 5]]
|
||||||
|
>>> combination_sum([2, 3, 6, 7], 7)
|
||||||
|
[[2, 2, 3], [7]]
|
||||||
|
>>> combination_sum([-8, 2.3, 0], 1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
RecursionError: maximum recursion depth exceeded in comparison
|
||||||
|
"""
|
||||||
|
path = [] # type: list[int]
|
||||||
|
answer = [] # type: list[int]
|
||||||
|
backtrack(candidates, path, answer, target, 0)
|
||||||
|
return answer
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print(combination_sum([-8, 2.3, 0], 1))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
main()
|
@ -71,7 +71,7 @@ def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int)
|
|||||||
>>> curr_ind = 1
|
>>> curr_ind = 1
|
||||||
>>> util_hamilton_cycle(graph, path, curr_ind)
|
>>> util_hamilton_cycle(graph, path, curr_ind)
|
||||||
True
|
True
|
||||||
>>> print(path)
|
>>> path
|
||||||
[0, 1, 2, 4, 3, 0]
|
[0, 1, 2, 4, 3, 0]
|
||||||
|
|
||||||
Case 2: Use exact graph as in previous case, but in the properties taken from
|
Case 2: Use exact graph as in previous case, but in the properties taken from
|
||||||
@ -85,7 +85,7 @@ def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int)
|
|||||||
>>> curr_ind = 3
|
>>> curr_ind = 3
|
||||||
>>> util_hamilton_cycle(graph, path, curr_ind)
|
>>> util_hamilton_cycle(graph, path, curr_ind)
|
||||||
True
|
True
|
||||||
>>> print(path)
|
>>> path
|
||||||
[0, 1, 2, 4, 3, 0]
|
[0, 1, 2, 4, 3, 0]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -95,10 +95,10 @@ def util_hamilton_cycle(graph: list[list[int]], path: list[int], curr_ind: int)
|
|||||||
return graph[path[curr_ind - 1]][path[0]] == 1
|
return graph[path[curr_ind - 1]][path[0]] == 1
|
||||||
|
|
||||||
# Recursive Step
|
# Recursive Step
|
||||||
for next in range(0, len(graph)):
|
for next_ver in range(0, len(graph)):
|
||||||
if valid_connection(graph, next, curr_ind, path):
|
if valid_connection(graph, next_ver, curr_ind, path):
|
||||||
# Insert current vertex into path as next transition
|
# Insert current vertex into path as next transition
|
||||||
path[curr_ind] = next
|
path[curr_ind] = next_ver
|
||||||
# Validate created path
|
# Validate created path
|
||||||
if util_hamilton_cycle(graph, path, curr_ind + 1):
|
if util_hamilton_cycle(graph, path, curr_ind + 1):
|
||||||
return True
|
return True
|
||||||
|
@ -78,7 +78,7 @@ def open_knight_tour(n: int) -> list[list[int]]:
|
|||||||
|
|
||||||
>>> open_knight_tour(2)
|
>>> open_knight_tour(2)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Open Kight Tour cannot be performed on a board of size 2
|
ValueError: Open Kight Tour cannot be performed on a board of size 2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -91,7 +91,8 @@ def open_knight_tour(n: int) -> list[list[int]]:
|
|||||||
return board
|
return board
|
||||||
board[i][j] = 0
|
board[i][j] = 0
|
||||||
|
|
||||||
raise ValueError(f"Open Kight Tour cannot be performed on a board of size {n}")
|
msg = f"Open Kight Tour cannot be performed on a board of size {n}"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
69
backtracking/minmax.py
Normal file
69
backtracking/minmax.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
"""
|
||||||
|
Minimax helps to achieve maximum score in a game by checking all possible moves.
|
||||||
|
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
def minimax(
|
||||||
|
depth: int, node_index: int, is_max: bool, scores: list[int], height: float
|
||||||
|
) -> int:
|
||||||
|
"""
|
||||||
|
depth is current depth in game tree.
|
||||||
|
node_index is index of current node in scores[].
|
||||||
|
scores[] contains the leaves of game tree.
|
||||||
|
height is maximum height of game tree.
|
||||||
|
|
||||||
|
>>> scores = [90, 23, 6, 33, 21, 65, 123, 34423]
|
||||||
|
>>> height = math.log(len(scores), 2)
|
||||||
|
>>> minimax(0, 0, True, scores, height)
|
||||||
|
65
|
||||||
|
>>> minimax(-1, 0, True, scores, height)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Depth cannot be less than 0
|
||||||
|
>>> minimax(0, 0, True, [], 2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Scores cannot be empty
|
||||||
|
>>> scores = [3, 5, 2, 9, 12, 5, 23, 23]
|
||||||
|
>>> height = math.log(len(scores), 2)
|
||||||
|
>>> minimax(0, 0, True, scores, height)
|
||||||
|
12
|
||||||
|
"""
|
||||||
|
|
||||||
|
if depth < 0:
|
||||||
|
raise ValueError("Depth cannot be less than 0")
|
||||||
|
|
||||||
|
if not scores:
|
||||||
|
raise ValueError("Scores cannot be empty")
|
||||||
|
|
||||||
|
if depth == height:
|
||||||
|
return scores[node_index]
|
||||||
|
|
||||||
|
return (
|
||||||
|
max(
|
||||||
|
minimax(depth + 1, node_index * 2, False, scores, height),
|
||||||
|
minimax(depth + 1, node_index * 2 + 1, False, scores, height),
|
||||||
|
)
|
||||||
|
if is_max
|
||||||
|
else min(
|
||||||
|
minimax(depth + 1, node_index * 2, True, scores, height),
|
||||||
|
minimax(depth + 1, node_index * 2 + 1, True, scores, height),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
scores = [90, 23, 6, 33, 21, 65, 123, 34423]
|
||||||
|
height = math.log(len(scores), 2)
|
||||||
|
print(f"Optimal value : {minimax(0, 0, True, scores, height)}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
main()
|
@ -12,7 +12,7 @@ from __future__ import annotations
|
|||||||
solution = []
|
solution = []
|
||||||
|
|
||||||
|
|
||||||
def isSafe(board: list[list[int]], row: int, column: int) -> bool:
|
def is_safe(board: list[list[int]], row: int, column: int) -> bool:
|
||||||
"""
|
"""
|
||||||
This function returns a boolean value True if it is safe to place a queen there
|
This function returns a boolean value True if it is safe to place a queen there
|
||||||
considering the current state of the board.
|
considering the current state of the board.
|
||||||
@ -63,7 +63,7 @@ def solve(board: list[list[int]], row: int) -> bool:
|
|||||||
If all the combinations for that particular branch are successful the board is
|
If all the combinations for that particular branch are successful the board is
|
||||||
reinitialized for the next possible combination.
|
reinitialized for the next possible combination.
|
||||||
"""
|
"""
|
||||||
if isSafe(board, row, i):
|
if is_safe(board, row, i):
|
||||||
board[row][i] = 1
|
board[row][i] = 1
|
||||||
solve(board, row + 1)
|
solve(board, row + 1)
|
||||||
board[row][i] = 0
|
board[row][i] = 0
|
||||||
|
@ -107,7 +107,6 @@ def depth_first_search(
|
|||||||
|
|
||||||
# We iterate each column in the row to find all possible results in each row
|
# We iterate each column in the row to find all possible results in each row
|
||||||
for col in range(n):
|
for col in range(n):
|
||||||
|
|
||||||
# We apply that we learned previously. First we check that in the current board
|
# We apply that we learned previously. First we check that in the current board
|
||||||
# (possible_board) there are not other same value because if there is it means
|
# (possible_board) there are not other same value because if there is it means
|
||||||
# that there are a collision in vertical. Then we apply the two formulas we
|
# that there are a collision in vertical. Then we apply the two formulas we
|
||||||
@ -130,9 +129,9 @@ def depth_first_search(
|
|||||||
|
|
||||||
# If it is False we call dfs function again and we update the inputs
|
# If it is False we call dfs function again and we update the inputs
|
||||||
depth_first_search(
|
depth_first_search(
|
||||||
possible_board + [col],
|
[*possible_board, col],
|
||||||
diagonal_right_collisions + [row - col],
|
[*diagonal_right_collisions, row - col],
|
||||||
diagonal_left_collisions + [row + col],
|
[*diagonal_left_collisions, row + col],
|
||||||
boards,
|
boards,
|
||||||
n,
|
n,
|
||||||
)
|
)
|
||||||
|
93
backtracking/power_sum.py
Normal file
93
backtracking/power_sum.py
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
"""
|
||||||
|
Problem source: https://www.hackerrank.com/challenges/the-power-sum/problem
|
||||||
|
Find the number of ways that a given integer X, can be expressed as the sum
|
||||||
|
of the Nth powers of unique, natural numbers. For example, if X=13 and N=2.
|
||||||
|
We have to find all combinations of unique squares adding up to 13.
|
||||||
|
The only solution is 2^2+3^2. Constraints: 1<=X<=1000, 2<=N<=10.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from math import pow
|
||||||
|
|
||||||
|
|
||||||
|
def backtrack(
|
||||||
|
needed_sum: int,
|
||||||
|
power: int,
|
||||||
|
current_number: int,
|
||||||
|
current_sum: int,
|
||||||
|
solutions_count: int,
|
||||||
|
) -> tuple[int, int]:
|
||||||
|
"""
|
||||||
|
>>> backtrack(13, 2, 1, 0, 0)
|
||||||
|
(0, 1)
|
||||||
|
>>> backtrack(100, 2, 1, 0, 0)
|
||||||
|
(0, 3)
|
||||||
|
>>> backtrack(100, 3, 1, 0, 0)
|
||||||
|
(0, 1)
|
||||||
|
>>> backtrack(800, 2, 1, 0, 0)
|
||||||
|
(0, 561)
|
||||||
|
>>> backtrack(1000, 10, 1, 0, 0)
|
||||||
|
(0, 0)
|
||||||
|
>>> backtrack(400, 2, 1, 0, 0)
|
||||||
|
(0, 55)
|
||||||
|
>>> backtrack(50, 1, 1, 0, 0)
|
||||||
|
(0, 3658)
|
||||||
|
"""
|
||||||
|
if current_sum == needed_sum:
|
||||||
|
# If the sum of the powers is equal to needed_sum, then we have a solution.
|
||||||
|
solutions_count += 1
|
||||||
|
return current_sum, solutions_count
|
||||||
|
|
||||||
|
i_to_n = int(pow(current_number, power))
|
||||||
|
if current_sum + i_to_n <= needed_sum:
|
||||||
|
# If the sum of the powers is less than needed_sum, then continue adding powers.
|
||||||
|
current_sum += i_to_n
|
||||||
|
current_sum, solutions_count = backtrack(
|
||||||
|
needed_sum, power, current_number + 1, current_sum, solutions_count
|
||||||
|
)
|
||||||
|
current_sum -= i_to_n
|
||||||
|
if i_to_n < needed_sum:
|
||||||
|
# If the power of i is less than needed_sum, then try with the next power.
|
||||||
|
current_sum, solutions_count = backtrack(
|
||||||
|
needed_sum, power, current_number + 1, current_sum, solutions_count
|
||||||
|
)
|
||||||
|
return current_sum, solutions_count
|
||||||
|
|
||||||
|
|
||||||
|
def solve(needed_sum: int, power: int) -> int:
|
||||||
|
"""
|
||||||
|
>>> solve(13, 2)
|
||||||
|
1
|
||||||
|
>>> solve(100, 2)
|
||||||
|
3
|
||||||
|
>>> solve(100, 3)
|
||||||
|
1
|
||||||
|
>>> solve(800, 2)
|
||||||
|
561
|
||||||
|
>>> solve(1000, 10)
|
||||||
|
0
|
||||||
|
>>> solve(400, 2)
|
||||||
|
55
|
||||||
|
>>> solve(50, 1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Invalid input
|
||||||
|
needed_sum must be between 1 and 1000, power between 2 and 10.
|
||||||
|
>>> solve(-10, 5)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Invalid input
|
||||||
|
needed_sum must be between 1 and 1000, power between 2 and 10.
|
||||||
|
"""
|
||||||
|
if not (1 <= needed_sum <= 1000 and 2 <= power <= 10):
|
||||||
|
raise ValueError(
|
||||||
|
"Invalid input\n"
|
||||||
|
"needed_sum must be between 1 and 1000, power between 2 and 10."
|
||||||
|
)
|
||||||
|
|
||||||
|
return backtrack(needed_sum, power, 1, 0, 0)[1] # Return the solutions_count
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
@ -88,12 +88,12 @@ def run_maze(maze: list[list[int]], i: int, j: int, solutions: list[list[int]])
|
|||||||
solutions[i][j] = 1
|
solutions[i][j] = 1
|
||||||
return True
|
return True
|
||||||
|
|
||||||
lower_flag = (not (i < 0)) and (not (j < 0)) # Check lower bounds
|
lower_flag = (not i < 0) and (not j < 0) # Check lower bounds
|
||||||
upper_flag = (i < size) and (j < size) # Check upper bounds
|
upper_flag = (i < size) and (j < size) # Check upper bounds
|
||||||
|
|
||||||
if lower_flag and upper_flag:
|
if lower_flag and upper_flag:
|
||||||
# check for already visited and block points.
|
# check for already visited and block points.
|
||||||
block_flag = (not (solutions[i][j])) and (not (maze[i][j]))
|
block_flag = (not solutions[i][j]) and (not maze[i][j])
|
||||||
if block_flag:
|
if block_flag:
|
||||||
# check visited
|
# check visited
|
||||||
solutions[i][j] = 1
|
solutions[i][j] = 1
|
||||||
|
@ -39,14 +39,14 @@ def create_state_space_tree(
|
|||||||
if sum(path) == max_sum:
|
if sum(path) == max_sum:
|
||||||
result.append(path)
|
result.append(path)
|
||||||
return
|
return
|
||||||
for num_index in range(num_index, len(nums)):
|
for index in range(num_index, len(nums)):
|
||||||
create_state_space_tree(
|
create_state_space_tree(
|
||||||
nums,
|
nums,
|
||||||
max_sum,
|
max_sum,
|
||||||
num_index + 1,
|
index + 1,
|
||||||
path + [nums[num_index]],
|
[*path, nums[index]],
|
||||||
result,
|
result,
|
||||||
remaining_nums_sum - nums[num_index],
|
remaining_nums_sum - nums[index],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
168
backtracking/word_search.py
Normal file
168
backtracking/word_search.py
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
"""
|
||||||
|
Author : Alexander Pantyukhin
|
||||||
|
Date : November 24, 2022
|
||||||
|
|
||||||
|
Task:
|
||||||
|
Given an m x n grid of characters board and a string word,
|
||||||
|
return true if word exists in the grid.
|
||||||
|
|
||||||
|
The word can be constructed from letters of sequentially adjacent cells,
|
||||||
|
where adjacent cells are horizontally or vertically neighboring.
|
||||||
|
The same letter cell may not be used more than once.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
Matrix:
|
||||||
|
---------
|
||||||
|
|A|B|C|E|
|
||||||
|
|S|F|C|S|
|
||||||
|
|A|D|E|E|
|
||||||
|
---------
|
||||||
|
|
||||||
|
Word:
|
||||||
|
"ABCCED"
|
||||||
|
|
||||||
|
Result:
|
||||||
|
True
|
||||||
|
|
||||||
|
Implementation notes: Use backtracking approach.
|
||||||
|
At each point, check all neighbors to try to find the next letter of the word.
|
||||||
|
|
||||||
|
leetcode: https://leetcode.com/problems/word-search/
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def get_point_key(len_board: int, len_board_column: int, row: int, column: int) -> int:
|
||||||
|
"""
|
||||||
|
Returns the hash key of matrix indexes.
|
||||||
|
|
||||||
|
>>> get_point_key(10, 20, 1, 0)
|
||||||
|
200
|
||||||
|
"""
|
||||||
|
|
||||||
|
return len_board * len_board_column * row + column
|
||||||
|
|
||||||
|
|
||||||
|
def exits_word(
|
||||||
|
board: list[list[str]],
|
||||||
|
word: str,
|
||||||
|
row: int,
|
||||||
|
column: int,
|
||||||
|
word_index: int,
|
||||||
|
visited_points_set: set[int],
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Return True if it's possible to search the word suffix
|
||||||
|
starting from the word_index.
|
||||||
|
|
||||||
|
>>> exits_word([["A"]], "B", 0, 0, 0, set())
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
|
||||||
|
if board[row][column] != word[word_index]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if word_index == len(word) - 1:
|
||||||
|
return True
|
||||||
|
|
||||||
|
traverts_directions = [(0, 1), (0, -1), (-1, 0), (1, 0)]
|
||||||
|
len_board = len(board)
|
||||||
|
len_board_column = len(board[0])
|
||||||
|
for direction in traverts_directions:
|
||||||
|
next_i = row + direction[0]
|
||||||
|
next_j = column + direction[1]
|
||||||
|
if not (0 <= next_i < len_board and 0 <= next_j < len_board_column):
|
||||||
|
continue
|
||||||
|
|
||||||
|
key = get_point_key(len_board, len_board_column, next_i, next_j)
|
||||||
|
if key in visited_points_set:
|
||||||
|
continue
|
||||||
|
|
||||||
|
visited_points_set.add(key)
|
||||||
|
if exits_word(board, word, next_i, next_j, word_index + 1, visited_points_set):
|
||||||
|
return True
|
||||||
|
|
||||||
|
visited_points_set.remove(key)
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def word_exists(board: list[list[str]], word: str) -> bool:
|
||||||
|
"""
|
||||||
|
>>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCED")
|
||||||
|
True
|
||||||
|
>>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "SEE")
|
||||||
|
True
|
||||||
|
>>> word_exists([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCB")
|
||||||
|
False
|
||||||
|
>>> word_exists([["A"]], "A")
|
||||||
|
True
|
||||||
|
>>> word_exists([["A","A","A","A","A","A"],
|
||||||
|
... ["A","A","A","A","A","A"],
|
||||||
|
... ["A","A","A","A","A","A"],
|
||||||
|
... ["A","A","A","A","A","A"],
|
||||||
|
... ["A","A","A","A","A","B"],
|
||||||
|
... ["A","A","A","A","B","A"]],
|
||||||
|
... "AAAAAAAAAAAAABB")
|
||||||
|
False
|
||||||
|
>>> word_exists([["A"]], 123)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: The word parameter should be a string of length greater than 0.
|
||||||
|
>>> word_exists([["A"]], "")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: The word parameter should be a string of length greater than 0.
|
||||||
|
>>> word_exists([[]], "AB")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: The board should be a non empty matrix of single chars strings.
|
||||||
|
>>> word_exists([], "AB")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: The board should be a non empty matrix of single chars strings.
|
||||||
|
>>> word_exists([["A"], [21]], "AB")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: The board should be a non empty matrix of single chars strings.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate board
|
||||||
|
board_error_message = (
|
||||||
|
"The board should be a non empty matrix of single chars strings."
|
||||||
|
)
|
||||||
|
|
||||||
|
len_board = len(board)
|
||||||
|
if not isinstance(board, list) or len(board) == 0:
|
||||||
|
raise ValueError(board_error_message)
|
||||||
|
|
||||||
|
for row in board:
|
||||||
|
if not isinstance(row, list) or len(row) == 0:
|
||||||
|
raise ValueError(board_error_message)
|
||||||
|
|
||||||
|
for item in row:
|
||||||
|
if not isinstance(item, str) or len(item) != 1:
|
||||||
|
raise ValueError(board_error_message)
|
||||||
|
|
||||||
|
# Validate word
|
||||||
|
if not isinstance(word, str) or len(word) == 0:
|
||||||
|
raise ValueError(
|
||||||
|
"The word parameter should be a string of length greater than 0."
|
||||||
|
)
|
||||||
|
|
||||||
|
len_board_column = len(board[0])
|
||||||
|
for i in range(len_board):
|
||||||
|
for j in range(len_board_column):
|
||||||
|
if exits_word(
|
||||||
|
board, word, i, j, 0, {get_point_key(len_board, len_board_column, i, j)}
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
@ -1,7 +1,7 @@
|
|||||||
def get_1s_count(number: int) -> int:
|
def get_1s_count(number: int) -> int:
|
||||||
"""
|
"""
|
||||||
Count the number of set bits in a 32 bit integer using Brian Kernighan's way.
|
Count the number of set bits in a 32 bit integer using Brian Kernighan's way.
|
||||||
Ref - http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
|
Ref - https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
|
||||||
>>> get_1s_count(25)
|
>>> get_1s_count(25)
|
||||||
3
|
3
|
||||||
>>> get_1s_count(37)
|
>>> get_1s_count(37)
|
||||||
@ -17,16 +17,19 @@ def get_1s_count(number: int) -> int:
|
|||||||
>>> get_1s_count(-1)
|
>>> get_1s_count(-1)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: the value of input must be positive
|
ValueError: Input must be a non-negative integer
|
||||||
>>> get_1s_count(0.8)
|
>>> get_1s_count(0.8)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
TypeError: Input value must be an 'int' type
|
ValueError: Input must be a non-negative integer
|
||||||
|
>>> get_1s_count("25")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Input must be a non-negative integer
|
||||||
"""
|
"""
|
||||||
if number < 0:
|
if not isinstance(number, int) or number < 0:
|
||||||
raise ValueError("the value of input must be positive")
|
raise ValueError("Input must be a non-negative integer")
|
||||||
elif isinstance(number, float):
|
|
||||||
raise TypeError("Input value must be an 'int' type")
|
|
||||||
count = 0
|
count = 0
|
||||||
while number:
|
while number:
|
||||||
# This way we arrive at next set bit (next 1) instead of looping
|
# This way we arrive at next set bit (next 1) instead of looping
|
||||||
|
@ -1,34 +1,91 @@
|
|||||||
def get_set_bits_count(number: int) -> int:
|
from timeit import timeit
|
||||||
|
|
||||||
|
|
||||||
|
def get_set_bits_count_using_brian_kernighans_algorithm(number: int) -> int:
|
||||||
"""
|
"""
|
||||||
Count the number of set bits in a 32 bit integer
|
Count the number of set bits in a 32 bit integer
|
||||||
>>> get_set_bits_count(25)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(25)
|
||||||
3
|
3
|
||||||
>>> get_set_bits_count(37)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(37)
|
||||||
3
|
3
|
||||||
>>> get_set_bits_count(21)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(21)
|
||||||
3
|
3
|
||||||
>>> get_set_bits_count(58)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(58)
|
||||||
4
|
4
|
||||||
>>> get_set_bits_count(0)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(0)
|
||||||
0
|
0
|
||||||
>>> get_set_bits_count(256)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(256)
|
||||||
1
|
1
|
||||||
>>> get_set_bits_count(-1)
|
>>> get_set_bits_count_using_brian_kernighans_algorithm(-1)
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: the value of input must be positive
|
ValueError: the value of input must not be negative
|
||||||
"""
|
"""
|
||||||
if number < 0:
|
if number < 0:
|
||||||
raise ValueError("the value of input must be positive")
|
raise ValueError("the value of input must not be negative")
|
||||||
|
result = 0
|
||||||
|
while number:
|
||||||
|
number &= number - 1
|
||||||
|
result += 1
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def get_set_bits_count_using_modulo_operator(number: int) -> int:
|
||||||
|
"""
|
||||||
|
Count the number of set bits in a 32 bit integer
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(25)
|
||||||
|
3
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(37)
|
||||||
|
3
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(21)
|
||||||
|
3
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(58)
|
||||||
|
4
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(0)
|
||||||
|
0
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(256)
|
||||||
|
1
|
||||||
|
>>> get_set_bits_count_using_modulo_operator(-1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: the value of input must not be negative
|
||||||
|
"""
|
||||||
|
if number < 0:
|
||||||
|
raise ValueError("the value of input must not be negative")
|
||||||
result = 0
|
result = 0
|
||||||
while number:
|
while number:
|
||||||
if number % 2 == 1:
|
if number % 2 == 1:
|
||||||
result += 1
|
result += 1
|
||||||
number = number >> 1
|
number >>= 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def benchmark() -> None:
|
||||||
|
"""
|
||||||
|
Benchmark code for comparing 2 functions, with different length int values.
|
||||||
|
Brian Kernighan's algorithm is consistently faster than using modulo_operator.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def do_benchmark(number: int) -> None:
|
||||||
|
setup = "import __main__ as z"
|
||||||
|
print(f"Benchmark when {number = }:")
|
||||||
|
print(f"{get_set_bits_count_using_modulo_operator(number) = }")
|
||||||
|
timing = timeit("z.get_set_bits_count_using_modulo_operator(25)", setup=setup)
|
||||||
|
print(f"timeit() runs in {timing} seconds")
|
||||||
|
print(f"{get_set_bits_count_using_brian_kernighans_algorithm(number) = }")
|
||||||
|
timing = timeit(
|
||||||
|
"z.get_set_bits_count_using_brian_kernighans_algorithm(25)",
|
||||||
|
setup=setup,
|
||||||
|
)
|
||||||
|
print(f"timeit() runs in {timing} seconds")
|
||||||
|
|
||||||
|
for number in (25, 37, 58, 0):
|
||||||
|
do_benchmark(number)
|
||||||
|
print()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
doctest.testmod()
|
doctest.testmod()
|
||||||
|
benchmark()
|
||||||
|
34
bit_manipulation/highest_set_bit.py
Normal file
34
bit_manipulation/highest_set_bit.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
def get_highest_set_bit_position(number: int) -> int:
|
||||||
|
"""
|
||||||
|
Returns position of the highest set bit of a number.
|
||||||
|
Ref - https://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
|
||||||
|
>>> get_highest_set_bit_position(25)
|
||||||
|
5
|
||||||
|
>>> get_highest_set_bit_position(37)
|
||||||
|
6
|
||||||
|
>>> get_highest_set_bit_position(1)
|
||||||
|
1
|
||||||
|
>>> get_highest_set_bit_position(4)
|
||||||
|
3
|
||||||
|
>>> get_highest_set_bit_position(0)
|
||||||
|
0
|
||||||
|
>>> get_highest_set_bit_position(0.8)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: Input value must be an 'int' type
|
||||||
|
"""
|
||||||
|
if not isinstance(number, int):
|
||||||
|
raise TypeError("Input value must be an 'int' type")
|
||||||
|
|
||||||
|
position = 0
|
||||||
|
while number:
|
||||||
|
position += 1
|
||||||
|
number >>= 1
|
||||||
|
|
||||||
|
return position
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
51
bit_manipulation/index_of_rightmost_set_bit.py
Normal file
51
bit_manipulation/index_of_rightmost_set_bit.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# Reference: https://www.geeksforgeeks.org/position-of-rightmost-set-bit/
|
||||||
|
|
||||||
|
|
||||||
|
def get_index_of_rightmost_set_bit(number: int) -> int:
|
||||||
|
"""
|
||||||
|
Take in a positive integer 'number'.
|
||||||
|
Returns the zero-based index of first set bit in that 'number' from right.
|
||||||
|
Returns -1, If no set bit found.
|
||||||
|
|
||||||
|
>>> get_index_of_rightmost_set_bit(0)
|
||||||
|
-1
|
||||||
|
>>> get_index_of_rightmost_set_bit(5)
|
||||||
|
0
|
||||||
|
>>> get_index_of_rightmost_set_bit(36)
|
||||||
|
2
|
||||||
|
>>> get_index_of_rightmost_set_bit(8)
|
||||||
|
3
|
||||||
|
>>> get_index_of_rightmost_set_bit(-18)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Input must be a non-negative integer
|
||||||
|
>>> get_index_of_rightmost_set_bit('test')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Input must be a non-negative integer
|
||||||
|
>>> get_index_of_rightmost_set_bit(1.25)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Input must be a non-negative integer
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not isinstance(number, int) or number < 0:
|
||||||
|
raise ValueError("Input must be a non-negative integer")
|
||||||
|
|
||||||
|
intermediate = number & ~(number - 1)
|
||||||
|
index = 0
|
||||||
|
while intermediate:
|
||||||
|
intermediate >>= 1
|
||||||
|
index += 1
|
||||||
|
return index - 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
"""
|
||||||
|
Finding the index of rightmost set bit has some very peculiar use-cases,
|
||||||
|
especially in finding missing or/and repeating numbers in a list of
|
||||||
|
positive integers.
|
||||||
|
"""
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod(verbose=True)
|
37
bit_manipulation/is_even.py
Normal file
37
bit_manipulation/is_even.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
def is_even(number: int) -> bool:
|
||||||
|
"""
|
||||||
|
return true if the input integer is even
|
||||||
|
Explanation: Lets take a look at the following deicmal to binary conversions
|
||||||
|
2 => 10
|
||||||
|
14 => 1110
|
||||||
|
100 => 1100100
|
||||||
|
3 => 11
|
||||||
|
13 => 1101
|
||||||
|
101 => 1100101
|
||||||
|
from the above examples we can observe that
|
||||||
|
for all the odd integers there is always 1 set bit at the end
|
||||||
|
also, 1 in binary can be represented as 001, 00001, or 0000001
|
||||||
|
so for any odd integer n => n&1 is always equals 1 else the integer is even
|
||||||
|
|
||||||
|
>>> is_even(1)
|
||||||
|
False
|
||||||
|
>>> is_even(4)
|
||||||
|
True
|
||||||
|
>>> is_even(9)
|
||||||
|
False
|
||||||
|
>>> is_even(15)
|
||||||
|
False
|
||||||
|
>>> is_even(40)
|
||||||
|
True
|
||||||
|
>>> is_even(100)
|
||||||
|
True
|
||||||
|
>>> is_even(101)
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
return number & 1 == 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
57
bit_manipulation/is_power_of_two.py
Normal file
57
bit_manipulation/is_power_of_two.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
"""
|
||||||
|
Author : Alexander Pantyukhin
|
||||||
|
Date : November 1, 2022
|
||||||
|
|
||||||
|
Task:
|
||||||
|
Given a positive int number. Return True if this number is power of 2
|
||||||
|
or False otherwise.
|
||||||
|
|
||||||
|
Implementation notes: Use bit manipulation.
|
||||||
|
For example if the number is the power of two it's bits representation:
|
||||||
|
n = 0..100..00
|
||||||
|
n - 1 = 0..011..11
|
||||||
|
|
||||||
|
n & (n - 1) - no intersections = 0
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def is_power_of_two(number: int) -> bool:
|
||||||
|
"""
|
||||||
|
Return True if this number is power of 2 or False otherwise.
|
||||||
|
|
||||||
|
>>> is_power_of_two(0)
|
||||||
|
True
|
||||||
|
>>> is_power_of_two(1)
|
||||||
|
True
|
||||||
|
>>> is_power_of_two(2)
|
||||||
|
True
|
||||||
|
>>> is_power_of_two(4)
|
||||||
|
True
|
||||||
|
>>> is_power_of_two(6)
|
||||||
|
False
|
||||||
|
>>> is_power_of_two(8)
|
||||||
|
True
|
||||||
|
>>> is_power_of_two(17)
|
||||||
|
False
|
||||||
|
>>> is_power_of_two(-1)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: number must not be negative
|
||||||
|
>>> is_power_of_two(1.2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: unsupported operand type(s) for &: 'float' and 'float'
|
||||||
|
|
||||||
|
# Test all powers of 2 from 0 to 10,000
|
||||||
|
>>> all(is_power_of_two(int(2 ** i)) for i in range(10000))
|
||||||
|
True
|
||||||
|
"""
|
||||||
|
if number < 0:
|
||||||
|
raise ValueError("number must not be negative")
|
||||||
|
return number & (number - 1) == 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
39
bit_manipulation/numbers_different_signs.py
Normal file
39
bit_manipulation/numbers_different_signs.py
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
"""
|
||||||
|
Author : Alexander Pantyukhin
|
||||||
|
Date : November 30, 2022
|
||||||
|
|
||||||
|
Task:
|
||||||
|
Given two int numbers. Return True these numbers have opposite signs
|
||||||
|
or False otherwise.
|
||||||
|
|
||||||
|
Implementation notes: Use bit manipulation.
|
||||||
|
Use XOR for two numbers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def different_signs(num1: int, num2: int) -> bool:
|
||||||
|
"""
|
||||||
|
Return True if numbers have opposite signs False otherwise.
|
||||||
|
|
||||||
|
>>> different_signs(1, -1)
|
||||||
|
True
|
||||||
|
>>> different_signs(1, 1)
|
||||||
|
False
|
||||||
|
>>> different_signs(1000000000000000000000000000, -1000000000000000000000000000)
|
||||||
|
True
|
||||||
|
>>> different_signs(-1000000000000000000000000000, 1000000000000000000000000000)
|
||||||
|
True
|
||||||
|
>>> different_signs(50, 278)
|
||||||
|
False
|
||||||
|
>>> different_signs(0, 2)
|
||||||
|
False
|
||||||
|
>>> different_signs(2, 0)
|
||||||
|
False
|
||||||
|
"""
|
||||||
|
return num1 ^ num2 < 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
@ -14,10 +14,11 @@ def get_reverse_bit_string(number: int) -> str:
|
|||||||
TypeError: operation can not be conducted on a object of type str
|
TypeError: operation can not be conducted on a object of type str
|
||||||
"""
|
"""
|
||||||
if not isinstance(number, int):
|
if not isinstance(number, int):
|
||||||
raise TypeError(
|
msg = (
|
||||||
"operation can not be conducted on a object of type "
|
"operation can not be conducted on a object of type "
|
||||||
f"{type(number).__name__}"
|
f"{type(number).__name__}"
|
||||||
)
|
)
|
||||||
|
raise TypeError(msg)
|
||||||
bit_string = ""
|
bit_string = ""
|
||||||
for _ in range(0, 32):
|
for _ in range(0, 32):
|
||||||
bit_string += str(number % 2)
|
bit_string += str(number % 2)
|
||||||
|
45
blockchain/README.md
Normal file
45
blockchain/README.md
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Blockchain
|
||||||
|
|
||||||
|
A Blockchain is a type of **distributed ledger** technology (DLT) that consists of growing list of records, called **blocks**, that are securely linked together using **cryptography**.
|
||||||
|
|
||||||
|
Let's breakdown the terminologies in the above definition. We find below terminologies,
|
||||||
|
|
||||||
|
- Digital Ledger Technology (DLT)
|
||||||
|
- Blocks
|
||||||
|
- Cryptography
|
||||||
|
|
||||||
|
## Digital Ledger Technology
|
||||||
|
|
||||||
|
It is otherwise called as distributed ledger technology. It is simply the opposite of centralized database. Firstly, what is a **ledger**? A ledger is a book or collection of accounts that records account transactions.
|
||||||
|
|
||||||
|
*Why is Blockchain addressed as digital ledger if it can record more than account transactions? What other transaction details and information can it hold?*
|
||||||
|
|
||||||
|
Digital Ledger Technology is just a ledger which is shared among multiple nodes. This way there exist no need for central authority to hold the info. Okay, how is it differentiated from central database and what are their benefits?
|
||||||
|
|
||||||
|
There is an organization which has 4 branches whose data are stored in a centralized database. So even if one branch needs any data from ledger they need an approval from database in charge. And if one hacks the central database he gets to tamper and control all the data.
|
||||||
|
|
||||||
|
Now lets assume every branch has a copy of the ledger and then once anything is added to the ledger by anyone branch it is gonna automatically reflect in all other ledgers available in other branch. This is done using Peer-to-peer network.
|
||||||
|
|
||||||
|
So this means even if information is tampered in one branch we can find out. If one branch is hacked we can be alerted ,so we can safeguard other branches. Now, assume these branches as computers or nodes and the ledger is a transaction record or digital receipt. If one ledger is hacked in a node we can detect since there will be a mismatch in comparison with other node information. So this is the concept of Digital Ledger Technology.
|
||||||
|
|
||||||
|
*Is it required for all nodes to have access to all information in other nodes? Wouldn't this require enormous storage space in each node?*
|
||||||
|
|
||||||
|
## Blocks
|
||||||
|
|
||||||
|
In short a block is nothing but collections of records with a labelled header. These are connected cryptographically. Once a new block is added to a chain, the previous block is connected, more precisely said as locked and hence, will remain unaltered. We can understand this concept once we get a clear understanding of working mechanism of blockchain.
|
||||||
|
|
||||||
|
## Cryptography
|
||||||
|
|
||||||
|
It is the practice and study of secure communication techniques in the midst of adversarial behavior. More broadly, cryptography is the creation and analysis of protocols that prevent third parties or the general public from accessing private messages.
|
||||||
|
|
||||||
|
*Which cryptography technology is most widely used in blockchain and why?*
|
||||||
|
|
||||||
|
So, in general, blockchain technology is a distributed record holder which records the information about ownership of an asset. To define precisely,
|
||||||
|
> Blockchain is a distributed, immutable ledger that makes it easier to record transactions and track assets in a corporate network.
|
||||||
|
An asset could be tangible (such as a house, car, cash, or land) or intangible (such as a business) (intellectual property, patents, copyrights, branding). A blockchain network can track and sell almost anything of value, lowering risk and costs for everyone involved.
|
||||||
|
|
||||||
|
So this is all about introduction to blockchain technology. To learn more about the topic refer below links....
|
||||||
|
* <https://en.wikipedia.org/wiki/Blockchain>
|
||||||
|
* <https://en.wikipedia.org/wiki/Chinese_remainder_theorem>
|
||||||
|
* <https://en.wikipedia.org/wiki/Diophantine_equation>
|
||||||
|
* <https://www.geeksforgeeks.org/modular-division/>
|
@ -53,6 +53,7 @@ def chinese_remainder_theorem(n1: int, r1: int, n2: int, r2: int) -> int:
|
|||||||
|
|
||||||
# ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid----------------
|
# ----------SAME SOLUTION USING InvertModulo instead ExtendedEuclid----------------
|
||||||
|
|
||||||
|
|
||||||
# This function find the inverses of a i.e., a^(-1)
|
# This function find the inverses of a i.e., a^(-1)
|
||||||
def invert_modulo(a: int, n: int) -> int:
|
def invert_modulo(a: int, n: int) -> int:
|
||||||
"""
|
"""
|
||||||
|
50
boolean_algebra/and_gate.py
Normal file
50
boolean_algebra/and_gate.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
"""
|
||||||
|
An AND Gate is a logic gate in boolean algebra which results to 1 (True) if both the
|
||||||
|
inputs are 1, and 0 (False) otherwise.
|
||||||
|
|
||||||
|
Following is the truth table of an AND Gate:
|
||||||
|
------------------------------
|
||||||
|
| Input 1 | Input 2 | Output |
|
||||||
|
------------------------------
|
||||||
|
| 0 | 0 | 0 |
|
||||||
|
| 0 | 1 | 0 |
|
||||||
|
| 1 | 0 | 0 |
|
||||||
|
| 1 | 1 | 1 |
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Refer - https://www.geeksforgeeks.org/logic-gates-in-python/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def and_gate(input_1: int, input_2: int) -> int:
|
||||||
|
"""
|
||||||
|
Calculate AND of the input values
|
||||||
|
|
||||||
|
>>> and_gate(0, 0)
|
||||||
|
0
|
||||||
|
>>> and_gate(0, 1)
|
||||||
|
0
|
||||||
|
>>> and_gate(1, 0)
|
||||||
|
0
|
||||||
|
>>> and_gate(1, 1)
|
||||||
|
1
|
||||||
|
"""
|
||||||
|
return int((input_1, input_2).count(0) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_and_gate() -> None:
|
||||||
|
"""
|
||||||
|
Tests the and_gate function
|
||||||
|
"""
|
||||||
|
assert and_gate(0, 0) == 0
|
||||||
|
assert and_gate(0, 1) == 0
|
||||||
|
assert and_gate(1, 0) == 0
|
||||||
|
assert and_gate(1, 1) == 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_and_gate()
|
||||||
|
print(and_gate(1, 0))
|
||||||
|
print(and_gate(0, 0))
|
||||||
|
print(and_gate(0, 1))
|
||||||
|
print(and_gate(1, 1))
|
47
boolean_algebra/nand_gate.py
Normal file
47
boolean_algebra/nand_gate.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
"""
|
||||||
|
A NAND Gate is a logic gate in boolean algebra which results to 0 (False) if both
|
||||||
|
the inputs are 1, and 1 (True) otherwise. It's similar to adding
|
||||||
|
a NOT gate along with an AND gate.
|
||||||
|
Following is the truth table of a NAND Gate:
|
||||||
|
------------------------------
|
||||||
|
| Input 1 | Input 2 | Output |
|
||||||
|
------------------------------
|
||||||
|
| 0 | 0 | 1 |
|
||||||
|
| 0 | 1 | 1 |
|
||||||
|
| 1 | 0 | 1 |
|
||||||
|
| 1 | 1 | 0 |
|
||||||
|
------------------------------
|
||||||
|
Refer - https://www.geeksforgeeks.org/logic-gates-in-python/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def nand_gate(input_1: int, input_2: int) -> int:
|
||||||
|
"""
|
||||||
|
Calculate NAND of the input values
|
||||||
|
>>> nand_gate(0, 0)
|
||||||
|
1
|
||||||
|
>>> nand_gate(0, 1)
|
||||||
|
1
|
||||||
|
>>> nand_gate(1, 0)
|
||||||
|
1
|
||||||
|
>>> nand_gate(1, 1)
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
return int((input_1, input_2).count(0) != 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_nand_gate() -> None:
|
||||||
|
"""
|
||||||
|
Tests the nand_gate function
|
||||||
|
"""
|
||||||
|
assert nand_gate(0, 0) == 1
|
||||||
|
assert nand_gate(0, 1) == 1
|
||||||
|
assert nand_gate(1, 0) == 1
|
||||||
|
assert nand_gate(1, 1) == 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(nand_gate(0, 0))
|
||||||
|
print(nand_gate(0, 1))
|
||||||
|
print(nand_gate(1, 0))
|
||||||
|
print(nand_gate(1, 1))
|
48
boolean_algebra/norgate.py
Normal file
48
boolean_algebra/norgate.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
A NOR Gate is a logic gate in boolean algebra which results to false(0)
|
||||||
|
if any of the input is 1, and True(1) if both the inputs are 0.
|
||||||
|
Following is the truth table of a NOR Gate:
|
||||||
|
| Input 1 | Input 2 | Output |
|
||||||
|
| 0 | 0 | 1 |
|
||||||
|
| 0 | 1 | 0 |
|
||||||
|
| 1 | 0 | 0 |
|
||||||
|
| 1 | 1 | 0 |
|
||||||
|
|
||||||
|
Following is the code implementation of the NOR Gate
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def nor_gate(input_1: int, input_2: int) -> int:
|
||||||
|
"""
|
||||||
|
>>> nor_gate(0, 0)
|
||||||
|
1
|
||||||
|
>>> nor_gate(0, 1)
|
||||||
|
0
|
||||||
|
>>> nor_gate(1, 0)
|
||||||
|
0
|
||||||
|
>>> nor_gate(1, 1)
|
||||||
|
0
|
||||||
|
>>> nor_gate(0.0, 0.0)
|
||||||
|
1
|
||||||
|
>>> nor_gate(0, -7)
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
return int(input_1 == input_2 == 0)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
print("Truth Table of NOR Gate:")
|
||||||
|
print("| Input 1 | Input 2 | Output |")
|
||||||
|
print(f"| 0 | 0 | {nor_gate(0, 0)} |")
|
||||||
|
print(f"| 0 | 1 | {nor_gate(0, 1)} |")
|
||||||
|
print(f"| 1 | 0 | {nor_gate(1, 0)} |")
|
||||||
|
print(f"| 1 | 1 | {nor_gate(1, 1)} |")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
main()
|
||||||
|
"""Code provided by Akshaj Vishwanathan"""
|
||||||
|
"""Reference: https://www.geeksforgeeks.org/logic-gates-in-python/"""
|
37
boolean_algebra/not_gate.py
Normal file
37
boolean_algebra/not_gate.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
"""
|
||||||
|
A NOT Gate is a logic gate in boolean algebra which results to 0 (False) if the
|
||||||
|
input is high, and 1 (True) if the input is low.
|
||||||
|
Following is the truth table of a XOR Gate:
|
||||||
|
------------------------------
|
||||||
|
| Input | Output |
|
||||||
|
------------------------------
|
||||||
|
| 0 | 1 |
|
||||||
|
| 1 | 0 |
|
||||||
|
------------------------------
|
||||||
|
Refer - https://www.geeksforgeeks.org/logic-gates-in-python/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def not_gate(input_1: int) -> int:
|
||||||
|
"""
|
||||||
|
Calculate NOT of the input values
|
||||||
|
>>> not_gate(0)
|
||||||
|
1
|
||||||
|
>>> not_gate(1)
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
|
||||||
|
return 1 if input_1 == 0 else 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_not_gate() -> None:
|
||||||
|
"""
|
||||||
|
Tests the not_gate function
|
||||||
|
"""
|
||||||
|
assert not_gate(0) == 1
|
||||||
|
assert not_gate(1) == 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(not_gate(0))
|
||||||
|
print(not_gate(1))
|
46
boolean_algebra/or_gate.py
Normal file
46
boolean_algebra/or_gate.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"""
|
||||||
|
An OR Gate is a logic gate in boolean algebra which results to 0 (False) if both the
|
||||||
|
inputs are 0, and 1 (True) otherwise.
|
||||||
|
Following is the truth table of an AND Gate:
|
||||||
|
------------------------------
|
||||||
|
| Input 1 | Input 2 | Output |
|
||||||
|
------------------------------
|
||||||
|
| 0 | 0 | 0 |
|
||||||
|
| 0 | 1 | 1 |
|
||||||
|
| 1 | 0 | 1 |
|
||||||
|
| 1 | 1 | 1 |
|
||||||
|
------------------------------
|
||||||
|
Refer - https://www.geeksforgeeks.org/logic-gates-in-python/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def or_gate(input_1: int, input_2: int) -> int:
|
||||||
|
"""
|
||||||
|
Calculate OR of the input values
|
||||||
|
>>> or_gate(0, 0)
|
||||||
|
0
|
||||||
|
>>> or_gate(0, 1)
|
||||||
|
1
|
||||||
|
>>> or_gate(1, 0)
|
||||||
|
1
|
||||||
|
>>> or_gate(1, 1)
|
||||||
|
1
|
||||||
|
"""
|
||||||
|
return int((input_1, input_2).count(1) != 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_or_gate() -> None:
|
||||||
|
"""
|
||||||
|
Tests the or_gate function
|
||||||
|
"""
|
||||||
|
assert or_gate(0, 0) == 0
|
||||||
|
assert or_gate(0, 1) == 1
|
||||||
|
assert or_gate(1, 0) == 1
|
||||||
|
assert or_gate(1, 1) == 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(or_gate(0, 1))
|
||||||
|
print(or_gate(1, 0))
|
||||||
|
print(or_gate(0, 0))
|
||||||
|
print(or_gate(1, 1))
|
@ -1,15 +1,16 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
|
from typing import Literal
|
||||||
|
|
||||||
|
|
||||||
def compare_string(string1: str, string2: str) -> str:
|
def compare_string(string1: str, string2: str) -> str | Literal[False]:
|
||||||
"""
|
"""
|
||||||
>>> compare_string('0010','0110')
|
>>> compare_string('0010','0110')
|
||||||
'0_10'
|
'0_10'
|
||||||
|
|
||||||
>>> compare_string('0110','1101')
|
>>> compare_string('0110','1101')
|
||||||
'X'
|
False
|
||||||
"""
|
"""
|
||||||
list1 = list(string1)
|
list1 = list(string1)
|
||||||
list2 = list(string2)
|
list2 = list(string2)
|
||||||
@ -19,7 +20,7 @@ def compare_string(string1: str, string2: str) -> str:
|
|||||||
count += 1
|
count += 1
|
||||||
list1[i] = "_"
|
list1[i] = "_"
|
||||||
if count > 1:
|
if count > 1:
|
||||||
return "X"
|
return False
|
||||||
else:
|
else:
|
||||||
return "".join(list1)
|
return "".join(list1)
|
||||||
|
|
||||||
@ -36,10 +37,10 @@ def check(binary: list[str]) -> list[str]:
|
|||||||
for i in range(len(binary)):
|
for i in range(len(binary)):
|
||||||
for j in range(i + 1, len(binary)):
|
for j in range(i + 1, len(binary)):
|
||||||
k = compare_string(binary[i], binary[j])
|
k = compare_string(binary[i], binary[j])
|
||||||
if k != "X":
|
if k is False:
|
||||||
check1[i] = "*"
|
check1[i] = "*"
|
||||||
check1[j] = "*"
|
check1[j] = "*"
|
||||||
temp.append(k)
|
temp.append("X")
|
||||||
for i in range(len(binary)):
|
for i in range(len(binary)):
|
||||||
if check1[i] == "$":
|
if check1[i] == "$":
|
||||||
pi.append(binary[i])
|
pi.append(binary[i])
|
||||||
@ -56,7 +57,7 @@ def decimal_to_binary(no_of_variable: int, minterms: Sequence[float]) -> list[st
|
|||||||
temp = []
|
temp = []
|
||||||
for minterm in minterms:
|
for minterm in minterms:
|
||||||
string = ""
|
string = ""
|
||||||
for i in range(no_of_variable):
|
for _ in range(no_of_variable):
|
||||||
string = str(minterm % 2) + string
|
string = str(minterm % 2) + string
|
||||||
minterm //= 2
|
minterm //= 2
|
||||||
temp.append(string)
|
temp.append(string)
|
||||||
|
48
boolean_algebra/xnor_gate.py
Normal file
48
boolean_algebra/xnor_gate.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"""
|
||||||
|
A XNOR Gate is a logic gate in boolean algebra which results to 0 (False) if both the
|
||||||
|
inputs are different, and 1 (True), if the inputs are same.
|
||||||
|
It's similar to adding a NOT gate to an XOR gate
|
||||||
|
|
||||||
|
Following is the truth table of a XNOR Gate:
|
||||||
|
------------------------------
|
||||||
|
| Input 1 | Input 2 | Output |
|
||||||
|
------------------------------
|
||||||
|
| 0 | 0 | 1 |
|
||||||
|
| 0 | 1 | 0 |
|
||||||
|
| 1 | 0 | 0 |
|
||||||
|
| 1 | 1 | 1 |
|
||||||
|
------------------------------
|
||||||
|
Refer - https://www.geeksforgeeks.org/logic-gates-in-python/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def xnor_gate(input_1: int, input_2: int) -> int:
|
||||||
|
"""
|
||||||
|
Calculate XOR of the input values
|
||||||
|
>>> xnor_gate(0, 0)
|
||||||
|
1
|
||||||
|
>>> xnor_gate(0, 1)
|
||||||
|
0
|
||||||
|
>>> xnor_gate(1, 0)
|
||||||
|
0
|
||||||
|
>>> xnor_gate(1, 1)
|
||||||
|
1
|
||||||
|
"""
|
||||||
|
return 1 if input_1 == input_2 else 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_xnor_gate() -> None:
|
||||||
|
"""
|
||||||
|
Tests the xnor_gate function
|
||||||
|
"""
|
||||||
|
assert xnor_gate(0, 0) == 1
|
||||||
|
assert xnor_gate(0, 1) == 0
|
||||||
|
assert xnor_gate(1, 0) == 0
|
||||||
|
assert xnor_gate(1, 1) == 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(xnor_gate(0, 0))
|
||||||
|
print(xnor_gate(0, 1))
|
||||||
|
print(xnor_gate(1, 0))
|
||||||
|
print(xnor_gate(1, 1))
|
46
boolean_algebra/xor_gate.py
Normal file
46
boolean_algebra/xor_gate.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
"""
|
||||||
|
A XOR Gate is a logic gate in boolean algebra which results to 1 (True) if only one of
|
||||||
|
the two inputs is 1, and 0 (False) if an even number of inputs are 1.
|
||||||
|
Following is the truth table of a XOR Gate:
|
||||||
|
------------------------------
|
||||||
|
| Input 1 | Input 2 | Output |
|
||||||
|
------------------------------
|
||||||
|
| 0 | 0 | 0 |
|
||||||
|
| 0 | 1 | 1 |
|
||||||
|
| 1 | 0 | 1 |
|
||||||
|
| 1 | 1 | 0 |
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Refer - https://www.geeksforgeeks.org/logic-gates-in-python/
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def xor_gate(input_1: int, input_2: int) -> int:
|
||||||
|
"""
|
||||||
|
calculate xor of the input values
|
||||||
|
|
||||||
|
>>> xor_gate(0, 0)
|
||||||
|
0
|
||||||
|
>>> xor_gate(0, 1)
|
||||||
|
1
|
||||||
|
>>> xor_gate(1, 0)
|
||||||
|
1
|
||||||
|
>>> xor_gate(1, 1)
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
return (input_1, input_2).count(0) % 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_xor_gate() -> None:
|
||||||
|
"""
|
||||||
|
Tests the xor_gate function
|
||||||
|
"""
|
||||||
|
assert xor_gate(0, 0) == 0
|
||||||
|
assert xor_gate(0, 1) == 1
|
||||||
|
assert xor_gate(1, 0) == 1
|
||||||
|
assert xor_gate(1, 1) == 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(xor_gate(0, 0))
|
||||||
|
print(xor_gate(0, 1))
|
@ -34,7 +34,7 @@ import numpy as np
|
|||||||
from matplotlib import pyplot as plt
|
from matplotlib import pyplot as plt
|
||||||
from matplotlib.colors import ListedColormap
|
from matplotlib.colors import ListedColormap
|
||||||
|
|
||||||
usage_doc = "Usage of script: script_nama <size_of_canvas:int>"
|
usage_doc = "Usage of script: script_name <size_of_canvas:int>"
|
||||||
|
|
||||||
choice = [0] * 100 + [1] * 10
|
choice = [0] * 100 + [1] * 10
|
||||||
random.shuffle(choice)
|
random.shuffle(choice)
|
||||||
@ -66,7 +66,6 @@ def run(canvas: list[list[bool]]) -> list[list[bool]]:
|
|||||||
next_gen_canvas = np.array(create_canvas(current_canvas.shape[0]))
|
next_gen_canvas = np.array(create_canvas(current_canvas.shape[0]))
|
||||||
for r, row in enumerate(current_canvas):
|
for r, row in enumerate(current_canvas):
|
||||||
for c, pt in enumerate(row):
|
for c, pt in enumerate(row):
|
||||||
# print(r-1,r+2,c-1,c+2)
|
|
||||||
next_gen_canvas[r][c] = __judge_point(
|
next_gen_canvas[r][c] = __judge_point(
|
||||||
pt, current_canvas[r - 1 : r + 2, c - 1 : c + 2]
|
pt, current_canvas[r - 1 : r + 2, c - 1 : c + 2]
|
||||||
)
|
)
|
||||||
|
@ -45,8 +45,7 @@ def construct_highway(
|
|||||||
|
|
||||||
highway = [[-1] * number_of_cells] # Create a highway without any car
|
highway = [[-1] * number_of_cells] # Create a highway without any car
|
||||||
i = 0
|
i = 0
|
||||||
if initial_speed < 0:
|
initial_speed = max(initial_speed, 0)
|
||||||
initial_speed = 0
|
|
||||||
while i < number_of_cells:
|
while i < number_of_cells:
|
||||||
highway[0][i] = (
|
highway[0][i] = (
|
||||||
randint(0, max_speed) if random_speed else initial_speed
|
randint(0, max_speed) if random_speed else initial_speed
|
||||||
|
@ -9,26 +9,26 @@ SYMBOLS = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def check_keys(keyA: int, keyB: int, mode: str) -> None:
|
def check_keys(key_a: int, key_b: int, mode: str) -> None:
|
||||||
if mode == "encrypt":
|
if mode == "encrypt":
|
||||||
if keyA == 1:
|
if key_a == 1:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
"The affine cipher becomes weak when key "
|
"The affine cipher becomes weak when key "
|
||||||
"A is set to 1. Choose different key"
|
"A is set to 1. Choose different key"
|
||||||
)
|
)
|
||||||
if keyB == 0:
|
if key_b == 0:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
"The affine cipher becomes weak when key "
|
"The affine cipher becomes weak when key "
|
||||||
"B is set to 0. Choose different key"
|
"B is set to 0. Choose different key"
|
||||||
)
|
)
|
||||||
if keyA < 0 or keyB < 0 or keyB > len(SYMBOLS) - 1:
|
if key_a < 0 or key_b < 0 or key_b > len(SYMBOLS) - 1:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
"Key A must be greater than 0 and key B must "
|
"Key A must be greater than 0 and key B must "
|
||||||
f"be between 0 and {len(SYMBOLS) - 1}."
|
f"be between 0 and {len(SYMBOLS) - 1}."
|
||||||
)
|
)
|
||||||
if cryptomath.gcd(keyA, len(SYMBOLS)) != 1:
|
if cryptomath.gcd(key_a, len(SYMBOLS)) != 1:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
f"Key A {keyA} and the symbol set size {len(SYMBOLS)} "
|
f"Key A {key_a} and the symbol set size {len(SYMBOLS)} "
|
||||||
"are not relatively prime. Choose a different key."
|
"are not relatively prime. Choose a different key."
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,16 +39,16 @@ def encrypt_message(key: int, message: str) -> str:
|
|||||||
... 'substitution cipher.')
|
... 'substitution cipher.')
|
||||||
'VL}p MM{I}p~{HL}Gp{vp pFsH}pxMpyxIx JHL O}F{~pvuOvF{FuF{xIp~{HL}Gi'
|
'VL}p MM{I}p~{HL}Gp{vp pFsH}pxMpyxIx JHL O}F{~pvuOvF{FuF{xIp~{HL}Gi'
|
||||||
"""
|
"""
|
||||||
keyA, keyB = divmod(key, len(SYMBOLS))
|
key_a, key_b = divmod(key, len(SYMBOLS))
|
||||||
check_keys(keyA, keyB, "encrypt")
|
check_keys(key_a, key_b, "encrypt")
|
||||||
cipherText = ""
|
cipher_text = ""
|
||||||
for symbol in message:
|
for symbol in message:
|
||||||
if symbol in SYMBOLS:
|
if symbol in SYMBOLS:
|
||||||
symIndex = SYMBOLS.find(symbol)
|
sym_index = SYMBOLS.find(symbol)
|
||||||
cipherText += SYMBOLS[(symIndex * keyA + keyB) % len(SYMBOLS)]
|
cipher_text += SYMBOLS[(sym_index * key_a + key_b) % len(SYMBOLS)]
|
||||||
else:
|
else:
|
||||||
cipherText += symbol
|
cipher_text += symbol
|
||||||
return cipherText
|
return cipher_text
|
||||||
|
|
||||||
|
|
||||||
def decrypt_message(key: int, message: str) -> str:
|
def decrypt_message(key: int, message: str) -> str:
|
||||||
@ -57,25 +57,27 @@ def decrypt_message(key: int, message: str) -> str:
|
|||||||
... '{xIp~{HL}Gi')
|
... '{xIp~{HL}Gi')
|
||||||
'The affine cipher is a type of monoalphabetic substitution cipher.'
|
'The affine cipher is a type of monoalphabetic substitution cipher.'
|
||||||
"""
|
"""
|
||||||
keyA, keyB = divmod(key, len(SYMBOLS))
|
key_a, key_b = divmod(key, len(SYMBOLS))
|
||||||
check_keys(keyA, keyB, "decrypt")
|
check_keys(key_a, key_b, "decrypt")
|
||||||
plainText = ""
|
plain_text = ""
|
||||||
modInverseOfkeyA = cryptomath.find_mod_inverse(keyA, len(SYMBOLS))
|
mod_inverse_of_key_a = cryptomath.find_mod_inverse(key_a, len(SYMBOLS))
|
||||||
for symbol in message:
|
for symbol in message:
|
||||||
if symbol in SYMBOLS:
|
if symbol in SYMBOLS:
|
||||||
symIndex = SYMBOLS.find(symbol)
|
sym_index = SYMBOLS.find(symbol)
|
||||||
plainText += SYMBOLS[(symIndex - keyB) * modInverseOfkeyA % len(SYMBOLS)]
|
plain_text += SYMBOLS[
|
||||||
|
(sym_index - key_b) * mod_inverse_of_key_a % len(SYMBOLS)
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
plainText += symbol
|
plain_text += symbol
|
||||||
return plainText
|
return plain_text
|
||||||
|
|
||||||
|
|
||||||
def get_random_key() -> int:
|
def get_random_key() -> int:
|
||||||
while True:
|
while True:
|
||||||
keyA = random.randint(2, len(SYMBOLS))
|
key_b = random.randint(2, len(SYMBOLS))
|
||||||
keyB = random.randint(2, len(SYMBOLS))
|
key_b = random.randint(2, len(SYMBOLS))
|
||||||
if cryptomath.gcd(keyA, len(SYMBOLS)) == 1 and keyB % len(SYMBOLS) != 0:
|
if cryptomath.gcd(key_b, len(SYMBOLS)) == 1 and key_b % len(SYMBOLS) != 0:
|
||||||
return keyA * len(SYMBOLS) + keyB
|
return key_b * len(SYMBOLS) + key_b
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
@ -38,26 +38,13 @@ def atbash(sequence: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def benchmark() -> None:
|
def benchmark() -> None:
|
||||||
"""Let's benchmark them side-by-side..."""
|
"""Let's benchmark our functions side-by-side..."""
|
||||||
from timeit import timeit
|
from timeit import timeit
|
||||||
|
|
||||||
print("Running performance benchmarks...")
|
print("Running performance benchmarks...")
|
||||||
print(
|
setup = "from string import printable ; from __main__ import atbash, atbash_slow"
|
||||||
"> atbash_slow()",
|
print(f"> atbash_slow(): {timeit('atbash_slow(printable)', setup=setup)} seconds")
|
||||||
timeit(
|
print(f"> atbash(): {timeit('atbash(printable)', setup=setup)} seconds")
|
||||||
"atbash_slow(printable)",
|
|
||||||
setup="from string import printable ; from __main__ import atbash_slow",
|
|
||||||
),
|
|
||||||
"seconds",
|
|
||||||
)
|
|
||||||
print(
|
|
||||||
"> atbash()",
|
|
||||||
timeit(
|
|
||||||
"atbash(printable)",
|
|
||||||
setup="from string import printable ; from __main__ import atbash",
|
|
||||||
),
|
|
||||||
"seconds",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
131
ciphers/autokey.py
Normal file
131
ciphers/autokey.py
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
"""
|
||||||
|
https://en.wikipedia.org/wiki/Autokey_cipher
|
||||||
|
An autokey cipher (also known as the autoclave cipher) is a cipher that
|
||||||
|
incorporates the message (the plaintext) into the key.
|
||||||
|
The key is generated from the message in some automated fashion,
|
||||||
|
sometimes by selecting certain letters from the text or, more commonly,
|
||||||
|
by adding a short primer key to the front of the message.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt(plaintext: str, key: str) -> str:
|
||||||
|
"""
|
||||||
|
Encrypt a given plaintext (string) and key (string), returning the
|
||||||
|
encrypted ciphertext.
|
||||||
|
>>> encrypt("hello world", "coffee")
|
||||||
|
'jsqqs avvwo'
|
||||||
|
>>> encrypt("coffee is good as python", "TheAlgorithms")
|
||||||
|
'vvjfpk wj ohvp su ddylsv'
|
||||||
|
>>> encrypt("coffee is good as python", 2)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: key must be a string
|
||||||
|
>>> encrypt("", "TheAlgorithms")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: plaintext is empty
|
||||||
|
"""
|
||||||
|
if not isinstance(plaintext, str):
|
||||||
|
raise TypeError("plaintext must be a string")
|
||||||
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("key must be a string")
|
||||||
|
|
||||||
|
if not plaintext:
|
||||||
|
raise ValueError("plaintext is empty")
|
||||||
|
if not key:
|
||||||
|
raise ValueError("key is empty")
|
||||||
|
|
||||||
|
key += plaintext
|
||||||
|
plaintext = plaintext.lower()
|
||||||
|
key = key.lower()
|
||||||
|
plaintext_iterator = 0
|
||||||
|
key_iterator = 0
|
||||||
|
ciphertext = ""
|
||||||
|
while plaintext_iterator < len(plaintext):
|
||||||
|
if (
|
||||||
|
ord(plaintext[plaintext_iterator]) < 97
|
||||||
|
or ord(plaintext[plaintext_iterator]) > 122
|
||||||
|
):
|
||||||
|
ciphertext += plaintext[plaintext_iterator]
|
||||||
|
plaintext_iterator += 1
|
||||||
|
elif ord(key[key_iterator]) < 97 or ord(key[key_iterator]) > 122:
|
||||||
|
key_iterator += 1
|
||||||
|
else:
|
||||||
|
ciphertext += chr(
|
||||||
|
(
|
||||||
|
(ord(plaintext[plaintext_iterator]) - 97 + ord(key[key_iterator]))
|
||||||
|
- 97
|
||||||
|
)
|
||||||
|
% 26
|
||||||
|
+ 97
|
||||||
|
)
|
||||||
|
key_iterator += 1
|
||||||
|
plaintext_iterator += 1
|
||||||
|
return ciphertext
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt(ciphertext: str, key: str) -> str:
|
||||||
|
"""
|
||||||
|
Decrypt a given ciphertext (string) and key (string), returning the decrypted
|
||||||
|
ciphertext.
|
||||||
|
>>> decrypt("jsqqs avvwo", "coffee")
|
||||||
|
'hello world'
|
||||||
|
>>> decrypt("vvjfpk wj ohvp su ddylsv", "TheAlgorithms")
|
||||||
|
'coffee is good as python'
|
||||||
|
>>> decrypt("vvjfpk wj ohvp su ddylsv", "")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: key is empty
|
||||||
|
>>> decrypt(527.26, "TheAlgorithms")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
TypeError: ciphertext must be a string
|
||||||
|
"""
|
||||||
|
if not isinstance(ciphertext, str):
|
||||||
|
raise TypeError("ciphertext must be a string")
|
||||||
|
if not isinstance(key, str):
|
||||||
|
raise TypeError("key must be a string")
|
||||||
|
|
||||||
|
if not ciphertext:
|
||||||
|
raise ValueError("ciphertext is empty")
|
||||||
|
if not key:
|
||||||
|
raise ValueError("key is empty")
|
||||||
|
|
||||||
|
key = key.lower()
|
||||||
|
ciphertext_iterator = 0
|
||||||
|
key_iterator = 0
|
||||||
|
plaintext = ""
|
||||||
|
while ciphertext_iterator < len(ciphertext):
|
||||||
|
if (
|
||||||
|
ord(ciphertext[ciphertext_iterator]) < 97
|
||||||
|
or ord(ciphertext[ciphertext_iterator]) > 122
|
||||||
|
):
|
||||||
|
plaintext += ciphertext[ciphertext_iterator]
|
||||||
|
else:
|
||||||
|
plaintext += chr(
|
||||||
|
(ord(ciphertext[ciphertext_iterator]) - ord(key[key_iterator])) % 26
|
||||||
|
+ 97
|
||||||
|
)
|
||||||
|
key += chr(
|
||||||
|
(ord(ciphertext[ciphertext_iterator]) - ord(key[key_iterator])) % 26
|
||||||
|
+ 97
|
||||||
|
)
|
||||||
|
key_iterator += 1
|
||||||
|
ciphertext_iterator += 1
|
||||||
|
return plaintext
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
|
||||||
|
doctest.testmod()
|
||||||
|
operation = int(input("Type 1 to encrypt or 2 to decrypt:"))
|
||||||
|
if operation == 1:
|
||||||
|
plaintext = input("Typeplaintext to be encrypted:\n")
|
||||||
|
key = input("Type the key:\n")
|
||||||
|
print(encrypt(plaintext, key))
|
||||||
|
elif operation == 2:
|
||||||
|
ciphertext = input("Type the ciphertext to be decrypted:\n")
|
||||||
|
key = input("Type the key:\n")
|
||||||
|
print(decrypt(ciphertext, key))
|
||||||
|
decrypt("jsqqs avvwo", "coffee")
|
@ -1,34 +1,63 @@
|
|||||||
import base64
|
def base16_encode(data: bytes) -> str:
|
||||||
|
|
||||||
|
|
||||||
def base16_encode(inp: str) -> bytes:
|
|
||||||
"""
|
"""
|
||||||
Encodes a given utf-8 string into base-16.
|
Encodes the given bytes into base16.
|
||||||
|
|
||||||
>>> base16_encode('Hello World!')
|
>>> base16_encode(b'Hello World!')
|
||||||
b'48656C6C6F20576F726C6421'
|
'48656C6C6F20576F726C6421'
|
||||||
>>> base16_encode('HELLO WORLD!')
|
>>> base16_encode(b'HELLO WORLD!')
|
||||||
b'48454C4C4F20574F524C4421'
|
'48454C4C4F20574F524C4421'
|
||||||
>>> base16_encode('')
|
>>> base16_encode(b'')
|
||||||
b''
|
|
||||||
"""
|
|
||||||
# encode the input into a bytes-like object and then encode b16encode that
|
|
||||||
return base64.b16encode(inp.encode("utf-8"))
|
|
||||||
|
|
||||||
|
|
||||||
def base16_decode(b16encoded: bytes) -> str:
|
|
||||||
"""
|
|
||||||
Decodes from base-16 to a utf-8 string.
|
|
||||||
|
|
||||||
>>> base16_decode(b'48656C6C6F20576F726C6421')
|
|
||||||
'Hello World!'
|
|
||||||
>>> base16_decode(b'48454C4C4F20574F524C4421')
|
|
||||||
'HELLO WORLD!'
|
|
||||||
>>> base16_decode(b'')
|
|
||||||
''
|
''
|
||||||
"""
|
"""
|
||||||
# b16decode the input into bytes and decode that into a human readable string
|
# Turn the data into a list of integers (where each integer is a byte),
|
||||||
return base64.b16decode(b16encoded).decode("utf-8")
|
# Then turn each byte into its hexadecimal representation, make sure
|
||||||
|
# it is uppercase, and then join everything together and return it.
|
||||||
|
return "".join([hex(byte)[2:].zfill(2).upper() for byte in list(data)])
|
||||||
|
|
||||||
|
|
||||||
|
def base16_decode(data: str) -> bytes:
|
||||||
|
"""
|
||||||
|
Decodes the given base16 encoded data into bytes.
|
||||||
|
|
||||||
|
>>> base16_decode('48656C6C6F20576F726C6421')
|
||||||
|
b'Hello World!'
|
||||||
|
>>> base16_decode('48454C4C4F20574F524C4421')
|
||||||
|
b'HELLO WORLD!'
|
||||||
|
>>> base16_decode('')
|
||||||
|
b''
|
||||||
|
>>> base16_decode('486')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Base16 encoded data is invalid:
|
||||||
|
Data does not have an even number of hex digits.
|
||||||
|
>>> base16_decode('48656c6c6f20576f726c6421')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Base16 encoded data is invalid:
|
||||||
|
Data is not uppercase hex or it contains invalid characters.
|
||||||
|
>>> base16_decode('This is not base64 encoded data.')
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Base16 encoded data is invalid:
|
||||||
|
Data is not uppercase hex or it contains invalid characters.
|
||||||
|
"""
|
||||||
|
# Check data validity, following RFC3548
|
||||||
|
# https://www.ietf.org/rfc/rfc3548.txt
|
||||||
|
if (len(data) % 2) != 0:
|
||||||
|
raise ValueError(
|
||||||
|
"""Base16 encoded data is invalid:
|
||||||
|
Data does not have an even number of hex digits."""
|
||||||
|
)
|
||||||
|
# Check the character set - the standard base16 alphabet
|
||||||
|
# is uppercase according to RFC3548 section 6
|
||||||
|
if not set(data) <= set("0123456789ABCDEF"):
|
||||||
|
raise ValueError(
|
||||||
|
"""Base16 encoded data is invalid:
|
||||||
|
Data is not uppercase hex or it contains invalid characters."""
|
||||||
|
)
|
||||||
|
# For every two hexadecimal digits (= a byte), turn it into an integer.
|
||||||
|
# Then, string the result together into bytes, and return it.
|
||||||
|
return bytes(int(data[i] + data[i + 1], 16) for i in range(0, len(data), 2))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -34,9 +34,8 @@ def base64_encode(data: bytes) -> bytes:
|
|||||||
"""
|
"""
|
||||||
# Make sure the supplied data is a bytes-like object
|
# Make sure the supplied data is a bytes-like object
|
||||||
if not isinstance(data, bytes):
|
if not isinstance(data, bytes):
|
||||||
raise TypeError(
|
msg = f"a bytes-like object is required, not '{data.__class__.__name__}'"
|
||||||
f"a bytes-like object is required, not '{data.__class__.__name__}'"
|
raise TypeError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
binary_stream = "".join(bin(byte)[2:].zfill(8) for byte in data)
|
binary_stream = "".join(bin(byte)[2:].zfill(8) for byte in data)
|
||||||
|
|
||||||
@ -88,10 +87,11 @@ def base64_decode(encoded_data: str) -> bytes:
|
|||||||
"""
|
"""
|
||||||
# Make sure encoded_data is either a string or a bytes-like object
|
# Make sure encoded_data is either a string or a bytes-like object
|
||||||
if not isinstance(encoded_data, bytes) and not isinstance(encoded_data, str):
|
if not isinstance(encoded_data, bytes) and not isinstance(encoded_data, str):
|
||||||
raise TypeError(
|
msg = (
|
||||||
"argument should be a bytes-like object or ASCII string, not "
|
"argument should be a bytes-like object or ASCII string, "
|
||||||
f"'{encoded_data.__class__.__name__}'"
|
f"not '{encoded_data.__class__.__name__}'"
|
||||||
)
|
)
|
||||||
|
raise TypeError(msg)
|
||||||
|
|
||||||
# In case encoded_data is a bytes-like object, make sure it contains only
|
# In case encoded_data is a bytes-like object, make sure it contains only
|
||||||
# ASCII characters so we convert it to a string object
|
# ASCII characters so we convert it to a string object
|
||||||
|
@ -5,7 +5,7 @@ Author: Mohit Radadiya
|
|||||||
from string import ascii_uppercase
|
from string import ascii_uppercase
|
||||||
|
|
||||||
dict1 = {char: i for i, char in enumerate(ascii_uppercase)}
|
dict1 = {char: i for i, char in enumerate(ascii_uppercase)}
|
||||||
dict2 = {i: char for i, char in enumerate(ascii_uppercase)}
|
dict2 = dict(enumerate(ascii_uppercase))
|
||||||
|
|
||||||
|
|
||||||
# This function generates the key in
|
# This function generates the key in
|
||||||
|
@ -9,16 +9,17 @@ https://www.braingle.com/brainteasers/codes/bifid.php
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
SQUARE = [
|
||||||
|
["a", "b", "c", "d", "e"],
|
||||||
|
["f", "g", "h", "i", "k"],
|
||||||
|
["l", "m", "n", "o", "p"],
|
||||||
|
["q", "r", "s", "t", "u"],
|
||||||
|
["v", "w", "x", "y", "z"],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class BifidCipher:
|
class BifidCipher:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
SQUARE = [
|
|
||||||
["a", "b", "c", "d", "e"],
|
|
||||||
["f", "g", "h", "i", "k"],
|
|
||||||
["l", "m", "n", "o", "p"],
|
|
||||||
["q", "r", "s", "t", "u"],
|
|
||||||
["v", "w", "x", "y", "z"],
|
|
||||||
]
|
|
||||||
self.SQUARE = np.array(SQUARE)
|
self.SQUARE = np.array(SQUARE)
|
||||||
|
|
||||||
def letter_to_numbers(self, letter: str) -> np.ndarray:
|
def letter_to_numbers(self, letter: str) -> np.ndarray:
|
||||||
@ -32,7 +33,7 @@ class BifidCipher:
|
|||||||
>>> np.array_equal(BifidCipher().letter_to_numbers('u'), [4,5])
|
>>> np.array_equal(BifidCipher().letter_to_numbers('u'), [4,5])
|
||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
index1, index2 = np.where(self.SQUARE == letter)
|
index1, index2 = np.where(letter == self.SQUARE)
|
||||||
indexes = np.concatenate([index1 + 1, index2 + 1])
|
indexes = np.concatenate([index1 + 1, index2 + 1])
|
||||||
return indexes
|
return indexes
|
||||||
|
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
|
import string
|
||||||
|
|
||||||
|
|
||||||
def decrypt(message: str) -> None:
|
def decrypt(message: str) -> None:
|
||||||
"""
|
"""
|
||||||
>>> decrypt('TMDETUX PMDVU')
|
>>> decrypt('TMDETUX PMDVU')
|
||||||
@ -28,16 +31,15 @@ def decrypt(message: str) -> None:
|
|||||||
Decryption using Key #24: VOFGVWZ ROFXW
|
Decryption using Key #24: VOFGVWZ ROFXW
|
||||||
Decryption using Key #25: UNEFUVY QNEWV
|
Decryption using Key #25: UNEFUVY QNEWV
|
||||||
"""
|
"""
|
||||||
LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
for key in range(len(string.ascii_uppercase)):
|
||||||
for key in range(len(LETTERS)):
|
|
||||||
translated = ""
|
translated = ""
|
||||||
for symbol in message:
|
for symbol in message:
|
||||||
if symbol in LETTERS:
|
if symbol in string.ascii_uppercase:
|
||||||
num = LETTERS.find(symbol)
|
num = string.ascii_uppercase.find(symbol)
|
||||||
num = num - key
|
num = num - key
|
||||||
if num < 0:
|
if num < 0:
|
||||||
num = num + len(LETTERS)
|
num = num + len(string.ascii_uppercase)
|
||||||
translated = translated + LETTERS[num]
|
translated = translated + string.ascii_uppercase[num]
|
||||||
else:
|
else:
|
||||||
translated = translated + symbol
|
translated = translated + symbol
|
||||||
print(f"Decryption using Key #{key}: {translated}")
|
print(f"Decryption using Key #{key}: {translated}")
|
||||||
|
@ -27,7 +27,7 @@ def encrypt(input_string: str, key: int, alphabet: str | None = None) -> str:
|
|||||||
=========================
|
=========================
|
||||||
The caesar cipher is named after Julius Caesar who used it when sending
|
The caesar cipher is named after Julius Caesar who used it when sending
|
||||||
secret military messages to his troops. This is a simple substitution cipher
|
secret military messages to his troops. This is a simple substitution cipher
|
||||||
where very character in the plain-text is shifted by a certain number known
|
where every character in the plain-text is shifted by a certain number known
|
||||||
as the "key" or "shift".
|
as the "key" or "shift".
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
@ -6,7 +6,8 @@ def gcd(a: int, b: int) -> int:
|
|||||||
|
|
||||||
def find_mod_inverse(a: int, m: int) -> int:
|
def find_mod_inverse(a: int, m: int) -> int:
|
||||||
if gcd(a, m) != 1:
|
if gcd(a, m) != 1:
|
||||||
raise ValueError(f"mod inverse of {a!r} and {m!r} does not exist")
|
msg = f"mod inverse of {a!r} and {m!r} does not exist"
|
||||||
|
raise ValueError(msg)
|
||||||
u1, u2, u3 = 1, 0, a
|
u1, u2, u3 = 1, 0, a
|
||||||
v1, v2, v3 = 0, 1, m
|
v1, v2, v3 = 0, 1, m
|
||||||
while v3 != 0:
|
while v3 != 0:
|
||||||
|
@ -228,10 +228,10 @@ class DiffieHellman:
|
|||||||
|
|
||||||
def is_valid_public_key(self, key: int) -> bool:
|
def is_valid_public_key(self, key: int) -> bool:
|
||||||
# check if the other public key is valid based on NIST SP800-56
|
# check if the other public key is valid based on NIST SP800-56
|
||||||
if 2 <= key and key <= self.prime - 2:
|
return (
|
||||||
if pow(key, (self.prime - 1) // 2, self.prime) == 1:
|
2 <= key <= self.prime - 2
|
||||||
return True
|
and pow(key, (self.prime - 1) // 2, self.prime) == 1
|
||||||
return False
|
)
|
||||||
|
|
||||||
def generate_shared_key(self, other_key_str: str) -> str:
|
def generate_shared_key(self, other_key_str: str) -> str:
|
||||||
other_key = int(other_key_str, base=16)
|
other_key = int(other_key_str, base=16)
|
||||||
@ -243,10 +243,10 @@ class DiffieHellman:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def is_valid_public_key_static(remote_public_key_str: int, prime: int) -> bool:
|
def is_valid_public_key_static(remote_public_key_str: int, prime: int) -> bool:
|
||||||
# check if the other public key is valid based on NIST SP800-56
|
# check if the other public key is valid based on NIST SP800-56
|
||||||
if 2 <= remote_public_key_str and remote_public_key_str <= prime - 2:
|
return (
|
||||||
if pow(remote_public_key_str, (prime - 1) // 2, prime) == 1:
|
2 <= remote_public_key_str <= prime - 2
|
||||||
return True
|
and pow(remote_public_key_str, (prime - 1) // 2, prime) == 1
|
||||||
return False
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def generate_shared_key_static(
|
def generate_shared_key_static(
|
||||||
|
@ -26,7 +26,7 @@ def primitive_root(p_val: int) -> int:
|
|||||||
|
|
||||||
def generate_key(key_size: int) -> tuple[tuple[int, int, int, int], tuple[int, int]]:
|
def generate_key(key_size: int) -> tuple[tuple[int, int, int, int], tuple[int, int]]:
|
||||||
print("Generating prime p...")
|
print("Generating prime p...")
|
||||||
p = rabin_miller.generateLargePrime(key_size) # select large prime number.
|
p = rabin_miller.generate_large_prime(key_size) # select large prime number.
|
||||||
e_1 = primitive_root(p) # one primitive root on modulo p.
|
e_1 = primitive_root(p) # one primitive root on modulo p.
|
||||||
d = random.randrange(3, p) # private_key -> have to be greater than 2 for safety.
|
d = random.randrange(3, p) # private_key -> have to be greater than 2 for safety.
|
||||||
e_2 = cryptomath.find_mod_inverse(pow(e_1, d, p), p)
|
e_2 = cryptomath.find_mod_inverse(pow(e_1, d, p), p)
|
||||||
@ -37,26 +37,23 @@ def generate_key(key_size: int) -> tuple[tuple[int, int, int, int], tuple[int, i
|
|||||||
return public_key, private_key
|
return public_key, private_key
|
||||||
|
|
||||||
|
|
||||||
def make_key_files(name: str, keySize: int) -> None:
|
def make_key_files(name: str, key_size: int) -> None:
|
||||||
if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"):
|
if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"):
|
||||||
print("\nWARNING:")
|
print("\nWARNING:")
|
||||||
print(
|
print(
|
||||||
'"%s_pubkey.txt" or "%s_privkey.txt" already exists. \n'
|
f'"{name}_pubkey.txt" or "{name}_privkey.txt" already exists. \n'
|
||||||
"Use a different name or delete these files and re-run this program."
|
"Use a different name or delete these files and re-run this program."
|
||||||
% (name, name)
|
|
||||||
)
|
)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
publicKey, privateKey = generate_key(keySize)
|
public_key, private_key = generate_key(key_size)
|
||||||
print(f"\nWriting public key to file {name}_pubkey.txt...")
|
print(f"\nWriting public key to file {name}_pubkey.txt...")
|
||||||
with open(f"{name}_pubkey.txt", "w") as fo:
|
with open(f"{name}_pubkey.txt", "w") as fo:
|
||||||
fo.write(
|
fo.write(f"{public_key[0]},{public_key[1]},{public_key[2]},{public_key[3]}")
|
||||||
"%d,%d,%d,%d" % (publicKey[0], publicKey[1], publicKey[2], publicKey[3])
|
|
||||||
)
|
|
||||||
|
|
||||||
print(f"Writing private key to file {name}_privkey.txt...")
|
print(f"Writing private key to file {name}_privkey.txt...")
|
||||||
with open(f"{name}_privkey.txt", "w") as fo:
|
with open(f"{name}_privkey.txt", "w") as fo:
|
||||||
fo.write("%d,%d" % (privateKey[0], privateKey[1]))
|
fo.write(f"{private_key[0]},{private_key[1]}")
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
|
@ -86,24 +86,21 @@ def _validator(
|
|||||||
"""
|
"""
|
||||||
# Checks if there are 3 unique rotors
|
# Checks if there are 3 unique rotors
|
||||||
|
|
||||||
unique_rotsel = len(set(rotsel))
|
if (unique_rotsel := len(set(rotsel))) < 3:
|
||||||
if unique_rotsel < 3:
|
msg = f"Please use 3 unique rotors (not {unique_rotsel})"
|
||||||
raise Exception(f"Please use 3 unique rotors (not {unique_rotsel})")
|
raise Exception(msg)
|
||||||
|
|
||||||
# Checks if rotor positions are valid
|
# Checks if rotor positions are valid
|
||||||
rotorpos1, rotorpos2, rotorpos3 = rotpos
|
rotorpos1, rotorpos2, rotorpos3 = rotpos
|
||||||
if not 0 < rotorpos1 <= len(abc):
|
if not 0 < rotorpos1 <= len(abc):
|
||||||
raise ValueError(
|
msg = f"First rotor position is not within range of 1..26 ({rotorpos1}"
|
||||||
"First rotor position is not within range of 1..26 (" f"{rotorpos1}"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
if not 0 < rotorpos2 <= len(abc):
|
if not 0 < rotorpos2 <= len(abc):
|
||||||
raise ValueError(
|
msg = f"Second rotor position is not within range of 1..26 ({rotorpos2})"
|
||||||
"Second rotor position is not within range of 1..26 (" f"{rotorpos2})"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
if not 0 < rotorpos3 <= len(abc):
|
if not 0 < rotorpos3 <= len(abc):
|
||||||
raise ValueError(
|
msg = f"Third rotor position is not within range of 1..26 ({rotorpos3})"
|
||||||
"Third rotor position is not within range of 1..26 (" f"{rotorpos3})"
|
raise ValueError(msg)
|
||||||
)
|
|
||||||
|
|
||||||
# Validates string and returns dict
|
# Validates string and returns dict
|
||||||
pbdict = _plugboard(pb)
|
pbdict = _plugboard(pb)
|
||||||
@ -131,9 +128,11 @@ def _plugboard(pbstring: str) -> dict[str, str]:
|
|||||||
# a) is type string
|
# a) is type string
|
||||||
# b) has even length (so pairs can be made)
|
# b) has even length (so pairs can be made)
|
||||||
if not isinstance(pbstring, str):
|
if not isinstance(pbstring, str):
|
||||||
raise TypeError(f"Plugboard setting isn't type string ({type(pbstring)})")
|
msg = f"Plugboard setting isn't type string ({type(pbstring)})"
|
||||||
|
raise TypeError(msg)
|
||||||
elif len(pbstring) % 2 != 0:
|
elif len(pbstring) % 2 != 0:
|
||||||
raise Exception(f"Odd number of symbols ({len(pbstring)})")
|
msg = f"Odd number of symbols ({len(pbstring)})"
|
||||||
|
raise Exception(msg)
|
||||||
elif pbstring == "":
|
elif pbstring == "":
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
@ -143,9 +142,11 @@ def _plugboard(pbstring: str) -> dict[str, str]:
|
|||||||
tmppbl = set()
|
tmppbl = set()
|
||||||
for i in pbstring:
|
for i in pbstring:
|
||||||
if i not in abc:
|
if i not in abc:
|
||||||
raise Exception(f"'{i}' not in list of symbols")
|
msg = f"'{i}' not in list of symbols"
|
||||||
|
raise Exception(msg)
|
||||||
elif i in tmppbl:
|
elif i in tmppbl:
|
||||||
raise Exception(f"Duplicate symbol ({i})")
|
msg = f"Duplicate symbol ({i})"
|
||||||
|
raise Exception(msg)
|
||||||
else:
|
else:
|
||||||
tmppbl.add(i)
|
tmppbl.add(i)
|
||||||
del tmppbl
|
del tmppbl
|
||||||
@ -231,7 +232,6 @@ def enigma(
|
|||||||
# encryption/decryption process --------------------------
|
# encryption/decryption process --------------------------
|
||||||
for symbol in text:
|
for symbol in text:
|
||||||
if symbol in abc:
|
if symbol in abc:
|
||||||
|
|
||||||
# 1st plugboard --------------------------
|
# 1st plugboard --------------------------
|
||||||
if symbol in plugboard:
|
if symbol in plugboard:
|
||||||
symbol = plugboard[symbol]
|
symbol = plugboard[symbol]
|
||||||
|
@ -104,10 +104,11 @@ class HillCipher:
|
|||||||
|
|
||||||
req_l = len(self.key_string)
|
req_l = len(self.key_string)
|
||||||
if greatest_common_divisor(det, len(self.key_string)) != 1:
|
if greatest_common_divisor(det, len(self.key_string)) != 1:
|
||||||
raise ValueError(
|
msg = (
|
||||||
f"determinant modular {req_l} of encryption key({det}) is not co prime "
|
f"determinant modular {req_l} of encryption key({det}) "
|
||||||
f"w.r.t {req_l}.\nTry another key."
|
f"is not co prime w.r.t {req_l}.\nTry another key."
|
||||||
)
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
def process_text(self, text: str) -> str:
|
def process_text(self, text: str) -> str:
|
||||||
"""
|
"""
|
||||||
@ -201,11 +202,11 @@ class HillCipher:
|
|||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
N = int(input("Enter the order of the encryption key: "))
|
n = int(input("Enter the order of the encryption key: "))
|
||||||
hill_matrix = []
|
hill_matrix = []
|
||||||
|
|
||||||
print("Enter each row of the encryption key with space separated integers")
|
print("Enter each row of the encryption key with space separated integers")
|
||||||
for _ in range(N):
|
for _ in range(n):
|
||||||
row = [int(x) for x in input().split()]
|
row = [int(x) for x in input().split()]
|
||||||
hill_matrix.append(row)
|
hill_matrix.append(row)
|
||||||
|
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str:
|
from string import ascii_uppercase
|
||||||
"""
|
|
||||||
|
|
||||||
For key:hello
|
|
||||||
|
def mixed_keyword(
|
||||||
|
keyword: str, plaintext: str, verbose: bool = False, alphabet: str = ascii_uppercase
|
||||||
|
) -> str:
|
||||||
|
"""
|
||||||
|
For keyword: hello
|
||||||
|
|
||||||
H E L O
|
H E L O
|
||||||
A B C D
|
A B C D
|
||||||
@ -12,57 +16,60 @@ def mixed_keyword(key: str = "college", pt: str = "UNIVERSITY") -> str:
|
|||||||
Y Z
|
Y Z
|
||||||
and map vertically
|
and map vertically
|
||||||
|
|
||||||
>>> mixed_keyword("college", "UNIVERSITY") # doctest: +NORMALIZE_WHITESPACE
|
>>> mixed_keyword("college", "UNIVERSITY", True) # doctest: +NORMALIZE_WHITESPACE
|
||||||
{'A': 'C', 'B': 'A', 'C': 'I', 'D': 'P', 'E': 'U', 'F': 'Z', 'G': 'O', 'H': 'B',
|
{'A': 'C', 'B': 'A', 'C': 'I', 'D': 'P', 'E': 'U', 'F': 'Z', 'G': 'O', 'H': 'B',
|
||||||
'I': 'J', 'J': 'Q', 'K': 'V', 'L': 'L', 'M': 'D', 'N': 'K', 'O': 'R', 'P': 'W',
|
'I': 'J', 'J': 'Q', 'K': 'V', 'L': 'L', 'M': 'D', 'N': 'K', 'O': 'R', 'P': 'W',
|
||||||
'Q': 'E', 'R': 'F', 'S': 'M', 'T': 'S', 'U': 'X', 'V': 'G', 'W': 'H', 'X': 'N',
|
'Q': 'E', 'R': 'F', 'S': 'M', 'T': 'S', 'U': 'X', 'V': 'G', 'W': 'H', 'X': 'N',
|
||||||
'Y': 'T', 'Z': 'Y'}
|
'Y': 'T', 'Z': 'Y'}
|
||||||
'XKJGUFMJST'
|
'XKJGUFMJST'
|
||||||
|
|
||||||
|
>>> mixed_keyword("college", "UNIVERSITY", False) # doctest: +NORMALIZE_WHITESPACE
|
||||||
|
'XKJGUFMJST'
|
||||||
"""
|
"""
|
||||||
key = key.upper()
|
keyword = keyword.upper()
|
||||||
pt = pt.upper()
|
plaintext = plaintext.upper()
|
||||||
temp = []
|
alphabet_set = set(alphabet)
|
||||||
for i in key:
|
|
||||||
if i not in temp:
|
# create a list of unique characters in the keyword - their order matters
|
||||||
temp.append(i)
|
# it determines how we will map plaintext characters to the ciphertext
|
||||||
len_temp = len(temp)
|
unique_chars = []
|
||||||
# print(temp)
|
for char in keyword:
|
||||||
alpha = []
|
if char in alphabet_set and char not in unique_chars:
|
||||||
modalpha = []
|
unique_chars.append(char)
|
||||||
for j in range(65, 91):
|
# the number of those unique characters will determine the number of rows
|
||||||
t = chr(j)
|
num_unique_chars_in_keyword = len(unique_chars)
|
||||||
alpha.append(t)
|
|
||||||
if t not in temp:
|
# create a shifted version of the alphabet
|
||||||
temp.append(t)
|
shifted_alphabet = unique_chars + [
|
||||||
# print(temp)
|
char for char in alphabet if char not in unique_chars
|
||||||
r = int(26 / 4)
|
]
|
||||||
# print(r)
|
|
||||||
k = 0
|
# create a modified alphabet by splitting the shifted alphabet into rows
|
||||||
for _ in range(r):
|
modified_alphabet = [
|
||||||
s = []
|
shifted_alphabet[k : k + num_unique_chars_in_keyword]
|
||||||
for j in range(len_temp):
|
for k in range(0, 26, num_unique_chars_in_keyword)
|
||||||
s.append(temp[k])
|
]
|
||||||
if not (k < 25):
|
|
||||||
|
# map the alphabet characters to the modified alphabet characters
|
||||||
|
# going 'vertically' through the modified alphabet - consider columns first
|
||||||
|
mapping = {}
|
||||||
|
letter_index = 0
|
||||||
|
for column in range(num_unique_chars_in_keyword):
|
||||||
|
for row in modified_alphabet:
|
||||||
|
# if current row (the last one) is too short, break out of loop
|
||||||
|
if len(row) <= column:
|
||||||
break
|
break
|
||||||
k += 1
|
|
||||||
modalpha.append(s)
|
# map current letter to letter in modified alphabet
|
||||||
# print(modalpha)
|
mapping[alphabet[letter_index]] = row[column]
|
||||||
d = {}
|
letter_index += 1
|
||||||
j = 0
|
|
||||||
k = 0
|
if verbose:
|
||||||
for j in range(len_temp):
|
print(mapping)
|
||||||
for m in modalpha:
|
# create the encrypted text by mapping the plaintext to the modified alphabet
|
||||||
if not (len(m) - 1 >= j):
|
return "".join(mapping[char] if char in mapping else char for char in plaintext)
|
||||||
break
|
|
||||||
d[alpha[k]] = m[j]
|
|
||||||
if not k < 25:
|
|
||||||
break
|
|
||||||
k += 1
|
|
||||||
print(d)
|
|
||||||
cypher = ""
|
|
||||||
for i in pt:
|
|
||||||
cypher += d[i]
|
|
||||||
return cypher
|
|
||||||
|
|
||||||
|
|
||||||
print(mixed_keyword("college", "UNIVERSITY"))
|
if __name__ == "__main__":
|
||||||
|
# example use
|
||||||
|
print(mixed_keyword("college", "UNIVERSITY"))
|
||||||
|
@ -22,7 +22,7 @@ class Onepad:
|
|||||||
for i in range(len(key)):
|
for i in range(len(key)):
|
||||||
p = int((cipher[i] - (key[i]) ** 2) / key[i])
|
p = int((cipher[i] - (key[i]) ** 2) / key[i])
|
||||||
plain.append(chr(p))
|
plain.append(chr(p))
|
||||||
return "".join([i for i in plain])
|
return "".join(plain)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -39,7 +39,6 @@ def prepare_input(dirty: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def generate_table(key: str) -> list[str]:
|
def generate_table(key: str) -> list[str]:
|
||||||
|
|
||||||
# I and J are used interchangeably to allow
|
# I and J are used interchangeably to allow
|
||||||
# us to use a 5x5 table (25 letters)
|
# us to use a 5x5 table (25 letters)
|
||||||
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
|
alphabet = "ABCDEFGHIKLMNOPQRSTUVWXYZ"
|
||||||
|
@ -8,16 +8,17 @@ https://www.braingle.com/brainteasers/codes/polybius.php
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
SQUARE = [
|
||||||
|
["a", "b", "c", "d", "e"],
|
||||||
|
["f", "g", "h", "i", "k"],
|
||||||
|
["l", "m", "n", "o", "p"],
|
||||||
|
["q", "r", "s", "t", "u"],
|
||||||
|
["v", "w", "x", "y", "z"],
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class PolybiusCipher:
|
class PolybiusCipher:
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
SQUARE = [
|
|
||||||
["a", "b", "c", "d", "e"],
|
|
||||||
["f", "g", "h", "i", "k"],
|
|
||||||
["l", "m", "n", "o", "p"],
|
|
||||||
["q", "r", "s", "t", "u"],
|
|
||||||
["v", "w", "x", "y", "z"],
|
|
||||||
]
|
|
||||||
self.SQUARE = np.array(SQUARE)
|
self.SQUARE = np.array(SQUARE)
|
||||||
|
|
||||||
def letter_to_numbers(self, letter: str) -> np.ndarray:
|
def letter_to_numbers(self, letter: str) -> np.ndarray:
|
||||||
@ -30,7 +31,7 @@ class PolybiusCipher:
|
|||||||
>>> np.array_equal(PolybiusCipher().letter_to_numbers('u'), [4,5])
|
>>> np.array_equal(PolybiusCipher().letter_to_numbers('u'), [4,5])
|
||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
index1, index2 = np.where(self.SQUARE == letter)
|
index1, index2 = np.where(letter == self.SQUARE)
|
||||||
indexes = np.concatenate([index1 + 1, index2 + 1])
|
indexes = np.concatenate([index1 + 1, index2 + 1])
|
||||||
return indexes
|
return indexes
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
def rabinMiller(num: int) -> bool:
|
def rabin_miller(num: int) -> bool:
|
||||||
s = num - 1
|
s = num - 1
|
||||||
t = 0
|
t = 0
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ def rabinMiller(num: int) -> bool:
|
|||||||
s = s // 2
|
s = s // 2
|
||||||
t += 1
|
t += 1
|
||||||
|
|
||||||
for trials in range(5):
|
for _ in range(5):
|
||||||
a = random.randrange(2, num - 1)
|
a = random.randrange(2, num - 1)
|
||||||
v = pow(a, s, num)
|
v = pow(a, s, num)
|
||||||
if v != 1:
|
if v != 1:
|
||||||
@ -29,7 +29,7 @@ def is_prime_low_num(num: int) -> bool:
|
|||||||
if num < 2:
|
if num < 2:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
lowPrimes = [
|
low_primes = [
|
||||||
2,
|
2,
|
||||||
3,
|
3,
|
||||||
5,
|
5,
|
||||||
@ -200,17 +200,17 @@ def is_prime_low_num(num: int) -> bool:
|
|||||||
997,
|
997,
|
||||||
]
|
]
|
||||||
|
|
||||||
if num in lowPrimes:
|
if num in low_primes:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
for prime in lowPrimes:
|
for prime in low_primes:
|
||||||
if (num % prime) == 0:
|
if (num % prime) == 0:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return rabinMiller(num)
|
return rabin_miller(num)
|
||||||
|
|
||||||
|
|
||||||
def generateLargePrime(keysize: int = 1024) -> int:
|
def generate_large_prime(keysize: int = 1024) -> int:
|
||||||
while True:
|
while True:
|
||||||
num = random.randrange(2 ** (keysize - 1), 2 ** (keysize))
|
num = random.randrange(2 ** (keysize - 1), 2 ** (keysize))
|
||||||
if is_prime_low_num(num):
|
if is_prime_low_num(num):
|
||||||
@ -218,6 +218,6 @@ def generateLargePrime(keysize: int = 1024) -> int:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
num = generateLargePrime()
|
num = generate_large_prime()
|
||||||
print(("Prime number:", num))
|
print(("Prime number:", num))
|
||||||
print(("is_prime_low_num:", is_prime_low_num(num)))
|
print(("is_prime_low_num:", is_prime_low_num(num)))
|
||||||
|
@ -72,7 +72,7 @@ def decrypt(input_string: str, key: int) -> str:
|
|||||||
counter = 0
|
counter = 0
|
||||||
for row in temp_grid: # fills in the characters
|
for row in temp_grid: # fills in the characters
|
||||||
splice = input_string[counter : counter + len(row)]
|
splice = input_string[counter : counter + len(row)]
|
||||||
grid.append([character for character in splice])
|
grid.append(list(splice))
|
||||||
counter += len(row)
|
counter += len(row)
|
||||||
|
|
||||||
output_string = "" # reads as zigzag
|
output_string = "" # reads as zigzag
|
||||||
|
@ -37,12 +37,12 @@ def get_text_from_blocks(
|
|||||||
|
|
||||||
|
|
||||||
def encrypt_message(
|
def encrypt_message(
|
||||||
message: str, key: tuple[int, int], blockSize: int = DEFAULT_BLOCK_SIZE
|
message: str, key: tuple[int, int], block_size: int = DEFAULT_BLOCK_SIZE
|
||||||
) -> list[int]:
|
) -> list[int]:
|
||||||
encrypted_blocks = []
|
encrypted_blocks = []
|
||||||
n, e = key
|
n, e = key
|
||||||
|
|
||||||
for block in get_blocks_from_text(message, blockSize):
|
for block in get_blocks_from_text(message, block_size):
|
||||||
encrypted_blocks.append(pow(block, e, n))
|
encrypted_blocks.append(pow(block, e, n))
|
||||||
return encrypted_blocks
|
return encrypted_blocks
|
||||||
|
|
||||||
@ -63,8 +63,8 @@ def decrypt_message(
|
|||||||
def read_key_file(key_filename: str) -> tuple[int, int, int]:
|
def read_key_file(key_filename: str) -> tuple[int, int, int]:
|
||||||
with open(key_filename) as fo:
|
with open(key_filename) as fo:
|
||||||
content = fo.read()
|
content = fo.read()
|
||||||
key_size, n, EorD = content.split(",")
|
key_size, n, eor_d = content.split(",")
|
||||||
return (int(key_size), int(n), int(EorD))
|
return (int(key_size), int(n), int(eor_d))
|
||||||
|
|
||||||
|
|
||||||
def encrypt_and_write_to_file(
|
def encrypt_and_write_to_file(
|
||||||
@ -76,10 +76,11 @@ def encrypt_and_write_to_file(
|
|||||||
key_size, n, e = read_key_file(key_filename)
|
key_size, n, e = read_key_file(key_filename)
|
||||||
if key_size < block_size * 8:
|
if key_size < block_size * 8:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
|
"ERROR: Block size is {} bits and key size is {} bits. The RSA cipher "
|
||||||
"requires the block size to be equal to or greater than the key size. "
|
"requires the block size to be equal to or greater than the key size. "
|
||||||
"Either decrease the block size or use different keys."
|
"Either decrease the block size or use different keys.".format(
|
||||||
% (block_size * 8, key_size)
|
block_size * 8, key_size
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
encrypted_blocks = [str(i) for i in encrypt_message(message, (n, e), block_size)]
|
encrypted_blocks = [str(i) for i in encrypt_message(message, (n, e), block_size)]
|
||||||
@ -101,10 +102,11 @@ def read_from_file_and_decrypt(message_filename: str, key_filename: str) -> str:
|
|||||||
|
|
||||||
if key_size < block_size * 8:
|
if key_size < block_size * 8:
|
||||||
sys.exit(
|
sys.exit(
|
||||||
"ERROR: Block size is %s bits and key size is %s bits. The RSA cipher "
|
"ERROR: Block size is {} bits and key size is {} bits. The RSA cipher "
|
||||||
"requires the block size to be equal to or greater than the key size. "
|
"requires the block size to be equal to or greater than the key size. "
|
||||||
"Did you specify the correct key file and encrypted file?"
|
"Did you specify the correct key file and encrypted file?".format(
|
||||||
% (block_size * 8, key_size)
|
block_size * 8, key_size
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
encrypted_blocks = []
|
encrypted_blocks = []
|
||||||
@ -125,15 +127,15 @@ def main() -> None:
|
|||||||
|
|
||||||
if mode == "encrypt":
|
if mode == "encrypt":
|
||||||
if not os.path.exists("rsa_pubkey.txt"):
|
if not os.path.exists("rsa_pubkey.txt"):
|
||||||
rkg.makeKeyFiles("rsa", 1024)
|
rkg.make_key_files("rsa", 1024)
|
||||||
|
|
||||||
message = input("\nEnter message: ")
|
message = input("\nEnter message: ")
|
||||||
pubkey_filename = "rsa_pubkey.txt"
|
pubkey_filename = "rsa_pubkey.txt"
|
||||||
print(f"Encrypting and writing to {filename}...")
|
print(f"Encrypting and writing to {filename}...")
|
||||||
encryptedText = encrypt_and_write_to_file(filename, pubkey_filename, message)
|
encrypted_text = encrypt_and_write_to_file(filename, pubkey_filename, message)
|
||||||
|
|
||||||
print("\nEncrypted text:")
|
print("\nEncrypted text:")
|
||||||
print(encryptedText)
|
print(encrypted_text)
|
||||||
|
|
||||||
elif mode == "decrypt":
|
elif mode == "decrypt":
|
||||||
privkey_filename = "rsa_privkey.txt"
|
privkey_filename = "rsa_privkey.txt"
|
||||||
|
@ -13,7 +13,7 @@ import math
|
|||||||
import random
|
import random
|
||||||
|
|
||||||
|
|
||||||
def rsafactor(d: int, e: int, N: int) -> list[int]:
|
def rsafactor(d: int, e: int, n: int) -> list[int]:
|
||||||
"""
|
"""
|
||||||
This function returns the factors of N, where p*q=N
|
This function returns the factors of N, where p*q=N
|
||||||
Return: [p, q]
|
Return: [p, q]
|
||||||
@ -35,16 +35,16 @@ def rsafactor(d: int, e: int, N: int) -> list[int]:
|
|||||||
p = 0
|
p = 0
|
||||||
q = 0
|
q = 0
|
||||||
while p == 0:
|
while p == 0:
|
||||||
g = random.randint(2, N - 1)
|
g = random.randint(2, n - 1)
|
||||||
t = k
|
t = k
|
||||||
while True:
|
while True:
|
||||||
if t % 2 == 0:
|
if t % 2 == 0:
|
||||||
t = t // 2
|
t = t // 2
|
||||||
x = (g**t) % N
|
x = (g**t) % n
|
||||||
y = math.gcd(x - 1, N)
|
y = math.gcd(x - 1, n)
|
||||||
if x > 1 and y > 1:
|
if x > 1 and y > 1:
|
||||||
p = y
|
p = y
|
||||||
q = N // y
|
q = n // y
|
||||||
break # find the correct factors
|
break # find the correct factors
|
||||||
else:
|
else:
|
||||||
break # t is not divisible by 2, break and choose another g
|
break # t is not divisible by 2, break and choose another g
|
||||||
|
@ -2,55 +2,54 @@ import os
|
|||||||
import random
|
import random
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from . import cryptomath_module as cryptoMath
|
from . import cryptomath_module as cryptoMath # noqa: N812
|
||||||
from . import rabin_miller as rabinMiller
|
from . import rabin_miller as rabinMiller # noqa: N812
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
print("Making key files...")
|
print("Making key files...")
|
||||||
makeKeyFiles("rsa", 1024)
|
make_key_files("rsa", 1024)
|
||||||
print("Key files generation successful.")
|
print("Key files generation successful.")
|
||||||
|
|
||||||
|
|
||||||
def generateKey(keySize: int) -> tuple[tuple[int, int], tuple[int, int]]:
|
def generate_key(key_size: int) -> tuple[tuple[int, int], tuple[int, int]]:
|
||||||
print("Generating prime p...")
|
print("Generating prime p...")
|
||||||
p = rabinMiller.generateLargePrime(keySize)
|
p = rabinMiller.generate_large_prime(key_size)
|
||||||
print("Generating prime q...")
|
print("Generating prime q...")
|
||||||
q = rabinMiller.generateLargePrime(keySize)
|
q = rabinMiller.generate_large_prime(key_size)
|
||||||
n = p * q
|
n = p * q
|
||||||
|
|
||||||
print("Generating e that is relatively prime to (p - 1) * (q - 1)...")
|
print("Generating e that is relatively prime to (p - 1) * (q - 1)...")
|
||||||
while True:
|
while True:
|
||||||
e = random.randrange(2 ** (keySize - 1), 2 ** (keySize))
|
e = random.randrange(2 ** (key_size - 1), 2 ** (key_size))
|
||||||
if cryptoMath.gcd(e, (p - 1) * (q - 1)) == 1:
|
if cryptoMath.gcd(e, (p - 1) * (q - 1)) == 1:
|
||||||
break
|
break
|
||||||
|
|
||||||
print("Calculating d that is mod inverse of e...")
|
print("Calculating d that is mod inverse of e...")
|
||||||
d = cryptoMath.find_mod_inverse(e, (p - 1) * (q - 1))
|
d = cryptoMath.find_mod_inverse(e, (p - 1) * (q - 1))
|
||||||
|
|
||||||
publicKey = (n, e)
|
public_key = (n, e)
|
||||||
privateKey = (n, d)
|
private_key = (n, d)
|
||||||
return (publicKey, privateKey)
|
return (public_key, private_key)
|
||||||
|
|
||||||
|
|
||||||
def makeKeyFiles(name: str, keySize: int) -> None:
|
def make_key_files(name: str, key_size: int) -> None:
|
||||||
if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"):
|
if os.path.exists(f"{name}_pubkey.txt") or os.path.exists(f"{name}_privkey.txt"):
|
||||||
print("\nWARNING:")
|
print("\nWARNING:")
|
||||||
print(
|
print(
|
||||||
'"%s_pubkey.txt" or "%s_privkey.txt" already exists. \n'
|
f'"{name}_pubkey.txt" or "{name}_privkey.txt" already exists. \n'
|
||||||
"Use a different name or delete these files and re-run this program."
|
"Use a different name or delete these files and re-run this program."
|
||||||
% (name, name)
|
|
||||||
)
|
)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
publicKey, privateKey = generateKey(keySize)
|
public_key, private_key = generate_key(key_size)
|
||||||
print(f"\nWriting public key to file {name}_pubkey.txt...")
|
print(f"\nWriting public key to file {name}_pubkey.txt...")
|
||||||
with open(f"{name}_pubkey.txt", "w") as out_file:
|
with open(f"{name}_pubkey.txt", "w") as out_file:
|
||||||
out_file.write(f"{keySize},{publicKey[0]},{publicKey[1]}")
|
out_file.write(f"{key_size},{public_key[0]},{public_key[1]}")
|
||||||
|
|
||||||
print(f"Writing private key to file {name}_privkey.txt...")
|
print(f"Writing private key to file {name}_privkey.txt...")
|
||||||
with open(f"{name}_privkey.txt", "w") as out_file:
|
with open(f"{name}_privkey.txt", "w") as out_file:
|
||||||
out_file.write(f"{keySize},{privateKey[0]},{privateKey[1]}")
|
out_file.write(f"{key_size},{private_key[0]},{private_key[1]}")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -42,7 +42,7 @@ class ShuffledShiftCipher:
|
|||||||
"""
|
"""
|
||||||
:return: passcode of the cipher object
|
:return: passcode of the cipher object
|
||||||
"""
|
"""
|
||||||
return "Passcode is: " + "".join(self.__passcode)
|
return "".join(self.__passcode)
|
||||||
|
|
||||||
def __neg_pos(self, iterlist: list[int]) -> list[int]:
|
def __neg_pos(self, iterlist: list[int]) -> list[int]:
|
||||||
"""
|
"""
|
||||||
|
@ -21,7 +21,7 @@ def create_cipher_map(key: str) -> dict[str, str]:
|
|||||||
:param key: keyword to use
|
:param key: keyword to use
|
||||||
:return: dictionary cipher map
|
:return: dictionary cipher map
|
||||||
"""
|
"""
|
||||||
# Create alphabet list
|
# Create a list of the letters in the alphabet
|
||||||
alphabet = [chr(i + 65) for i in range(26)]
|
alphabet = [chr(i + 65) for i in range(26)]
|
||||||
# Remove duplicate characters from key
|
# Remove duplicate characters from key
|
||||||
key = remove_duplicates(key.upper())
|
key = remove_duplicates(key.upper())
|
||||||
|
@ -9,66 +9,66 @@ def main() -> None:
|
|||||||
key = "LFWOAYUISVKMNXPBDCRJTQEGHZ"
|
key = "LFWOAYUISVKMNXPBDCRJTQEGHZ"
|
||||||
resp = input("Encrypt/Decrypt [e/d]: ")
|
resp = input("Encrypt/Decrypt [e/d]: ")
|
||||||
|
|
||||||
checkValidKey(key)
|
check_valid_key(key)
|
||||||
|
|
||||||
if resp.lower().startswith("e"):
|
if resp.lower().startswith("e"):
|
||||||
mode = "encrypt"
|
mode = "encrypt"
|
||||||
translated = encryptMessage(key, message)
|
translated = encrypt_message(key, message)
|
||||||
elif resp.lower().startswith("d"):
|
elif resp.lower().startswith("d"):
|
||||||
mode = "decrypt"
|
mode = "decrypt"
|
||||||
translated = decryptMessage(key, message)
|
translated = decrypt_message(key, message)
|
||||||
|
|
||||||
print(f"\n{mode.title()}ion: \n{translated}")
|
print(f"\n{mode.title()}ion: \n{translated}")
|
||||||
|
|
||||||
|
|
||||||
def checkValidKey(key: str) -> None:
|
def check_valid_key(key: str) -> None:
|
||||||
keyList = list(key)
|
key_list = list(key)
|
||||||
lettersList = list(LETTERS)
|
letters_list = list(LETTERS)
|
||||||
keyList.sort()
|
key_list.sort()
|
||||||
lettersList.sort()
|
letters_list.sort()
|
||||||
|
|
||||||
if keyList != lettersList:
|
if key_list != letters_list:
|
||||||
sys.exit("Error in the key or symbol set.")
|
sys.exit("Error in the key or symbol set.")
|
||||||
|
|
||||||
|
|
||||||
def encryptMessage(key: str, message: str) -> str:
|
def encrypt_message(key: str, message: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> encryptMessage('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Harshil Darji')
|
>>> encrypt_message('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Harshil Darji')
|
||||||
'Ilcrism Olcvs'
|
'Ilcrism Olcvs'
|
||||||
"""
|
"""
|
||||||
return translateMessage(key, message, "encrypt")
|
return translate_message(key, message, "encrypt")
|
||||||
|
|
||||||
|
|
||||||
def decryptMessage(key: str, message: str) -> str:
|
def decrypt_message(key: str, message: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> decryptMessage('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Ilcrism Olcvs')
|
>>> decrypt_message('LFWOAYUISVKMNXPBDCRJTQEGHZ', 'Ilcrism Olcvs')
|
||||||
'Harshil Darji'
|
'Harshil Darji'
|
||||||
"""
|
"""
|
||||||
return translateMessage(key, message, "decrypt")
|
return translate_message(key, message, "decrypt")
|
||||||
|
|
||||||
|
|
||||||
def translateMessage(key: str, message: str, mode: str) -> str:
|
def translate_message(key: str, message: str, mode: str) -> str:
|
||||||
translated = ""
|
translated = ""
|
||||||
charsA = LETTERS
|
chars_a = LETTERS
|
||||||
charsB = key
|
chars_b = key
|
||||||
|
|
||||||
if mode == "decrypt":
|
if mode == "decrypt":
|
||||||
charsA, charsB = charsB, charsA
|
chars_a, chars_b = chars_b, chars_a
|
||||||
|
|
||||||
for symbol in message:
|
for symbol in message:
|
||||||
if symbol.upper() in charsA:
|
if symbol.upper() in chars_a:
|
||||||
symIndex = charsA.find(symbol.upper())
|
sym_index = chars_a.find(symbol.upper())
|
||||||
if symbol.isupper():
|
if symbol.isupper():
|
||||||
translated += charsB[symIndex].upper()
|
translated += chars_b[sym_index].upper()
|
||||||
else:
|
else:
|
||||||
translated += charsB[symIndex].lower()
|
translated += chars_b[sym_index].lower()
|
||||||
else:
|
else:
|
||||||
translated += symbol
|
translated += symbol
|
||||||
|
|
||||||
return translated
|
return translated
|
||||||
|
|
||||||
|
|
||||||
def getRandomKey() -> str:
|
def get_random_key() -> str:
|
||||||
key = list(LETTERS)
|
key = list(LETTERS)
|
||||||
random.shuffle(key)
|
random.shuffle(key)
|
||||||
return "".join(key)
|
return "".join(key)
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
def __encryptPart(messagePart: str, character2Number: dict[str, str]) -> str:
|
def __encrypt_part(message_part: str, character_to_number: dict[str, str]) -> str:
|
||||||
one, two, three = "", "", ""
|
one, two, three = "", "", ""
|
||||||
tmp = []
|
tmp = []
|
||||||
|
|
||||||
for character in messagePart:
|
for character in message_part:
|
||||||
tmp.append(character2Number[character])
|
tmp.append(character_to_number[character])
|
||||||
|
|
||||||
for each in tmp:
|
for each in tmp:
|
||||||
one += each[0]
|
one += each[0]
|
||||||
@ -17,18 +17,18 @@ def __encryptPart(messagePart: str, character2Number: dict[str, str]) -> str:
|
|||||||
return one + two + three
|
return one + two + three
|
||||||
|
|
||||||
|
|
||||||
def __decryptPart(
|
def __decrypt_part(
|
||||||
messagePart: str, character2Number: dict[str, str]
|
message_part: str, character_to_number: dict[str, str]
|
||||||
) -> tuple[str, str, str]:
|
) -> tuple[str, str, str]:
|
||||||
tmp, thisPart = "", ""
|
tmp, this_part = "", ""
|
||||||
result = []
|
result = []
|
||||||
|
|
||||||
for character in messagePart:
|
for character in message_part:
|
||||||
thisPart += character2Number[character]
|
this_part += character_to_number[character]
|
||||||
|
|
||||||
for digit in thisPart:
|
for digit in this_part:
|
||||||
tmp += digit
|
tmp += digit
|
||||||
if len(tmp) == len(messagePart):
|
if len(tmp) == len(message_part):
|
||||||
result.append(tmp)
|
result.append(tmp)
|
||||||
tmp = ""
|
tmp = ""
|
||||||
|
|
||||||
@ -79,51 +79,57 @@ def __prepare(
|
|||||||
"332",
|
"332",
|
||||||
"333",
|
"333",
|
||||||
)
|
)
|
||||||
character2Number = {}
|
character_to_number = {}
|
||||||
number2Character = {}
|
number_to_character = {}
|
||||||
for letter, number in zip(alphabet, numbers):
|
for letter, number in zip(alphabet, numbers):
|
||||||
character2Number[letter] = number
|
character_to_number[letter] = number
|
||||||
number2Character[number] = letter
|
number_to_character[number] = letter
|
||||||
|
|
||||||
return message, alphabet, character2Number, number2Character
|
return message, alphabet, character_to_number, number_to_character
|
||||||
|
|
||||||
|
|
||||||
def encryptMessage(
|
def encrypt_message(
|
||||||
message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5
|
message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5
|
||||||
) -> str:
|
) -> str:
|
||||||
message, alphabet, character2Number, number2Character = __prepare(message, alphabet)
|
message, alphabet, character_to_number, number_to_character = __prepare(
|
||||||
|
message, alphabet
|
||||||
|
)
|
||||||
encrypted, encrypted_numeric = "", ""
|
encrypted, encrypted_numeric = "", ""
|
||||||
|
|
||||||
for i in range(0, len(message) + 1, period):
|
for i in range(0, len(message) + 1, period):
|
||||||
encrypted_numeric += __encryptPart(message[i : i + period], character2Number)
|
encrypted_numeric += __encrypt_part(
|
||||||
|
message[i : i + period], character_to_number
|
||||||
|
)
|
||||||
|
|
||||||
for i in range(0, len(encrypted_numeric), 3):
|
for i in range(0, len(encrypted_numeric), 3):
|
||||||
encrypted += number2Character[encrypted_numeric[i : i + 3]]
|
encrypted += number_to_character[encrypted_numeric[i : i + 3]]
|
||||||
|
|
||||||
return encrypted
|
return encrypted
|
||||||
|
|
||||||
|
|
||||||
def decryptMessage(
|
def decrypt_message(
|
||||||
message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5
|
message: str, alphabet: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.", period: int = 5
|
||||||
) -> str:
|
) -> str:
|
||||||
message, alphabet, character2Number, number2Character = __prepare(message, alphabet)
|
message, alphabet, character_to_number, number_to_character = __prepare(
|
||||||
|
message, alphabet
|
||||||
|
)
|
||||||
decrypted_numeric = []
|
decrypted_numeric = []
|
||||||
decrypted = ""
|
decrypted = ""
|
||||||
|
|
||||||
for i in range(0, len(message) + 1, period):
|
for i in range(0, len(message) + 1, period):
|
||||||
a, b, c = __decryptPart(message[i : i + period], character2Number)
|
a, b, c = __decrypt_part(message[i : i + period], character_to_number)
|
||||||
|
|
||||||
for j in range(0, len(a)):
|
for j in range(0, len(a)):
|
||||||
decrypted_numeric.append(a[j] + b[j] + c[j])
|
decrypted_numeric.append(a[j] + b[j] + c[j])
|
||||||
|
|
||||||
for each in decrypted_numeric:
|
for each in decrypted_numeric:
|
||||||
decrypted += number2Character[each]
|
decrypted += number_to_character[each]
|
||||||
|
|
||||||
return decrypted
|
return decrypted
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
msg = "DEFEND THE EAST WALL OF THE CASTLE."
|
msg = "DEFEND THE EAST WALL OF THE CASTLE."
|
||||||
encrypted = encryptMessage(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ")
|
encrypted = encrypt_message(msg, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ")
|
||||||
decrypted = decryptMessage(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ")
|
decrypted = decrypt_message(encrypted, "EPSDUCVWYM.ZLKXNBTFGORIJHAQ")
|
||||||
print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}")
|
print(f"Encrypted: {encrypted}\nDecrypted: {decrypted}")
|
||||||
|
@ -14,53 +14,53 @@ def main() -> None:
|
|||||||
mode = input("Encryption/Decryption [e/d]: ")
|
mode = input("Encryption/Decryption [e/d]: ")
|
||||||
|
|
||||||
if mode.lower().startswith("e"):
|
if mode.lower().startswith("e"):
|
||||||
text = encryptMessage(key, message)
|
text = encrypt_message(key, message)
|
||||||
elif mode.lower().startswith("d"):
|
elif mode.lower().startswith("d"):
|
||||||
text = decryptMessage(key, message)
|
text = decrypt_message(key, message)
|
||||||
|
|
||||||
# Append pipe symbol (vertical bar) to identify spaces at the end.
|
# Append pipe symbol (vertical bar) to identify spaces at the end.
|
||||||
print(f"Output:\n{text + '|'}")
|
print(f"Output:\n{text + '|'}")
|
||||||
|
|
||||||
|
|
||||||
def encryptMessage(key: int, message: str) -> str:
|
def encrypt_message(key: int, message: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> encryptMessage(6, 'Harshil Darji')
|
>>> encrypt_message(6, 'Harshil Darji')
|
||||||
'Hlia rDsahrij'
|
'Hlia rDsahrij'
|
||||||
"""
|
"""
|
||||||
cipherText = [""] * key
|
cipher_text = [""] * key
|
||||||
for col in range(key):
|
for col in range(key):
|
||||||
pointer = col
|
pointer = col
|
||||||
while pointer < len(message):
|
while pointer < len(message):
|
||||||
cipherText[col] += message[pointer]
|
cipher_text[col] += message[pointer]
|
||||||
pointer += key
|
pointer += key
|
||||||
return "".join(cipherText)
|
return "".join(cipher_text)
|
||||||
|
|
||||||
|
|
||||||
def decryptMessage(key: int, message: str) -> str:
|
def decrypt_message(key: int, message: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> decryptMessage(6, 'Hlia rDsahrij')
|
>>> decrypt_message(6, 'Hlia rDsahrij')
|
||||||
'Harshil Darji'
|
'Harshil Darji'
|
||||||
"""
|
"""
|
||||||
numCols = math.ceil(len(message) / key)
|
num_cols = math.ceil(len(message) / key)
|
||||||
numRows = key
|
num_rows = key
|
||||||
numShadedBoxes = (numCols * numRows) - len(message)
|
num_shaded_boxes = (num_cols * num_rows) - len(message)
|
||||||
plainText = [""] * numCols
|
plain_text = [""] * num_cols
|
||||||
col = 0
|
col = 0
|
||||||
row = 0
|
row = 0
|
||||||
|
|
||||||
for symbol in message:
|
for symbol in message:
|
||||||
plainText[col] += symbol
|
plain_text[col] += symbol
|
||||||
col += 1
|
col += 1
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(col == numCols)
|
(col == num_cols)
|
||||||
or (col == numCols - 1)
|
or (col == num_cols - 1)
|
||||||
and (row >= numRows - numShadedBoxes)
|
and (row >= num_rows - num_shaded_boxes)
|
||||||
):
|
):
|
||||||
col = 0
|
col = 0
|
||||||
row += 1
|
row += 1
|
||||||
|
|
||||||
return "".join(plainText)
|
return "".join(plain_text)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -2,39 +2,39 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from . import transposition_cipher as transCipher
|
from . import transposition_cipher as trans_cipher
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
inputFile = "Prehistoric Men.txt"
|
input_file = "Prehistoric Men.txt"
|
||||||
outputFile = "Output.txt"
|
output_file = "Output.txt"
|
||||||
key = int(input("Enter key: "))
|
key = int(input("Enter key: "))
|
||||||
mode = input("Encrypt/Decrypt [e/d]: ")
|
mode = input("Encrypt/Decrypt [e/d]: ")
|
||||||
|
|
||||||
if not os.path.exists(inputFile):
|
if not os.path.exists(input_file):
|
||||||
print(f"File {inputFile} does not exist. Quitting...")
|
print(f"File {input_file} does not exist. Quitting...")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
if os.path.exists(outputFile):
|
if os.path.exists(output_file):
|
||||||
print(f"Overwrite {outputFile}? [y/n]")
|
print(f"Overwrite {output_file}? [y/n]")
|
||||||
response = input("> ")
|
response = input("> ")
|
||||||
if not response.lower().startswith("y"):
|
if not response.lower().startswith("y"):
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
startTime = time.time()
|
start_time = time.time()
|
||||||
if mode.lower().startswith("e"):
|
if mode.lower().startswith("e"):
|
||||||
with open(inputFile) as f:
|
with open(input_file) as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
translated = transCipher.encryptMessage(key, content)
|
translated = trans_cipher.encrypt_message(key, content)
|
||||||
elif mode.lower().startswith("d"):
|
elif mode.lower().startswith("d"):
|
||||||
with open(outputFile) as f:
|
with open(output_file) as f:
|
||||||
content = f.read()
|
content = f.read()
|
||||||
translated = transCipher.decryptMessage(key, content)
|
translated = trans_cipher.decrypt_message(key, content)
|
||||||
|
|
||||||
with open(outputFile, "w") as outputObj:
|
with open(output_file, "w") as output_obj:
|
||||||
outputObj.write(translated)
|
output_obj.write(translated)
|
||||||
|
|
||||||
totalTime = round(time.time() - startTime, 2)
|
total_time = round(time.time() - start_time, 2)
|
||||||
print(("Done (", totalTime, "seconds )"))
|
print(("Done (", total_time, "seconds )"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -8,43 +8,43 @@ def main() -> None:
|
|||||||
|
|
||||||
if mode.lower().startswith("e"):
|
if mode.lower().startswith("e"):
|
||||||
mode = "encrypt"
|
mode = "encrypt"
|
||||||
translated = encryptMessage(key, message)
|
translated = encrypt_message(key, message)
|
||||||
elif mode.lower().startswith("d"):
|
elif mode.lower().startswith("d"):
|
||||||
mode = "decrypt"
|
mode = "decrypt"
|
||||||
translated = decryptMessage(key, message)
|
translated = decrypt_message(key, message)
|
||||||
|
|
||||||
print(f"\n{mode.title()}ed message:")
|
print(f"\n{mode.title()}ed message:")
|
||||||
print(translated)
|
print(translated)
|
||||||
|
|
||||||
|
|
||||||
def encryptMessage(key: str, message: str) -> str:
|
def encrypt_message(key: str, message: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> encryptMessage('HDarji', 'This is Harshil Darji from Dharmaj.')
|
>>> encrypt_message('HDarji', 'This is Harshil Darji from Dharmaj.')
|
||||||
'Akij ra Odrjqqs Gaisq muod Mphumrs.'
|
'Akij ra Odrjqqs Gaisq muod Mphumrs.'
|
||||||
"""
|
"""
|
||||||
return translateMessage(key, message, "encrypt")
|
return translate_message(key, message, "encrypt")
|
||||||
|
|
||||||
|
|
||||||
def decryptMessage(key: str, message: str) -> str:
|
def decrypt_message(key: str, message: str) -> str:
|
||||||
"""
|
"""
|
||||||
>>> decryptMessage('HDarji', 'Akij ra Odrjqqs Gaisq muod Mphumrs.')
|
>>> decrypt_message('HDarji', 'Akij ra Odrjqqs Gaisq muod Mphumrs.')
|
||||||
'This is Harshil Darji from Dharmaj.'
|
'This is Harshil Darji from Dharmaj.'
|
||||||
"""
|
"""
|
||||||
return translateMessage(key, message, "decrypt")
|
return translate_message(key, message, "decrypt")
|
||||||
|
|
||||||
|
|
||||||
def translateMessage(key: str, message: str, mode: str) -> str:
|
def translate_message(key: str, message: str, mode: str) -> str:
|
||||||
translated = []
|
translated = []
|
||||||
keyIndex = 0
|
key_index = 0
|
||||||
key = key.upper()
|
key = key.upper()
|
||||||
|
|
||||||
for symbol in message:
|
for symbol in message:
|
||||||
num = LETTERS.find(symbol.upper())
|
num = LETTERS.find(symbol.upper())
|
||||||
if num != -1:
|
if num != -1:
|
||||||
if mode == "encrypt":
|
if mode == "encrypt":
|
||||||
num += LETTERS.find(key[keyIndex])
|
num += LETTERS.find(key[key_index])
|
||||||
elif mode == "decrypt":
|
elif mode == "decrypt":
|
||||||
num -= LETTERS.find(key[keyIndex])
|
num -= LETTERS.find(key[key_index])
|
||||||
|
|
||||||
num %= len(LETTERS)
|
num %= len(LETTERS)
|
||||||
|
|
||||||
@ -53,9 +53,9 @@ def translateMessage(key: str, message: str, mode: str) -> str:
|
|||||||
elif symbol.islower():
|
elif symbol.islower():
|
||||||
translated.append(LETTERS[num].lower())
|
translated.append(LETTERS[num].lower())
|
||||||
|
|
||||||
keyIndex += 1
|
key_index += 1
|
||||||
if keyIndex == len(key):
|
if key_index == len(key):
|
||||||
keyIndex = 0
|
key_index = 0
|
||||||
else:
|
else:
|
||||||
translated.append(symbol)
|
translated.append(symbol)
|
||||||
return "".join(translated)
|
return "".join(translated)
|
||||||
|
@ -128,12 +128,10 @@ class XORCipher:
|
|||||||
assert isinstance(file, str) and isinstance(key, int)
|
assert isinstance(file, str) and isinstance(key, int)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(file) as fin:
|
with open(file) as fin, open("encrypt.out", "w+") as fout:
|
||||||
with open("encrypt.out", "w+") as fout:
|
# actual encrypt-process
|
||||||
|
for line in fin:
|
||||||
# actual encrypt-process
|
fout.write(self.encrypt_string(line, key))
|
||||||
for line in fin:
|
|
||||||
fout.write(self.encrypt_string(line, key))
|
|
||||||
|
|
||||||
except OSError:
|
except OSError:
|
||||||
return False
|
return False
|
||||||
@ -153,12 +151,10 @@ class XORCipher:
|
|||||||
assert isinstance(file, str) and isinstance(key, int)
|
assert isinstance(file, str) and isinstance(key, int)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(file) as fin:
|
with open(file) as fin, open("decrypt.out", "w+") as fout:
|
||||||
with open("decrypt.out", "w+") as fout:
|
# actual encrypt-process
|
||||||
|
for line in fin:
|
||||||
# actual encrypt-process
|
fout.write(self.decrypt_string(line, key))
|
||||||
for line in fin:
|
|
||||||
fout.write(self.decrypt_string(line, key))
|
|
||||||
|
|
||||||
except OSError:
|
except OSError:
|
||||||
return False
|
return False
|
||||||
|
@ -154,7 +154,7 @@ def reverse_bwt(bwt_string: str, idx_original_string: int) -> str:
|
|||||||
)
|
)
|
||||||
|
|
||||||
ordered_rotations = [""] * len(bwt_string)
|
ordered_rotations = [""] * len(bwt_string)
|
||||||
for x in range(len(bwt_string)):
|
for _ in range(len(bwt_string)):
|
||||||
for i in range(len(bwt_string)):
|
for i in range(len(bwt_string)):
|
||||||
ordered_rotations[i] = bwt_string[i] + ordered_rotations[i]
|
ordered_rotations[i] = bwt_string[i] + ordered_rotations[i]
|
||||||
ordered_rotations.sort()
|
ordered_rotations.sort()
|
||||||
|
@ -31,8 +31,8 @@ def parse_file(file_path: str) -> list[Letter]:
|
|||||||
c = f.read(1)
|
c = f.read(1)
|
||||||
if not c:
|
if not c:
|
||||||
break
|
break
|
||||||
chars[c] = chars[c] + 1 if c in chars.keys() else 1
|
chars[c] = chars[c] + 1 if c in chars else 1
|
||||||
return sorted((Letter(c, f) for c, f in chars.items()), key=lambda l: l.freq)
|
return sorted((Letter(c, f) for c, f in chars.items()), key=lambda x: x.freq)
|
||||||
|
|
||||||
|
|
||||||
def build_tree(letters: list[Letter]) -> Letter | TreeNode:
|
def build_tree(letters: list[Letter]) -> Letter | TreeNode:
|
||||||
@ -47,7 +47,7 @@ def build_tree(letters: list[Letter]) -> Letter | TreeNode:
|
|||||||
total_freq = left.freq + right.freq
|
total_freq = left.freq + right.freq
|
||||||
node = TreeNode(total_freq, left, right)
|
node = TreeNode(total_freq, left, right)
|
||||||
response.append(node)
|
response.append(node)
|
||||||
response.sort(key=lambda l: l.freq)
|
response.sort(key=lambda x: x.freq)
|
||||||
return response[0]
|
return response[0]
|
||||||
|
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ def traverse_tree(root: Letter | TreeNode, bitstring: str) -> list[Letter]:
|
|||||||
Recursively traverse the Huffman Tree to set each
|
Recursively traverse the Huffman Tree to set each
|
||||||
Letter's bitstring dictionary, and return the list of Letters
|
Letter's bitstring dictionary, and return the list of Letters
|
||||||
"""
|
"""
|
||||||
if type(root) is Letter:
|
if isinstance(root, Letter):
|
||||||
root.bitstring[root.letter] = bitstring
|
root.bitstring[root.letter] = bitstring
|
||||||
return [root]
|
return [root]
|
||||||
treenode: TreeNode = root # type: ignore
|
treenode: TreeNode = root # type: ignore
|
||||||
|
@ -43,10 +43,10 @@ def decompress_data(data_bits: str) -> str:
|
|||||||
lexicon[curr_string] = last_match_id + "0"
|
lexicon[curr_string] = last_match_id + "0"
|
||||||
|
|
||||||
if math.log2(index).is_integer():
|
if math.log2(index).is_integer():
|
||||||
newLex = {}
|
new_lex = {}
|
||||||
for curr_key in list(lexicon):
|
for curr_key in list(lexicon):
|
||||||
newLex["0" + curr_key] = lexicon.pop(curr_key)
|
new_lex["0" + curr_key] = lexicon.pop(curr_key)
|
||||||
lexicon = newLex
|
lexicon = new_lex
|
||||||
|
|
||||||
lexicon[bin(index)[2:]] = last_match_id + "1"
|
lexicon[bin(index)[2:]] = last_match_id + "1"
|
||||||
index += 1
|
index += 1
|
||||||
|
226
compression/lz77.py
Normal file
226
compression/lz77.py
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
"""
|
||||||
|
LZ77 compression algorithm
|
||||||
|
- lossless data compression published in papers by Abraham Lempel and Jacob Ziv in 1977
|
||||||
|
- also known as LZ1 or sliding-window compression
|
||||||
|
- form the basis for many variations including LZW, LZSS, LZMA and others
|
||||||
|
|
||||||
|
It uses a “sliding window” method. Within the sliding window we have:
|
||||||
|
- search buffer
|
||||||
|
- look ahead buffer
|
||||||
|
len(sliding_window) = len(search_buffer) + len(look_ahead_buffer)
|
||||||
|
|
||||||
|
LZ77 manages a dictionary that uses triples composed of:
|
||||||
|
- Offset into search buffer, it's the distance between the start of a phrase and
|
||||||
|
the beginning of a file.
|
||||||
|
- Length of the match, it's the number of characters that make up a phrase.
|
||||||
|
- The indicator is represented by a character that is going to be encoded next.
|
||||||
|
|
||||||
|
As a file is parsed, the dictionary is dynamically updated to reflect the compressed
|
||||||
|
data contents and size.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
"cabracadabrarrarrad" <-> [(0, 0, 'c'), (0, 0, 'a'), (0, 0, 'b'), (0, 0, 'r'),
|
||||||
|
(3, 1, 'c'), (2, 1, 'd'), (7, 4, 'r'), (3, 5, 'd')]
|
||||||
|
"ababcbababaa" <-> [(0, 0, 'a'), (0, 0, 'b'), (2, 2, 'c'), (4, 3, 'a'), (2, 2, 'a')]
|
||||||
|
"aacaacabcabaaac" <-> [(0, 0, 'a'), (1, 1, 'c'), (3, 4, 'b'), (3, 3, 'a'), (1, 2, 'c')]
|
||||||
|
|
||||||
|
Sources:
|
||||||
|
en.wikipedia.org/wiki/LZ77_and_LZ78
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
__version__ = "0.1"
|
||||||
|
__author__ = "Lucia Harcekova"
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Token:
|
||||||
|
"""
|
||||||
|
Dataclass representing triplet called token consisting of length, offset
|
||||||
|
and indicator. This triplet is used during LZ77 compression.
|
||||||
|
"""
|
||||||
|
|
||||||
|
offset: int
|
||||||
|
length: int
|
||||||
|
indicator: str
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
"""
|
||||||
|
>>> token = Token(1, 2, "c")
|
||||||
|
>>> repr(token)
|
||||||
|
'(1, 2, c)'
|
||||||
|
>>> str(token)
|
||||||
|
'(1, 2, c)'
|
||||||
|
"""
|
||||||
|
return f"({self.offset}, {self.length}, {self.indicator})"
|
||||||
|
|
||||||
|
|
||||||
|
class LZ77Compressor:
|
||||||
|
"""
|
||||||
|
Class containing compress and decompress methods using LZ77 compression algorithm.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, window_size: int = 13, lookahead_buffer_size: int = 6) -> None:
|
||||||
|
self.window_size = window_size
|
||||||
|
self.lookahead_buffer_size = lookahead_buffer_size
|
||||||
|
self.search_buffer_size = self.window_size - self.lookahead_buffer_size
|
||||||
|
|
||||||
|
def compress(self, text: str) -> list[Token]:
|
||||||
|
"""
|
||||||
|
Compress the given string text using LZ77 compression algorithm.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: string to be compressed
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
output: the compressed text as a list of Tokens
|
||||||
|
|
||||||
|
>>> lz77_compressor = LZ77Compressor()
|
||||||
|
>>> str(lz77_compressor.compress("ababcbababaa"))
|
||||||
|
'[(0, 0, a), (0, 0, b), (2, 2, c), (4, 3, a), (2, 2, a)]'
|
||||||
|
>>> str(lz77_compressor.compress("aacaacabcabaaac"))
|
||||||
|
'[(0, 0, a), (1, 1, c), (3, 4, b), (3, 3, a), (1, 2, c)]'
|
||||||
|
"""
|
||||||
|
|
||||||
|
output = []
|
||||||
|
search_buffer = ""
|
||||||
|
|
||||||
|
# while there are still characters in text to compress
|
||||||
|
while text:
|
||||||
|
# find the next encoding phrase
|
||||||
|
# - triplet with offset, length, indicator (the next encoding character)
|
||||||
|
token = self._find_encoding_token(text, search_buffer)
|
||||||
|
|
||||||
|
# update the search buffer:
|
||||||
|
# - add new characters from text into it
|
||||||
|
# - check if size exceed the max search buffer size, if so, drop the
|
||||||
|
# oldest elements
|
||||||
|
search_buffer += text[: token.length + 1]
|
||||||
|
if len(search_buffer) > self.search_buffer_size:
|
||||||
|
search_buffer = search_buffer[-self.search_buffer_size :]
|
||||||
|
|
||||||
|
# update the text
|
||||||
|
text = text[token.length + 1 :]
|
||||||
|
|
||||||
|
# append the token to output
|
||||||
|
output.append(token)
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def decompress(self, tokens: list[Token]) -> str:
|
||||||
|
"""
|
||||||
|
Convert the list of tokens into an output string.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
tokens: list containing triplets (offset, length, char)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
output: decompressed text
|
||||||
|
|
||||||
|
Tests:
|
||||||
|
>>> lz77_compressor = LZ77Compressor()
|
||||||
|
>>> lz77_compressor.decompress([Token(0, 0, 'c'), Token(0, 0, 'a'),
|
||||||
|
... Token(0, 0, 'b'), Token(0, 0, 'r'), Token(3, 1, 'c'),
|
||||||
|
... Token(2, 1, 'd'), Token(7, 4, 'r'), Token(3, 5, 'd')])
|
||||||
|
'cabracadabrarrarrad'
|
||||||
|
>>> lz77_compressor.decompress([Token(0, 0, 'a'), Token(0, 0, 'b'),
|
||||||
|
... Token(2, 2, 'c'), Token(4, 3, 'a'), Token(2, 2, 'a')])
|
||||||
|
'ababcbababaa'
|
||||||
|
>>> lz77_compressor.decompress([Token(0, 0, 'a'), Token(1, 1, 'c'),
|
||||||
|
... Token(3, 4, 'b'), Token(3, 3, 'a'), Token(1, 2, 'c')])
|
||||||
|
'aacaacabcabaaac'
|
||||||
|
"""
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
|
||||||
|
for token in tokens:
|
||||||
|
for _ in range(token.length):
|
||||||
|
output += output[-token.offset]
|
||||||
|
output += token.indicator
|
||||||
|
|
||||||
|
return output
|
||||||
|
|
||||||
|
def _find_encoding_token(self, text: str, search_buffer: str) -> Token:
|
||||||
|
"""Finds the encoding token for the first character in the text.
|
||||||
|
|
||||||
|
Tests:
|
||||||
|
>>> lz77_compressor = LZ77Compressor()
|
||||||
|
>>> lz77_compressor._find_encoding_token("abrarrarrad", "abracad").offset
|
||||||
|
7
|
||||||
|
>>> lz77_compressor._find_encoding_token("adabrarrarrad", "cabrac").length
|
||||||
|
1
|
||||||
|
>>> lz77_compressor._find_encoding_token("abc", "xyz").offset
|
||||||
|
0
|
||||||
|
>>> lz77_compressor._find_encoding_token("", "xyz").offset
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: We need some text to work with.
|
||||||
|
>>> lz77_compressor._find_encoding_token("abc", "").offset
|
||||||
|
0
|
||||||
|
"""
|
||||||
|
|
||||||
|
if not text:
|
||||||
|
raise ValueError("We need some text to work with.")
|
||||||
|
|
||||||
|
# Initialise result parameters to default values
|
||||||
|
length, offset = 0, 0
|
||||||
|
|
||||||
|
if not search_buffer:
|
||||||
|
return Token(offset, length, text[length])
|
||||||
|
|
||||||
|
for i, character in enumerate(search_buffer):
|
||||||
|
found_offset = len(search_buffer) - i
|
||||||
|
if character == text[0]:
|
||||||
|
found_length = self._match_length_from_index(text, search_buffer, 0, i)
|
||||||
|
# if the found length is bigger than the current or if it's equal,
|
||||||
|
# which means it's offset is smaller: update offset and length
|
||||||
|
if found_length >= length:
|
||||||
|
offset, length = found_offset, found_length
|
||||||
|
|
||||||
|
return Token(offset, length, text[length])
|
||||||
|
|
||||||
|
def _match_length_from_index(
|
||||||
|
self, text: str, window: str, text_index: int, window_index: int
|
||||||
|
) -> int:
|
||||||
|
"""Calculate the longest possible match of text and window characters from
|
||||||
|
text_index in text and window_index in window.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
text: _description_
|
||||||
|
window: sliding window
|
||||||
|
text_index: index of character in text
|
||||||
|
window_index: index of character in sliding window
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The maximum match between text and window, from given indexes.
|
||||||
|
|
||||||
|
Tests:
|
||||||
|
>>> lz77_compressor = LZ77Compressor(13, 6)
|
||||||
|
>>> lz77_compressor._match_length_from_index("rarrad", "adabrar", 0, 4)
|
||||||
|
5
|
||||||
|
>>> lz77_compressor._match_length_from_index("adabrarrarrad",
|
||||||
|
... "cabrac", 0, 1)
|
||||||
|
1
|
||||||
|
"""
|
||||||
|
if not text or text[text_index] != window[window_index]:
|
||||||
|
return 0
|
||||||
|
return 1 + self._match_length_from_index(
|
||||||
|
text, window + text[text_index], text_index + 1, window_index + 1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from doctest import testmod
|
||||||
|
|
||||||
|
testmod()
|
||||||
|
# Initialize compressor class
|
||||||
|
lz77_compressor = LZ77Compressor(window_size=13, lookahead_buffer_size=6)
|
||||||
|
|
||||||
|
# Example
|
||||||
|
TEXT = "cabracadabrarrarrad"
|
||||||
|
compressed_text = lz77_compressor.compress(TEXT)
|
||||||
|
print(lz77_compressor.compress("ababcbababaa"))
|
||||||
|
decompressed_text = lz77_compressor.decompress(compressed_text)
|
||||||
|
assert decompressed_text == TEXT, "The LZ77 algorithm returned the invalid result."
|
@ -11,14 +11,15 @@ import os
|
|||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
PIXEL_MAX = 255.0
|
||||||
|
|
||||||
def psnr(original: float, contrast: float) -> float:
|
|
||||||
|
def peak_signal_to_noise_ratio(original: float, contrast: float) -> float:
|
||||||
mse = np.mean((original - contrast) ** 2)
|
mse = np.mean((original - contrast) ** 2)
|
||||||
if mse == 0:
|
if mse == 0:
|
||||||
return 100
|
return 100
|
||||||
PIXEL_MAX = 255.0
|
|
||||||
PSNR = 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
|
return 20 * math.log10(PIXEL_MAX / math.sqrt(mse))
|
||||||
return PSNR
|
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@ -34,11 +35,11 @@ def main() -> None:
|
|||||||
|
|
||||||
# Value expected: 29.73dB
|
# Value expected: 29.73dB
|
||||||
print("-- First Test --")
|
print("-- First Test --")
|
||||||
print(f"PSNR value is {psnr(original, contrast)} dB")
|
print(f"PSNR value is {peak_signal_to_noise_ratio(original, contrast)} dB")
|
||||||
|
|
||||||
# # Value expected: 31.53dB (Wikipedia Example)
|
# # Value expected: 31.53dB (Wikipedia Example)
|
||||||
print("\n-- Second Test --")
|
print("\n-- Second Test --")
|
||||||
print(f"PSNR value is {psnr(original2, contrast2)} dB")
|
print(f"PSNR value is {peak_signal_to_noise_ratio(original2, contrast2)} dB")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -28,11 +28,13 @@ import tensorflow as tf
|
|||||||
from tensorflow.keras import layers, models
|
from tensorflow.keras import layers, models
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
||||||
# Initialising the CNN
|
# Initialising the CNN
|
||||||
|
# (Sequential- Building the model layer by layer)
|
||||||
classifier = models.Sequential()
|
classifier = models.Sequential()
|
||||||
|
|
||||||
# Step 1 - Convolution
|
# Step 1 - Convolution
|
||||||
|
# Here 64,64 is the length & breadth of dataset images and 3 is for the RGB channel
|
||||||
|
# (3,3) is the kernel size (filter matrix)
|
||||||
classifier.add(
|
classifier.add(
|
||||||
layers.Conv2D(32, (3, 3), input_shape=(64, 64, 3), activation="relu")
|
layers.Conv2D(32, (3, 3), input_shape=(64, 64, 3), activation="relu")
|
||||||
)
|
)
|
||||||
@ -91,7 +93,7 @@ if __name__ == "__main__":
|
|||||||
test_image = tf.keras.preprocessing.image.img_to_array(test_image)
|
test_image = tf.keras.preprocessing.image.img_to_array(test_image)
|
||||||
test_image = np.expand_dims(test_image, axis=0)
|
test_image = np.expand_dims(test_image, axis=0)
|
||||||
result = classifier.predict(test_image)
|
result = classifier.predict(test_image)
|
||||||
training_set.class_indices
|
# training_set.class_indices
|
||||||
if result[0][0] == 0:
|
if result[0][0] == 0:
|
||||||
prediction = "Normal"
|
prediction = "Normal"
|
||||||
if result[0][0] == 1:
|
if result[0][0] == 1:
|
||||||
|
@ -22,7 +22,6 @@ def main() -> None:
|
|||||||
Get images list and annotations list from input dir.
|
Get images list and annotations list from input dir.
|
||||||
Update new images and annotations.
|
Update new images and annotations.
|
||||||
Save images and annotations in output dir.
|
Save images and annotations in output dir.
|
||||||
>>> pass # A doctest is not possible for this function.
|
|
||||||
"""
|
"""
|
||||||
img_paths, annos = get_dataset(LABEL_DIR, IMAGE_DIR)
|
img_paths, annos = get_dataset(LABEL_DIR, IMAGE_DIR)
|
||||||
print("Processing...")
|
print("Processing...")
|
||||||
@ -48,7 +47,6 @@ def get_dataset(label_dir: str, img_dir: str) -> tuple[list, list]:
|
|||||||
- label_dir <type: str>: Path to label include annotation of images
|
- label_dir <type: str>: Path to label include annotation of images
|
||||||
- img_dir <type: str>: Path to folder contain images
|
- img_dir <type: str>: Path to folder contain images
|
||||||
Return <type: list>: List of images path and labels
|
Return <type: list>: List of images path and labels
|
||||||
>>> pass # A doctest is not possible for this function.
|
|
||||||
"""
|
"""
|
||||||
img_paths = []
|
img_paths = []
|
||||||
labels = []
|
labels = []
|
||||||
@ -88,7 +86,6 @@ def update_image_and_anno(
|
|||||||
- new_imgs_list <type: narray>: image after resize
|
- new_imgs_list <type: narray>: image after resize
|
||||||
- new_annos_lists <type: list>: list of new annotation after scale
|
- new_annos_lists <type: list>: list of new annotation after scale
|
||||||
- path_list <type: list>: list the name of image file
|
- path_list <type: list>: list the name of image file
|
||||||
>>> pass # A doctest is not possible for this function.
|
|
||||||
"""
|
"""
|
||||||
new_annos_lists = []
|
new_annos_lists = []
|
||||||
path_list = []
|
path_list = []
|
||||||
|
@ -7,9 +7,8 @@ https://en.wikipedia.org/wiki/Harris_Corner_Detector
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class Harris_Corner:
|
class HarrisCorner:
|
||||||
def __init__(self, k: float, window_size: int):
|
def __init__(self, k: float, window_size: int):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
k : is an empirically determined constant in [0.04,0.06]
|
k : is an empirically determined constant in [0.04,0.06]
|
||||||
window_size : neighbourhoods considered
|
window_size : neighbourhoods considered
|
||||||
@ -22,11 +21,9 @@ class Harris_Corner:
|
|||||||
raise ValueError("invalid k value")
|
raise ValueError("invalid k value")
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
|
return str(self.k)
|
||||||
return f"Harris Corner detection with k : {self.k}"
|
|
||||||
|
|
||||||
def detect(self, img_path: str) -> tuple[cv2.Mat, list[list[int]]]:
|
def detect(self, img_path: str) -> tuple[cv2.Mat, list[list[int]]]:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Returns the image with corners identified
|
Returns the image with corners identified
|
||||||
img_path : path of the image
|
img_path : path of the image
|
||||||
@ -69,7 +66,6 @@ class Harris_Corner:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
edge_detect = HarrisCorner(0.04, 3)
|
||||||
edge_detect = Harris_Corner(0.04, 3)
|
|
||||||
color_img, _ = edge_detect.detect("path_to_image")
|
color_img, _ = edge_detect.detect("path_to_image")
|
||||||
cv2.imwrite("detect.png", color_img)
|
cv2.imwrite("detect.png", color_img)
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
from typing import SupportsIndex
|
from typing import SupportsIndex
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy.ndimage.filters import convolve
|
from scipy.ndimage import convolve
|
||||||
|
|
||||||
|
|
||||||
def warp(
|
def warp(
|
||||||
|
@ -23,7 +23,6 @@ def main() -> None:
|
|||||||
Get images list and annotations list from input dir.
|
Get images list and annotations list from input dir.
|
||||||
Update new images and annotations.
|
Update new images and annotations.
|
||||||
Save images and annotations in output dir.
|
Save images and annotations in output dir.
|
||||||
>>> pass # A doctest is not possible for this function.
|
|
||||||
"""
|
"""
|
||||||
img_paths, annos = get_dataset(LABEL_DIR, IMG_DIR)
|
img_paths, annos = get_dataset(LABEL_DIR, IMG_DIR)
|
||||||
for index in range(NUMBER_IMAGES):
|
for index in range(NUMBER_IMAGES):
|
||||||
@ -60,7 +59,6 @@ def get_dataset(label_dir: str, img_dir: str) -> tuple[list, list]:
|
|||||||
- label_dir <type: str>: Path to label include annotation of images
|
- label_dir <type: str>: Path to label include annotation of images
|
||||||
- img_dir <type: str>: Path to folder contain images
|
- img_dir <type: str>: Path to folder contain images
|
||||||
Return <type: list>: List of images path and labels
|
Return <type: list>: List of images path and labels
|
||||||
>>> pass # A doctest is not possible for this function.
|
|
||||||
"""
|
"""
|
||||||
img_paths = []
|
img_paths = []
|
||||||
labels = []
|
labels = []
|
||||||
@ -105,7 +103,6 @@ def update_image_and_anno(
|
|||||||
- output_img <type: narray>: image after resize
|
- output_img <type: narray>: image after resize
|
||||||
- new_anno <type: list>: list of new annotation after scale
|
- new_anno <type: list>: list of new annotation after scale
|
||||||
- path[0] <type: string>: get the name of image file
|
- path[0] <type: string>: get the name of image file
|
||||||
>>> pass # A doctest is not possible for this function.
|
|
||||||
"""
|
"""
|
||||||
output_img = np.zeros([output_size[0], output_size[1], 3], dtype=np.uint8)
|
output_img = np.zeros([output_size[0], output_size[1], 3], dtype=np.uint8)
|
||||||
scale_x = scale_range[0] + random.random() * (scale_range[1] - scale_range[0])
|
scale_x = scale_range[0] + random.random() * (scale_range[1] - scale_range[0])
|
||||||
@ -162,7 +159,7 @@ def update_image_and_anno(
|
|||||||
new_anno.append([bbox[0], xmin, ymin, xmax, ymax])
|
new_anno.append([bbox[0], xmin, ymin, xmax, ymax])
|
||||||
|
|
||||||
# Remove bounding box small than scale of filter
|
# Remove bounding box small than scale of filter
|
||||||
if 0 < filter_scale:
|
if filter_scale > 0:
|
||||||
new_anno = [
|
new_anno = [
|
||||||
anno
|
anno
|
||||||
for anno in new_anno
|
for anno in new_anno
|
||||||
|
106
conversions/astronomical_length_scale_conversion.py
Normal file
106
conversions/astronomical_length_scale_conversion.py
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
"""
|
||||||
|
Conversion of length units.
|
||||||
|
Available Units:
|
||||||
|
Metre, Kilometre, Megametre, Gigametre,
|
||||||
|
Terametre, Petametre, Exametre, Zettametre, Yottametre
|
||||||
|
|
||||||
|
USAGE :
|
||||||
|
-> Import this file into their respective project.
|
||||||
|
-> Use the function length_conversion() for conversion of length units.
|
||||||
|
-> Parameters :
|
||||||
|
-> value : The number of from units you want to convert
|
||||||
|
-> from_type : From which type you want to convert
|
||||||
|
-> to_type : To which type you want to convert
|
||||||
|
|
||||||
|
REFERENCES :
|
||||||
|
-> Wikipedia reference: https://en.wikipedia.org/wiki/Meter
|
||||||
|
-> Wikipedia reference: https://en.wikipedia.org/wiki/Kilometer
|
||||||
|
-> Wikipedia reference: https://en.wikipedia.org/wiki/Orders_of_magnitude_(length)
|
||||||
|
"""
|
||||||
|
|
||||||
|
UNIT_SYMBOL = {
|
||||||
|
"meter": "m",
|
||||||
|
"kilometer": "km",
|
||||||
|
"megametre": "Mm",
|
||||||
|
"gigametre": "Gm",
|
||||||
|
"terametre": "Tm",
|
||||||
|
"petametre": "Pm",
|
||||||
|
"exametre": "Em",
|
||||||
|
"zettametre": "Zm",
|
||||||
|
"yottametre": "Ym",
|
||||||
|
}
|
||||||
|
# Exponent of the factor(meter)
|
||||||
|
METRIC_CONVERSION = {
|
||||||
|
"m": 0,
|
||||||
|
"km": 3,
|
||||||
|
"Mm": 6,
|
||||||
|
"Gm": 9,
|
||||||
|
"Tm": 12,
|
||||||
|
"Pm": 15,
|
||||||
|
"Em": 18,
|
||||||
|
"Zm": 21,
|
||||||
|
"Ym": 24,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def length_conversion(value: float, from_type: str, to_type: str) -> float:
|
||||||
|
"""
|
||||||
|
Conversion between astronomical length units.
|
||||||
|
|
||||||
|
>>> length_conversion(1, "meter", "kilometer")
|
||||||
|
0.001
|
||||||
|
>>> length_conversion(1, "meter", "megametre")
|
||||||
|
1e-06
|
||||||
|
>>> length_conversion(1, "gigametre", "meter")
|
||||||
|
1000000000
|
||||||
|
>>> length_conversion(1, "gigametre", "terametre")
|
||||||
|
0.001
|
||||||
|
>>> length_conversion(1, "petametre", "terametre")
|
||||||
|
1000
|
||||||
|
>>> length_conversion(1, "petametre", "exametre")
|
||||||
|
0.001
|
||||||
|
>>> length_conversion(1, "terametre", "zettametre")
|
||||||
|
1e-09
|
||||||
|
>>> length_conversion(1, "yottametre", "zettametre")
|
||||||
|
1000
|
||||||
|
>>> length_conversion(4, "wrongUnit", "inch")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
...
|
||||||
|
ValueError: Invalid 'from_type' value: 'wrongUnit'.
|
||||||
|
Conversion abbreviations are: m, km, Mm, Gm, Tm, Pm, Em, Zm, Ym
|
||||||
|
"""
|
||||||
|
|
||||||
|
from_sanitized = from_type.lower().strip("s")
|
||||||
|
to_sanitized = to_type.lower().strip("s")
|
||||||
|
|
||||||
|
from_sanitized = UNIT_SYMBOL.get(from_sanitized, from_sanitized)
|
||||||
|
to_sanitized = UNIT_SYMBOL.get(to_sanitized, to_sanitized)
|
||||||
|
|
||||||
|
if from_sanitized not in METRIC_CONVERSION:
|
||||||
|
msg = (
|
||||||
|
f"Invalid 'from_type' value: {from_type!r}.\n"
|
||||||
|
f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}"
|
||||||
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
if to_sanitized not in METRIC_CONVERSION:
|
||||||
|
msg = (
|
||||||
|
f"Invalid 'to_type' value: {to_type!r}.\n"
|
||||||
|
f"Conversion abbreviations are: {', '.join(METRIC_CONVERSION)}"
|
||||||
|
)
|
||||||
|
raise ValueError(msg)
|
||||||
|
from_exponent = METRIC_CONVERSION[from_sanitized]
|
||||||
|
to_exponent = METRIC_CONVERSION[to_sanitized]
|
||||||
|
exponent = 1
|
||||||
|
|
||||||
|
if from_exponent > to_exponent:
|
||||||
|
exponent = from_exponent - to_exponent
|
||||||
|
else:
|
||||||
|
exponent = -(to_exponent - from_exponent)
|
||||||
|
|
||||||
|
return value * pow(10, exponent)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from doctest import testmod
|
||||||
|
|
||||||
|
testmod()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user