다각형의 넓이를 구합니다


9

s1, s2, s3... s_n원 안에 새겨진 n-gon의 연속 된 측면 길이 가 주어지면 해당 영역을 찾으십시오. 다각형이 존재한다고 가정 할 수 있습니다. 또한 다각형은 볼록하고 자체 교차하지 않으므로 고유성을 보장하기에 충분합니다. 이 문제를 구체적으로 해결하는 기본 제공 기능과 원주 또는 둘레 중심을 계산하는 기본 제공 기능은 금지됩니다 (이 문제의 이전 버전과 다릅니다).

입력 : 순환 다각형의 측면 길이. 함수, stdin 등의 매개 변수로 사용할 수 있습니다.

출력 : 다각형의 면적.

답은 소수점 이하 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
나는 변의 수를 찾는 쉬운 방법을 알고있다
Luis Mendo

이 문제는 둘레가 주어지면 꽤 쉽지만 그것 없이는 엄청나게 어렵습니다.
poi830

코드 골프에서 중요하지 않은 5면 미만인 경우에도 쉽습니다.
Neil

답변:


5

파이썬 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)하는 circumradius 주어진 r. 그 지역은 cos(a)*s/2*r입니다.

연산

  1. r주변과 같이 너무 큰 것으로 설정하십시오 .
  2. 누적 각도가보다 작 으면 2 단계를 2pi줄이고 r반복하십시오.
  3. 면적을 계산하십시오.

평균적으로 몇 번의 반복이 r설정됩니까? (호기심에서)
soktinpk

이것이 필요한 정밀도를 가질 수있는 방법은 없습니다. 반경에 0.9999를 반복해서 곱하면 감소하는 6 자리의 정밀도를 매우 쉽게 언더 슈트 할 수 있습니다.
orlp

15000 주위 @soktinpk r*=1-1e-4및 150000을 r*=1-1e-5.
Rainer P.

@RainerP. 이 두 값은 같습니다.
Fund Monica의 소송

1
@ soktinpk 일반적으로 특정 답변에 대한 예외를 만드는 것은 좋지 않습니다.
Cyoce
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.