알고리즘
프로그래머스JS | [1차] 뉴스 클러스터링
3jun
2022. 7. 29. 16:32
출처 : 프로그래머스 - 코딩테스트 연습 - 2018 KAKAO BLIND RECRUITMENT- [1차] 뉴스 클러스터링
❌ Solution ( 정확성 53.8 / 100 )
function solution(str1, str2) {
var answer = 0;
const upperStr1 = str1.toUpperCase();
const upperStr2 = str2.toUpperCase();
const arrStr1 = splitEl(upperStr1);
const arrStr2 = splitEl(upperStr2);
const union = [];
const intersection = [];
for(let i = 0; i < arrStr1.length; i++) {
// 변환된 str1 배열의 인자가 변환된 str2 배열에도 존재하고, 교집합에 들어있지 않다면 교집합에 추가
if(arrStr2.indexOf(arrStr1[i]) !== -1 && intersection.indexOf(arrStr1[i]) === -1) {
intersection.push(arrStr1[i])
}
// 합집합 배열에는 변환된 str1 배열을 추가
if(union.indexOf(arrStr1[i]) === -1) {
union.push(arrStr1[i]);
}
}
for(let j = 0; j < arrStr2.length; j++) {
// 합집합 배열에 변환된 str2 배열의 인자가 없다면 해당 인자를 합집합 배열에 추가
if(union.indexOf(arrStr2[j]) === -1) {
union.push(arrStr2[j])
}
}
// 정답 계산식
answer = parseInt(65536 * (intersection.length / union.length));
// 두 집합이 공배열일 경우 처리
if(isNaN(answer)) return 65536;
return answer;
}
// 문자열을 2글자 단위로 쪼개기 위한 함수
function splitEl(str) {
const splitedArr = [];
const reg = /^[A-Z]{2}/g
for(let i = 0; i < str.length -1; i++) {
const newEl = str.split('')[i] + str.split('')[i+1];
if(newEl.match(reg) !== null) {
splitedArr.push(newEl)
}
}
return splitedArr;
}
1. 영문자로 된 글자쌍만 유효하고, 대소문자는 구별하지 않으므로 splitEl 함수를 사용하여 주어진 문자열을 대문자로 통일해준 다음 정규표현식을 사용하여 영문자로 이루어진 다중집합을 return 한다.
2. str1의 다중집합의 원소가 str2의 다중집합에도 들어있고 교집합 배열 intersection 에 포함되어 있지 않다면 해당 원소를 intersection 배열에 추가한다.
3. str1의 다중집합의 원소는 모두 합집합 배열 union 에 추가한다.
4. str2의 다중집합의 원소 중 union 배열에 들어있지 않은 원소가 있다면 union 배열에 추가한다.
5. 교집합 intersection의 length, 합집합 union 의 length를 사용하여 자카드 유사도를 구하고 65536를 곱한 후에 소수점 아래를 버리고 정수부만 출력한다.
💡 자카드 유사도는 원소의 중복을 허용하는 다중집합에 대해 확장할 수 있다. 라는 문구가 있는데, 이를 고려하지 않고 코드를 작성하였다.
이를 고려한 예제를 확인하면 아래와 같다.
A = { 1, 1, 2, 2, 3 } // 다중집합 A
B = { 1, 2, 2, 4, 5 } // 다중집합 B
AnB = { 1, 2, 2 } // 교집합
AuB = { 1, 1, 2, 2, 3, 4, 5} // 합집합
교집합의 경우 중복되는 원소의 가장 작은 반복횟수만큼, 합집합의 경우 중복되는 원소의 가장 큰 반복횟수만큼 인자가 들어간다.
✅ Solution
for (var i = 0; i < arrStr1.length; i++) {
if (arrStr2.indexOf(arrStr1[i]) >= 0) {
intersection.push(arrStr2.splice(arrStr2.indexOf(arrStr1[i]), 1))
}
union.push(arrStr1[i])
}
for (var i = 0; i < arrStr2.length; i++) {
union.push(arrStr2[i])
}
첫번째 반복문에서 splice 함수를 사용하여 arrStr2 배열에서 arrStr1 배열과 중복되는 부분을 제거한 다음 두번째 반복문을 사용하여 중복되는 인자가 제거된 arrStr2의 배열을 union 배열에 추가하면 다중집합의 원소중복에 대해서 대응이 가능하다.