The curve is the cubic Bézier arc with control points
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1).$$
It starts at \((1,0)\), ends at \((0,1)\), and is meant to mimic a quarter of the unit circle. The parameter \(v\) is not arbitrary: the region bounded by the coordinate axes and the Bézier arc must have the same area as a quarter disk, namely \(\pi/4\). Once that area condition determines \(v\), we compute the Bézier arc length \(L\) and compare it with the exact quarter-circle length \(\pi/2\).
The quantity printed by the program is
$$100\cdot \frac{L-\pi/2}{\pi/2}.$$
A cubic Bézier curve has the Bernstein form
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1.$$
Substituting the four control points and separating coordinates gives
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3.$$
After expansion this becomes exactly the polynomial form used in the solution files:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3.$$
Differentiating gives the velocity components
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2.$$
The implementations package these derivatives inside the speed function
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}.$$
The enclosed region is bounded by the \(x\)-axis from \((0,0)\) to \((1,0)\), the Bézier arc from \((1,0)\) to \((0,1)\), and the \(y\)-axis back to the origin. Green's theorem allows us to write the area as the line integral
$$A=\oint_C x\,dy.$$
The two axis segments contribute nothing: on the \(x\)-axis we have \(dy=0\), and on the \(y\)-axis we have \(x=0\). Therefore only the Bézier arc remains:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt.$$
Multiplying the two polynomials gives
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5. \end{aligned}$$
Integrating term by term over \([0,1]\) simplifies to
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}.$$
This is the exact closed form used by curve_area(v) in the C++ source.
The problem requires the area to equal the area of a quarter unit disk:
$$A(v)=\frac{\pi}{4}.$$
Substituting the formula for \(A(v)\) gives
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}.$$
Multiplying by \(20\) and rearranging yields
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0.$$
Applying the quadratic formula gives
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}.$$
The plus sign gives a value greater than \(1\), so the interior control points would leave the unit square. The geometric branch used by every implementation is therefore
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468.$$
For a parametric plane curve, the arc length is
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt.$$
Here the integrand is a square root of a quartic polynomial in \(t\). The repository solutions do not try to derive an elementary antiderivative; instead they evaluate the integral numerically to high precision.
The final percentage is then
$$\text{percent}=100\cdot \frac{L(v)-\pi/2}{\pi/2}.$$
The numerical part is identical in all three languages. For any interval \([a,b]\), Simpson's rule approximates the integral of \(s(t)\) by
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right).$$
Adaptive Simpson then splits the interval at the midpoint \(m\), computes \(S(a,m)\) and \(S(m,b)\), and compares
$$S(a,m)+S(m,b)$$
with the old estimate \(S(a,b)\). If
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon,$$
the code accepts the corrected estimate
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}.$$
Otherwise it recurses on both halves with tolerance \(\varepsilon/2\). The C++ version uses long double, tolerance \(10^{-18}\), and maximum depth \(30\). The Python and Java versions use the same recursion pattern with tolerance \(10^{-15}\) and depth \(30\).
Using the exact value of \(v\) above, the numerical integration gives
$$L\approx 1.570796911273925.$$
Hence
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091.$$
This matches the formatted output of the local solution programs.
The C++ implementation also contains useful checkpoints. At \(v=0\), the area formula gives
$$A(0)=\frac12,$$
and the curve degenerates to the diagonal segment \(x+y=1\), whose length is
$$\sqrt{2}.$$
The code verifies both facts numerically before computing the final answer, and it also checks that the chosen \(v\) lies in the interval \((0,1)\) and reproduces the target area \(\pi/4\).
The three implementation files share the same structure. solve_v() uses the closed-form quadratic solution, so the parameter search is not numerical. curve_speed(t, v) evaluates the norm of the derivative vector. curve_length(v) starts Simpson's rule on \([0,1]\), and adaptive_simpson(...) refines the partition until the error estimate is below the requested tolerance or the recursion depth reaches zero.
The C++ file adds curve_area(v) and run_checkpoints() explicitly, which makes the mathematical structure especially transparent: first validate the exact area formula, then integrate the speed, then form the relative error percentage.
Deriving \(v\) from the quadratic equation is \(O(1)\) time and \(O(1)\) memory. The arc-length computation dominates the runtime. If the adaptive Simpson routine ends up using \(m\) accepted subintervals, then the time cost is \(O(m)\) function evaluations up to a constant factor, and the memory usage is \(O(d)\), where \(d\) is the recursion depth. In this repository, \(d\le 30\) by construction, so the memory footprint is effectively constant.
Gesucht ist eine kubische Bézierkurve mit den Kontrollpunkten
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1).$$
Sie verbindet \((1,0)\) mit \((0,1)\) und soll einen Viertelkreis möglichst gut approximieren. Der Parameter \(v\) wird dabei nicht frei gewählt: Die von den Koordinatenachsen und dem Bézierbogen eingeschlossene Fläche muss genau \(\pi/4\) sein, also der Fläche eines Viertels der Einheitskreisscheibe entsprechen. Danach wird die Bogenlänge \(L\) der Bézierkurve berechnet und mit der exakten Viertelkreis-Bogenlänge \(\pi/2\) verglichen.
Ausgegeben wird
$$100\cdot \frac{L-\pi/2}{\pi/2}.$$
Eine kubische Bézierkurve hat die Bernstein-Darstellung
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1.$$
Nach Einsetzen der Kontrollpunkte und Aufspalten in \(x\)- und \(y\)-Koordinate erhält man
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3.$$
Ausmultipliziert ist das genau die Form aus den Lösungsdateien:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3.$$
Die Ableitungen lauten
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2.$$
Daraus bildet der Code die Geschwindigkeit
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}.$$
Die eingeschlossene Region besteht aus der \(x\)-Achse von \((0,0)\) nach \((1,0)\), dem Bézierbogen von \((1,0)\) nach \((0,1)\) und der \(y\)-Achse zurück zum Ursprung. Mit dem Satz von Green kann man die Fläche als Kurvenintegral schreiben:
$$A=\oint_C x\,dy.$$
Die beiden Achsenstücke tragen nichts bei: Auf der \(x\)-Achse gilt \(dy=0\), auf der \(y\)-Achse gilt \(x=0\). Also bleibt nur der Bézierbogen übrig:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt.$$
Das Produkt der beiden Polynome ist
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5. \end{aligned}$$
Termweises Integrieren über \([0,1]\) ergibt die geschlossene Formel
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}.$$
Genau diese Formel implementiert die C++-Funktion curve_area(v).
Die Problemvorgabe verlangt
$$A(v)=\frac{\pi}{4}.$$
Also
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}.$$
Nach Multiplikation mit \(20\) und Umstellen erhält man
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0.$$
Mit der Mitternachtsformel folgt
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}.$$
Der positive Zweig liegt über \(1\) und wäre geometrisch unpassend. Deshalb verwenden alle drei Implementierungen
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468.$$
Für eine parametrisierte ebene Kurve lautet die Bogenlänge
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt.$$
Der Integrand ist hier die Wurzel eines quartischen Polynoms in \(t\). Die Repository-Lösungen versuchen daher nicht, eine elementare Stammfunktion herzuleiten, sondern berechnen das Integral numerisch mit hoher Präzision.
Die Endausgabe ist dann
$$\text{Prozent}=100\cdot \frac{L(v)-\pi/2}{\pi/2}.$$
Der numerische Teil ist in C++, Python und Java strukturell gleich. Für ein Intervall \([a,b]\) verwendet Simpson zunächst
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right).$$
Dann wird in der Mitte \(m\) geteilt und \(S(a,m)\) sowie \(S(m,b)\) werden berechnet. Verglichen wird
$$S(a,m)+S(m,b)$$
mit der alten Näherung \(S(a,b)\). Falls
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon,$$
wird die korrigierte Näherung
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}$$
akzeptiert; sonst rekursiert das Verfahren auf beiden Teilintervallen mit Toleranz \(\varepsilon/2\). Die C++-Version nutzt long double, Toleranz \(10^{-18}\) und maximale Tiefe \(30\). Python und Java verwenden dieselbe Rekursion mit Toleranz \(10^{-15}\) und Tiefe \(30\).
Für den exakt bestimmten Parameter \(v\) liefert die numerische Integration
$$L\approx 1.570796911273925.$$
Daraus folgt
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091.$$
Das ist exakt der formatierte Ausgabewert der lokalen Lösungsprogramme.
Die C++-Datei enthält zusätzlich Kontrolltests. Für \(v=0\) ergibt die Flächenformel
$$A(0)=\frac12,$$
und die Kurve degeneriert zum Diagonalsegment \(x+y=1\) mit Länge
$$\sqrt{2}.$$
Außerdem prüft der Code, dass das berechnete \(v\) tatsächlich in \((0,1)\) liegt und die Zielfläche \(\pi/4\) reproduziert.
Alle drei Implementierungen folgen derselben Pipeline. solve_v() liefert \(v\) direkt aus der quadratischen Formel, also ohne numerische Nullstellensuche. curve_speed(t, v) berechnet die Norm des Tangentialvektors. curve_length(v) startet die Simpson-Näherung auf \([0,1]\), und adaptive_simpson(...) verfeinert die Unterteilung so lange, bis die Fehlerschranke eingehalten ist oder die Rekursionstiefe endet.
Besonders klar ist die C++-Version, weil sie mit curve_area(v) und run_checkpoints() die Herleitung direkt im Programm abbildet: erst Fläche validieren, dann Länge integrieren, dann den relativen Prozentfehler ausgeben.
Die Berechnung von \(v\) aus der quadratischen Gleichung ist \(O(1)\) in Zeit und Speicher. Den Hauptaufwand verursacht die adaptive Quadratur. Wenn das Verfahren am Ende \(m\) akzeptierte Teilintervalle benötigt, dann ist die Laufzeit \(O(m)\) bis auf konstante Faktoren für die Funktionsauswertungen, und der Speicherbedarf beträgt \(O(d)\) mit Rekursionstiefe \(d\). In diesem Repository gilt konstruktiv \(d\le 30\), also ist der Speicher praktisch konstant.
Aranan eğri, kontrol noktaları
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1)$$
olan kübik Bézier eğrisidir. Eğri \((1,0)\) noktasından başlayıp \((0,1)\) noktasında biter ve birim çemberin çeyrek yayını yaklaşık temsil eder. Ancak \(v\) serbest değildir: koordinat eksenleri ile Bézier yayı arasında kalan alan tam olarak \(\pi/4\) olmalıdır. Bu şart \(v\)'yi belirledikten sonra eğrinin yay uzunluğu \(L\) hesaplanır ve gerçek çeyrek çember yay uzunluğu \(\pi/2\) ile karşılaştırılır.
Programın bastığı değer
$$100\cdot \frac{L-\pi/2}{\pi/2}$$
ifadesidir.
Kübik Bézier eğrisinin Bernstein biçimi
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1$$
şeklindedir. Verilen kontrol noktalarını yerine koyup \(x\) ve \(y\) bileşenlerini ayırırsak
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3$$
elde edilir. Açılmış hali, çözüm dosyalarında kullanılan polinom biçimiyle aynıdır:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3.$$
Türevler de
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2$$
olur. Kod bu iki türevden
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}$$
hız fonksiyonunu üretir.
Kapalı bölge, \((0,0)\) ile \((1,0)\) arasındaki \(x\)-ekseni parçası, \((1,0)\) ile \((0,1)\) arasındaki Bézier yayı ve \((0,1)\)'den tekrar orijine inen \(y\)-ekseni parçasından oluşur. Green teoremi alanı
$$A=\oint_C x\,dy$$
şeklinde yazmamıza izin verir. Eksen parçaları katkı yapmaz: \(x\)-ekseni üzerinde \(dy=0\), \(y\)-ekseni üzerinde ise \(x=0\). Böylece yalnızca Bézier yayı kalır:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt.$$
İki polinomu çarptığımızda
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5 \end{aligned}$$
çıkar. \([0,1]\) aralığında terim terim integral alınca kapalı form
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}$$
elde edilir. C++ dosyasındaki curve_area(v) tam olarak bunu uygular.
Problem koşulu
$$A(v)=\frac{\pi}{4}$$
olduğundan
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}$$
yazarız. Her iki tarafı \(20\) ile çarpıp düzenlersek
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0$$
bulunur. Kökler
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}$$
şeklindedir. Artı işaretli kök \(1\)'den büyük olduğundan geometrik olarak istenen dal değildir. Bu yüzden tüm uygulamalar
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468$$
değerini kullanır.
Parametrik düzlem eğrilerinde yay uzunluğu
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt$$
ile verilir. Burada integrand, \(t\)'de dördüncü dereceden bir polinomun kareköküdür. Repo içindeki çözümler bu integral için elemanter bir kapalı form aramaz; onun yerine yüksek hassasiyetli sayısal integrasyon kullanır.
Son yüzde değer de
$$\text{yüzde}=100\cdot \frac{L(v)-\pi/2}{\pi/2}$$
olarak hesaplanır.
Üç dildeki kodun sayısal kısmı aynıdır. \([a,b]\) aralığında Simpson kuralı
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right)$$
yaklaşımını verir. Sonra aralık orta nokta \(m\)'de ikiye bölünür ve \(S(a,m)\) ile \(S(m,b)\) hesaplanır. Eski tahmin \(S(a,b)\) ile yeni toplam karşılaştırılır. Eğer
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon$$
ise düzeltilmiş değer
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}$$
kabul edilir. Aksi halde her iki yarıda tolerans \(\varepsilon/2\) ile yineleme yapılır. C++ sürümü long double, \(10^{-18}\) tolerans ve en fazla \(30\) derinlik kullanır. Python ve Java sürümleri aynı mantığı \(10^{-15}\) tolerans ve \(30\) derinlik ile uygular.
Yukarıdaki tam \(v\) değeriyle nümerik integral
$$L\approx 1.570796911273925$$
sonucunu verir. Dolayısıyla
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091$$
olur. Bu değer yerel çözüm programlarının biçimlendirilmiş çıktısıyla aynıdır.
C++ çözümündeki kontrol noktaları da önemlidir. \(v=0\) için alan formülü
$$A(0)=\frac12$$
verir. Bu durumda eğri \(x+y=1\) doğrusu üzerindeki köşegen parçaya çöker ve uzunluğu
$$\sqrt{2}$$
olur. Kod ayrıca bulunan \(v\)'nin gerçekten \((0,1)\) aralığında olduğunu ve hedef alan \(\pi/4\)'ü yeniden ürettiğini doğrular.
Üç çözüm dosyası aynı akışı izler. solve_v() doğrudan ikinci dereceden denklemden gelir; yani sayısal kök arama yoktur. curve_speed(t, v) türev vektörünün normunu hesaplar. curve_length(v) başlangıç Simpson tahminini kurar ve adaptive_simpson(...) hata tahmini kabul edilebilir seviyeye inene kadar aralığı bölmeye devam eder.
C++ sürümü, curve_area(v) ve run_checkpoints() yardımcıları sayesinde matematiksel türetimi kod içinde açık biçimde gösterir: önce alan formülü doğrulanır, sonra uzunluk integrali alınır, ardından göreli yüzde fark yazdırılır.
\(v\)'nin kapalı formdan bulunması \(O(1)\) zaman ve \(O(1)\) bellek gerektirir. Toplam çalışma süresini adaptif Simpson integrasyonu belirler. Yöntem sonunda \(m\) kabul edilmiş alt aralık kullanıyorsa, fonksiyon değerlendirmeleri açısından zaman karmaşıklığı sabit katsayılarla \(O(m)\), bellek karmaşıklığı ise özyineleme derinliği \(d\) için \(O(d)\)'dir. Bu repoda \(d\le 30\) olduğu için bellek kullanımı pratikte sabittir.
La curva buscada es el arco Bézier cúbico con puntos de control
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1).$$
Parte de \((1,0)\), termina en \((0,1)\) y pretende aproximar un cuarto de circunferencia unitaria. El parámetro \(v\) no se ajusta por ensayo: debe elegirse de modo que el área encerrada por los ejes coordenados y el arco Bézier sea exactamente \(\pi/4\), es decir, el área de un cuarto de disco unidad. Una vez fijado \(v\), se calcula la longitud del arco \(L\) y se compara con la longitud exacta de un cuarto de círculo, \(\pi/2\).
El valor impreso por el programa es
$$100\cdot \frac{L-\pi/2}{\pi/2}.$$
Una curva Bézier cúbica se escribe en forma de Bernstein como
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1.$$
Al sustituir los puntos de control y separar coordenadas obtenemos
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3.$$
Al desarrollar ambos polinomios aparece exactamente la forma usada en los archivos de solución:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3.$$
Las derivadas son
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2.$$
Con ellas el código define la rapidez
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}.$$
La región cerrada está formada por el tramo del eje \(x\) desde \((0,0)\) hasta \((1,0)\), el arco Bézier desde \((1,0)\) hasta \((0,1)\) y el tramo del eje \(y\) que vuelve al origen. Por el teorema de Green podemos escribir el área como
$$A=\oint_C x\,dy.$$
Los dos segmentos sobre los ejes no aportan nada: en el eje \(x\) se tiene \(dy=0\), y en el eje \(y\) se tiene \(x=0\). Por tanto sólo queda la contribución del arco Bézier:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt.$$
El producto de los polinomios es
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5. \end{aligned}$$
Integrando término a término en \([0,1]\) se obtiene la fórmula cerrada
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}.$$
Ésta es exactamente la expresión implementada por curve_area(v) en C++.
La condición geométrica del problema es
$$A(v)=\frac{\pi}{4}.$$
Entonces
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}.$$
Multiplicando por \(20\) y reordenando, obtenemos
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0.$$
La fórmula cuadrática da
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}.$$
La raíz con signo positivo es mayor que \(1\), así que no corresponde a la aproximación geométrica buscada dentro del cuadrado unidad. Por eso las tres implementaciones usan
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468.$$
Para una curva plana parametrizada, la longitud es
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt.$$
Aquí el integrando es la raíz cuadrada de un polinomio cuártico en \(t\). Los programas del repositorio no intentan obtener una primitiva elemental; en su lugar evalúan esta integral numéricamente con alta precisión.
Después calculan
$$\text{porcentaje}=100\cdot \frac{L(v)-\pi/2}{\pi/2}.$$
La parte numérica es esencialmente idéntica en C++, Python y Java. En un intervalo \([a,b]\), la regla de Simpson usa
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right).$$
Luego se divide el intervalo en el punto medio \(m\) y se calculan \(S(a,m)\) y \(S(m,b)\). Se compara la nueva suma
$$S(a,m)+S(m,b)$$
con la aproximación anterior \(S(a,b)\). Si se cumple
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon,$$
el código acepta la corrección
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}.$$
En caso contrario, recurre en ambas mitades con tolerancia \(\varepsilon/2\). La versión de C++ usa long double, tolerancia \(10^{-18}\) y profundidad máxima \(30\). Python y Java siguen el mismo esquema con tolerancia \(10^{-15}\) y profundidad \(30\).
Con el valor exacto de \(v\), la integración produce
$$L\approx 1.570796911273925.$$
Por tanto,
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091.$$
Éste es exactamente el resultado que imprimen las soluciones locales.
El archivo en C++ además incluye verificaciones útiles. Para \(v=0\), la fórmula del área da
$$A(0)=\frac12,$$
y la curva se colapsa sobre el segmento diagonal \(x+y=1\), cuya longitud es
$$\sqrt{2}.$$
El programa también comprueba que el \(v\) calculado pertenece a \((0,1)\) y que reproduce el área objetivo \(\pi/4\).
Los tres archivos de implementación siguen la misma idea. solve_v() obtiene \(v\) mediante la fórmula cerrada de la ecuación cuadrática, así que no hay búsqueda numérica de raíces. curve_speed(t, v) evalúa la norma del vector tangente. curve_length(v) construye la aproximación inicial de Simpson en \([0,1]\), y adaptive_simpson(...) refina la partición hasta que la estimación del error cae por debajo del umbral fijado o se agota la profundidad permitida.
La versión de C++ deja especialmente clara la estructura matemática porque expone también curve_area(v) y run_checkpoints(): primero valida la fórmula exacta del área, luego integra la rapidez y por último forma el porcentaje relativo.
Obtener \(v\) a partir de la fórmula cuadrática cuesta \(O(1)\) tiempo y \(O(1)\) memoria. El coste real está en la cuadratura adaptativa. Si el algoritmo termina aceptando \(m\) subintervalos, el tiempo es \(O(m)\) evaluaciones de la función hasta un factor constante, y la memoria es \(O(d)\), donde \(d\) es la profundidad de recursión. En este repositorio se impone \(d\le 30\), por lo que el consumo de memoria es efectivamente constante.
题目中的曲线是一个三次 Bézier 曲线,其控制点为
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1)$$
它从 \((1,0)\) 出发,到 \((0,1)\) 结束,用来逼近单位圆的四分之一圆弧。参数 \(v\) 不是随便选的,而是由面积条件唯一确定:坐标轴与这条 Bézier 曲线围成的区域面积必须等于四分之一单位圆的面积 \(\pi/4\)。求出 \(v\) 以后,再计算曲线弧长 \(L\),并与真实四分之一圆弧长度 \(\pi/2\) 做比较。
程序最终输出的是
$$100\cdot \frac{L-\pi/2}{\pi/2}$$
三次 Bézier 曲线的 Bernstein 形式为
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1$$
代入四个控制点并分别看 \(x\) 坐标与 \(y\) 坐标,可得
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3$$
展开以后,正好就是三个解法文件里使用的形式:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3$$
对 \(t\) 求导得到
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2$$
代码中的 curve_speed 就是根据这两个导数计算速度函数
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}$$
闭合区域由三部分组成:从原点到 \((1,0)\) 的 \(x\) 轴线段,从 \((1,0)\) 到 \((0,1)\) 的 Bézier 曲线,以及从 \((0,1)\) 回到原点的 \(y\) 轴线段。由 Green 公式可把面积写成
$$A=\oint_C x\,dy$$
两段坐标轴的贡献都为零:在 \(x\) 轴上 \(dy=0\),在 \(y\) 轴上 \(x=0\)。因此只需要对 Bézier 曲线积分:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt$$
把上面的多项式相乘,得到
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5 \end{aligned}$$
在 \([0,1]\) 上逐项积分,可以化简成非常紧凑的闭式:
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}$$
这正是 C++ 文件里 curve_area(v) 所使用的公式。
题目要求该面积恰好等于四分之一圆面积:
$$A(v)=\frac{\pi}{4}$$
于是有
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}$$
两边乘以 \(20\) 并整理:
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0$$
利用求根公式可得
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}$$
其中带正号的根大于 \(1\),不再是单位正方形内部那种自然的几何构型,因此三个实现都取
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468$$
参数曲线的弧长公式为
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt$$
这里被积函数是一个四次多项式平方根,没有简单的初等原函数可直接使用。仓库中的三个程序都采用高精度数值积分,而不是继续做符号化推导。
最后输出
$$\text{percent}=100\cdot \frac{L(v)-\pi/2}{\pi/2}$$
三种语言的数值部分完全同构。在区间 \([a,b]\) 上,Simpson 公式为
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right)$$
然后把区间在中点 \(m\) 处分成两半,分别计算 \(S(a,m)\) 和 \(S(m,b)\),并把新估计
$$S(a,m)+S(m,b)$$
与旧估计 \(S(a,b)\) 比较。如果满足
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon,$$
就接受修正后的估计
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}$$
否则就在左右两个子区间上继续递归,并把容差改成 \(\varepsilon/2\)。C++ 版本使用 long double、容差 \(10^{-18}\)、最大深度 \(30\)。Python 和 Java 版本使用相同的递归结构,只是容差为 \(10^{-15}\),深度同样为 \(30\)。
把上面精确求得的 \(v\) 代入后,数值积分给出
$$L\approx 1.570796911273925$$
于是
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091$$
这正是本地解法程序输出到小数点后 10 位的结果。
C++ 实现还加入了几项很有价值的检查。令 \(v=0\) 时,面积公式给出
$$A(0)=\frac12,$$
而曲线会退化到直线段 \(x+y=1\),其长度为
$$\sqrt{2}$$
代码还验证了解出的 \(v\) 的确满足 \(0<v<1\),并且重新代回面积公式后得到目标值 \(\pi/4\)。
三个实现文件的结构一致。solve_v() 直接用二次方程闭式求解 \(v\),因此不存在数值找根误差。curve_speed(t, v) 负责计算切向量长度。curve_length(v) 先在 \([0,1]\) 上建立一次 Simpson 近似,而 adaptive_simpson(...) 再根据误差估计不断细分区间,直到满足精度要求或递归深度耗尽。
C++ 文件额外暴露了 curve_area(v) 和 run_checkpoints(),因此数学结构在代码里表现得非常直接:先验证面积公式,再积分速度函数,最后输出相对百分比误差。
由二次方程求 \(v\) 只需 \(O(1)\) 时间与 \(O(1)\) 空间。真正的成本来自自适应 Simpson 积分。若算法最终接受了 \(m\) 个子区间,则时间复杂度可视为 \(O(m)\) 次函数求值,空间复杂度为递归深度 \(d\) 的 \(O(d)\)。本仓库把 \(d\) 上限固定为 \(30\),因此空间开销实际上是常数量级。
Рассматривается кубическая кривая Безье с контрольными точками
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1).$$
Она соединяет точки \((1,0)\) и \((0,1)\) и должна хорошо приближать четверть единичной окружности. Параметр \(v\) определяется не подбором, а из точного условия на площадь: область, ограниченная осями координат и дугой Безье, должна иметь площадь \(\pi/4\). После нахождения \(v\) вычисляется длина дуги \(L\), а затем она сравнивается с точной длиной четверти окружности \(\pi/2\).
Программа печатает величину
$$100\cdot \frac{L-\pi/2}{\pi/2}.$$
Кубическая кривая Безье задается в форме Бернштейна:
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1.$$
Подставляя данные контрольные точки и выделяя координаты, получаем
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3.$$
После раскрытия скобок это превращается ровно в ту полиномиальную форму, которая используется в коде:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3.$$
Производные равны
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2.$$
Из них все реализации строят функцию скорости
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}.$$
Замкнутая область состоит из отрезка оси \(x\) от \((0,0)\) до \((1,0)\), дуги Безье от \((1,0)\) до \((0,1)\) и отрезка оси \(y\), возвращающегося к началу координат. По формуле Грина площадь можно записать как
$$A=\oint_C x\,dy.$$
Вклад осевых отрезков равен нулю: на оси \(x\) имеем \(dy=0\), а на оси \(y\) имеем \(x=0\). Поэтому остается только вклад самой кривой Безье:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt.$$
После перемножения полиномов получается
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5. \end{aligned}$$
Почленное интегрирование на \([0,1]\) дает компактную формулу
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}.$$
Именно эта формула реализована в функции curve_area(v) в C++.
По условию задачи нужно, чтобы
$$A(v)=\frac{\pi}{4}.$$
Следовательно,
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}.$$
Умножаем на \(20\) и приводим подобные:
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0.$$
По формуле корней получаем
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}.$$
Корень со знаком плюс больше \(1\), поэтому он не соответствует ожидаемой геометрии внутри единичного квадрата. Во всех трех реализациях используется
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468.$$
Для параметрической плоской кривой длина равна
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt.$$
Здесь подкоренное выражение является многочленом четвертой степени по \(t\), поэтому решения в репозитории не ищут простую элементарную первообразную. Вместо этого интеграл вычисляется численно с высокой точностью.
После этого формируется итоговый процент
$$\text{percent}=100\cdot \frac{L(v)-\pi/2}{\pi/2}.$$
Численная часть одинакова в C++, Python и Java. На интервале \([a,b]\) правило Симпсона использует приближение
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right).$$
Затем интервал делится пополам в точке \(m\), вычисляются \(S(a,m)\) и \(S(m,b)\), и новая сумма
$$S(a,m)+S(m,b)$$
сравнивается со старой оценкой \(S(a,b)\). Если
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon,$$
то принимается скорректированное значение
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}.$$
Иначе алгоритм рекурсивно повторяет процесс на обоих полуинтервалах с точностью \(\varepsilon/2\). В C++ используется long double, точность \(10^{-18}\) и максимальная глубина \(30\). В Python и Java применяется та же схема с точностью \(10^{-15}\) и глубиной \(30\).
Подставляя найденное точное значение \(v\), получаем
$$L\approx 1.570796911273925.$$
Следовательно,
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091.$$
Именно это число печатают локальные программы после форматирования до 10 знаков после запятой.
В C++-версии есть и дополнительные проверки. При \(v=0\) формула площади дает
$$A(0)=\frac12,$$
а сама кривая вырождается в диагональный отрезок \(x+y=1\) длины
$$\sqrt{2}.$$
Код также проверяет, что найденное \(v\) действительно лежит в интервале \((0,1)\) и воспроизводит целевую площадь \(\pi/4\).
Все три файла реализуют одну и ту же идею. solve_v() сразу возвращает точный корень квадратного уравнения, поэтому численный поиск параметра не нужен. curve_speed(t, v) вычисляет норму касательного вектора. curve_length(v) строит исходную оценку Симпсона на \([0,1]\), а adaptive_simpson(...) рекурсивно уточняет разбиение, пока оценка ошибки не станет достаточно малой или не закончится разрешенная глубина.
Особенно показателен C++-файл: в нем есть и curve_area(v), и run_checkpoints(), поэтому математическая логика прямо отражена в программе: сначала проверка формулы площади, затем интегрирование скорости, затем вычисление относительной процентной ошибки.
Нахождение \(v\) из квадратного уравнения требует \(O(1)\) времени и \(O(1)\) памяти. Основное время уходит на адаптивное численное интегрирование. Если алгоритм в итоге принимает \(m\) подынтервалов, то временная сложность равна \(O(m)\) вычислений функции с точностью до констант, а память составляет \(O(d)\), где \(d\) — глубина рекурсии. В данном репозитории \(d\le 30\), поэтому память фактически постоянна.
المنحنى المطلوب هو منحنى Bézier تكعيبي بنقاط التحكم
$$P_0=(1,0),\qquad P_1=(1,v),\qquad P_2=(v,1),\qquad P_3=(0,1).$$
يبدأ من \((1,0)\) وينتهي عند \((0,1)\)، والهدف أن يكون تقريبًا جيدًا لربع دائرة الوحدة. المعامل \(v\) لا يُختار عشوائيًا، بل يُحدَّد من شرط مساحة دقيق: المساحة المحصورة بين المحورين وهذا القوس يجب أن تساوي \(\pi/4\)، أي مساحة ربع قرص الوحدة. بعد تحديد \(v\)، نحسب طول القوس \(L\) ثم نقارنه بطول ربع الدائرة الحقيقي \(\pi/2\).
القيمة التي يطبعها البرنامج هي
$$100\cdot \frac{L-\pi/2}{\pi/2}.$$
الصيغة القياسية لمنحنى Bézier التكعيبي هي
$$B(t)=(1-t)^3P_0+3(1-t)^2tP_1+3(1-t)t^2P_2+t^3P_3,\qquad 0\le t\le 1.$$
بالتعويض عن نقاط التحكم، ثم فصل الإحداثيين، نحصل على
$$x(t)=(1-t)^3+3(1-t)^2t+3v(1-t)t^2,$$
$$y(t)=3v(1-t)^2t+3(1-t)t^2+t^3.$$
وبعد التوسيع الجبري تصبح الصيغة تمامًا كما تستعملها ملفات الحل:
$$x(t)=1+3(v-1)t^2+(2-3v)t^3,$$
$$y(t)=3vt+(3-6v)t^2+(3v-2)t^3.$$
ومشتقاتها هي
$$x'(t)=6(v-1)t+3(2-3v)t^2,$$
$$y'(t)=3v+2(3-6v)t+3(3v-2)t^2.$$
ومن هنا تُعرِّف الشيفرة دالة السرعة
$$s(t)=\sqrt{(x'(t))^2+(y'(t))^2}.$$
المنطقة المغلقة تتكوّن من قطعة على محور \(x\) من \((0,0)\) إلى \((1,0)\)، ثم قوس Bézier من \((1,0)\) إلى \((0,1)\)، ثم قطعة على محور \(y\) عائدة إلى الأصل. بواسطة مبرهنة غرين يمكن كتابة المساحة على صورة
$$A=\oint_C x\,dy.$$
قطعتا المحورين لا تسهمان في التكامل: على محور \(x\) لدينا \(dy=0\)، وعلى محور \(y\) لدينا \(x=0\). لذلك يبقى فقط تكامل القوس:
$$A(v)=\int_0^1 x(t)\,y'(t)\,dt.$$
وبعد ضرب كثيرتي الحدود نحصل على
$$\begin{aligned} x(t)y'(t)=&\,3v+(6-12v)t+(9v^2-6)t^2+(-45v^2+60v-18)t^3\\ &+(63v^2-87v+30)t^4+(-27v^2+36v-12)t^5. \end{aligned}$$
ثم إن التكامل حدًا حدًا على الفترة \([0,1]\) يعطي الصيغة المغلقة
$$A(v)=\frac12+\frac{3v}{5}-\frac{3v^2}{20}.$$
وهذه هي الصيغة نفسها الموجودة في الدالة curve_area(v) في نسخة C++.
شرط المسألة هو
$$A(v)=\frac{\pi}{4}.$$
إذًا
$$\frac12+\frac{3v}{5}-\frac{3v^2}{20}=\frac{\pi}{4}.$$
وبعد الضرب في \(20\) ثم إعادة الترتيب نحصل على
$$10+12v-3v^2=5\pi,$$
$$3v^2-12v+(5\pi-10)=0.$$
ومن صيغة حل المعادلة التربيعية ينتج
$$v=\frac{12\pm\sqrt{144-12(5\pi-10)}}{6}=2\pm \frac{\sqrt{66-15\pi}}{3}.$$
الجذر ذو الإشارة الموجبة أكبر من \(1\)، لذلك لا يوافق الوضع الهندسي المطلوب داخل مربع الوحدة. ولهذا تعتمد جميع التطبيقات الجذر
$$\boxed{v=2-\frac{\sqrt{66-15\pi}}{3}}\approx 0.551778477804468.$$
طول منحنى مستوٍ مُعلَّم بمعامل يُعطى بالعلاقة
$$L(v)=\int_0^1 \sqrt{(x'(t))^2+(y'(t))^2}\,dt=\int_0^1 s(t)\,dt.$$
هنا integrand هو جذر تربيعي لكثير حدود من الدرجة الرابعة في \(t\)، ولذلك لا تحاول الشيفرات استخراج دالة أصلية ابتدائية له، بل تنتقل مباشرة إلى التكامل العددي عالي الدقة.
بعد ذلك يُحسب الناتج النهائي من
$$\text{percent}=100\cdot \frac{L(v)-\pi/2}{\pi/2}.$$
الجزء العددي متطابق في C++ وPython وJava. على الفترة \([a,b]\) تعطي قاعدة سمبسون التقريب
$$S(a,b)=\frac{b-a}{6}\left(s(a)+4s\!\left(\frac{a+b}{2}\right)+s(b)\right).$$
ثم تُقسَّم الفترة عند المنتصف \(m\)، ويُحسب \(S(a,m)\) و\(S(m,b)\)، وتُقارَن القيمة الجديدة
$$S(a,m)+S(m,b)$$
بالتقدير السابق \(S(a,b)\). إذا تحقق الشرط
$$\left|S(a,m)+S(m,b)-S(a,b)\right|\le 15\varepsilon,$$
فإن الخوارزمية تقبل التصحيح
$$S(a,m)+S(m,b)+\frac{S(a,m)+S(m,b)-S(a,b)}{15}.$$
وإلا فإنها تستدعي نفسها على نصفي الفترة مع استعمال \(\varepsilon/2\). إصدار C++ يستخدم long double مع سماحية \(10^{-18}\) وعمق أقصى \(30\). أما Python وJava فيستخدمان البنية نفسها مع سماحية \(10^{-15}\) وعمق \(30\).
عند التعويض عن \(v\) الدقيق السابق نحصل عدديًا على
$$L\approx 1.570796911273925.$$
ومن ثم
$$100\cdot \frac{L-\pi/2}{\pi/2}\approx 0.0000372091.$$
وهذه هي القيمة التي تطبعها الحلول المحلية بعد التنسيق حتى 10 منازل عشرية.
ملف C++ يتضمن أيضًا اختبارات تحقق مهمة. عندما \(v=0\)، فإن صيغة المساحة تعطي
$$A(0)=\frac12,$$
ويصبح المنحنى في هذه الحالة منكمشًا إلى القطعة المستقيمة \(x+y=1\) التي طولها
$$\sqrt{2}.$$
كما تتحقق الشيفرة من أن \(v\) المحسوب يقع فعلًا داخل المجال \((0,1)\)، وأنه يعيد إنتاج المساحة الهدف \(\pi/4\).
الملفات الثلاثة تتبع البنية نفسها. الدالة solve_v() تحسب \(v\) مباشرة من الحل المغلق للمعادلة التربيعية، لذلك لا يوجد بحث عددي عن الجذر. الدالة curve_speed(t, v) تحسب معيار متجه المماس. ثم تبدأ curve_length(v) بتقريب سمبسون على الفترة \([0,1]\)، بينما تقوم adaptive_simpson(...) بتقسيم الفترة تكراريًا حتى تصبح إشارة الخطأ صغيرة بما يكفي أو يُستنفد العمق الأقصى.
نسخة C++ توضح البنية الرياضية بشكل أفضل لأنها تحتوي أيضًا على curve_area(v) وrun_checkpoints(): أولًا تُراجع صيغة المساحة، ثم يُحسب تكامل السرعة، ثم تُطبع النسبة المئوية النسبية.
حساب \(v\) من الصيغة التربيعية يكلف \(O(1)\) زمنًا و\(O(1)\) ذاكرة. الكلفة الفعلية تأتي من التكامل العددي التكيفي. إذا انتهت الخوارزمية بعد قبول \(m\) فترات فرعية، فإن الزمن يكون \(O(m)\) من حيث عدد تقييمات الدالة حتى ثابت ضربي، بينما الذاكرة تكون \(O(d)\)، حيث \(d\) هو عمق الاستدعاء التكراري. وفي هذا المستودع لدينا دائمًا \(d\le 30\)، لذا فإن استهلاك الذاكرة يبقى عمليًا ثابتًا.