Bestimmen Sie bei aufeinanderfolgenden Seitenlängen s1, s2, s3... s_n
eines in einen Kreis eingeschriebenen n-Gons dessen Fläche. Sie können davon ausgehen, dass das Polygon vorhanden ist. Darüber hinaus ist das Polygon konvex und schneidet sich nicht selbst, was ausreicht, um die Eindeutigkeit zu gewährleisten. Integrierte Funktionen, die diese Herausforderung speziell lösen, sowie integrierte Funktionen zur Berechnung des Zirkumradius oder des Zirkumzentrums sind verboten (dies unterscheidet sich von einer früheren Version dieser Herausforderung).
Eingabe: Die Seitenlängen des zyklischen Polygons; kann als Parameter für eine Funktion, ein Standard usw. verwendet werden.
Ausgabe: Die Fläche des Polygons.
Die Antwort sollte auf 6 Dezimalstellen genau sein und innerhalb von 20 Sekunden auf einem vernünftigen Laptop ausgeführt werden.
Dies ist Code Golf, also gewinnt der kürzeste Code!
Spezifische Testfälle:
[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
Testfallgenerator:
function randPolygon(n) {
var left = 2 * Math.PI;
var angles = [];
for (var i = 0; i < n - 1; ++i) {
var r = Math.random() * left;
angles.push(r);
left -= r;
}
angles.push(left);
var area = 0;
var radius = 1 + Math.random() * 9;
for (var i = 0; i < angles.length; ++i) area += radius * radius * Math.sin(angles[i]) / 2;
var sideLens = angles.map(function(a) {
return Math.sin(a / 2) * radius * 2;
});
document.querySelector("#radius").innerHTML = radius;
document.querySelector("#angles").innerHTML = "[" + angles.join(", ") + "]";
document.querySelector("#inp").innerHTML = "[" + sideLens.join(", ") + "]";
document.querySelector("#out").innerHTML = area;
draw(angles);
}
function draw(angles) {
var canv = document.querySelector("#diagram"),
ctx = canv.getContext("2d");
var size = canv.width
ctx.clearRect(0, 0, size, size);
ctx.beginPath();
ctx.arc(size / 2, size / 2, size / 2, 0, 2 * Math.PI, true);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(size, size / 2);
var runningTotal = 0;
for (var i = 0; i < angles.length; ++i) {
runningTotal += angles[i];
var x = Math.cos(runningTotal) * size / 2 + size / 2;
var y = Math.sin(runningTotal) * size / 2 + size / 2;
ctx.lineTo(x, y);
}
ctx.stroke();
}
document.querySelector("#gen").onclick = function() {
randPolygon(parseInt(document.querySelector("#sideLens").value, 10));
}
<div id="hints">
<p><strong>These are to help you; they are not part of the input or output.</strong>
</p>
Circumradius:
<pre id="radius"></pre>
Angles, in radians, of each sector (this are NOT the angles of the polygon):
<pre id="angles"></pre>
</div>
<hr>
<div id="output">
Input:
<pre id="inp"></pre>
Output:
<pre id="out"></pre>
</div>
<hr>
<div id="draw">
Diagram:
<br />
<canvas id="diagram" width="200" height="200" style="border:1px solid black"></canvas>
</div>
Number of side lengths:
<input type="number" id="sideLens" step="1" min="3" value="3" />
<br />
<button id="gen">Generate test case</button>
Antworten:
Python 2, 191 Bytes
Verwendet eine binäre Suche, um den Radius zu finden, und berechnet dann die Fläche jedes Segments anhand des Winkels / Radius.
Der Radius wird ermittelt, indem zuerst alle bis auf den größten Akkordwinkel summiert und der verbleibende Winkel zum verbleibenden Akkord überprüft wird. Diese Winkel werden dann auch verwendet, um die Fläche jedes Segments zu berechnen. Die Fläche eines Segments kann negativ sein, wenn sein Winkel größer als 180 Grad ist.
Lesbare Implementierung:
quelle
sqrt(4**2 - c**2/4)
muss das negativ sein, wenn der Winkel größer als istpi
.Oktave, 89 Bytes
Erläuterung
Der Winkel
a
durch ein Segment der Länge aufgespannts
wird2*asin(s/2/r)
, einen circumradius gegebenr
. Seine Fläche istcos(a)*s/2*r
.Algorithmus
r
etwas zu Großes ein, z. B. den Umfang.2pi
, reduzieren Sier
Schritt 2 und wiederholen Sie ihn.quelle
r
bis diese festgelegt sind? (aus Neugier)r*=1-1e-4
und 150000 fürr*=1-1e-5
.