ex = "~!@#$%^&*()_+=- /?|/\"\'\\1234567890,.<>;:"
을 선언해줘서 알파벳이 아닌 문자열들을 골라내기로 하였다.return 65536
을 해주고, 아니라면 교집합의 크기/합집합의 크기 * 65536
으로 답을 구해준다.copy()
를 사용해줬다.def solution(str1, str2):
# 자카드 유사도: 교집합크기/합집합크기
# 대소문자는 무시 -> 다 소문자로 만들기
str1 = str1.lower()
str2 = str2.lower()
ex = "~!@#$%^&*()_+=- /?|/\"\'\\1234567890,.<>;:"
g1, g2 = [], []
sum_group, inter_group = [], []
# 입력으로 들어온 문자열은 두 글자씩 끊어서 다중집합의 원소로 만든다.
for i in range(1, len(str1)):
if str1[i-1] in ex or str1[i] in ex:
pass
else:
g1.append(str1[i-1]+str1[i])
for i in range(1, len(str2)):
if str2[i-1] in ex or str2[i] in ex:
pass
else:
g2.append(str2[i-1]+str2[i])
g1_copy = g1.copy()
g2_copy = g2.copy()
# 교집합 구하기
for g in g1:
if g in g2_copy:
inter_group.append(g)
g1_copy.remove(g)
g2_copy.remove(g)
# 합집합 구하기
sum_group = inter_group + g1_copy + g2_copy
# 이를 다루기 쉽도록 65536을 곱한 후에 소수점 아래를 버리고 정수부만 출력한다.
if len(sum_group) == 0:
return 65536
else:
return int(len(inter_group)/len(sum_group) * 65536)
살짝 무식하게 풀었는데.. 키보드에 존재하는 특수문자들을 ex
라는 문자열로 선언해주고 str1
과 str2
가 특수문자열 ex
에 있으면 g1
, g2
에 넣어주지 않는다. 이렇게 하면 이때 영문자로 된 글자 쌍만 유효하고, 기타 공백이나 숫자, 특수 문자가 들어있는 경우는 그 글자 쌍을 버린다.
를 만족하는 문자열들을 집합에 담을 수 있다.
교집합을 구할 때 g1_copy
와 g2_copy
에서 교집합 안에 들어간 원소를 remove
해주지 않으면 제대로된 합집합을 구할 수 없다!!
따라서 이를 제거해 준 다음에 합집합에 더해주면 된다.
나는 다소 무식하게 풀었지만, 다른 사람들 풀이를 보면 정규표현식, isalpha()
를 이용하여 알파벳만 추출하는 방법들이 존재해서 이를 정리하고자 한다.
import re
str1 = [str1[i:i+2].lower() for i in range(0, len(str1)-1) if not re.findall('[^a-zA-Z]+', str1[i:i+2])]
str2 = [str2[i:i+2].lower() for i in range(0, len(str2)-1) if not re.findall('[^a-zA-Z]+', str2[i:i+2])]
나의 구구절절한 코드를 두줄로 축약 가능
isalpha()
list1 = [str1[n:n+2].lower() for n in range(len(str1)-1) if str1[n:n+2].isalpha()]
list2 = [str2[n:n+2].lower() for n in range(len(str2)-1) if str2[n:n+2].isalpha()]
두개씩 끊은 문자열이 알파벳이라면, 소문자로 바꾸고 리스트에 담아준다!
이 역시 나의 구구절절한 코드보다 훨씬 간단한 부분이다.
Counter
사용from collections import Counter
def solution(str1, str2):
# make sets
s1 = [str1[i:i+2].lower() for i in range(len(str1)-1) if str1[i:i+2].isalpha()]
s2 = [str2[i:i+2].lower() for i in range(len(str2)-1) if str2[i:i+2].isalpha()]
if not s1 and not s2:
return 65536
c1 = Counter(s1)
c2 = Counter(s2)
answer = int(float(sum((c1&c2).values()))/float(sum((c1|c2).values())) * 65536)
return answer
wow
교집합과 합집합 역시 간결하게 나타내 준 코드이다!!
교집합은 & , 합집합은 | 표현으로 set
함수와 똑같이 작동한다.
예제 1번을 통해서 설명을 하자면
str1, str2 = 'FRANCE', 'french'
s1 = [str1[i:i+2].lower() for i in range(len(str1)-1) if str1[i:i+2].isalpha()]
s2 = [str2[i:i+2].lower() for i in range(len(str2)-1) if str2[i:i+2].isalpha()]
알파벳만 존재하는 다중집합을 만들어 주고
c1 = Counter(s1)
c2 = Counter(s2)
(Counter({'fr': 1, 'ra': 1, 'an': 1, 'nc': 1, 'ce': 1}), Counter({'fr': 1, 're': 1, 'en': 1, 'nc': 1, 'ch': 1}))
위와 같이 Counter
객체를 생성한다.
c1&c2
Counter({'fr': 1, 'nc': 1})
이렇게 교집합을 구할 수 있다.
(c1&c2).values()
dict_values([1, 1])
이렇게 원소들의 값만 구하여
sum((c1&c2).values())
2
합을 구하면 집합의 크기가 된다.
우리에게 필요한 값은 어느 원소가 교집합, 합집합에 속해있느냐
가 아니라 교집합, 합집합의 크기
이기 때문에 이렇게 구해주면 아주 간단하게 코드를 짤 수 있다!
파이썬 집합자료형 set 연산 : 합집합, 교집합, 차집합
collections 모듈의 Counter 클래스
정규표현식을 배웠고, isalpha()
를 사용해 다양한 문제를 풀었음에도.. 또 Counter
클래스를 사용해봤음에도!!! 무식하게 문제를 풀었다..😂 배운 것을 잘 써먹는 것 또한 매우매우 어려운 부분인 것 같다😢