CS/algorithm & data structure

[프로그래머스] [1차] 뉴스 클러스터링 (파이썬 풀이)

hjkim0502 2022. 6. 25. 22:06

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

 

코딩테스트 연습 - [1차] 뉴스 클러스터링

뉴스 클러스터링 여러 언론사에서 쏟아지는 뉴스, 특히 속보성 뉴스를 보면 비슷비슷한 제목의 기사가 많아 정작 필요한 기사를 찾기가 어렵다. Daum 뉴스의 개발 업무를 맡게 된 신입사원 튜브

programmers.co.kr

내 풀이:

from collections import defaultdict

def make_table(str):
    table = defaultdict(int)
    for i in range(len(str) - 1): 
        if str[i:i + 2].isalpha():
            table[str[i:i + 2].lower()] += 1
            
    return table

def solution(str1, str2):
    # 유효한 문자열의 다중집합
    dict1, dict2 = make_table(str1), make_table(str2)
    
    # 교집합, 합집합 원소 갯수 계산
    same, all = 0, 0
    for s1 in dict1:
        if s1 in dict2:
            same += min(dict1[s1], dict2[s1])
            all += max(dict1[s1], dict2[s1])
        else:
            all += dict1[s1]
    for s2 in dict2:
        if s2 not in dict1:
            all += dict2[s2]
            
    if all == 0:
        return 65536
    return int(same / all * 65536)
  • 아이디어: 순차 탐색하며 유효한 문자열 생성하여 갯수 저장하고, 두 딕셔너리에서 교집합, 합집합 갯수 추출

 

참고 답안:

import re
import math

def solution(str1, str2):
    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])]
	
    # 교집합, 합집합 원소 추출
    gyo = set(str1) & set(str2)
    hap = set(str1) | set(str2)

    if len(hap) == 0 :
        return 65536
	
    # 추출한 원소로 교집합, 합집합 원소 갯수 계산
    gyo_sum = sum([min(str1.count(gg), str2.count(gg)) for gg in gyo])
    hap_sum = sum([max(str1.count(hh), str2.count(hh)) for hh in hap])

    return math.floor((gyo_sum/hap_sum)*65536)
  • 교집합, 합집합에 해당하는 원소들을 미리 저장하여 나중에 계산할 때 깔끔하게 코드 작성 가능
  • 리스트로 문자열 저장해 나중에 count 함수로 일일히 계산

아이디어 적용 답안:

from collections import defaultdict

def make_table(str):
    table = defaultdict(int)
    for i in range(len(str) - 1): 
        if str[i:i + 2].isalpha():
            table[str[i:i + 2].lower()] += 1
            
    return table

def solution(str1, str2):
    dict1, dict2 = make_table(str1), make_table(str2)
    
    # 교집합, 대칭차집합
    intersect = set(dict1) & set(dict2)
    sym_dif = set(dict1) ^ set(dict2)
    
    num, den = 0, 0
    for i in intersect:
        num += min(dict1[i], dict2[i])
        den += max(dict1[i], dict2[i])
        
    for s in sym_dif:
        den += dict1[s] + dict2[s]
            
    if den == 0:
        return 65536
    return int(num / den * 65536)
  • 딕셔너리로도 set 함수 적용 가능하고, 대칭차집합 이용하여 원소갯수 더 편리하게 계산
  • defaultdict기 때문에 dict1이나 dict2에 s가 존재하지 않아도 0 더해짐