2D 볼록 껍질의 면적


11

2D 유클리드 평면에서 점의 직교 좌표 (엑스,와이) 를 나타내는 정수 쌍의 배열 / 목록 / 벡터가 제공됩니다 . 모든 좌표 사이 104104 , 중복이 허용됩니다. 가장 가까운 정수로 반올림 된 점 의 볼록 껍질 선체 면적을 찾습니다 . 정확한 중간 점은 가장 가까운 짝수로 반올림되어야합니다. 중간 계산에서 부동 소수점 숫자를 사용할 수 있지만 최종 결과가 항상 정확하다는 것을 보장 할 수있는 경우에만 가능합니다. 이것은 이므로 가장 짧은 올바른 프로그램이 승리합니다.

볼록 선체 포인트 세트의 포함 최소 볼록 집합 인 . 유클리드 평면에서 단일 점 (엑스,와이) 경우 점 자체입니다. 두 개의 별개의 점의 경우 점을 포함하는 선이고, 3 개의 비공 선 점의 경우 점이 형성되는 삼각형 등입니다.

볼록 껍질이 무엇인지에 대한 좋은 시각적 설명은 모든 점을 나무 판에 손톱으로 상상 한 다음 그 주위에 고무 밴드를 늘려서 모든 점을 둘러싸는 것으로 가장 잘 설명됩니다.
여기에 이미지 설명을 입력하십시오

일부 테스트 사례 :

Input: [[50, -13]]
Result: 0

Input: [[-25, -26], [34, -27]]
Result: 0

Input: [[-6, -14], [-48, -45], [21, 25]]
Result: 400

Input: [[4, 30], [5, 37], [-18, 49], [-9, -2]]
Result: 562

Input: [[0, 16], [24, 18], [-43, 36], [39, -29], [3, -38]]
Result: 2978

Input: [[19, -19], [15, 5], [-16, -41], [6, -25], [-42, 1], [12, 19]]
Result: 2118

Input: [[-23, 13], [-13, 13], [-6, -7], [22, 41], [-26, 50], [12, -12], [-23, -7]]
Result: 2307

Input: [[31, -19], [-41, -41], [25, 34], [29, -1], [42, -42], [-34, 32], [19, 33], [40, 39]]
Result: 6037

Input: [[47, 1], [-22, 24], [36, 38], [-17, 4], [41, -3], [-13, 15], [-36, -40], [-13, 35], [-25, 22]]
Result: 3908

Input: [[29, -19], [18, 9], [30, -46], [15, 20], [24, -4], [5, 19], [-44, 4], [-20, -8], [-16, 34], [17, -36]]
Result: 2905

2
테스트 사례가 있습니까?
Maltysen

17
코드 골프에서 공백을 계산하지 않는 것은 나쁜 생각입니다. 문자열을 코드로 변환하고 실행하기 위해 대량의 공백과 일반 코드가 포함 된 제출로 이어집니다.
xnor

4
정확한 중간 점은 가장 가까운 정수로 반올림해야합니다 . 그 이유는 무엇인지 궁금하십니까?
Arnauld

4
[[0, 0], [1, 1], [0, 1]]1/20

6
일반적으로 과제는 자체적으로 포함되어 있지만 그렇지 않습니다. 볼록 껍질이 무엇인지, 어떻게 계산할 수 있습니까? 아니면 참조 온라인 리소스를 가리 킵니까?
Olivier Grégoire

답변:


9

SQL Server 2012+, 84 바이트

SELECT Round(Geometry::ConvexHullAggregate(Geometry::Point(x,y,0)).STArea(),0)FROM A

SQL Server에서 지오메트리 함수와 집계를 사용합니다. 조정 A열은 x및 열이있는 테이블에서 가져옵니다 y.


9

Java 10, 405 ... 더 이상 맞지 않았습니다. 히스토리 편집을 참조하십시오. 317 316 bytes

P->{int n=P.length,l=0,i=0,p,q,t[],h[][]=P.clone(),s=0;for(;++i<n;)l=P[i][0]<P[l][0]?i:l;p=l;do for(h[s++]=P[p],q=-~p%n,i=-1;++i<n;q=(t[1]-P[p][1])*(P[q][0]-t[0])<(t[0]-P[p][0])*(P[q][1]-t[1])?i:q)t=P[i];while((p=q)!=l);for(p=i=0;i<s;p-=(t[0]+h[++i%s][0])*(t[1]-h[i%s][1]))t=h[i];return Math.round(.5*p/~(p%=2))*~p;}

-52 덕분 바이트 @ OlivierGrégoire
-3 덕분에 바이트 @PeterTaylor
-7 덕분에 바이트를 @ceilingcat을

온라인으로 사용해보십시오.

또는 299 반올림하지 않고 바이트 .. .

설명:

