문제
https://school.programmers.co.kr/learn/courses/30/lessons/67256
문제설명
스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.
이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
- 엄지손가락은 상하좌우 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 해주세요.
입출력 예
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, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5]이고, 오른손잡이입니다.
따라서 "LRLLLRLLRRL"를 return 합니다.
입출력 예 #2
왼손잡이가 [7, 0, 8, 2, 8, 3, 1, 5, 7, 6, 2]를 순서대로 누르면 사용한 손은 "LRLLRRLLLRR"이 됩니다.
입출력 예 #3
오른손잡이가 [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]를 순서대로 누르면 사용한 손은 "LLRLLRLLRL"이 됩니다.
풀이
접근
- 키패드의 위치를 좌표화 해 딕셔너리에 저장한다. 손가락이 어디에 있는지, 목표하는 키패드가 어디에 있는지 저장하기 위함
-
num_dict = {1:(3,0), 2:(3,1), 3:(3,2), 4:(2,0), 5:(2,1), 6:(2,2), 7:(1,0), 8:(1,1), 9:(1,2), '*': (0,0), 0:(0,1), '#': (0,2)}
-
- 거리를 비교하기 위해 맨해튼 거리를 사용한다.
- (두 점 (a1,a2), (b1,b2) 사이의 맨해튼 거리는 |a1 - b2| + |a1 - b2| )
-
''' 거리 구하는 함수 num_dict[now] : 목표 위치 num_dict[hand] : 현재 손가락의 위치 ''' def distance_func(now,hand): dis = abs( (num_dict[now][0] - num_dict[hand][0])) + abs((num_dict[now][1] - num_dict[hand][1]) ) return dis
- numbers를 순회하여 각각 경우에 오른손인지, 왼손인지 판별한다.
- 숫자가 1,4,7 인 경우 : L
- 숫자가 3,6,9 인 경우 : R
- 숫자가 2,4,8,0 인 경우
- 왼손 거리 < 오른손 거리 : L
- 왼손 거리 > 오른손 거리 : R
- 왼손 거리 = 오른손 거리이며 오른손잡이인 경우 : R
- 왼손 거리 = 오른손 거리이며 왼손잡이인 경우 : L
풀이 코드 - 1차
def solution(numbers, hand):
answer = ''
num_dict = {1:(3,0), 2:(3,1), 3:(3,2),
4:(2,0), 5:(2,1), 6:(2,2),
7:(1,0), 8:(1,1), 9:(1,2),
'*': (0,0), 0:(0,1), '#': (0,2)}
current_left = '*'
current_right = '#'
def distance_func(now,hand):
dis = abs( (num_dict[now][0] - num_dict[hand][0])) + abs((num_dict[now][1] - num_dict[hand][1]) )
return dis
for i in numbers:
if i in [1,4,7]:
answer += "L"
current_left = i
elif i in [3,6,9]:
answer += "R"
current_right = i
elif i in [2,5,8,0]:
if distance_func(i,current_left) < distance_func(i,current_right) :
answer += "L"
current_left = i
elif distance_func(i,current_left) > distance_func(i,current_right) :
answer += "R"
current_right = i
elif distance_func(i,current_left) == distance_func(i,current_right) and hand == 'right':
answer += "R"
current_right = i
elif distance_func(i,current_left) == distance_func(i,current_right) and hand == 'left':
answer += "L"
current_left = i
return answer
잘 통과했지만 후반 테스트케이스로 갈 수록 다소 느려지는 모습
2차
숫자가 2,5,8,0인 경우에서,
answer에 L 을 담는 경우와 answer에 R 을 담는 행위는 같으므로 if 문을 여러번 쓰지 말고 한번에 묶었다.
def solution(numbers, hand):
answer = ''
num_dict = {1: (3, 0), 2: (3, 1), 3: (3, 2),
4: (2, 0), 5: (2, 1), 6: (2, 2),
7: (1, 0), 8: (1, 1), 9: (1, 2),
'*': (0, 0), 0: (0, 1), '#': (0, 2)}
def distance_func(hand_pos, target_pos):
return abs(hand_pos[0] - target_pos[0]) + abs(hand_pos[1] - target_pos[1])
current_left = '*'
current_right = '#'
for i in numbers:
if i in [1, 4, 7]:
answer += "L"
current_left = i
elif i in [3, 6, 9]:
answer += "R"
current_right = i
elif i in [2, 5, 8, 0]:
left_distance = distance_func(num_dict[current_left], num_dict[i])
right_distance = distance_func(num_dict[current_right], num_dict[i])
# 왼손을 쓰는 모든 경우 : 왼손거리<오른손거리 이거나 거리가 같고 왼손잡이
if left_distance < right_distance or (left_distance == right_distance and hand == 'left'):
answer += "L"
current_left = i
# 오른손을 쓰는 모든 경우 : 왼손거리<오른손거리 이거나 거리가 같고 오른손잡이
else:
answer += "R"
current_right = i
return answer
실행 속도가 조금 더 빨라진 것을 확인할 수 있다.
GitHub 댓글