행복한 엔더 문제


32

해피 엔딩 문제 (실제로는 정리) 상태가

일반 위치의 평면에서 5 개의 점 집합에는 볼록 사변형의 꼭지점을 형성하는 4 개의 점의 하위 집합이 있습니다.

폴 에르 도스 (Paul Erdős) 는이 문제에 처음으로 문제를 일으킨 두 명의 수학자 인 에스터 클라인 (Ester Klein)과 조지 세 케레스 (George Szekeres)가 약혼하고 결혼했습니다.

설명 :

  • 여기서 일반적인 위치 는 세 점이 동일 선상에 있지 않음을 의미합니다.
  • 4 개의 정점에 의해 형성된 사변형은 점의 순서에 관계없이 항상 교차하지 않는 것으로 간주됩니다. 예를 들어, 네 개의 포인트를 주어 [1 1], [1 2], [2 1], [2 2]의도 된 사각형은 정사각형이 아닌 나비 넥타이입니다 :

    여기에 이미지 설명을 입력하십시오

  • 내부 각도가 180도를 초과하지 않으면 교차하지 않는 사변형은 볼록 합니다. 또는 두 대각선이 사변형 안에있는 경우에도 마찬가지입니다.

도전

양의 정수 좌표를 가진 5 개의 점이 주어지면 볼록한 사변형을 형성하는 점 중 4 개를 출력합니다.

규칙

여러 솔루션이있는 경우 (즉, 4 포인트의 여러 세트), 솔루션 중 하나 또는 모두를 지속적으로 출력하도록 선택할 수 있습니다.

입력 및 출력 형식은 평소처럼 유연합니다 (배열, 목록, 목록 목록, 적절한 구분 기호가있는 문자열 등).

코드 골프, 가장 적은 바이트가 이깁니다.

테스트 사례

  1. 입력:

    [6 8] [1 10] [6 6] [5 9] [8 10]
    

    가능한 출력은 하나뿐입니다.

    [6 8] [1 10] [6 6] [5 9]
    
  2. 입력:

    [3 8] [7 5] [6 9] [7 8] [5 1]
    

    다섯 가지 해결책이 있습니다.

    [3 8] [7 5] [6 9] [7 8]
    [3 8] [7 5] [6 9] [5 1]
    [3 8] [7 5] [7 8] [5 1]
    [3 8] [6 9] [7 8] [5 1]
    [7 5] [6 9] [7 8] [5 1]
    
  3. 입력:

    [4 8] [1 9] [9 9] [10 2] [1 6]
    

    세 가지 해결책이 있습니다.

    [4 8] [1 9] [10 2] [1 6]
    [4 8] [9 9] [10 2] [1 6]
    [1 9] [9 9] [10 2] [1 6]
    

    다음은이 경우에 대한 세 가지 솔루션입니다.

여기에 이미지 설명을 입력하십시오


14
나는 긍정적 인 감정이 표현 된 Martin의 대답을 기대하고 있습니다.
El'endia Starman 2016 년

1
해피 엔딩 문제는 해피 엔더 문제와 혼동되어서는 안됩니다.이 문제는 군 신병들이 실제 시뮬레이션을 발견하지 못하도록 막는 방법 입니다.
user253751

답변:


24

CJam, 37 34 32 바이트

{e!Wf<{2*3ew{)f.-~W%.*:-V>},!}=}

:-V행복 여부 는 확실하지 않지만 K Zhang이 지적한 것처럼 =}끝에 있습니다. :)

중복을 제거하는 것이 비용이 많이 들기 때문에 하나의 솔루션 만 인쇄합니다.

여기에서 테스트하십시오.

설명

아이디어는 매우 간단합니다. 가능한 모든 사변형 (점의 모든 순서 포함)을 생성 한 다음 볼록한 것을 선택하면됩니다. 모든 모서리 쌍을보고 모두 같은 방향으로 회전하는지 확인하여 볼록 함을 테스트합니다.

도트 제품에서 터닝 센스를 매우 쉽게 얻을 수 있습니다. 사변형에서 세 개의 연속 점을 가져 와서 첫 번째에서 두 번째로, 첫 번째에서 세 번째로 선을 그린 후 후자를 이전의 수직선에 투영하면 기호가있는 숫자가 나타납니다 ... 이 세 점이 왼쪽 또는 오른쪽으로 회전하는지 여부 (이것에 대한 다이어그램을 추가해야 할 것입니다.)이 "수직 투영법"은 상당히 관련이있는 소리이지만 실제로는 두 벡터 중 하나를 뒤집어 곱셈 후 성분을 더하는 대신 빼는 것을 의미합니다. 코드는 다음과 같습니다.

