[JAVA][백준 16463] 13일의 금요일
문제
재운이는 이 구역의 소문난 오컬트 매니아다. 늘 도서관에서 오컬트 서적을 읽고 외계문물 스터디에 참여하던 재운이는 어느 날 엄청난 소문을 듣게 되었다. 소문의 정체는 지구의 미래에 관한 예언이었는데, 그 예언에 따르면 2019년부터 다가오는 13일의 금요일의 수를 세지 않으면 지구가 멸망할 수 있다고 한다. 평소 배려심이 넘치는 재운이는 자신 뿐만 아니라 자신의 후세들을 위해 앞으로 기원 후 100,000년 까지 누적되는 13일의 금요일의 수를 매 년도마다 기록하기로 했다. 하지만 계산에 약한 재운이는 온갖 계산을 우리에게 떠맡겼다. 재운이를 도와 2019년부터 N년까지 누적되는 13일의 금요일의 수를 계산하여 알려주자.
입력
첫째 줄에 정수 N이 입력된다. (2019 ≤ N ≤ 100,000)
출력
첫째 줄에 2019년부터 N년까지 누적되는 13일의 금요일의 수를 출력한다
✨ Methodology
매년 돌면서, 각 월마다 13일이 금요일인지 확인하기
이 문제를 풀기 위해서 2019년 1월 1일의 요일을 확인해보았다. 1월 1일은 화요일로, 요일 배열을 만들 때 중요하게 작용한다 (직접 찾아봤는데 힌트에 써있었다...)
1. 윤년
이 문제를 풀기 위해서는 윤년에 대해서 이해할 필요가 있다.
2월은 28일 혹은 29일까지 있는데, N이 년도일 때,
- N % 4 == 0 이면 윤년이다 (29일)
- N % 4 == 0 이지만, N % 100 == 0이면 윤년이 아니다 (28일)
- 위 조건을 만족하지만, N % 400 == 0 이면 윤년이다 (29일)
위 조건을 코드로 표현하면, 아래와 같다.
if((N % 4==0 && N % 100!=0)||N % 400==0 )
2. 일수 배열과 요일 배열
각 월별 일수를 저장한 배열과 요일 배열이 필요하다.
일수 배열은
static int[] days = {0,31,28,31,30,31,30,31,31,30,31,30,31};
로 표현하였다.
- 0은 dummy data로 총 일수를 구하려면 그 전달까지의 full days와 해당 월의 13일을 더해야 하기 때문에 매 1월 13일을 편하게 구하기 위해서 넣어주었다. 요일맞추기에서 자세하게 설명하였다.
- 요일 배열은 화요일에서 부터 시작하기 때문에 가장 첫 원소로 월요일을 넣어주었다. 이 역시, 링크텍스트에서 설명하였지만 간단히 설명하자면 1월 1일이 월요일이라면 1월 8일도 월요일이 된다. 즉, 요일배열[days%7==1]=월요일이 되므로, 해당 문제에서는 1월 1일이 화요일이기 때문에 요일배열[1]이 화요일이 되기 위해선 0번째 원소는 월요일이 되어야 한다.
- 이 문제에서는 13일이 금요일인지를 확인하는 문제이기 때문에, 요일배열[전달까지의 총 일수+13일 % 7 ]이 금요일인지를 확인하면 된다.
3. for loop
- freaky_fridays라는 변수를 두어, 만일 13일이 금요일일 경우 ++시켜 13일이 금요일인 횟수를 카운트 해주었다.
- 브루트포스 방식으로 해당 2019년 부터 N 년도 까지 outer loop를 돌려 주었고, 해당 년도가 윤년인지 평년인지 계산하여 만약 윤년이라면 일수배열[2월달]을 29일로 설정 아니라면 28일로 설정하였다.
for(int i = 2019; i<=N ; i++) {//년
if((i%4==0 && i%100!=0)||i%400==0 ){//윤년일 경우 ->2월에 +1
days[2] = 29;}
else {days[2]=28;}//윤년이 아닐 경우
//inner for loop
}
- outer loop에서 해당 년도에 대한 루프를 돌렸기 때문에, inner loop를 생성하여 월별로 13일이 금요일인지 아닌지 확인하였다.
for(int i = 2019; i<=N ; i++) {//년
if((i%4==0 && i%100!=0)||i%400==0 ){//윤년일 경우 ->2월에 +1
days[2] = 29;}
else {days[2]=28;}//윤년이 아닐 경우
for(int j = 1; j<=12;j++) {//월
if(date[(total_days+13)%7]==5) {//13해당 월의 13일이 금요일인가?
//System.out.println(i+"년"+j+"월"); //몇년 몇월달의 13일이 금요일인지 확인 가능
freaky_fridays++;} //13일이 금요일이면 카운트 ++
total_days+=days[j];}//확인이 끝났다면 해당 월의 일수를 총 일수에 더한다
}
총 일수에 13을 더하고 금요일인지 확인한 후, 해당 월에 남은 일수를 더할 수도 있지만 개인적으로 직접 더하지 않고 전월까지의 총 일수+13일 % 7 로 이번달의 13일이 금요일인지 확인한 후, 해당 월의 총 일수를 더하는 방식이 더 쉽게 느껴져서 위처럼 코딩하였다.
✨ 전체 소스 코드
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class BOJ_16463_13일의금요일 {
static int[] days = {0,31,28,31,30,31,30,31,31,30,31,30,31};
static int[] date = {1,2,3,4,5,6,7};//월~일 : 1월 1일이 화요일임
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());//2019~N년
int freaky_fridays = 0;//13일의 금요일
int total_days = 0;
for(int i = 2019; i<=N ; i++) {//년
if((i%4==0 && i%100!=0)||i%400==0 ){//윤년일 경우 ->2월에 +1
days[2] = 29;
}
else {days[2]=28;}//윤년이 아닐 경우
//Base Case:
for(int j = 1; j<=12;j++) {//월
if(date[(total_days+13)%7]==5) {
//System.out.println(i+"년"+j+"월");
freaky_fridays++;}
total_days+=days[j];}
}
System.out.println(freaky_fridays);
}
}
Author And Source
이 문제에 관하여([JAVA][백준 16463] 13일의 금요일), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@junbee/JAVA백준-16463-13일의-금요일저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)