This is my solution to exercise 1.6 in Cracking the Coding Interview. I am interested in receiving feedback on the coding style and time/space complexity.
The exercise statement is:
Implement a method to perform basic string compression using the counts of repeated characters. For example, the string aabcccccaaa would become a2b1c5a3. If the compressed string would not become smaller than the original string your method should return the original string. You can assume the string has only uppercase and lowercase letters (a-z).
import unittest
from collections import defaultdict
from math import log10, floor
def compress_string(data: str) -> str:
"""A function to perform basic string compression using the counts of repeated characters
If the compressed string is not smaller than the original string the function returns
the original string. The assumption is that the string has only uppercase and lowercase letters (a-z)."""
curr_char_pos = 0
frequencies = defaultdict(int)
compressed_string = []
compressed_string_size = 0
for idx in range(len(data)):
if compressed_string_size >= len(data):
break
if data[idx] == data[curr_char_pos]:
frequencies[curr_char_pos] += 1
else:
compressed_string.append(data[curr_char_pos])
compressed_string.append(frequencies[curr_char_pos])
compressed_string_size += floor(log10(frequencies[curr_char_pos])) + 2
curr_char_pos = idx
frequencies[curr_char_pos] = 1
compressed_string.append(data[curr_char_pos])
compressed_string.append(frequencies[curr_char_pos])
compressed_string_size += floor(log10(frequencies[curr_char_pos])) + 2
if compressed_string_size < len(data):
compressed_data = ''.join(str(char) for char in compressed_string)
return compressed_data
else:
return data
class MyTest(unittest.TestCase):
def test_compress_string(self):
self.assertEqual(compress_string('aabcccccaaa'), 'a2b1c5a3')
self.assertEqual(compress_string('abcd'), 'abcd')
self.assertEqual(compress_string('tTTttaAbBBBccDd'), 'tTTttaAbBBBccDd')