[python] 프로그래머스 쿼드압축 후 개수 세기

Youngseo Lee·2024년 9월 22일

완전탐색

목록 보기
2/3

프로그래머스 쿼드압축 후 개수 세기

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

문제

0과 1로 이루어진 2n x 2n 크기의 2차원 정수 배열 arr이 있습니다. 당신은 이 arr을 쿼드 트리와 같은 방식으로 압축하고자 합니다. 구체적인 방식은 다음과 같습니다.

  1. 당신이 압축하고자 하는 특정 영역을 S라고 정의합니다.
  2. 만약 S 내부에 있는 모든 수가 같은 값이라면, S를 해당 수 하나로 압축시킵니다.
  3. 그렇지 않다면, S를 정확히 4개의 균일한 정사각형 영역(입출력 예를 참고해주시기 바랍니다.)으로 쪼갠 뒤, 각 정사각형 영역에 대해 같은 방식의 압축을 시도합니다.
    arr이 매개변수로 주어집니다. 위와 같은 방식으로 arr을 압축했을 때, 배열에 최종적으로 남는 0의 개수와 1의 개수를 배열에 담아서 return 하도록 solution 함수를 완성해주세요.

풀이

def conquer(temp):
    one = any(1 in row for row in temp)
    zero = any(0 in row for row in temp)
    
    if one == False:
        return 0  # 모두 0으로 이루어짐
    elif zero == False:
        return 1  # 모두 1로 이루어짐
    else: 
        return 2  # 0과 1이 섞여 있음

def divide(arr):
    width = len(arr) // 2
    height = len(arr) // 2

    # 배열을 4개로 나누기
    temp1 = [row[:width] for row in arr[:height]]  # 왼쪽 위
    temp2 = [row[width:] for row in arr[:height]]  # 오른쪽 위
    temp3 = [row[:width] for row in arr[height:]]  # 왼쪽 아래
    temp4 = [row[width:] for row in arr[height:]]  # 오른쪽 아래
    
    # 각 부분을 정복
    result1 = conquer(temp1)
    result2 = conquer(temp2)
    result3 = conquer(temp3)
    result4 = conquer(temp4)
    
    # 각각의 부분 결과를 합산
    answer0, answer1 = 0, 0
    
    if result1 == 1:
        answer1 += 1
    elif result1 == 0:
        answer0 += 1
    else:
        temp_answer0, temp_answer1 = divide(temp1)
        answer0 += temp_answer0
        answer1 += temp_answer1
    
    if result2 == 1:
        answer1 += 1
    elif result2 == 0:
        answer0 += 1
    else:
        temp_answer0, temp_answer1 = divide(temp2)
        answer0 += temp_answer0
        answer1 += temp_answer1
    
    if result3 == 1:
        answer1 += 1
    elif result3 == 0:
        answer0 += 1
    else:
        temp_answer0, temp_answer1 = divide(temp3)
        answer0 += temp_answer0
        answer1 += temp_answer1
    
    if result4 == 1:
        answer1 += 1
    elif result4 == 0:
        answer0 += 1
    else:
        temp_answer0, temp_answer1 = divide(temp4)
        answer0 += temp_answer0
        answer1 += temp_answer1

    return answer0, answer1

def solution(arr):
    one = any(1 in row for row in arr)
    zero = any(0 in row for row in arr)
    
    # 초기 정답
    answer0, answer1 = 0, 0
    
    if one == False:
        # 모든 값이 0인 경우
        return [1, 0]
    elif zero == False:
        # 모든 값이 1인 경우
        return [0, 1]
    else: 
        # 배열을 분할해서 탐색
        answer0, answer1 = divide(arr)
    
    return [answer0, answer1]

📌 주의

else:
temp_answer0, temp_answer1 = divide(temp1)
answer0 += temp_answer0
answer1 += temp_answer1

만일 네모 안에 0 과 1 이 섞여있다면 2를 반환하고 else 문으로 갈텐데, 그러면 그 네모를 다시 4등분할 수 있는 지 확인하기 위해 재귀적으로 부른다.
반환되는 값 temp_answer0는 temp1에서 발견된 0의 개수이고, temp_answer1는 temp1에서 발견된 1의 개수가 된다. 이 값을 누적해서 더해주면 최종적으로 0과 1의 개수를 알 수 있다.
처음에 나는 else: return 을 해버려서 함수가 끝까지 확인하지 않는 그런 코드를 작성해버렸다. 재귀는 어렵다.

그리고 10번 테스트 케이스에서 틀렸었는데 (과거에) [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]] 가 테스트 케이스였다. 따라서 모든 값이 1인 경우엔 하나의 1만 남아서 모든 값이 0 일 경우 혹은 1일 경우를 따로 빼주었다.

profile
leenthepotato

0개의 댓글