우당탕탕 개발일지

[프로그래머스] Level 2. 아날로그 시계 본문

Algorithm(c++)/Level 2

[프로그래머스] Level 2. 아날로그 시계

devchop 2025. 2. 12. 11:25

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

 

프로그래머스

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

programmers.co.kr

 

해결 방법

  1. 맨처음 시작순간에 겹쳐져있다면, answer + 1을 해준다. 0시와 12시일때 겹쳐있을것이다. 
  2. 이제 시작시간과 끝시간을 초로 변경한다. 1초씩 이동하면서, 1초사이에 시침 혹은 분침과 겹치는 순간이 있는지를 체크한다. 
  3. 만약 시침,분침,초침이 모두 같은곳에 있다면, answer 을 2가 아니라 1만 올린다.

 

핵심 1 ) 특정시간에서 시침,분침,초침의 각도 구하기

시침은 12시간에 360도이므로, 1초에 1/120 도 움직인다. 분침은 60분에 360도이므로, 1초에 1/10도 움직인다. 초침은 60초에 360도이므로, 1초에 6도 움직인다. 그러므로 현재시간 sec이 주어졌을때 시,분,초침이 각각 몇도에 위치하는지를 알 수 있다.

vector<double> getDegree(int sec){
    double hDegree = fmod(sec/120.0f,360.0f);
    double mDegree = fmod(sec/10.0f, 360.0f);
    double sDegree = fmod(sec*6.0f, 360.0f);
    return vector<double>{hDegree,mDegree,sDegree};
}

 

핵심 2)  1초 사이에 겹쳤는지 확인하기

s 초일때 초침각도가 시침각도보다 작았는데, s+1초일때 초침각도가 시침각도보다 커졌다면, 그 사이에 겹쳤다는 것을 알 수 있다. 여기에서 정말 주의해야 하는것은, 초침이 59->0초로 이동할땐 일반적인 비교에서 걸러지지 않는다는 것이다. 따라서 초침이 59->0초로 이동했을때는 시침의 위치를 확인하여, 시침또한 59->0 사이에 있다면 겹쳤다고 판단하는 예외처리를 추가한다. 

bool hourMatch(vector<double> cnt, vector<double> next){
    if(cnt[0] > cnt[2] && next[0] <= next[2]){
        return true;
    }

    // 초침이 354도에서 0도로 넘어갈 때 예외 케이스
    // 초침이 59->0으로 이동하는데, 그때 시침또한 59쪽에 있다면
    // 위 if문에 걸리지않음. next초침은 0이기 때문. 
    if(cnt[2] == 354 && cnt[0] > 354){
        return true;
    }
    return false;
}

 

 

전체코드

#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

// 시침가 초침의 겹침을 판단
bool hourMatch(vector<double> cnt, vector<double> next){
    if(cnt[0] > cnt[2] && next[0] <= next[2]){
        return true;
    }

    // 초침이 354도에서 0도로 넘어갈 때 예외 케이스
    if(cnt[2] == 354 && cnt[0] > 354){
        return true;
    }
    return false;
}

vector<double> getDegree(int sec){
    double hDegree = fmod(sec/120.0f,360.0f);
    double mDegree = fmod(sec/10.0f, 360.0f);
    double sDegree = fmod(sec*6.0f, 360.0f);
    return vector<double>{hDegree,mDegree,sDegree};
}
// 분침과 초침의 겹침을 판단
bool minuteMatch(vector<double> cnt, vector<double> next){
    if(cnt[1] > cnt[2] && next[1] <= next[2]){
        return true;
    }

    // 초침이 354도에서 0도로 넘어갈 때 예외 케이스
    if(cnt[2] == 354 && cnt[1] > 354){
        return true;
    }
    return false;
}

int solution(int h1, int m1, int s1, int h2, int m2, int s2) {
    int answer = 0;

    int start = h1*3600 + m1*60 + s1;
    int end = h2*3600 + m2*60 + s2;
    
    // 그래서 0시 또는 12시에 시작한다면, 한번 겹치고 시작하는 것이기 때문에 +1
    if(start == 0 || start == 12*3600) answer++;
   
    // 현재 시간과 다음시간 비교. 1초사이에 겹치는지 확인. 
    for(; start < end; start++){
        vector<double> cnt = getDegree(start);
        vector<double> next = getDegree(start+1);

        bool hMatch = hourMatch(cnt,next);
        bool mMatch = minuteMatch(cnt,next);

        if(hMatch) answer++;
        if(mMatch) answer++;
        
        //초,분,시침 세개가 모두겹친다면 카운트를 한개만 ++해줘야함.
        if(hMatch && mMatch && next[0] == next[1]) answer--;
        
    }

    return answer;
}

 

 

마무리하며

이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고? 이게레벨2라고?

해답을 보고도 이해가 안되어서 1시간동안 들여다봤다. 진짜로 ㅠㅠ