[Java] 2018 Kakao Blind Recruitment [1차] 비밀지도

Eunbi Lee·2024년 1월 21일
0

Algorithm

목록 보기
5/7

비밀지도

문제 설명

  • 지도는 한 변의 길이가 n인 정사각형 배열 형태이다.
    - 각 칸은 공백("") 또는 벽("#") 두 종류로 이루어져 있다.
  • 전체 지도는 두 장의 지돌르 겹쳐서 얻을 수 있다.
    - 이때, 두 장의 지도는 각각 지도 1과 지도 2라고 하자.
  • 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다.
    - 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
  • 지도 1과 지도 2는 각각 정수 배열로 암호화되어 있다.
    - 암호화된 배열은 지도의 각 가로 줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.
  • 지도 1과 2, 그리고 전체 지도는 다음과 같다.

입력 형식

  • 입력으로 지도의 한 번 크기 n과 2개의 정수 배열 arr1, arr2가 들어온다.
  • 1 <= n <= 16
  • arr1, arr2는 길이 n인 정수 배열로 주어진다.
  • 정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n이하이다.

출력 형식

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

입출력 예제

n : 5,
arr1 : [9, 20, 28, 18, 11]
arr2 : [30, 1, 21, 17, 28]
출력 : ["#####", "# # #", "### #", "# ##", "######"]

n : 6,
arr1 : [46, 33, 33, 22, 31, 50]
arr2 : [27, 56, 19, 14, 14, 10]

풀이

처음에는 다음과 같이 풀이 방향을 정했다.

  1. 지도1, 2에 대한 문자열 배열을 이진수 배열로 변환한다.
  2. 1은 #, 0은 ""(공백)으로 바꾼다.
  3. 1과 0을 비교하여 각 배열의 원소의 문자에 대해 값이 다르거나 1로서 똑같다면 #으로 원소를 치환한다.

그런데, 다음과 같은 문제들을 마주했다.

  1. 문자열 배열의 원소 하나 - 문자열에 대해 어떻게 2진수로 바꿀 수 있을까?
  2. 예를 들어, n = 5일 경우 "01000"이 아닌 "1000"일 경우 어떻게 자릿수를 맞춰줘야 할까?
  • ex. 16 = 2^5 0 + 2^4 + 2^3 0 + ... + 2^0 * 0
  1. 문자열 배열의 원소인 문자열에 대해 문자 하나를 어떻게 대치시켜줄까?

해결 방법은 다음과 같았다.

  1. Integer.toBinaryString() : 문자열 -> 2진수 배열
  2. if (2진수 배열.length() != n) -> += "0"
  3. StringBuilder -> if (2진수 배열[idx].charAt(idx) != 또 다른 2진수 배열[idx].charAt(idx) || .. == 1 && .. == 1)

하지만, 이때 2와 3의 문제 풀이에 문제가 있다는 것을 디버깅을 통해 알게 되었다. (디버그를 생활화 하자 ㅠ.ㅠ)

  1. n = 5일 경우, 16이라는 값에 대해서는 2의 4승 값을 제외한 2의 0승, 1승, 2승, 3승, 5승은 필요하지 않으므로 0이라는 값이 필요하다. 따라서 "1000"이 아닌 "01000"이어야 한다.
    그런데, 이때 아무 생각 없이 문자열의 맨 뒤에 "0"을 붙여버리는 참사를 일으켰었다.

따라서 다음과 같이 수정하였다.

String.format("%" + n + "s", 2진수배열[idx]).replace(' ', '0');

  • 즉, s라는 이어지는 문자열에 대해 n만큼의 width를 가지는 포맷(형식)을 정해주겠다는 뜻이다.
  • 그리고 .replace()는 첫 번째 인자를 두 번째 인자로 변경해주겠다는 뜻이다.

