본문 바로가기

알고리즘

[프로그래머스] 이진 변환 반복하기 [월간 코드 챌린지 시즌1]

반응형

programmers.co.kr/learn/courses/30/lessons/70129

 

코딩테스트 연습 - 이진 변환 반복하기

 

programmers.co.kr

0과 1로 이루어진 어떤 문자열 x에 대한 이진 변환을 다음과 같이 정의합니다.

  1.     x의 모든 0을 제거합니다.
  2.     x의 길이를 c라고 하면, x를 "c를 2진법으로 표현한 문자열"로 바꿉니다.

예를 들어, x = "0111010"이라면, x에 이진 변환을 가하면 x = "0111010" -> "1111" -> "100" 이 됩니다.

0과 1로 이루어진 문자열 s가 매개변수로 주어집니다. s가 "1"이 될 때까지 계속해서 s에 이진 변환을 가했을 때, 이진 변환의 횟수와 변환 과정에서 제거된 모든 0의 개수를 각각 배열에 담아 return 하도록 solution 함수를 완성해주세요.


제한사항

  •     s의 길이는 1 이상 150,000 이하입니다.
  •     s에는 '1'이 최소 하나 이상 포함되어 있습니다.

입출력 예

s result
"110010101001" [3,8]
"01110" [3,3]
"1111111" [4,1]

입출력 예 설명

입출력 예 #1

  • "110010101001"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 이진 변환 이전 제거할 0의 개수 0 제거 후 길이 이진 변환 결과
1 "110010101001" 6 6 "110"
2 "110" 1 2 "10"
3 "10" 1 1 "1"
  • 3번의 이진 변환을 하는 동안 8개의 0을 제거했으므로, [3,8]을 return 해야 합니다.

입출력 예 #2

  • "01110"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 이진 변환 이전 제거할 0의 개수 0 제거 후 길이 이진 변환 결과
1 "01110" 2 3 "11"
2 "11" 0 2 "10"
3 "10" 1 1 "1"
  • 3번의 이진 변환을 하는 동안 3개의 0을 제거했으므로, [3,3]을 return 해야 합니다.

입출력 예 #3

  • "1111111"이 "1"이 될 때까지 이진 변환을 가하는 과정은 다음과 같습니다.
회차 이진 변환 이전 제거할 0의 개수 0 제거 후 길이 이진 변환 결과
1 "1111111" 0 7 "111"
2 "111" 0 3 "11"
3 "11" 0 2 "10"
4 "10" 1 1 "1"
  • 4번의 이진 변환을 하는 동안 1개의 0을 제거했으므로, [4,1]을 return 해야 합니다.

풀이

문제가 요구하는 순서대로 구현하면 해결되는 문제입니다. 먼저, s의 문자 중 0을 제거하기 위해 s를 순회하여 0인 경우를 제외하여 리스트를 구성합니다.

tmp = []
for x in s:
  if x != '0':
    tmp.append(x)
        
c = len(tmp)

다음과 같이 파이썬의 List Comprehension을 이용하여 짧게 구현할 수도 있습니다.

tmp = [x for x in s if x != '0']
c = len(tmp)

이제 c를 2진법으로 표현한 문자열을 만들어봅시다. 사실 문제의 경우 문자열이나 리스트나 크게 상관이 없어 리스트로 생성하였습니다. 어떤 10진수를 2진법으로 변환하는 방법은 간단합니다. 10진수를 몫이 1 이상인 동안 2로 계속 나누어 나머지를 리스트에 역순으로 넣어주면 됩니다. 이를 파이썬 코드로 나타내면 다음과 같습니다.

s = []
while c:
  s.insert(-1, str(c % 2))
  c //= 2

이진 변환을 실시할 때마다 횟수에 1을 더해주고, s의 길이에서 len(tmp)만큼 뺀 값이 제거한 0의 갯수가 됩니다. 결과적으로 코드는 다음과 같아집니다.

def solution(s):
    s = list(s)
    answer = [0, 0]
    while s != ['1']:
        c = len([x for x in s if x != '0'])
        answer[0] += 1
        answer[1] += len(s) - c
        
        s = []
        while c:
            s.insert(-1, str(c % 2))
            c //= 2
        
    return answer
반응형