http://kldp.org/node/124415

위의 문제를 풀어보았다.

문제: 어떤 가게가 여는 시간이 a, 닫는 시간이 b라고 하자. x를 입력하면 가게가 열었는지 닫았는지 알려주는 함수를 만들어 보자.
예: a=2시, b=15시. f(x=12)=true, f(x=1)=false, f(x=17)=false
예: a=20시, b=5시. f(x=1)=true, f(x=12)=false, f(x=23)=true

C언어라고 가정하자.
가장 빠르게 떠오르는 답은 다음과 같다.
isOpen(int a, int b, int x){
  if a<b {
    if a<x && x<b{
      return true;
    } else{
      return false;
    }
  } else {
    if a>x || x>b{
      return true;
    } else{
      return false;
    }
  }
}

KLDP게시판에 많은 고수분들이 괜찮은 풀이를 올렸는데, 그중에 내가 제안한 것 두가지만 여기서 설명하도록 하겠다.

첫번째로
isOpen(int a, int b, int x){ return ((a-b)(x-a)(x-b)/abs((a-b)(x-a)(x-b))+1)/2; }
일단 a<b인 경우에 a<x<b이면 참을 반환하고, a>b인 경우에 b<x<a이면 거짓을 반환하면 된다. 잘 생각해보면, x-a와 x-b가 a<b인 경우에는 부호가 달라진다는 사실을 알 수 있다. 그리고 a-b<0이다. 따라서 (a-b)(x-a)(x-b)는 a<b이고 a<x<b인 경우에는 양수가 된다. 반대로 a>b이면 a-b는 양수이다. 이 경우에도 b<x<a이면 x-a와 x-b는 부호가 다르다. 따라서 세 항의 곱은 음수가 된다. 이 특징을 이용하면 true인 경우에는 양수이고 false인 경우에는 음수가 된다는 사실을 알아낼 수 있다. false는 0이므로 음수인 경우에 0을 반환해주기 위하여 식을 좀 더 복잡하게 썼다.
이 함수의 문제는 a=b, a=x, b=x인 경우에는 0으로 나누는 문제가 발생한다는 점이다. 예외처리를 위해서 if문을 쓸 수밖에 없게 된다.

두번째로
isOpen(int a, int b, int x){
    return (x-a+n)%n<(b-a+n)%n;
}

여기서 n은 하루의 길이를 나타내는 정수이다. 이런식으로 계산하는 것이 가능한 것은 24시간을 기준으로 할 때 항상 x<b이기만 하면 되기 때문이다. a와 b가 입력되는 숫자로는 a<b이거나 a>b일 수 있겠지만(a=b는?) 실제 개념으로는 항상 a<x<b이 성립한다. 따라서 0<x-a<b-a도 항상 성립한다. x-a와 b-a는 하루의 길이 내에서 존재하므로 %연산자를 써서 하루 단위로 잘라준다. 그런데 a>b인 경우에는 b-a가 음수가 되는데, 그런 사태를 막기 위해서 양변에 n을 더해준 후에 %로 잘라주게 된다.

세번째로
isOpen(int a, int b, int x){
    return (a-b)(x-a)(x-b)>0;
}

첫번째 답의 변형이다. 셋 중에서 제일 간단한 것 같다
.
by snowall 2011. 7. 17. 01:02