Source Code : https://github.com/JangAJang/Algorithm/blob/main/프로그래머스_Lv1/키패드%20누르기/src/Solution.java
문제를 확인했을 때, 일반 핸드폰에 있는 키패드와 동일한 상태에서 움직여야 한다고 해서 처음엔 키패드를 배열로 구현할 생각을 했다.
근데 문득 든 생각은, '배열이 아니라 그 버튼의 주소를 저장하면 어떨까?' 였다.
기본적으로 0을 제외한 숫자들을 생각해보면, 그 수를 n이라고 했을 때, 그 수의 좌표는 {x/3, x%3}으로 설정해 보았다.
1 | {0, 1} | 2 | {0, 2} | 3 | {1, 0} |
4 | {1, 1} | 5 | {1, 2} | 6 | {2, 0} |
7 | {2, 1} | 8 | {2, 2} | 9 | {3, 0} |
이 상태를 그려보았을 때, 조금 상태가 어긋남을 느낀 것이,
우리가 일반적인 2차원 배열을 표현할 때 제일 왼쪽 위의 주소는 {0, 0}이다.
그래서 x로 불러와 좌표를 설정할 때, 값을 1씩 빼보았다.
주소를 구할때 { (x-1)/3, (x-1)%3}로 계산을 했을 때 아래처럼 주소가 나왔다.
1 {0, 0} | 2 {0, 1} | 3 {0, 2} |
4 {1, 0} | 5 {1, 1} | 6 {1, 2} |
7 {2, 0} | 8 {2, 1} | 9 {2, 2} |
정확히 2차원 배열로 나오고, 여기에 0과 *, #을 추가해야 한다. * = {3, 0}, 0 = {3, 1}, # = {3, 2}로 나머지를 채웠다.
private class Position{
int[] location;
int distance;
public Position(int[] location, int distance){
this.location = location;
this.distance = distance;
}
public void setDistance(int x){
distance = Math.abs(location[0] - x/3) + Math.abs(location[1] - x%3);
}
public int getDistance(){
return distance;
}
public void setLocation(int[] x){
location = x;
}
}
이런 식으로 위치를 나타내는 클래스를 만들었고, 이를 이용해 Postion형 변수 left, right를 만들었다.
이를 이용한 방식은
- 눌러야 되는 키의 값 x가 들어온다. (입력시에는 위에서 말했듯이 x-1로 불러온다)
- left, right에 setDistance로 x부터 양손의 거리를 구한다.
- getDistance로 두 손을 비교해 더 가까운 손을 찾아낸다.
- 더 가까운 손에 setLocation해준다. (이 때 좌표는 2차원 배열이므로 두 변수를 배열 하나로 담아 저장시킨다.
이렇게 손이 얼마나 멀리있는지, 어떻게 움직이는지를 구현했다.
다음으로는 이 손들이 움직인다는 것을 어떻게 판단할지를 생각했다.
- 0이 들어오면 11로 만들어준다.
- 만약 x%3 == 1이라면 (1, 4, 7) 왼쪽 손이 움직인다
- left.setLocation( (x-1)/3, (x-1)%3)
- 만약 x%3 == 0이라면 {3, 6, 9) 오른쪽 손이 움직인다
- right.setLocation( (x-1)/3, (x-1)%3)
- 그게 아니라면 (2, 5, 8, 0) 키패드 중간줄이므로, 거리를 구해서 연산해야 한다.
- x로 부터 양손의 거리를 구한다.
- 둘의 거리가 같다면 오른손잡이인지 왼손잡이인지 판단한다
- 왼손잡이면 left.setLocation( (x-1)/3, (x-1)%3)
- 오른손잡이면 right.setLocation( (x-1)/3, (x-1)%3)
이런 과정으로 동작시켰다.
안으로 들여쓰기가 된 부분은 하나의 메서드 안에서 구현할 것이었다면 indent가 엄청났을 것 같다.
(내가 이걸 생각하는 이유는 https://jangsarchive.tistory.com/17 게시물 참고)
~~문 안에 다른 ~~문이 들어가지 않게 하고, 조금 더 보았을 때 이해할 수 있기 위해 메서드를 최대한 세분화 해보았다.
private String getNextFinger(int x, String hand){
if(x == 0) x = 11;
if(x%3 == 1) return setL(x-1);
if(x%3 == 0) return setR(x-1);
return findFromMiddleLine(x-1, hand);
}
private String findFromMiddleLine(int x, String hand){
left.setDistance(x);
right.setDistance(x);
if(left.getDistance() == right.getDistance()) return getFromSameDist(x, hand);
return getFromDifferentDist(x);
}
private String getFromSameDist(int x, String hand){
if(hand.equals("right")) return setR(x);
return setL(x);
}
private String getFromDifferentDist(int x){
if(left.getDistance() < right.getDistance()) return setL(x);
return setR(x);
}
private String setR(int x){
right.setLocation(new int[]{x/3, x%3});
return "R";
}
private String setL(int x){
left.setLocation(new int[]{x/3, x%3});
return "L";
}
이런 방식으로 문제를 풀었던 것 같다.
배운점
이 문제를 풀기 전에, 백준에서 단계별로 존재하는 2차원 배열의 문제들도 풀어보았다.
배열과 관련되었다는 문제들을 볼 때 마다 생각하는 것은
- 어떻게 하면 그 배열들을 다 담지 않고 끝낼 수 있을까?
- 배열을 담아야 한다면 어떻게 담는게 최소화를 시킬 수 있는 방법일까?
라는 것이다.
배열에 데이터를 담는 것 자체가 문제가 되지 않는다. 탐색이나 정렬을 할 때에 배열이나 리스트에 데이터를 담고 시작해야 하니깐.
그렇다면 거기서 얼마나 데이터를 담고, 이를 연산하는 과정을 줄일 수 있을지 생각해보아야겠다.
'개발공부 > 프로그래머스' 카테고리의 다른 글
[프로그래머스] PCCP 2번. 석유시추 (2) | 2024.03.06 |
---|---|
[프로그래머스] lv.2 전력망을 둘로 나누기 (0) | 2023.02.10 |
[프로그래머스] 코딩테스트 Lv.1 신규 아이디 추천 (0) | 2022.10.28 |
[프로그래머스] 코딩테스트 Lv.1 완주하지 못한 선수 (0) | 2022.10.28 |
[프로그래머스] 코딩테스트 Lv.1 완주하지 못한 선수 (0) | 2022.10.21 |