본문 바로가기

Algorithm & SQL/Programmers

[Programmers] [Python] 비밀지도

비밀지도

2018 KAKAO BLIND RECRUITMENT


문제 설명


비밀지도

네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.

  1. 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 공백(" ) 또는벽(#") 두 종류로 이루어져 있다.

  2. 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 지도 1과 지도 2라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.

  3. 지도 1과 지도 2는 각각 정수 배열로 암호화되어 있다.

  4. 암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.

image

입력 형식


입력으로 지도의 한 변 크기 n 과 2개의 정수 배열 arr1, arr2가 들어온다.

  • 1 ≦ n ≦ 16
  • arr1, arr2는 길이 n인 정수 배열로 주어진다.
  • 정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n 이하이다. 즉, 0 ≦ x ≦ 2n - 1을 만족한다.

출력 형식


원래의 비밀지도를 해독하여 '#', 공백으로 구성된 문자열 배열로 출력하라.

1차제출 코드


def solution(n, arr1, arr2):
   answer = []
   for num1, num2 in zip(arr1, arr2):
       tmp = str(bin(num1 | num2))[2:]
       tmp = tmp.replace('1', '#')
       tmp = tmp.replace('0', ' ')
       answer.append(tmp)
   return answer

1차로 제출한 코드는 위와 같다.

지도1과 지도2의 겹치는 원소를 가져와 bitwise연산을 진행해야 했기 때문에 zip을 이용하여 원소를 뽑아내고 tmp 변수에 num1값 과 num2값의 bitwise연산 결과를 저장한 뒤 가공하였다.

1번 테스트케이스는 통과하였으나 2번 테스트케이스를 통과하지 못하였다.

원인이 무엇일까 곰곰히 생각해봤는데 n이 6인 경우, answer원소들의 길이가 6이여야 하는 예외를 처리해주지 못했다.

제출코드


def solution(n, arr1, arr2):
   answer = []
   for num1, num2 in zip(arr1, arr2):
       tmp = bin(num1 | num2)[2:]
       if len(tmp) < n:
           tmp = '0'*(n-len(tmp)) + tmp
       tmp = tmp.replace('1', '#')
       tmp = tmp.replace('0', ' ')
       answer.append(tmp)
   return answer

코드설명


*Line 3~4 : *zip을 이용하여 arr1arr2에서 같은 위치의 원소를 뽑아오며 순회한다.

Line 5~6 : 1차제출 코드에서 놓쳤던 부분이다. 출력값 포맷을 위해 n의 길이에 맞춰서 binary 수를 가져왔어야 했다. 만일 bitwise 연산 결과인 tmp의 길이가 n보다 작을 경우 부족한 만큼 앞에 0을 붙여준다.

Line 7~9 : string 내장 메서드 replace를 이용하여 1#으로, 0' '공백으로 치환시켜준뒤 answerappend 한다.

다른 사람의 풀이


def solution(n, arr1, arr2):
   answer = []
   for i,j in zip(arr1, arr2):
       a12 = str(bin(i|j)[2:])
       a12 = a12.rjust(n, '0')
       a12 = a12.replace('1', '#')
       a12 = a12.replace('0', ' ')
       answer.append(a12)
      return answer

전반적으로 나의 풀이와 매우 유사하다.

필자는 if문을 이용해 길이가 n보다 작을 경우, 0을 붙여주었는데 이 분 께서는 string의 내장 메서드

rjust를 이용하여 0을 붙여주셨다.

굳굳...!!

배운 점


문자열 정렬 - ljust, center, rjust

s = '가나다라'
n = 7

s.ljust(n)        # 좌측 정렬
s.center(n)        # 가운데 정렬
s.rjust(n)        # 우측 정렬

01. 문자열 정렬 함수 응용

ljust, rjust와 같은 측 정렬 진행시, [fillchar] 인자를 넣어줌으로써 원하는 문자로 비는 부분을 채울 수 있다.

# rjust(width, [fillchar])

"2".rjust(3, "0")
# "002"

"123".ljust(5, "1")
# "12311"

02. zfill(width) 함수 사용

오직 문자열 앞에만 0을 덧붙힐 수 있는 기능이다.

zero(0)으로 fill 채운다 해서 zfill이라고 명명한 것 같은 추측을 조심스레 해본다..

이번 문제에서 사용했더라면 매우 유용했을 함수이다.

# zfill(width)

"2".zfill(3)
# "002"

"123".zfill(8)
# "00000123"