본문 바로가기

코딩/프로그래머스

[프로그래머스/JAVA] PCCP 기출문제 > 3번 > 아날로그 시계 (by 다알쥐AI)

728x90

[아날로그 시계] PCCP 기출문제 > 3번 > 아날로그 시계

 
 
※ 문제풀이 방법은 다양합니다. 참고만 해주세요 
[문제설명]

더보기

시침, 분침, 초침이 있는 아날로그시계가 있습니다. 시계의 시침은 12시간마다, 분침은 60분마다, 초침은 60초마다 시계를 한 바퀴 돕니다. 따라서 시침, 분침, 초침이 움직이는 속도는 일정하며 각각 다릅니다. 이 시계에는 초침이 시침/분침과 겹칠 때마다 알람이 울리는 기능이 있습니다. 당신은 특정 시간 동안 알람이 울린 횟수를 알고 싶습니다.

다음은 0시 5분 30초부터 0시 7분 0초까지 알람이 울린 횟수를 세는 예시입니다.

  • 가장 짧은 바늘이 시침, 중간 길이인 바늘이 분침, 가장 긴 바늘이 초침입니다.
  • 알람이 울리는 횟수를 세기 시작한 시각은 0시 5분 30초입니다.
  • 이후 0시 6분 0초까지 초침과 시침/분침이 겹치는 일은 없습니다.
  • 약 0시 6분 0.501초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다.
  • 이후 0시 6분 6초까지 초침과 시침/분침이 겹치는 일은 없습니다.
  • 약 0시 6분 6.102초에 초침과 분침이 겹칩니다. 이때 알람이 한 번 울립니다.
  • 이후 0시 7분 0초까지 초침과 시침/분침이 겹치는 일은 없습니다.

0시 5분 30초부터 0시 7분 0초까지는 알람이 두 번 울립니다. 이후 약 0시 7분 0.584초에 초침과 시침이 겹쳐서 울리는 세 번째 알람은 횟수에 포함되지 않습니다.

다음은 12시 0분 0초부터 12시 0분 30초까지 알람이 울린 횟수를 세는 예시입니다.

  • 알람이 울리는 횟수를 세기 시작한 시각은 12시 0분 0초입니다.
  • 초침과 시침, 분침이 겹칩니다. 이때 알람이 한 번 울립니다. 이와 같이 0시 정각, 12시 정각에 초침과 시침, 분침이 모두 겹칠 때는 알람이 한 번만 울립니다.
  • 이후 12시 0분 30초까지 초침과 시침/분침이 겹치는 일은 없습니다.

12시 0분 0초부터 12시 0분 30초까지는 알람이 한 번 울립니다.

알람이 울리는 횟수를 센 시간을 나타내는 정수 h1, m1, s1, h2, m2, s2가 매개변수로 주어집니다. 이때, 알람이 울리는 횟수를 return 하도록 solution 함수를 완성해주세요.


제한사항
  • 0 ≤ h1, h2 ≤ 23
  • 0 ≤ m1, m2 ≤ 59
  • 0 ≤ s1, s2 ≤ 59
  • h1시 m1분 s1초부터 h2시 m2분 s2초까지 알람이 울리는 횟수를 센다는 의미입니다.
    • h1시 m1분 s1초 < h2시 m2분 s2초
    • 시간이 23시 59분 59초를 초과해서 0시 0분 0초로 돌아가는 경우는 주어지지 않습니다.

입출력 예

입출력 예 설명

입출력 예 #1

문제 예시와 같습니다.

입출력 예 #2

문제 예시와 같습니다.

입출력 예 #3

0시 6분 1초부터 0시 6분 6초까지 초침과 시침/분침이 겹치는 일은 없습니다. 따라서 알람이 울리지 않으며 0을 return 해야 합니다.

입출력 예 #4

  • 11시 59분 30초부터 11시 59분 59초까지 초침과 시침/분침이 겹치는 일은 없습니다.
  • 12시 0분 0초에 초침과 시침, 분침이 겹칩니다. 이때 알람이 한 번 울립니다.

11시 59분 30초부터 12시 0분 0초까지 초침과 시침/분침이 겹치는 횟수는 1이며 따라서 알람이 한 번 울립니다.

