[BAEKJOON] 백준 1308: D-Day (C#)

2024. 5. 22. 23:30IT/BaekJoon

문제 링크

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

 

 

문제

캠프에 오게 된 송유진은 캠프가 너무 지루해서 오늘로부터 캠프가 끝날 때 까지 며칠이나 남았는지 알아보고 싶었다. 그런데 캠프는 비상식적으로 길지도 몰라서 (윤년을 포함할지도 모른다) 손으로 하나하나 세기에는 힘들어 보였다.

더욱 정확한 계산을 위해, 유진이는 윤년이 정해지는 기준을 찾아보았고, 그것은 다음과 같았다.

  • 서력기원 연수가 4로 나누어떨어지는 해는 우선 윤년으로 한다. (2004년, 2008년, …)
  • 100으로 나누어떨어지는 해는 평년으로 한다. (2100년, 2200년, …)
  • 400으로 나누어떨어지는 해는 다시 윤년으로 한다. (1600년, 2000년, …)

그런데 캠프가 너무 길 경우, 사춘기인 유진이는 캠프에 무단으로 빠질지도 모른다.

 

 

입력

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

 

 

출력

오늘부터 D-Day까지 x일이 남았다면, "D-"를 출력하고 그 뒤에 공백 없이 x를 출력한다. 만약 캠프가 천년 이상 지속된다면 (오늘이 y년 m월 d일이고, D-Day가 y+1000년 m월 d일과 같거나 늦다면) 대신 "gg"를 출력한다. 오늘이 2월 29일인 경우는 주어지지 않는다.

 

 

 

통과한 답안

namespace _1308
{
    internal class Program
    {
        static void Main(string[] args)
        {
            string[] inputs = Console.ReadLine().Split(' ');
            int todayYear = int.Parse(inputs[0]);
            int todayMonth = int.Parse(inputs[1]);
            int todayDay = int.Parse(inputs[2]);
            inputs = Console.ReadLine().Split(' ');
            int dDayYear = int.Parse(inputs[0]);
            int dDayMonth = int.Parse(inputs[1]);
            int dDayDay = int.Parse(inputs[2]);

            if (dDayYear > todayYear + 1000 || (dDayYear == todayYear + 1000 && dDayMonth >= todayMonth && dDayDay >= todayDay))
            {
                Console.WriteLine("gg");
                return;
            }
            int today = ToDayNumber(todayYear, todayMonth, todayDay);
            int dDay = ToDayNumber(dDayYear, dDayMonth, dDayDay);
            Console.WriteLine($"D-{dDay - today}");
        }
        static int ToDayNumber(int year, int month, int day)
        {
            int number = 0;
            for (int i = 1; i < year; i++)
            {
                number += IsLeapYear(i) ? 366 : 365;
            }

            int[] dayInMonth = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
            
            if (IsLeapYear(year))
            {
                dayInMonth[1] = 29;
            }

            for (int i = 1; i < month; i++)
            {
                number += dayInMonth[i - 1];
            }

            number += day;
            return number;
        }

        static bool IsLeapYear(int year)
        {
            if (year % 400 == 0) return true;
            if (year % 100 == 0) return false;
            return year % 4 == 0;
        }
    }
}

 

year, month, day를 모두 day로 변환한 뒤에 둘의 차이를 구하는 방식으로 코드를 작성했다.

년도를 일로 바꾸는 경우에 가장 중요한 것은 윤년으로

IsLeapYear를 이용하여 이를 구하도록 작성하였다.

 

1년부터 해당 년도까지 윤년이면 366일을 윤년이 아니면 365일로 계산해서 더하고

월의 경우에는 배열을 만들어 둔 뒤에 윤년인지 판단하여 2월을 수정하고

각각의 월을 더하도록 구현하였다.

 

마지막으로 문제의 조건 중

만약 캠프가 천년 이상 지속된다면 (오늘이 y년 m월 d일이고,

D-Day가 y+1000년 m월 d일과 같거나 늦다면) 대신 "gg"를 출력한다.

라는 부분이 문제가 틀리는 가장 큰 이유인데

이는 문제의 조건 그대로 작성하면 된다.

 

if (dDayYear > todayYear + 1000 || (dDayYear == todayYear + 1000 && dDayMonth >= todayMonth && dDayDay >= todayDay))
{
    Console.WriteLine("gg");
    return;
}

 

위와 같이 작성 함으로써 해결할 수 있다.

왼쪽은 '년도 수가 1000년 이상 차이난다면'을 작성한 것이고

오른쪽이 1000년이 차이가 있는 경우인데

m월 d일과 같거나 늦다면 이므로

1년 1월 1일과 1001년 1월 1일 이라면 "gg"가 나와야 되므로

month와 day 둘 다 같거나 크게 작성하면 된다.