├── CryptographyAlgorithms ├── caesar_cipher.py ├── gronsfeld_cipher.py ├── morse_code.py ├── polybius_square_cipher.py ├── rsa.py └── vigenere_cipher.py ├── LICENSE ├── README.md ├── SearchingAlgorithms ├── binary_search.py ├── interpolation_search.py └── linear_search.py └── SortingAlgorithms ├── bubble_sort.py ├── bucket_sort.py ├── cocktail_sort.py ├── comb_sort.py ├── gnome_sort.py ├── insertion_sort.py ├── merge_sort.py ├── quick_sort.py ├── selection_sort.py ├── shell_sort.py └── stooge_sort.py /CryptographyAlgorithms/caesar_cipher.py: -------------------------------------------------------------------------------- 1 | def processing(text, key, mode): 2 | finished_text = "" 3 | for i in range(len(text)): 4 | if text[i].isalnum(): 5 | if text[i].isupper(): 6 | finished_text += chr((ord(text[i]) + key * mode - 65) % 26 + 65) 7 | else: 8 | finished_text += chr((ord(text[i]) + key * mode - 97) % 26 + 97) 9 | else: 10 | finished_text += text[i] 11 | 12 | return finished_text 13 | 14 | 15 | def assembly(mode): 16 | text = str(input("[+] Enter your cipher text - ")) 17 | key = int(input("[+] Enter your key - ")) 18 | 19 | finished_text = processing(text, key, mode) 20 | 21 | print("\n »» The result of decryption by Caesar-Cipher algorithm. ««") 22 | print(finished_text) 23 | 24 | 25 | def main(): 26 | print("[x] Caesar-Cipher cryptography algorithm. [x]") 27 | print(" • 0. Encryption mode.\n • 1. Decryption mode.") 28 | 29 | mode = (-1) ** int(input("[?] Select program mode - ")) 30 | assembly(mode) 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /CryptographyAlgorithms/gronsfeld_cipher.py: -------------------------------------------------------------------------------- 1 | from string import ascii_uppercase as alphabet 2 | 3 | 4 | def processing(text, key, mode): 5 | key *= len(text) // len(key) + 1 6 | text = text.upper() 7 | 8 | return ''.join([alphabet[alphabet.find(j) + int(key[i]) * mode] for i, j in enumerate(text)]) 9 | 10 | 11 | def assembly(mode): 12 | text = str(input("[+] Enter your text - ")) 13 | key = str(input("[+] Enter your key - ")) 14 | 15 | finished_text = processing(text, key, mode) 16 | 17 | print("\n »» The result of encryption by Gronsfeld cryptography algorithm. ««") 18 | print(finished_text) 19 | 20 | 21 | def main(): 22 | print("[x] Gronsfeld cryptography algorithm. [x]") 23 | print(" • 0. Encryption mode.\n • 1. Decryption mode.") 24 | 25 | mode = (-1) ** int(input("[?] Select program mode - ")) 26 | 27 | assembly(mode) 28 | 29 | 30 | if __name__ == '__main__': 31 | main() 32 | -------------------------------------------------------------------------------- /CryptographyAlgorithms/morse_code.py: -------------------------------------------------------------------------------- 1 | def codesTable(char): 2 | table = { 3 | "A": ".-", "B": "-...", "C": "-.-.", "D": "-..", "E": ".", 4 | "F": "..-.", "G": "--.", "H": "....", "I": "..", "J": ".---", 5 | "K": "-.-", "L": ".-..", "M": "--", "N": "-.", "O": "---", 6 | "P": ".--.", "Q": "--.-", "R": ".-.", "S": "...", "T": "-", 7 | "U": "..-", "V": "...-", "W": ".--", "X": "-..-", "Y": "-.--", "Z": "--..", 8 | 9 | ".-": "A", "-...": "B", "-.-.": "C", "-..": "D", ".": "E", 10 | "..-.": "F", "--.": "G", "....": "H", "..": "I", ".---": "J", 11 | "-.-": "K", ".-..": "L", "--": "M", "-.": "N", "---": "O", 12 | ".--.": "P", "--.-": "Q", ".-.": "R", "...": "S", "-": "T", 13 | "..-": "U", "...-": "V", ".--": "W", "-..-": "X", "-.--": "Y", "--..": "Z", 14 | 15 | "0": "-----", "1": ".----", "2": "..---", "3": "...--", "4": "....-", 16 | "5": ".....", "6": "-....", "7": "--...", "8": "---..", "9": "----.", 17 | 18 | "-----": "0", ".----": "1", "..---": "2", "...--": "3", "....-": "4", 19 | ".....": "5", "-....": "6", "--...": "7", "---..": "8", "----.": "9" 20 | } 21 | 22 | return table[char] 23 | 24 | 25 | def encoding(text): 26 | text, finished_text = text.upper(), "" 27 | for symbol in text: 28 | if symbol.isalnum(): 29 | finished_text += codesTable(symbol) + " " 30 | 31 | return finished_text 32 | 33 | 34 | def decoding(text): 35 | text, finished_text = text.upper(), "" 36 | for code in text.split(): 37 | finished_text += codesTable(code) 38 | 39 | return finished_text 40 | 41 | 42 | def assembly(mode): 43 | text = str(input("[+] Enter your text - ")) 44 | 45 | if mode == 0: 46 | finished_text = encoding(text) 47 | else: 48 | finished_text = decoding(text) 49 | 50 | print("\n »» The result of encoding by Morse algorithm. ««") 51 | print(finished_text) 52 | 53 | 54 | def main(): 55 | print("[x] Morse cryptography algorithm. [x]") 56 | print(" • 0. Encoding mode.\n • 1. Decoding mode.") 57 | 58 | mode = int(input("[?] Select program mode - ")) 59 | assembly(mode) 60 | 61 | 62 | if __name__ == '__main__': 63 | main() 64 | -------------------------------------------------------------------------------- /CryptographyAlgorithms/polybius_square_cipher.py: -------------------------------------------------------------------------------- 1 | from string import ascii_uppercase as alphabet 2 | 3 | 4 | def codes_table(char): 5 | table = { 6 | "A": 11, "B": 21, "C": 31, "D": 41, "E": 51, 7 | "F": 12, "G": 22, "H": 32, "I": 42, "K": 52, 8 | "L": 13, "M": 23, "N": 33, "O": 43, "P": 53, 9 | "Q": 14, "R": 24, "S": 34, "T": 44, "U": 54, 10 | "V": 15, "W": 25, "X": 35, "Y": 45, "Z": 55, "J": 0, 11 | 12 | 11: "A", 21: "B", 31: "C", 41: "D", 51: "E", 13 | 12: "F", 22: "G", 32: "H", 42: "I", 52: "K", 14 | 13: "L", 23: "M", 33: "N", 43: "O", 53: "P", 15 | 14: "Q", 24: "R", 34: "S", 44: "T", 54: "U", 16 | 15: "V", 25: "W", 35: "X", 45: "Y", 55: "Z", 0: "J" 17 | } 18 | 19 | return table[char] 20 | 21 | 22 | def encoding(text): 23 | text, finished_text = text.upper(), "" 24 | for symbol in text: 25 | if symbol in alphabet: 26 | finished_text += str(codes_table(symbol)) + " " 27 | 28 | return finished_text 29 | 30 | 31 | def decoding(text): 32 | text, finished_text = text.upper(), "" 33 | for symbol in list(map(int, text.split())): 34 | finished_text += codes_table(symbol) 35 | 36 | return finished_text 37 | 38 | 39 | def assembly(mode): 40 | text = str(input("[+] Enter your text - ")) 41 | 42 | if mode == 0: 43 | finished_text = encoding(text) 44 | else: 45 | finished_text = decoding(text) 46 | 47 | print("\n »» The result of encoding by Morse algorithm. ««") 48 | print(finished_text) 49 | 50 | 51 | def main(): 52 | print("[x] Polybius Square cryptography algorithm. [x]") 53 | print(" • 0. Encoding mode.\n • 1. Decoding mode.") 54 | 55 | mode = int(input("[?] Select program mode - ")) 56 | assembly(mode) 57 | 58 | 59 | if __name__ == '__main__': 60 | main() 61 | -------------------------------------------------------------------------------- /CryptographyAlgorithms/rsa.py: -------------------------------------------------------------------------------- 1 | """ 2 | Further in creation_keys() function will be used alphabetic variables. 3 | I will explain the meaning of each of them. 4 | They were used for convenience. 5 | [p], [q] - two prime numbers. 6 | [n] - the product of [p] on [q]. 7 | [f] - euler function of [n]. 8 | [e] - an open exponent is such that ([e] is prime) and (e < f) and (f mod e != 0). 9 | [d] - an secret exponent is such that (d * e) mod f = 1. 10 | """ 11 | from math import sqrt 12 | from random import randint 13 | 14 | 15 | def is_prime(n): 16 | i = 2 17 | while i <= sqrt(n): 18 | if n % i == 0: 19 | return False 20 | i += 1 21 | return True 22 | 23 | 24 | def creation_keys(): 25 | p, q, e = 10, 10, 4 26 | while not is_prime(p): 27 | p = randint(500, 700) 28 | while not is_prime(q): 29 | q = randint(500, 700) 30 | n, f, d = p * q, (p - 1) * (q - 1), 0 31 | while (not is_prime(e)) or (e > f) or (f % e == 0): 32 | e += 1 33 | while (d * e) % f != 1: 34 | d += 1 35 | return (e, n), (d, n) 36 | 37 | 38 | def encoding(text, open_key): 39 | cipher_list = [] 40 | e, n = open_key 41 | for letter in text: 42 | cipher_list.append(ord(letter) ** e % n) 43 | 44 | return cipher_list 45 | 46 | 47 | def decoding(cipher_list, close_key): 48 | text = "" 49 | d, n = close_key 50 | for item in cipher_list: 51 | text += chr(int(item) ** d % n) 52 | 53 | return text 54 | 55 | 56 | def encoding_mode(): 57 | print("\n » Encoding mode activated! « (~˘▾˘)~") 58 | 59 | text = str(input("[+] Enter your text - ")) 60 | open_key, close_key = creation_keys() 61 | print("[~] Your open key - [{},{}].".format(open_key[0], open_key[1])) 62 | print("[~] Your close key - [{},{}].".format(close_key[0], close_key[1])) 63 | 64 | cipher_list = encoding(text, open_key) 65 | 66 | print("\n »» The result of encoding by RSA algorithm. ««") 67 | print(cipher_list) 68 | 69 | 70 | def decoding_mode(): 71 | print("\n » Decoding mode activated! « (~˘▾˘)~") 72 | 73 | cipher_list = eval(input("[+] Enter your cipher list - ")) 74 | close_key = eval(input("[+] Enter your close key - ")) 75 | 76 | text = decoding(cipher_list, close_key) 77 | 78 | print("\n »» The result of decoding by RSA algorithm. ««") 79 | print(text) 80 | 81 | 82 | def main(): 83 | print("[x] Rivest–Shamir–Adleman cryptography algorithm. [x]") 84 | print(" • 0. Encoding mode.\n • 1. Decoding mode.") 85 | 86 | mode = int(input("[?] Select program mode - ")) 87 | 88 | if mode == 0: 89 | encoding_mode() 90 | elif mode == 1: 91 | decoding_mode() 92 | else: 93 | print("[x] Invalid input! You can only select: \"0, 1, 2\".") 94 | raise SystemExit 95 | 96 | 97 | if __name__ == '__main__': 98 | main() 99 | -------------------------------------------------------------------------------- /CryptographyAlgorithms/vigenere_cipher.py: -------------------------------------------------------------------------------- 1 | def processing(mode, text, key): 2 | key_ints = [ord(i) for i in key] 3 | text_ints = [ord(i) for i in text] 4 | finished_text = "" 5 | for i in range(len(text_ints)): 6 | adder = key_ints[i % len(key)] 7 | if mode == 1: 8 | adder *= -1 9 | char = (text_ints[i] - 32 + adder) % 95 10 | finished_text += chr(char + 32) 11 | return finished_text 12 | 13 | 14 | def assembly(mode): 15 | text = str(input("[+] Enter your text - ")) 16 | key = str(input("[+] Enter your key - ")) 17 | 18 | finished_text = processing(mode, text, key) 19 | 20 | print("\n »» The result by Vigenere algorithm. ««") 21 | print(finished_text) 22 | 23 | 24 | def main(): 25 | print("[x] Vigenere cryptography algorithm. [x]") 26 | print(" • 0. Encryption mode.\n • 1. Decryption mode.") 27 | 28 | mode = int(input("[?] Select program mode - ")) 29 | assembly(mode) 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Ilyas Salimov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## The Algorithms. 2 | ![front-image](https://image.ibb.co/eUJKdS/Algorithms_In_Computer_Science.jpg) 3 | ### Some information about the repository. 4 | All algorithms are implemented on Python. For the execution of algorithms, the standard Python library version 3.6 is required. These algorithms are need for practice Python, a better understanding of algorithms and education the programming. 5 | ### What is Algorithms? 6 | - Algorithm. 7 | In mathematics and computer science, an algorithm is an unambiguous specification of how to solve a class of problems. Algorithms can perform calculation, data processing and automated reasoning tasks. 8 | 9 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Algorithm) 10 | 11 | - Computer algorithm. 12 | In computer systems, an algorithm is basically an instance of logic written in software by software developers to be effective for the intended "target" computer(s) to produce output from given (perhaps null) input. An optimal algorithm, even running in old hardware, would produce faster results than a non-optimal (higher time complexity) algorithm for the same purpose, running in more efficient hardware; that is why algorithms, like computer hardware, are considered technology. 13 | 14 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Algorithm#Computer_algorithms) 15 | 16 | ### Sorting Algorithms. 17 | In computer science, a sorting algorithm is an algorithm that puts elements of a list in a certain order. The most-used orders are numerical order and lexicographical order. Efficient sorting is important for optimizing the use of other algorithms (such as search and merge algorithms) which require input data to be in sorted lists; it is also often useful for canonicalizing data and for producing human-readable output. 18 | ##### Source: [Wikipeadia](https://en.wikipedia.org/wiki/Sorting_algorithm) 19 | 20 | #### Bubble Sort. 21 | Bubble sort, sometimes referred to as sinking sort, is a simple sorting algorithm that repeatedly steps through the list to be sorted, compares each pair of adjacent items and swaps them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted. 22 | ##### Visualization of bubble sort. 23 | ![Visualization of bubble sort](https://upload.wikimedia.org/wikipedia/commons/c/c8/Bubble-sort-example-300px.gif "Visualization of bubble sort") 24 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Bubble_sort) 25 | 26 | #### Insertion Sort. 27 | Insertion sort is a simple sorting algorithm that builds the final sorted array (or list) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. 28 | ##### Visualization of insertion sort. 29 | ![Visualization of insertion sort](https://upload.wikimedia.org/wikipedia/commons/0/0f/Insertion-sort-example-300px.gif "Visualization of insertion sort") 30 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Insertion_sort) 31 | 32 | #### Gnome Sort. 33 | It is a sorting algorithm which is similar to insertion sort, except that moving an element to its proper place is accomplished by a series of swaps, as in bubble sort. It is conceptually simple, requiring no nested loops. 34 | ##### Visualization of gnome sort. 35 | ![Visualization of gnome sort](https://upload.wikimedia.org/wikipedia/commons/3/37/Sorting_gnomesort_anim.gif "Visualization of gnome sort") 36 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Gnome_sort) 37 | 38 | #### Cocktail Sort. 39 | Cocktail shaker sort, also known as bidirectional bubble sort, cocktail sort, shaker sort (which can also refer to a variant of selection sort), ripple sort, shuffle sort, or shuttle sort, is a variation of bubble sort that is both a stable sorting algorithm and a comparison sort. 40 | ##### Visualization of cocktail sort. 41 | ![Visualization of cocktail sort](https://upload.wikimedia.org/wikipedia/commons/e/ef/Sorting_shaker_sort_anim.gif "Visualization of cocktail sort") 42 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Cocktail_sort) 43 | 44 | #### Merge Sort. 45 | Insertion sort is a simple sorting algorithm that builds the final sorted array (or list) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. 46 | ##### Visualization of merge sort. 47 | ![Visualization of merge sort](https://upload.wikimedia.org/wikipedia/commons/c/cc/Merge-sort-example-300px.gif "Visualization of merge sort") 48 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Merge_sort) 49 | 50 | #### Selection Sort. 51 | In computer science, selection sort is a sorting algorithm, specifically an in-place comparison sort. It has O(n2) time complexity, making it inefficient on large lists, and generally performs worse than the similar insertion sort. Selection sort is noted for its simplicity, and it has performance advantages over more complicated algorithms in certain situations, particularly where auxiliary memory is limited. 52 | ##### Visualization of selection sort. 53 | ![Visualization of selection sort](https://upload.wikimedia.org/wikipedia/commons/9/94/Selection-Sort-Animation.gif "Visualization of selection sort") 54 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Selection_sort) 55 | 56 | #### Shell Sort. 57 | Shellsort, also known as Shell sort or Shell's method, is an in-place comparison sort. It can be seen as either a generalization of sorting by exchange (bubble sort) or sorting by insertion (insertion sort). 58 | ##### Visualization of shell sort. 59 | ![Visualization of shell sort](https://upload.wikimedia.org/wikipedia/commons/d/d8/Sorting_shellsort_anim.gif "Visualization of shell sort") 60 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Shell_sort) 61 | 62 | #### Bucket Sort. 63 | Bucket sort, or bin sort, is a sorting algorithm that works by distributing the elements of an array into a number of buckets. Each bucket is then sorted individually, either using a different sorting algorithm, or by recursively applying the bucket sorting algorithm. 64 | ##### Visualization of bucket sort. 65 | ![Visualization of bucket sort](http://sorting.valemak.com/wp-content/uploads/2013/12/sort_bucket.gif "Visualization of bucket sort") 66 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Bucket_sort) 67 | 68 | #### Quick Sort. 69 | Quicksort (sometimes called partition-exchange sort) is an efficient sorting algorithm, serving as a systematic method for placing the elements of an array in order. Developed by Tony Hoare in 1959 and published in 1961, it is still a commonly used algorithm for sorting. 70 | ##### Visualization of quick sort. 71 | ![Visualization of quick sort](https://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif "Visualization of quick sort") 72 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Quicksort) 73 | 74 | #### Comb Sort. 75 | Comb sort is a relatively simple sorting algorithm originally designed by Włodzimierz Dobosiewicz in 1980. Later it was rediscovered by Stephen Lacey and Richard Box in 1991. Comb sort improves on bubble sort. 76 | ##### Visualization of comb sort. 77 | ![Visualization of comb sort](https://upload.wikimedia.org/wikipedia/commons/4/46/Comb_sort_demo.gif "Visualization of comb sort") 78 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Comb_sort) 79 | 80 | #### Stooge Sort. 81 | Stooge sort is a recursive sorting algorithm. The running time of the algorithm is thus slower compared to efficient sorting algorithms, such as Merge sort, and is even slower than Bubble sort, a canonical example of a fairly inefficient and simple sort. 82 | ##### Visualization of stooge sort. 83 | ![Visualization of stooge sort](https://upload.wikimedia.org/wikipedia/commons/f/f8/Sorting_stoogesort_anim.gif "Visualization of stooge sort") 84 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Stooge_sort) 85 | 86 | ### Searching Algorithms. 87 | In computer science, a search algorithm is any algorithm which solves the search problem, namely, to retrieve information stored within some data structure, or calculated in the search space of a problem domain. Examples of such structures include but are not limited to a linked list, an array data structure, or a search tree. The appropriate search algorithm often depends on the data structure being searched, and may also include prior knowledge about the data. Searching also encompasses algorithms that query the data structure, such as the SQL SELECT command. 88 | ##### Source: [Wikipeadia](https://en.wikipedia.org/wiki/Search_algorithm) 89 | 90 | #### Linear Search. 91 | In computer science, linear search or sequential search is a method for finding a target value within a list. It sequentially checks each element of the list for the target value until a match is found or until all the elements have been searched. 92 | ##### Visualization of linear search. 93 | ![Visualization of linear search](https://www.tutorialspoint.com/data_structures_algorithms/images/linear_search.gif "Visualization of linear search") 94 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Linear_search) 95 | 96 | #### Binary Search. 97 | In computer science, binary search, also known as half-interval search, logarithmic search, or binary chop, is a search algorithm that finds the position of a target value within a sorted array. 98 | ##### Visualization of binary search. 99 | ![Visualization of binary search](https://image.ibb.co/jHDFsx/68747470733a2f2f626c6f672e70656e6a65652e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031352f31322f6f7074696d616c2d62696e6172792d7365617263682d747265652d66726f6d2d736f727465642d61727261792e676966.gif "Visualization of binary search") 100 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Binary_search) 101 | 102 | #### Interpolation Search. 103 | Interpolation search is an algorithm for searching for a given key in an indexed array that has been ordered by numerical values assigned to the keys (key values). It parallels how humans search through a telephone book for a particular name, the key value by which the book's entries are ordered. In each search step it calculates where in the remaining search space the sought item might be, based on the key values at the bounds of the search space and the value of the sought key, usually via a linear interpolation. The key value actually found at this estimated position is then compared to the key value being sought. If it is not equal, then depending on the comparison, the remaining search space is reduced to the part before or after the estimated position. This method will only work if calculations on the size of differences between key values are sensible. 104 | ##### Visualization of interpolation search. 105 | ![Visualization of interpolation search](https://image.ibb.co/b6OFsx/Interpolation_Searchfig_1.png "Visualization of interpolation search") 106 | ![Visualization of interpolation search](https://image.ibb.co/efwDec/Interpolation_Searchfig_2.png "Visualization of interpolation search") 107 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Interpolation_search) 108 | 109 | ### Cryprography Algorithms. 110 | Cryptography is the practice and study of techniques for secure communication in the presence of third parties called adversaries. More generally, cryptography is about constructing and analyzing protocols that prevent third parties or the public from reading private messages; various aspects in information security such as data confidentiality, data integrity, authentication, and non-repudiation are central to modern cryptography. Modern cryptography exists at the intersection of the disciplines of mathematics, computer science, electrical engineering, communication science, and physics. Applications of cryptography include electronic commerce, chip-based payment cards, digital currencies, computer passwords, and military communications. 111 | ##### Source: [Wikipeadia](https://en.wikipedia.org/wiki/Cryptography) 112 | 113 | #### RSA. 114 | RSA (Rivest–Shamir–Adleman) is one of the first public-key cryptosystems and is widely used for secure data transmission. In such a cryptosystem, the encryption key is public and it is different from the decryption key which is kept secret (private). In RSA, this asymmetry is based on the practical difficulty of the factorization of the product of two large prime numbers, the "factoring problem". The acronym RSA is made of the initial letters of the surnames of Ron Rivest, Adi Shamir, and Leonard Adleman, who first publicly described the algorithm in 1978. Clifford Cocks, an English mathematician working for the British intelligence agency Government Communications Headquarters (GCHQ), had developed an equivalent system in 1973, but this was not declassified until 1997. 115 | ##### Visualization of RSA. 116 | ![Visualization of RSA](https://image.ibb.co/kJfYFS/Crypto_Fig05b.jpg "Visualization of RSA") 117 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/RSA_(cryptosystem)) 118 | 119 | #### Caesar cipher. 120 | In cryptography, a Caesar cipher, also known as Caesar's cipher, the shift cipher, Caesar's code or Caesar shift, is one of the simplest and most widely known encryption techniques. It is a type of substitution cipher in which each letter in the plaintext is replaced by a letter some fixed number of positions down the alphabet. 121 | ##### Visualization of Caesar cipher. 122 | ![Visualization of Caesar cipher](https://www.sciencebuddies.org/Files/9037/8/caesar-cipher-shift-left-thumbnail.png "Visualization of Caesar cipher") 123 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Caesar_cipher) 124 | 125 | #### Gronsfeld cipher. 126 | The Gronsfeld cipher is a variant created by Count Gronsfeld which is identical to the Vigenère cipher, except that it uses just 10 different cipher alphabets (corresponding to the digits 0 to 9). The Gronsfeld cipher is strengthened because its key is not a word, but it is weakened because it has just 10 cipher alphabets. Gronsfeld's cipher did become widely used throughout Germany and Europe, despite its weaknesses. 127 | ##### Visualization of Gronsfeld cipher. 128 | ![Visualization of Gronsfeld cipher](https://www.cryptool.org/images/gronsfeldEN.jpg "Visualization of Gronsfeld cipher") 129 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) 130 | 131 | #### Morse code. 132 | Morse code is a method of transmitting text information as a series of on-off tones, lights, or clicks that can be directly understood by a skilled listener or observer without special equipment. It is named for Samuel F. B. Morse, an inventor of the telegraph. The International Morse Code encodes the ISO basic Latin alphabet, some extra Latin letters, the Arabic numerals and a small set of punctuation and procedural signals (prosigns) as standardized sequences of short and long signals called "dots" and "dashes", or "dits" and "dahs", as in amateur radio practice. 133 | ##### Visualization of Morse code. 134 | ![Visualization of Morse code](https://upload.wikimedia.org/wikipedia/commons/thumb/c/ca/Morse_code_tree3.png/650px-Morse_code_tree3.png "Visualization of Morse code") 135 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Morse_code) 136 | 137 | #### Vigenere cipher. 138 | The Vigenère cipher is a method of encrypting alphabetic text by using a series of interwoven Caesar ciphers based on the letters of a keyword. It is a form of polyalphabetic substitution. 139 | ##### Visualization of Vigenere cipher. 140 | ![Visualization of Vigenere cipher](https://pages.mtu.edu/~shene/NSF-4/Tutorial/VIG/FIG-VIG-Table.jpg "Visualization of Vigenere cipher") 141 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher) 142 | 143 | #### Polybius Square cipher. 144 | In cryptography, the Polybius square, also known as the Polybius checkerboard, is a device invented by the Ancient Greek historian and scholar Polybius, for fractionating plaintext characters so that they can be represented by a smaller set of symbols. 145 | ##### Visualization of Polybius Square cipher. 146 | ![Visualization of Polybius Square cipher](http://www.rimwe.com/_Media/polybius_square_med.jpeg "Visualization of Polybius Square cipher") 147 | ##### Source: [Wikipedia](https://en.wikipedia.org/wiki/Polybius_square) 148 | 149 | > Sincerely, Ilyas Salimov. 150 | > Email: ilyas.salimov.07@gmail.com -------------------------------------------------------------------------------- /SearchingAlgorithms/binary_search.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def binary_search(collection, target): 6 | left, right, counter = 0, len(collection), 0 7 | while left != right: 8 | c = (left + right) // 2 9 | if target == collection[c]: 10 | counter += 1 11 | print("Step %i -->" % counter, [collection[c]]) 12 | return c, counter 13 | elif target < collection[c]: 14 | counter += 1 15 | right = c 16 | print("Step %i -->" % counter, collection[:right]) 17 | else: 18 | counter += 1 19 | left = c + 1 20 | print("Step %i -->" % counter, collection[left:]) 21 | 22 | return -1, counter 23 | 24 | 25 | def visualization(): 26 | length = 10 27 | collection = [item for item in range(0, length)] 28 | target = randint(0, length - 1) 29 | 30 | print("Initial list:", collection) 31 | print("The number of which must be found:", target) 32 | print("Visualization of algorithm work.") 33 | 34 | result, counter = binary_search(collection, target) 35 | if result != -1: 36 | print("Result of searching:", result) 37 | else: 38 | print("This number does not exist in the list.") 39 | 40 | print("Total numbers of passages:", counter) 41 | 42 | 43 | def main(): 44 | elapsed_time = timeit.timeit(visualization, number=1) 45 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /SearchingAlgorithms/interpolation_search.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def interpolation_search(collection, target): 6 | left, right, counter = 0, len(collection) - 1, 0 7 | while (collection[left] <= target) and (collection[right] >= target): 8 | middle = left + ((target - collection[left]) * (right - left)) // (collection[right] - collection[left]) 9 | if collection[middle] < target: 10 | counter += 1 11 | left = middle + 1 12 | print("Step %i -->" % counter, collection[left:]) 13 | elif collection[middle] > target: 14 | counter += 1 15 | right = middle - 1 16 | print("Step %i -->" % counter, collection[:right]) 17 | else: 18 | counter += 1 19 | print("Step %i -->" % counter, [collection[middle]]) 20 | return middle, counter 21 | 22 | return -1, counter 23 | 24 | 25 | def visualization(): 26 | length = 10 27 | collection = [item for item in range(0, length)] 28 | target = randint(0, length - 1) 29 | 30 | print("Initial list:", collection) 31 | print("The number of which must be found:", target) 32 | print("Visualization of algorithm work.") 33 | 34 | result, counter = interpolation_search(collection, target) 35 | if result != -1: 36 | print("Result of searching: ", result) 37 | else: 38 | print("This number does not exist in the list.") 39 | 40 | print("Total numbers of passages:", counter) 41 | 42 | 43 | def main(): 44 | elapsed_time = timeit.timeit(visualization, number=1) 45 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | -------------------------------------------------------------------------------- /SearchingAlgorithms/linear_search.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def linear_search(collection, target): 6 | for i in range(0, len(collection)): 7 | if collection[i] == target: 8 | return i 9 | return -1 10 | 11 | 12 | def visualization(): 13 | length = 10 14 | collection = [randint(0, length) for _ in range(0, length)] 15 | target = randint(0, length - 1) 16 | 17 | print("Initial list:", collection) 18 | print("The number of which must be found:", target) 19 | 20 | result = linear_search(collection, target) 21 | if result != -1: 22 | print("Result of searching: ", result) 23 | else: 24 | print("This number does not exist in the list.") 25 | 26 | 27 | def main(): 28 | elapsed_time = timeit.timeit(visualization, number=1) 29 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 30 | 31 | 32 | if __name__ == '__main__': 33 | main() 34 | -------------------------------------------------------------------------------- /SortingAlgorithms/bubble_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def bubble_sort(collection): 6 | counter = 0 7 | length = len(collection) 8 | for i in range(0, length - 1): 9 | is_sorted = True 10 | for j in range(0, length - 1): 11 | if collection[j] > collection[j + 1]: 12 | collection[j], collection[j + 1] = collection[j + 1], collection[j] 13 | is_sorted = False 14 | counter += 1 15 | print("Step %i -->" % counter, collection) 16 | if is_sorted: 17 | break 18 | 19 | return collection, counter 20 | 21 | 22 | def visualization(): 23 | length = 10 24 | collection = [randint(0, length) for _ in range(length)] 25 | 26 | print("Initial list:", collection) 27 | print("Visualization of algorithm work.") 28 | 29 | collection, counter = bubble_sort(collection) 30 | 31 | print("Final list:", collection) 32 | print("Total numbers of passages:", counter) 33 | 34 | 35 | def main(): 36 | elapsed_time = timeit.timeit(visualization, number=1) 37 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /SortingAlgorithms/bucket_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def bucket_sort(collection): 6 | length = len(collection) 7 | buckets_list = [0 for _ in range(length + 1)] 8 | 9 | print("\tBuckets list before sorting - {}".format(buckets_list)) 10 | 11 | for j in range(length): 12 | buckets_list[collection[j]] += 1 13 | 14 | print("\tBuckets list after sorting - {}".format(buckets_list)) 15 | 16 | counter = 0 17 | for i in range(length + 1): 18 | for j in range(buckets_list[i]): 19 | collection[counter] = i 20 | counter += 1 21 | 22 | return collection 23 | 24 | 25 | def visualization(): 26 | length = 10 27 | collection = [randint(0, length) for _ in range(length)] 28 | 29 | print("Initial list:", collection) 30 | print("Visualization of algorithm work.") 31 | 32 | collection = bucket_sort(collection) 33 | 34 | print("Final list:", collection) 35 | 36 | 37 | def main(): 38 | elapsed_time = timeit.timeit(visualization, number=1) 39 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 40 | 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /SortingAlgorithms/cocktail_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def cocktail_sort(collection): 6 | counter = 0 7 | length = len(collection) 8 | left, right = 0, length - 1 9 | 10 | while left <= right: 11 | for i in range(left, right, +1): 12 | if collection[i] > collection[i + 1]: 13 | collection[i], collection[i + 1] = collection[i + 1], collection[i] 14 | 15 | right -= 1 16 | for i in range(right, left, -1): 17 | if collection[i - 1] > collection[i]: 18 | collection[i], collection[i - 1] = collection[i - 1], collection[i] 19 | left += 1 20 | counter += 1 21 | print("Step %i -->" % counter, collection) 22 | 23 | return collection, counter 24 | 25 | 26 | def visualization(): 27 | length = 10 28 | collection = [randint(0, length) for _ in range(length)] 29 | 30 | print("Initial list:", collection) 31 | print("Visualization of algorithm work.") 32 | 33 | collection, counter = cocktail_sort(collection) 34 | 35 | print("Final list:", collection) 36 | print("Total numbers of passages:", counter) 37 | 38 | 39 | def main(): 40 | elapsed_time = timeit.timeit(visualization, number=1) 41 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /SortingAlgorithms/comb_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def comb_sort(collection, counter): 6 | length = len(collection) 7 | gap = length * 10 // 13 if length > 1 else 0 8 | 9 | while gap: 10 | if 8 < gap < 11: 11 | gap = 11 12 | swapped = 0 13 | for index in range(length - gap): 14 | if collection[index + gap] < collection[index]: 15 | collection[index + gap], collection[index] = collection[index], collection[index + gap] 16 | swapped = 1 17 | 18 | counter += 1 19 | print("Step %i -->" % counter, collection) 20 | gap = (gap * 10 // 13) or swapped 21 | 22 | return collection, counter 23 | 24 | 25 | def visualization(): 26 | counter = 0 27 | length = 10 28 | collection = [randint(0, length) for _ in range(length)] 29 | 30 | print("Initial list:", collection) 31 | print("Visualization of algorithm work.") 32 | 33 | collection, counter = comb_sort(collection, counter) 34 | 35 | print("Final list:", collection) 36 | print("Total numbers of passages:", counter) 37 | 38 | 39 | def main(): 40 | elapsed_time = timeit.timeit(visualization, number=1) 41 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 42 | 43 | 44 | if __name__ == '__main__': 45 | main() 46 | -------------------------------------------------------------------------------- /SortingAlgorithms/gnome_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def gnome_sort(collection): 6 | length = len(collection) 7 | i, j, counter = 1, 2, 0 8 | 9 | while i < length: 10 | if collection[i - 1] < collection[i]: 11 | i, j = j, j + 1 12 | 13 | counter += 1 14 | print("Step %i -->" % counter, collection) 15 | else: 16 | collection[i], collection[i - 1] = collection[i - 1], collection[i] 17 | i -= 1 18 | if i == 0: 19 | i, j = j, j + 1 20 | 21 | return collection, counter 22 | 23 | 24 | def visualization(): 25 | length = 10 26 | collection = [randint(0, length) for _ in range(length)] 27 | 28 | print("Initial list:", collection) 29 | print("Visualization of algorithm work.") 30 | 31 | collection, counter = gnome_sort(collection) 32 | 33 | print("Final list:", collection) 34 | print("Total numbers of passages:", counter) 35 | 36 | 37 | def main(): 38 | elapsed_time = timeit.timeit(visualization, number=1) 39 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 40 | 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /SortingAlgorithms/insertion_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def insertion_sort(collection): 6 | counter = 0 7 | length = len(collection) 8 | for i in range(0, length): 9 | value = collection[i] 10 | j = i 11 | while (j > 0) and (collection[j - 1] > value): 12 | collection[j] = collection[j - 1] 13 | j -= 1 14 | collection[j] = value 15 | 16 | counter += 1 17 | print("Step %i -->" % counter, collection) 18 | 19 | return collection, counter 20 | 21 | 22 | def visualization(): 23 | length = 10 24 | collection = [randint(0, length) for _ in range(length)] 25 | 26 | print("Initial list:", collection) 27 | print("Visualization of algorithm work.") 28 | 29 | collection, counter = insertion_sort(collection) 30 | 31 | print("Final list:", collection) 32 | print("Total numbers of passages:", counter) 33 | 34 | 35 | def main(): 36 | elapsed_time = timeit.timeit(visualization, number=1) 37 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 38 | 39 | 40 | if __name__ == '__main__': 41 | main() 42 | -------------------------------------------------------------------------------- /SortingAlgorithms/merge_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def merge_sort(collection, length, counter): 6 | if len(collection) > 1: 7 | middle_position = len(collection) // 2 8 | left = collection[:middle_position] 9 | right = collection[middle_position:] 10 | counter = merge_sort(left, length, counter) 11 | counter = merge_sort(right, length, counter) 12 | 13 | left_index, right_index, index = 0, 0, 0 14 | while (left_index < len(left)) and (right_index < len(right)): 15 | if left[left_index] < right[right_index]: 16 | collection[index] = left[left_index] 17 | left_index += 1 18 | else: 19 | collection[index] = right[right_index] 20 | right_index += 1 21 | index += 1 22 | 23 | while left_index < len(left): 24 | collection[index] = left[left_index] 25 | left_index += 1 26 | index += 1 27 | 28 | while right_index < len(right): 29 | collection[index] = right[right_index] 30 | right_index += 1 31 | index += 1 32 | 33 | counter += 1 34 | print("Step %i -->" % counter, left, "<-->", right) 35 | 36 | if len(collection) == length: 37 | return collection, counter 38 | return counter 39 | 40 | 41 | def visualization(): 42 | counter = 0 43 | length = 10 44 | collection = [randint(0, length) for _ in range(length)] 45 | 46 | print("Initial list:", collection) 47 | print("Visualization of algorithm work.") 48 | 49 | collection, counter = merge_sort(collection, length, counter) 50 | 51 | print("Final list:", collection) 52 | print("Total numbers of passages:", counter) 53 | 54 | 55 | def main(): 56 | elapsed_time = timeit.timeit(visualization, number=1) 57 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 58 | 59 | 60 | if __name__ == '__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /SortingAlgorithms/quick_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def partition(collection, left, right): 6 | pivot = collection[right] 7 | j = left 8 | for i in range(left, right): 9 | if collection[i] <= pivot: 10 | collection[i], collection[j] = collection[j], collection[i] 11 | j += 1 12 | collection[right], collection[j] = collection[j], collection[right] 13 | return j 14 | 15 | 16 | def quickSort(collection, left, right, counter): 17 | if left < right: 18 | counter += 1 19 | print("Step %i -->" % counter, collection) 20 | 21 | mainstay = partition(collection, left, right) 22 | collection, counter = quickSort(collection, left, mainstay - 1, counter) 23 | collection, counter = quickSort(collection, mainstay + 1, right, counter) 24 | 25 | return collection, counter 26 | 27 | 28 | def visualization(): 29 | counter = 0 30 | length = 10 31 | collection = [randint(0, length) for _ in range(length)] 32 | 33 | print("Initial list:", collection) 34 | print("Visualization of algorithm work.") 35 | 36 | collection, counter = quickSort(collection, 0, length - 1, counter) 37 | 38 | print("Final list:", collection) 39 | print("Total numbers of passages:", counter) 40 | 41 | 42 | def main(): 43 | elapsedTime = timeit.timeit(visualization, number=1) 44 | print("Elapsed time: ", round(elapsedTime, 7), "sec.") 45 | 46 | 47 | if __name__ == '__main__': 48 | main() 49 | -------------------------------------------------------------------------------- /SortingAlgorithms/selection_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def selection_sort(collection): 6 | counter = 0 7 | length = len(collection) 8 | for i in range(0, length - 1): 9 | j = i 10 | for index in range(i + 1, length): 11 | if collection[index] < collection[j]: 12 | j = index 13 | collection[j], collection[i] = collection[i], collection[j] 14 | 15 | counter += 1 16 | print("Step %i -->" % counter, collection) 17 | 18 | return collection, counter 19 | 20 | 21 | def visualization(): 22 | length = 10 23 | collection = [randint(0, length) for _ in range(length)] 24 | 25 | print("Initial list:", collection) 26 | print("Visualization of algorithm work.") 27 | 28 | collection, counter = selection_sort(collection) 29 | 30 | print("Final list:", collection) 31 | print("Total numbers of passages:", counter) 32 | 33 | 34 | def main(): 35 | elapsed_time = timeit.timeit(visualization, number=1) 36 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 37 | 38 | 39 | if __name__ == '__main__': 40 | main() 41 | -------------------------------------------------------------------------------- /SortingAlgorithms/shell_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def shell_sort(collection): 6 | length = len(collection) 7 | middle, counter = length // 2, 0 8 | 9 | while middle > 0: 10 | for i in range(0, length - middle): 11 | j = i 12 | while (j >= 0) and (collection[j] > collection[j + middle]): 13 | temp = collection[j] 14 | collection[j] = collection[j + middle] 15 | collection[j + middle] = temp 16 | 17 | j, counter = j - 1, counter + 1 18 | print("Step %i -->" % counter, collection) 19 | 20 | middle = middle // 2 21 | 22 | return collection, counter 23 | 24 | 25 | def visualization(): 26 | length = 10 27 | collection = [randint(0, length) for _ in range(length)] 28 | 29 | print("Initial list:", collection) 30 | print("Visualization of algorithm work.") 31 | 32 | collection, counter = shell_sort(collection) 33 | 34 | print("Final list:", collection) 35 | print("Total numbers of passages:", counter) 36 | 37 | 38 | def main(): 39 | elapsed_time = timeit.timeit(visualization, number=1) 40 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | -------------------------------------------------------------------------------- /SortingAlgorithms/stooge_sort.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | from random import randint 3 | 4 | 5 | def stooge_sort(collection, left, right, counter): 6 | if left >= right: 7 | return 8 | 9 | if collection[right] < collection[left]: 10 | collection[left], collection[right] = collection[right], collection[left] 11 | 12 | counter += 1 13 | print("Step %i -->" % counter, collection) 14 | 15 | if (right - left + 1) > 2: 16 | list_part = (right - left + 1) // 3 17 | counter = stooge_sort(collection, left, right - list_part, counter) 18 | counter = stooge_sort(collection, left + list_part, right, counter) 19 | counter = stooge_sort(collection, left, right - list_part, counter) 20 | 21 | return counter 22 | 23 | 24 | def visualization(): 25 | counter = 0 26 | length_list = 10 27 | collection = [randint(0, length_list) for _ in range(length_list)] 28 | 29 | print("Initial list:", collection) 30 | print("Visualization of algorithm work.") 31 | 32 | counter = stooge_sort(collection, 0, length_list - 1, counter) 33 | 34 | print("Final list:", collection) 35 | print("Total numbers of passages:", counter) 36 | 37 | 38 | def main(): 39 | elapsed_time = timeit.timeit(visualization, number=1) 40 | print("Elapsed time: ", round(elapsed_time, 7), "sec.") 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | --------------------------------------------------------------------------------