세 가지 단계가 있습니다.

  1. 입력 좌표를 기준으로 볼록 껍질의 점을 계산합니다 ( Jarvis 'Algorithm / Wrapping 사용 )
  2. 이 볼록 껍질의 면적을 계산하십시오
  3. 은행가의 반올림

볼록 껍질의 일부인 좌표를 계산하려면 다음 방법을 사용하십시오.

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

코드는 다음과 같습니다.

P->{                      // Method with 2D integer array as parameter & long return-type
  int n=P.length,         //  Integer `n`, the amount of points in the input
      l=0,                //  Integer `l`, to calculate the left-most point
      i=0,                //  Index-integer `i`
      p,                  //  Integer `p`, which will be every next counterclockwise point
      q,                  //  Temp integer `q`
      t[],                //  Temp integer-array/point
      h[][]=P.clone(),    //  Initialize an array of points `h` for the Convex Hull
      s=0;                //  And a size-integer for this Convex Hull array, starting at 0
  for(;++i<n;)            //  Loop `i` in the range [1, `n`):
    l=                    //   Change `l` to:
      P[i][0]<P[l][0]?    //   If i.x is smaller than l.x:
       i                  //    Replace `l` with the current `i`
      :l;                 //   Else: leave `l` unchanged
  p=l;                    //  Now set `p` to this left-most coordinate `l`
  do                      //  Do:
    for(h[s++]=P[p],      //   Add the `p`'th point to the 2D-array `h`
        q=-~p%n,          //   Set `q` to `(p+1)` modulo-`n`
        i=-1;++i<n;       //    Loop `i` in the range [0, `n`):
        ;q=               //      After every iteration: change `q` to:
                          //       We calculate: (i.y-p.y)*(q.x-i.x)-(i.x-p.x)*(q.y-i.y), 
                          //       which results in 0 if the three points are collinear;
                          //       a positive value if they are clockwise;
                          //       or a negative value if they are counterclockwise
           (t[1]-P[p][1])*(P[q][0]-t[0])<(t[0]-P[p][0])*(P[q][1]-t[1])?
                          //       So if the three points are counterclockwise:
            i             //        Replace `q` with `i`
           :q)            //       Else: leave `q` unchanged
      t=P[i];             //     Set `t` to the `i`'th Point (to save bytes)
  while((p=q)             //  And after every while-iteration: replace `p` with `q`
             !=l);        //  Continue the do-while as long as `p` is not back at the
                          //  left-most point `l` yet
  // Now step 1 is complete, and we have our Convex Hull points in the List `h`

  for(p=i=0;              //  Set `p` (the area) to 0
      i<s                 //  Loop `i` in the range [0, `s`):
      ;p-=                //    After every iteration: Decrease the area `p` by:
        (t[0]+h[++i%s][0])//     i.x+(i+1).x
        *(t[1]-h[i%s][1]))//     Multiplied by i.y-(i+1).y
    t=h[i];               //   Set `t` to the `i`'th point (to save bytes)
 return Math.round(.5*p/~(p%=2))*~p;}
                          //  And return `p/2` rounded to integer with half-even



6

자바 스크립트 (ES6),  191  189 바이트

자비스 행진 (일명 선물 포장 알고리즘)을 구현합니다 .

P=>(r=(g=p=>([X,Y]=P[p],Y*h-X*v)+(P.map(([x,y],i)=>q=(y-Y)*(P[q][0]-x)<(x-X)*(P[q][1]-y)?i:q,q=P[++p]?p:0,h=X,v=Y)|q?g(q):V*h-H*v))(v=h=0,([[H,V]]=P.sort(([x],[X])=>x-X)))/2)+(r%1&&r&1)/2|0

온라인으로 사용해보십시오!

또는 번거로운 반올림 체계가없는 170 바이트 .


반올림 영역은 항상 정확히 정수이기 때문에 반올림은 빨간색 청어였습니다.
Vladimir Reshetnikov

4
@VladimirReshetnikov 호기심에서 : 반올림이 붉은 청어라는 것을 알고 있다면 왜 그렇지 않으면 좋은 도전에서 벗어나기 위해 그것을 추가해야합니까? 죄송합니다 : 일반적으로 도전 같은 I 및 TBH .. PS, 내 자바 답을 작성하지만, 반올림과 볼록 선체는 도전 자체에 포함 된 그것을 upvoting에서 저를 자제하는 것입니다 무엇인지 설명이 부족 즐겼다 @Arnauld는 A와 이렇게 당신의 대답에 코멘트 ..
Kevin Cruijssen

4

R , 85 81 78 바이트

function(i,h=chull(i),j=c(h,h[1]))round((i[h,1]+i[j[-1],1])%*%diff(-i[j,2])/2)

온라인으로 사용해보십시오!

입력을 2 열 행렬로 사용합니다 (첫 번째는 x, 두 번째는) y. R은 round실제로 은행가의 반올림 방법을 사용하므로 여기에서 매우 운이 좋습니다.

나는(엑스나는1+엑스)(와이나는1와이나는)/2

-3 바이트의 Giuseppe에게 감사드립니다.


3

[R + sp 패키지], 55 바이트

function(x)round(sp::Polygon(x[chull(x),,drop=F])@area)

RDRR에서 사용해보십시오

anx 2 행렬을 취하고 둥근 영역을 반환하는 함수입니다. sp패키지를 사용합니다 . 은 drop=F하나의 좌표 경우를 처리하기 위해 필요합니다. TIO에 sp패키지 가 없기 때문에 데모에 사용되는 RDRR .

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