https://school.programmers.co.kr/learn/courses/30/lessons/150370?language=cpp
문제 설명이 줄줄이 길게 있다.
하지만 결국에 이 문제를 요약을 하면은 이런 문제다.
다음과 같이 today와 terms, privacies가 주어지고
privacies와 terms 더 한 거(만료일)을 today와 비교하는 문제이다.
그리고 만료일 < today라면 그걸 출력(index 출력)하라는 문제이다.
string today = "2022.05.19";
vector<string> terms = {"A 6", "B 12", "C 3"};
vector<string> privacies = {"2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"};
vector<int> solution(string today, vector<string> terms, vector<string> privacies) {
vector<int> answer; return answer;}
privacies와 terms 더 한거를 today와 비교하는 문제임
terms의 뒤의 month는 100이 될 수도 있음.
즉, 날짜에 대해서 +연산을 요구하고, 비교연산을 요구하는 문제이다.
이 문제 유형을 제대로 잡으면 다른 날짜 관련된 여러 문제에도 똑같이 적용시킬 수 있을 것 같다고 느꼈다.
그래서 같은 유형 문제에도 적용할 수 있도록 코드를 정리해보았다.
tran_date는 string 날짜를 int y,m,d로 변환하는 함수이다.
calc_date는 int로 된 y,m,d와 int형의 month를 받아 새로운 ry,rm,rd를 반환하는 함수이다.
comp_date는 int형의 y, m, d, yy, mm, dd를 받아서 비교(날짜와 날짜를 비교)하는 함수이다.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
void tran_date(const string& s, int& y, int& m, int& d) {
y = stoi(s.substr(0, 4)); // 연도 추출
m = stoi(s.substr(5, 2)); // 월 추출
d = stoi(s.substr(8, 2)); // 일 추출
}
void calc_date(int year, int month, int day, int term, int& ry, int& rm, int& rd) {
month += term;
year += (month - 1) / 12;
month = (month - 1) % 12 + 1;
day -= 1;
if (day == 0) {
month -= 1;
if (month == 0) {
year -= 1;
month = 12;
}
day = 28;
}
ry = year;
rm = month;
rd = day;
}
bool comp_date(int y, int m, int d, int yy, int mm, int dd) {
if (yy < y) return true;
if (yy == y && mm < m) return true;
if (yy == y && mm == m && dd < d) return true;
return false;
}
vector<int> solution(string today, vector<string> terms, vector<string> privacies) {
vector<int> answer;
unordered_map<char, int> mp;
int ty, tm, td;
tran_date(today, ty, tm, td);
// 보관 기간을 해시맵에 저장
for (const auto& term : terms) {
stringstream ss(term);
char c;
int month;
ss >> c >> month;
mp[c] = month;
}
// 개인정보 만료 여부 확인
int i = 0;
for (string privacy : privacies) {
string dateStr; int type;
stringstream ss(privacy);
ss >> dateStr >> type;
int y, m, d;
tran_date(dateStr, y, m, d);
int termDuration = mp[type];
int yy, mm, dd;
calc_date(y, m, d, termDuration, yy, mm, dd);
if (comp_date(ty, tm, td, yy, mm, dd)) {
answer.push_back(i + 1);
}
i++;
}
return answer;
}
int main() {
string today = "2022.05.19";
vector<string> terms = {"A 6", "B 12", "C 3"};
vector<string> privacies = {"2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"};
vector<int> result = solution(today, terms, privacies);
for (int idx : result) {
cout << idx << " ";
}
cout << endl;
return 0;
}
calc_date
왜 아래와 같이 계산할까?
month += term;
year += (month - 1) / 12;
month = (month - 1) % 12 + 1;
날짜에 month를 더하면 어떻게 되냐...
month에 12를 더하면
2022.05.19 => 2022.17.19=>2023.05.18이 된다.
month에 7을 더하면
2022.05.19 => 2022.12.19 이 된다.
즉, 월을 합한 결과가 12라면 아직 y에 더해주면 안된다. 즉, 0을 더 한다.
그리고 13이라면 y에는 1을 더해야 한다.
24와 25일 때도 같은 방식으로 생각해보면 더더욱 이해가 될 것이다.
결론적으로 year += (month - 1) / 12이다.(month는 현재 term과 합한 결과임)
12에서 13이 될 때 자릿수 초기화가 일어나기 때문에 (month - 1)을 기준으로 나눈 것이다.
month는 어떻게 될까?
12에서 13이 될 때 자릿수 초기화가 일어난다는 점이 같고,
month는 나머지로 구해진다.
그러므로 (month - 1) % 12라는 식이 될 것이라고 예상할 수 있다.
하지만, 좀 더 깊게 생각해야 한다.
12로 나눈 나머지는 0과 11이다. month는 0이 될 수 없고 1~12의 값만 가능하다.
그러므로 1을 더해줘야한다.
그래서 식이 month = (month - 1) % 12 + 1가 되는 것이다.
comp_date
year를 비교하고
year가 같으면 month를 비교하고
year와 month가 같으면 day를 비교한다.
전부 day의 개수로 변환
하지만 날짜 관련된 걸 비교하는 문제는 이 보다 더 쉽게 푸는 방법이 있다.
전부 day로 변환해서 푸는 것이다..!
그러면 calc_date와 같이 복잡하게 y, m, d를 계산할 필요가 전혀 없어지며
비교는 단순히 day를 비교하면 된다.
#include <algorithm>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void tran_date(string today, int &year, int &month, int &days) {
year = stoi(today.substr(0, 4));
month = stoi(today.substr(5, 2));
days = stoi(today.substr(8));
}
vector<int> solution(string today, vector<string> terms, vector<string> privacies) {
vector<int> answer;
int year;
int month;
int days;
tran_date(today, year, month, days);
int todayD = (year)*12 * 28 + (month - 1) * 28 + days;
vector<int> ar(privacies.size());
map<char, int> mp;
for (int i = 0; i < terms.size(); i++) {
stringstream ss(terms[i]);
char c;
int month;
ss >> c >> month;
mp[c] = month;
}
for (int i = 0; i < privacies.size(); i++) {
int y = stoi(privacies[i].substr(0, 4));
int m = stoi(privacies[i].substr(5, 2));
int d = stoi(privacies[i].substr(8, 2));
char c = privacies[i].back();
ar[i] = (y)*12 * 28 + (m - 1) * 28 + d + mp[c] * 28 - 1;
}
for (int i = 0; i < ar.size(); i++) {
if (ar[i] < todayD) {
answer.push_back(i + 1);
}
}
return answer;
}
'알고리즘' 카테고리의 다른 글
백준, 카데인 알고리즘 (0) | 2025.01.15 |
---|---|
백준 32350번 오버킬(overkill) 문제풀이 (1) | 2025.01.14 |
백준 2252 줄 세우기 (위상정렬) (2) | 2025.01.13 |
다익스트라, 벨만포드 알고리즘 (1) | 2024.12.23 |
백준 32714번 방벽게임 (0) | 2024.11.27 |