ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [프로그래머스 level2] 아날로그 시계 자바 시계 바늘 겹치는 횟수
    코딩테스트 2025. 4. 18. 10:07
    반응형

    https://school.programmers.co.kr/learn/courses/30/lessons/250135

     

    프로그래머스

    SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

    programmers.co.kr

    문제

    시작시간과 종료시간을 각각 의미하는 h1~s1 과 h2 ~ s2가 주어진다.

    시작시간 ~ 종료시간까지 초침이 돌아가는 동안, 초침이 시침 또는 분침과 겹친 횟수를 구하시오.

    단, 시침,분침,초침이 동시에 겹친 경우에는 겹친 횟수를 1회로 간주한다.

     

    접근 - 실패

    시침과 분침, 초침이 각각 초당 몇 도씩 움직이는지 계산한 후,
    초침의 각도와 시침각, 분침각이 겹치는 지 비교하는 코드를 사용함.
    그러나 테스트케이스의 반 이상 실패하여 폐기.
    public int solution2(int h1, int m1, int s1, int h2, int m2, int s2) {
            int start = h1 * 3600 + m1 * 60 + s1;
            int end = h2 * 3600 + m2 * 60 + s2;
            int count = 0;
            double epsilon = 1e-8;
    
            for (int t = start; t <= end; t++) {
                int h = (t / 3600) % 12;
                int m = (t % 3600) / 60;
                int s = t % 60;
    
                double secondAngle = s * 6.0;
                double minuteAngle = m * 6.0 + s * 0.1;
                double hourAngle = h * 30.0 + m * 0.5 + s / 120.0;
    
                boolean sameSecMin = isSame(secondAngle, minuteAngle, epsilon);
                boolean sameSecHour = isSame(secondAngle, hourAngle, epsilon);
    
                if (sameSecMin && sameSecHour) {
                    count++; // 한 번만 카운트
                } else if (sameSecMin || sameSecHour) {
                    count++;
                }
            }
    
            return count;
        }
        private boolean isSame(double a, double b, double epsilon) {
            double diff = Math.abs(a - b);
            return Math.min(diff, 360.0 - diff) < epsilon;
        }

    피드백

    새로운 방법을 시도하였음.
    '초침과 분침은 한시간에 59회 겹침' 과 '초침과 시침은 12시간동안 719회 겹침' 의 성질을 이용한 코드이다.
    public int solution2(int h1, int m1, int s1, int h2, int m2, int s2) {
            int start = h1 * 3600 + m1 * 60 + s1;
            int end = h2 * 3600 + m2 * 60 + s2;
            Set<Double> alarms = new HashSet<>();
    
            // 초침과 분침이 겹치는 시간: 60분마다 59번 발생
            for (int i = 0; ; i++) {
                // 초침과 분침은 60분마다 59번 겹침 → 주기: 3600 / 59초
                double t = i * 3600.0 / 59;
                if (t > end) break;
                if (t >= start){
                    alarms.add(t);
                }
    
            }
    
            // 초침과 시침이 겹치는 시간: 43200초(12시간) 동안 719번 발생
            for (int i = 0; ; i++) {
                double t = i * 43200.0 / 719;
                if (t > end) break;
                if (t >= start) {
                    alarms.add(t);
                }
    
            }
    
            return alarms.size();
        }

     

    ✅ 초침과 분침이 1시간(3600초) 동안 59번 겹치는 이유

    1. 분침과 초침의 속도 차이

    • 초침: 1초에 6도 (360도 / 60초)
    • 분침: 1초에 0.1도 (360도 / 3600초)
    • → 초침이 분침보다 초당 5.9도 더 빠릅니다.

    2. 겹치는 조건

    초침이 분침을 따라잡는 순간 = 두 바늘의 각도 차가 0도가 되는 순간.

    3. 겹침 횟수 계산 (상대속도 이용)

    • 초침은 1분마다 원을 한 바퀴 (360도) 돌고,
    • 그동안 분침은 6도 이동 (360도 / 60 = 6도)
    • 초침이 분침을 따라잡으려면 360도를 상대속도만큼 벌어야 함.

    👉 상대속도: 6 - 0.1 = 5.9도/초
    👉 한 바퀴(360도)를 따라잡기까지 걸리는 시간: 360 / 5.9 ≈ 61초
    즉, 약 61초마다 한 번 겹침

    4. 1시간 동안 몇 번 겹칠까?

    • 초침이 3600초 동안 몇 번 분침을 따라잡나?3600360/5.9=3600×5.9360≈59\frac{3600}{360 / 5.9} = \frac{3600 \times 5.9}{360} ≈ 59

    👉 그래서 초침과 분침은 1시간에 59번 겹칩니다.


    ✅ 초침과 시침이 12시간(43200초) 동안 719번 겹치는 이유

    1. 시침과 초침의 속도 차이

    • 시침: 12시간 = 43200초에 한 바퀴 → 0.00833도/초 (360 / 43200)
    • 초침: 6도/초
    • 상대속도: 6 - 0.00833 ≈ 5.9917도/초

    2. 겹침 주기 계산

    • 초침이 시침을 따라잡으려면 360도 상대속도로 돌면 됨.3605.9917≈60.06초\frac{360}{5.9917} ≈ 60.06 \text{초}

    즉, 약 60.06초마다 겹침 발생

    3. 12시간 동안 몇 번 겹치나?

    4320060.06≈719\frac{43200}{60.06} ≈ 719

    👉 그래서 12시간 동안 초침과 시침은 719번 겹칩니다.


    📌 요약

    겹치는 대상주기 (초)1시간 내 횟수12시간 내 횟수
    초침 - 분침 약 61초 59회 1416회
    초침 - 시침 약 60.06초 59.9회 719회

     

    알게된 것

    1. for문 end조건이 없는 상태로도 동작이 가능하다.
    2. 보다 상세한 계산에는 double이 더 적합하다.
    반응형

    댓글

Designed by Tistory.