mirea-projects/Second term/Algorithms/5.1/1.py

107 lines
3.3 KiB
Python
Raw Permalink Normal View History

2024-09-23 23:22:33 +00:00
class Node():
def __init__(self, count, data, left=None, right=None) -> None:
self.count = count
self.data = data
self.left = left
self.right = right
def create_coding_formats(node: Node, encoding_format: dict[str, str], decoding_format: dict[str, str], bits="") -> None:
if node is None:
return
if node.data is not None:
encoding_format[node.data] = bits
decoding_format[bits] = node.data
create_coding_formats(node.left, encoding_format, decoding_format, bits + "0")
create_coding_formats(node.right, encoding_format, decoding_format, bits + "1")
def get_unique_letters(message: str) -> list[Node]:
nodes = []
for letter in set(message):
node = Node(message.count(letter), letter)
nodes.append(node)
nodes.sort(key=lambda node: node.count, reverse=True)
return nodes
def huffman_algorithm(nodes: list[Node]) -> tuple[dict[str, str], dict[str, str], Node]:
while len(nodes) > 1:
first_node = nodes.pop()
second_node = nodes.pop()
new_node = Node(first_node.count + second_node.count,
None, first_node, second_node)
nodes.append(new_node)
nodes.sort(key=lambda node: node.count, reverse=True)
encoding_format = {}
decoding_format = {}
create_coding_formats(nodes[0], encoding_format, decoding_format)
return encoding_format, decoding_format, nodes[0]
def encode(message: str, encoding_format: dict[str, str]) -> str:
encoded_message = ""
for letter in message:
encoded_message += encoding_format[letter]
return encoded_message
def decode(encoded_message: int, decoding_format: dict[str, str]) -> str:
decoded_message = ""
bits = ""
for bit in encoded_message:
bits += bit
if decoding_format.get(bits) is not None:
decoded_message += decoding_format[bits]
bits = ""
return decoded_message
def print_tree(node: Node, message: str, depth: int = 0) -> None:
if node is None:
return
print_tree(node.right, message, depth + 1)
print(" " * depth * 5, f"{node.data or '*'} ({node.count / len(message) :.7f})", sep="")
print_tree(node.left, message, depth + 1)
def main() -> None:
print("Введите текст, содержащий не менее двух символов...")
message = input()
unique_letters = get_unique_letters(message)
print("Полученный список:")
for node in unique_letters:
print(f"{node.data} ({node.count / len(message) :.7f})", end=" ---> ")
print("\nПостроим дерево...")
new_encoding_fromat, new_decoding_format, huffman_tree = huffman_algorithm(unique_letters)
print_tree(huffman_tree, message)
print("---------------------------------------------")
print("Приступим к кодировке введенного текста...")
encoded_message = encode(message, new_encoding_fromat)
print("Код перед Вами...", encoded_message)
print(f"Коэффициент сжатия: {len(encoded_message) / (len(message) * 8) * 100 :.4f}%")
decoded_message = decode(encoded_message, new_decoding_format)
print("Ранее было зашифровано...", message)
print("Расшифровано...", decoded_message)
if __name__ == "__main__":
main()