Étant donné les longueurs latérales consécutives s1, s2, s3... s_n
d'un n-gon inscrit dans un cercle, trouvez son aire. Vous pouvez supposer que le polygone existe. De plus, le polygone sera convexe et non auto-intersecté, ce qui est suffisant pour garantir l'unicité. Les fonctions intégrées qui résolvent spécifiquement ce défi, ainsi que les fonctions intégrées qui calculent le circumradius ou le circumcenter, sont interdites (ce qui est différent d'une version précédente de ce défi).
Entrée: les longueurs latérales du polygone cyclique; peut être pris comme paramètre d'une fonction, stdin, etc.
Sortie: l'aire du polygone.
La réponse doit être précise à 6 décimales et doit s'exécuter dans les 20 secondes sur un ordinateur portable raisonnable.
C'est le golf de code donc le code le plus court gagne!
Cas de test spécifiques:
[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
Générateur de cas de test:
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>
Réponses:
Python 2, 191 octets
Utilise une recherche binaire pour trouver le rayon, puis calcule l'aire de chaque segment par l'angle / rayon.
Il trouve le rayon en additionnant tout d'abord, sauf le plus grand angle d'accord, et en vérifiant l'angle restant par rapport à l'accord restant. Ces angles sont ensuite également utilisés pour calculer l'aire de chaque segment. La zone d'un segment peut être négative si son angle est supérieur à 180 degrés.
Implémentation lisible:
la source
sqrt(4**2 - c**2/4)
besoin doit être négatif, lorsque l'angle est supérieur àpi
.Octave, 89 octets
Explication
L'angle
a
couvert par un segment de longueurs
est2*asin(s/2/r)
, étant donné un circumradiusr
. Sa zone estcos(a)*s/2*r
.Algorithme
r
sur quelque chose de trop grand, comme le périmètre.2pi
, réduisezr
et répétez l'étape 2.la source
r
être défini? (par curiosité)r*=1-1e-4
et 150000 pourr*=1-1e-5
.