키패드 누르기(Lv1. Swift)

Updated:

키패드 누르기(Lv1. Swift)

🔍 문제

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

image

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

엄지손가락은 상하좌우 4가지 방향으로만 이동할 수 있으며 키패드 이동 한 칸은 거리로 1에 해당합니다. 왼쪽 열의 3개의 숫자 1, 4, 7을 입력할 때는 왼손 엄지손가락을 사용합니다. 오른쪽 열의 3개의 숫자 3, 6, 9를 입력할 때는 오른손 엄지손가락을 사용합니다. 가운데 열의 4개의 숫자 2, 5, 8, 0을 입력할 때는 두 엄지손가락의 현재 키패드의 위치에서 더 가까운 엄지손가락을 사용합니다. 4-1. 만약 두 엄지손가락의 거리가 같다면, 오른손잡이는 오른손 엄지손가락, 왼손잡이는 왼손 엄지손가락을 사용합니다. 순서대로 누를 번호가 담긴 배열 numbers, 왼손잡이인지 오른손잡이인 지를 나타내는 문자열 hand가 매개변수로 주어질 때, 각 번호를 누른 엄지손가락이 왼손인 지 오른손인 지를 나타내는 연속된 문자열 형태로 return 하도록 solution 함수를 완성해주세요.

🔶 제한사항

  • numbers 배열의 크기는 1 이상 1,000 이하입니다.

  • numbers 배열 원소의 값은 0 이상 9 이하인 정수입니다.

  • hand는 “left” 또는 “right” 입니다.

    - "left"는 왼손잡이, "right"는 오른손잡이를 의미합니다.
    
  • 왼손 엄지손가락을 사용한 경우는 L, 오른손 엄지손가락을 사용한 경우는 R을 순서대로 이어붙여 문자열 형태로 return 해주세요.

🔷 입출력 예

image

🔷 입축력 예 설명

순서대로 눌러야 할 번호가 [1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5]이고, 오른손잡이입니다.

image

따라서 “LRLLLRLLRRL”를 return 합니다.


📌 풀이

키패드는 상하좌우로만 움직일 수 있으니 키패드 숫자들의 상하좌우간 관계를 파악하면 되는 문제이다.

먼저 눌러야 하는 숫자가 1, 4, 7인 경우는 무조건 왼손이 3, 6, 9인 경우는 무조건 오른손이 누르게 된다.

문제는 다음 눌러야 하는 숫자가 2, 5, 8, 0인 경우이다.

이 경우에는 현재 왼손과 오른손이 위치한 키패드의 숫자를 중심으로, 눌러야 하는 숫자까지의 거리를 계산해서 거리가 더 짧은 곳에 있는 손이 해당 숫자를 누르도록 선택해야 한다. 이를 위해 키패드간 거리를 계산하는 방법을 찾아야하는 것이 이 문제의 핵심이다.

키패드의 숫자들을 살펴보면

좌우에 있는 숫자들끼리는 +1, -1씩 차이가 난다. 예) 4, 5, 6

상하에 있는 숫자들끼리는 +3, -3씩 차이가 난다. 예) 1, 4, 7

현재 손이 있는 곳과 다음 눌러야 하는 숫자의 차이를 3으로 나누어 그 몫과 나머지를 더하면 해당 거리를 구할 수 있다.

예를 들면

왼손 위치 오른손 위치 눌러야할 숫자
1 9 8

왼손 위치(1) - 눌러야 할 숫자(8) = 7 (차이를 구하는 것이므로 절대값으로 계산한다) 왼손 위치와 눌러야 할 숫자의 차이(7) / 3 = 2…1 몫이 2이고 나머지가 1이므로 두 숫자를 더한 3이 키패드 1과 8의 거리값이 된다

오른손 위치(9) - 눌러야 할 숫자(8) = 1 1/ 3 = 0…1 몫이 0이고 나머지가 1이므로 두 숫자를 더한 1이 키패드 9와 8의 거리값이 된다

이런식으로 계산할 경우

키패드 숫자0을 11로 놓고 계산해야 한다.

또한 * 는 10, #는 12로 설정해주었다.

이렇게 계산 한 후, 거리 값이 작은 곳에 있는 손이 선택되도록 해주고 값이 같을 경우 hand에 따라 선택되도록 해주었다.

func solution(_ numbers:[Int], _ hand:String) -> String {

enum KeyPadHand {
	case left
	case right
}

var result = ""
var leftHand = 10 // 왼손이 누른 키패드 숫자를 저장할 변수 선언 (* = 10)
var rightHand = 12 // 오른손이 누른 키패드 숫자를 젖ㅇ할 변수 선언 (# = 12)

for i in numbers {
	let number = i == 0 ? 11 : i // 키패드 숫자가 0일 경우 11로 바꿔준다
	var tapHand: KeyPadHand = .left

	switch number {
	case 1, 4, 7: // 1,4,7 일 경우
		tapHand = .left
	case 3, 6, 9: // 3, 6, 9 일 경우
		tapHand = .right

	case 2, 5, 8, 11: // 2, 5, 8, 0 일경우
		let leftTemp = abs(number - leftHand) // 눌러야 할 숫자와 왼손이 눌렀던 숫자 의 차이의 절대값
		let rightTemp = abs(number - rightHand) // 눌러야할 숫자와 오른손이 눌런던 숫자의 차이 절대값

		let leftDistance = (leftTemp / 3) + (leftTemp % 3) // 왼손과 눌러야 할 숫자간의 거리
		let rightDistance = (rightTemp / 3) + (rightTemp % 3) // 오른손과 눌러야 할 숫자간의 거리

		if leftDistance == rightDistance { // 왼손과 오른손 거리값이 같은 경우
			tapHand = hand == "left" ? .left : .right // 어느 손잡이 인지 따라 손이 걸정이 됨
		} else {
			tapHand = leftDistance < rightDistance ? .left : .right
		}

	default:
		break
	}

	// 선택된 손에 따라 결과 값 저장하고 누른 숫자 updata 해 주기
	if tapHand == .left {
		result.append("L")
		leftHand = number
	} else {
		result.append("R")
		rightHand = number
	}
}
	return result
}

print(solution([1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5], "right")) // LRLLLRLLRRL


Reference

프로그래머스 - https://programmers.co.kr/learn/courses/30/lessons/67256

Categories:

Updated:

Leave a comment