프로그래머스: 뉴스 클러스터링

Song-Minhyung·2022년 10월 29일
0

Problem Solving

목록 보기
28/50
post-thumbnail

문제

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

문자 A, B의 자카드 유사도 J(A,B)를 구하는 문제다
구하는 방법은 두 집합의 교집합 크기를 합집합의 크기로 나누면 된다.

입력

  • str1, str2
    • 2 이상 1000이하의 길이를 가진 문자열

출력
자카드 유사도에 65536을 곱한후 소숫점을 버린후 출력한다

정답코드

function getStr(str) {
  const arr = [];
  const reg = /[A-Z]/;
  for (let i = 0; i < str.length - 1; i++) {
    const left = reg.test(str[i]);
    const right = reg.test(str[i + 1]);

    if (left && right) {
      arr.push([str[i], str[i + 1]].join(''));
    }
  }
  return arr;
}
const getIntersection = (arr1, arr2) => {
  const result = [];
  for (let i = 0; i < arr1.length; i++) {
    if (arr2.includes(arr1[i])) {
      const idx = arr2.indexOf(arr1[i]);
      result.push(arr2[idx]);
      arr2.splice(idx, 1);
    }
  }
  return result.length;
};

function solution(str1, str2) {
  const arr1 = getStr(str1.toUpperCase());
  const arr2 = getStr(str2.toUpperCase());

  let intersection = getIntersection([...arr1], [...arr2]);
  let union = arr1.length + arr2.length - intersection;

  const result = Math.floor((intersection / union) * 65536);
  if(union === 0) return 65536;
  if(intersection === 0) return 0;
  return result;
}

해설

합집합을 구하는 방법은 두 집합의 크기 - 교집합의 크기 이다.
그래서 우선 교집합을 구해야 하는데 그 전에 집합을 만들어준다.

1. 집합 구하기

function getStr(str) {
  const arr = [];
  const reg = /[A-Z]/;
  for (let i = 0; i < str.length - 1; i++) {
    const left = reg.test(str[i]);
    const right = reg.test(str[i + 1]);

    if (left && right) {
      arr.push([str[i], str[i + 1]].join(''));
    }
  }
  return arr;
}

집합을 구하는 함수인데 0부터 시작해 문자열길이 -1까지 탐색을 한다.
그러고서 만약 특수문자가 있다면 집합에 포함하지 않고 없다면 집합에 포함시켜준다.

2. 교집합 구하기

const getIntersection = (arr1, arr2) => {
  const result = [];
  for (let i = 0; i < arr1.length; i++) {
    if (arr2.includes(arr1[i])) {
      const idx = arr2.indexOf(arr1[i]);
      result.push(arr2[idx]);
      arr2.splice(idx, 1);
    }
  }
  return result.length;
};

위의 코드는 교집합을 구하는 함수다.
집합 arr1, arr2를 입력받은후에 arr1을 for문으로 돌아본다.
그러고서 arr1[i]가 arr2[i]에 있다면 arr2에서 해당 원소를 제거한다.
만약 제거하지 않으면 나와야 하는 값보다 더 크게 나올수도 있으므로 꼭 제거해야 한다.

마지막. 결과 구하기

let intersection = getIntersection([...arr1], [...arr2]);
let union = arr1.length + arr2.length - intersection;

const result = Math.floor((intersection / union) * 65536);
if(union === 0) return 65536;
if(intersection === 0) return 0;
return return result;

문제에 나온대로 교집합 / 합집합 * 65536 후에 소수점을 버린다.
그 후에 비교할 집합이 아에 없으면(양쪽다 공집합이면) 65536을 리턴하고
교집합으로 나온값이 없다면 0을 리턴한다.
둘다 아니라면 result로 나온 값을 리턴해주면 된다

profile
기록하는 블로그

0개의 댓글