e!       e# Generate all permutations of the five input points.
Wf<      e# Discard the fifth point in each permutations, giving all
         e# possible quadrilaterals.
{        e# Select the first for which this block gives a truthy result...
  2*     e#   Double the list of points, so that it includes each cyclically
         e#   adjacent set of three points.
  3ew    e#   Get all sublists of length 3, i.e. all sets of three consecutive
         e#   points (with two duplicates).
  {      e#   Filter these sets of three points...
    )    e#     Pull off the last point.
    f.-  e#     Subtract it from the other two, giving vectors from it to
         e#     to those.
    ~    e#     Unwrap the array dumping both vectors on the stack.
    W%   e#     Reverse one of them.
    .*   e#     Element-wise multiplication.
    :-   e#     Subtract the second element from the first. This completes
         e#     the projection.
    V>   e#     Check whether it's greater than 0. This is *false* for right-
         e#     turning sets of three points.
  },     e#   If all corners are right-turning, this will result
         e#   in an empty array.
  !      e#   Logical NOT - hence, only quadrilaterals where all corners
         e#   are right-turning give something truthy.
}=

2
물론, 행복한 오리!
Luis Mendo 2016 년

1
@LuisMendo 나는 마지막 두 문자가 더 스마일리 =}처럼 보인다고 생각합니다
K Zhang

!}윙크로 간주 될 수 있습니다
Jezzamon

2
CodeGolf의 존 소총은 ..이 놀랍
알렉스 칼슨

8

MATLAB, 67 바이트

I=input('');for k=~eye(5);if nnz(convhull(I(k,:)))>4;I(k,:),end;end

입력은 열이 각각 X와 Y 인 2D 행렬의 형태입니다.

[6 8; 1 10; 6 6; 5 9; 8 10]
[3 8; 7 5; 6 9; 7 8; 5 1]
[4 8; 1 9; 9 9; 10 2; 1 6]

볼록 사변형을 만드는 4 개의 점 집합이 모두 같은 형식으로 표시됩니다.

다음은 Octave에서 작동하도록 약간 수정 된 데모 입니다.

설명

이 솔루션은 입력의 4 포인트의 모든 하위 세트를 취합니다 (순서는 중요하지 않음). 이를 위해 아이덴티티 매트릭스를 생성하고 무효화합니다 ~eye(5). 이 행렬의 열을 k반복 하고 (루프 인덱스)는 고려해야 할 4 개 지점을 지정하는 논리 형 배열입니다. 그런 다음이를 사용하여 입력 ( I(k,:)) 에서이 4 개의 XY 포인트를 가져옵니다 .

그런 다음이 4 점 ( convhull) 의 볼록 껍질을 계산합니다 . 의 출력은 convhull볼록 껍질을 구성하는 점에 해당하는 입력의 인덱스입니다 (첫 번째 색인이 복제되어 선체를 닫습니다).

볼록 사변형의 경우, 4 개의 점 모두 동일한 점 ( nnz(convhull(points)) > 4) 의 볼록 껍질의 일부가 됩니다. 이것이 사실임을 감지하면이 특정 반복에 사용 된 포인트를 표시합니다.


4

자바 스크립트 (ES6), 306 293 283 바이트

c=(v,w,x)=>(w[0]-v[0])*(w[1]-x[1])-(w[1]-v[1])*(w[0]-x[0])>0?1:0
i=(v,w,x,y)=>(c(v,w,x)+c(w,x,y)+c(x,y,v)+c(y,v,w))%4==0&&r.push([v,w,x,y])
j=(v,w,x,y)=>{i(v,w,x,y);i(v,w,y,x);i(v,x,w,y)}
k=(v,w,x,y,z)=>{j(v,w,x,y);j(v,w,x,z);j(v,w,y,z);j(v,x,y,z);j(w,x,y,z)}
f=(v)=>(r=[],k(...v),r)

설명 :

이 함수 c는 다각형의 인접한 3 개 점 사이에서 벡터의 교차 곱을 계산하고 양수이면 1을, 그렇지 않으면 0을 반환합니다 (참고 : 점이 동일 선상에있을 수 없으므로 교차 곱은 0 일 수 없음).

j=(v,w,x,y)=>{i(v,w,x,y);i(v,w,y,x);i(v,x,w,y)}
k=(v,w,x,y,z)=>{j(v,w,x,y);j(v,w,x,z);j(v,w,y,z);j(v,x,y,z);j(w,x,y,z)}

함수 kj입력 배열 (순서를 반대로 무시) 모든 순환 순열을 생성한다.

i=(v,w,x,y)=>(c(v,w,x)+c(w,x,y)+c(x,y,v)+c(y,v,w))%4==0&&r.push([v,w,x,y])

그런 다음 각 순환 순열에 대해 함수 'i'가 호출되어 c인접한 좌표의 4 개의 트리플렛 각각에 대한 함수의 합을 계산합니다 . 교차 곱이 모두 같은 부호를 가지면 모두 0 또는 1이고 총합이 0 (모듈로 4)이되고 다각형이 오목하고 출력 배열로 푸시됩니다. 삼중 항의 부호가 다른 경우 총계는 0이 아니고 (모듈로 4) 다각형은 볼록합니다.

f=(v)=>(r=[],k(...v),r)

이 함수 f는 출력 배열을 초기화 한 다음 출력을 반환하기 전에 위의 함수를 호출하는 데 사용됩니다.

