링크 : 프로그래머스 > Level 1 > 개인정보 수집 유효기간
고객의 약관 동의를 얻어서 수집된 1~n번으로 분류되는 개인정보 n개가 있습니다. 약관 종류는 여러 가지 있으며 각 약관마다 개인정보 보관 유효기간이 정해져 있습니다. 당신은 각 개인정보가 어떤 약관으로 수집됐는지 알고 있습니다. 수집된 개인정보는 유효기간 전까지만 보관 가능하며, 유효기간이 지났다면 반드시 파기해야 합니다. 예를 들어, A라는 약관의 유효기간이 12 달이고, 2021년 1월 5일에 수집된 개인정보가 A약관으로 수집되었다면 해당 개인정보는 2022년 1월 4일까지 보관 가능하며 2022년 1월 5일부터 파기해야 할 개인정보입니다.당신은 오늘 날짜로 파기해야 할 개인정보 번호들을 구하려 합니다. 모든 달은 28일까지 있다고 가정합니다.
70분
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
public class PersonalInformationCollectionValidityPeriodTest {
@Test
void tester() {
int[] solution = solution("2022.05.19", new String[]{"A 6", "B 12", "C 3"},
new String[]{"2021.05.02 A",
"2021.07.01 B",
"2022.02.19 C",
"2022.02.20 C"});
System.out.println(Arrays.toString(solution));
Assertions.assertArrayEquals(new int[]{1,3}, solution);
}
public int[] solution(String today, String[] strTerms, String[] strPrivacies) {
// 약관 데이터 구조를 생성합니다.
HashMap<String, Integer> termsMap = new HashMap<>();
Arrays.stream(strTerms)
.forEach(strTerm -> {
String[] idAndLimitMonth = strTerm.split(" ");
termsMap.put(idAndLimitMonth[0], Integer.parseInt(idAndLimitMonth[1]));
});
// 각 개인정보의 유효한 날짜를 계산합니다.
List<LocalDate> validDates = Arrays.stream(strPrivacies)
.map(strPrivacy -> strPrivacy.split(" "))
.map(collectDateAndTerm -> toValidDate(collectDateAndTerm, termsMap))
.collect(Collectors.toList());
// 오늘 날짜와 비교하여 파기 여부를 판단합니다.
List<Integer> destroyPrivacies = new ArrayList<>();
LocalDate todayDate = toDate(today);
IntStream.range(0, validDates.size())
.forEach(index -> {
if (validDates.get(index).isBefore(todayDate)) {
destroyPrivacies.add(index + 1);
}
});
// 정수 배열로 변환하여 반환합니다.
return destroyPrivacies.stream()
.mapToInt(i -> i)
.toArray();
}
LocalDate toValidDate(String[] collectDateAndTerm, HashMap<String, Integer> termsMap) {
LocalDate collectDate = toDate(collectDateAndTerm[0]);
String termId = collectDateAndTerm[1];
Integer validMonth = termsMap.get(termId);
LocalDate validDate = collectDate.plusMonths(validMonth).minusDays(1);
if (collectDate.getDayOfMonth() == 1) {
validDate = LocalDate.of(validDate.getYear(), validDate.getMonth(), 28);
}
return validDate;
}
LocalDate toDate(String date) {
String[] todayItems = date.split("\\.");
return LocalDate.of(Integer.parseInt(todayItems[0]), // 년
Integer.parseInt(todayItems[1]), // 월
Integer.parseInt(todayItems[2])); // 일
}
}
70분이라는 시간동안 테스트 케이스를 통과하도록 작성한 날 것 그대로의 코드입니다.
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.IntStream;
public int[] solution(String today, String[] strTerms, String[] strPrivacies) {
// 특별히 유의해야할 제약사항은 보이지 않습니다.
class Privacy {
String term;
LocalDate collectedDate;
}
// 1. 각 개인정보의 파기 날짜를 계산합니다.
// 약관을 참조하기 쉽도록 맵으로 만듭니다.
HashMap<String, Integer> termsMap = new HashMap<>();
Arrays.stream(strTerms)
.forEach(strTerm -> {
String[] idAndLimitMonth = strTerm.split(" ");
termsMap.put(idAndLimitMonth[0], Integer.parseInt(idAndLimitMonth[1]));
});
// 개인정보를 참조하기 쉽도록 객체 목록으로 만듭니다.
List<Privacy> privacies = new ArrayList<>();
Arrays.stream(strPrivacies)
.forEach( strPrivacy -> {
String[] collectionAndTerm = strPrivacy.split(" ");
Privacy privacy = new Privacy();
String[] dateItems = collectionAndTerm[0].split("\\.");
privacy.collectedDate = LocalDate.of(Integer.parseInt(dateItems[0]), // 년
Integer.parseInt(dateItems[1]), // 원
Integer.parseInt(dateItems[2])); // 일
privacy.term = collectionAndTerm[1];
privacies.add(privacy);
});
// 개인정보.약관을 참조하여 개인정보.번호와 파기날짜로 구성된 객체를 생성한다.
class PrivacyDueDate {
int privacyId;
LocalDate dueDate;
}
List<PrivacyDueDate> privacyDueDates = new ArrayList<>();
IntStream.range(0, privacies.size())
.forEach(index -> {
PrivacyDueDate privacyDueDate = new PrivacyDueDate();
privacyDueDate.dueDate = toDueDate(privacies.get(index).collectedDate,
termsMap.get(privacies.get(index).term));
privacyDueDate.privacyId = index + 1;
privacyDueDates.add(privacyDueDate);
});
// 오늘 날짜와 비교하여 파기 여부를 판단합니다.
String[] todayItems = today.split("\\.");
LocalDate todayDate = LocalDate.of(Integer.parseInt(todayItems[0]),
Integer.parseInt(todayItems[1]),
Integer.parseInt(todayItems[2]));
List<Integer> dueDatePrivacies = new ArrayList<>();
privacyDueDates.forEach( privacyDueDate -> {
// 날짜 비교는 어떻게 수행할 것인가? 개인정보 파기 날짜보다 작거나 같은지 비교해야 한다.
if (privacyDueDate.dueDate.isBefore(todayDate)) {
dueDatePrivacies.add(privacyDueDate.privacyId);
}
});
// 배열 인덱스에서 1씩 더하여 개인정보 번호를 반환합니다.
int[] answer = new int[dueDatePrivacies.size()];
IntStream.range(0, dueDatePrivacies.size())
.forEach( index -> {
answer[index] = dueDatePrivacies.get(index);
});
return answer;
}
LocalDate toDueDate(LocalDate startDate, int month) {
LocalDate dueDate = startDate.plusMonths(month).minusDays(1);
if (startDate.getDayOfMonth() == 1) {
dueDate = LocalDate.of(dueDate.getYear(), dueDate.getMonth(), 28);
}
return dueDate;
}