코테 리팩토링) 문자열 압축

EBAB!·2024년 5월 15일
0
post-custom-banner

목표

  • 기존에 문제를 푸는데만 집중해서 풀었던 문제들을 클린 코드, 객체 지향 방식으로 리팩토링
  • 완벽한 효율보다는 다양한 스타일로 작성

문제

코테 문제) https://school.programmers.co.kr/learn/courses/30/lessons/60057

압축할 문자열 s가 매개변수로 주어질 때, 위에 설명한 방법으로 1개 이상 단위로 문자열을 잘라 압축하여 표현한 문자열 중 가장 짧은 것의 길이를 return 하도록 solution 함수를 완성해주세요.

제한사항

  • s의 길이는 1 이상 1,000 이하입니다.
  • s는 알파벳 소문자로만 이루어져 있습니다.




기존 코드

def solution(s):
    l = len(s)
    if l==1:
        return 1
    answer = []
    
    for n in range(1,(l//2)+1):
        ss = ''
        cnt = 1
        for i in range(0,l,n):

            if s[i:i+n] == s[i+n:i+2*n]:
                cnt+=1
                
            else:
                if cnt==1:
                    ss+=s[i:i+n]
                else:
                    ss+=(str(cnt)+s[i-n:i])
                    cnt=1
        answer.append(len(ss))
        
    return min(answer)


수정코드

class StringCompressor:
    def __init__(self, string):
        self.string: str = string
        self.__best_compressed: str | None = None
    
    def _compress_with_slice_size(self, slice_size: int) -> str:
        compressed: list[str] = []
        count: int = 1
        
        for i in range(0, len(self.string), slice_size):
            current_slice: str = self.string[i:i + slice_size]
            next_slice: str = self.string[i + slice_size:i + 2 * slice_size]
            
            if current_slice == next_slice:
                count += 1
            elif count > 1:
                compressed.append(f"{count}{current_slice}")
                count = 1
            else:
                compressed.append(current_slice)

        return ''.join(compressed)
    
    def _find_best_compression(self) -> str:
        if len(self.string) == 1:
            return self.string
        
        best_compressed = self.string
        max_slice_size = len(self.string) // 2
        
        for slice_size in range(1, max_slice_size + 1):
            compressed = self._compress_with_slice_size(slice_size)
            if len(compressed) < len(best_compressed):
                best_compressed = compressed

        return best_compressed
    
    @property
    def best_compressed(self) -> str:
        if not self.__best_compressed:
            self.__best_compressed = self._find_best_compression()
        
        return self.__best_compressed

    
def solution(s:str) -> int:
    compressor = StringCompressor(s)

    return len(compressor.best_compressed)

개선점

  • PEP8 가이드라인에 따라 작성된 코드

  • 타입 힌트 추가

  • 객체 지향적 설계를 통해 코드의 재사용성과 유지보수성 증가

    • StringCompressor 객체를 통해 문자열 압축에 관한 역할 부여
  • 메서드 분리와 프로퍼티 사용으로 코드의 모듈성을 높이고 가독성을 개선

    • 맹글링을 통해 내부 사용과 프라이빗 변수에 대해 표현
    • 지연 계산으로 효율적인 동작 구현
  • 리스트를 통한 문자열 조작으로 효율성을 향상.

    • 기존의 코드에서 사용한 문자열 += 문자열 방식에서 리스트에 문자열을 저장하는 방식으로 변경

      문자열은 불변 객체

      파이썬에서 문자열은 불변 객체이므로 새로운 문자열을 더할 때마다 새로운 객체를 생성하는 방식이 적용됩니다.
      따라서 문자열이 계속해서 더해지는 상황에서는 차라리 리스트에 문자열을 담고 마지막에 하나의 문자열을 생성하는 것이 더 효율적인 방식이 될 수 있습니다.

  • 명확한 변수 및 메서드 명명과 중복 코드 제거를 통해 가독성과 명확성 향상.

profile
공부!
post-custom-banner

0개의 댓글