스터디 기록 26

유아현·2023년 1월 27일
0

Study

목록 보기
27/27
post-thumbnail

문제 목록

📌 [1차] 뉴스 클러스터링



 //? 집합 원소 만드는 함수
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]

해당 부분은 너무 길어서 말로 풀 수가 없지만 주기적으로 한 번 읽어 봐야 도움이 될 것 같다 콘솔 주석을 꼼꼼히 써놔서 다행이다. 나는 모든 걸 배열로 끝을 냈는데 다른 사람들의 코드를 보니까 객체로 넣고 또 다른 부분은 구조분해할당을 통해 값을 받아 오는 형식을 보니까 나도 구조분해할당을 쓸걸..... 하는 아쉬움이 들었다. 그래도 푼 것에 의의를 두자 ^^

0개의 댓글