Dengan panjang sisi berurutan s1, s2, s3... s_n
n-gon yang tertulis dalam lingkaran, temukan luasnya. Anda dapat mengasumsikan bahwa poligon itu ada. Selain itu, poligon akan menjadi cembung dan tidak berpotongan sendiri, yang cukup untuk menjamin keunikan. Built-in yang secara khusus mengatasi tantangan ini, serta fungsi built-in yang menghitung circumradius atau circumcenter, dilarang (ini berbeda dari versi sebelumnya dari tantangan ini).
Input: Panjang sisi poligon siklik; dapat diambil sebagai parameter ke suatu fungsi, stdin, dll.
Output: Area poligon.
Jawabannya harus akurat hingga 6 desimal dan harus berjalan dalam 20 detik pada laptop yang masuk akal.
Ini golf kode sehingga kode terpendek menang!
Kasus uji khusus:
[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
Generator test case:
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>
Jawaban:
Python 2, 191 byte
Menggunakan pencarian biner untuk menemukan jari-jari, kemudian menghitung luas setiap segmen berdasarkan sudut / jari-jari.
Ia menemukan jari-jari dengan pertama-tama menjumlahkan semua kecuali sudut akor terbesar, dan memeriksa sudut yang tersisa ke akor yang tersisa. Sudut-sudut itu kemudian juga digunakan untuk menghitung luas setiap segmen. Area segmen bisa negatif, jika sudutnya lebih besar dari 180 derajat.
Implementasi yang mudah dibaca:
sumber
sqrt(4**2 - c**2/4)
kebutuhan menjadi negatif, ketika sudut lebih besar daripi
.Oktaf, 89 byte
Penjelasan
Sudut
a
membentang oleh segmen panjangs
adalah2*asin(s/2/r)
, diberikan circumradius sebuahr
. Daerahnya adalahcos(a)*s/2*r
.Algoritma
r
ke sesuatu yang terlalu besar, seperti perimeter.2pi
, kurangir
dan ulangi langkah 2.sumber
r
ditetapkan? (penasaran)r*=1-1e-4
dan 150000 untukr*=1-1e-5
.