https://school.programmers.co.kr/learn/courses/30/lessons/159994

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

프로그래머스 코딩테스트 1단계에 수록되어 있는 '카드 뭉치' 문제를 풀었습니다. 다른 사람의 풀이와 비교해보니 제가 조금 독특하게 풀었더라구요. 제 코드가 좀 지저분하긴 하지만 남들과 다른 아이디어로 푼 게 마음에 들어 sorted 문법 정리할 겸 풀이과정을 작성해보고자 합니다.

 

 

우선 제출한 답안은 다음과 같습니다.

def solution(cards1, cards2, goal):
    cards1_sorted = sorted(enumerate(cards1), 
    	key = lambda x: (goal.index(x[1]) if x[1] in goal else len(goal) + 1))
    cards2_sorted = sorted(enumerate(cards2), 
    	key = lambda x: (goal.index(x[1]) if x[1] in goal else len(goal) + 1))
                           
    index_1 = [index for index, value in cards1_sorted]
    index_2 = [index for index, value in cards2_sorted]
    
    if index_1 != sorted(index_1) or index_2 != sorted(index_2):
        return "No"
    else:
        return "Yes"
정확성: 100.0, 합계: 100.0 / 100.0

 

하나씩 쪼개어 정리해 보겠습니다.

테스트케이스의 2번째 예시로 설명해 보겠습니다.

 

 

 

1. 먼저, cards1과 cards2에 enumerate() 함수를 이용해서 (인덱스, 카드)값이 되도록 만들어 줍니다. list()함수를 씌워 결과값을 눈으로 확인하면 다음과 같습니다.

cards1 = ["i", "water", "drink"]
cards2 = ["want", "to"]	
goal = ["i", "want", "to", "drink", "water"]	

list(enumerate(cards1))
# [(0, 'i'), (1, 'water'), (2, 'drink')]

list(enumerate(cards2))
# [(0, 'want'), (1, 'to')]

 

 

 

 

2. 저는 이렇게 추출한 이뉴머레이트 결과값을, sorted()를 이용해서 정렬을 해줄 거에요. 이 때 정렬을 해 주는 기준으로 goal을 넣어 주어서, goal에 있는 순서대로 정렬되도록 하겠습니다.

cards1_sorted = sorted(enumerate(cards1), key = lambda x: goal.index(x[1])
cards2_sorted = sorted(enumerate(cards2), key = lambda x: goal.index(x[1])

cards1_sorted
# [(0, 'i'), (2, 'drink'), (1, 'water')]

cards2_sorted
# [(0, 'want'), (1, 'to')]

 

key = lambda x: goal.index(x[1]) 와 같이 정렬 조건을 걸어줌으로써, cards1의 이뉴머레이트 결과값의 인덱스 1번 벨류가 goal에 어떤 순서대로 있느냐?를 기준으로 정렬한 값을 반환하도록 하였습니다. 결과값을 확인해보니 cards2는 그대로이지만 cards1은 drink가 앞으로 온 것을 확인할 수 있습니다. 그런데 이 문법에는 문제가 있습니다. 만약 cards1에 있는 단어가 goal에 없다면 어떻게 될까요?

 

2 - (1)

cards1 = ["i", "water", "drink", "apple"]
cards1_sorted = sorted(list(enumerate(cards1)), key = lambda x: goal.index(x[1]))

# ValueError: 'apple' is not in list

 

cards1에 'apple'을 추가해 보니, 벨류 에러가 발생합니다. 따라서 이렇게 없는 값이 있을 경우에는 cards1_sorted의 맨 뒤에다가 값을 추가해주도록 조건을 걸어주겠습니다.

cards1_sorted = sorted(list(enumerate(cards1)), 
             	   key = lambda x: (goal.index(x[1]) if x[1] in goal else len(goal) + 1))
cards2_sorted = sorted(list(enumerate(cards2)), 
            	   key = lambda x: (goal.index(x[1]) if x[1] in goal else len(goal) + 1))

 

만약 x[1]이 goal에 있다면 기존대로 정렬을 하고, 없다면 뒤에 추가하도록 if else 구문을 사용하여 조건을 걸어줬습니다. 이 부분은 챗지피티의 도움으로 완성할 수 있었습니다^_ㅠ 엄청 직관적인 문법이 아닌것 같긴 합니다만 그래도 자주 사용해서 자유자재로 구사할 수 있도록 하려고 합니다.

 

다시 apple이 없었던 원래의 예시문제로 돌아가서 계속해서 설명해보겠습니다.

 

 

 

 

3.

index_1 = [index for index, value in cards1_sorted]
index_2 = [index for index, value in cards2_sorted]


index_1
# [0, 2, 1]
index_2
# [0, 1]

 

 

이제 cards1_sorted와 cards_2sorted에서 인덱스만 뽑아서 깔끔한 리스트 index_1, index_2로 뽑아냅니다. 저는 이 index 리스트의 결과값이 0-2-1처럼 순서에 맞지 않을 경우 카드를 앞에서부터 차례로 사용하는 조건에 어긋난다는 점을 발견했습니다. 

 

따라서 index_1, index_2가 오름차순으로 정렬되어 있다면 "Yes"를, 그렇지 않다면(순서가 뒤죽박죽이라면) "No"를 리턴하도록 함수를 작성했습니다.

def solution(cards1, cards2, goal):
    cards1_sorted = sorted(enumerate(cards1), key = lambda x: (goal.index(x[1]) if x[1] in goal else len(goal) + 1))
    cards2_sorted = sorted(enumerate(cards2), key = lambda x: (goal.index(x[1]) if x[1] in goal else len(goal) + 1))

    index_1 = [index for index, value in cards1_sorted]
    index_2 = [index for index, value in cards2_sorted]
    
    if index_1 != sorted(index_1) or index_2 != sorted(index_2):
        return "No"
    else:
        return "Yes"

 

 

 

최근에 sorted() 함수에 대해서 리뷰를 했으며 특히 key 뒤에 lambda 함수를 어떻게 활용할 수 있는 지 여러번 살펴보았기 때문에 위와 같은 아이디어로 문제를 풀 수 있었습니다. 다른 사람의 풀이를 확인해보니 이런 방식으로 풀이를 하신 분은 찾아보기 어려웠고 더 짧고 깔끔하고 반듯하게 푸신 분이 많아서 존경스러웠습니다! 아주 깔끔한 코드는 아니지만 그래도 재밌는 아이디어로 풀어낸 점을 스스로 높게 평가하고자 합니다 ^_^!

 

 

 

감사합니다.

 

 

 

+ Recent posts