다음으로 3.은 이렇게 해결했다.

  1. 생각해보니, 문자열 내에서 각각의 문자 자체가 중요한 것이 아니라 하나의 문자열 내에 1라는 문자가 섞여있다면 무조건 #으로 표현될 것이므로..
    (1) 정사각형 배열의 한 행을 문자열 배열이 아닌 문자열로 취급하여 .equals('1')을 통해 치환한다.
    (2) .charAt()를 통해 하나씩 읽어올 때, 지도 1의 2진수 배열과 지도 2의 2진수 배열의 각 문자가 모두 0일 경우, StringBuilder에 추가한다.(기댓값과 실행 결과가 자꾸 다르게 나오는 것으로 보아 추가 조건을 찾아야 하는 것 같으므로 뒤집어서 생각했다)

나는 (2)로 풀었고, 무사히 답을 얻을 수 있었다.

전체 코드

import java.util.*;

class Solution {
    public String[] solution(int n, int[] arr1, int[] arr2) {
        String[] answer = new String[n];
        String[] binaryArr1 = new String[n];
        String[] binaryArr2 = new String[n];
        
        int length = arr1.length;
        for (int i = 0; i < length; i ++) {
            binaryArr1[i] = Integer.toBinaryString(arr1[i]);
            binaryArr2[i] = Integer.toBinaryString(arr2[i]);
        }
        
        for (int i = 0; i < length; i ++) {
        	if (binaryArr1[i].length() != n) {
                binaryArr1[i] = String.format("%" + n + "s", binaryArr1[i]).replace(' ', '0');
            }
            if (binaryArr2[i].length() != n) {
                binaryArr2[i] = String.format("%" + n + "s", binaryArr2[i]).replace(' ', '0');
            }
        }
        
         for (int i = 0; i < length; i ++) {
              StringBuilder sb = new StringBuilder();
              
              for (int j = 0; j < length; j ++) {
                if (binaryArr1[i].charAt(j) == '0' && binaryArr2[i].charAt(j) == '0') {
                    sb.append(' ');
                } else {
                    sb.append('#');
                }
            }
            
            answer[i] = sb.toString();
            sb.setLength(0);
        }
        
        return answer;
    }
}

후기

한 3~4개월 전 마주했을 때는 너무 어려워서 안 풀고 넘어갔던 문제인데, 이번에는 그래도 도전할 엄두가 나서 다행이었다.

그래도 오랜만에 프로그래머스의 문제를 풀다보니..

  • 자바 기본 메서드를 많이 까먹었었다. 특히, Integer.toBinaryString()과 같은 메서드는 생소할지라도 이런 문제에서는 꼭 필요한 메서드니 알아야할 것 같다.
  • 백준으로 풀 때는 인텔리제이를 자주 이용했었는데, 그래서 그런지 나도 모르게 자동 완성에 많이 익숙해져있었던 것 같았다. import java.util"s". *;이라고 친다던지..?
  • 디버그를 좀 더 생활화해야겠다. 예를 들어 ..
int length = arr1.length;
        for (int i = 0; i < length; i ++) {
            binaryArr1[i] = Integer.toBinaryString(arr1[i]);
            binaryArr2[i] = Integer.toBinaryString(arr2[i]);
        }

이후에 바로 1 -> #, 0 -> ""으로 치환하는 작업이 아니라 print()를 통해서 값이 잘 받아와졌는지부터 확인한다던지?

또는

binaryArr1[i] = String.format("%" + n + "s", binaryArr1[i]).replace(' ', '0');

이 아니라

binaryArr1[i] = String.format("%" + n + "s", binaryArr1[i])

까지 진행해서 print() 해본 후,.replace(' ', '0');을 진행한다던지?


이제 이력서도 쓰고, 자소서도 쓰다보니 채용 절차의 첫 관문인 코테의 중요성에 대해 더더욱 실감하고 있다.

감시 스터디를 같이 진행하며 위 풀이의 문제 해결에 도움을 준 진혁님에게 감사함을 표하며 이번 주 포스팅은 여기서 끝!

profile
B - B = 이은비

0개의 댓글