# 2. 영문자 2개씩 끊어서 집합에 넣을껀데 영문자가 아닌것이 포함된 문자는 넣지 않는다.
예): {AAA} -> {AA, AA}가 되고 {AA2B} -> {AA}가 된다
# 3. 교집합과 합집합의 크기를 각각 구하고 자카드 유사도를 구해 65536을 곱해준다.
- 3.1 중복되는 수를 추가 해준다.
일반집합의 교집합이나 합집합은 중복을 허락하지 않는다.
예를 들어 교집합이 {1,2,2}가 될 수 없다 {1,2}이어야 한다. 따라서 중복되는 수를 추가 해준다.
# 4. 예외처리는 항상 까먹지 말고
import re
def solution(str1, str2):
# 예외 처리
if len(str1)<=1 and len(str2)<=1:
return 65536
# 1. 영문자를 통일
str1, str2 = str1.upper(), str2.upper()
# 2. 2개씩 끊어서 집합에 넣기
str1List = []
str2List = []
pattern = re.compile(r'[A-Z]{2}') # 오직 영문자에 대해서만 2개씩
for i in range(len(str1)-1): # 문자열을 다 돌아
twoset=str1[i]+str1[i+1]
if pattern.findall(twoset): # 2개 짜리가 영문자로만 이루어져있으면
str1List.append(twoset) # 리스트에 넣기
for i in range(len(str2)-1):
twoset=str2[i]+str2[i+1]
if pattern.findall(twoset):
str2List.append(twoset)
# 원소의 중복을 허용하는 다중집합이 아님 교집합이 {1,2,2}가 아닌 {1,2}가 나옴
a = set(str1List) & set(str2List)
b = set(str1List) | set(str2List)
# 3.1 중복되는 수를 알아낸다.
# 따라서 추가되는 수를 알아내고 추가 해줘야함
intersection_num = 0
union_num = 0
# 교집합
for i in a:
if str1List.count(i) > 1 and str2List.count(i) > 1:
if str1List.count(i) > str2List.count(i):
intersection_num += str2List.count(i)-1 # -1을 하는 이유는 이미 일반집합에 하나는 넣어져 있어서
else: # str1List와 str2List에서 더 적은것을 고른다
intersection_num += str1List.count(i)-1
# 합집합
for i in b:
if str1List.count(i) > 1 or str2List.count(i) > 1:
if str1List.count(i) > str2List.count(i):
union_num += str1List.count(i)-1 # str1List와 str2List에서 더 많은것을 고른다
else:
union_num += str2List.count(i)-1
# 교집합 길이 수에 중복되는 수를 더해주고 합집합도 마찬가지로 해준다
total_inter = len(a)+intersection_num
totla_union = len(b)+union_num
# 예외 처리
if totla_union == 0:
return 65536
if total_inter == 0:
return 0
# 3. 자카드 유사도를 구한다
return int(total_inter / totla_union * 65536)
if __name__ == '__main__':
testcase = [
('FRANCE', 'french'),
('handshake', 'shake hands'),
('aa1+aa2', 'AAAA12'),
('E=M*C^2', 'e=m*c^2')
]
for str1, str2 in testcase:
print(solution(str1, str2))
print()