프로그래머스 1단계인 비밀지도 문제를 풀다가 발생한 Exception이다. Exception 들은 알면 알수록 나중에 대처가 빨라질테니 모르는 Exception들을 그 때 그 때 정리해서 포스팅하려고 한다.
다음은 문제의 코드이다.
// [1차] 비밀지도
class Prob35 { // 2점
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
char[][] totalMap = new char[n][n];
for (int i = 0; i < n; i++) {
String binary1 = String.format("%0" + n + "s", Integer.toBinaryString(arr1[i]));
String binary2 = String.format("%0" + n + "s", Integer.toBinaryString(arr2[i]));
for (int j = 0; j < n; j++) {
boolean wall1 = (binary1.charAt(j) + "").equals("1");
boolean wall2 = (binary2.charAt(j) + "").equals("1");
totalMap[i][j] = (wall1 || wall2) ? '#' : ' ';
}
}
for (int i = 0; i < n; i++) {
answer[i] = String.valueOf(totalMap[i]);
}
return answer;
}
}
코드 내에 String.format 함수를 사용해서 2진수 문자열을 총 n의 자리만큼 만들어서 변수에 저장하는 코드가 있다.
String binary1 = String.format("%0" + n + "s", Integer.toBinaryString(arr1[i]));
여기서 FormatFlagsConversionMismatchException이 났다.
먼저 Exception의 의미부터 추측을 해보자. Flag? Flag가 뭔지는 아직 모르겠지만 Format 함수를 사용해서 conversion(변환)을 하다가 mismatch가 되어 Exception이 난 거라고 추측해볼 수가 있다. 일단 대충은 파악했으니 Flag에 대해 알아봐야 더 정확하게 알 것 같다.
구글링을 통해 명쾌한 답변을 준 블로그를 찾게 되었다.
(https://blog.devez.net/ko/100)
Flag란 format의 형식인 %d, %s 등의 사이에 문자열을 변환시켜주기 위해 사용하는 코드이다. Flag라는 표현만 모르고 있었지 Flag 개념 자체는 이미 공부해서 알고 있었다.
Flag까지 알게 되었으니 그렇다면 왜 Exception이 난 걸까?
내가 format을 이용해서 String에 저장하고 싶었던 것은 binary형태의 문자열이였다. 그러므로 문자열을 받아주는 %s를 사용해였다. 거기에 Flag로 0n을 사용하여 문자열의 총길이가 n이 되게끔 하고 싶었다. 하지만 0 flag는 실수, 정수 타입에는 사용이 가능하지만 문자열에는 사용이 불가능해서 FormatFlagsConversionMismatchException이 발생한 것이다.
그럼 어떻게 해야 문자열의 길이를 n개로 저장할 수 있을까? 위에서 정수 타입은 0 flag를 사용할 수 있다고 했으므로 binary문자열을 parseInt를 사용해서 10진수 정수 타입으로 바꾼 후, %d에 0 flag를 사용하면 되지 않을까? 역시나 정상적으로 실행이 되었다.
String binary1 = String.format("%0" + n + "d", Integer.parseInt(Integer.toBinaryString(arr1[i]))));
Exception을 잘 해결했음에도 불구하고 몇몇 테스트 케이스에서 런타임 에러가 났다. 거의 대부분 맞았으므로 알고리즘 상의 문제는 아닐 것 같다는 생각을 했다. 그렇다면 뭐가 문제일까? 문제의 답은 문제에 있었다. 비밀지도 문제를 다시 읽어 보았는데 놓친 부분이 있었다. binary 문자열로 변환되기 전 10진수 데이터의 크기가 2의 16제곱 정도의 크기였다. int 타입의 MAX_VALUE 가 어림잡아 20억인데 2의 16제곱을 계산 안해봐도 훌쩍 넘을 것 같았다. 따라서 Long타입으로 바꿔줌으로서 해결이 되었다.
String binary1 = String.format("%0" + n + "d", Long.parseLong(Integer.toBinaryString(arr1[i])));