문제 출처
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의 배수라면 참으로 계산되도록 풀었었기 때문에 헷갈린 풀이였다.
■ 삼항 조건 연산자는 해석하기 어렵기는 하지만 코드가 간결해진다는 장점이 있다.
■ 즉, 이는 삼항 조건 연산자의 해석이 익숙해지면 오히려 가독성이 올라갈 수도 있다는 뜻이다.
■ 그러므로 일단 공부를 열심히 하자.