문제 출처
https://school.programmers.co.kr/learn/courses/30/lessons/250135
문제 설명
시침, 분침, 초침이 있는 아날로그시계가 있습니다. 시계의 시침은 12시간마다, 분침은 60분마다, 초침은 60초마다 시계를 한 바퀴 돕니다. 따라서 시침, 분침, 초침이 움직이는 속도는 일정하며 각각 다릅니다. 이 시계에는 초침이 시침/분침과 겹칠 때마다 알람이 울리는 기능이 있습니다. 당신은 특정 시간 동안 알람이 울린 횟수를 알고 싶습니다.
다음은 0시 5분 30초부터 0시 7분 0초까지 알람이 울린 횟수를 세는 예시입니다.
![](https://blog.kakaocdn.net/dn/cdK1Kb/btsL1eMakyL/3JCOPl1EXoK7Ez3C41nK8k/img.png)
- 가장 짧은 바늘이 시침, 중간 길이인 바늘이 분침, 가장 긴 바늘이 초침입니다.
- 알람이 울리는 횟수를 세기 시작한 시각은 0시 5분 30초입니다.
- 이후 0시 6분 0초까지 초침과 시침/분침이 겹치는 일은 없습니다.
![](https://blog.kakaocdn.net/dn/kXdYC/btsL2IrpsCg/jRFP0yUg7PcgnJNLYgKUW0/img.png)
- 약 0시 6분 0.501초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다.
- 이후 0시 6분 6초까지 초침과 시침/분침이 겹치는 일은 없습니다.
![](https://blog.kakaocdn.net/dn/XFF3X/btsL1spMoIZ/LqOtQJHDkoUAGI8S66t3c0/img.png)
- 약 0시 6분 6.102초에 초침과 분침이 겹칩니다. 이때 알람이 한 번 울립니다.
- 이후 0시 7분 0초까지 초침과 시침/분침이 겹치는 일은 없습니다.
0시 5분 30초부터 0시 7분 0초까지는 알람이 두 번 울립니다. 이후 약 0시 7분 0.584초에 초침과 시침이 겹쳐서 울리는 세 번째 알람은 횟수에 포함되지 않습니다.
다음은 12시 0분 0초부터 12시 0분 30초까지 알람이 울린 횟수를 세는 예시입니다.
![](https://blog.kakaocdn.net/dn/ey1iko/btsL2bOm3QY/xfWIeM3AQOYkPjaEvYfFmK/img.png)
- 알람이 울리는 횟수를 세기 시작한 시각은 12시 0분 0초입니다.
- 초침과 시침, 분침이 겹칩니다. 이때 알람이 한 번 울립니다. 이와 같이 0시 정각, 12시 정각에 초침과 시침, 분침이 모두 겹칠 때는 알람이 한 번만 울립니다.
![](https://blog.kakaocdn.net/dn/zWNeG/btsL1eecMl8/7KajIF9LH02NPkG7TD2DW1/img.png)
- 이후 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초로 돌아가는 경우는 주어지지 않습니다.
![](https://blog.kakaocdn.net/dn/SEtfG/btsL2IkE1QT/291mNgKL0UlLRE8c49jbx0/img.png)
입출력 예 설명
입출력 예 #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번 울립니다.
풀이 방법
- 아날로그의 시계 이므로, 초당 각도가 변화되는 것을 인지하고 풀어야한다.
- 따라서 현재의 시간과 1초뒤의 상황을 각도로 변환해준 다음 끝까지 반복하여 값이 넘어가는 경우 ans에 카운트를 해준다
예외 상황
- 초기 시간이 0시이거나, 12시이거나 하면 먼저 값을 증가시키고 시작행야한다.
- 또한, 반복 도중 정각이 되는 경우(시,분,초침 모두 한위치)에는 1을 감소시켜주어야한다.(이전 if문에서 두번 증가되었음)
풀이코드 - Java
class Solution {
public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
int answer = 0;
//시간을 초로 변환하기
double start = h1 * 3600 + m1 * 60 + s1;
double end = h2 * 3600 + m2 * 60 + s2;
//0시이거나, 12시이거나
if(start == 0 || start == 12 * 3600){
answer++;
}
while(start < end){
//각도로 시간 계산하기
double hAngle = start / 120 % 360 ;
double mAngle = start / 10 % 360;
double sAngle = start * 6 % 360;
//다음 각도 보기
double nextHAngle = checkOnTime((start + 1) / 120 % 360);
double nextMAngle = checkOnTime((start + 1) / 10 % 360);
double nextSAngle = checkOnTime((start + 1) * 6 % 360);
//시침과 초침이 마주치거나, 분침과 초침이 마주치거나.
if(sAngle < hAngle && nextHAngle <= nextSAngle){
answer++;
}
if(sAngle < mAngle && nextMAngle <= nextSAngle){
answer++;
}
//동시에 겹치는 경우 1번 빼주기
if(nextSAngle == nextMAngle && nextSAngle == nextHAngle){
answer--;
}
start++;
}
return answer;
}
public double checkOnTime(double x){
if(x == 0){
return 360;
}
else return x;
}
}
Java 코드 결과
풀이 코드 - JavaScript
- 감을 잃지않기위해, 자바스크립트로도 풀어보았다.
function solution(h1, m1, s1, h2, m2, s2) {
var answer = 0;
//시간 초로 변환
let start = h1 * 3600 + m1 * 60 + s1;
let end = h2 * 3600 + m2 * 60 + s2;
if(start === 0 || start === 12 * 3600){
answer++;
}
while(start < end){
const hAngle = start / 120 % 360;
const mAngle = start / 10 % 360;
const sAngle = start * 6 % 360;
const nextHAngle = checkOnTime((start + 1) / 120 % 360);
const nextMAngle = checkOnTime((start + 1) / 10 % 360);
const nextSAngle = checkOnTime((start + 1) * 6 % 360);
if(sAngle < hAngle && nextHAngle <= nextSAngle){
answer++;
}
if(sAngle < mAngle && nextMAngle <= nextSAngle){
answer++;
}
if(nextSAngle === nextMAngle && nextSAngle === nextHAngle){
answer--;
}
start++;
}
return answer;
}
function checkOnTime(x){
if(x === 0){
return 360;
}
else return x;
}
- 사실 각도가 중요한 문제라... 코드에 별 차이는 없다.
JavaScript 결과
회고
- 왜 자바스크립트가 더 빠르지
'알고리즘' 카테고리의 다른 글
[백준] 주사위 굴리기 - Java (1) | 2025.01.31 |
---|---|
[백준] 숫자 정사각형 - Java (1) | 2025.01.26 |
[프로그래머스] 보석 쇼핑 - JavaScript (1) | 2025.01.24 |
[백준] 가장 가까운 세 사람의 심리적 거리 - Java (3) | 2025.01.23 |
[프로그래머스] 경주로 건설 - Java (1) | 2025.01.22 |