키패드 누르기

문제

스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.

1 2 3
4 5 6
7 8 9
* 0 #

이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.

  • 엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다.
  • 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다.
  • 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다.
  • 가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다.
    • 4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다.

순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

numbers hand result
[1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5] “right” “LRLLLRLLRRL”
[7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2] “left” “LRLLRRLLLRR”
[1, 2, 3, 4, 5, 6, 7, 8, 9, 0] “right” “LLRLLRLLRL”

1차답안

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class Solution {
public String solution(int[] numbers, String hand) {
String answer = "";

//left 및 right로 무조건 들어가야할 영역 생성
int [] left = {1,4,7};
int [] right = {3,6,9};
int [] middle = {2,5,8,0};

// 초기화
int leftFg = 0, rightFg = 0, currentFg = 0;
int rightLoc= 0, leftLoc = 0, currentLoc = 0;

for(int number: numbers) {
//left 라면?
if (contains(number, left)){
answer += "L";
leftFg = number;
currentFg = number;
} else if (contains(number, right)) {
answer += "R";
rightFg = number;
currentFg = number;
// 가운데라면 비교 후
} else {
currentLoc = locationFg(number);
rightLoc = Math.abs(currentLoc - locationFg(rightFg));
leftLoc = Math.abs(currentLoc - locationFg(leftFg));

if(rightLoc > leftLoc){ // 왼쪽이 더가깝다면
answer += "L";
leftFg = number;
currentFg = number;
} else if(rightLoc < leftLoc){ // 오른쪽이 더가깝다면
answer += "R";
rightFg = number;
currentFg = number;
} else { // 둘다 거리가 같다면
if(contains(leftFg, middle) && contains(rightFg, middle)){
if("left".equals(hand)){
answer += "L";
leftFg = number;
currentFg = number;
} else {
answer += "R";
rightFg = number;
currentFg = number;
}
} else if (contains(rightFg, middle)){
answer += "R";
rightFg = number;
currentFg = number;
} else if (contains(leftFg, middle)){
answer += "L";
leftFg = number;
currentFg = number;
} else {
if("left".equals(hand)){
answer += "L";
leftFg = number;
currentFg = number;
} else {
answer += "R";
rightFg = number;
currentFg = number;
}
}
}
}
}

return answer;
}

public boolean contains(int key ,int[] arrays){
return Arrays.stream(arrays).anyMatch(i -> i == key);
// for(int num : arrays){
// if (num == key){
// return true;
// }
// }
// return false;
}

public int locationFg(int key){
switch(key) {
case 1: case 2: case 3:
return 1;
case 4: case 5: case 6:
return 2;
case 7: case 8: case 9:
return 3;
default:
return 4;
}
}
}

CASE1 통과 불가 - 4/5 일경우

테스트 1
입력값 〉 [1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5], “right”
기댓값 〉 “LRLLLRLLRRL”
실행 결과 〉 실행한 결괏값 “LRLLLRLLLRL”이(가) 기댓값 “LRLLLRLLRRL”와(과) 다릅니다.

1 2 3
4 5 6
7 8 9
* 0 #

leftFg = 2
rightFg = 4
currentFg = 5
hand = right 이므로 R값이 들어가야하지만 CASE 문으로 ROW 형태로 관리되었기때문에 해당 관련 로직 해결하지 못함

2차답안

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
public String solution(int[] numbers, String hand) {
String answer = "";

// 초기화 *=10 / 0=11 / #=12
int leftFg = 10, rightFg = 12;
int rightDis= 0, leftDis = 0;

for(int number: numbers) {
if(number == 0)
number = 11;

switch(number % 3) {
case 0: // 오른쪽일때
answer += "R";
rightFg = number;
break;
case 1: // 왼쪽일떄
answer += "L";
leftFg = number;
break;
case 2: // 가운데일때 거리 비교 (거리는 3의몫 + 3의나머지)
leftDis = Math.abs(number - leftFg) % 3 + Math.abs(number - leftFg) / 3;
rightDis = Math.abs(number - rightFg) % 3 + Math.abs(number - rightFg) / 3;

if(leftDis > rightDis) {
answer += "R";
rightFg = number;
} else if(leftDis < rightDis){
answer += "L";
leftFg = number;
} else {
if("left".equals(hand)){
answer += "L";
leftFg = number;
} else {
answer += "R";
rightFg = number;
}
}
break;
}
}
return answer;
}
}

중요한 개념으로 거리는 절대값(위치-FG)/3 + 절대값(위치-FG)%3

1 2 3
4 5 6
7 8 9
* 0 #

일떄 만약 ‘5’ 를 검색한다면 left = 4 right = 2 이므로

leftFg
(5-2) /3 => 1
(5-2) %3 => 0
rightFg
(5-4) /3 => 0
(5-4) %3 => 1
leftFg = 0 / rightFg = 0 즉 거리가 같으므로 hand가 right이므로 R값이 + 되어야한다.