테스트 :

c=(v,w,x)=>(w[0]-v[0])*(w[1]-x[1])-(w[1]-v[1])*(w[0]-x[0])>0?1:0
i=(v,w,x,y)=>(c(v,w,x)+c(w,x,y)+c(x,y,v)+c(y,v,w))%4==0&&r.push([v,w,x,y])
j=(v,w,x,y)=>{i(v,w,x,y);i(v,w,y,x);i(v,x,w,y)}
k=(v,w,x,y,z)=>{j(v,w,x,y);j(v,w,x,z);j(v,w,y,z);j(v,x,y,z);j(w,x,y,z)}
f=(v)=>(r=[],k(...v),r)

tests = [
  [[6,8],[1,10],[6,6],[5,9],[8,10]],
  [[3,8],[7,5],[6,9],[7,8],[5,1]],
  [[4,8],[1,9],[9,9],[10,2],[1,6]]
];

tests.forEach(
  (test,i)=>{
    console.log( "Test " + (i+1) );
    f(test).forEach(
      (x)=>console.log( "  " + x.map((e)=>"("+e[0]+","+e[1]+")").join(','))
    );
  }
);

편집 :

원래 버전을 사용하고 처음 두 줄을 다음과 같이 변경하여 동일 직선상의 점을 처리 할 수도 있습니다.

t=(a,b,c)=>Math.sign((b[0]-a[0])*(b[1]-c[1])-(b[1]-a[1])*(b[0]-c[0]))
p=(a,b,c,d)=>[t(a,b,c),t(b,c,d),t(c,d,a),t(d,a,b)].filter(x=>x).reduce((p,c,i,a)=>p&c==a[0],1)
q=(a,m,n,o)=>[a[0],a[m],a[n],a[o]]
f=(a)=>{r=[];for(i=0;i<5;i++){b=a.slice();b.splice(i,1);r.push(q(b,1,2,3));r.push(q(b,1,3,2));r.push(q(b,2,1,3))}return r.filter((a)=>p(...a))}

그러나이 경우는 질문에서 특별히 제외되므로 추가 문자가 필요하지 않습니다.


3

Mathematica 105 96 바이트

Select[#~Subsets~{4},f@#&]&(5) 점 목록에서을 만족하는 4 점의 하위 집합을 선택 f합니다.

f만족 될 때 한 세트의 4 점의 각 점의 거짓말 RegionBoundaryConvexHull4 점.

f@p_:=Apply[And,RegionBoundary@ConvexHullMesh@p~RegionMember~#&/@p];
Select[#~Subsets~{4},f@#&]&

테스트 사례

1. {{6, 8}, {1, 10}, {6, 6}, {5, 9}, {8, 10}}의 5 개 부분 집합 (각 4 점)의 볼록 껍질을 살펴 보겠습니다. .

Select[#~Subsets~{4},f@#&[{{6, 8}, {1, 10}, {6, 6}, {5, 9}, {8, 10}}]

{{{6, 8}, {1, 10}, {6, 6}, {5, 9}}}


{{6, 8}, {1, 10}, {6, 6}, {5, 9}}만이 유일한 해결책입니다. 4 개의 점 각각은 볼록 껍질의 정점 (동일한 4 점)으로 사용됩니다.

해결책


{{6, 8}, {1, 10}, {6, 6}, {8, 10}}은 해결책이 아닙니다. 볼록 껍질에는 3 개의 정점이 있습니다. {6, 8}은 선체 안에 있습니다.

fail1


나머지 하위 집합도 솔루션이 아닙니다.

fail2

fail3

fail4


2. {{4, 8}, {1, 9}, {9, 9}, {10, 2}, {1, 6}}에는 세 가지 솔루션이 있습니다.

Select[#~Subsets~{4},f@#&[{{4, 8}, {1, 9}, {9, 9}, {10, 2}, {1, 6}}]

{
{{4, 8}, {1, 9}, {10, 2}, {1, 6}},
{{4, 8}, {9, 9}, {10, 2}, {1, 6 }},
{{1, 9}, {9, 9}, {10, 2}, {1, 6}}
}


3. {{3, 8}, {7, 5}, {6, 9}, {7, 8}, {5, 1}}에는 5 가지 솔루션이 있습니다.

Select[#~Subsets~{4},f@#&[{{3, 8}, {7, 5}, {6, 9}, {7, 8}, {5, 1}}]

{
{{3, 8}, {7, 5}, {6, 9}, {7, 8}},
{{3, 8}, {7, 5}, {6, 9}, {5, 1 }},
{{3, 8}, {7, 5}, {7, 8}, {5, 1}},
{{3, 8}, {6, 9}, {7, 8}, {5 , 1}},
{{7, 5}, {6, 9}, {7, 8}, {5, 1}}
}

5 개의 점 각각은 모든 점의 볼록 껍질의 경계에 있습니다.

점 중 하나가 제거되면 나머지 4 점은 각각 볼록 껍질이 축소 된 정점이됩니다.

sol2

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.