diff options
Diffstat (limited to 'scenes/v10_buffon.py')
| -rw-r--r-- | scenes/v10_buffon.py | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/scenes/v10_buffon.py b/scenes/v10_buffon.py new file mode 100644 index 0000000..35ee4e0 --- /dev/null +++ b/scenes/v10_buffon.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +import sys, os, math +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +from manim import * +from tiktok import * + +D = 1.1 # separacion entre rayas = largo de la aguja +Y0 = 0.35 # raya mas baja +NLIN = 5 +SEED, N1, N2 = 36, 60, 200 + + +def tirar(n): + rng = np.random.default_rng(SEED) + x = rng.uniform(-3.9, 3.9, n) + y = rng.uniform(Y0 + 0.1, Y0 + (NLIN - 1) * D - 0.1, n) + th = rng.uniform(0, PI, n) + dx, dy = D / 2 * np.cos(th), D / 2 * np.sin(th) + p1 = np.stack([x - dx, y - dy, np.zeros(n)], axis=1) + p2 = np.stack([x + dx, y + dy, np.zeros(n)], axis=1) + cruza = np.floor((p1[:, 1] - Y0) / D) != np.floor((p2[:, 1] - Y0) / D) + return p1, p2, cruza + + +class Buffon(TikTok): + NAME = "buffon" + + def construct(self): + self.prepare() + chip = self.chip("π sin círculos", ROSA) + p1, p2, cruza = tirar(N2) + + rayas = VGroup(*[Line([-4.2, Y0 + k * D, 0], [4.2, Y0 + k * D, 0], + stroke_width=4, color="#33405C") for k in range(NLIN)]) + + with self.beat(0) as b: + hook = VGroup( + self.fit(Text("tiro agujas al piso", font=FONT, font_size=52, + weight=BOLD, color=WHITE), 8.2), + self.fit(Text("y sale π", font=FONT, font_size=64, + weight=BOLD, color=AMBAR), 8.2), + ).arrange(DOWN, buff=0.32).move_to(UP * 2.4) + b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.45) + b.play(FadeIn(hook[0], shift=UP * 0.15), run_time=0.6) + b.play(Write(hook[1]), run_time=0.8) + + with self.beat(1) as b: + b.play(FadeOut(hook), run_time=0.35) + b.play(LaggedStart(*[Create(r) for r in rayas], lag_ratio=0.12), run_time=0.9) + demo = Line([-1.0, Y0 + D, 0], [-1.0, Y0 + 2 * D, 0], + stroke_width=9, color=AMBAR) + med = DoubleArrow([0.2, Y0 + D, 0], [0.2, Y0 + 2 * D, 0], buff=0, + color=VERDE, stroke_width=6, tip_length=0.2) + lab = Text("mismo largo", font=FONT, font_size=32, weight=BOLD, color=VERDE) + lab.next_to(med, RIGHT, buff=0.25) + b.play(Create(demo), run_time=0.5) + b.play(GrowArrow(med), FadeIn(lab), run_time=0.6) + + agujas = VGroup(*[Line(p1[i], p2[i], stroke_width=4.5, color="#7C8AA8") + for i in range(N2)]) + + with self.beat(2) as b: + b.play(FadeOut(VGroup(demo, med, lab)), run_time=0.3) + b.play(LaggedStart(*[FadeIn(agujas[i]) for i in range(N1)], + lag_ratio=0.012), run_time=max(1.1, b.floor - 0.5)) + + with self.beat(3) as b: + hit = [agujas[i] for i in range(N1) if cruza[i]] + miss = [agujas[i] for i in range(N1) if not cruza[i]] + b.play(*[a.animate.set_stroke(AMBAR, 6) for a in hit], + *[a.animate.set_stroke("#46526E", 3.5) for a in miss], run_time=1.0) + + c1 = int(cruza[:N1].sum()) + + def marcador(n, c, y=-0.75): + g = VGroup( + VGroup(Text("tiradas", font=FONT, font_size=30, color=GRIS), + Text(str(n), font=FONT, font_size=62, weight=BOLD, color=WHITE) + ).arrange(DOWN, buff=0.1), + VGroup(Text("cruzan", font=FONT, font_size=30, color=GRIS), + Text(str(c), font=FONT, font_size=62, weight=BOLD, color=AMBAR) + ).arrange(DOWN, buff=0.1), + ).arrange(RIGHT, buff=1.5).move_to([0, y, 0]) + return g + + marc = marcador(N1, c1) + with self.beat(4) as b: + b.play(FadeIn(marc, shift=UP * 0.15), run_time=0.8) + + with self.beat(5) as b: + f = MathTex(r"\frac{2 \times \text{tiradas}}{\text{cruces}}", + color=CELESTE).scale(1.25).move_to(DOWN * 2.45) + b.play(Write(f), run_time=1.1) + + with self.beat(6) as b: + est = 2 * N1 / c1 + res = MathTex(r"= %s" % f"{est:.4f}".replace(".", "{,}"), + color=VERDE).scale(1.45) + res.next_to(f, RIGHT, buff=0.4) + grp = VGroup(f, res) + b.play(Write(res), run_time=0.8) + b.play(grp.animate.move_to(DOWN * 2.45), run_time=0.4) + b.play(Flash(res, color=VERDE, line_length=0.5, num_lines=16, + flash_radius=1.4), run_time=0.6) + + c2 = int(cruza.sum()) + with self.beat(7) as b: + hit = [agujas[i] for i in range(N1, N2) if cruza[i]] + miss = [agujas[i] for i in range(N1, N2) if not cruza[i]] + for a in hit: + a.set_stroke(AMBAR, 6) + for a in miss: + a.set_stroke("#46526E", 3.5) + b.play(LaggedStart(*[FadeIn(agujas[i]) for i in range(N1, N2)], + lag_ratio=0.004), run_time=max(1.0, b.floor - 1.3)) + est2 = 2 * N2 / c2 + nm = marcador(N2, c2) + nres = MathTex(r"= %s" % f"{est2:.4f}".replace(".", "{,}"), + color=VERDE).scale(1.45).next_to(f, RIGHT, buff=0.4) + b.play(Transform(marc, nm), Transform(res, nres), run_time=0.9) + + with self.beat(8) as b: + pi = MathTex(r"\pi = 3{,}14159\ldots", color=AMBAR).scale(1.5) + pi.move_to(UP * 5.5) + b.play(Write(pi), run_time=1.0) + b.play(Circumscribe(pi, color=AMBAR, buff=0.25, stroke_width=6), run_time=0.8) + + with self.beat(9) as b: + b.play(FadeOut(VGroup(marc, pi, f, res)), run_time=0.45) + t = VGroup( + self.fit(Text("no hay ningún círculo", font=FONT, font_size=48, + weight=BOLD, color=WHITE), 8.2), + self.fit(Text("y π aparece igual", font=FONT, font_size=48, + weight=BOLD, color=AMBAR), 8.2), + ).arrange(DOWN, buff=0.35).move_to(DOWN * 1.5) + b.play(FadeIn(t[0], shift=UP * 0.15), run_time=0.6) + b.play(FadeIn(t[1], shift=UP * 0.15), run_time=0.7) + + with self.beat(10) as b: + b.play(FadeOut(t), run_time=0.35) + cta = VGroup( + self.fit(Text("aguja de Buffon", font=FONT, font_size=58, + weight=BOLD, color=AMBAR), 8.0), + self.fit(Text("hacelo con fósforos", font=FONT, font_size=44, + weight=BOLD, color=WHITE), 8.0), + ).arrange(DOWN, buff=0.35).move_to(DOWN * 1.5) + b.play(Write(cta[0]), run_time=0.8) + b.play(FadeIn(cta[1], shift=UP * 0.15), run_time=0.6) + + self.finish() |