입출력 예 #5

  • 약 11시 58분 59.917초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다.

11시 58분 59초부터 11시 59분 0초까지 초침과 시침/분침이 겹치는 횟수는 1이며 따라서 알람이 한 번 울립니다.

입출력 예 #6

  • 약 1시 5분 5.085초에 초침과 분침이 겹칩니다. 이때 알람이 한 번 울립니다.
  • 약 1시 5분 5.424초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다.

1시 5분 5초부터 1시 5분 6초까지 초침과 시침/분침이 겹치는 횟수는 2며 따라서 알람이 두 번 울립니다.

입출력 예 #7

0시 0분 0초부터 23시 59분 59초까지 초침과 시침/분침이 겹치는 횟수는 2852며 따라서 알람이 총 2852번 울립니다.

 

 

 


[간단설명]
주어진 시간동안, 초침이 360도 회전하면서,
시침과 분침을 지나치는 경우를 전부 더해서 리턴하는 문제
 
[접근방법]
1) 시작시간, 종료시간 초로 계산하기
2) 시침, 분침, 초침 1초당 얼만큼 각도가 움직이는지 계산하기
3) 초침이 시침, 분침을 지나가는 경우, 조건문 만들고, 카운트 +1
4) 시침과 분침이 겹치는 경우, 카운트 -1
 
[주의사항]
1) 12시 0분 0초 인 경우가 2번(00시, 12시) 존재하니, 이때는 카운트 +1 해주고 시작
2) 위에서 얘기했던 시침과 분침이 겹치는 경우 고려
3) 나누기 할때는 double형으로 캐스팅 해야 소수점 계산이 됨
 
[소스공개]

import java.util.*;
class Solution {
    public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
   
        // 시작시간(단위 : 초), 종료시간(단위 : 초)
        int start_time = h1*3600+m1*60+s1;
        int end_time = h2*3600+m2*60+s2;
        
        int answer = 0;
        //시작시간이 12시 0분 0초인 경우(0시,12시 2번 있음)
        if(start_time%360==0 || start_time%360==12) answer++;
        
        // 종료시간 될때까지 1초씩 증가
        while(start_time<end_time){
            // 시침 : 12시간에 360도 > 1시간(60분)에 30도 > 1분(60초)에 1/2도 > 1초에 1/120도 움직임
            // 분침 : 60분에 360도 > 1분(60초)에 6도 > 1초에 1/10도 움직임
            // 초침 : 60초에 360도 > 1초에 6도 움직임
            
            // 초로 계산한 현재시간을 시침,분침,초침 단위로 각도 계산
            // ex) 0시 5분 30초 start_time = 330초
            double h_angle = (start_time/(double)120)%360; //ex) 시침 : 2.750도
            double m_angle = (start_time/(double)10)%360;  //ex) 분침 : 33.0도
            double s_angle = (start_time*6)%360;           //ex) 초침 : 180도
            
            // 1초 지난후, 시침,분침,초침 단위로 각도 계산
            double h_angle_next = ((start_time+1)/(double)120)%360; //ex) 시침 : 2.758도
            double m_angle_next = ((start_time+1)/(double)10)%360;  //ex) 분침 : 33.1도
            double s_angle_next = ((start_time+1)*6)%360;           //ex) 초침 : 186도
            
            // 각도가 0도면 360도로 계산
            if(h_angle_next==0) h_angle_next=360;
            if(m_angle_next==0) m_angle_next=360;
            if(s_angle_next==0) s_angle_next=360;
            
            // 초침의 각도가 시침보다 작았는데, 시침을 넘어서는 경우
            if(s_angle<h_angle && s_angle_next>=h_angle_next) answer++;
            // 초침의 각도가 분침보다 작았는데, 분침을 넘어서는 경우
            if(s_angle<m_angle && s_angle_next>=m_angle_next) answer++;
            // 시침과 분침이 같아서 계산이 2번된 경우 -1
            if(h_angle_next==m_angle_next) answer--;
            
            // 1초 증가
            start_time+=1;
        }
        
        return answer;
    }
}

 
[실행결과]
 

728x90