1. 문제 설명
(1) 오늘이 몇년, 몇월, 며칠인지 알려주고, 개인정보의 유형별로 정보 보관 기간을 알려준다.
(2) String 배열 형태로, 정보가 수집된 날짜
, 개인정보의 유형
이 주어질 때, 주어진 배열에서 오늘 파기될 정보가 무엇인지, 번호를 배열 형태로 반환하라.
2. 접근 방식
KEY WORD
: 문자열 자르기
해당 문제의 입력은 다음과 같이 주어진다.
today | terms | privacies | result |
---|---|---|---|
"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"] | [1, 3] |
"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"] | [1, 4, 5] |
여타 다른 문제들과 다르게, 해당 문제는 하나의 문자열에 여러가지 의미를 담고 있다. 또한 해당 의미가 "." 혹은 띄어쓰기로 구분되어 있기도 하다.
따라서 해당 문제는 문자열을 의미별로 적절히 잘라서 사용할 수 있는지를 묻고 있는 문제이다. 나는 이를 위해서 StringTokenizer
를 썼다. StringTokenizer(값, delim, delim 포함여부 boolean)의 인자가 들어간다. delim이 문자열을 나누는 기준이 되며, 3번째 인자의 true, false 여부에 따라 delim이 포함될지 안될지가 결정이 된다.
3. 코드 분석
import java.io.*;
import java.util.*;
class Solution {
// 1. map에 값 저장
// 2. 저장한 개인정보를 기준으로, 파기해야할 날짜 계산
// (1) 달 + 저장기간
// (2) 달 + 저장기간이 12개월을 초과하면, 년도 +1
// (3) 일은 현재 일자 -1 (만약 1일이라면 28일로 변경)
// 3. today랑 비교해서 현재 파기해야하는지 확인
static ArrayList<Integer> ans = new ArrayList<>();
static HashMap<String, Integer> map = new HashMap<>();
static int nowYear = 0;
static int nowMonth = 0;
static int nowDays = 0;
public int[] solution(String today, String[] terms, String[] privacies) {
StringTokenizer dDay = new StringTokenizer(today, ".", false);
nowYear = Integer.parseInt(dDay.nextToken());
nowMonth = Integer.parseInt(dDay.nextToken());
nowDays = Integer.parseInt(dDay.nextToken());
// map에 값 저장
for(int i = 0; i < terms.length; i ++){
StringTokenizer st = new StringTokenizer(terms[i], " ", false);
map.put(st.nextToken(), Integer.parseInt(st.nextToken()));
}
// 만료일 계산
for(int i = 0; i < privacies.length; i++){
StringTokenizer outer = new StringTokenizer(privacies[i]);
StringTokenizer inner = new StringTokenizer(outer.nextToken(), ".", false);
String term = outer.nextToken();
int expire = map.get(term);
int year = Integer.parseInt(inner.nextToken());
int month = Integer.parseInt(inner.nextToken());
int days = Integer.parseInt(inner.nextToken());
month += expire;
if(month > 12){
if(month%12 == 0){
year += month/12 -1;
month = 12;
}else {
year += month/12;
month = month%12;
}
}
days -= 1;
if(days == 0){
month --;
days = 28;
}
System.out.printf("파기 날짜: %d.%d.%d\n", year, month, days);
if(nowYear > year) {
ans.add((i+1));
}else if(nowYear == year && nowMonth > month){
ans.add((i+1));
}else if(nowYear == year && nowMonth == month && nowDays > days){
ans.add((i+1));
}
}
return ans.stream().mapToInt(i -> i).toArray();
}
}
4. 성장 하기
month += expire;
if(month > 12){
if(month%12 == 0){
year += month/12 -1;
month = 12;
}else {
year += month/12;
month = month%12;
}
}
days -= 1;
if(days == 0){
month --;
days = 28;
}
System.out.printf("파기 날짜: %d.%d.%d\n", year, month, days);
if(nowYear > year) {
ans.add((i+1));
}else if(nowYear == year && nowMonth > month){
ans.add((i+1));
}else if(nowYear == year && nowMonth == month && nowDays > days){
ans.add((i+1));
}
이까지의 식을 보면, 굳이 년, 월, 일을 따로 계산하여 문제를 풀어서, 문제를 기존보다 더 어렵게 풀었다. 년과 월은 모두 제일 작은 단위인 일(day)로 치환할 수 있다. 또한 문제에서 모든 달은 28일로만 이루어졌다고 했기에, 해당 계산이 훨씬 쉽다. 따라서 year -> day
: (year) x 12 x 28, month -> day
: (month) x 28 로 나타낼 수 있을 것이다. 이것을 이용해 모두 day로 치환 후 문제를 풀게 되면 위와 같이 가독성이 떨어지는 if, else문의 향연을 피할 수 있다!
public boolean isExpire(int year, int month, int day, int expire) {
int input = year*12*28 + month*28 + day + expire*28;
int now = nowYear*12*28 + nowMonth*28 + nowDays;
return input <= now? true : false;
}
이런식으로 치환해서 비교하는 함수를 만들면
if(isExpire(Integer.parseInt(inner.nextToken()),
Integer.parseInt(inner.nextToken()),
Integer.parseInt(inner.nextToken()),
map.get(outer.nextToken()))) ans.add((i+1));
input 값만 적절히 넣어주면 바로 개인정보 보관 기간의 만료 여부를 알 수 있다.
'알고리즘 > 문제 풀이' 카테고리의 다른 글
99클럽 코테 스터디 28일차 + [백준] 1874 스택 수열 java 풀이 (0) | 2024.08.18 |
---|---|
[백준] 30458 팰린드롬 애너그램 java 풀이 (0) | 2024.08.16 |
99클럽 코테 스터디 25일차 TIL + [프로그래머스] 순위 두 가지 풀이 ✨ (0) | 2024.08.15 |
[백준] 2644 촌수계산 java 풀이 (0) | 2024.08.08 |
99클럽 코테 스터디 18일차 TIL + [백준] 5547 일루미네이션 java 완벽 설명! ^^ (0) | 2024.08.08 |