Diện tích thân tàu lồi 2D


11

Bạn được cung cấp một mảng / danh sách / vectơ của các cặp số nguyên biểu thị tọa độ cartesian của các điểm trên mặt phẳng Euclide 2D; tất cả các tọa độ nằm trong khoảng đến , các bản sao được cho phép. Tìm diện tích vỏ lồi của các điểm đó, làm tròn đến số nguyên gần nhất; một điểm giữa chính xác phải được làm tròn đến số nguyên chẵn gần nhất. Bạn có thể sử dụng số dấu phẩy động trong các tính toán trung gian, nhưng chỉ khi bạn có thể đảm bảo rằng kết quả cuối cùng sẽ luôn chính xác. Đây là , vì vậy chương trình đúng ngắn nhất sẽ thắng.(x,y)104104

Các thân lồi của một tập hợp các điểm là tập lồi nhỏ nhất chứa . Trên mặt phẳng Euclide, với bất kỳ điểm nào , nó là chính điểm đó; đối với hai điểm khác biệt, đó là đường thẳng chứa chúng, đối với ba điểm không thẳng hàng, đó là tam giác mà chúng tạo thành, v.v.PP(x,y)

Một lời giải thích trực quan tốt về những gì một thân tàu lồi, được mô tả tốt nhất là tưởng tượng tất cả các điểm như đinh trong một tấm gỗ, và sau đó kéo căng một dải cao su xung quanh chúng để bao quanh tất cả các điểm:
nhập mô tả hình ảnh ở đây

Một số trường hợp thử nghiệm:

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
Bạn có bất kỳ trường hợp thử nghiệm?
Maltysen

17
Không tính khoảng trắng trong mã golf là một ý tưởng tồi, nó dẫn đến việc đệ trình với chuỗi khoảng trắng lớn cộng với mã chung để chuyển đổi chuỗi thành mã và thực thi nó.
xnor

4
một điểm giữa chính xác nên được làm tròn đến số nguyên chẵn gần nhất : chỉ cần tự hỏi lý do đằng sau đó là gì?
Arnauld

4
@nwellnhof Đúng. Nhưng việc thực thi quy tắc này chỉ là một sự phiền toái đối với các ngôn ngữ không thực hiện theo cách đó (và tôi nghĩ Python 2 cũng không làm tròn được). Tôi không nghĩ rằng chúng ta nên làm tròn tất cả. Tam giác [[0, 0], [1, 1], [0, 1]]thực sự sẽ mang lại chứ không phải . 01/20
Arnauld

6
Thông thường các thử thách là khép kín, nhưng thử thách này thì không. Bạn có thể giải thích một thân tàu lồi là gì và làm thế nào để tính toán nó? Hoặc chỉ đến một số tài nguyên trực tuyến tham khảo?
Olivier Grégoire

Câu trả lời:


9

Máy chủ SQL 2012+, 84 byte

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

Sử dụng các hàm và tập hợp hình học trong SQL Server. Tọa độ là từ bảng Avới cột xy.


9

Java 10, 405 ... không còn phù hợp nữa; xem lịch sử chỉnh sửa .. 317 316 byte

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 byte nhờ @ OlivierGrégoire
-3 byte nhờ @PeterTaylor
-7 byte nhờ @ceilingcat

Hãy thử trực tuyến.

Hoặc 299 byte mà không làm tròn .. .

Giải trình:

Có ba bước để làm:

  1. Tính toán các điểm cho Hull Convex dựa trên tọa độ đầu vào (sử dụng Thuật toán / Gói của Jarvis )
  2. Tính diện tích của thân lồi này
  3. Làm tròn ngân hàng ..

Để tính toán tọa độ là một phần của Convex Hull, chúng tôi sử dụng phương pháp sau:

Đặt điểm và về tọa độ ngoài cùng bên trái. Sau đó tính điểm tiếp theo theo chiều quay ngược chiều kim đồng hồ; và tiếp tục làm như vậy cho đến khi chúng tôi quay trở lại điểm ban đầu . Đây là một hình ảnh cho điều này:lppl

nhập mô tả hình ảnh ở đây

Đối với mã:

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

JavaScript (ES6),  191  189 byte

Thực hiện cuộc diễu hành Jarvis (còn gọi là thuật toán gói quà).

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

Hãy thử trực tuyến!

Hoặc 170 byte mà không có sơ đồ làm tròn cồng kềnh.


Làm tròn chỉ là một cá trích đỏ vì hai lần diện tích luôn luôn chính xác.
Vladimir Reshetnikov

4
@VladimirReshetnikov Vì tò mò: nếu bạn biết làm tròn là một cá trích đỏ, thì tại sao lại thêm nó để đánh lạc hướng khỏi thách thức tốt khác? .. Không phải tất cả các ngôn ngữ đều tạo ra cách làm tròn của Banker, thậm chí không phải là ngôn ngữ nổi tiếng như JS và Java. Tôi thích thử thách nói chung và rất thích viết câu trả lời Java của tôi, nhưng làm tròn và thiếu giải thích Convex Hull là gì để khiến cho thử thách khép kín khiến tôi không thể nâng cao nó, tbh .. PS: Xin lỗi @Arnauld để làm điều này như một bình luận trong câu trả lời của bạn ..
Kevin Cruijssen

4

R , 85 81 78 byte

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

Hãy thử trực tuyến!

Lấy đầu vào dưới dạng ma trận 2 cột - đầu tiên cho x, thứ hai cho y. R roundthực sự sử dụng phương pháp làm tròn của ngân hàng, vì vậy chúng tôi khá may mắn ở đây.

i(xi1+x)(yi1yi)/2

Cảm ơn Giuseppe cho -3 byte.


3

[Gói R + sp], 55 byte

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

Hãy thử nó tại RDRR

Một hàm lấy 2 ma trận lo lắng và trả về vùng tròn. Điều này sử dụng spgói. Điều drop=Fcần thiết là để xử lý một trường hợp phối hợp. RDRR được sử dụng để demo vì TIO thiếu spgói.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.