본문 바로가기
프로그래밍/알고리즘 문제풀이

[pg] 프로그래머스 개인정보 수집 유효기간

by 노잼인간이라불립니다 2023. 7. 25.

0. 개요

 그룹 스터디에서 코딩테스트 준비를 하기 위해서 여러가지 의견들이 있었지만 결국에는 프로그래머스 문제를 다 풀어보는 것으로 결정났다. 그래서 레벨 1에서는 카카오 기출, 그리고 레벨 2부터는 문제를 전부 풀어보는 것을 목표로 진행할 예정이다.

 

1. 문제 정의

 오늘의 문제를 요약하자면 다음과 같다.

 개인정보 수집에 동의한 날짜가 있고, 각 약관마다 유효기간이 다르다. (6달, 12달, 3달 등) 그래서 오늘 날짜를 기준으로 만료된 개인정보를 리턴하는 문제이다.

 

 주어지는 것은

1. 약관 타입과 약관 유효기간이 담긴 배열

2. 개인정보 번호, 약관타입, 개인정보 동의날짜 (yyyy.MM.dd)가 담긴 배열

3. 오늘 날짜

가 주어진다.

 주의해야할 것은 각 월을 28일 기준으로 계산된다는 점이다.

 

2. 나의 시도

 개인적으로 날짜 계산에 약한 나로써는 일자로 통일해서 계산하는게 좋다고 생각했다. 그래서 year, month, day를 넣으면 일수를 계산해주는 메서드를 작성하고 시작했다.

 

 1. 오늘의 날짜를 day로 바꿔준다.

 2. 약관 동의 날짜도 day로 바꿔준다.

 3. 약관 동의 day에 약관 유효기간 day를 더해준다.

 4. 오늘의 날짜 day 보다 약관 동의 날짜 + 유효기간이 같거나 적다면 유효기간이 만료되었으므로 결과 값에 추가한다.

 

이런 식의 흐름으로 작성했다.

 

3. code

public int[] solution(String today, String[] terms, String[] privacies) {
        /*
         * 유효기간이 만료된 privacy 번호를 담아 리턴할 answer
         */
        List<Integer> answer = new ArrayList<>();

        /*
         * 날짜를 day로 변환하기 위한 로직
         */
        String[] splitToday = today.split("\\.");
        Integer calculatedToday = calculateDay(splitToday[0], splitToday[1], splitToday[2]);

        /*
         * privacies에서 약관이 만료되는 날짜를 계산하려면 약관 타입을 가지고 terms에서 검색해야 하기 때문에 검색 성능이 좋은 map을 사용.
         */
        Map<String, Integer> termsMap = new HashMap<>();

        /*
         * terms 안에 있는 데이터를 map으로 넣어주는 로직
         */
        for (int i = 0; i < terms.length; i++) {
            String term = terms[i];
            String[] splitTerm = term.split(" ");
            String type = splitTerm[0]; // 약관 타입
            Integer period = Integer.parseInt(splitTerm[1].replace("달", "").trim()) * 28; // 유효기간
            termsMap.put(type, period);
        }

        /*
         * privacies를 순회하면서 해당 약관이 만료되었는지 확인 후 만료된 pravacy 번호를 List에 추가해주는 로직.
         */
        for (int i = 0; i < privacies.length; i++) {
            String privacy = privacies[i];
            String[] splitPrivacy = privacy.split(" ");
            String[] splitPrivacyDate = splitPrivacy[0].split("\\.");
            Integer privacyDay = calculateDay(splitPrivacyDate[0], splitPrivacyDate[1], splitPrivacyDate[2]) +
                            termsMap.get(splitPrivacy[1]);

            if(calculatedToday >= privacyDay){
                answer.add(i+1);
            }
        }
        return answer.stream().mapToInt(i->i).toArray();
    }


    /**
     * 날짜를 일로 변환하는 메서드
     *
     * @param year 년
     * @param month 월
     * @param day 일
     * @return 변환된 day
     */
    public Integer calculateDay(String year, String month, String day) {
        int yearDay = (Integer.parseInt(year) - 2000) * 12 * 28;
        int monthDay = Integer.parseInt(month) * 28;
        return yearDay + monthDay + Integer.parseInt(day);
    }

 

4. 깨닫거나 알게된 점

 이번에 문자열을 split을 했는데도 불구하고, OutOfBound Exception이 자꾸 발생해서, 디버깅을 해보았더니, 날짜가 정상적으로 split이 되지 않았다.

 검색을 해보니 .은 예약어이기 때문에 정상적으로 split을 하려면 \\.으로 split을 해야한다고 한다. 지금까지 split을 많이 사용했지만, 이런 경우는 처음이라 당황했다.

 그래도 이 기회에 알게 되어 다행이다. 코딩테스트 중간에 알아차렸다면, 디버깅하랴, 검색하랴 당황했을 것이다.

 

 

참조

https://school.programmers.co.kr/learn/courses/30/lessons/150370