문제 링크 : https://school.programmers.co.kr/learn/courses/30/lessons/150370
프로그래머스의 개인정보 수집 유효기간 문제이다.
문제
[오늘 날짜] [개인정보 수집 약관 종류] [등록된 사용자별 개인정보 수집약관 리스트] 를 input 으로 받고
[유효기간 만기 된 수집약관 리스트] 를 return 하는 문제이다.
문제 원본을 보려면 아래를 펼쳐 보자.
풀이
1. createTermsMap(terms) 메서드로 이용약관 종류를 정리한 key-value Map을 만든다.
function createTermsMap(terms) {
return terms.reduce((acc, curr)=> {
const [termName, term] = curr.split(' ')
acc.set(termName, Number(term));
return acc;
} ,new Map());
}
2. 각 이용약관 마다 '유효기간 만료' 여부를 판단하는 loop 를 시행한다.
유효기간이 지난 이용약관은 answer.push(idx+1) 해 준다.
1. createDateAndAddTerm 메서드는 이용약관 등록날짜 에서 유효기간을 더해 해당 약관의 만료일을 [cYear, cMonth, cDate] 로 리턴한다.
2. proccessYear 메서드는 유효기간이 '이번년도' 보다 지났다면 answer.push 해 주고, '다음년도' 이후라면 다음 루프를 돌도록 한다.
3. proccessMonth 메서드는 2. 의 로직을 'Month' 에 적용한다.
4. proccessDate 메서드는 2. 의 로직을 'Date' 에 적용한다.
(c.f. 각 메서드 내용은 아래의 전체코드 보기에서 볼 수 있다.)
privacies.forEach((priv, idx) => {
let [collectedDate, term] = priv.split(' ');
let [cYear, cMonth, cDate] = createDateAndAddTerm(collectedDate, termsMap, term);
if(proccessYear(answer, year, cYear, idx)){
return;
}
//연도는 같은 경우
if(proccessMonth(answer, month, cMonth, idx)){
return;
}
//달 이 같은 경우
proccessDate(answer, date, cDate, idx);
})
예외상황
1. javascript 에서의 나눗셈.
cMonth + 유효기간 이 12 를 초과할 경우, 12로 나눈 몫 만큼 cYear 에 더해줘야 한다.
그런데, javascript 의 Number 는 기본적으로 부동소숫점(float, double) 이므로 나눈 몫이 '소수'일 수가 있다.
그러므로 꼭 Math.floor 를 이용해 소숫점 아래는 버림해 몫을 정수로 만들어 주자.
(이것 때문에 제출 시 30% 이상 통과하지 못했다... 원인을 못 찾아 한참을 해맸다)
2. cMonth + 유효기간이 12의 배수일 때
cMonth + 유효기간 이 12 를 초과할 경우, 12로 나눈 몫 만큼 cYear 에 더해주고, 나머지를 cMonth 로 할당해준다.
그치만, 12의 배수인 경우(24, 36 ....) 12로 나눈 나머지가 0이 돼 cMonth 에 0을 할당해주게 된다.
이 경우엔 ( 몫 - 1 ) 을 해주고, cMonth 에 12를 할당해 주자.
전체 코드
function solution(today, terms, privacies) {
var answer = [];
const [year, month, date] = createDate(today);
const termsMap = createTermsMap(terms);
privacies.forEach((priv, idx) => {
let [collectedDate, term] = priv.split(' ');
let [cYear, cMonth, cDate] = createDateAndAddTerm(collectedDate, termsMap, term);
if(proccessYear(answer, year, cYear, idx)){
return;
}
//연도는 같은 경우
if(proccessMonth(answer, month, cMonth, idx)){
return;
}
//달 이 같은 경우
proccessDate(answer, date, cDate, idx);
})
return answer;
}
function createDate(today) {
const [year, month, date] = today.split('.');
return [Number(year), Number(month), Number(date)];
}
function createTermsMap(terms) {
return terms.reduce((acc, curr)=> {
const [termName, term] = curr.split(' ')
acc.set(termName, Number(term));
return acc;
} ,new Map());
}
function createDateAndAddTerm(collectedDate, termsMap, term) {
let [cYear, cMonth, cDate] = createDate(collectedDate);
cMonth += termsMap.get(term);
if(cMonth > 12) {
const quot = Math.floor(cMonth / 12);
const division = cMonth % 12;
if(division == 0){
cMonth = 12;
cYear += (quot-1);
}else {
cMonth = division;
cYear += quot;
}
}
return [cYear, cMonth, cDate];
}
function proccessYear(answer, year, cYear, idx) {
if(year > cYear) {
answer.push(idx+1);
return true;
}else if(year < cYear) {
return true;
}
return false;
}
function proccessMonth(answer, month, cMonth, idx) {
if(month > cMonth) {
answer.push(idx+1);
return true;
}else if(month < cMonth){
return true;
}
return false;
}
function proccessDate(answer, date, cDate, idx) {
if(date >= cDate) {
answer.push(idx+1);
}
}
'취업 > 코딩 테스트' 카테고리의 다른 글
[프로그래머스] 2023 KAKAO BLIND RECRUITMENT > 택배 배달과 수거하기 (javascript) (0) | 2023.01.07 |
---|