네오는 평소 프로도가 비상금을 숨겨놓는 장소를 알려줄 비밀지도를 손에 넣었다. 그런데 이 비밀지도는 숫자로 암호화되어 있어 위치를 확인하기 위해서는 암호를 해독해야 한다. 다행히 지도 암호를 해독할 방법을 적어놓은 메모도 함께 발견했다.
n
인 정사각형 배열 형태로, 각 칸은 "공백"(" ") 또는 "벽"("#") 두 종류로 이루어져 있다.1
, 공백 부분을 0
으로 부호화했을 때 얻어지는 이진수에 해당하는 값의 배열이다.네오가 프로도의 비상금을 손에 넣을 수 있도록, 비밀지도의 암호를 해독하는 작업을 도와줄 프로그램을 작성하라.
입력으로 지도의 한 변 크기 n
과 2개의 정수 배열 arr1
, arr2
가 들어온다.
n
≦ 16arr1
, 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] |
출력 | ["######", "### #", "## ##", " #### ", " #####", "### # "] |
이 문제의 포인트는 주어진 10진수를 2진수로 변환하는 것이다.
문제 풀이 방식을 3가지로 나눠서 설명 하고자 한다.
문자열 변환 과정에서 풀이 속도가 달라진다.
제일 처음 풀었던 방식이며, 제일 속도가 느렸던 방식이다.
public static String Change(int num, int n){
String temp = Integer.toString(num, 2);
while(temp.length() < n){
temp = "0" + temp;
}
return temp;
}
주어진 문자열을 하나씩 받아 Integer.toString(num, 2);
을 통해 2진법으로 변환하였다.
while(temp.length() < n){
temp = "0" + temp;
}
변환한 2진수를 자릿수를 맞추기 위해서 변환한 문자열 앞에 "0"
을 추가하였다.
여기서 문자열 앞에 계속 문자열을 추가해서 속도가 느리게 나온 것 같다.
public String decode(String a, String b, int n){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < n; i++){
if(a.charAt(i) == '1' || b.charAt(i) == '1'){
sb.append("#");
}
else{
sb.append(" ");
}
}
return sb.toString();
}
2진법으로 바꾼 두 숫자를 비교하여 둘 중 1이 한개라도 있으면 "#"
을 그 외는 " "
을 넣어 문자열을 만들어 주었다.
import java.util.*;
class Solution {
public static String Change(int num, int n){
String temp = Integer.toString(num, 2);
while(temp.length() < n){
temp = "0" + temp;
}
return temp;
}
public String decode(String a, String b, int n){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < n; i++){
if(a.charAt(i) == '1' || b.charAt(i) == '1'){
sb.append("#");
}
else{
sb.append(" ");
}
}
return sb.toString();
}
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
ArrayList<String> a1 = new ArrayList<>();
ArrayList<String> a2 = new ArrayList<>();
for(int i = 0; i < arr1.length; i++){
a1.add(Change(arr1[i], n));
a2.add(Change(arr2[i], n));
}
for(int i = 0; i < arr1.length; i++){
answer[i] = decode(a1.get(i), a2.get(i), n);
}
return answer;
}
}
1번 풀이 과정에서 달라진 점은 10진법을 2진법으로 바꾸는 방식만 바꿨다.
public static String Change(int num, int n){
String temp = String.format("%16s",Integer.toString(num, 2));
return temp.substring(temp.length() - n);
}
String.format()
을 이용하여 문자열의 길이를 통일하였고, substring()
으로 문자열을 잘라 주었다.
import java.util.*;
class Solution {
public static String Change(int num, int n){
String temp = String.format("%16s",Integer.toString(num, 2));
return temp.substring(temp.length() - n);
}
public String decode(String a, String b, int n){
StringBuffer sb = new StringBuffer();
for(int i = 0; i < n; i++){
if(a.charAt(i) == '1' || b.charAt(i) == '1'){
sb.append("#");
}
else{
sb.append(" ");
}
}
return sb.toString();
}
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
ArrayList<String> a1 = new ArrayList<>();
ArrayList<String> a2 = new ArrayList<>();
for(int i = 0; i < arr1.length; i++){
a1.add(Change(arr1[i], n));
a2.add(Change(arr2[i], n));
}
for(int i = 0; i < arr1.length; i++){
answer[i] = decode(a1.get(i), a2.get(i), n);
}
return answer;
}
}
이 코드는 많은 사람들이 푼 방법이며, 제일 코드가 간단해서 보고 놀랐던 방식이다.
비트를 이용하는 방식이다.
문제를 잘 보면 1이 하나라도 있으면 "#"
으로 변환이 되는데 이게 OR 연산과 같다는 것을 알 수 있다.
이것을 통하여 10진법에서 2진법으로 바꿀때 Integer.toBinaryString(arr1[i] | arr2[i])
을 사용하여 변환하였다. 참고로 OR 연산이 | 와 같다.
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
for(int i = 0; i < n ; i++){
String temp = String.format("%16s", Integer.toBinaryString(arr1[i] | arr2[i]));
temp = temp.substring(temp.length() - n);
temp = temp.replaceAll("1","#");
temp = temp.replaceAll("0"," ");
answer[i] = temp;
}
return answer;
}
}