PS (C, C++)

[백준/C & C++] 1308 D-Day

최연재 2023. 2. 21. 08:00

https://www.acmicpc.net/problem/1308

 

1308번: D-Day

첫째 줄에 오늘의 날짜가 주어지고, 두 번째 줄에 D-Day인 날의 날짜가 주어진다. 날짜는 연도, 월, 일순으로 주어지며, 공백으로 구분한다. 입력 범위는 1년 1월 1일부터 9999년 12월 31일 까지 이다.

www.acmicpc.net

C

#include <stdio.h>
int isleap(int n)
{
	int result = 0;
	if (n % 4 == 0)
	{
		result = 1;
		if (n % 100 == 0) result = 0;
		if (n % 400 == 0) result = 1;
	}
	return result;
}
int main()
{
	int year, month, day, dyear, dmonth, dday, leap = 0, out=0;
	int dayofmonth[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31}}, dayofyear[2] = { 365,366 };
	long long result = 0;
	scanf("%d %d %d", &year, &month, &day);
	scanf("%d %d %d", &dyear, &dmonth, &dday);
	if (dyear - year > 1000) out = 1;
	else if (dyear - year == 1000) if ((dmonth > month) || (dmonth == month && dday >= day)) out = 1;
    
	if (out == 1) printf("gg");
	else
	{
		for (int i = year + 1; i < dyear; i++) result += dayofyear[isleap(i)];

		if (dyear == year)
		{
			leap = isleap(dyear);
			for (int i = month + 1; i < dmonth; i++) result += dayofmonth[leap][i - 1];
			if (dmonth == month) result += dday - day;
			else
			{
				result += dayofmonth[leap][month - 1] - day;
				result += dday;
			}
		}
		else
		{
			leap = isleap(year);
			result += dayofmonth[leap][month - 1] - day;
			for (int i = month + 1; i <= 12; i++) result += dayofmonth[leap][i - 1];
			leap = isleap(dyear);
			result += dday;
			for (int i = 1; i < dmonth; i++) result += dayofmonth[leap][i - 1];

		}
		printf("D-%lld", result);
	}
	return 0;
}

C++

#include <iostream>
using namespace std;

int isleap(int n)
{
	int result = 0;
	if (n % 4 == 0)
	{
		result = 1;
		if (n % 100 == 0) result = 0;
		if (n % 400 == 0) result = 1;
	}
	return result;
}
int main()
{
	int year, month, day, dyear, dmonth, dday, leap = 0, out = 0;
	int dayofmonth[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31} }, dayofyear[2] = { 365,366 };
	long long result = 0;
	cin >> year >> month >> day;
	cin >> dyear >> dmonth >> dday;

	if (dyear - year > 1000) out = 1;
	else if (dyear - year == 1000) if ((dmonth > month) || (dmonth == month && dday >= day)) out = 1;

	if (out == 1) cout << "gg";
	else
	{
		for (int i = year + 1; i < dyear; i++) result += dayofyear[isleap(i)];

		if (dyear == year)
		{
			leap = isleap(dyear);
			for (int i = month + 1; i < dmonth; i++) result += dayofmonth[leap][i - 1];
			if (dmonth == month) result += dday - day;
			else
			{
				result += dayofmonth[leap][month - 1] - day;
				result += dday;
			}
		}
		else
		{
			leap = isleap(year);
			result += dayofmonth[leap][month - 1] - day;
			for (int i = month + 1; i <= 12; i++) result += dayofmonth[leap][i - 1];
			leap = isleap(dyear);
			result += dday;
			for (int i = 1; i < dmonth; i++) result += dayofmonth[leap][i - 1];

		}
		cout << "D-" << result;
	}
	return 0;
}

코드 설명

전체적인 아이디어는 다음과 같다. 

현재 날짜와 D-DAY 날짜를 입력받는다. 캠프가 천년 이상 지속될 경우인지를 먼저 확인하고, 지속되는 경우일 경우 gg를 출력한다. 그렇지 않을 경우 else문을 수행한다. 오늘과 디데이가 2년 이상 차이가 난다면 오늘과 디데이 사이의 연도 일수를 합한다. (ex. 오늘이 2023년 ~이고, 디데이가 2025년 ~일 경우 2024년의 일수를 결과에 미리 더한다.)

오늘과 디데이가 같은 해라면 올해가 윤년인지 먼저 확인한다. 오늘과 디데이 사이의 달 일수를 더한다. (오늘이 2023년 2월 ~이고, 디데이가 2023년 5월~이라면 2023년 3월과 4월의 일수를 결과에 더한다.) 같은 달일 경우 디데이의 날짜(일)에서 오늘 날짜(일)를 빼준다.  다른 달일 경우 오늘 날짜에 해당하는 달의 일수에서 오늘 일을 빼준 값을 결과에 더하고, 결과에 디데이 날짜를 더한다. (ex. 오늘이 2023년 2월 21일이고, 디데이가 2023년 3월 2일이라면 28-21+2를 하면 디데이를 구할 수 있다.) 결과를 요구사항에 맞게 출력한다.

 

main 함수

오늘의 날짜를 year, month, day에 저장하고, 디데이 날짜를 dyear, dmonth, dday에 저장한다. 윤년인 경우와 아닌 경우를 나눠서 월의 일수를 2차원 배열로, 연의 일수를 배열에 저장해서 사용한다.

 

캠프가 천년 이상 지속되는지 확인하고 천년 이상 지속된다면 out에 1을 대입한다. 확인이 끝난 후 out이 1이라면 gg를 출력하고, 그렇지 않은 경우에는 디데이 계산을 한다. 계산 과정은 아이디어에 작성한 내용을 코드로 구현하면 된다.

 

📌오늘과 디데이 사이가 2년 이상 차이가 난다면 그 사이 연도의 일수를 결과에 더해준다. (이때 isleap함수로 해당 연도가 윤년인지 확인한다.)

 

📌오늘과 디데이가 같은 해일 경우에는 오늘의 날짜에서 연도가 윤년인지 확인한다. 오늘 바로 다음 달의 일수부터 디데이 직전 달의 일수를 반복문을 이용해서 결과에 더해준다. 만약 오늘과 디데이가 같은 달이라면 dday-day한 값을 결과에 더해준다. 같은 달이 아니라면 결과에 오늘이 속한 달의 전체 일수에서 오늘 일수를 뺀 값을 결과에 더한다. 그리고 결과에 dday값을 더하면 된다. 

 

📌 오늘과 디데이가 같은 해가 아닐 경우 올해가 윤년인지 확인한다. 이번 달의 남은 일수를 결과에 더한 후, 다음 달부터 12월까지의 일수를 반복문을 이용해서 결과에  더해준다. 이번에는 디데이 해가 윤년인지 확인하고, 1월부터 디데이 직전 달까지의 일수를 반복문을 이용해서 결과에 더한다. dday를 결과에 더하면 끝이다.

 

이렇게 구한 결과를 출력하고 프로그램을 종료한다.

 

isleap 함수

매개변수로 받는 연도가 윤년인지 확인하는 함수이다. 윤년의 기준을 이용해서 윤년인지 확인하고 윤년이라면 1을, 아니라면 0을 반환한다.

 

느낀 점

윤년인지에 따라 더하는 값이 달라지기에 2차원 배열을 이용해서 월의 일수를 저장했다. 연의 일수는 배열에 저장했다. 

처음에 아이디어를 잘 떠올리지 못해서 틀렸고, 문제를 푼 이후에도 조금 더 수정해보려다가 실패했다. 지금의 나에게 최선의 코드인 것 같다.