-
[알고리즘/자바스크립트] 페이지 카운트 (Page Count)Algorithm 2019. 5. 1. 19:14
[문제] Viserion은 예민한 사람들이 많은 도서관에서 공부를 합니다.
Viserion은 한번에 특정 페이지를 열지 못하고, 교과서의 맨 앞장이나 맨 뒷장부터 차례로 넘길 수만 있습니다.
그래서 책을 넘기는 소리를 적게 내는 방법을 고민해야 합니다. 또한 항상 한번에 한페이지만 넘길 수 있습니다.
Viserion이 책 앞장을 펼치면, 항상 1페이지는 오른쪽에 있습니다.
* _________________________________
* | : |
* | : |
* | : |
* | : 1page |
* |_______________ : _______________|1페이에서 한장을 넘기면, 다음 장에는 2페이지와 3페이지가 있습니다.
* _________________________________
* | : |
* | : |
* | : |
* | 2page : 3page |
* |_______________ : _______________|교과서의 마지막장에는 주어진 책의 쪽수에 따라서 앞쪽에만 페이지가 출력되어있을 수도 있습니다.
총 n페이지의 교과서가 있고, Viserion이 p페이지를 읽고 싶을때, 가장 적은 횟수로 책을 넘겨 p페이지를 펼칠 수 있는 횟수는 얼마일까요?
예를들어, n=6인 교과서가 있고, p=2인 페이지를 열어보고 싶을때, 책을 가장 최소로 넘겨서 2페이지를 열 수 있는 방법은, 교재의 맨 앞장부터 넘기는 경우, 1번만 페이지를 넘기면 됩니다.
( 0 : 1 ) => ( 2 : 3 )
교과서의 맨 뒷장부터 넘기는 경우, 2번을 넘겨야 합니다.
( 6 : 0 ) => ( 4 : 5 ) => ( 2 : 3 )
따라서 가장 적게 책장을 넘기는 횟수는 1이 되며, 함수에서 1을 반환해주면 됩니다.
* @param {number} n
* @param {number} p
* @return {number}
만약에 어떤 책이 짝수페이지를 가지고 있다면 맨 왼쪽의 그림처럼 첫 페이지와 마지막 페이지는 왼쪽, 오른쪽에 공백 페이지를 가진다.
만약에 맨 왼쪽 그림처럼 어떤 책이 8p로 이루어져있다고 해보자.
여기서 내가 찾고자 하는 페이지가 책의 절반보다 작으면 앞에서부터 넘겨야하고 책의 절반보다 크면 뒤에서부터 넘겨야할 것이다.
즉, 내가 찾고자 하는 페이지가 3p라면 총 페이지 수인 8p를 2로 나눈 숫자 4보다 작기때문에 앞에서부터 책을 넘기는 것이 유리할 것이다.
그러나 만약에 내가 찾고자 하는 페이지가 5p라면 앞에서 넘기던 뒤에서 넘기던 상관이 없어진다.
그러나 찾고자 하는 페이지가 6p가 되어버리면 4p보다 숫자가 커지니까 뒤에서부터 책을 넘기는 것이 유리해진다.
위 논리로 책을 앞에서부터 넘기는 것이 좋을지 뒤에서부터 넘기는 것이 좋을지 판별한다.
※ 앞에서부터 넘기는 것이 유리한 경우:
- 내가 찾고자하는 p가 짝수라면 (예를 들어 2p or 4p)
찾고자하는 수를 2로 나눈 값을 출력한다.
만약에 위 그림에서 2p를 찾는다면 2 / 2 = 1번만 넘기면 (2 : 3) 페이지가 나온다.
4p를 찾는다면 4 / 2 = 2번만 넘기면 (4 : 5) 페이지가 나온다.
- 내가 찾고자 하는 p가 홀수라면 (예를 들어 1p or 3p)
찾고자하는 수를 2로 나눈 후 소수점을 버려서 출력한다.
즉, 위 그림에서 1p를 찾는다면 1 / 2 = 0.5 => 0번 넘기면 된다.
만약에 3p를 찾는다면 3 / 2 = 1.5 => 1번 넘기면 (2 : 3)페이지가 나온다.
※ 뒤에서부터 넘기는 것이 유리한 경우:
이 경우 살짝 복잡해지는데, 왜냐하면 총 페이지수가 짝수냐 홀수냐에 따라서
마지막 페이지가 2개가 보일 수도 있고 1개만 보일 수도 있기 때문이다.
- 전체 페이지수 n이 짝수라면 (예를 들어 8p)
전체 페이지수에서 내가 찾고자하는 페이지수를 뺀다.
예를 들어 찾는 페이지가 6p라면 8 - 6) = 2
여기에 1을 더한 후 2로 나눠서 소수점을 버린다.
1을 더하는 이유는 마지막 페이지에 공백페이지 1개가 더 있기 때문이다.
- 전체 페이지수 n이 홀수라면 (예를 들어 9p)
전체 페이지수에서 내가 찾고자하는 페이지를 뺀 후 2로 나눠서 소수점을 버린다.
코드로 표현하면 다음과 같다.
function pageCount(n, p) { // Complete the pageCount function. if(fromFront(n)) { // 앞에서부터 return (p % 2 === 0) ? (p / 2) : Math.floor(p / 2); } else { // 뒤에서부터 return (n % 2 === 0) ? Math.floor((n-p+1) / 2) : Math.floor((n-p) / 2); } // 앞에서부터 or 뒤에서부터 펼칠지 검사 function fromFront(num) { var center = parseInt(num / 2); if(p <= center) { return true; } } }
function pageCount(n, p) { // Complete the pageCount function. if(fromFront(n)) { // 앞에서부터 return (p % 2 === 0) ? (p / 2) : Math.floor(p / 2); } else { // 뒤에서부터 return (n % 2 === 0) ? Math.floor((n-p+1) / 2) : Math.floor((n-p) / 2); } // 앞에서부터 or 뒤에서부터 펼칠지 검사 function fromFront(num) { return p <= parseInt(num / 2); } }
(190515 피드백 받고 수정한 코드)
fromFront() 함수 안에 들어가는 구문을 구구절절 쓰지 않고 간단하게 정리할 수 있었다(!)
그냥 return문에 조건을 저렇게 넣으면 된다ㅋㅋ.. 허무..ㅋㅋㅋ
반응형'Algorithm' 카테고리의 다른 글
[알고리즘/자바스크립트] 꼬리에 붙은 0 (팩토리얼과 Trailing Zero) (0) 2019.05.12 [알고리즘/자바스크립트] 괄호 짝 찾기 (Valid Braces) (0) 2019.05.03 [알고리즘/자바스크립트] 영역 안에 떨어진 사과와 오렌지 개수 구하기 (Count Apples and Oranges) (0) 2019.05.01 [알고리즘/자바스크립트] 합해서 나눠떨어지는 쌍 찾기 (Divisible Sum Pairs) (0) 2019.05.01 [알고리즘/자바스크립트] 컵 돌리기 게임 (Find Key) (0) 2019.05.01 COMMENT