본문 바로가기
코딩 테스트/프로그래머스

[프로그래머스 - Python] Lv.2 뉴스 클러스터링

by 오엥?은 2023. 3. 8.
반응형
  • 문제

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

  • 풀이
import math
import re

def solution(str1, str2):
    one = [str1[x:x + 2].lower() for x in range(0, len(str1) - 1)]
    two = [str2[x:x + 2].lower() for x in range(0, len(str2) - 1)]

    # 공백, 숫자, 특수문자 포함 문자열 제거
    new_one = []
    for x in one:
        new_str = re.sub(r"[^a-zA-Z]", "", x)    # 정규식을 이용하여 알파벳을 제외한 문자 제거
        if len(new_str) == len(x):      # 만약 제거했는 데도 길이가 같다면 알파벳으로만 이루어졌다는 뜻
            new_one.append(x)

    new_two = []
    for x in two:
        new_str = re.sub(r"[^a-zA-Z]", "", x)  # 정규식을 이용하여 알파벳을 제외한 문자 제거
        if len(new_str) == len(x):  # 만약 제거했는 데도 길이가 같다면 알파벳으로만 이루어졌다는 뜻
            new_two.append(x)

    intersection = list(set(new_one) & set(new_two))  # 교집합
    union = list(set(new_one) | set(new_two))  # 합집합

    if len(new_one) == 0 & len(new_two) == 0:
        answer = 65536
    else:
        answer = math.trunc((len(intersection) / len(union)) * 65536)

    return answer

처음엔 이렇게 했다.

 

문제가 되는 부분은

intersection = list(set(new_one) & set(new_two))  # 교집합
union = list(set(new_one) | set(new_two))  # 합집합

여기였다.

 

list 를 set 으로 바꾼 후 교집합과 합집합을 구했기 때문에 중복되는 요소들이 지워졌다.

print(solution('aa1+aa2', 'AAAA12'))	#65536

그래서 solution('aa1+aa2', 'AAAA12') 와 같이 매개변수를 넣었을 때 

new_one = ['aa', 'aa']

new_two = ['aa', 'aa', 'aa'] 

 

교집합과 합집합이

intersection = ['aa']

union = ['aa'] 

이렇게 돼서 (1 / 1) * 65536 = 65536 으로 return 이 된다. 

 

intersection = ['aa', 'aa']

union = ['aa', 'aa', 'aa'] 

이렇게 돼서 (2 / 3) * 65536 = 43690 으로 return 되어야 한다.

 

set 지우니까 에러나서 다른 방법 찾았다 힝

 

import math
import re

def solution(str1, str2):
    # 1
    one = [str1[x:x + 2].lower() for x in range(0, len(str1) - 1)]
    two = [str2[x:x + 2].lower() for x in range(0, len(str2) - 1)]

    # 2
    new_one = []
    for x in one:
        new_str = re.sub(r"[^a-zA-Z]", "", x)    
        if len(new_str) == len(x):      
            new_one.append(x)

    new_two = []
    for x in two:
        new_str = re.sub(r"[^a-zA-Z]", "", x)  
        if len(new_str) == len(x):  
            new_two.append(x)
	
    # 3
    intersection = []   # 교집합
    union = []  # 합집합
    new_one_temp = new_one
    for x in new_two:
        union.append(x)
        if x in new_one_temp:
            intersection.append(x)
            new_one_temp.remove(x)

    for x in new_one_temp:
        union.append(x)

    # 4
    if len(union) == 0 & len(intersection) == 0:
        answer = 65536
    else:
        answer = math.trunc((len(intersection) / len(union)) * 65536)

    return answer

# 1

one 과 two 는 각각 str1, str2 를 두 글자씩 끊어서 list에 저장한 것이다. 대소문자는 구분을 하지 않는다고 해서 lower() 해줬다.

 

#2

one 과 two 의 요소들을 각각 반복문을 돌린다. 

정규식을 이용하여 알파벳 이외의 문자가 있다면 ""으로 바꾼다. 아무 것도 바뀐 것이 없다면 (문자열의 길이가 그대로 2라면) new_one 과 new_two 에 각각 담아준다.

 

#3

• intersectinon(교집합 list) :

new_two 의 요소들을 반복문을 돌려서 임시로 만든 new_one 과 같은 new_one_temp 에도 있는 요소라면 intersection에 담는다. 겹쳐서 담은 요소는 new_one_temp 에서 지워준다.

 

• union(합집합 list) :

new_two 의 요소들을 반복문을 돌려서 union에 담는다. 그 후 임시로 만든 new_one 과 같은 new_one_temp 에도 있는 요소라면, new_one_temp 에서는 지워준다. 그러면 new_one_temp 에는 new_one에는 있지만 new_two 에는 없는 요소들만 남을 것이다. 그 요소들 전부를 union에 담아주면 합집합 완성!@

 

#4

집합 A와 집합 B가 모두 공집합일 경우에는 나눗셈이 정의되지 않으니 따로 J(A, B) = 1로 정의한다.

 

문제에서 이렇게 나왔기 때문에 조건을 걸어주고 조건에 해당되지 않으면 (교집합 / 합집합) * 65536 을 한 뒤 소숫점 버린다.

 

 

  • 다른 사람 풀이
inter = list((Counter1 & Counter2).elements())
union = list((Counter1 | Counter2).elements())

다른 사람 풀이 보니까 내가 처음에 썼던 방법 set 로 변환하지 않고 뒤에 .elements() 붙이면 list로 가능한가보다. 

 

 

반응형