Skip to content

Commit ccff4c1

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 224f854 + bd9464e commit ccff4c1

File tree

104 files changed

+3439
-514
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+3439
-514
lines changed

.github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ jobs:
2323
python -m pip install mypy pytest-cov -r requirements.txt
2424
- run: mypy --install-types --non-interactive .
2525
- name: Run tests
26-
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. .
26+
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/validate_solutions.py --cov-report=term-missing:skip-covered --cov=. .
2727
- if: ${{ success() }}
2828
run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md

CONTRIBUTING.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ Welcome to [TheAlgorithms/Python](https://github.com/TheAlgorithms/Python)! Befo
88

99
### Contributor
1010

11-
We are very happy that you consider implementing algorithms and data structure 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:
11+
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:
1212

1313
- You did your work - no plagiarism allowed
1414
- Any plagiarized work will not be merged.
1515
- Your work will be distributed under [MIT License](LICENSE.md) once your pull request is merged
16-
- You submitted work fulfils or mostly fulfils our styles and standards
16+
- Your submitted work fulfils or mostly fulfils our styles and standards
1717

1818
__New implementation__ is welcome! For example, new solutions for a problem, different representations for a graph data structure or algorithm designs with different complexity but __identical implementation__ of an existing implementation is not allowed. Please check whether the solution is already implemented or not before submitting your pull request.
1919

@@ -25,7 +25,7 @@ We appreciate any contribution, from fixing a grammar mistake in a comment to im
2525

2626
Your contribution will be tested by our [automated testing on Travis CI](https://travis-ci.org/TheAlgorithms/Python/pull_requests) to save time and mental energy. After you have submitted your pull request, you should see the Travis 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 Travis 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.
2727

28-
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.
28+
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.
2929

3030
#### What is an Algorithm?
3131

@@ -53,7 +53,7 @@ Algorithms in this repo should not be how-to examples for existing Python packag
5353
Use [pre-commit](https://pre-commit.com/#installation) to automatically format your code to match our coding style:
5454

5555
```bash
56-
python3 -m pip install pre-commit # required only once
56+
python3 -m pip install pre-commit # only required the first time
5757
pre-commit install
5858
```
5959
That's it! The plugin will run every time you commit any changes. If there are any errors found during the run, fix them and commit those changes. You can even run the plugin manually on all files:

DIRECTORY.md

+32-5
Large diffs are not rendered by default.

bit_manipulation/README.md

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations
2-
https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations
3-
https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types
4-
5-
https://wiki.python.org/moin/BitManipulation
6-
https://wiki.python.org/moin/BitwiseOperators
7-
https://www.tutorialspoint.com/python3/bitwise_operators_example.htm
1+
* https://docs.python.org/3/reference/expressions.html#binary-bitwise-operations
2+
* https://docs.python.org/3/reference/expressions.html#unary-arithmetic-and-bitwise-operations
3+
* https://docs.python.org/3/library/stdtypes.html#bitwise-operations-on-integer-types
4+
* https://wiki.python.org/moin/BitManipulation
5+
* https://wiki.python.org/moin/BitwiseOperators
6+
* https://www.tutorialspoint.com/python3/bitwise_operators_example.htm

bit_manipulation/binary_and_operator.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def binary_and(a: int, b: int) -> str:
2222
>>> binary_and(0, -1)
2323
Traceback (most recent call last):
2424
...
25-
ValueError: the value of both input must be positive
25+
ValueError: the value of both inputs must be positive
2626
>>> binary_and(0, 1.1)
2727
Traceback (most recent call last):
2828
...
@@ -33,7 +33,7 @@ def binary_and(a: int, b: int) -> str:
3333
TypeError: '<' not supported between instances of 'str' and 'int'
3434
"""
3535
if a < 0 or b < 0:
36-
raise ValueError("the value of both input must be positive")
36+
raise ValueError("the value of both inputs must be positive")
3737

3838
a_binary = str(bin(a))[2:] # remove the leading "0b"
3939
b_binary = str(bin(b))[2:] # remove the leading "0b"

bit_manipulation/binary_or_operator.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def binary_or(a: int, b: int) -> str:
2121
>>> binary_or(0, -1)
2222
Traceback (most recent call last):
2323
...
24-
ValueError: the value of both input must be positive
24+
ValueError: the value of both inputs must be positive
2525
>>> binary_or(0, 1.1)
2626
Traceback (most recent call last):
2727
...
@@ -32,7 +32,7 @@ def binary_or(a: int, b: int) -> str:
3232
TypeError: '<' not supported between instances of 'str' and 'int'
3333
"""
3434
if a < 0 or b < 0:
35-
raise ValueError("the value of both input must be positive")
35+
raise ValueError("the value of both inputs must be positive")
3636
a_binary = str(bin(a))[2:] # remove the leading "0b"
3737
b_binary = str(bin(b))[2:]
3838
max_len = max(len(a_binary), len(b_binary))

bit_manipulation/binary_xor_operator.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def binary_xor(a: int, b: int) -> str:
2222
>>> binary_xor(0, -1)
2323
Traceback (most recent call last):
2424
...
25-
ValueError: the value of both input must be positive
25+
ValueError: the value of both inputs must be positive
2626
>>> binary_xor(0, 1.1)
2727
Traceback (most recent call last):
2828
...
@@ -33,7 +33,7 @@ def binary_xor(a: int, b: int) -> str:
3333
TypeError: '<' not supported between instances of 'str' and 'int'
3434
"""
3535
if a < 0 or b < 0:
36-
raise ValueError("the value of both input must be positive")
36+
raise ValueError("the value of both inputs must be positive")
3737

3838
a_binary = str(bin(a))[2:] # remove the leading "0b"
3939
b_binary = str(bin(b))[2:] # remove the leading "0b"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
def get_1s_count(number: int) -> int:
2+
"""
3+
Count the number of set bits in a 32 bit integer using Brian Kernighan's way.
4+
Ref - http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetKernighan
5+
>>> get_1s_count(25)
6+
3
7+
>>> get_1s_count(37)
8+
3
9+
>>> get_1s_count(21)
10+
3
11+
>>> get_1s_count(58)
12+
4
13+
>>> get_1s_count(0)
14+
0
15+
>>> get_1s_count(256)
16+
1
17+
>>> get_1s_count(-1)
18+
Traceback (most recent call last):
19+
...
20+
ValueError: the value of input must be positive
21+
>>> get_1s_count(0.8)
22+
Traceback (most recent call last):
23+
...
24+
TypeError: Input value must be an 'int' type
25+
"""
26+
if number < 0:
27+
raise ValueError("the value of input must be positive")
28+
elif isinstance(number, float):
29+
raise TypeError("Input value must be an 'int' type")
30+
count = 0
31+
while number:
32+
# This way we arrive at next set bit (next 1) instead of looping
33+
# through each bit and checking for 1s hence the
34+
# loop won't run 32 times it will only run the number of `1` times
35+
number &= number - 1
36+
count += 1
37+
return count
38+
39+
40+
if __name__ == "__main__":
41+
import doctest
42+
43+
doctest.testmod()

boolean_algebra/quine_mc_cluskey.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ def prime_implicant_chart(
146146
return chart
147147

148148

149-
def main():
149+
def main() -> None:
150150
no_of_variable = int(input("Enter the no. of variables\n"))
151151
minterms = [
152-
int(x)
152+
float(x)
153153
for x in input(
154154
"Enter the decimal representation of Minterms 'Spaces Separated'\n"
155155
).split()

cellular_automata/conways_game_of_life.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]:
7070
return next_generation
7171

7272

73-
def generate_images(cells: list[list[int]], frames) -> list[Image.Image]:
73+
def generate_images(cells: list[list[int]], frames: int) -> list[Image.Image]:
7474
"""
7575
Generates a list of images of subsequent Game of Life states.
7676
"""

cellular_automata/game_of_life.py

+11-10
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,18 @@
4040
random.shuffle(choice)
4141

4242

43-
def create_canvas(size):
43+
def create_canvas(size: int) -> list[list[bool]]:
4444
canvas = [[False for i in range(size)] for j in range(size)]
4545
return canvas
4646

4747

48-
def seed(canvas):
48+
def seed(canvas: list[list[bool]]) -> None:
4949
for i, row in enumerate(canvas):
5050
for j, _ in enumerate(row):
5151
canvas[i][j] = bool(random.getrandbits(1))
5252

5353

54-
def run(canvas):
54+
def run(canvas: list[list[bool]]) -> list[list[bool]]:
5555
"""This function runs the rules of game through all points, and changes their
5656
status accordingly.(in the same canvas)
5757
@Args:
@@ -62,21 +62,22 @@ def run(canvas):
6262
--
6363
None
6464
"""
65-
canvas = np.array(canvas)
66-
next_gen_canvas = np.array(create_canvas(canvas.shape[0]))
67-
for r, row in enumerate(canvas):
65+
current_canvas = np.array(canvas)
66+
next_gen_canvas = np.array(create_canvas(current_canvas.shape[0]))
67+
for r, row in enumerate(current_canvas):
6868
for c, pt in enumerate(row):
6969
# print(r-1,r+2,c-1,c+2)
7070
next_gen_canvas[r][c] = __judge_point(
71-
pt, canvas[r - 1 : r + 2, c - 1 : c + 2]
71+
pt, current_canvas[r - 1 : r + 2, c - 1 : c + 2]
7272
)
7373

74-
canvas = next_gen_canvas
74+
current_canvas = next_gen_canvas
7575
del next_gen_canvas # cleaning memory as we move on.
76-
return canvas.tolist()
76+
return_canvas: list[list[bool]] = current_canvas.tolist()
77+
return return_canvas
7778

7879

79-
def __judge_point(pt, neighbours):
80+
def __judge_point(pt: bool, neighbours: list[list[bool]]) -> bool:
8081
dead = 0
8182
alive = 0
8283
# finding dead or alive neighbours count.

ciphers/baconian_cipher.py

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
"""
2+
Program to encode and decode Baconian or Bacon's Cipher
3+
Wikipedia reference : https://en.wikipedia.org/wiki/Bacon%27s_cipher
4+
"""
5+
6+
encode_dict = {
7+
"a": "AAAAA",
8+
"b": "AAAAB",
9+
"c": "AAABA",
10+
"d": "AAABB",
11+
"e": "AABAA",
12+
"f": "AABAB",
13+
"g": "AABBA",
14+
"h": "AABBB",
15+
"i": "ABAAA",
16+
"j": "BBBAA",
17+
"k": "ABAAB",
18+
"l": "ABABA",
19+
"m": "ABABB",
20+
"n": "ABBAA",
21+
"o": "ABBAB",
22+
"p": "ABBBA",
23+
"q": "ABBBB",
24+
"r": "BAAAA",
25+
"s": "BAAAB",
26+
"t": "BAABA",
27+
"u": "BAABB",
28+
"v": "BBBAB",
29+
"w": "BABAA",
30+
"x": "BABAB",
31+
"y": "BABBA",
32+
"z": "BABBB",
33+
" ": " ",
34+
}
35+
36+
37+
decode_dict = {value: key for key, value in encode_dict.items()}
38+
39+
40+
def encode(word: str) -> str:
41+
"""
42+
Encodes to Baconian cipher
43+
44+
>>> encode("hello")
45+
'AABBBAABAAABABAABABAABBAB'
46+
>>> encode("hello world")
47+
'AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB'
48+
>>> encode("hello world!")
49+
Traceback (most recent call last):
50+
...
51+
Exception: encode() accepts only letters of the alphabet and spaces
52+
"""
53+
encoded = ""
54+
for letter in word.lower():
55+
if letter.isalpha() or letter == " ":
56+
encoded += encode_dict[letter]
57+
else:
58+
raise Exception("encode() accepts only letters of the alphabet and spaces")
59+
return encoded
60+
61+
62+
def decode(coded: str) -> str:
63+
"""
64+
Decodes from Baconian cipher
65+
66+
>>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB")
67+
'hello world'
68+
>>> decode("AABBBAABAAABABAABABAABBAB")
69+
'hello'
70+
>>> decode("AABBBAABAAABABAABABAABBAB BABAAABBABBAAAAABABAAAABB!")
71+
Traceback (most recent call last):
72+
...
73+
Exception: decode() accepts only 'A', 'B' and spaces
74+
"""
75+
if set(coded) - {"A", "B", " "} != set():
76+
raise Exception("decode() accepts only 'A', 'B' and spaces")
77+
decoded = ""
78+
for word in coded.split():
79+
while len(word) != 0:
80+
decoded += decode_dict[word[:5]]
81+
word = word[5:]
82+
decoded += " "
83+
return decoded.strip()
84+
85+
86+
if __name__ == "__main__":
87+
from doctest import testmod
88+
89+
testmod()

ciphers/base32.py

+36-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,42 @@
11
import base64
22

33

4-
def main() -> None:
5-
inp = input("->")
6-
encoded = inp.encode("utf-8") # encoded the input (we need a bytes like object)
7-
b32encoded = base64.b32encode(encoded) # b32encoded the encoded string
8-
print(b32encoded)
9-
print(base64.b32decode(b32encoded).decode("utf-8")) # decoded it
4+
def base32_encode(string: str) -> bytes:
5+
"""
6+
Encodes a given string to base32, returning a bytes-like object
7+
>>> base32_encode("Hello World!")
8+
b'JBSWY3DPEBLW64TMMQQQ===='
9+
>>> base32_encode("123456")
10+
b'GEZDGNBVGY======'
11+
>>> base32_encode("some long complex string")
12+
b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY='
13+
"""
14+
15+
# encoded the input (we need a bytes like object)
16+
# then, b32encoded the bytes-like object
17+
return base64.b32encode(string.encode("utf-8"))
18+
19+
20+
def base32_decode(encoded_bytes: bytes) -> str:
21+
"""
22+
Decodes a given bytes-like object to a string, returning a string
23+
>>> base32_decode(b'JBSWY3DPEBLW64TMMQQQ====')
24+
'Hello World!'
25+
>>> base32_decode(b'GEZDGNBVGY======')
26+
'123456'
27+
>>> base32_decode(b'ONXW2ZJANRXW4ZZAMNXW24DMMV4CA43UOJUW4ZY=')
28+
'some long complex string'
29+
"""
30+
31+
# decode the bytes from base32
32+
# then, decode the bytes-like object to return as a string
33+
return base64.b32decode(encoded_bytes).decode("utf-8")
1034

1135

1236
if __name__ == "__main__":
13-
main()
37+
test = "Hello World!"
38+
encoded = base32_encode(test)
39+
print(encoded)
40+
41+
decoded = base32_decode(encoded)
42+
print(decoded)

ciphers/base64_encoding.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def base64_encode(data: bytes) -> bytes:
77
The data is first transformed to binary and appended with binary digits so that its
88
length becomes a multiple of 6, then each 6 binary digits will match a character in
99
the B64_CHARSET string. The number of appended binary digits would later determine
10-
how many "=" sign should be added, the padding.
10+
how many "=" signs should be added, the padding.
1111
For every 2 binary digits added, a "=" sign is added in the output.
1212
We can add any binary digits to make it a multiple of 6, for instance, consider the
1313
following example:

0 commit comments

Comments
 (0)