본문 바로가기

별걸다하는 IT/알고리즘 문제풀이

[백준 알고리즘]1924번-2007년(날짜 요일 구하기 문제 +프로그래머스 2016년)

 

백준(BAEKJOON) 알고리즘 문제 풀기

[1924번] 2007년 

----------------------------------------------------------------------------------------

 

문제: 오늘은 2007년 1월 1일 월요일이다. 그렇다면 2007년 x월 y일은 무슨 요일일까? 이를 알아내는 프로그램을 작성하시오.

시간제한: 2초,  메모리 제한 128MB

입력: 첫째 줄에 빈 칸을 사이에 두고 x(1<=x<=12)와 y(1<=y<=31)이 주어진다. 참고로 2007년에는 1,3,5,7,8,10,12월은 31일까지, 4,6,9,11월은 30일까지, 2월은 28일까지 있다.

출력: 첫째 줄에 x월 y일이 무슨 요일인지에 따라 SUN, MON, TUE, WED, THU, FRI, SAT중 하나를 출력한다.

 

예시1

입력: 1 1

출력: MON

예시2

입력: 3 14

출력: WED

 

ANSWER

문제의 핵심은 요일을 알아내는 것이죠. 요일은 일, 월, 화, 수, 목, 금, 토 즉 7일마다 반복된다는 특징이 있습니다. 

즉 2007년 1월 1일이 월요일이면 2007년 1월 8일 또한 월요일이라는 거죠! 해당 날짜 사이의 일수가 중요합니다. 이정도 눈치 챘으면 문제를 푸는 것은 어렵지 않아요 

 

각 월이 가지는 일수가 동일하면 총 일수를 계산하기 쉽겠지만.. 현재 우리 달력은 1,3,5,7,8,10,12월은 31까지, 4,6,9,11월은 30일까지 2월은 28일을 가지고 있어요. 각 월별 일자를 정리해놓으면 계산하기 좀 더 수월하겠죠?

총 일수를 더하는 거니까 3월이면 1,2월 달까지의 일수를 더한 값에 남은 일수를 더하고, 5월이면 1,2,3,4 월이 가지는 총 일수를 더한 후에 5월의 일수를 더하면 되겠네요! 즉 y는 한 번만 더해주면 된다는거. *항상 C/C++은 배열 크기에 신경을 써줍시다.

 

[C++언어]

#include <iostream>
using namespace std;

int main() {
    int x = NULL, y = NULL;
    int sum=0;
    int dayInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    const char* day[] = { "SUN","MON","TUE","WED","THU","FRI","SAT" };

    cin >> x >> y;
    for (int i = 1; i < x; i++)
    {
        sum += dayInMonth[i - 1];
    }
    sum += y;
    cout << day[sum % 7] << "\n";
    return 0;
}

메모리: 1984KB

시간: 0ms

코드 길이: 382B

 

이번에는 다른 관점에서 문제를 풀어볼게요. 수학적으로 말고 좀 더 단순한 반복 관점으로 살펴봅시다.

앞의 예시처럼 총 일수를 파악한 뒤 계산하는 방법도 있지만 1월 1일부터 원하는 날짜가 될때까지 하루하루를 세는 방법이 있어요. 손가락으로 세듯이, 1월 1일이 월요일이니까 1월 3일은 월요일 다음 화요일 다음 수요일.! 이런 방식이요 ㅎㅎ

이 때 기준은 1월 1일이 아니라 내가 입력한 월과 일이 됩니다. 1월 1일이 기준에 도달할 때까지 증가하면서 매번 확인하는 방법이예요.

 

[C언어]

#include <stdio.h>
int main() 
{ 
    int count_x =1, count_y =1;
    int x, y;
    int dayInMonth[] = { 31,28,31,30,31,30,31,31,30,31,30,31 };  
    const char* day[] = { "MON","TUE","WED","THU","FRI","SAT","SUN" }; 
    //1일이 기준이기 때문에 시작요일을 월요일로 둡시다.
    int sum = 0;

    scanf("%d%d", &x, &y); 
    while (x != count_x || y != count_y)  
    { 
        count_y++; //날짜를 하나씩 더해가면서 확인하는 거예요. 
        sum = (sum + 1) % 7; //월화수목금토일..월화수목금토일..
        if (count_y > dayInMonth[count_x-1]) //이렇게 하나하나 센 일수가 한달 일수와 똑같으면 
        { count_x++; count_y = 1; } //월을 하나 증가시켜주고 일수는 다시 1일이 됩니다.
    }
    printf("%s", day[sum]);
    return 0;
}

메모리: 1116KB

시간: 0ms

코드 길이: 454B

 

[Java]

import java.util.Scanner;

class Main{
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int x = sc.nextInt();
        int y = sc.nextInt();
        int sum =0;
        String[] day={"SUN","MON","TUE","WED","THU","FRI","SAT"};
        sum+=y;
        for(int i=1; i<x; i++){
            switch(i){
                case 1: case 3: case 5: case 7: case 8: case 10:
                    sum+=31; continue;
                case 2:
                    sum+=28; continue;
                case 4: case 6: case 9: case 11:
                    sum+=30; continue;
            }
        }
        System.out.println(day[sum%7]);
    }
}

메모리: 14336KB

시간: 104ms

코드 길이: 693B

 

이렇게 배열 대신 switch문을 이용해서 더해줄 수도 있습니다

알고리즘을 푸는 방법은 여러가지가 될 수 있어요. 정답이 꼭 정해져있는 것은 아니랍니다. 하지만 제 기준 C++방법이 좀 더 깔끔하고 마음에 드네욤 ㅎㅎ

 

연습문제

비슷한 문제로 프로그래머스 2016년 문제를 가져와봤습니다.

기준 날짜만 바꼈을 뿐 문제가 토시하나 틀리지 않아요! 연습삼아 풀어보세요

 

[프로그래머스] 2016년 

----------------------------------------------------------------------------------------

문제: 2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a,b를 입력받아 2016년 a월 일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각 SUN, MON, TUE, WED, THU, FRI, SAT입니다.

예를 들어 a=5,b =24라면 5월 24일은 화요일이므로 문자열 "TUE"를 반환하세요. 

 

제한조건:

2016년은 윤년입니다.

2016년 a월 b일은 실제로 있는 날입니다 (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다.

----------------------------------------------------------------------------------------

 

해당 문제 사이트 링크: https://programmers.co.kr/learn/courses/30/lessons/12901