Algorithm/Programmers

[programmers lv2.python] 이진 변환 반복하기 풀이 (리팩토링 다..수..)

쉬지마 이굥진 2024. 4. 29. 11:16

https://school.programmers.co.kr/learn/courses/30/lessons/70129

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

문제

 

1차 풀이 (리팩토링 전) 👉 정답

def solution(s):
    count_zero = 0
    count_binary = 0
    
    while s != '1':
        # 0의 갯수 카운트하고 s의 모든 0 제거
        count_zero += s.count('0')
        s = s.replace('0', '')
         
        # s를 s의 길이(c)를 2진법으로 표현한 문자열로 바꾸기
        c = len(s)
        binary_str = ''
    
        # 정수를 2로 나눠가면서 나머지를 구하고 이를 역순으로 연결
        while c > 0:
            binary_str += str(c % 2)
            c //= 2
            
        s = binary_str[::-1]
        count_binary += 1
    
    return [count_binary, count_zero]

 

분명 정수 → 이진법으로 바꿔주는 함수가 있을 거라고 생각했는데, 일단은 구글링 안 해 보고 for 문으로 구현했다.

 

  1. 0을 제거해주기 위해서 일단 문자열 s의 갯수를 먼저 세 주고, replace() 로 0을 공백으로 대체해줬다.
  2. 그 이후 s의 길이(c)를 2로 나눈 나머지를 binary_str에 추가해줬다. (나머지는 항상 0 혹은 1이 된다) 그 다음 c를 2로 나눈 몫으로 갱신한 후 , 이진수 변환 과정에서 얻는 이진수의 자릿수를 정확한 위치에 맞춰주기 위해서 이진수 문자열을 거꾸로 뒤집어 반환한다.
  3. 이진수 변환 횟수(count_binary)를 + 1 갱신해준다.

하지만 코드 통과가 되는걸 보고 난 후에, 정수를 이진수로 바꾸는 부분을 메서드로 빼면 좋을 것 같아서 리팩토링 과정을 추가로 진행했다.

 

2차 풀이 (리팩토링 후)

def solution(s):
    count_zero = 0
    count_binary = 0
    
    while s != '1':
        # 0의 갯수 카운트하고 s의 모든 0 제거
        count_zero += s.count('0')
        s = s.replace('0', '')
         
        # s를 s의 길이를 2진법으로 표현한 문자열로 바꾸기
        s = convert_to_binary(len(s))
    
        count_binary += 1
    
    return [count_binary, count_zero]

def convert_to_binary(n):
    binary_str = ''
    while n > 0:
        binary_str += str(n % 2)
        n //= 2
    return binary_str[::-1]

 

1차 풀이에서 이진수로 바꾸는 부분을 convert_to_binary 메서드로 빼 줬다.

 

리팩토링 까지 해보고 나니 아까 놓쳤던, 정수를 이진수로 바꿔주는 내장 함수가 있는지 찾아봤다. 출처

찾아보니 있구만 !!!!!

 

당장 적용해보자 !!!!!!!!!!1

 

3차 풀이 (내장 함수 적용)

파이썬에서 10진수를 2진수로 변환해주는내장 함수는 bin() 이다.

주의할 점은 이 함수는 결과적으로 문자열 앞에 'Ob' 를 붙여서 변환하기 때문에 이 문자를 제거해주는 작업이 필요하다.

나는 슬라이싱을 사용해서 제거했다.

def solution(s):
    count_zero = 0
    count_binary = 0
    
    while s != '1':
        # 0의 갯수 카운트하고 s의 모든 0 제거
        count_zero += s.count('0')
        s = s.replace('0', '')
         
        # s를 s의 길이를 2진법으로 표현한 문자열로 바꾸기
        s = convert_to_binary(len(s))
    
        count_binary += 1
    
    return [count_binary, count_zero]

def convert_to_binary(n):
    return str(bin(n)[2:])

 

2차 풀이보다 훨씬 깔끔해보인다 ㅎ

 

4차 풀이 (숏코딩)

줄일 수 있는 부분은 줄여서 간결하게도 만들어 봤다.

def solution(s):
    count_zero = 0
    count_binary = 0
    
    while s != '1':
        count_zero += s.count('0') # 0의 개수 카운트
        s = bin(len(s.replace('0', '')))[2:] # '0'을 모두 제거하고 나머지 길이 2진법으로 변환
        count_binary += 1
    
    return [count_binary, count_zero]

 

가독성은 조금 떨어지지만 숏코딩 재밌잖아요 .. 🥹

 


마치며

결론은 1차나 2차나 3차나 시간 복잡도는 똑같지만 가독성은 내장 함수 적용한 부분이 훨씬 좋은 것 같다. (또, 가능하면 존재하는 라이브러리를 재사용 하는 게 좋다고 한다)

 

리팩토링 할 만한 부분이 있어서 특정 부분을 메서드로 빼 주는 과정을 거치면서 느낀 점이 많았고, bin() 내장함수 절대 안 까먹을 것 같다 ..ㅋㅋㅋ 히 

thanks to 지훈