aboutsummaryrefslogtreecommitdiffstats
path: root/scenes/v11_collatz.py
diff options
context:
space:
mode:
Diffstat (limited to 'scenes/v11_collatz.py')
-rw-r--r--scenes/v11_collatz.py171
1 files changed, 171 insertions, 0 deletions
diff --git a/scenes/v11_collatz.py b/scenes/v11_collatz.py
new file mode 100644
index 0000000..49436b8
--- /dev/null
+++ b/scenes/v11_collatz.py
@@ -0,0 +1,171 @@
+# -*- coding: utf-8 -*-
+import sys, os, math
+sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
+from manim import *
+from tiktok import *
+
+X0, X1 = -3.75, 3.75
+Y0, Y1 = -1.30, 3.30
+
+
+def seq(n):
+ s = [n]
+ while n != 1:
+ n = n // 2 if n % 2 == 0 else 3 * n + 1
+ s.append(n)
+ return s
+
+
+def curva(sq, color=AMBAR, sw=5, mx=None, nx=None, log=False):
+ """Trayectoria como poligonal. mx/nx permiten compartir escala entre curvas."""
+ mx = mx or max(sq)
+ nx = nx or len(sq)
+ if log:
+ f = lambda v: math.log(v) / math.log(mx)
+ else:
+ f = lambda v: v / mx
+ pts = [[X0 + (X1 - X0) * i / (nx - 1), Y0 + (Y1 - Y0) * f(sq[i]), 0]
+ for i in range(len(sq))]
+ m = VMobject(stroke_color=color, stroke_width=sw)
+ m.set_points_as_corners(pts)
+ return m, pts
+
+
+def tile(v, col):
+ t = Text(str(v), font=FONT, font_size=44, weight=BOLD, color="#0B0F1A")
+ box = RoundedRectangle(corner_radius=0.16, width=max(0.95, t.width + 0.45),
+ height=0.88, stroke_width=0, fill_color=col, fill_opacity=1)
+ return VGroup(box, t)
+
+
+class Collatz(TikTok):
+ NAME = "collatz"
+
+ def construct(self):
+ self.prepare()
+ chip = self.chip("Abierto desde 1937", ROSA)
+
+ with self.beat(0) as b:
+ n = self.big("27", 150, AMBAR).move_to(UP * 1.9)
+ cap = self.fit(Text("agarrá cualquier número", font=FONT, font_size=50,
+ weight=BOLD, color=WHITE), 8.2).move_to(DOWN * 0.3)
+ b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.45)
+ b.play(FadeIn(n, scale=0.6), run_time=0.45)
+ for v in ("6", "19", "41"):
+ b.play(Transform(n, self.big(v, 150, AMBAR).move_to(UP * 1.9)), run_time=0.26)
+ b.play(FadeIn(cap, shift=UP * 0.15), run_time=0.5)
+
+ def regla(txt, op, col):
+ a = Text(txt, font=FONT, font_size=46, weight=BOLD, color=col)
+ fl = Arrow(ORIGIN, RIGHT * 0.85, buff=0, color=GRIS, stroke_width=6,
+ max_tip_length_to_length_ratio=0.35)
+ c = Text(op, font=FONT, font_size=52, weight=BOLD, color=WHITE)
+ return VGroup(a, fl, c).arrange(RIGHT, buff=0.35)
+
+ with self.beat(1) as b:
+ b.play(FadeOut(VGroup(n, cap)), run_time=0.3)
+ r1 = regla("es PAR", "÷ 2", CELESTE)
+ r2 = regla("es IMPAR", "× 3 + 1", AMBAR)
+ rr = VGroup(r1, r2).arrange(DOWN, buff=0.7).move_to(UP * 1.6)
+ self.fit(rr, 8.2)
+ b.play(FadeIn(r1, shift=UP * 0.2), run_time=0.7)
+ b.play(FadeIn(r2, shift=UP * 0.2), run_time=0.7)
+
+ s6 = seq(6)
+ with self.beat(2) as b:
+ b.play(rr.animate.scale(0.72).move_to(UP * 5.2), run_time=0.5)
+ seis = self.big("6", 140, VERDE).move_to(UP * 1.0)
+ b.play(FadeIn(seis, scale=0.6), run_time=0.6)
+
+ with self.beat(3) as b:
+ b.play(FadeOut(seis), run_time=0.25)
+ tiles = VGroup(*[tile(v, VERDE if v == 1 else (CELESTE if v % 2 == 0 else AMBAR))
+ for v in s6])
+ fila1 = VGroup(*tiles[:5]).arrange(RIGHT, buff=0.28)
+ fila2 = VGroup(*tiles[5:]).arrange(RIGHT, buff=0.28)
+ grid = VGroup(fila1, fila2).arrange(DOWN, buff=0.45).move_to(UP * 1.4)
+ self.fit(grid, 8.2)
+ b.play(LaggedStart(*[FadeIn(t, scale=0.6) for t in tiles],
+ lag_ratio=0.5), run_time=max(1.4, b.floor - 0.4))
+
+ with self.beat(4) as b:
+ b.play(Circumscribe(tiles[-1], color=VERDE, buff=0.12, stroke_width=6),
+ run_time=0.7)
+ b.play(FadeOut(grid), run_time=0.35)
+ siete = self.big("7", 140, AMBAR).move_to(UP * 1.0)
+ b.play(FadeIn(siete, scale=0.6), run_time=0.5)
+
+ base = Line([X0 - 0.25, Y0, 0], [X1 + 0.25, Y0, 0], stroke_width=4, color="#33405C")
+ uno = Text("1", font=FONT, font_size=32, weight=BOLD, color=VERDE)
+ uno.next_to(base.get_start(), LEFT, buff=0.12)
+
+ s7 = seq(7)
+ with self.beat(5) as b:
+ b.play(FadeOut(siete), run_time=0.25)
+ c7, p7 = curva(s7, AMBAR, 6)
+ pico = Text("52", font=FONT, font_size=34, weight=BOLD, color=AMBAR)
+ pico.next_to([p7[s7.index(max(s7))][0], Y1, 0], UP, buff=0.12)
+ b.play(FadeIn(base), FadeIn(uno), run_time=0.35)
+ b.play(Create(c7), run_time=max(1.2, b.floor - 1.1))
+ b.play(FadeIn(pico), run_time=0.4)
+
+ s27 = seq(27)
+ with self.beat(6) as b:
+ b.play(FadeOut(VGroup(c7, pico)), run_time=0.3)
+ c27, p27 = curva(s27, ROSA, 5)
+ k = s27.index(max(s27))
+ top = Text("9.232", font=FONT, font_size=40, weight=BOLD, color=ROSA)
+ top.next_to([p27[k][0], Y1, 0], UP, buff=0.12)
+ lab = Text("27", font=FONT, font_size=40, weight=BOLD, color=ROSA)
+ lab.move_to([X0 - 0.05, Y1 + 0.45, 0])
+ b.play(FadeIn(lab), run_time=0.3)
+ b.play(Create(c27), run_time=max(1.3, b.floor - 1.0))
+ b.play(FadeIn(top), run_time=0.4)
+
+ with self.beat(7) as b:
+ fin = Dot([p27[-1][0], Y0, 0], radius=0.14, color=VERDE)
+ pasos = self.fit(Text("111 pasos y cae al 1", font=FONT, font_size=48,
+ weight=BOLD, color=VERDE), 8.0).move_to(DOWN * 2.6)
+ b.play(FadeIn(fin, scale=0.4), run_time=0.4)
+ b.play(Flash(fin, color=VERDE, line_length=0.35, num_lines=14,
+ flash_radius=0.8), run_time=0.6)
+ b.play(FadeIn(pasos, shift=UP * 0.15), run_time=0.6)
+
+ with self.beat(8) as b:
+ b.play(FadeOut(VGroup(c27, top, lab, fin, pasos)), run_time=0.4)
+ todos = [seq(k) for k in range(2, 80)]
+ MX = max(max(s) for s in todos)
+ NX = max(len(s) for s in todos)
+ cols = [AMBAR, CELESTE, ROSA, VERDE]
+ gr = VGroup(*[curva(s, cols[i % 4], 2.4, mx=MX, nx=NX, log=True)[0]
+ for i, s in enumerate(todos)])
+ gr.set_stroke(opacity=0.65)
+ b.play(LaggedStart(*[Create(c) for c in gr], lag_ratio=0.02),
+ run_time=max(1.6, b.floor - 0.9))
+ marca = self.fit(Text("todos terminan en 1", font=FONT, font_size=46,
+ weight=BOLD, color=VERDE), 8.0).move_to(DOWN * 2.6)
+ b.play(FadeIn(marca, shift=UP * 0.15), run_time=0.6)
+
+ with self.beat(9) as b:
+ b.play(FadeOut(VGroup(gr, marca, base, uno, rr)), run_time=0.45)
+ t = VGroup(
+ self.fit(Text("nadie pudo demostrar", font=FONT, font_size=50,
+ weight=BOLD, color=WHITE), 8.2),
+ self.fit(Text("que pasa SIEMPRE", font=FONT, font_size=54,
+ weight=BOLD, color=ROSA), 8.2),
+ ).arrange(DOWN, buff=0.35).move_to(UP * 1.2)
+ b.play(FadeIn(t[0], shift=UP * 0.15), run_time=0.6)
+ b.play(FadeIn(t[1], scale=0.8), run_time=0.7)
+
+ with self.beat(10) as b:
+ b.play(FadeOut(t), run_time=0.35)
+ cta = VGroup(
+ self.fit(Text("conjetura de Collatz", font=FONT, font_size=56,
+ weight=BOLD, color=AMBAR), 8.0),
+ self.fit(Text("dejá tu número abajo", font=FONT, font_size=46,
+ weight=BOLD, color=WHITE), 8.0),
+ ).arrange(DOWN, buff=0.38).move_to(UP * 0.8)
+ b.play(Write(cta[0]), run_time=0.9)
+ b.play(FadeIn(cta[1], shift=UP * 0.15), run_time=0.6)
+
+ self.finish()