function solution(str1, str2) {
const reg = /[a-z]/;
const str1Lower = str1.toLowerCase();
const str2Lower = str2.toLowerCase();
const str1Ob = {};
const str2Ob = {};
for (let i = 1; i < str1Lower.length; i++) {
if (reg.test(str1Lower[i-1]) && reg.test(str1Lower[i])) {
str1Ob[str1Lower[i-1] + str1Lower[i]] ? str1Ob[str1Lower[i-1] + str1Lower[i]]++ : str1Ob[str1Lower[i-1] + str1Lower[i]] = 1;
}
};
for (let i = 1; i < str2Lower.length; i++) {
if (reg.test(str2Lower[i-1]) && reg.test(str2Lower[i])) {
str2Ob[str2Lower[i-1] + str2Lower[i]] ? str2Ob[str2Lower[i-1] + str2Lower[i]]++ : str2Ob[str2Lower[i-1] + str2Lower[i]] = 1;
}
};
let intersection = 0;
Object.keys(str2Ob).forEach((v) => {
if (str1Ob[v]) {
intersection += Math.min(str1Ob[v], str2Ob[v]);
str1Ob[v] = Math.max(str1Ob[v], str2Ob[v]);
} else {
str1Ob[v] = str2Ob[v];
};
});
let union = 0;
Object.values(str1Ob).forEach((v) => {
union += v;
});
return union === 0 && intersection === 0 ? 65536 : Math.floor(intersection / union * 65536);
}
처음에는 중복을 허용하는 집합인지 모르고 풀다가 오답이 나왔습니다. 문제를 잘 읽어보니 중복을 허용하는 집합이라 코드를 고쳤습니다. 문제는 처음부터 끝까지 차근차근 꼼꼼하게 읽어봐야겠습니다.
function solution (str1, str2) {
function explode(text) {
const result = [];
for (let i = 0; i < text.length - 1; i++) {
const node = text.substr(i, 2);
if (node.match(/[A-Za-z]{2}/)) {
result.push(node.toLowerCase());
}
}
return result;
}
const arr1 = explode(str1);
const arr2 = explode(str2);
const set = new Set([...arr1, ...arr2]);
let union = 0;
let intersection = 0;
set.forEach(item => {
const has1 = arr1.filter(x => x === item).length;
const has2 = arr2.filter(x => x === item).length;
union += Math.max(has1, has2);
intersection += Math.min(has1, has2);
})
return union === 0 ? 65536 : Math.floor(intersection / union * 65536);
}
위에서 풀었던 코드는 통과가 되지만 효율적인 코드 작성을 위해 다른 사람의 코드는 어떤식으로 구현했는지 보고 싶어 가져왔습니다.
function explode(text) {
const result = [];
for (let i = 0; i < text.length - 1; i++) {
const node = text.substr(i, 2);
if (node.match(/[A-Za-z]{2}/)) {
result.push(node.toLowerCase());
}
}
return result;
}
str1과 str2의 반복되는 작업이므로 내부 함수를 작성하여 코드의 수를 줄였습니다.
index는 0부터 substr을 통해서 2개씩 문자열을 잘라주고 정규식 /[A-Za-z]{2}/로 2개의 알파벳으로 이루어져 있는지 확인하고 소문자로 변환하여 push해주었습니다.
저는 정규식 test를 사용했고 위에 코드는 match를 사용했는데 둘의 차이는 아래와 같습니다.
test() - 매칭되는것이 있다면 true 없다면 false 리턴
match() - 매칭되는것이 있다면 매칭된 문자열 출력
사용하고 싶은 것을 사용해도 무방합니다.
set.forEach(item => {
const has1 = arr1.filter(x => x === item).length;
const has2 = arr2.filter(x => x === item).length;
union += Math.max(has1, has2);
intersection += Math.min(has1, has2);
})
그리고 여기서는 set의 값을 반복하면서 각 원소의 갯수를 구해서 union과 intersection으로 더해주었습니다.
union === 0 ? 65536 : Math.floor(intersection / union * 65536);
마지막은 어차피 합집합이 0개면 교집합도 0개이니 union만 0인지 확인해주고 반환했습니다.