프로그래머스/LV2

[프로그래머스 Lv2, python] - 후보키

chyam_eun 2025. 4. 30. 11:32

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

 

프로그래머스

SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

from itertools import combinations

def check(li, relation, col, row):
    new_list, res_list = [], set() # 값 비교할 리스트, 열 번호 저장할 리스트
    iswrong = 0 # 중복이 있는지?
    for r in range(row):
        tmp = []
        for i in li:
            tmp.append(relation[r][i])
            res_list.add(i)
        if tmp not in new_list:
            new_list.append(tmp)
        else:
            iswrong = 1
    if iswrong == 1:
        return []
    return res_list
            
def solution(relation):
    col, row = len(relation[0]), len(relation) # 열, 행
    li = [i for i in range(col)] # 열 번호 저장
    pk = [] # 후보키 저장
    for i in range(1, col+1): # 후보키가 1개일때 ~ col개일때
        new_li = list(combinations(li,i)) # 가능한 조합
        for new in new_li: 
            res_list = check(new, relation, col, row)
            if not res_list:
                continue
            # res_list가 기존 후보키의 상위 집합이면 안 됨
            tmp_set = set(res_list)
            if any(set(p).issubset(tmp_set) for p in pk): # tmp_set 중에 pk의 값이 포함되는게 하나라도 있으면 넘어가기
                continue
			# 포함되는게 없을 때
            # 기존 후보키 중 res_list에 포함되는 (상위 후보키) 제거
            pk = [p for p in pk if not tmp_set.issubset(set(p))]
            pk.append(res_list)

    return len(pk)

issubset()은 하위집합인지 알려주는 함수이고, issuperset()은 상위집합인지 알려주는 함수이다.

any()는 하나라도 True이면 True이다.