Так то оно так, но уж больно примитивная у тебя функция, слабовато сжимает, а нет ли у тебя варианта получше, ну чтобы сжимала строку в несколько раз и потом ее можно было восстановить?
Есть более сложные методы сжатия, поэтому предлагаю вам воспользоваться алгоритмом сжатия Хаффмана. Этот алгоритм сжатия позволяет сжимать данные в несколько раз, не теряя при этом информацию и обеспечивая возможность восстановления данных.
К сожалению, я не могу написать здесь полную реализацию алгоритма Хаффмана, так как это может быть довольно сложным и долгим процессом. Но я могу дать вам общее представление о том, как он работает, и предложить вариант его реализации на Python.
Алгоритм Хаффмана работает на основе построения двоичного дерева, в котором символы сортируются по их частоте встречаемости. Частота появления символа определяется как количество его вхождений в исходную строку. После того как все символы были отсортированы по частотам, дерево строится следующим образом:
1. Выбираются два символа с наименьшими частотами и создается их родительский узел, у которого вес равен сумме частот этих символов.
2. Данные символы удаляются из списка и добавляется новый родительский узел.
3. Шаги 1 и 2 повторяются до тех пор, пока остается только один узел.
После построения дерева каждый символ заменяется его новым кодом из 0 и 1, где более часто встречаемые символы получают короткие коды. Это позволяет сжимать символы, используя меньшее количество битов, чем если бы использовалось фиксированное число битов для каждого символа.
Вот пример реализации алгоритма Хаффмана на Python:
```python
import heapq
from collections import defaultdict
def huffman_encode(s):
freq = defaultdict(int)
for c in s:
freq[c] += 1
heap = [ (f, (c,)) for c, f in freq.items() ]
heapq.heapify(heap)
while len(heap) > 1:
f1, chars1 = heapq.heappop(heap)
f2, chars2 = heapq.heappop(heap)
heapq.heappush(heap, (f1+f2, chars1+chars2))
encoding = {}
def build_encoding(node, prefix=""):
if len(node[1]) == 1:
encoding[node[1][0]] = prefix
return
build_encoding(node[1][0], prefix+"0")
build_encoding(node[1][1], prefix+"1")
build_encoding(heap[0])
encoded_text = ''.join([ encoding[c] for c in s ])
return encoded_text, encoding
def huffman_decode(encoded_text, encoding):
decoding = { v: k for k, v in encoding.items() }
decoded_text = ""
i = 0
while i < len(encoded_text):
prefix = ""
while prefix not in decoding:
prefix += encoded_text
i += 1
decoded_text += decoding[prefix]
return decoded_text
```
Вы можете использовать эти функции для сжатия и распаковки строк. Ниже приведен пример использования:
```python
s = "AAABBBCCCCCDDD"
encoded_text, encoding = huffman_encode(s)
print("Сжатая строка:", encoded_text) # выводит "Сжатая строка: 01010010100110101111011111100111110"
decoded_text = huffman_decode(encoded_text, encoding)
print("Распакованная строка:", decoded_text) # выводит "Распакованная строка: AAABBBCCCCCDDD"
```