CS/알고리즘 문제풀이

프로그래머스 LV1 - 키패드 누르기

AI쟁이J 2022. 8. 15. 00:09

처음 프로그래머스 사이트를 알고 1단계 가장 맨 위의 문제였다. 보자마자 빤스런 박았다. 그리고 1단계를 이 문제를 제외하고 모두 풀었다... 부딪혀야지 어쩌겠는가? 그리고

 

keypad = [[1,2,3],[4,5,6],[7,8,9],['*',0,'#']]

def get_index(n):
    for idx1, i in enumerate(keypad):
        for idx2, j in enumerate(i):
            if j == n:
                return [idx1, idx2]
    return None

def solution(numbers, hand):

    left = ['*']
    right = ['#']
    ans = []
    
    for finger in numbers:
        if finger in [1,4,7]:
            left.append(finger)
            ans.append("L")
            
        elif finger in [3,6,9]:
            right.append(finger)
            ans.append("R")
            
        elif finger in [2,5,8,0]:
            now_left = get_index(left[-1])
            now_right = get_index(right[-1])
            ld = sum([abs(x-y) for x,y in zip(now_left, get_index(finger))]) # left distance
            rd = sum([abs(x-y) for x,y in zip(now_right, get_index(finger))]) # right distance
            
            if ld == rd:
                if hand == "right":
                    right.append(finger)
                    ans.append("R")
                elif hand == "left":
                    left.append(finger)
                    ans.append("L")
            elif ld < rd:
                left.append(finger)
                ans.append("L")
            elif rd < ld:
                right.append(finger)
                ans.append("R")

    return "".join(ans)

 

1단계 문제 중 가장 긴 코드와 함께 1단계를 졸업했다.

순전히 내 힘으로 풀었다기엔 가장 위의 함수는 구글의 도움을 받았다.

https://hashcode.co.kr/questions/10079/%ED%8C%8C%EC%9D%B4%EC%8D%AC-2%EC%A4%91-%EB%A6%AC%EC%8A%A4%ED%8A%B8-%EC%9D%B8%EB%8D%B1%EC%8A%A4-%EA%B0%92-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0-%EC%A7%88%EB%AC%B8

 

 

 

파이썬 2중 리스트 인덱스 값 가져오기 질문

아래 에 puzzle 리스트에서 n 에 입력되는 값 의 인덱스를 찾아내고 싶은데 첫 번째 리스트의 1,2,3,4 이후에는 에러가 자꾸 발생합니다. index = puzzle[i].index(n) 이부분이 이상한 것 같은데 어떻게 고쳐

hashcode.co.kr

나는 keypad를 [1,2,3] 가장 윗 줄을 0번째 원소로 하는 2중 리스트로 두고 접근했기에 keypad[0][0] 과 keypad[0][3] 의 거리 차이는 3이다! 이런 느낌으로 접근하려 했다. 그런데 이 리스트 값을 가져올 방법을 도저히 못 찾겠어서 도움을 받았고 덕분에 저 함수 코드를 천천히 뜯어먹고 소화해서 사용했다. 봐줘잉

 

풀이 접근은 먼저 get_index() 함수를 따로 지정하고 풀이에 들어간다.

 

 

    left = ['*']
    right = ['#']
    ans = []
    
    for finger in numbers:
        if finger in [1,4,7]:
            left.append(finger)
            ans.append("L")
            
        elif finger in [3,6,9]:
            right.append(finger)
            ans.append("R")

 

left와 right는 다시 돌아올 일 없는 첫 위치를 스택에 넣은 채로 시작한다.

그리고 1,4,7 왼손과 3,6,9 오른손은 간단하게 구현한다. 저 경우 해당 키를 현재 left, right 위치에 넣으며 답안도 작성하는 것.

 

 

elif finger in [2,5,8,0]:
    now_left = get_index(left[-1])
    now_right = get_index(right[-1])
    ld = sum([abs(x-y) for x,y in zip(now_left, get_index(finger))]) # left distance
    rd = sum([abs(x-y) for x,y in zip(now_right, get_index(finger))]) # right distance

 

그러면 이제 이 문제의 핵심인 2,5,8,0이 나타난다. 쫄지 말자 우리에겐 index 위치를 구하는 함수가 있다

일단 현재 손꾸락의 위치를 left 스택의 가장 끝자락에서, right 스택의 가장 끝자락에서 구해서 get_index()로 위치를 반환한다.

거리는 내가 애용하는 zip()을 사용한 리스트 컴프리헨션으로 구했다. 각 인덱스 [0,1] 과 [0,3] 이라면 ([0 - 0] [1- 3]) 꼴로 묶고 이 각 원소를 x-y 를 통해 거리를 구하는 것이다. 거리기 때문에 abs()로 절댓값으로 감싼다.

 

 

            if ld == rd:
                if hand == "right":
                    right.append(finger)
                    ans.append("R")
                elif hand == "left":
                    left.append(finger)
                    ans.append("L")
            elif ld < rd:
                left.append(finger)
                ans.append("L")
            elif rd < ld:
                right.append(finger)
                ans.append("R")

 

사실 이 거리들만 구하면 이후는 쉽다. 오른손잡이, 왼손잡이 여부에 따라 if문을 계속 써서 케이스를 나눠주면 된다.

이 케이스별로 ans에 답안을 계속 작성한 후, return 값으로는 이 ans 리스트를 join()을 통해 문자열로 내면 끝.

 

다른 사람의 풀이 보면서 설마 이 문제도 한줄코드 쓴 멋진 형님들이 있으면 어쩌나 했다.

다행히도 그딴거 없이 다들 엄청나게 긴 코드 썼더라. 쉬운 문제에나 간지나는 1줄 풀이가 가능한 것이었다.