문제
https://school.programmers.co.kr/learn/courses/30/lessons/67256?language=python3
문제 설명
스마트폰 전화 키패드의 각 칸에 다음과 같이 숫자들이 적혀 있습니다.

이 전화 키패드에서 왼손과 오른손의 엄지손가락만을 이용해서 숫자만을 입력하려고 합니다.
맨 처음 왼손 엄지손가락은 * 키패드에 오른손 엄지손가락은 # 키패드 위치에서 시작하며, 엄지손가락을 사용하는 규칙은 다음과 같습니다.
- 엄지손가락은 상하좌우 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]이고, 오른손잡이입니다.
왼손 위치 오른손 위치 눌러야 할 숫자 사용한 손 설명
| * | # | 1 | L | 1은 왼손으로 누릅니다. |
| 1 | # | 3 | R | 3은 오른손으로 누릅니다. |
| 1 | 3 | 4 | L | 4는 왼손으로 누릅니다. |
| 4 | 3 | 5 | L | 왼손 거리는 1, 오른손 거리는 2이므로 왼손으로 5를 누릅니다. |
| 5 | 3 | 8 | L | 왼손 거리는 1, 오른손 거리는 3이므로 왼손으로 8을 누릅니다. |
| 8 | 3 | 2 | R | 왼손 거리는 2, 오른손 거리는 1이므로 오른손으로 2를 누릅니다. |
| 8 | 2 | 1 | L | 1은 왼손으로 누릅니다. |
| 1 | 2 | 4 | L | 4는 왼손으로 누릅니다. |
| 4 | 2 | 5 | R | 왼손 거리와 오른손 거리가 1로 같으므로, 오른손으로 5를 누릅니다. |
| 4 | 5 | 9 | R | 9는 오른손으로 누릅니다. |
| 4 | 9 | 5 | L | 왼손 거리는 1, 오른손 거리는 2이므로 왼손으로 5를 누릅니다. |
| 5 | 9 | - | - |
따라서 "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"이 됩니다.
풀이
- 문제 이해를 위한 정리
- 엄지 손가락만 사용한다 (오른손 엄지/왼손 엄지)
- 초기 위치: L (*), R(#)
- 이동경우 : LRUD → 대각선은 움직임이 X ⇒ 수직과 수평으로만 따짐
- 버튼 동작의 룰 case by case → if문 사용하겠네
- 1, 4, 7 : 무조건 왼손
- 3, 6, 9 : 무조건 오른손
- 2, 5, 8, 0 : 가장 가까운 거리 → 거리 계산 (자주 사용되겠다)
- 거리가 같을 때
- 입력의 어느 손 잡이냐가 중요 → hand 정보 필요
- 거리가 다를 때
- 거리가 짧은 것을 선택
- 거리가 같을 때
- solution 함수 제출
- 입력
- numbers
- 누를 숫자 리스트 [1, 3, 4, 5, 8, 2, 1, 4, 5, 9, 5]
- 0~9 정수만 딱 들어옴
- 갯수는 1~1000개
- hand
- 어느손잡이(문자열)→ “left”, “right”
- numbers
- 출력
- answer
- 문자열
- 입력 number에 해당하는 버튼 누른 손(L/R)+ 공백없이 문자열!
- answer
- 이슈
- 핸드폰 키패드를 어떻게 코드화할 것인가
- 코드화 + 자표화가 관건
- 거리: 직교거리(가로거리 얼마 + 세로 거리 얼마)
- 대각선 거리를 계산하지 않음
- 가로 거리의 차이 + 세로 거리의 차이
- 2개의 버튼 사이의 거리 빈번하게 계산 (여러번 사용될 것… ) → 1개의 case에서도 여러 번 활용이 필요해서 ⇒ 함수로 만들어보자
- 개인의 선택 → 2개의 버튼 사이의 거리(직교 거리) 계산하는 함수 만들 것
- 세팅
- 위치 & 거리 계산
- 키패드 추상적인 부분에 대한 코드화 : 좌표화!!!!!
- 주어진 키패드에 코드화 → 좌표, dict
- 초기값 *, #를 포함해서 입력으로 숫자 0 ~ 9 모든 버튼이 대상
- 키값들을 문자열로, 값(위에 설정한 좌표값) ⇒ 완전히 개인의 취향(좌표 다르게 잡아도 됨)
- 핵심 키패드라는 것을 코드화 하는 것
#키패드 딕셔너리로 코드화 key_pad = { "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], "*":[3,0], "0":[3,1], "#":[3,2], } key_pad - 참고) 앞에서처럼 리스트 중심으로 정수 인덱스를 기반으로 한다면
# 키패드 리스트로 정수인덱스 활용해 코드화 # 참고) 앞에서처럼 리스트 중심으로 정수 인덱스를 기반으로 한다면 key_pad_list = ["1","2","3","4".....] pos_x = [ 0, 0, 0, 1,......] pos_y = [0, 1, 2,0,,,,,,,] pos = [ [0,0], [0,1], [0,2], [1,0].,,,, ]
- 주어진 키패드에 코드화 → 좌표, dict
- 키패드 추상적인 부분에 대한 코드화 : 좌표화!!!!!
- 위치 & 거리 계산
- 예) * 위치에 있을 때 좌표값은?
key_pad["*"][0], key_pad["*"][1] #멀티 할당 사용 가능 temp_x, temp_y = key_pad["*"] print(temp_x, temp_y) - 코드의 흐름 → 가장 큰 틀 : 누를 버튼은 롤링하는 것
for num in numbers: if 1/4/7: 무조건 왼손 elif 3/6/9: 무조건 오른손 else/elif 2/5/8/0: 양 손에서 이 버튼 사이의 거리 계산 # 함수로 할 것 (입력 : 손의 위치,누를 버튼) --> 출력 : 수직거리 D_L( 왼손 거리), D_R(오른손 거리) if 거리가 다를 떄: 짧은 거리의 손을 선택!!! else: #거리 같을 때 입력변수 hand를 참조해서 사용 - 추가적인 기능: 거리 구하는 부분 —> 여러번 사용될 것 같아서 함수로 만들 것
- 2, 5, 8, 0 일 때만 불러서 사용하면 됨
- 입력: 2개 키패드 위치(눌러야할 키패드, 손 위치)
- 기능: 입력 2개 위치상 거리 (직선거리, L2, 맨하탄 거리 etc) 계산
- 출력: 계산 결과
- 1-2, 2-1 : 어떤 숫자이든 다 양수로 나와야함
- 음수여도 최종적으로 양수가 나와야 ⇒ 절대값 사용!
- abs() 함수 사용해도 된다.
#거리 구하는 부분 —> 여러번 사용될 것 같아서 함수로 만들 것 def get_distance(number, pos): # 입력으로 받은 number, pos 변수 : 이 함수 내에서만 생존!!! key_pad = {"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],"*":[3,0], "0":[3,1], "#":[3,2],} #명시적으로 눌러야 할 버튼, 위치 버튼 : 문자열로 형 변환 number = str(number) pos = str (pos) # 1) 눌러야 할 버튼의 좌표값 & 파이썬 멀티 할당 x_number, y_number = key_pad[number] # 2) 손의 위치 버튼의 좌표값 & 파이썬 멀티 할당 x_pos, y_pos = key_pad[pos] #3) 1번하고 2번하고 수직 거리 : abs/ if/...... abs_dis = abs(x_number - x_pos) + abs(y_number-y_pos) # 최종 출력!!!! return abs_dis

