ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [알고리즘/자바스크립트] 초를 시:분:초 형태로 변환하기 (Human Readable Time)
    Algorithm 2019. 4. 5. 22:38

    -해당 문제는 codewars사이트의 level5 문제입니다. (1~8단계 중 8단계가 가장 쉬운 레벨)-

     

    [문제] Write a function, which takes a non-negative integer (seconds) as input and returns the time in a human-readable format (HH:MM:SS)

    HH = hours, padded to 2 digits, range: 00 - 99
    MM = minutes, padded to 2 digits, range: 00 - 59
    SS = seconds, padded to 2 digits, range: 00 - 59
    The maximum time never exceeds 359999 (99:59:59)

    You can find some examples in the test fixtures.

     

    [해석] 양수를 파라미터로 받아서 사람이 읽을 수 있는 시간의 형태로 변환하여라. (HH:MM:SS)

     

    HH = 시간, 00~99 범위의 2자리 수

    MM = 분, 00~59 범위의 2자리 수

    SS = 초, 00~59 범위의 2자리 수

    최대 시간은 359999초 이상을 넘지 않는다.


     

     

    며칠전에 스톱워치 구현하면서 시간 계산하느라 머리 터지는 줄 알았었는데

    알고리즘 문제도 시간 관련된 문제가 있길래 이 참에 한 번 풀어보기로 했다.

     

    나는 초등학교 때 시간 관련된 문제를 매우 매우 싫어했다.

    초2 때 엄마랑 아날로그 시계를 옆에 놓고 직접 돌려가면서

    이해하려고 애를 썼던 것 같은데 너무나 힘들었었지..

    그랬던 내가 지금 시간 알고리즘을 풀고 있다. 세상은 오래 살고 볼 일이다.

     

     

    function humanReadable(seconds) {
    	if(seconds < 60) {
    		return '00:00:' + addZero(seconds)
    	}
    	if(seconds < 3600) {
    		var min = Math.floor(seconds/60)
    		var sec = seconds - min*60
    		return '00:'+ addZero(min) + ':' + addZero(sec)
    	}
    	var hours = Math.floor(seconds/3600)
    	var min = Math.floor((seconds - hours*3600)/60)
    	var sec = seconds - hours*3600 - min*60
    	return addZero(hours) + ':' + addZero(min) + ':' + addZero(sec)
    
    	function addZero(num) {
    		return ((num < 10) ? '0' : '') + num
    	}
    }

    일단 내가 생각한 코드는 이렇다.

     

    1. seconds가 60 미만이면 연산할 필요가 없으니 그대로 '00:00:'을 앞에 붙여서 리턴한다.
    2. seconds가 3600 미만이면 분, 초만 계산하고 앞에는 '00:'을 붙여서 리턴한다.
      • seconds를 60으로 나누면 45.8889..와 같이 실수로 출력되는데 이 값에서 Math.floor()로 소수점 이하를 버리면 그 값이 분이 된다.
      • 그리고 seconds에서 (위에서 구한 분*60)을 빼준 값이 초가 된다.
    3. seconds가 3600 이상이면 시, 분, 초로 이루어져 있다는 뜻이니 위와 같은 방법으로 계산해서 리턴한다.
      • hours는 seconds를 3600(60*60)으로 나눈 값에서 소수점 이하를 버린 값이다.
      • min은 seconds에서 (위에서 구한 hours*3600)을 뺀 값에서 60을 나눈 값이다.
      • sec은 seconds에서 (hours*3600)과 (min*60)을 뺀 값이다.

     

     

    근데 생각해보면 저렇게 if문을 써서 3번에 걸쳐 코드를 쓸 필요는 없었다.

    만약에 처음 input값이 0초였다면 Math.floor(seconds/3600)을 하던 뭘 하던 어차피 연산결과가 0이 나올테니

    거기다 00:00:0을 붙여서 출력하면 그만이니까..

     

    항상 길게 길게 늘여 쓴 답안을 제출하고 다른 사람들 풀이를 보면

    1~3줄짜리 답변이 많아서 슬프다 흑흑..

    어쨌든 위의 알고리즘 그대로 간단하게 써보면 아래와 같다.

     

    function humanReadable(seconds) {
    	// sec
    	var hours = Math.floor(seconds/3600)
    	var mins = Math.floor((seconds - hours*3600)/60)
    	var secs = seconds - hours*3600 - mins*60
    
    	return addZero(hours) + ':' + addZero(mins) + ':' + addZero(secs)
    	function addZero(num) {
    		return ((num < 10) ? '0' : '') + num
    	}
    }

     

     

    나는 숫자가 1자리인 경우 앞에 '0'을 붙여서 '01', '02' 이런 식으로 출력하는 걸

    addZero()같이 함수 형태로 만들어서 사용하는데

     

    다른 사람 풀이에서 padStart()를 사용한 답변을 많이 발견했다.

    padStart()의 사용법은 다음과 같다.

    var num = '1'
    var addZero = num.padStart(2, '0')
    console.log(addZero) // -> '01'

    string01.padStart(num, string02)을 하면

    padStart는 string01의 length가 num이 될 때가지 string02를 string01앞에 붙여서 새로운 string을 만든다.

     

    같은 개념으로 padEnd()도 있는데 padEnd는 string01뒤에 string02를 붙인다.

     

    매우 편리하지만 안타깝게도(!) 역시나(!) 익스플로러에서 지원을 안한다.ㅋ...

    여러모로 뒤떨어진 익스플로러^^...

    반응형

    COMMENT