문제 목록
//? 집합 원소 만드는 함수
function makeSet (s){
const set = [];
while(s.length){
if(s.length === 1) break; // 두글자씩 끊어서 하기 때문에 남은 글자가 한 글자라면 멈추기
const str = s.slice(0, 2); // 집합 원소
if(!str.replace(/[A-Z]/g, '').length) set.push(str) // 원소가 [A-Z]라면 공백으로 바꿈 => 길이가 없을 경우 집합에 push
s = s.slice(1); // 한글자씩 밀기
}
return set;
}
function solution(str1, str2) {
/*
! 교집합 크기 / 합집합 =자카드
! 공집합 => 1
1. 각 집합 만들어 주기 => makeSet() 호출
2. 교집합 구하기 => forEach 돌려서 다른 집합에 indexOf를 통해 해당 요소 0으로 만들어 주고 count
3. 합집합 구하기 => (set1 길이 + set2 길이) - 교집합 수
4. 나눠버리기~!
*/
const set1 = makeSet(str1.toUpperCase());
const set2 = makeSet(str2.toUpperCase());
/*
console.log(set1);
console.log(set2);
*/
//! 공집합일 경우
if(!set1.length && !set2.length) return 65536
//? 교집합 구하기
let intersection = 0;
set1.forEach( (e) => { // set1의 요소를 순회하면서
if(set2.indexOf(e) !== -1){ // set1의 요소를 set2가 가지고 있다면
set2[set2.indexOf(e)] = 0 // set2의 해당 위치를 0으로 바꿔주기 (중복 때문에)
intersection++; // 교집합 원소의 수 count
}
});
//? 합집합 => 전체 원소의 수 - 교집합 수
const union = (set1.length + set2.length) - intersection
/*
! 교집합 / 합집합 = 자카드
! return 자카드 * 65536 => floor 소수점 버리기
*/
const jaccard = intersection / union
// console.log(Math.floor(jaccard * 65536));
return Math.floor(jaccard * 65536)
}
// solution('FRANCE', 'french') // expect output => 16384
각 집합의 원소를 만들어 주는 함수 makeSet
함수를 만들어 놓고 집합1과 집합2에 조건이 부합하는 원소들이 들어간 형태의 배열 집합을 만들어 주었다. makeSet 내에서 원소를 만들어 줄때 2글자씩 잘라서 문자열에 해당할 때만(A-Z거나 a-z일 때) 집합의 원소가 될 수 있는데 해당 부분은 나는 slice로 잘라 정규식을 통해 A-Z에 해당하면 공백으로 바꾸는 replace 메서드를 활용해서 해 주었는데 그 부분은 다음과 같다.
const str = s.slice(0, 2); // 집합 원소
if(!str.replace(/[A-Z]/g, '').length) set.push(str)
이 코드도 괜찮았지만 스터디를 진행하면서 대부분 다른 분들의 코드에서 .test 메서드를 활용해 정규식을 통과하는지 판별을 해 주었다.
// 다중 집합 구성하는 코드 (민혁님)
for (let i = 0; i < s.length - 1; i++) {
if (/[A-Z]/.test(s[i])) {
if (/[A-Z]/.test(s[i + 1])) {
const key = s[i] + s[i + 1];
multiset[key] = (multiset[key] || 0) + 1;
} else i++;
}
이 코드를 참고해 나도 살짝 리팩토링을 해 보자면
const str = s.slice(0, 2); // 집합 원소
if(/[A-Z]/.test(ser)) set.push(str)
이런 식으로 해 주면 훨씬 간결하고 직관적인 코드가 된다!! 넘나 좋은 것...
function solution(today, terms, privacies) {
/*
각 개인정보마다 약관 종류에 맞는 유효기간 날짜를 구한 뒤
하루 전 날짜를 기준으로 오늘 날짜와 비교해서 오늘 날짜가 더 크다면 유효기간이 지난 것임
terms[약관종류][유효기간]
*/
/* "2022.05.19" => .을 공백으로 바꾼 뒤 숫자로 변환
각 개인정보들도 이와 같은 방법으로
개인정보 수집 일자를 기준으로 유효기간 마지막날을 구해
숫자 타입끼리 비교할 계획
*/
today = Number(today.replaceAll('.', ''));
console.log(today);
// [[유형][유효기간]]
terms = terms.map((e) => e.split(' '));
console.log(terms);
privacies = privacies.map((e) => {
// 다음과 같이 들어온 개인정보 e => "2021.05.02 A"
e = e.split(' '); // [날짜][약관종류] => [['2021.05.02'], ['A']]
e[0] = e[0].split('.'); // 날짜를 .기준으로 나누기 [['2021', '05', '02'], ['A']]
console.log(e);
console.log(e[1]); // e => e[날짜][약관종류]
for (let i = 0; i < terms.length; i++) {
// 각 약관 종류에 맞는 유효기간 넣어주기
if (e[1] === terms[i][0]) {
// terms[[유형][유효기간]]
e[1] = Number(terms[i][1]);
}
}
console.log(e[0]); // 날짜 숫자로 바꿔주기
for (let i = 0; i <= 2; i++) {
e[0][i] = Number(e[0][i]);
}
return e;
});
console.log(privacies);
//! 유효기간 딱 ! 지난 날짜
privacies.forEach((e) => {
// e => e[날짜][유효기간]
console.log(e); // 개인정보 묶음
console.log(e[1]); // 유효기간
console.log(e[0][1]); // 월
console.log(e[0][0]); // 연
let month = e[1] + e[0][1]; // 수집한 달 + 유효기간
e[0][1] = e[1] + e[0][1]; // 유효기간 + 월
console.log(month);
while (month > 12) {
// 12월이 넘어가면 +1년 이기 때문에 month가 12보다 클 때만 실행
e[0][0]++; // 연++
e[0][1] = month - 12; // 1년 지났으니까 달은 -12달
month -= 12; // while 반복
}
});
console.log(privacies);
//! 보관 가능한 날짜 구하기 => 유효기간 지난 날 -1일
privacies = privacies.map((e) => {
// e => e[날짜][유효기간]
console.log(e); // 개인정보 묶음
console.log(e[0][1]); // 월
console.log(e[0][2]); // 일
e[0][2] === 1 ? ((e[0][2] = 28), e[0][1]--) : e[0][2]--; //! 1일이라면 ? (true) 달: -1 , 일: 28일 : (false) 일: -1
console.log(e[0][1] < 10); // 월과 일이 한 자리수라면 앞에 0 붙이기
if (e[0][1] < 10) e[0][1] = `0${e[0][1]}`; // 월
if (e[0][2] < 10) e[0][2] = `0${e[0][2]}`; // 일
console.log(e);
return (e = Number(e[0].join(''))); // 다 붙이고 숫자 타입으로 변환
});
// privacies => 보관 가능한 마지막날로만 구성된 배열
console.log(privacies);
// today => 오늘 날짜
console.log(today);
// 서로 number 타입이니 보관 가능한 마지막날보다 오늘 날짜가 더 크다면 해당 인덱스에 +1한 번호를 push
// 번호는 1부터 시작이므로 인덱스 +1임
const result = [];
privacies.forEach((e, idx) => {
if (e < today) {
result.push(idx + 1);
}
});
console.log(result);
return result;
}
solution(
'2022.05.19',
['A 6', 'B 12', 'C 3'],
['2021.05.02 A', '2021.07.01 B', '2022.02.19 C', '2022.02.20 C']
); // expect output => [1, 3]
// solution("2020.01.01", ["Z 3", "D 5"], ["2019.01.01 D", "2019.11.15 Z", "2019.08.02 D", "2019.07.01 D", "2018.12.28 Z"]) // expect output => [1, 4, 5]
해당 부분은 너무 길어서 말로 풀 수가 없지만 주기적으로 한 번 읽어 봐야 도움이 될 것 같다 콘솔 주석을 꼼꼼히 써놔서 다행이다. 나는 모든 걸 배열로 끝을 냈는데 다른 사람들의 코드를 보니까 객체로 넣고 또 다른 부분은 구조분해할당을 통해 값을 받아 오는 형식을 보니까 나도 구조분해할당을 쓸걸..... 하는 아쉬움이 들었다. 그래도 푼 것에 의의를 두자 ^^