from big_ol_pile_of_manim_imports import * from active_projects.eop.reusable_imports import * class BrickRowScene(PiCreatureScene): def split_tallies(self, row, direction = DOWN): # Split all tally symbols at once and move the copies # either horizontally on top of the brick row # or diagonally into the bricks self.tallies_copy = self.tallies.copy() self.add_foreground_mobject(self.tallies_copy) tally_targets_left = [ rect.get_center() + 0.25 * rect.get_width() * LEFT for rect in row.rects ] tally_targets_right = [ rect.get_center() + 0.25 * rect.get_width() * RIGHT for rect in row.rects ] if np.all(direction == LEFT) or np.all(direction == RIGHT): tally_y_pos = self.tallies[0].anchor[1] for target in tally_targets_left: target[1] = tally_y_pos for target in tally_targets_right: target[1] = tally_y_pos for (i, tally) in enumerate(self.tallies): target_left = tally_targets_left[i] new_tally_left = TallyStack(tally.nb_heads + 1, tally.nb_tails) new_tally_left.move_anchor_to(target_left) v = target_left - tally.anchor self.play( tally.move_anchor_to, target_left, ) tally.anchor = target_left self.play(Transform(tally, new_tally_left)) tally_copy = self.tallies_copy[i] target_right = tally_targets_right[i] new_tally_right = TallyStack(tally.nb_heads, tally.nb_tails + 1) new_tally_right.move_anchor_to(target_right) v = target_right - tally_copy.anchor self.play(tally_copy.move_anchor_to, target_right) tally_copy.anchor = target_right self.play(Transform(tally_copy, new_tally_right)) tally_copy.nb_heads = new_tally_right.nb_heads tally_copy.nb_tails = new_tally_right.nb_tails tally.nb_heads = new_tally_left.nb_heads tally.nb_tails = new_tally_left.nb_tails def tally_split_animations(self, row, direction = DOWN): # Just creates the animations and returns them # Execution can be timed afterwards # Returns two lists: first all those going left, then those to the right self.tallies_copy = self.tallies.copy() self.add_foreground_mobject(self.tallies_copy) tally_targets_left = [ rect.get_center() + 0.25 * rect.get_width() * LEFT for rect in row.rects ] tally_targets_right = [ rect.get_center() + 0.25 * rect.get_width() * RIGHT for rect in row.rects ] if np.all(direction == LEFT) or np.all(direction == RIGHT): tally_y_pos = self.tallies[0].anchor[1] for target in tally_targets_left: target[1] = tally_y_pos for target in tally_targets_right: target[1] = tally_y_pos anims1 = [] for (i, tally) in enumerate(self.tallies): new_tally_left = TallyStack(tally.nb_heads + 1, tally.nb_tails) target_left = tally_targets_left[i] new_tally_left.move_to(target_left) anims1.append(Transform(tally, new_tally_left)) tally.anchor = target_left tally.nb_heads = new_tally_left.nb_heads tally.nb_tails = new_tally_left.nb_tails anims2 = [] for (i, tally) in enumerate(self.tallies_copy): new_tally_right = TallyStack(tally.nb_heads, tally.nb_tails + 1) target_right = tally_targets_right[i] new_tally_right.move_to(target_right) anims2.append(Transform(tally, new_tally_right)) tally.anchor = target_right tally.nb_heads = new_tally_right.nb_heads tally.nb_tails = new_tally_right.nb_tails return anims1, anims2 def split_tallies_at_once(self, row, direction = DOWN): anims1, anims2 = self.tally_split_animations(row, direction = direction) self.play(*(anims1 + anims2)) def split_tallies_in_two_steps(self, row, direction = DOWN): # First all those to the left, then those to the right anims1, anims2 = self.tally_split_animations(row, direction = direction) self.play(*anims1) self.wait(0.3) self.play(*anims2) def merge_rects_by_subdiv(self, row): half_merged_row = row.copy() half_merged_row.subdiv_level += 1 half_merged_row.generate_points() half_merged_row.move_to(row) self.play(FadeIn(half_merged_row)) self.remove(row) return half_merged_row def merge_tallies(self, row, target_pos = UP): r = row.subdiv_level if np.all(target_pos == DOWN): tally_targets = [ rect.get_center() for rect in row.get_rects_for_level(r) ] elif np.all(target_pos == UP): y_pos = row.get_center()[1] + 1.2 * 0.5 * row.get_height() for target in tally_targets: target[1] = y_pos else: raise Exception("Invalid target position (either UP or DOWN)") anims = [] for (tally, target) in zip(self.tallies[1:], tally_targets[1:-1]): anims.append(tally.move_anchor_to) anims.append(target) for (tally, target) in zip(self.tallies_copy[:-1], tally_targets[1:-1]): anims.append(tally.move_anchor_to) anims.append(target) self.play(*anims) # update anchors for (tally, target) in zip(self.tallies[1:], tally_targets[1:-1]): tally.anchor = target for (tally, target) in zip(self.tallies_copy[:-1], tally_targets[1:-1]): tally.anchor = target self.remove(self.tallies_copy) self.tallies.add(self.tallies_copy[-1]) def merge_rects_by_coloring(self, row): merged_row = row.copy() merged_row.coloring_level += 1 merged_row.generate_points() merged_row.move_to(row) self.play(FadeIn(merged_row)) self.remove(row) return merged_row def move_tallies_on_top(self, row): self.play( self.tallies.shift, 1.2 * 0.5 * row.height * UP ) for tally in self.tallies: tally.anchor += 1.2 * 0.5 * row.height * UP def create_pi_creature(self): randy = CoinFlippingPiCreature(color = MAROON_E) return randy def construct(self): self.force_skipping() randy = self.get_primary_pi_creature() randy = randy.scale(0.5).move_to(3*DOWN + 6*LEFT) #self.add(randy) self.row = BrickRow(0, height = 2, width = 10) self.wait() self.play(FadeIn(self.row)) self.wait() # move in all kinds of sequences coin_seqs = VGroup() for i in range(20): n = np.random.randint(1,10) seq = [np.random.choice(["H", "T"]) for j in range(n)] coin_seq = CoinSequence(seq).scale(1.5) loc = np.random.uniform(low = -10, high = 10) * RIGHT loc += np.random.uniform(low = -6, high = 6) * UP coin_seq.move_to(loc) coin_seq.target = coin_seq.copy().scale(0.3).move_to(0.4 * loc) coin_seq.target.fade(1) coin_seqs.add(coin_seq) self.play( OldLaggedStart( Succession, coin_seqs, lambda m: (FadeIn(m, run_time = 0.1), MoveToTarget(m)), run_time = 5, lag_ratio = 0.5 ) ) # # # # # # # # # FIRST FLIP # # # # # # # # # self.play(FlipCoin(randy)) self.play(SplitRectsInBrickWall(self.row)) self.row = self.merge_rects_by_subdiv(self.row) self.row = self.merge_rects_by_coloring(self.row) # # put tallies on top single_flip_labels = VGroup(UprightHeads(), UprightTails()) for (label, rect) in zip(single_flip_labels, self.row.rects): label.next_to(rect, UP) self.play(FadeIn(label)) self.wait() self.wait() # # # # # # # # # SECOND FLIP # # # # # # # # # self.play(FlipCoin(randy)) self.wait() self.play( SplitRectsInBrickWall(self.row) ) self.wait() # split sequences single_flip_labels_copy = single_flip_labels.copy() self.add(single_flip_labels_copy) v = self.row.get_outcome_centers_for_level(2)[0] - single_flip_labels[0].get_center() self.play( single_flip_labels.shift, v ) new_heads = VGroup(UprightHeads(), UprightHeads()) for i in range(2): new_heads[i].move_to(single_flip_labels[i]) new_heads[i].shift(COIN_SEQUENCE_SPACING * DOWN) self.play(FadeIn(new_heads)) v = self.row.get_outcome_centers_for_level(2)[-1] - single_flip_labels_copy[-1].get_center() self.play( single_flip_labels_copy.shift, v ) new_tails = VGroup(UprightTails(), UprightTails()) for i in range(2): new_tails[i].move_to(single_flip_labels_copy[i]) new_tails[i].shift(COIN_SEQUENCE_SPACING * DOWN) self.play(FadeIn(new_tails)) self.add_foreground_mobject(single_flip_labels) self.add_foreground_mobject(new_heads) self.add_foreground_mobject(single_flip_labels_copy) self.add_foreground_mobject(new_tails) # get individual outcomes outcomes = self.row.get_outcome_rects_for_level(2, with_labels = False, inset = True) grouped_outcomes = VGroup(outcomes[0], outcomes[1:3], outcomes[3]) decimal_tallies = VGroup() # introduce notion of tallies rects = self.row.get_rects_for_level(2) rect = rects[0] tally = DecimalTally(2,0) tally.next_to(rect, UP) decimal_tallies.add(tally) self.play( FadeIn(tally), FadeIn(grouped_outcomes[0]) ) self.wait() rect = rects[1] tally = DecimalTally(1,1) tally.next_to(rect, UP) decimal_tallies.add(tally) self.play( FadeIn(tally), FadeOut(grouped_outcomes[0]), FadeIn(grouped_outcomes[1]) ) self.wait() rect = rects[2] tally = DecimalTally(0,2) tally.next_to(rect, UP) decimal_tallies.add(tally) self.play( FadeIn(tally), FadeOut(grouped_outcomes[1]), FadeIn(grouped_outcomes[2]) ) self.wait() self.play( FadeOut(grouped_outcomes[2]) ) self.wait() self.wait() self.play( FadeOut(single_flip_labels), FadeOut(new_heads), FadeOut(single_flip_labels_copy), FadeOut(new_tails) ) self.wait() self.tallies = VGroup() for (i, rect) in enumerate(self.row.get_rects_for_level(2)): tally = TallyStack(2-i, i, show_decimals = False) tally.move_to(rect) self.tallies.add(tally) self.play(FadeIn(self.tallies)) self.wait() anims = [] for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies): anims.append(ApplyFunction( tally_stack.position_decimal_tally, decimal_tally )) self.play(*anims) self.wait() # replace the original decimal tallies with # the ones that belong to the TallyStacks for (decimal_tally, tally_stack) in zip(decimal_tallies, self.tallies): self.remove(decimal_tally) tally_stack.position_decimal_tally(tally_stack.decimal_tally) tally_stack.add(tally_stack.decimal_tally) self.add_foreground_mobject(self.tallies) self.row = self.merge_rects_by_subdiv(self.row) self.wait() self.row = self.merge_rects_by_coloring(self.row) self.wait() # # # # # # # # # # # # # # CALLBACK TO SEQUENCES # # # # # # # # # # # # # # outcomes = self.row.get_outcome_rects_for_level(2, with_labels = True, inset = True) subdivs = self.row.get_sequence_subdivs_for_level(2) self.play( FadeIn(outcomes), FadeIn(subdivs), FadeOut(self.tallies) ) self.wait() rect_to_dice = self.row.get_outcome_rects_for_level(2, with_labels = False, inset = False)[1] N = 10 dice_width = rect_to_dice.get_width()/N dice_height = rect_to_dice.get_height()/N prototype_dice = Rectangle( width = dice_width, height = dice_height, stroke_width = 2, stroke_color = WHITE, fill_color = WHITE, fill_opacity = 0 ) prototype_dice.align_to(rect_to_dice, direction = UP) prototype_dice.align_to(rect_to_dice, direction = LEFT) all_dice = VGroup() for i in range(N): for j in range(N): dice_copy = prototype_dice.copy() dice_copy.shift(j * dice_width * RIGHT + i * dice_height * DOWN) all_dice.add(dice_copy) self.play( OldLaggedStart(FadeIn, all_dice), FadeOut(outcomes[1]) ) self.wait() table = Ellipse(width = 1.5, height = 1) table.set_fill(color = GREEN_E, opacity = 1) table.next_to(rect_to_dice, UP) self.add(table) coin1 = UprightHeads(radius = 0.1) coin2 = UprightTails(radius = 0.1) def get_random_point_in_ellipse(ellipse): width = ellipse.get_width() height = ellipse.get_height() x = y = 1 while x**2 + y**2 > 0.9: x = np.random.uniform(-1,1) y = np.random.uniform(-1,1) x *= width/2 y *= height/2 return ellipse.get_center() + x * RIGHT + y * UP for dice in all_dice: p1 = get_random_point_in_ellipse(table) p2 = get_random_point_in_ellipse(table) coin1.move_to(p1) coin2.move_to(p2) self.add(coin1, coin2) self.play( ApplyMethod(dice.set_fill, {"opacity" : 0.5}, rate_func = there_and_back, run_time = 0.05) ) self.wait() self.play( FadeOut(outcomes), FadeOut(subdivs), FadeOut(all_dice), FadeOut(table), FadeOut(coin1), FadeOut(coin2), FadeIn(self.tallies) ) self.wait() # # # # # # # # # THIRD FLIP # # # # # # # # # # move row up, leave a copy without tallies below new_row = self.row.copy() self.clear() self.add(randy, self.row, self.tallies) self.bring_to_back(new_row) self.play( self.row.shift, 2.5 * UP, self.tallies.shift, 2.5 * UP, ) old_row = self.row self.row = new_row self.play(FlipCoin(randy)) self.wait() self.play( SplitRectsInBrickWall(self.row) ) self.wait() self.split_tallies_in_two_steps(self.row) self.wait() self.add_foreground_mobject(self.tallies) self.add_foreground_mobject(self.tallies_copy) self.remove(new_row) new_row = self.row self.clear() self.add(randy, self.row, old_row) self.add_foreground_mobject(self.tallies) self.add_foreground_mobject(self.tallies_copy) self.play( self.row.fade, 0.7, old_row.fade, 0.7, FadeOut(self.tallies), FadeOut(self.tallies_copy), ) # # # # # # # # # # # # # # # # # # SHOW SPLITTING WITH OUTCOMES # # # # # # # # # # # # # # # # # # # # show individual outcomes # old_outcomes = old_row.get_outcome_rects_for_level(2, with_labels = True) # old_outcomes_copy = old_outcomes.copy() # new_outcomes = self.row.get_outcome_rects_for_level(3, with_labels = True) # self.play( # FadeIn(old_outcomes[0]), # FadeIn(old_outcomes_copy[0]), # ) # self.wait() # self.play( # Transform(old_outcomes_copy[0], new_outcomes[1]) # ) # self.wait() # self.play( # FadeIn(old_outcomes[1:3]), # FadeIn(old_outcomes_copy[1:3]), # ) # self.wait() # self.play( # Transform(old_outcomes_copy[1:3], new_outcomes[2:4]) # ) # self.wait() # self.row = self.merge_rects_by_subdiv(self.row) # self.wait() # self.play( # FadeOut(old_row), # FadeOut(old_outcomes[0:3]), # FadeOut(new_outcomes[1:4]), # self.row.fade,0, # FadeIn(self.tallies[1]), # FadeIn(self.tallies_copy[0]), # ) # # rest of the new row # self.play( # FadeIn(self.tallies[:1]), # FadeIn(self.tallies[2:]), # FadeIn(self.tallies_copy[1:]) # ) # self.wait() # self.merge_tallies(self.row, target_pos = DOWN) # self.add_foreground_mobject(self.tallies) # self.row = self.merge_rects_by_coloring(self.row) # self.wait() # # # # # # # # # # # # # # # # # SHOW SPLITTING WITH TALLIES # # # # # # # # # # # # # # # # # tally_left = TallyStack(2,0) tally_left.move_to(old_row.rects[0]) tally_right = TallyStack(1,1) tally_right.move_to(old_row.rects[1]) rect_left = old_row.rects[0].copy() rect_right = old_row.rects[1].copy() self.play( FadeIn(rect_left), FadeIn(rect_right), FadeIn(tally_left), FadeIn(tally_right) ) rect_left.target = rect_left.copy() rect_left.target.stretch(0.5,0) left_target_pos = self.row.get_outcome_centers_for_level(3)[1] left_v = left_target_pos - rect_left.get_center() rect_left.target.move_to(left_target_pos) rect_right.target = rect_right.copy() rect_right.target.stretch(0.5,0) right_target_pos = 0.5 * (self.row.get_outcome_centers_for_level(3)[2] + self.row.get_outcome_centers_for_level(3)[3]) right_v = right_target_pos - rect_right.get_center() rect_right.target.move_to(right_target_pos) self.play( MoveToTarget(rect_left), tally_left.move_to, left_target_pos ) #tally_left.anchor += left_v self.wait() new_tally_left = TallyStack(2,1) #new_tally_left.move_anchor_to(tally_left.anchor) new_tally_left.move_to(tally_left) self.play( Transform(tally_left, new_tally_left) ) self.play( MoveToTarget(rect_right), tally_right.move_to, right_target_pos ) #tally_right.anchor += right_v self.wait() new_tally_right = TallyStack(2,1) #new_tally_right.move_anchor_to(tally_right.anchor) new_tally_right.move_to(tally_right) self.play( Transform(tally_right, new_tally_right) ) self.wait() self.row = self.merge_rects_by_subdiv(self.row) self.wait() self.play( FadeOut(old_row), self.row.fade,0, FadeOut(new_tally_left), FadeOut(new_tally_right), FadeIn(self.tallies[1]), FadeIn(self.tallies_copy[0]), ) # rest of the new row self.play( FadeIn(self.tallies[:1]), FadeIn(self.tallies[2:]), FadeIn(self.tallies_copy[1:]) ) self.wait() self.merge_tallies(self.row, target_pos = DOWN) self.add_foreground_mobject(self.tallies) self.row = self.merge_rects_by_coloring(self.row) self.wait() # show the 8 individual outcomes outcomes = self.row.get_outcome_rects_for_level(3, with_labels = True, inset = True) self.play(FadeOut(self.tallies)) self.wait() self.play(OldLaggedStart( FadeIn, outcomes, #rate_func = there_and_back_with_pause, run_time = 5)) self.wait() braces = VGroup(*[Brace(rect, UP) for rect in self.row.rects]) counts = [choose(3, i) for i in range(4)] probs = VGroup(*[TexMobject("{" + str(k) + "\over 8}") for k in counts]) for (brace, prob) in zip(braces, probs): prob.next_to(brace, UP) self.play( OldLaggedStart(ShowCreation, braces), OldLaggedStart(Write, probs) ) self.wait() self.play(OldLaggedStart( FadeOut, outcomes, #rate_func = there_and_back_with_pause, run_time = 5), ) self.play( FadeIn(self.tallies) ) self.wait() self.play( FadeOut(braces), FadeOut(probs) ) self.wait() # put visuals for other probability distribtuions here # back to three coin flips, show all 8 outcomes run_time = 5 self.play( OldLaggedStart(FadeIn, outcomes, #rate_func = there_and_back_with_pause, run_time = run_time), FadeOut(self.tallies, run_time = run_time) ) self.wait() self.play( OldLaggedStart(FadeOut, outcomes, #rate_func = there_and_back_with_pause, run_time = 5), FadeIn(self.tallies, run_time = run_time) ) # # # # # # # # # FOURTH FLIP # # # # # # # # # previous_row = self.row.copy() self.add(previous_row) v = 1.25 * self.row.height * UP self.play( previous_row.shift, v, self.tallies.shift, v, ) self.add_foreground_mobject(self.tallies) self.play( SplitRectsInBrickWall(self.row) ) self.wait() self.row = self.merge_rects_by_subdiv(self.row) self.revert_to_original_skipping_status() self.wait() n = 3 # level to split k = 1 # tally to split # show individual outcomes outcomes = previous_row.get_outcome_rects_for_level(n, with_labels = False, inset = True ) grouped_outcomes = VGroup() index = 0 for i in range(n + 1): size = choose(n,i) grouped_outcomes.add(VGroup(outcomes[index:index + size])) index += size grouped_outcomes_copy = grouped_outcomes.copy() original_grouped_outcomes = grouped_outcomes.copy() # for later reference self.play( OldLaggedStart(FadeIn, grouped_outcomes), OldLaggedStart(FadeIn, grouped_outcomes_copy), ) self.wait() # show how the outcomes in one tally split into two copies # going into the neighboring tallies #self.revert_to_original_skipping_status() target_outcomes = self.row.get_outcome_rects_for_level(n + 1, with_labels = False, inset = True ) grouped_target_outcomes = VGroup() index = 0 old_tally_sizes = [choose(n,i) for i in range(n + 1)] new_tally_sizes = [choose(n + 1,i) for i in range(n + 2)] for i in range(n + 2): size = new_tally_sizes[i] grouped_target_outcomes.add(VGroup(target_outcomes[index:index + size])) index += size old_tally_sizes.append(0) # makes the edge cases work properly # split all tallies for i in range(n + 1): self.play( Transform(grouped_outcomes[i][0], grouped_target_outcomes[i][0][old_tally_sizes[i - 1]:] ), Transform(grouped_outcomes_copy[i][0], grouped_target_outcomes[i + 1][0][:old_tally_sizes[i]] ) ) return self.wait() # fade in new tallies new_rects = self.row.get_rects_for_level(4) new_tallies = VGroup(*[ TallyStack(n + 1 - i, i).move_to(rect) for (i, rect) in enumerate(new_rects) ]) self.play(FadeIn(new_tallies)) self.add_foreground_mobject(new_tallies[1]) # remove outcomes and sizes except for one tally anims = [] for i in range(n + 1): if i != k - 1: anims.append(FadeOut(grouped_outcomes_copy[i])) if i != k: anims.append(FadeOut(grouped_outcomes[i])) anims.append(FadeOut(new_tallies[i])) #anims.append(FadeOut(self.tallies[0])) #anims.append(FadeOut(self.tallies[2:])) anims.append(FadeOut(new_tallies[-1])) self.play(*anims) self.wait() self.play( Transform(grouped_outcomes_copy[k - 1], original_grouped_outcomes[k - 1]) ) self.play( Transform(grouped_outcomes[k], original_grouped_outcomes[k]) ) new_rects = self.row.get_rects_for_level(n + 1) self.play( Transform(grouped_outcomes[k][0],grouped_target_outcomes[k][0][old_tally_sizes[k - 1]:]), Transform(grouped_outcomes_copy[k - 1][0],grouped_target_outcomes[k][0][:old_tally_sizes[k - 1]]), ) self.play( FadeOut(previous_row), FadeOut(self.tallies), ) self.row = self.merge_rects_by_coloring(self.row) self.play( FadeIn(new_tallies[0]), FadeIn(new_tallies[2:]), ) # # # # # # # # # # # EVEN MORE FLIPS # # # # # # # # # # # self.play(FadeOut(new_tallies)) self.clear() self.row = BrickRow(3) self.add(randy, self.row) for i in range(3): self.play(FlipCoin(randy)) self.wait() previous_row = self.row.copy() self.play(previous_row.shift, 1.25 * self.row.height * UP) self.play( SplitRectsInBrickWall(self.row) ) self.wait() self.row = self.merge_rects_by_subdiv(self.row) self.wait() self.row = self.merge_rects_by_coloring(self.row) self.wait() self.play(FadeOut(previous_row)) class ShowProbsInBrickRow3(BrickRowScene): def construct(self): randy = self.get_primary_pi_creature() randy = randy.scale(0.5).move_to(3*DOWN + 6*LEFT) #self.add(randy) self.row = BrickRow(3, height = 2, width = 10) self.wait() self.add(self.row) tallies = VGroup() for (i, rect) in enumerate(self.row.get_rects_for_level(3)): tally = TallyStack(3-i, i, show_decimals = False) tally.move_to(rect) tallies.add(tally) self.add(tallies) self.wait(6) braces = VGroup(*[Brace(rect, UP) for rect in self.row.rects]) counts = [choose(3, i) for i in range(4)] probs = VGroup(*[TexMobject("{" + str(k) + "\over 8}") for k in counts]) for (brace, prob) in zip(braces, probs): prob.next_to(brace, UP) self.wait() self.play( OldLaggedStart(ShowCreation, braces, run_time = 3), OldLaggedStart(Write, probs, run_time = 3) ) self.wait() self.play(FadeOut(braces),FadeOut(probs)) class ShowOutcomesInBrickRow4(BrickRowScene): def construct(self): randy = self.get_primary_pi_creature() randy = randy.scale(0.5).move_to(3*DOWN + 6*LEFT) #self.add(randy) self.row = BrickRow(3, height = 2, width = 10) previous_row = self.row.copy() v = 1.25 * self.row.height * UP self.play( previous_row.shift, v, ) self.add(self.row) self.add(previous_row) self.wait() previous_outcomes = previous_row.get_outcome_rects_for_level(3, with_labels = True, inset = True) previous_outcomes_copy = previous_outcomes.copy() self.play( OldLaggedStart(FadeIn, previous_outcomes), OldLaggedStart(FadeIn, previous_outcomes_copy), ) self.wait() new_outcomes = self.row.get_outcome_rects_for_level(4, with_labels = True, inset = True) # remove each last coin new_outcomes_left = VGroup( new_outcomes[0], new_outcomes[2], new_outcomes[3], new_outcomes[4], new_outcomes[8], new_outcomes[9], new_outcomes[10], new_outcomes[14] ) new_outcomes_right = VGroup( new_outcomes[1], new_outcomes[5], new_outcomes[6], new_outcomes[7], new_outcomes[11], new_outcomes[12], new_outcomes[13], new_outcomes[15] ) heads_labels = VGroup(*[outcome.label[-1] for outcome in new_outcomes_left]) tails_labels = VGroup(*[outcome.label[-1] for outcome in new_outcomes_right]) heads_labels.save_state() tails_labels.save_state() for outcome in new_outcomes: outcome.label[-1].fade(1) run_time = 0.5 self.play(Transform(previous_outcomes[0], new_outcomes_left[0], run_time = run_time)) self.play(Transform(previous_outcomes[1:4], new_outcomes_left[1:4], run_time = run_time)) self.play(Transform(previous_outcomes[4:7], new_outcomes_left[4:7], run_time = run_time)) self.play(Transform(previous_outcomes[7], new_outcomes_left[7], run_time = run_time)) self.play(heads_labels.restore) self.play(Transform(previous_outcomes_copy[0], new_outcomes_right[0], run_time = run_time)) self.play(Transform(previous_outcomes_copy[1:4], new_outcomes_right[1:4], run_time = run_time)) self.play(Transform(previous_outcomes_copy[4:7], new_outcomes_right[4:7], run_time = run_time)) self.play(Transform(previous_outcomes_copy[7], new_outcomes_right[7], run_time = run_time)) self.play(tails_labels.restore) self.wait() anims = [FadeOut(previous_outcomes),FadeOut(previous_outcomes_copy)] for outcome in new_outcomes_left: anims.append(FadeOut(outcome.label[-1])) for outcome in new_outcomes_right: anims.append(FadeOut(outcome.label[-1])) self.play(*anims) self.wait() class SplitTalliesIntoBrickRow4(BrickRowScene): def construct(self): randy = self.get_primary_pi_creature() randy = randy.scale(0.5).move_to(3*DOWN + 6*LEFT) #self.add(randy) self.row = BrickRow(3, height = 2, width = 10) previous_row = self.row.copy() v = 1.25 * self.row.height * UP self.play( previous_row.shift, v, ) tallies = VGroup() for (i, rect) in enumerate(previous_row.get_rects_for_level(3)): tally = TallyStack(3-i, i, show_decimals = True) tally.move_to(rect) tallies.add(tally) moving_tallies_left = tallies.copy() moving_tallies_right = tallies.copy() self.add(self.row, previous_row) self.add_foreground_mobject(tallies) self.add_foreground_mobject(moving_tallies_left) self.add_foreground_mobject(moving_tallies_right) self.play(SplitRectsInBrickWall(self.row)) anims = [] for (tally, rect) in zip(moving_tallies_left, previous_row.rects): anims.append(tally.move_to) anims.append(rect.get_center() + rect.get_width() * 0.25 * LEFT) self.play(*anims) new_tallies_left = VGroup() for (i, tally) in enumerate(moving_tallies_left): new_tally = TallyStack(4-i,i, with_labels = True) new_tally.move_to(tally) new_tallies_left.add(new_tally) self.play(Transform(moving_tallies_left, new_tallies_left)) anims = [] for (tally, rect) in zip(moving_tallies_right, previous_row.rects): anims.append(tally.move_to) anims.append(rect.get_center() + rect.get_width() * 0.25 * RIGHT) self.play(*anims) new_tallies_right = VGroup() for (i, tally) in enumerate(moving_tallies_right): new_tally = TallyStack(3-i,i+1, with_labels = True) new_tally.move_to(tally) new_tallies_right.add(new_tally) self.play(Transform(moving_tallies_right, new_tallies_right)) hypothetical_new_row = BrickRow(4, height = 2, width = 10) anims = [] for (tally, rect) in zip(moving_tallies_left[1:], hypothetical_new_row.rects[1:-1]): anims.append(tally.move_to) anims.append(rect) for (tally, rect) in zip(moving_tallies_right[:-1], hypothetical_new_row.rects[1:-1]): anims.append(tally.move_to) anims.append(rect) self.play(*anims) self.wait() self.row = self.merge_rects_by_subdiv(self.row) self.wait() self.row = self.merge_rects_by_coloring(self.row) self.wait()