[2018 KAKAO BLIND RECRUITMENT] 뉴스 클러스터링

송현아·2021년 9월 3일
0
post-thumbnail

📑 뉴스 클러스터링

시간 : 1시간

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

  • 문제 정보

    • 자카드 유사도 계산 방법

      J(A, B) : 두 집합의 교집합 크기 / 두 집합의 합집합 크기

      • A와 B가 공집합인 경우

        • J(A, B) = 1
      • 중복을 허용하는 다중 집합에서 사용이 가능

        • A ∩ B = 중복 원소의 최솟값
        • A ∪ B = 중복 원소의 최댓값
  • 입력

    • str1str2의 두 문자열 ( 길이는 2 이상, 1,000 이하 )
    • 각 문자열은 두 글자씩 끊어서 다중 집합의 원소로 만든다.
    • 그 이후에, 영어(소문자) 외의 것들은 버린다.
  • 출력

    • 유사도 * 65536
    • 소수점을 버린다.
  • 정답 코드

다중 집합의 원소 리스트를 생성한 후, 문제에서 주어지는 조건대로 자카드 유사도 만 잘 구하면 되는 문제이다. convert() 라는 함수를 통해서 다중 집합의 원소 리스트를 생성하고, calculate() 함수를 이용하여 자카드 유사도를 계산하였다.

def convert(str1, str2):
    list1, list2 = [],[]
    for i in range(0,len(str1)-1):
        list1.append(str1[i:i+2])
    for i in range(0,len(str2)-1):
        list2.append(str2[i:i+2])

    list1 = [i.lower() for i in list1 if i.isalpha()]
    list2 = [i.lower() for i in list2 if i.isalpha()]
    return list1,list2

def calculate(list1, list2):

    # A와 B가 공집합인 경우
    if not list1 and not list2:
        return 1

    # 중복되는 원소가 없는 경우
    elif len(list1) == len(set(list1)) and len(list2) == len(set(list2)):
        result1 = len(list(set(list1) & set(list2)))
        result2 = len(list(set(list1)|set(list2)))
        return result1 / result2

    # 중복되는 원소가 있는 경우
    else:
        dict1,dict2 = {},{}
        result1 = list(set(list1) & set(list2)) # 곱 원소 (only 1개)
        result2 = list(set(list1)|set(list2)) # 합 원소 (only 1개)
        len1 = len(result1)
        len2 = len(result2)

        for i in list1:
            if i in dict1:
                dict1[i] +=1
            else:
                dict1[i] = 1

        for i in list2:
            if i in dict2:
                dict2[i] +=1
            else:
                dict2[i] = 1

        for i in result1:
            if dict1[i]>1 or dict2[i]>1:
                len1 += min(dict1[i],dict2[i])-1
                continue

        for i in result2:
            if (i in list1) and (i not in list2):
                len2 += dict1[i]- 1
                continue
            elif (i in list2) and (i not in list1):
                len2 += dict2[i]- 1
                continue
            elif (i in list2) and (i in list1):
                len2 += max(dict1[i], dict2[i])-1
                continue
        return len1 / len2

def solution(str1, str2):
    list1,list2 = convert(str1, str2)
    similarity = calculate(list1,list2)
    return int(65536 * similarity)

[Hyun's Code]

난이도는 쉬운 편이였다. 문제에 주어진 조건만 정리 잘해서 푼다면 쉽게 풀 수 있는 문제였다. 그럼에도 시간이 1시간이나 걸린 이유는 continue와 break를 혼동해서 사용했기 때문이다. 너무나도 사소한 개념 혼동 실수라니 ㅠㅠ 역시 문법 공부도 소홀히 해서는 안되겠다.

  • break

    • 제어흐름 (반복문 : for문, while문)을 아예 중지시킨다.
i = 0
while True:    # 무한 루프
    print(i)
    i += 1          # i를 1씩 증가시킴
    if i == 100:    # i가 100일 때
        break       # 반복문을 끝냄. while의 제어흐름을 벗어남
        
for i in range(10000):    # 0부터 9999까지 반복
    print(i)
    if i == 100:    # i가 100일 때
        break       # 반복문을 끝냄. for의 제어흐름을 벗어남
  • continue

    • 제어흐름은 유지하고, 코드 실행만 건너뛴다.
      • 즉, 아래의 코드는 실행하지 않고, 다음 단계의 제어흐름을 실행한다.
for i in range(100):       # 0부터 99까지 증가하면서 100번 반복
    if i % 2 == 0:         # i를 2로 나누었을 때 나머지가 0면 짝수
        continue           # 아래 코드를 실행하지 않고 건너뜀
    print(i)

0개의 댓글