def get_distance(number, pos):
key_pad = {"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],"*":[3,0], "0":[3,1], "#":[3,2],}
number = str(number)
pos = str(pos)
x_number, y_number = key_pad[number]
x_pos, y_pos = key_pad[pos]
abs_dis = abs(x_number - x_pos) + abs(y_number-y_pos)
return abs_dis
def solution(numbers, hand):
answer = ''
#------------------------------
# 1-1) 필요한 변수들에대한 세팅 : 초기화!!!
left_pos = "*"
right_pos ="#"
# 1-2) 필요한 변수 세팅
# : 무슨손 잡이인지 left/right으로 입력 -> 이걸 L/R로 사용해야함
if hand =="left":
hand = "L"
else: # --> 오른손 잡이...
hand = "R"
#------------------------------
# 2) 본격적인 할 일 : 눌러야할 버튼 롤링!!!
for num in numbers:
# 2-1) 무조건 왼손 : 1/4/7
if num in [1,4,7]: #if (num ==1) or (num==4) or (num==7):
answer += "L"
# ++ 왼손으로 눌렀으니,,왼손 위치 갱신!!!!
left_pos = num
# 2-2) 무조건 오른손 : 3/6/9
elif num in [3,6,9]:
answer += "R"
# +++ 오른손을 눌렀으니,,,오른손의 위치 갱신!!
right_pos = num
# 2-3) 중간 따지자 : 2/5/8/0
#else/elif
elif num in [2,5,8,0]:
# 각 손과 num사이의 거리 계산!!!!! --> 비교!!!:담당할 변수 만들자.
dis_left = get_distance(num, left_pos)
dis_right = get_distance(num, right_pos)
# 2-3-1) 거리가 왼쪽이 짧을 떄
if dis_left < dis_right:
answer += "L"
left_pos = num
# 2-3-2) 거리가 오른쪽이 짧을 때
elif dis_left > dis_right:
answer += "R"
right_pos = num
# 2-3-3) 거리가 동일할 때!
elif dis_left == dis_right:
answer += hand
# 위치를 갱신을 해야하는데,,,무슨 손 잡이냐에 따라서,,,
if hand =="R":
right_pos = num
elif hand =="L":
left_pos = num
#------------------------------
return answer
'파이썬 > 코딩테스트' 카테고리의 다른 글
| [파이썬] 코딩테스트 10 구현_주차문제 (4) | 2025.08.06 |
|---|---|
| [파이썬] 코딩테스트 08 자료형_마라톤 (3) | 2025.08.06 |
| [파이썬]코딩테스트 06 정렬_파일명 (6) | 2025.08.05 |
| [파이썬]코딩테스트 05 정렬_실패율 (0) | 2025.08.05 |
| [파이썬]코딩테스트 04 정렬_기본정리 (2) | 2025.08.05 |