Area di uno scafo convesso 2D


11

Ti viene data una matrice / lista / vettore di coppie di numeri interi che rappresentano coordinate cartesiane (x,y) di punti su un piano euclideo 2D; tutte le coordinate sono comprese tra 104 e 104 , sono ammessi duplicati. Trova l'area dello scafo convesso di quei punti, arrotondata al numero intero più vicino; un punto medio esatto dovrebbe essere arrotondato al numero intero pari più vicino. È possibile utilizzare numeri in virgola mobile nei calcoli intermedi, ma solo se è possibile garantire che il risultato finale sia sempre corretto. Questo è , quindi vince il programma corretto più breve.

Il guscio convesso di un insieme di punti P è il più piccolo insieme convesso contenente P . Sul piano euclideo, per ogni singolo punto (x,y) , è il punto stesso; per due punti distinti, è la linea che li contiene, per tre punti non collineari, è il triangolo che formano, e così via.

Una buona spiegazione visiva di ciò che uno scafo convesso, è meglio descritto come immaginare tutti i punti come chiodi in una tavola di legno, e quindi allungare un elastico attorno a loro per racchiudere tutti i punti:
inserisci qui la descrizione dell'immagine

Alcuni casi di test:

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
Hai dei casi di test?
Maltysen,

17
Non contare gli spazi bianchi nel golf del codice è una cattiva idea, porta a invii con enormi stringhe di spazi bianchi più il codice generico per convertire la stringa in codice ed eseguirla.
xnor

4
un punto medio esatto dovrebbe essere arrotondato al numero intero pari più vicino : ti stai solo chiedendo qual è il ragionamento che sta dietro?
Arnauld,

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

6
Di solito le sfide sono autonome, ma non lo è. Potresti spiegare cos'è uno scafo convesso e come calcolarlo? O indicare qualche risorsa online di riferimento?
Olivier Grégoire,

Risposte:


9

SQL Server 2012+, 84 byte

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

Utilizza le funzioni e gli aggregati della geometria in SQL Server. I coordinate sono dalla tabella Acon colonne xe y.


9

Java 10, 405 ... non si adattava più; vedere la cronologia delle modifiche .. 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 grazie a @ OlivierGrégoire
-3 byte grazie a @PeterTaylor
-7 byte grazie a @ceilingcat

Provalo online.

O 299 byte senza arrotondamento .

Spiegazione:

Ci sono tre passaggi da fare:

  1. Calcola i punti per lo scafo convesso in base alle coordinate di input (usando l'algoritmo / avvolgimento di Jarvis )
  2. Calcola l'area di questo scafo convesso
  3. Arrotondamento del banco

Per calcolare le coordinate che fanno parte dello scafo convesso, utilizziamo il seguente approccio:

lppl

inserisci qui la descrizione dell'immagine

Per quanto riguarda il codice:

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

Implementa la marcia Jarvis (aka algoritmo di confezione regalo).

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

Provalo online!

O 170 byte senza lo schema di arrotondamento ingombrante.


L'arrotondamento era solo un'aringa rossa perché il doppio dell'area è sempre esattamente intero.
Vladimir Reshetnikov,

4
@VladimirReshetnikov Per curiosità: se sapevi che l'arrotondamento era un'aringa rossa, allora perché aggiungerlo per distrarre dalla sfida altrimenti buona? .. Non tutte le lingue hanno costruito l'arrotondamento di Banker, nemmeno apparentemente lingue ben conosciute come JS e Java. Mi piace la sfida in generale e mi è piaciuto scrivere la mia risposta Java, ma l'arrotondamento e la mancanza di spiegazioni su cosa sia Convex Hull per rendere la sfida autonoma mi ha trattenuto dal votarla, tbh .. PS: Mi dispiace @Arnauld di farlo come un commento nella tua risposta ..
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)

Provalo online!

Accetta input come matrice a 2 colonne - prima per x, seconda per y. R in roundrealtà usa il metodo di arrotondamento del banchiere, quindi siamo abbastanza fortunati qui.

i(xi1+x)(yi1yi)/2

Grazie a Giuseppe per -3 byte.


3

[Pacchetto R + sp], 55 byte

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

Provalo su RDRR

Una funzione che accetta una matrice anx 2 e restituisce l'area arrotondata. Questo utilizza il sppacchetto. Il drop=Fè necessario per gestire il caso un co-ordinate. RDRR utilizzato per la demo poiché a TIO manca il sppacchetto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.