Advertisement
Guest User

Untitled

a guest
Jun 3rd, 2021
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.06 KB | None | 0 0
  1. """
  2. задание:
  3. реализовать алгоритм сжатия Хаффмана
  4.  
  5.  
  6. Создаю класс дерева, чтобы удобно взаимодействовать и не городить.
  7. Наследую от списка потому что так представляю себе структуру дерева,
  8. сразу определяю сумму элементов и элементы на концах веток дерева.
  9.  
  10. !!!читая код, имей в виду, что ноды всегда две!!!
  11. """
  12. class Tree(list):
  13.     def __init__(self, elements, key):
  14.         super().__init__(elements)
  15.         self.sum = 0
  16.         for element in elements:
  17.             if isinstance(element, (int, float)):
  18.                 self.sum += key(element)
  19.             elif isinstance(element, Tree):
  20.                 self.sum += element.sum
  21.         self.ends = []
  22.         for element in elements:
  23.             if not isinstance(element, Tree):
  24.                 self.ends.append(element)
  25.  
  26.  
  27. # собственно, тут весь движ
  28. def generate_paths(text):
  29.     # инициализация всего важного:
  30.     # алфавита, кодов знаков (путей на дереве, поэтому и paths)
  31.     # и текущего состояния дерева (изначально просто алфавит, n несвязанных элементов)
  32.     alphabet = sorted(list(set(text)), key=text.count)
  33.     paths = {character: "" for character in alphabet}
  34.     current_tree = Tree(alphabet, key=text.count)  # still sorted
  35.     # во-первых, везде две ноды, так что нужно минимум два элемента
  36.     # во-вторых, мне нужна проверка на полную связность дерева,
  37.     # а если оно полностью связно, то длина списка, его представляющего, равна 1
  38.     while len(current_tree) > 1:
  39.         # присвоение среза не сработало (неявно приводит к списку),
  40.         # так что сделал в 3 строки.
  41.         # дерево (линейное пока что) я отсортировал при инициализации, когда оно еще списком было,
  42.         # так что и беру последние 2 элемента
  43.         two_last = current_tree[-2:]
  44.         current_tree = current_tree[:-2]  # removing last two elements
  45.         current_tree.append(Tree(two_last, key=text.count))
  46.         ### ЗАБАГАННАЯ ОБЛАСТЬ
  47.         # прохожусь по тому, что связал и добавляю в пути новый бит
  48.         for index, element in enumerate(current_tree[-1]):
  49.             # если строка, то добавляю прямо на нее
  50.             if not isinstance(element, Tree):
  51.                 paths[element] += str(1-index)
  52.             # если дерево, то прохожусь по концам веток и делаю то же самое
  53.             else:
  54.                 for end in element.ends:
  55.                     paths[end] += str(1-index)
  56.         ### ЗАБАГАННАЯ ОБЛАСТЬ
  57.         # наконец, в конце итерации сортирую по количеству опять
  58.         current_tree.sort(key = lambda x: text.count(x) if isinstance(x, str)
  59.                                                         else x.sum)
  60.     return paths
  61. # изначально нужно было сортировать по вероятности пока она не станет 1,
  62. # но это эквивалентно, ведь количество вхождений пропорционально вероятности,
  63. # а при вероятности 1 дерево будет связным
  64.  
  65.  
  66. if __name__ == "__main__":
  67.     from pprint import pprint
  68.     text = input()
  69.     pprint(generate_paths(text))
  70.    
  71. # анекдот: Буротино утонул, а там русалка на шпагат села
  72.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement