불량 사용자 (Lv.3) | Python

krystal·2022년 6월 25일
0

2019 카카오 개발자 겨울 인턴십 문제 (3. 불량 사용자) | 프로그래머스

불량 사용자

문제

개발팀 내에서 이벤트 개발을 담당하고 있는 "무지"는 최근 진행된 카카오이모티콘 이벤트에 비정상적인 방법으로 당첨을 시도한 응모자들을 발견하였습니다.

이런 응모자들을 따로 모아 불량 사용자라는 이름으로 목록을 만들어서 당첨 처리 시 제외하도록 이벤트 당첨자 담당자인 "프로도" 에게 전달하려고 합니다.

 이 때 개인정보 보호을 위해 사용자 아이디 중 일부 문자를 '*' 문자로 가려서 전달했습니다. 
가리고자 하는 문자 하나에 '*' 문자 하나를 사용하였고 아이디 당 최소 하나 이상의 '*' 문자를 사용하였습니다.

"무지"와 "프로도"는 불량 사용자 목록에 매핑된 응모자 아이디를 제재 아이디 라고 부르기로 하였습니다.

이벤트 응모자 아이디 목록이 담긴 배열 user_id와 불량 사용자 아이디 목록이 담긴 배열 banned_id가 매개변수로 주어질 때, 당첨에서 제외되어야 할 제재 아이디 목록은 몇가지 경우의 수가 가능한 지 return 하도록 solution 함수를 완성해주세요.


흐름 생각하기

1. 제재 아이디가 '*'가 포함되어있으니까 다른 아이디랑 헷갈리는 경우의 수가 생긴다.
	=> 그런 경우의 수를 반환하는 함수를 만들어야한다.
2. 아이디가 중복되는 경우는 없음
그러면 일단 문자열 길이 알아야하고, *를 제외한 문자들을 체크해야할 듯

두 번째 출력 예시의 경우까지는 다 뽑아냈는데 경우의 수를 어떻게 세느냐가 관건인듯

▲ 처참한 흔적

근데 처음부터 코드를 다시 짜야할 것같다.
*를 다 없애다보니까 비교하기가 꽤 어려워졌다 (하...ㅠ)


입출력 1,2,3에서의 경우의 수에 들어갈 id는 모두 찾을 수 있게 되었다.
이제 중요한 건 경우의 수를 어떻게 세느냐이다.

어거지로 맞췄더니 다음과 같은 결과가 나왔다
하 ㅠㅠ 경우의 수 그거 어떻게 맞추는건데.. 딕셔너리로 하고싶었는데 거기서 또 오류가 생겼다. 일단 삽질한 흔적의 코드는 다음과 같다.

def solution(user_id, banned_id):
    answer = 0
    not_in_list=False
    answer = 0
    case=[]
    case_clear = True
    breakpoint=False
    for i in range(len(banned_id)):
        for k in range(len(user_id)):
            if len(banned_id[i]) == len(user_id[k]):
                if not banned_id[i] in case:
                    case.append([banned_id[i]])
                for j in range(len(user_id[k])):
                    if banned_id[i][j]=='*':
                        continue
                    elif banned_id[i][j]== user_id[k][j]:
                        continue
                    else:
                        case_clear=False
                        break
                if case_clear:
                    for x in range(len(case)):
                        if banned_id[i] in case[x]: 
                            case[x].append(user_id[k])
                            break
                else:
                    case_clear = True
    
    total_case=[]
    for n in range(len(case)):
        if len(case[n]) == 1:
            continue
        else:
            total_case.append(list(set(case[n])))
    
    for k in range(len(total_case)-1):
        for i in range(len(total_case[k])):
            if total_case[k][i] in total_case[k+1]:
                total_case[k+1][total_case[k+1].index(total_case[k][i])]=''
    
    for x in range(len(total_case)):
        for y in range(len(total_case[x])):
            if not total_case[x][y] in banned_id:
                if total_case[x][y]=='':
                    breakpoint=True
                    break
        if breakpoint:
            if len(total_case[x])>2:
                answer+=1
            breakpoint=False
        else:
            if len(total_case[x])>2:
                answer+=2
    if len(set(banned_id)) != len(banned_id):
        answer-=(len(banned_id)-len(set(banned_id)))*2
    return answer

최종코드

결국 몇 시간을 투자해도 해결하지 못해서 구글링을 해보았는데, 순열 함수를 사용해서 풀면 매우 간단했던 문제였다. (도대체 난 무엇을 위해..🙊) banned_id의 문자열 길이를 보는 건 다들 비슷한가보다.
구한 banned_id의 문자열의 길이를 순열 함수의 매개변수로 써서 경우의 수를 만들어주고 차례로 제끼는 방식인가보다. 그리고 정규표현식을 쓰면 바로 해결할 수 있었던..... 알고리즘을 풀다보면 현타가 절로 온다

나중에 set을 이용해서 비교를 하지않으면 순서에 따라 또 다른 경우로 인식하기 때문에 set을 사용해서 비교하는 듯 하다. 근데 이럴거면 sort도 되지않나? tuple때문인가? => 해본 결과 상관은 없는듯. 그저 중복을 처리한다는게 중요한 듯하다.

점수가 나올 때 캡쳐를 하지못해서 빈공간으로 캡쳐되었다.
가형 29번 4점짜리 몰라서 몇 시간 고민하다가 답지보고 얼레벌레 맞춘 느낌이라 찝찝하다.. ㅎ


짚고 넘어가야할 함수 (복습)

itertools.permutations(iterable, r=None)
반복 가능 객체 중에 r개를 선택한 순열을 반환하는 함수.

(출처 : https://wikidocs.net/109282)

from itertools import permutations 를 통해 사용한다.

profile
https://source-coding.tistory.com/

0개의 댓글