ポリゴンの領域を見つける


9

s1, s2, s3... s_n円に内接するnゴンの連続する辺の長さを考慮して、その面積を求めます。ポリゴンが存在すると想定できます。さらに、ポリゴンは凸型で自己交差せず、一意性を保証するのに十分です。この課題を具体的に解決するビルトイン、およびサーカム半径またはサーカムセンターを計算するビルトイン関数は禁止されています(これは、このチャレンジの以前のバージョンとは異なります)。

入力:循環ポリゴンの辺の長さ。関数や標準入力などのパラメータとして使用できます。

出力:ポリゴンの面積。

答えは小数点以下6桁まで正確で、適切なラップトップでは20秒以内に実行する必要があります。

これはコードゴルフなので、最短のコードが勝ちます!

特定のテストケース:

[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

テストケースジェネレーター:


7
私はその周囲を見つける簡単な方法を知っています。
mIllIbyte

1
私は、辺の数を見つけるための簡単な方法を知っている
ルイス・Mendo

この問題は、外接円を考えると非常に簡単ですが、それがなければ非常に困難です。
poi830

コードゴルフでは重要ではなく、5面未満の場合も簡単です。
Neil、

回答:


5

Python 2、191バイト

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

バイナリ検索を使用して半径を検出し、角度/半径によって各セグメントの面積を計算します。

最初に最大の弦角度以外のすべてを合計し、残りの弦に対する残りの角度をチェックして、半径を見つけます。これらの角度は、各セグメントの面積の計算にも使用されます。角度が180度より大きい場合、セグメントの面積は負になる可能性があります。

読みやすい実装:

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])

中心がポリゴンの外側にある場合、これは機能しますか?(たとえば、辺の長さが6、7、12の三角形)。sqrt(4**2 - c**2/4)角度がより大きい場合は、負の値が必要になることがありますpi
soktinpk

@soktinpk私は私の答えを修正しました。
orlp

0

オクターブ、89バイト

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))

説明

外接円が与えられた場合、a長さのセグメントがまたがる角度sはです。その面積は。2*asin(s/2/r)rcos(a)*s/2*r

アルゴリズム

  1. r境界線など、大きすぎるものに設定します。
  2. 累積角度がより小さい場合は2pirステップ2を減らして繰り返します。
  3. 面積を計算します。

これをr設定するには、平均で何回の反復が必要ですか?(好奇心から)
soktinpk

これが必要な精度を持つ方法はありません。半径に0.9999を繰り返し乗算してそれを減らします。これにより、必要な6桁の精度を非常に簡単に下回ることができます。
orlp

@soktinpkで約15000、150000 r*=1-1e-4ですr*=1-1e-5
Rainer P.

@RainerP。これら2つの値は同じです。
モニカの訴訟に資金を提供する

1
@soktinpkは、特定の回答に例外を設けることは一般に良い考えではありません。
Cyoce
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.