문제
https://school.programmers.co.kr/learn/courses/30/lessons/150370#
해설
문제가 길어 복잡해보이지만 부분으로 끊어보면 간단한 문제입니다.
개인정보에 따라 얻은 수집 일자에 약관에 맞는 유효기간을 더해, 오늘 날짜와 비교하면 됩니다.
3단계로 분류하면
1. terms배열에서 약관종류에 따른 값을 찾기 쉽도록 Map자료구조에 넣습니다.
2. 각 개인정보 별로 최종 유효기간을 구해줍니다.
3. 최종 유효기간과 현재 날짜를 비교해 파기 여부를 확인합니다.
이때 입력 값들은 필요한 정보가 한 String안에 공백(" ", whitespace) 또는 온점(".")으로 구분되어 있어 String의 함수 중 하나인 split를 사용하여 원하는 정보를 얻어줍니다.
이때 String배열로 나오는 결과값을 int배열로 바꿔주기 위해 Stream의 mapToInt함수를 사용해 간단하게 바꿉니다.
또 수집 일자에 유효기간을 더할 때 12의 배수인 경우 월이 0이 되지 않도록 확인하며 년으로 올림시 주의합니다.
최종 배열의 길이가 연산 수에 따라 변동되므로 List에 추가를 하고 마지막에 int배열의 형태로 변경해 줍니다.
이때 Stream에서 Integer(wrapper class)를 int(primitive class)로 변경하는 unboxing작업이 필요합니다.
주의점
- 모든 달은 28일 까지 있다고 가정한다.
- 월 -> 년으로 변환시 월은 1월부터 시작한다.
- 유효기간과 현재 날짜가 동일할 경우 파기한다.
- 약관의 유효기간은 100까지 가능하다.
- '.'으로 구분하여 split을 하려면 "\\."을 해주어야 한다.
코드
import java.util.*;
import java.util.stream.Stream;
class Solution {
public int[] solution(String today, String[] terms, String[] privacies) {
int[] answer = {};
List<Integer> ansList = new ArrayList<>();
// 1번 파트 : 맵을 사용해 약관을 찾기 쉽도록 저장
Map<String, Integer> t = new HashMap<>();
for(String term : terms){
String[] tmp = term.split(" ");
t.put(tmp[0],Integer.parseInt(tmp[1]));
}
int[] todays = Stream.of(today.split("\\.")).mapToInt(Integer::parseInt).toArray();
// 2번 파트 : 각 개인정보 수집 일자별 연산 실행
for(int i=0;i<privacies.length;i++){
String[] dateNterm = privacies[i].split(" ");
int[] date = Stream.of(dateNterm[0].split("\\.")).mapToInt(Integer::parseInt).toArray();
if((date[1] += t.get(dateNterm[1])) > 12){
if(date[1]%12==0){
date[0] += date[1]/12 -1;
date[1] = 12;
}else{
date[0] += date[1]/12;
date[1] = date[1]%12;
}
}
// 3번 파트 : 파기해야 하는 정보인지 비교
if(todays[0]>date[0] ||
todays[0]==date[0] && todays[1]>date[1] ||
todays[0]==date[0] && todays[1]==date[1] && todays[2]>=date[2]){
ansList.add(i+1);
}
}
answer = ansList.stream().mapToInt(i->i).toArray();
return answer;
}
}
추가 코드
좀 더 개선된 방식의 풀이도 소개하겠습니다.
이 문제에서는 년, 월, 일의 형태가 중요하지 않고 오직 현재 날짜를 지났는가 아닌가만을 확인하고 모든 달을 28일로 고정을 해주었습니다.
따라서 형태를 유지하며 단위 변화등을 고려하는 것 보다 가장 작은 일 단위로 변환하여 비교하는 것이 보기에 더 명확하고 실수가 나올 부분이 적다 생각이 되어 날짜가 나오는 다른 문제들에서 고려해보면 좋을 부분인 듯 합니다.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Solution {
public int[] solution(String today, String[] terms, String[] privacies) {
List<Integer> answer = new ArrayList<>();
Map<String, Integer> termMap = new HashMap<>();
int date = getDate(today);
for (String s : terms) {
String[] term = s.split(" ");
termMap.put(term[0], Integer.parseInt(term[1]));
}
for (int i = 0; i < privacies.length; i++) {
String[] privacy = privacies[i].split(" ");
if (getDate(privacy[0]) + (termMap.get(privacy[1]) * 28) <= date) {
answer.add(i + 1);
}
}
return answer.stream().mapToInt(integer -> integer).toArray();
}
private int getDate(String today) {
String[] date = today.split("\\.");
int year = Integer.parseInt(date[0]);
int month = Integer.parseInt(date[1]);
int day = Integer.parseInt(date[2]);
return (year * 12 * 28) + (month * 28) + day;
}
}
'[IT] 코딩테스트 > [문제 및 풀이] 프로그래머스' 카테고리의 다른 글
[프로그래머스] 없는 숫자 더하기 / 자바(Java) (0) | 2023.08.23 |
---|---|
[프로그래머스] 최소직사각형 / 자바(Java) (0) | 2023.08.22 |
[프로그래머스] 숫자 짝궁 / 자바(Java) (0) | 2023.08.15 |
[프로그래머스] 햄버거 만들기 / 자바(Java) (0) | 2023.08.14 |
[프로그래머스] 문자열 나누기 / 자바(Java) (0) | 2023.08.13 |