카테고리 없음

[알고리즘] 아날로그 시계 문제

코딩연습중 2026. 2. 13. 16:50

 

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

 

프로그래머스에서 알고리즘 연습 중 기록을 위해 정리.

시침&초침, 분침&초침이 겹칠 때 알람이 울리는데, 처음에 어떻게 풀지 고민함.

초침이 시침&분침보다 뒤에 있다가 앞으로 넘어가는 부분을 찾아야겠다는 생각을 함.

초침이 뒤(왼쪽?)에 있는 경우를 -, 앞에 있는 경우를 +로 쳤을 때, 이게 바뀌면 카운트를 해야겠다고 생각했음..

그치만 구현이 까다로울 것 같아 아래의 방식으로 했더니 도저히 답이 나오지 않음.

class Solution {
    public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
        int answer = 0;
               
        double init_h = (double)(h1*60*60 + m1*60 + s1)/(12*60);
        double init_m = (double)(m1*60 + s1)/60;
        double init_s = (double)s1;
        
        double prev_h = init_h;
        double prev_m = init_m;
        double prev_s = init_s;
        
        boolean isFlag = false;
        
        // curr_m - curr_s <= 1 및 curr_h - curr_s <= 1인 경우에 봐야 함.
        if( ((prev_h - prev_s >= 0) && (prev_h - prev_s <= 1)) || ((prev_m - prev_s >= 0) &&(prev_m - prev_s <= 1))){
            isFlag = true;
        }
        
        // 알람 울리는지 판단
        if(prev_h==prev_s || prev_m==prev_s){
            answer += 1;
            isFlag = false;
        }
        
        
        // 본격적 비교
        for(int i = 1; i <= ((h2-h1)*60*60 + (m2-m1)*60 + s2-s1); i++){
            
            double curr_h = (prev_h + 1/(12*60))%60;
            double curr_m = (prev_m + 1/60)%60;
            double curr_s = (prev_s + 1)%60;
            
            if (isFlag){
                answer += 1;
                isFlag = false;
            }              
            if( ((curr_h - curr_s >= 0) && (curr_h - curr_s <= 1)) || ((curr_m - curr_s >= 0) &&(curr_m - curr_s <= 1))){
                isFlag = true;
            }           
            
            prev_h = curr_h;
            prev_m = curr_m;
            prev_s = curr_s;
        }   
        
        return answer;
        
    }
}

 

 

 

class Solution {
    public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
        int answer = 0;
               
        double init_h = (double)(h1*60*60 + m1*60 + s1)/(12*60);
        double init_m = (double)(m1*60 + s1)/60;
        double init_s = (double)s1;
        
        double prev_h = init_h;
        double prev_m = init_m;
        double prev_s = init_s;
        
        boolean h_Flag = false;
        boolean m_Flag = false;
        
        // curr_m - curr_s <= 1 및 curr_h - curr_s <= 1인 경우에 봐야 함.
        if((prev_h - prev_s >= 0) && (prev_h - prev_s <= 1)){
            h_Flag = true;
        }
        if((prev_m - prev_s >= 0) &&(prev_m - prev_s <= 1)){
            m_Flag = true;
        }
        
        // 알람 울리는지 판단
        if(prev_h==prev_s || prev_m==prev_s){
            answer += 1;
            h_Flag = false;
            m_Flag = false;
        }
        
        
        // 본격적 비교
        for(int i = 1; i <= ((h2-h1)*60*60 + (m2-m1)*60 + s2-s1); i++){
            
            double curr_h = (prev_h + 1/(12*60))%60;
            double curr_m = (prev_m + 1/60)%60;
            double curr_s = (prev_s + 1)%60;
            
            // 완전히 겹칠 때
            if(curr_h == curr_m && curr_m == curr_s){
                answer += 1;
                h_Flag = false;
                m_Flag = false;
                
                prev_h = curr_h;
                prev_m = curr_m;
                prev_s = curr_s;
                continue;
            }
            
            // flag 걸렸을 때
            if (h_Flag){
                answer += 1;
                h_Flag = false;
            }
            if(m_Flag){
                answer += 1;
                m_Flag = false;
            }            
            
            if((curr_h - curr_s >= 0) && (curr_h - curr_s <= 1)){
                h_Flag = true;
            } 
            if((curr_m - curr_s >= 0) &&(curr_m - curr_s <= 1)){
                m_Flag = true;
            }           
            
            prev_h = curr_h;
            prev_m = curr_m;
            prev_s = curr_s;
        }   
        
        return answer;
        
    }
}

 

이렇게 했더니

 

 

class Solution {
    public int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
        int answer = 0;
               
        double init_h = (double)(h1*60*60 + m1*60 + s1)/120;
        double init_m = (double)(m1*60 + s1)/10;
        double init_s = (double)s1*6;
        
        double prev_h = init_h;
        double prev_m = init_m;
        double prev_s = init_s;
        
        boolean h_Flag = false;
        boolean m_Flag = false;
        
        // curr_m - curr_s <= 1 및 curr_h - curr_s <= 1인 경우에 봐야 함.
        if(diff360(prev_h, prev_s) <= 6){
            h_Flag = true;
        }
        if(diff360(prev_m, prev_s) <= 6){
            m_Flag = true;
        }
        
        // 알람 울리는지 판단
        if(prev_h==prev_s || prev_m==prev_s){
            answer += 1;
            h_Flag = false;
            m_Flag = false;
        }
        
        // 본격적 비교
        for(int i = 1; i <= ((h2*60*60 + m2*60 + s2) - (h1*60*60 + m1*60 + s1)); i++){
            
            double curr_h = (prev_h + 1.0/(120))%360;
            double curr_m = (prev_m + 1.0/10)%360;
            double curr_s = (prev_s + 1.0*6)%360;
            
            // 완전히 겹칠 때
            if( curr_h == curr_m && curr_m == curr_s){
                answer += 1;
                h_Flag = false;
                m_Flag = false;
                
                prev_h = curr_h;
                prev_m = curr_m;
                prev_s = curr_s;
                continue;
            }
            
            // flag 걸렸을 때
            if (h_Flag){
                answer += 1;
                h_Flag = false;
            }
            if(m_Flag){
                answer += 1;
                m_Flag = false;
            }            
            
            // flag 걸기
            if(diff360(curr_h, curr_s) <= 6){
                h_Flag = true;
            } 
            if(diff360(curr_m, curr_s) <= 6){
                m_Flag = true;
            }           
            
            
            prev_h = curr_h;
            prev_m = curr_m;
            prev_s = curr_s;
        }   
        
        return answer;
        
    }
    
    static boolean eq(double a, double b) {
        return Math.abs(a - b) < 1e-9;
    }
    
    static double diff360(double a, double b) {
        return (a - b + 360.0) % 360.0; // 0 <= 결과 < 360
    }


}

교차판정이 맞는 것 같음

하 그리고 완전히 겹치는 경우는 저렇게 계산하면 될까,,?싶음

소수 비교가 정확할지 모르겠는데,,, 다음에 다시 이어서 풀어봐야지