프로그래머스/자바 Lv2
[프로그래머스] Java Lv2. 코딩테스트 연습 > PCCP 기출문제 > 아날로그 시계 250135
행수쌤
2024. 11. 1. 11:21
728x90
반응형
문제설명
초침이 시침/분침과 겹칠 때마다 알람이 울리는 기능이 있는 시계가 있습니다. 특정 기간 동안 알람이 울린 횟수를 알고 싶습니다.
접근방법
- 아날로그 시계 360도를 기준으로 1초마다 시침, 분침, 초침의 위치를 판단
- (현재의 시침 위치 - 현재의 초침 위치) 의 부호와 (1초후의 시침 위치 - 1초후의 초침 위치) 의 부호가 다르거나 차이가 0이면 초침이 시침을 지나감
핵심로직
- 시작 시간과 끝 시간을 초 단위로 변경 후 for문을 돌려 1초마다 시침, 분침, 초침의 위치관계 파악
- 시침 : 초당 360 / 60(초) * 60(분) * 12(시) = 1 / 120
- 분침 : 초당 360 / 60(초) * 60(분) = 1 / 10
- 초침 : 초당 360 / 60 = 6
- 현재의 (시/분침 위치 - 초침 위치) * 1초후의 (시/분침 위치 - 초침 위치) <= 0 이면 초침이 시/분침을 지나갔거나 일치하는 상태이므로 answer ++
- 마지막 회차에 정확하게 일치하는 경우 판단
- 시/분/초침이 동시에 일치하게 되는 경우 판단
- double 사용 시 계산 오류가 발생하여 오답 케이스 발생. BigDecimal 사용하여 해결
입출력 예
- h1 = 0
- m1 = 5
- s1 = 30
- h2 = 0
- m2 = 7
- s2 = 0
- result = 2
코드 작성
import java.math.*;
class Solution {
public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
// 시작 시간과 종료 시간을 초 단위로 변환
int startTime = h1 * 3600 + m1 * 60 + s1;
int endTime = h2 * 3600 + m2 * 60 + s2;
int different = endTime - startTime; // 전체 시간 차이 (초 단위)
int answer = 0; // 결과 값을 저장할 변수
BigDecimal deivde120 = new BigDecimal("120"); // 시침의 이동 속도에 사용
BigDecimal deivde10 = new BigDecimal("10"); // 분침의 이동 속도에 사용
BigDecimal deivdeDot1 = new BigDecimal("0.1"); // 분침의 세분화
BigDecimal deivde6 = new BigDecimal("6"); // 초침의 이동 속도에 사용
BigDecimal remainder360 = new BigDecimal("360"); // 360도를 기준으로 한 바퀴
// 각 초에 대해 초침, 분침, 시침의 위치를 계산하여 특정 조건을 확인
for (int i = 0; i < different; i++) {
int currentTime = startTime + i; // 현재 초 단위 시간
BigDecimal hNeedle = new BigDecimal(String.valueOf(currentTime));
BigDecimal mNeedle = new BigDecimal(String.valueOf(currentTime));
BigDecimal sNeedle = new BigDecimal(String.valueOf(currentTime));
// 시침 위치 계산
hNeedle = hNeedle.divide(deivde120, 4, RoundingMode.HALF_UP).remainder(remainder360);
// 분침 위치 계산
mNeedle = mNeedle.divide(deivde10, 1, RoundingMode.HALF_UP).remainder(remainder360);
// 초침 위치 계산
sNeedle = sNeedle.multiply(deivde6).remainder(remainder360);
int nextTime = currentTime + 1;
// 다음 초의 시침 위치
BigDecimal hNeedle2 = new BigDecimal(String.valueOf(nextTime))
.divide(deivde120, 4, RoundingMode.HALF_UP).remainder(remainder360);
// 다음 초의 분침 위치
BigDecimal mNeedle2 = mNeedle.add(deivdeDot1);
// 다음 초의 시침 위치
BigDecimal sNeedle2 = sNeedle.add(deivde6);
// 시침이 기준값을 넘지 않도록 처리
if (hNeedle.compareTo(deivde120) == 1 && hNeedle2.compareTo(deivde120) <= 0) {
hNeedle2 = hNeedle2.add(remainder360);
}
// 초침이 분침을 지나가는지 여부를 확인
if (sNeedle2.compareTo(mNeedle2) != 0
&& sNeedle.compareTo(mNeedle) * sNeedle2.compareTo(mNeedle2) <= 0) {
answer++;
} else if (nextTime == endTime && sNeedle2.compareTo(mNeedle2) == 0) {
answer++;
}
// 초침이 시침을 지나가는지 여부를 확인
if (sNeedle2.compareTo(hNeedle2) != 0
&& sNeedle.compareTo(hNeedle) * sNeedle2.compareTo(hNeedle2) <= 0) {
answer++;
} else if (nextTime == endTime && sNeedle2.compareTo(hNeedle2) == 0) {
answer++;
}
// 초침, 분침, 시침이 일치할 때의 예외 처리
if (sNeedle.compareTo(hNeedle) == 0 && hNeedle.compareTo(mNeedle) == 0) {
answer -= 1;
} else if (nextTime == endTime
&& sNeedle2.compareTo(hNeedle2) == 0
&& hNeedle2.compareTo(mNeedle2) == 0) {
answer -= 1;
}
}
return answer;
}
}
728x90
반응형