출처: https://school.programmers.co.kr/learn/courses/30/lessons/17681
문제 설명
비밀지도
네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.
지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.
전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"라고 하자. 지도 1 또는 지도 2 중 어느 하나라도 벽인 부분은 전체 지도에서도 벽이다. 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
"지도 1"과 "지도 2"는 각각 정수 배열로 암호화되어 있다.
암호화된 배열은 지도의 각 가로줄에서 벽 부분을 1, 공백 부분을 0으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.
secret map
네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.
입력 형식
입력으로 지도의 한 변 크기 n 과 2개의 정수 배열 arr1, arr2가 들어온다.
1 ≦ n ≦ 16
arr1, arr2는 길이 n인 정수 배열로 주어진다.
정수 배열의 각 원소 x를 이진수로 변환했을 때의 길이는 n 이하이다. 즉, 0 ≦ x ≦ 2n - 1을 만족한다.
출력 형식
원래의 비밀지도를 해독하여 '#', 공백으로 구성된 문자열 배열로 출력하라.
입출력 예제
매개변수 값
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]
출력 ["######", "### #", "## ##", " #### ", " #####", "### # "]
해설 보러가기
내가 작성한 코드문
import java.util.*;
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
// 지도는 한 변의 길이가 n인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류
// 전체 지도는 두 장의 지도를 겹쳐서 얻을 수 있다. 각각 "지도 1"과 "지도 2"
// 지도 1과 지도 2에서 모두 공백인 부분은 전체 지도에서도 공백이다.
// "지도 1"과 "지도 2"는 각각 정수 배열로 암호화
// 가로줄에서 벽 부분을 1, 공백 부분을 0
StringBuilder finalResult1 = new StringBuilder();
for(int i = 0; i < arr1.length; i++){
// 각 배열 원소를 이진법 화 해라
String binary1 = Integer.toBinaryString(arr1[i]);// 2진법 화
StringBuilder result1 = new StringBuilder(binary1);
for(int j = 0; j < binary1.length(); j++){
if(result1.charAt(j) == '1'){// 1일떄 #
result1.setCharAt(j, '#');
} else if(result1.charAt(j) == '0'){// 0일때 ' '
result1.setCharAt(j, ' ');
}
}
finalResult1.append(result1.toString()).append("\n");
}
StringBuilder finalResult2 = new StringBuilder();
for(int i = 0; i < arr2.length; i++){
String binary2 = Integer.toBinaryString(arr2[i]);
StringBuilder result2 = new StringBuilder(binary2);
for(int j = 0; j < binary2.length(); j++){
char ch2 = binary2.charAt(j);
if(result2.charAt(j) == '1'){// 1일떄 #
result2.setCharAt(j, '#');
} else if(ch2 == '0'){// 0일때 ' '
result2.setCharAt(j, ' ');
}
}
finalResult2.append(result2.toString()).append("\n");
}
for(int i = 0; i < finalResult1.length(); i++){
if(finalResult1.charAt(i) == '#'){
if(finalResult2.charAt(i) == '#'){
answer[i] = '#' + "";
} else {
answer[i] = '#' + "";
}
} else if(finalResult1.charAt(i) == ' '){
if(finalResult2.charAt(i) == '#'){
answer[i] = '#' + "";
} else {
answer[i] = ' ' + "";
}
}
}
return answer;
}
}
✅ 수정 포인트
StringBuilder로 전체 문자열(finalResult1, finalResult2)을 연결하고 비교하는 방식 → 줄 단위 배열로 변경
줄바꿈 문자 \n을 제거
answer[i]에 접근할 때 i는 0 ~ n-1까지만 접근해야 하므로, 줄 단위로 루프
요구사항 충족하는 코드문
import java.util.*;
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
String[] result1 = new String[n];
String[] result2 = new String[n];
for (int i = 0; i < n; i++) {
String binary1 = Integer.toBinaryString(arr1[i]);
// 왼쪽에 0을 붙여서 길이를 n으로 맞춤
while (binary1.length() < n) {
binary1 = "0" + binary1;
}
StringBuilder sb1 = new StringBuilder();
for (int j = 0; j < n; j++) {
if (binary1.charAt(j) == '1') {
sb1.append('#');
} else {
sb1.append(' ');
}
}
result1[i] = sb1.toString();
}
for (int i = 0; i < n; i++) {
String binary2 = Integer.toBinaryString(arr2[i]);
while (binary2.length() < n) {
binary2 = "0" + binary2;
}
StringBuilder sb2 = new StringBuilder();
for (int j = 0; j < n; j++) {
if (binary2.charAt(j) == '1') {
sb2.append('#');
} else {
sb2.append(' ');
}
}
result2[i] = sb2.toString();
}
for (int i = 0; i < n; i++) {
StringBuilder combined = new StringBuilder();
for (int j = 0; j < n; j++) {
// 둘 중 하나라도 '#'이면 '#' 표시
if (result1[i].charAt(j) == '#' || result2[i].charAt(j) == '#') {
combined.append('#');
} else {
combined.append(' ');
}
}
answer[i] = combined.toString();
}
return answer;
}
}
다른사람의 풀이
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] result = new String[n];
for (int i = 0; i < n; i++) {
result[i] = Integer.toBinaryString(arr1[i] | arr2[i]);// arr1[i] | arr2[i] → 벽 정보 계산, |는 비트 단위 OR 연산, 각 비트가 하나라도 1이면 결과가 1이 됨
}
for (int i = 0; i < n; i++) {
result[i] = String.format("%" + n + "s", result[i]);// String.format()으로 길이 맞춤, 숫자나 문자열을 특정 길이에 맞게 정렬하거나, 소수점 자릿수를 조정
result[i] = result[i].replaceAll("1", "#");// "1" → "#", "0" → " " 치환
result[i] = result[i].replaceAll("0", " ");
}
return result;
}
}
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
String temp;
for(int i = 0 ; i < n ; i++){
temp = String.format("%16s", Integer.toBinaryString(arr1[i] | arr2[i]));// 정수를 2진수 문자열로 바꾸고, 자릿수를 맞추고, 모양을 바꾸는 것까지" 한 번에 처리
temp = temp.substring(temp.length() - n);
temp = temp.replaceAll("1", "#");
temp = temp.replaceAll("0", " ");
answer[i] = temp;
}
return answer;
}
}