프로그래머스 | 키패드 누르기 (Java)

mul·2023년 2월 11일
0

알고리즘

목록 보기
17/65
post-custom-banner

🔒 문제

프로그래머스 Lv.1 2020 카카오 인턴십 키패드 누르기

🔑 해결

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

눌러야할 키패드의 위치(1/4/7, 2/5/8/0, 3/6/9)를 먼저 판별하고 (1/4/7)은 왼손, (3/6/9)는 오른손을 사용하는 것으로 판단한다. (2/5/8/0)은 눌러야할 키패드(target)과 왼손/오른손과의 거리(ld/rd)를 계산하여 거리가 가까운 손을 사용한다.

  1. *을 10, 0을 11, #을 12로 생각하여, 왼손의 위치(l)을 10으로, 오른손의 위치(r)을 12로 초기화하고, 사용한 손을 저장할 StringBuilder sb를 생성한다.
  2. numbers만큼 for문을 돌린다.
  3. if/else문을 통해 눌러야할 키패드(numbers[i])의 위치를 판별한다.
  4. 키패드의 위치가 중앙(2 5 8 0)이라면,
    4-1. 눌러야할 키패드(numbers[i])를 target에 저장. target이 0이라면 11을 저장.
    4-2. distance함수를 만들어 왼손/오른손과의 거리를 계산.
    4-2-1. 키패드를 2차원 배열로 생각하였을 때, target과의 거리는
    |target의 x좌표 - 왼/오른손이 있는 키패드(n)의 x좌표| + |target의 y좌표 - n의 y좌표|
    이므로, 키패드 번호를 좌표값(tx,ty,nx,ny)로 만들어 계산한다.
    4-2-2. x좌표를 계산할 땐, target에 -1을 해주고(이유: 3/6/9), y좌표를 계산할 땐, 나머지가 0이상(1/4/7/2/5/8/0)인 경우에는 -1을, 나머지가 0(3/6/9)면 +2를 하여 좌표값을 맞춰준다.
    4-2-3. |x좌표간의 차(xd)| + |y좌표간의 차(yd)|를 계산하여 거리 d를 return한다.
    4-3-1. 왼손과의 거리가 오른손보다 짧으면, 왼손을 사용(sb.append('L'))하고, 왼손의 위치(l)를 target으로 바꾼다.
    4-3-2. 오른손과의 거리가 왼손보다 짧으면, 오른손을 사용(sb.append('R'))하고, 오른손의 위치(r)를 target으로 바꾼다.
    4-3-3. 왼손과의 거리와 오른손과의 거리가 같으면, 매개변수 hand가 left면 왼손을, right면 오른손을 사용(sb.append())하고 l/r의 위치를 target으로 바꾼다.
  5. 키패드 번호가 3으로 나누었을 때 나머지가 1인 (1 4 7)이라면 왼손을 사용(sb.append('L'))하고 l에 키패드 번호(numbers[i])를 저장
  6. 키패드 번호가 (3 6 9)라면 오른손을 사용(sb.append('R'))하고 r에 numbers[i]를 저장
  7. sb를 String으로 변환한 뒤 answer에 저장한다.

🔓 코드

class Solution {
    public String solution(int[] numbers, String hand) {
		String answer = "";
		StringBuilder sb = new StringBuilder();

		int l = 10;
		int r = 12;

		for (int i = 0; i < numbers.length; i++) {
			if (numbers[i] == 0 || numbers[i] % 3 == 2) { // 2 5 8 0
				int target = numbers[i];
				if (target == 0)
					target = 11;
				
				int ld = distance(target, l);
				int rd = distance(target, r);

				if (ld < rd) {
					l = target;
					sb.append('L');
				} else if (rd < ld) {
					r = target;
					sb.append('R');
				} else {
					if (hand.equals("left")) {
						l = target;
						sb.append('L');
					} else {
						r = target;
						sb.append('R');
					}
				}
			} else if (numbers[i] % 3 == 1) { // 1 4 7
				l = numbers[i];
				sb.append('L');
			} else { // 3 6 9
				r = numbers[i];
				sb.append('R');
			}
		}
		answer = sb.toString();

		return answer;
	}
	
	public int distance(int target, int n) {
		int d = 0;
		
//		keypad
//		1 (0.0)		2 (0.1) 	3 (0.2)
//		4 (1.0)		2 (1.1) 	3 (1.2)
//		7 (2.0)		2 (2.1) 	3 (2.2)
//		* (3.0)		0 (3.1) 	# (3.2)
        
		int tx = (target-1) / 3;
		int ty = target % 3;
		if (ty > 0) {
			ty--;
		} else {
			ty = ty + 2;
		}
		
		int nx = (n-1) / 3;
		int ny = n % 3;
		if (ny > 0) {
			ny--;
		} else {
			ny = ny + 2;
		}
		
		int xd = tx - nx;
		if (xd < 0)
			xd = xd * (-1);
		int yd = ty - ny;
		if (yd < 0)
			yd = yd * (-1);
		
		d = xd + yd;
		
		return d;
	}
}
post-custom-banner

0개의 댓글