반복문 구조가 이상하여 한참을 쳐다본 코드이다.
합집합과 교집합을 구하기 위해서 count1, count2값을 조정하는데, 이에 대한 반복문을 실행할 때,
if (str[j] === union[i])
count1++;
else
break; // 테스트 통과를 못한 부분
else문으로 break를 걸어서 정확한 개수를 파악하지 못한 것이 문제점이었다.
따라서 반복되는 단어의 정확한 갯수를 파악하여 문제를 해결하도록 break를 삭제하였다
최종 코드는 다음과 같다👇
// 단어들의 집합을 구해내기 위한 함수
function getStringSet(str){
let set = [];
const alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
for(let i = 0 ; i < str.length-1 ; i++){
if(alpha.includes(str[i]) && alpha.includes(str[i+1]))
set.push(str[i] + str[i+1])
}
return set;
}
function solution(str1, str2) {
// str1, str2을 모두 대문자로 바꾼 뒤
// 이에 대한 단어들의 집합으로 변경
str1 = getStringSet(str1.toUpperCase());
str2= getStringSet(str2.toUpperCase());
// 중복되는 단어는 삭제하여 set에 저장
let str1_set = str1.filter((data,index)=> str1.indexOf(data) === index);
let str2_set = str2.filter((data,index)=> str2.indexOf(data) === index);
// 교집합
let intersection = str1_set.filter((data)=> str2_set.includes(data))
// 합집합
let union = [...new Set(str1) ,...new Set(str2)]
union = [...new Set(union)]
// 교집합 원소의 수, 합집합 원소의 수 초기화
let inter_count = 0, union_count =0;
// 교집합의 수 체크하기
for(let i = 0 ; i < intersection.length ; i++){
let count1 = 0, count2 = 0;
for(let j = str1.indexOf(intersection[i]) ; j < str1.length ; j++){
if(str1[j]=== intersection[i])
count1++;
}
for(let j = str2.indexOf(intersection[i]) ; j < str2.length ; j++){
if(str2[j]=== intersection[i])
count2++;
}
// 작은 수의 값을 교집합 수에 더해줌
if(count1 < count2)
inter_count += count1;
else
inter_count += count2;
}
// 합집합 구하기
for(let i = 0 ; i < union.length ; i++){
let count1 = 0, count2 = 0;
for(let j = str1.indexOf(union[i]) ; j < str1.length ; j++){
if(str1[j]=== union[i])
count1++;
}
for(let j = str2.indexOf(union[i]) ; j < str2.length ; j++){
if(str2[j]=== union[i])
count2++;
}
// 큰 수의 값을 합집합 수에 더해줌
if(count1 < count2)
union_count+= count2;
else
union_count+= count1;
}
// 합집합이 공집합이거나 교집합이 없으면 1
if((inter_count === 0 && union_count === 0) || union_count === 0)
return 1 * 65536
else // 소수점 버리고 반환
return Math.floor(inter_count / union_count * 65536)
}
// 문자열 가져올 수 있는 조합 반환 함수
function getStringCombinations(str) {
// 대문자로 변환시키고
const arr = str.toUpperCase().split('');
const result = [];
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
for (let i = 0; i < arr.length - 1; i++) {
if (alphabet.includes(arr[i]) && alphabet.includes(arr[i + 1])) result.push(arr[i] + arr[i + 1])
}
// 정렬해서 반환
return result.sort();
}
function solution(str1, str2) {
// 조합가져오기
str1 = getStringCombinations(str1);
str2 = getStringCombinations(str2);
// 중복되지않게 일단 교집합과 합집합 원소들 가져오기
const intersection = [...new Set(str1.filter((str) => str2.includes(str)))];
const union = [...new Set([...str1, ...str2])];
let intersectionCount = 0;
let unionCount = 0;
//교집합 원소의 수 -> 가장 적게 등장한 횟수를 더해주어야 함
intersection.forEach((data) => {
// str1,str2 각각에 대해 교집합 원소 시작 인덱스를 가져오고
let str1Index = str1.indexOf(data);
let str2Index = str2.indexOf(data);
let count1 = 0;
let count2 = 0;
// 증가시키면서 몇번 등장하는지 파악
while (str1[str1Index ] === data) {
count1 += 1;
str1Index += 1;
}
while (str2[str2Index] === data) {
count2 += 1;
str2Index += 1;
}
// 적게 등장한 수 더해주기
intersectionCount += count1 < count2 ? count1 : count2;
})
// 합집합 -> 가장 많이 등장한 횟수를 더해주어야함
union.forEach((data) => {
// str1,str2 각각에 대해 합집합 원소 시작 인덱스를 가져오고
let str1Index = str1.indexOf(data);
let str2Index = str2.indexOf(data);
let count1 = 0;
let count2 = 0;
// 증가시키면서 몇번 등장하는지 파악
while (str1[str1Index ] === data) {
count1 += 1;
str1Index += 1;
}
while (str2[str2Index ] === data) {
count2 += 1;
str2Index += 1;
}
// 많이 등장한 수 더해주기
unionCount += count1 > count2 ? count1 : count2;
})
//공집합이거나 교집합이 없으면 65536반환하고
// 그외에는 정수부만 출력
return ((intersectionCount === 0 && unionCount === 0) || unionCount === 0) ? 65536 : Math.floor(intersectionCount / unionCount * 65536);
}