|
| 1 | +""" |
| 2 | +Python version 3.7.0 |
| 3 | +1.6 - String Compression |
| 4 | +Implement a method to perform basic string compression using the counts |
| 5 | +of repeated characters. For example, the string aabcccccaaa would become a2b1c5a3. |
| 6 | +If the "compressed" string would not become smaller than the original string, your method |
| 7 | +should return the original string. You can assume the string has only uppercase and lowercase |
| 8 | +letters (a-z). |
| 9 | +""" |
| 10 | +import unittest |
| 11 | + |
| 12 | + |
| 13 | +def str_compression(s: str) -> str: |
| 14 | + """ |
| 15 | + String compression will attempt to reduce the size of s by condensing |
| 16 | + s using the counts of repeated characters. |
| 17 | + Runtime: O(n), asymptotic runtime depends on size of s |
| 18 | + Space Complexity: O(n), compressed list |
| 19 | + :param s: the string we want to compress |
| 20 | + :return: the compressed string or s if the compressed string is not smaller |
| 21 | + """ |
| 22 | + if len(s) == 0: |
| 23 | + return s |
| 24 | + compressed = [] |
| 25 | + prev_char = s[0] |
| 26 | + count = 1 |
| 27 | + for c in s[1:]: |
| 28 | + if c == prev_char: |
| 29 | + count += 1 |
| 30 | + continue |
| 31 | + compressed.append(f'{prev_char}{count}') |
| 32 | + prev_char = c |
| 33 | + count = 1 |
| 34 | + # clean up: last character count |
| 35 | + compressed.append(f'{prev_char}{count}') |
| 36 | + compressed = ''.join(compressed) |
| 37 | + if len(compressed) >= len(s): |
| 38 | + return s |
| 39 | + return compressed |
| 40 | + |
| 41 | + |
| 42 | +class TestStringCompressionFunction(unittest.TestCase): |
| 43 | + def test_string_compression(self): |
| 44 | + cases = [ |
| 45 | + ('aabcccccaaa', 'a2b1c5a3'), |
| 46 | + ('abcde', 'abcde'), |
| 47 | + ('aabbccdd', 'aabbccdd'), |
| 48 | + ('', ''), |
| 49 | + ('c', 'c'), |
| 50 | + ('aaAAccCCCCC', 'a2A2c2C5'), |
| 51 | + ('aaaaaaaaaa', 'a10') |
| 52 | + ] |
| 53 | + for s, expected in cases: |
| 54 | + self.assertEqual(str_compression(s), expected, msg=(s, expected)) |
| 55 | + |
| 56 | + |
| 57 | +if __name__ == '__main__': |
| 58 | + unittest.main() |
0 commit comments