일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Android
- androidstudio
- bitmap
- BOJ
- Canvas
- CS
- Database
- DBeaver
- DP
- Ecilpse
- Eclipse
- firebase
- git
- github
- GooglePlayServices
- gradle
- IDE
- IntelliJ
- java
- json
- kotlin
- level2
- linux
- mariadb
- MYSQL
- Paint
- permission
- python
- Sorting
- sourcetree
will come true
[프로그래머스 / Level1] 비밀지도 (Java) 본문
문제
2018 KAKAO BLIND RECRUITMENT, https://programmers.co.kr/learn/courses/30/lessons/17681?language=java
#비트 연산(Bitwise Operation)
- 지도는 한 변의 길이가 N인 정사각형 배열 형태, 각 칸은 공백(" ") 또는 벽("#") 두 종류이다.
- 전체 지도는 두 장의 지도(지도1 + 지도2)를 겹쳐야 얻을 수 있다.
- 지도1과 지도2는 각각 정수 배열로 암호화되어 있다.
- 암호화된 배열은 지도의 각 가로줄에서 벽=1, 공백=0으로 부호화했을 때 이진수에 해당하는 값의 배열
기존 코드 (성공)
class Solution {
public String[] solution(int n, int[] arr1, int[] arr2) {
String[] answer = new String[n];
for(int i=0; i < n; i++){
String row = String.format(String.format("%%%ds", n), Integer.toBinaryString(arr1[i] | arr2[i]));
for(int j=0; j < n; j++){
answer[i] = row.replace('1', '#').replace('0', ' ');
}
}
return answer;
}
}
- 기존 코드가 생각보다 깔끔하게 짜져서 이번에는 기존 코드에 사용된 메서드들만 간단히 정리해보기로 했다.
- 프로그래머스 코테 연습에서 카카오문제가 나오면 괜시리 긴장됐는데, 그래도 Level1 문제는 사람이 풀 수 있는 난이도로 내주는 것 같다.
- 지도가 정사각형(n x n)이기 때문에 계산에 사용되는 모든 배열의 길이 n으로 같다.
a. 지도의 가로줄(벽/공백)을 요소로 가지는 String 배열 answer의 길이
b. 지도1, 지도2의 가로줄(정수)을 요소로 가지는 int배열 arr1, arr2의 길이
c. 지도1과 지도2를 겹쳐 얻은 이진수(=가로줄)의 길이 - 지도1과 지도2에서 각각 같은 자리의 칸(arr1[i], arr2[i])을 가져와 겹친다. 이때 겹친다는 것은 두 지도 중 하나에서라도 해당 칸이 벽(#)일 경우 벽(#)으로 처리한다는 것이다. = OR연산
- 두 지도에서 한줄을 겹친 결과를 Integer.toBinaryString() 함수를 통해 이진수로 변환 후, 앞자리를 공백으로 채운다. (어차피 다음 단계에서 0을 공백으로 대체할 것이기 때문에, 공백을 0으로 미리 전환해둘 필요는 없음. 즉, 공백==0)
- 이진수 문자열에서 1은 #은 1로, 0은 공백으로 대체한 문자열을 저장한다.
학습 내용
비트연산 OR
public static void main(String[] args) {
int a = 9;
int b = 30;
System.out.println(a + ": " + Integer.toBinaryString(a));
System.out.println(b + ": " + Integer.toBinaryString(b));
System.out.println((a | b) + ": " + Integer.toBinaryString(a | b));
}
9: 1001
30: 11110
31: 11111
두 수를 이진화했을 때 각 자릿수에 대해 하나라도 1이면 1로 변환한 이진수 문자열을 반환한다.
이때 정수를 이진화 했을때의 길이가 달라도 된다. (ex: 101, 11000 간의 비트연산 가능)
String.format() 문자열 형식화
String 문자열의 형식을 변경할 수 있다.
public static void main(String[] args) {
int a = 8;
int b = 1;
String str = Integer.toBinaryString(a | b);
System.out.println(String.format("%s_", str));
System.out.println(String.format("%8s_", str));
System.out.println(String.format("%-8s_", str));
System.out.println(String.format("%.2s_", str));
System.out.println(String.format("%8.2s_", str));
System.out.println(String.format("%-8.2s_", str));
}
1001_
1001_
1001 _
10_
10_
10 _
- %s : 문자열 그대로 유지
- %8s : 문자열의 길이를 8로 맞추고 남은 자리는 공백으로 채우기 (오른쪽 정렬)
- %-8s : 문자열의 길이를 8로 맞추고 남은 자리는 공백으로 채우기 (왼쪽 정렬)
- %.2s : 문자열을 2자리 만큼 자르기
- %8.2s : 문자열을 2자리 만큼 자른 뒤 길이를 8로 맞추고 남은 자리는 공백으로 채우기 (오른쪽 정렬)
- %-8.2s : 문자열을 2자리 만큼 자른 뒤 길이를 8로 맞추고 남은 자리는 공백으로 채우기 (왼쪽 정렬)
- 밑줄(_)은 출력 시 문자열의 위치 구분용 문자일 뿐 아무 의미 없음.
10진수를 2진수로 변환 시 앞자리 0 출력하기 (이진수 자릿수 맞추기)
String.format() 메서드를 사용해 Integer.toBinaryString() 로 구한 이진수 문자열을 원하는 길이로 출력할 수 있다.
이때 Integer.parseInt로 형변환해주는 이유는 정수 타입만 String.format()에서 %08d을 사용해 공백을 0으로 채우는 것이 가능하기 때문이다. 참고로 Integer.toBinaryString()의 반환값은 String타입.
public static void main(String[] args) {
int a = 8;
int b = 1;
System.out.println(Integer.toBinaryString(a | b));
System.out.println(String.format("%8s", Integer.toBinaryString(a | b)));
System.out.println(String.format("%08d", Integer.parseInt(Integer.toBinaryString(a | b))));
//System.out.println(String.format("%08s", Integer.toBinaryString(a | b))) 은 에러 발생
}
1001
1001
00001001
String.Format 정수 자릿수 동적 할당
지금까지 "%8s"같이 고정자릿수를 기입해줬으나, 이 자릿수를 int변수 값에 따라 "%{n}s"같이 형식화되도록 할 수 있다.
public static String getFullBinary(int n, int num) {
return String.format(String.format("%%0%dd", n), Integer.parseInt(Integer.toBinaryString(num)));
}
public static void main(String[] args) {
int a = 8;
int b = 1;
int ab = a|b;
System.out.println(getFullBinary(4, ab));
System.out.println(getFullBinary(8, ab));
System.out.println(getFullBinary(10, a|b));
}
1001
00001001
0000001001
위에서는 두 개의 String.format이 중첩되어 있는데, 2번째 String.format()의 반환값 문자열을 그대로 1번째 String.format() 메서드에 첫번째 매개변수(format)으로 사용하고 있다. 이를 두 구문으로 쪼개서 각 String.format()의 반환 문자열을 확인해보면 아래와 같다. (※ format에 %문자를 쓰고싶다면 %%와 같이 두번 연속으로 쓰면 된다)
public static void main(String[] args) {
int a = 8;
int b = 1;
int ab = a|b;
int n = 8;
String s1 = String.format("%%0%dd", n);
System.out.println(s1);
String s2 = String.format(s1, Integer.parseInt(Integer.toBinaryString(ab)));
System.out.println(s2);
}
%08d
00001001
[참고]
- 2018 KAKAO BLIND RECRUITMENT, https://programmers.co.kr/learn/courses/30/lessons/17681?language=java
- 이진수 앞자리 0출력, https://okky.kr/article/449107
- Java format String with dynamic width and precision, https://stackoverflow.com/a/40608465
'Algorithm' 카테고리의 다른 글
[프로그래머스 / 데모테스트] 나머지 한 점 (Java) (0) | 2021.11.04 |
---|---|
[프로그래머스 / Level1] 두 개 뽑아서 더하기 (Java) (0) | 2021.11.04 |
[프로그래머스 / Level1] 부족한 금액 계산하기 (Java) (0) | 2021.11.01 |
[프로그래머스 / Level1] 2016년 (Java) (0) | 2021.10.31 |
[프로그래머스 / Level1] 다트 게임 (Java) (0) | 2021.10.31 |