# 두글자씩 끊은 다중집합 만들기
def make_set(str):
str_set = []
for i in range(len(str)-1):
temp = str[i:i+2] # 두글자씩 끊기
if temp.isalpha(): # 글자에 기호나 숫자 없다면
str_set.append(temp) # 추가
return str_set
def solution(str1, str2):
str1 = str1.upper() # 대소문자 차이 무시하므로 둘다 대문자로 변환
str2 = str2.upper()
str1_set = make_set(str1) # 각 문자열 다중집합으로 만들기
str2_set = make_set(str2)
intersection = 0 # 교집합 계산
for i in str1_set:
if i in str2_set[:]:
intersection += 1
str2_set.remove(i) # 중복 방지를 위해 삭제
union = len(str1_set) + len(str2_set) # 합집합 계산 (str2_set는 str1_set과의 교집합 원소들이 제거된 상태)
if union == 0: # 합집합 0인경우 1로 처리 -> 따라서 65546 반환
return 65536
else:
return int(intersection / union * 65536)
처음 코드
import re
def solution(str1, str2):
def comb(s) :
temp = []
s = s.lower()
is_str = re.compile('[a-z]+')
for i, j in zip(s[:-1], s[1:]) :
i_str = is_str.match(i)
j_str = is_str.match(j)
if i_str == None or j_str == None:
continue
else :
temp.append(i+j)
return temp
com_1 = comb(str1)
com_2 = comb(str2)
not_union = len(com_1 + com_2)
intersection = []
for i in com_1 :
if i in com_2 :
com_2.remove(i)
intersection.append(i)
union = not_union - len(intersection)
# 공집합의 경우
if union == 0:
return 65536
else :
return int((len(intersection) / union) * 65536)
최근 코드(맨 위의 코드)와 처음 코드(바로 위의 코드)와 비교해보니, 두 글자씩 끊은 다중 집합을 만드는 부분이 차이가 있었다.
- 처음 코드에서는 왜 그랬는지 모르겠지만 정규식 연산을 써서 더 복잡하게 풀었다. ㅋㅋㅋ 아마 알파벳만 추려야하니 '무조건 정규표현식을 써야해'라고 생각했나보다.
- 최근 코드에서는 두 글자씩 끊고, 조건문과
isalpha()
함수를 사용해서 두 글자 모두 알파벳인지 확인하고 추가해주었다.
풀이
1) 두 글자씩 끊는 다중 집합 만드는 함수
def comb(s) :
temp = []
s = s.lower()
is_str = re.compile('[a-z]+')
for i, j in zip(s[:-1], s[1:]) :
i_str = is_str.match(i)
j_str = is_str.match(j)
if i_str == None or j_str == None:
continue
else :
temp.append(i+j)
return temp
1. 다중집합 원소를 비교할때, 대소문자 구분은 무시하므로 입력받은 문자열(str1 또는 str2)을 소문자로 변환한다.
2. 소문자만(a-z)찾는 정규표현식을 저장하여, match 함수를 통해 입력받은 두 글자 모두 소문자라면(공백, 숫자, 특수문자가 아니라면) temp에 두 글자를 추가해준다.
2) 교집합, 합집합 계산
com_1 = comb(str1)
com_2 = comb(str2)
not_union = len(com_1 + com_2)
intersection = [] # 교집합
for i in com_1 :
if i in com_2 :
com_2.remove(i)
intersection.append(i)
union = not_union - len(intersection) # 합집합
1. 먼저 위의 다중집합 만드는 함수를 str1, str2에 적용시켜준다.
2. 교집합 구하기
* com_1의 원소가 com_2에 있다면 intersection 리스트에 넣어주고 중복을 방지하기 위해 com_2 에선 삭제한다.
3. 합집합 구하기
* com_1 과 com_2를 합한 전체 길이에서 교집합의 길이를 빼주면 합집합이 된다.
3) 자카드 유사도 출력
# 공집합의 경우
if union == 0:
return 65536
else :
return int((len(intersection) / union) * 65536)
1. 만약 합집합이 0인 경우는 두 문자열이 숫자 혹은 특수문자, 공백 등으로 섞여 있어 공집합이 된 경우이기 때문에 1 * 65536 인 65536을 반환한다.
2. 그게 아닐 경우에는 자카드 유사도 식(교집합 / 합집합 * 65536)을 따른다. ( 소수점 버리기 위해 int사용)
'Algorithm > Programmers' 카테고리의 다른 글
[Python] 위장 (0) | 2021.06.02 |
---|---|
[Python] 메뉴 리뉴얼 (0) | 2021.06.02 |
[Python] 소수 찾기 (0) | 2021.05.27 |
[Python] 전화번호 목록 (0) | 2021.05.27 |
[Python] 괄호변환 (0) | 2021.05.26 |