# -*- coding: utf-8 -*- import sys, os, math sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) from manim import * from tiktok import * BENF = [math.log10(1 + 1 / d) for d in range(1, 10)] # Benford's law PLANO = [1 / 9] * 9 # what one would expect BASE_Y, MAXH, BW = -0.9, 4.6, 0.72 XS = [-3.52 + i * 0.88 for i in range(9)] class Benford(TikTok): NAME = "benford" def bar(self, i, frac, color): h = max(frac / 0.31 * MAXH, 0.02) r = Rectangle(width=BW, height=h, stroke_width=0, fill_color=color, fill_opacity=1) r.move_to([XS[i], BASE_Y, 0], DOWN) return r def construct(self): self.prepare() chip = self.chip("Estadística forense", C_GREEN) # ---- list of numbers ----- raw = ["1.243", "87", "2.910", "146", "3.502", "1.078", "254", "19.640"] item_list = VGroup(*[Text(n, font=FONT, font_size=46, weight=BOLD, color=WHITE) for n in raw]).arrange_in_grid(4, 2, buff=(1.1, 0.42)) item_list.move_to(UP * 2.4) with self.beat(0) as b: b.play(FadeIn(chip, shift=DOWN * 0.3), run_time=0.45) b.play(LaggedStart(*[FadeIn(t, shift=UP * 0.15) for t in item_list], lag_ratio=0.12), run_time=1.3) with self.beat(1) as b: firsts = VGroup(*[t[0].copy().set_color(AMBER) for t in item_list]) b.play(LaggedStart(*[t[0].animate.set_color(AMBER) for t in item_list], lag_ratio=0.1), run_time=1.0) b.play(*[Indicate(t[0], color=AMBER, scale_factor=1.5) for t in item_list], run_time=0.8) # ---- what one would expect --- labels = VGroup(*[Text(str(d), font=FONT, font_size=38, weight=BOLD, color=C_GRAY) .move_to([XS[d - 1], BASE_Y - 0.42, 0]) for d in range(1, 10)]) floor = Line([-4.1, BASE_Y, 0], [4.1, BASE_Y, 0], stroke_width=5, color="#3A4766") bars = VGroup(*[self.bar(i, PLANO[i], "#44506E") for i in range(9)]) with self.beat(2) as b: b.play(FadeOut(item_list), run_time=0.4) b.play(Create(floor), FadeIn(labels), run_time=0.5) b.play(LaggedStart(*[GrowFromEdge(x, DOWN) for x in bars], lag_ratio=0.07), run_time=1.0) exp = Text("11% cada uno", font=FONT, font_size=40, weight=BOLD, color=C_GRAY) exp.move_to(UP * 4.6) b.play(FadeIn(exp), run_time=0.45) # ---- reality -------- with self.beat(3) as b: nb = self.bar(0, BENF[0], AMBER) b.play(FadeOut(exp), run_time=0.25) b.play(Transform(bars[0], nb), labels[0].animate.set_color(AMBER), run_time=1.0) pct = Text("30%", font=FONT, font_size=42, weight=BOLD, color=AMBER) pct.next_to(nb, UP, buff=0.18) b.play(FadeIn(pct, shift=UP * 0.15), run_time=0.5) with self.beat(4) as b: news = [self.bar(i, BENF[i], C_SKY) for i in range(1, 9)] b.play(LaggedStart(*[Transform(bars[i + 1], news[i]) for i in range(8)], lag_ratio=0.1), run_time=1.4) p2 = Text("17%", font=FONT, font_size=34, weight=BOLD, color=C_SKY) p2.next_to(news[0], UP, buff=0.15) p9 = Text("4%", font=FONT, font_size=34, weight=BOLD, color=C_SKY) p9.next_to(news[7], UP, buff=0.15) b.play(FadeIn(p2), FadeIn(p9), run_time=0.5) with self.beat(5) as b: name = self.fit(Text("LEY DE BENFORD", font=FONT, font_size=62, weight=BOLD, color=WHITE), 8.0).move_to(UP * 4.7) b.play(Write(name), run_time=1.0) with self.beat(6) as b: words = VGroup(*[Text(w, font=FONT, font_size=34, color=C_GRAY) for w in ("poblaciones", "precios", "likes", "ríos")]) words.arrange(RIGHT, buff=0.45).move_to(DOWN * 1.9) self.fit(words, 8.2) b.play(LaggedStart(*[FadeIn(w, shift=UP * 0.15) for w in words], lag_ratio=0.25), run_time=1.1) # ---- the made-up numbers ------- with self.beat(7) as b: b.play(FadeOut(words), run_time=0.3) fake = VGroup(*[Rectangle(width=BW, height=PLANO[i] / 0.31 * MAXH, stroke_color=C_PINK, stroke_width=5, fill_opacity=0).move_to([XS[i], BASE_Y, 0], DOWN) for i in range(9)]) lbl = Text("inventados", font=FONT, font_size=42, weight=BOLD, color=C_PINK) lbl.move_to(DOWN * 2.0) b.play(LaggedStart(*[Create(f) for f in fake], lag_ratio=0.07), run_time=1.1) b.play(FadeIn(lbl, shift=UP * 0.15), run_time=0.5) with self.beat(8) as b: b.play(*[Indicate(fake[i], color=C_PINK, scale_factor=1.06) for i in (0, 1)], run_time=0.8) gap = DoubleArrow(fake[0].get_top() + UP * 0.08, bars[0].get_top() + DOWN * 0.08, buff=0, color=C_PINK, stroke_width=7, tip_length=0.22).shift(RIGHT * 0.0) b.play(GrowArrow(gap), run_time=0.7) b.play(Flash(gap, color=C_PINK, line_length=0.4, num_lines=14, flash_radius=1.0), run_time=0.6) with self.beat(9) as b: b.play(FadeOut(VGroup(fake, gap, lbl)), run_time=0.4) txt = VGroup( self.fit(Text("así agarraron", font=FONT, font_size=46, weight=BOLD, color=WHITE), 8.0), self.fit(Text("fraudes contables reales", font=FONT, font_size=46, weight=BOLD, color=C_PINK), 8.0), ).arrange(DOWN, buff=0.3).move_to(DOWN * 2.1) b.play(FadeIn(txt[0], shift=UP * 0.15), run_time=0.5) b.play(FadeIn(txt[1], shift=UP * 0.15), run_time=0.6) with self.beat(10) as b: count_txt = self.fit(Text("probá con tu tarjeta", font=FONT, font_size=58, weight=BOLD, color=AMBER), 7.9).move_to(DOWN * 3.15) b.play(FadeOut(txt), run_time=0.3) b.play(Write(count_txt), run_time=0.9) b.play(Circumscribe(count_txt, color=AMBER, buff=0.28, stroke_width=7), run_time=1.0) self.finish()