ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 46. 후보키
    코딩 테스트/Level 2 2020. 8. 29. 12:52
    반응형

    후보키
    2019 KAKAO BLIND RECRUITMENT
    1798명 완료

    풀이 자체는 어렵지 않으나, 
    파이썬에서 zip의 사용법을 모르면
    코딩이 조금 까다롭다. 

    https://programmers.co.kr/learn/courses/30/lessons/42890

     

    코딩테스트 연습 - 후보키

    [["100","ryan","music","2"],["200","apeach","math","2"],["300","tube","computer","3"],["400","con","computer","4"],["500","muzi","music","3"],["600","apeach","music","2"]] 2

    programmers.co.kr

    머리는 적게 쓰고 컴퓨터를 많이 쓰는
    훌륭한(?) 전수조사(brute force) 알고리듬을 만들자. 

    나의 머리는 소중하니까..
    많이 부려먹으려고 비싼 컴퓨터 산 거 아님?

    각 칼럼의 조합 즉 nCr을 r = 1 ~ len(relation)까지 만들고.. 

    각 조합의 유일성을 확인하고.. 
    (파이썬에는 딕셔너리나 집합을 사용하면 편하다..)

    유일성을 통과한 조합을 A,
    유일성과 최소성 확인을 이미 통과한 조합들을 B 라할 때 
    B는 A의 부분 집합이 아니어야 한다. 

    그런데 zip의 사용법을 잊어버려서 한참을 헤맸다...
    8개월 만에 코딩이라..
    zip함수를 만들까까지 고민했다.

    list 2개를 인자로 넣으면 잘 작동된다. 

    list(zip([1, 2, 3], [4, 5, 6]))
    [(1, 4), (2, 5), (3, 6)]

    list 2개를 1개의 list로 묶어서 zip에 보내면 작동하지 않는다 ㅠ,.ㅠ 

    list(zip([[1, 2, 3], [4, 5, 6]]))
    [([1, 2, 3],), ([4, 5, 6],)]

    이럴 때 *를 이용하면 포장을 하나 벗겨준다.. 

    list(zip(*[[1, 2, 3], [4, 5, 6]]))
    [(1, 4), (2, 5), (3, 6)]

    이제 떠올랐으니 일사천리 코딩....

    def solution(relation):
        from itertools import combinations
        r = [tuple(each) for each in zip(*relation)]
        combies = [combi for i in range(len(r)) for combi in combinations(r, i + 1)]
        candidate_keys = []
        for combi in combies:
            zip_elements = list(zip(*combi))
            if len(zip_elements) == len(set(zip_elements)):  # 유일성 확인
                for candidate_key in candidate_keys:  # 최소성 확인. 지저분...
                    for element in candidate_key:
                        if element not in combi:
                            break
                    else:  # 브레이크가 없었다 = 모든 원소가 다 들어 있었다 = 최소성에서 탈락
                        break  # 탈락한 분들은 브레이크
                else:
                    candidate_keys.append(combi)
        return len(candidate_keys)
    

    일단 이렇게 풀어봤는데... 최소성 확인하는 부분이 좀 지저분...

    11번 테스트 케이스에서 걸려 버렸다.. 
    11번이 이런 케이스가 아닐까?

    [["a", "a"], ["b", "b"]]  # 2 가 나와야 하는데 1 이... 

    1번 2번 컬럼 모두 고유 키로 사용해도 되지만 위 코드에서는 이를 중복으로 본다.. 

    예를 들자면 이름과 전공이 art 인 사람.
    이름과 전공이 music 인 사람이 있을 때,
    이름을 고유 키로, 전공을 고유 키로 해도 된다.. 

    그래서 직접 비교하지 않고 인덱스를 이용하도록 코드를 고쳤다.. 
    지저분한 부분도 같이 수정.

    def solution(relation):
        from itertools import combinations
        r = [tuple(each) for each in zip(*relation)]
        combies = [set(combi) for i in range(len(r)) for combi in combinations(range(len(r)), i + 1)]
        candidate_keys = []
        for combi in combies:  # combi에는 (실제 원소?가 아닌) 숫자 인덱스의 조합만 들어있다..
            elements = [r[index] for index in combi]  # 실제 (원소?들의) 조합을 만들기 위해서 리스트를 하나..
            zip_elements = list(zip(*elements))
            if len(zip_elements) != len(set(zip_elements)):  # 유일성 테스트
                continue
            for candidate_key in candidate_keys:  # 최소성 테스트
                if candidate_key.intersection(combi) == candidate_key:
                    break
            else:
                candidate_keys.append(combi)
        return len(candidate_keys)
    테스트 1 〉	통과 (0.07ms, 10.8MB)
    테스트 2 〉	통과 (0.08ms, 10.7MB)
    테스트 3 〉	통과 (0.08ms, 10.6MB)
    테스트 4 〉	통과 (0.08ms, 10.8MB)
    테스트 5 〉	통과 (0.10ms, 10.7MB)
    테스트 6 〉	통과 (0.05ms, 10.9MB)
    테스트 7 〉	통과 (0.05ms, 10.8MB)
    테스트 8 〉	통과 (0.05ms, 10.6MB)
    테스트 9 〉	통과 (0.09ms, 10.8MB)
    테스트 10 〉	통과 (0.11ms, 10.8MB)
    테스트 11 〉	통과 (0.13ms, 10.8MB)
    테스트 12 〉	통과 (0.62ms, 10.6MB)
    테스트 13 〉	통과 (0.20ms, 10.8MB)
    테스트 14 〉	통과 (0.08ms, 10.7MB)
    테스트 15 〉	통과 (0.07ms, 10.7MB)
    테스트 16 〉	통과 (0.08ms, 10.7MB)
    테스트 17 〉	통과 (0.08ms, 10.7MB)
    테스트 18 〉	통과 (1.06ms, 10.7MB)
    테스트 19 〉	통과 (0.70ms, 10.7MB)
    테스트 20 〉	통과 (1.15ms, 10.6MB)
    테스트 21 〉	통과 (0.82ms, 10.9MB)
    테스트 22 〉	통과 (0.62ms, 10.8MB)
    테스트 23 〉	통과 (0.09ms, 10.7MB)
    테스트 24 〉	통과 (0.74ms, 11MB)
    테스트 25 〉	통과 (1.00ms, 10.8MB)
    테스트 26 〉	통과 (0.84ms, 10.9MB)
    테스트 27 〉	통과 (0.19ms, 10.5MB)
    테스트 28 〉	통과 (0.20ms, 10.7MB)

    다행히 통과...

    반응형
Designed by Tistory.