Trova l'area di un poligono


9

Date le lunghezze laterali consecutive s1, s2, s3... s_ndi una n-gon inscritta in un cerchio, trova la sua area. Puoi presumere che il poligono esista. Inoltre, il poligono sarà convesso e non autointersecante, il che è sufficiente per garantire unicità. Gli incorporati che risolvono in modo specifico questa sfida, così come le funzioni integrate che calcolano il circumradius o il circumcenter, sono vietati (questo è diverso da una versione precedente di questa sfida).

Input: le lunghezze laterali del poligono ciclico; può essere preso come parametro per una funzione, stdin, ecc.

Output: l'area del poligono.

La risposta deve essere precisa con 6 decimali e deve essere eseguita entro 20 secondi su un laptop ragionevole.

Questo è il codice golf, quindi vince il codice più corto!

Casi di prova specifici:

[3, 4, 5] --> 6
[3, 4, 6] --> 5.332682251925386
[3, 4, 6, 7] --> 22.44994432064365
[5, 5, 5, 5] --> 25
[6, 6, 6, 6, 6] --> 61.93718642120281
[6.974973020933265, 2.2393294197257387, 5.158285083300981, 1.4845682771595603, 3.5957940796134173] --> 21.958390804292847
[7.353566082457831, 12.271766915518073, 8.453884922273897, 9.879017670784675, 9.493366404245332, 1.2050010402321778] --> 162.27641678140589

Generatore di test case:


7
Conosco un modo semplice per trovarne il perimetro.
mIllIbyte

1
Conosco un modo semplice per trovare il numero di lati
Luis Mendo,

Questo problema è piuttosto semplice, dato il circumradius, ma senza di esso è incredibilmente difficile.
poi830,

È anche facile se ci sono meno di cinque lati, non è importante nel golf del codice.
Neil,

Risposte:


5

Python 2, 191 byte

from math import*
C=sorted(input());l,h=C[-1]/2,sum(C)
while h-l>1e-9:m=l+h;a=[asin(c/m)for c in C[:-1]];f=pi-sum(a);l,h=[l,m/2,h][m*sin(f)<C[-1]:][:2]
print sum(l*l*sin(2*t)for t in a+[f])/2

Utilizza una ricerca binaria per trovare il raggio, quindi calcola l'area di ciascun segmento in base all'angolo / raggio.

Trova il raggio sommando prima tutto tranne l'angolo di accordo più grande e controllando l'angolo rimanente rispetto all'accordo rimanente. Tali angoli vengono quindi utilizzati anche per calcolare l'area di ciascun segmento. L'area di un segmento può essere negativa, se l'angolo è maggiore di 180 gradi.

Implementazione leggibile:

import math

def segment_angles(line_segments, r):
    return [2*math.asin(c/(2*r)) for c in line_segments]

def cyclic_ngon_area(line_segments):
    line_segments = list(sorted(line_segments))
    lo, hi = max(line_segments) / 2, sum(line_segments)
    while hi - lo > 1e-9:
        mid = (lo + hi) / 2
        angles = segment_angles(line_segments[:-1], mid)
        angles.append(2*math.pi - sum(angles))
        if 2 * mid * math.sin(angles[-1]/2) < line_segments[-1]:
            lo = mid
        else:
            hi = mid
    return sum([lo*lo * math.sin(a) / 2 for a in angles])

Funziona se il centro è fuori dal poligono? (Ad esempio, un triangolo con lunghezze laterali 6, 7, 12). A volte il sqrt(4**2 - c**2/4)bisogno di essere negativo, quando l'angolo è maggiore di pi.
soktinpk,

@soktinpk Ho corretto la mia risposta.
orlp,

0

Ottava, 89 byte

r=sum(s=input(''));while sum(a=asin(s/2/r))<pi r*=1-1e-4;b=a;end;disp(sum(cos(b).*s/2*r))

Spiegazione

L'angolo aattraversato da un segmento di lunghezza sè 2*asin(s/2/r), dato un circumradius r. La sua area è cos(a)*s/2*r.

Algoritmo

  1. Impostato rsu qualcosa di troppo grande, come il perimetro.
  2. Se l'angolo cumulato è inferiore a 2pi, ridurre re ripetere il passaggio 2.
  3. Calcola l'area.

In media, quante iterazioni sono necessarie per ressere impostate? (per curiosità)
soktinpk

Non è possibile che ciò abbia la precisione richiesta. Moltiplichi ripetutamente il raggio per 0.9999 per ridurlo, questo rende molto semplice sottoporre a tiro i 6 decimali di precisione richiesti.
orlp,

@soktinpk circa 15000 per r*=1-1e-4e 150000 per r*=1-1e-5.
Rainer P.

@RainerP. Questi due valori sono uguali.
Finanzi la causa di Monica il

1
@soktinpk non è generalmente una buona idea fare un'eccezione per una risposta specifica.
Cyoce,
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.