Algorithms/프로그래머스

[프로그래머스] 키패드 누르기 (Python 파이썬)

떼닝 2022. 6. 30. 06:58

2020 카카오 인턴십 Level 1 키패드 누르기

문제 링크 : https://programmers.co.kr/learn/courses/30/lessons/67256

 

코딩테스트 연습 - 키패드 누르기

[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"

programmers.co.kr

💡 아이디어

💡 문제를 어떤 방식으로 해결하려 했는지 그 과정을 적어주세요. 초기에 접근한 방법과 최종 접근이 차이가 없으면 한개만 적어도 됩니다.

초기 접근

모든 키패드를 하나의 2차원 배열에 넣고... dx dy로 이동을 시켜볼까... 생각했다.

그러려면 매번 현재 위치의 숫자를 배열에서 찾아야되고... 뭐 그런...

최종 접근

근데 사실 위에 거랑 큰 차이는 없다. 배열에 안 넣었다 뿐... 비교해야할 때마다 위치를 검색하고 해야 한다.

분명 이것보다 쉬운 방법이 있었을 것 같긴 한데... 조금 복잡하더라도 레벨 1이라서 생각나는대로 해봤다.

실제로 시험 볼 때는 또 다른 방법을 생각할 겨를이 없으니깐...!

 

왼손이 입력 가능한 숫자와 오른손이 입력 가능한 숫자를 따로 지정해뒀다.

그 리스트에 존재하지 않는 값일 경우,

그러니깐 왼손과 오른손이 모두 입력할 수 있는 2580 중 하나가 들어왔을 경우 위치를 비교하게 된다.

해당 숫자의 위치는 키패드에서의 행열값으로 정해지게 되는데, 배열에 직접 넣진 않고 계산을 한다.

행값은 해당 숫자-1을 3으로 나눴을 때의 몫, 열값은 3으로 나눴을 때의 나머지.

위치 비교는 그냥 행값끼리의 거리 그리고 열값끼리의 거리 계산해서 비교.

 

효율이 조금 떨어지는 건 매번 위치를 계산해서 넣어주기 때문인 것 같다.

조건이 되게 여기저기서 들어가게 되어서 스파게티 식 코드가 되어버린...

나중에 한참 뒤에 다시 풀 땐 조금 더 깔끔하게 풀 수 있길 바라며...!

 

📋 사용 스펙

💡 어떤 알고리즘 또는 기법을 사용해 문제를 해결했는지 알려주세요

 

👨🏻‍💻 👩‍💻 코드

# 값 주어지면 해당 값의 위치를 tuple 형태로 반환
def getLocation(num):
    if num == '#':
        return (3, 2)
    if num == '*':
        return (3, 0)
    if num == 0:
        return (3, 1)
    
    return ((num-1)//3, (num-1)%3)

# 현재 위치 숫자값으로 확인 위해 location으로 표현되어있던 것 값으로 변경
# *은 10, 0은 11, 1은 12로 나타남
def Loc2Num(loc):
    return loc[0]*3 + loc[1] + 1

def solution(numbers, hand):
    answer = ''
    
    # 왼손이 입력 가능한 값, 오른손이 입력 가능한 값을 저장한 리스트 따로 선언
    leftnums=[1, 4, 7, '*']
    rightnums = [3, 6, 9, '#']

    # 현재 위치로 초기화. 왼손은 *, 오른손은 #
    leftnow = getLocation('*')
    rightnow = getLocation('#')
    
    # 입력받은 numbers에서 숫자 하나씩 돌면서 진행
    for num in numbers:
        # 왼손으로만 입력 가능할 경우
        # 왼손의 위치 갱신 후 최종적으로 return할 문자열에 L 추가
        if num in leftnums:
            leftnow = getLocation(num)
            answer+='L'
        # 오른손으로만 입력 가능한 경우
        # 오른손의 위치 갱신 후 최종적으로 return할 문자열에 R 추가
        elif num in rightnums:
            rightnow = getLocation(num)
            answer += 'R'
        # 왼손과 오른손 모두 입력 가능한 키인 경우
        else:
            # num의 위치 받아서
            numLoc = getLocation(num)
            
            # 왼손, 오른손의 위치와 거리 계산
            left_num = abs(numLoc[0]-leftnow[0]) + abs(numLoc[1]-leftnow[1])
            right_num = abs(numLoc[0]-rightnow[0]) + abs(numLoc[1]-rightnow[1])
            
            # 왼손에서의 위치, 오른손에서 위치를 비교해서
            # 왼손이 더 가까이 있으면 왼손 선택,
            # 오른손이 더 가까이 있으면 오른손 선택
            if left_num < right_num:
                leftnow = getLocation(num)
                answer += 'L'
            elif left_num > right_num:
                rightnow = getLocation(num)
                answer += 'R'
            # 거리가 같을 경우 왼손잡이인지 오른손잡이인지 판단 후 이동
            else:
                if hand=="left":
                    leftnow = getLocation(num)
                    answer += 'L'
                else:
                    rightnow = getLocation(num)
                    answer += 'R'               

    return answer