리메이크 중/C,C++ 실습 중심

C(&C++) 실습 6. 윤년 계산하기

라이피 (Lypi) 2021. 6. 22. 22:00
반응형


문제 출처

backjoon 2753번 문제


0. 문제

ⅰ. 연도를 입력받고, 그 해가 윤년이면 1, 윤년이 아니면 0을 출력하는 프로그램을 작성하시오.

■ 윤년은 연도가 4의 배수이면서, 100의 배수가 아니거나 연도가 400의 배수일 때이다.

■ 예를들어 2000년은 4의 배수이면서 100의 배수이지만 400의 배수이므로 윤년이다.

■ 또한 2012년은 4의 배수이면서 100의 배수가 아니므로 윤년이다.

■ 입력되는 연도는 1 이상, 4000 이하의 자연수이다.


Ⅰ. 코드

#include <iostream>
using namespace std;

int main()
{
    int a = 0;
    cin >> a;
     
    if(a%4 == 0) {
        if(a%100 == 0) {
            if(a%400 == 0) {
                cout << "1";
            } else {
                cout << "0";
            }
        } else {
            cout << "1";
        }
    } else {
        cout << "0";
    }
    
    return 0;
}

■ 중첩 if문을 이용한 풀이. 문제의 조건을 그대로 표현하고 있지만 조금 난잡하다.

 

#include <iostream>
using namespace std;

int main()
{
    int year = 0;
    cin >> year;
     
    if (year%400 == 0) {
        cout << '1';   
        return 0;
    } 
    
    if (year%4 == 0) {
        if (year%100 == 0) {
            cout << '0';
        } else {
            cout << '1';
        }
    } else {
        cout << '0';
    }

    return 0;
}

■ 연도가 400의 배수일때는 항상 윤년임을 이용하여 그 부분을 먼저 확인하고 맞으면 출력 후 프로그램을 종료시켰다.

■ 그래도 4의 배수이면서 100의 배수인지 확인하는 부분이 중첩되어 있어서 난잡한 느낌이 든다.

 

#include <iostream>
using namespace std;

int main()
{
    int year = 0;
    cin >> year;
   
    if (year%400 == 0) {
        cout << '1';   
        return 0;
    } 
    
    if (year%4 == 0) {
        cout << (year%100==0?'0':'1');
    } else {
        cout << '0';
    }

    return 0;
}

■ 4의 배수일 때 100의 배수인지 확인하는 부분을 삼항 조건 연산자로 처리했다. 

■ 삼항 조건 연산자 자체가 가독성이 떨어지는 면이 있긴 하지만 조금 나은 것 같기도 하다.

 

#include <iostream>
using namespace std;

int main()
{
    int a = 0;
    cin >> a;
     
    cout << !(a%100?a%4:a%400);
    
    return 0;
}

■ 이 풀이는 다른 사람의 풀이를 보다가 발견한 풀이이다. (완전히 같지는 않다.)

■ 보기 좋고 나쁘고를 떠나 너무 신기해서 이를 분석해보려고 이 포스팅을 썼다.

 

#include <iostream>
using namespace std;

int main()
{
    int a = 0;
    cin >> a;
     
    cout << !( // (3)
    a%100     // (1)
    ?
    a%4       // (2) - 1
    :
    a%400     // (2) - 2
    );
    
    return 0;
}

■ 위의 삼항 조건연산자를 분해해보면 다음과 같으며 우선순위에 따라 (1) ~ (4)의 순서로 평가될 것이다.

■ (1) a%100을 계산한다. 즉, a가 100의 배수이면 0(거짓), 100의 배수가 아니면 0이외의 수(즉, 참)으로 평가된다.

■ 위에서 a%100 == 0 으로 a가 100의 배수일 때 참으로 평가한 것과는 반대로 작동한다.

 

■ (2) - 1 // a%100이 0이 아닌 경우 (즉, a가 100의 배수가 아닌 경우) a%4를 계산한다. 

■ (2) - 1은 입력된 값이 100의 배수가 아닐 때(즉, 4의 배수이면 윤년인 경우) 4의 배수인지를 확인한다.

■ (2) -1 // 4의 배수일 경우 윤년이며 값은 0이 나온다. 4의 배수가 아닐 경우 윤년이 아니며 값은 0이 아닌 값이 나온다.

 

■ (2) - 2 // a%100이 1인 경우 (즉, a가 100의 배수인 경우) a%400을 계산한다.

■ (2) - 2은 입력된 값이 100의 배수이다. 즉, 400의 배수가 아니라면 윤년이 아니다.

■ (2) -2 // 400의 배수일 경우 윤년이며 값은 0이 나온다. 400의 배수가 아닐 경우 윤년이 아니며 값은 0이 아닌 값이 나온다.

 

■ (3) // (2)의 결과에 따라 윤년일 경우 값은 0이 나왔고, 윤년이 아닐 경우 값은 0이 아닌 값이 나왔다.

■ 하지만 문제에서는 윤년이면 1을 윤년이 아니면 0을 출력하라고 했으므로 값을 바꿔준다.

■ 0이 아닌 값에 부정을 취하면 0이 되며, 0인 값에 부정을 취하면 1이 되어서 문제의 조건을 충족시킨다.

 

 


Ⅲ. 결론

■ 앞에서 a가 100의 배수라면 참으로 계산되도록 풀었었기 때문에 헷갈린 풀이였다.

■ 삼항 조건 연산자는 해석하기 어렵기는 하지만 코드가 간결해진다는 장점이 있다.

■ 즉, 이는 삼항 조건 연산자의 해석이 익숙해지면 오히려 가독성이 올라갈 수도 있다는 뜻이다.

■ 그러므로 일단 공부를 열심히 하자.

 

반응형