From fe5438a841327ffaa1fbe1e46b3081bcbf997bb3 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Fri, 13 Apr 2018 12:24:39 +0200 Subject: [PATCH 1/8] expanded functionality of histograms, esp. for updating --- active_projects/eop/histograms.py | 73 ++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 21 deletions(-) diff --git a/active_projects/eop/histograms.py b/active_projects/eop/histograms.py index 2f5a847e..97ed6445 100644 --- a/active_projects/eop/histograms.py +++ b/active_projects/eop/histograms.py @@ -16,7 +16,8 @@ class Histogram(VMobject): "end_color" : BLUE, "x_scale" : 1.0, "y_scale" : 1.0, - "x_labels" : "auto", + "x_labels" : "auto", # widths, mids, auto, none, [...] + "y_labels" : "auto", # auto, none, [...] "x_min" : 0 } @@ -31,18 +32,29 @@ class Histogram(VMobject): elif mode == "posts" and len(x_values) != len(y_values) + 1: raise Exception("Array lengths do not match up!") - # preliminaries - self.y_values = np.array(y_values) - if mode == "widths": - self.widths = x_values + self.y_values = y_values + self.x_values = x_values + self.mode = mode + self.process_values() + + VMobject.__init__(self, **kwargs) + + + def process_values(self): + + # preliminaries + self.y_values = np.array(self.y_values) + + if self.mode == "widths": + self.widths = self.x_values self.posts = np.cumsum(self.widths) self.posts = np.insert(self.posts, 0, 0) self.posts += self.x_min self.x_max = self.posts[-1] - elif mode == "posts": - self.posts = x_values - self.widths = x_values[1:] - x_values[:-1] + elif self.mode == "posts": + self.posts = self.x_values + self.widths = self.x_values[1:] - self.x_values[:-1] self.x_min = self.posts[0] self.x_max = self.posts[-1] else: @@ -57,12 +69,14 @@ class Histogram(VMobject): self.y_values_scaled = self.y_scale * self.y_values - VMobject.__init__(self, **kwargs) - digest_config(self, kwargs) - + def generate_points(self): + self.process_values() + for submob in self.submobjects: + self.remove(submob) + def empty_string_array(n): arr = [] for i in range(n): @@ -72,21 +86,33 @@ class Histogram(VMobject): def num_arr_to_string_arr(arr): # converts number array to string array ret_arr = [] for x in arr: - ret_arr.append(str(x)) + if x == np.floor(x): + new_x = int(np.floor(x)) + else: + new_x = x + ret_arr.append(str(new_x)) return ret_arr previous_bar = ORIGIN - self.bars = [] + self.bars = VGroup() + self.x_labels_group = VGroup() + self.y_labels_group = VGroup() outline_points = [] + if self.x_labels == "widths": self.x_labels = num_arr_to_string_arr(self.widths) elif self.x_labels == "mids": - print self.x_mids self.x_labels = num_arr_to_string_arr(self.x_mids) elif self.x_labels == "none": self.x_labels = empty_string_array(len(self.widths)) - print self.x_labels + if self.y_labels == "auto": + self.y_labels = num_arr_to_string_arr(self.y_values) + elif self.y_labels == "none": + self.y_labels = empty_string_array(len(self.y_values)) + + + for (i,x) in enumerate(self.x_mids): @@ -104,12 +130,15 @@ class Histogram(VMobject): bar.set_stroke(width = 0) bar.next_to(previous_bar,RIGHT,buff = 0, aligned_edge = DOWN) - self.add(bar) - self.bars.append(bar) + self.bars.add(bar) - label = TextMobject(self.x_labels[i]) - label.next_to(bar,DOWN) - self.add(label) + x_label = TextMobject(self.x_labels[i]) + x_label.next_to(bar,DOWN) + self.x_labels_group.add(x_label) + + y_label = TextMobject(self.y_labels[i]) + y_label.next_to(bar, UP) + self.y_labels_group.add(y_label) if i == 0: # start with the lower left @@ -128,7 +157,9 @@ class Histogram(VMobject): self.outline = Polygon(*outline_points) self.outline.set_stroke(color = WHITE) - self.add(self.outline) + self.add(self.bars, self.x_labels_group, self.y_labels_group, self.outline) + + print self.submobjects def get_lower_left_point(self): return self.bars[0].get_anchors()[-2] From 85b2249a24079a0c617257946afa5869c758a499 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Fri, 13 Apr 2018 12:24:56 +0200 Subject: [PATCH 2/8] basic animation for dice working --- active_projects/eop/chapter1.py | 44 +++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/active_projects/eop/chapter1.py b/active_projects/eop/chapter1.py index 8d71e708..6e62cf9f 100644 --- a/active_projects/eop/chapter1.py +++ b/active_projects/eop/chapter1.py @@ -1123,16 +1123,44 @@ class RowOfDice(VGroup): class ShowUncertainty(PiCreatureScene): + def throw_a_die(self): + + eye = np.random.randint(1,7) + face = self.row_of_dice.submobjects[eye - 1] + self.tallies[eye - 1] += 1 + + new_hist = self.hist_from_tallies() + + self.play( + ApplyMethod(face.submobjects[0].set_fill, {"opacity": 1}, rate_func = there_and_back), + Transform(self.dice_histogram, new_hist) + ) + + + + def hist_from_tallies(self): + hist = Histogram(0.5 * np.ones(6), self.tallies, + mode = "widths", + x_labels = "none", + y_scale = 0.5 + ) + + hist.next_to(self.row_of_dice, UP) + hist.stretch_to_fit_width(self.row_of_dice.get_width()) + return hist + def construct(self): - row_of_dice = RowOfDice().scale(0.5).move_to(ORIGIN) - self.add(row_of_dice) - rounded_rect = RoundedRectangle( - width = 3, - height = 2, - corner_radius = 0.1 - ).shift(3*LEFT) - self.add(rounded_rect) + self.row_of_dice = RowOfDice().scale(0.5).move_to(3 * DOWN) + self.add(self.row_of_dice) + + self.tallies = np.ones(6) + self.dice_histogram = self.hist_from_tallies() + + self.add(self.dice_histogram) + + for i in range(30): + self.throw_a_die() From 5cc5b204085a75bbee40f697d63c355fdc243617 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Fri, 13 Apr 2018 13:32:58 +0200 Subject: [PATCH 3/8] throwing darts --- active_projects/eop/chapter1.py | 71 +++++++++++++++++++++++++++------ 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/active_projects/eop/chapter1.py b/active_projects/eop/chapter1.py index 6e62cf9f..6552a47e 100644 --- a/active_projects/eop/chapter1.py +++ b/active_projects/eop/chapter1.py @@ -1121,7 +1121,7 @@ class RowOfDice(VGroup): -class ShowUncertainty(PiCreatureScene): +class ShowUncertainty1(PiCreatureScene): def throw_a_die(self): @@ -1132,21 +1132,28 @@ class ShowUncertainty(PiCreatureScene): new_hist = self.hist_from_tallies() self.play( - ApplyMethod(face.submobjects[0].set_fill, {"opacity": 1}, rate_func = there_and_back), - Transform(self.dice_histogram, new_hist) + ApplyMethod(face.submobjects[0].set_fill, {"opacity": 1}, + rate_func = there_and_back, + run_time = 0.3, + ), + ) + self.play( + Transform(self.dice_histogram, new_hist, + run_time = 0.5) ) def hist_from_tallies(self): - hist = Histogram(0.5 * np.ones(6), self.tallies, + x_scale = self.row_of_dice.get_width() / np.size(self.tallies) + hist = Histogram(np.ones(6), self.tallies, mode = "widths", x_labels = "none", - y_scale = 0.5 + y_scale = 0.5, + x_scale = x_scale ) hist.next_to(self.row_of_dice, UP) - hist.stretch_to_fit_width(self.row_of_dice.get_width()) return hist def construct(self): @@ -1154,18 +1161,58 @@ class ShowUncertainty(PiCreatureScene): self.row_of_dice = RowOfDice().scale(0.5).move_to(3 * DOWN) self.add(self.row_of_dice) - self.tallies = np.ones(6) + self.tallies = np.zeros(6) self.dice_histogram = self.hist_from_tallies() self.add(self.dice_histogram) for i in range(30): self.throw_a_die() - - - - - + self.wait() + + + + +class ShowUncertainty2(PiCreatureScene): + + + def throw_darts(self, n, run_time = 1): + + points = np.random.normal( + loc = self.dartboard.get_center(), + scale = 0.6 * np.ones(3), + size = (n,3) + ) + points[:,2] = 0 + dots = VGroup() + for point in points: + dot = Dot(point, radius = 0.04, fill_opacity = 0.7) + dots.add(dot) + self.add(dot) + + self.play( + LaggedStart(FadeIn, dots, lag_ratio = 0.01, run_time = run_time) + ) + + + def construct(self): + + self.dartboard = ImageMobject("dartboard").scale(2) + dartboard_circle = Circle( + radius = self.dartboard.get_width() / 2, + fill_color = BLACK, + fill_opacity = 0.5, + stroke_color = WHITE, + stroke_width = 5 + ) + self.dartboard.add(dartboard_circle) + + self.add(self.dartboard) + + self.throw_darts(5,5) + self.throw_darts(20,5) + self.throw_darts(100,5) + self.throw_darts(1000,5) From 2171ee957a9561b439ebaafadc00444712830fcc Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Fri, 13 Apr 2018 14:08:51 +0200 Subject: [PATCH 4/8] 3rd example of uncertainty: coin flip --- active_projects/eop/chapter1.py | 58 ++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 5 deletions(-) diff --git a/active_projects/eop/chapter1.py b/active_projects/eop/chapter1.py index 6552a47e..9200fe8b 100644 --- a/active_projects/eop/chapter1.py +++ b/active_projects/eop/chapter1.py @@ -1,7 +1,6 @@ from big_ol_pile_of_manim_imports import * from old_projects.eoc.chapter8 import * from active_projects.eop.histograms import * -from svgpathtools import * import scipy.special @@ -75,7 +74,7 @@ class CoinFlippingPiCreature(PiCreature): def __init__(self, **kwargs): - coin = PiCreatureCoin() # Line(ORIGIN, 0.4 * RIGHT, stroke_width = 15, color = YELLOW) + coin = PiCreatureCoin() PiCreature.__init__(self,**kwargs) self.coin = coin self.add(coin) @@ -270,19 +269,33 @@ class TailsStack(CoinStack): } class TallyStack(VGroup): + CONFIG = { + "coin_thickness": COIN_THICKNESS + } - def __init__(self,h,t,**kwargs): + def __init__(self,h,t,anchor = ORIGIN, **kwargs): self.nb_heads = h self.nb_tails = t + self.anchor = anchor VGroup.__init__(self,**kwargs) def generate_points(self): stack1 = HeadsStack(size = self.nb_heads, coin_thickness = self.coin_thickness) stack2 = TailsStack(size = self.nb_tails, coin_thickness = self.coin_thickness) - stack2.next_to(stack1, RIGHT, buff = SMALL_BUFF) - stack2.align_to(stack1, DOWN) + stack1.next_to(self.anchor, LEFT, buff = SMALL_BUFF) + stack2.next_to(self.anchor, RIGHT, buff = SMALL_BUFF) + stack1.align_to(self.anchor, DOWN) + stack2.align_to(self.anchor, DOWN) + self.heads_stack = stack1 + self.tails_stack = stack2 self.add(stack1, stack2) + def move_anchor_to(self, new_anchor): + for submob in self.submobjects: + submob.shift(new_anchor - self.anchor) + self.anchor = new_anchor + return self + class CoinFlipTree(VGroup): CONFIG = { "total_width": 12, @@ -1218,6 +1231,41 @@ class ShowUncertainty2(PiCreatureScene): +class ShowUncertainty3(Scene): + + def construct(self): + + randy = CoinFlippingPiCreature(color = MAROON_E) + randy.scale(0.5).to_edge(LEFT + DOWN) + + heads = tails = 0 + tally = TallyStack(heads, tails, anchor = ORIGIN) + + for i in range(10): + + self.play(FlipCoin(randy)) + self.wait(0.5) + + flip = np.random.randint(0,2) + if flip == 0: + heads += 1 + elif flip == 1: + tails += 1 + else: + raise Exception("That side does not exist on this coin") + + new_tally = TallyStack(heads, tails, anchor = ORIGIN) + + if tally.nb_heads == 0 and new_tally.nb_heads == 1: + self.play(FadeIn(new_tally.heads_stack)) + elif tally.nb_tails == 0 and new_tally.nb_tails == 1: + self.play(FadeIn(new_tally.tails_stack)) + else: + self.play(Transform(tally, new_tally)) + + tally = new_tally + + From 75c0ed84c86220276ae832359f7947787846f3a9 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Fri, 13 Apr 2018 14:22:13 +0200 Subject: [PATCH 5/8] trying to improve the timing of the pi creature coin flip --- active_projects/eop/chapter1.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/active_projects/eop/chapter1.py b/active_projects/eop/chapter1.py index 9200fe8b..f7163cb9 100644 --- a/active_projects/eop/chapter1.py +++ b/active_projects/eop/chapter1.py @@ -106,12 +106,15 @@ class FlipCoin(AnimationGroup): rate_func = self.rate_func, **kwargs ) - coin_motion = FlipUpAndDown( - pi_creature.coin, - vector = UP, - nb_turns = 5, - rate_func = self.rate_func, - **kwargs + coin_motion = Succession( + EmptyAnimation(run_time = 1.0), + FlipUpAndDown( + pi_creature.coin, + vector = UP, + nb_turns = 5, + rate_func = self.rate_func, + **kwargs + ) ) AnimationGroup.__init__(self,pi_creature_motion, coin_motion) @@ -1241,12 +1244,16 @@ class ShowUncertainty3(Scene): heads = tails = 0 tally = TallyStack(heads, tails, anchor = ORIGIN) - for i in range(10): + nb_flips = 10 + + flips = np.random.randint(2, size = nb_flips) + + for i in range(nb_flips): self.play(FlipCoin(randy)) self.wait(0.5) - flip = np.random.randint(0,2) + flip = flips[i] if flip == 0: heads += 1 elif flip == 1: From 426f59b9f947bd5fa42448c87ad2ee77fb4fdd51 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Fri, 13 Apr 2018 18:24:48 +0200 Subject: [PATCH 6/8] putting things together in the intro scene --- active_projects/eop/chapter1.py | 149 +++++++++++++++----------------- 1 file changed, 69 insertions(+), 80 deletions(-) diff --git a/active_projects/eop/chapter1.py b/active_projects/eop/chapter1.py index f7163cb9..8830cd86 100644 --- a/active_projects/eop/chapter1.py +++ b/active_projects/eop/chapter1.py @@ -378,36 +378,6 @@ class CoinFlipTree(VGroup): -class TestScene(Scene): - - def construct(self): - - #seq = CoinSequence(["H", "T", "T", "H"]).move_to(2 * LEFT) - #self.add(seq) - - #stack = TallyStack(4,7, coin_thickness = COIN_THICKNESS) - #self.add(stack) - - tree = CoinFlipTree(nb_levels = 7, sort_until_level = 0) - tree.move_to(ORIGIN) - self.add(tree) - - for i in range(1, 8): - new_tree = CoinFlipTree(nb_levels = 7, sort_until_level = i) - new_tree.move_to(ORIGIN) - self.play(Transform(tree, new_tree)) - self.wait() - - self.wait() - - -class CoinFlipBranchToAreaScene(Scene): - - def construct(self): - - pass - - class Chapter1OpeningQuote(OpeningQuote): CONFIG = { @@ -441,6 +411,7 @@ class Introduction(TeacherStudentsScene): def construct(self): self.show_series() + self.show_area_model1() def show_series(self): series = VideoSeries() @@ -491,28 +462,28 @@ class Introduction(TeacherStudentsScene): Animation(self.teacher.bubble.content), ]) - essence_words = words.get_part_by_tex("Essence").copy() self.play( FadeOut(self.teacher.bubble), FadeOut(self.teacher.bubble.content), - essence_words.next_to, series, DOWN, *[ ApplyMethod(pi.change_mode, "pondering") for pi in self.get_pi_creatures() ] ) - self.wait(3) + self.wait() self.series = series - self.essence_words = essence_words -class IllustrateAreaModel1(Scene): - - def construct(self): + # # # # # # # # # # # # # # # # # # + # show examples of the area model # + # # # # # # # # # # # # # # # # # # + + def show_area_model1(self): + # show independent events - sample_space_width = sample_space_height = 3.0 + sample_space_width = sample_space_height = 2.5 p_of_A = 0.7 p_of_not_A = 1 - p_of_A p_of_B = 0.8 @@ -525,7 +496,8 @@ class IllustrateAreaModel1(Scene): stroke_width = 0, fill_color = BLUE, fill_opacity = 1.0 - ) + ).move_to(2 * RIGHT + 1.5 * UP) + rect_not_A = Rectangle( width = p_of_not_A * sample_space_width, height = 1 * sample_space_height, @@ -539,18 +511,13 @@ class IllustrateAreaModel1(Scene): brace_not_A = Brace(rect_not_A, DOWN) label_not_A = TexMobject("P(\\text{not }A)").next_to(brace_not_A, DOWN).scale(0.7) - self.play( - LaggedStart(FadeIn, VGroup(rect_A, rect_not_A), lag_factor = 0.5) - ) - self.play( - ShowCreation(brace_A), - Write(label_A), - ) # self.play( - # ShowCreation(brace_not_A), - # Write(label_not_A), + # LaggedStart(FadeIn, VGroup(rect_A, rect_not_A), lag_factor = 0.5) + # ) + # self.play( + # ShowCreation(brace_A), + # Write(label_A), # ) - @@ -576,16 +543,12 @@ class IllustrateAreaModel1(Scene): brace_not_B = Brace(rect_not_B, LEFT) label_not_B = TexMobject("P(\\text{not }B)").next_to(brace_not_B, LEFT).scale(0.7) - self.play( - LaggedStart(FadeIn, VGroup(rect_B, rect_not_B), lag_factor = 0.5) - ) - self.play( - ShowCreation(brace_B), - Write(label_B), - ) # self.play( - # ShowCreation(brace_not_B), - # Write(label_not_B), + # LaggedStart(FadeIn, VGroup(rect_B, rect_not_B), lag_factor = 0.5) + # ) + # self.play( + # ShowCreation(brace_B), + # Write(label_B), # ) rect_A_and_B = Rectangle( @@ -597,11 +560,9 @@ class IllustrateAreaModel1(Scene): label_A_and_B = TexMobject("P(A\\text{ and }B)").scale(0.7) label_A_and_B.move_to(rect_A_and_B) - self.play( - ShowCreation(rect_A_and_B) - ) - self.play(FadeIn(label_A_and_B)) - self.add_foreground_mobject(label_A_and_B) + # self.play( + # ShowCreation(rect_A_and_B) + # ) indep_formula = TexMobject("P(A\\text{ and }B)", "=", "P(A)", "\cdot", "P(B)") indep_formula = indep_formula.scale(0.7).next_to(rect_not_B, UP, buff = MED_LARGE_BUFF) @@ -609,16 +570,19 @@ class IllustrateAreaModel1(Scene): label_A_and_B_copy = label_A_and_B.copy() label_A_copy = label_A.copy() label_B_copy = label_B.copy() - self.add(label_A_and_B_copy, label_A_copy, label_B_copy) + # self.add(label_A_and_B_copy, label_A_copy, label_B_copy) - self.play(Transform(label_A_and_B_copy, indep_formula[0])) - self.play(FadeIn(indep_formula[1])) - self.play(Transform(label_A_copy, indep_formula[2])) - self.play(FadeIn(indep_formula[3])) - self.play(Transform(label_B_copy, indep_formula[4])) + # self.play(Transform(label_A_and_B_copy, indep_formula[0])) + # self.play(FadeIn(indep_formula[1])) + # self.play(Transform(label_A_copy, indep_formula[2])) + # self.play(FadeIn(indep_formula[3])) + # self.play(Transform(label_B_copy, indep_formula[4])) - self.wait() + #self.wait() + label_A_and_B_copy = indep_formula[0] + label_A_copy = indep_formula[2] + label_B_copy = indep_formula[4] # show conditional prob @@ -647,11 +611,22 @@ class IllustrateAreaModel1(Scene): fill_opacity = 0.5 ).next_to(rect_not_A_and_B, UP, buff = 0) - self.remove(rect_B, rect_not_B) - self.add(rect_A_and_not_B, rect_not_A_and_B, rect_not_A_and_not_B) + indep_formula.next_to(rect_not_A, LEFT, buff = 4) + indep_formula.shift(UP) + self.play(Write(indep_formula)) + self.play( + FadeIn(VGroup( + rect_A, rect_not_A, brace_A, label_A, brace_B, label_B, + rect_A_and_not_B, rect_not_A_and_B, rect_not_A_and_not_B, + rect_A_and_B, + label_A_and_B, + )) + ) + + self.wait() p_of_B_knowing_A = 0.6 @@ -684,7 +659,7 @@ class IllustrateAreaModel1(Scene): ) label_B_knowing_A = label_B - self.play(FadeOut(label_B_copy)) + #self.play(FadeOut(label_B_copy)) self.remove(indep_formula.get_part_by_tex("P(B)")) label_B_knowing_A_copy = label_B_knowing_A.copy() self.add(label_B_knowing_A_copy) @@ -700,6 +675,7 @@ class IllustrateAreaModel1(Scene): self.wait() + self.play( # in some places get_part_by_tex does not find the correct part # so I picked out fitting indices @@ -707,7 +683,17 @@ class IllustrateAreaModel1(Scene): label_A_copy.move_to, rearranged_formula[-1][10], label_A_and_B_copy.move_to, rearranged_formula[-1][3], indep_formula.get_part_by_tex("=").move_to, rearranged_formula.get_part_by_tex("="), - Transform(indep_formula.get_part_by_tex("\cdot"), rearranged_formula[-1][8]), + Transform(indep_formula.get_part_by_tex("\cdot"), rearranged_formula[2][6]), + ) + + + self.play( + FadeOut(VGroup( + indep_formula, rect_A, rect_B, rect_not_A, rect_not_B, + rect_A_and_B, rect_A_and_not_B, rect_not_A_and_B, rect_not_A_and_not_B, + brace_A, brace_B, label_A, label_B_knowing_A, label_A_and_B, + label_B_knowing_A_copy + )) ) @@ -792,8 +778,8 @@ class IllustrateAreaModel1(Scene): class IllustrateAreaModel2(GraphScene): CONFIG = { - "x_min" : -5, - "x_max" : 5, + "x_min" : -3.5, + "x_max" : 3.5, "y_min" : -0, "y_max" : 0.6, "graph_origin": 3*DOWN, @@ -801,7 +787,10 @@ class IllustrateAreaModel2(GraphScene): "y_axis_label" : "", "x_axis_label" : "", "variable_point_label" : "x", - "y_axis_height" : 4 + "y_axis_height" : 4, + "graph_origin": 2.5 * DOWN + 3 * LEFT, + "x_axis_width": 5, + "y_axis_height": 3 } def construct(self): @@ -809,7 +798,7 @@ class IllustrateAreaModel2(GraphScene): x_max_1 = 0 x_min_1 = -x_max_1 - x_max_2 = 5 + x_max_2 = 3.5 x_min_2 = -x_max_2 @@ -818,10 +807,10 @@ class IllustrateAreaModel2(GraphScene): self.add(graph) - cdf_formula = TexMobject("P(|X-\mu| < x) = \int_{-x}^x {\exp(-{1\over 2}({t\over \sigma})^2) \over \sigma\sqrt{2\pi}} dt") + cdf_formula.set_color_by_tex("x", YELLOW) - cdf_formula.next_to(graph, LEFT, buff = 1) + cdf_formula.next_to(graph, RIGHT, buff = -1) self.add(cdf_formula) From 0231b49850176834b8e4e427159ebd919bed15e3 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Sun, 15 Apr 2018 20:26:37 +0200 Subject: [PATCH 7/8] basic enumeration of permutations --- active_projects/eop/chapter2.py | 72 +++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 active_projects/eop/chapter2.py diff --git a/active_projects/eop/chapter2.py b/active_projects/eop/chapter2.py new file mode 100644 index 00000000..ec4c76d1 --- /dev/null +++ b/active_projects/eop/chapter2.py @@ -0,0 +1,72 @@ +from big_ol_pile_of_manim_imports import * + +def print_permutation(index_list): + + + n = max(max(index_list), len(index_list)) + for i in range(0,n): + if index_list[i] > n - i: + raise Exception("Impossible indices!") + + #print "given index list:", index_list + perm_list = n * ["_"] + alphabet = ["A", "B", "C", "D", "E", "F", + "G", "H", "I", "J", "K", "L", + "M", "N", "O", "P", "Q", "R", + "S", "T", "U", "V", "W", "X", + "Y", "Z"] + free_indices = range(n) + free_indices_p1 = range(1,n + 1) + #print perm_list + for i in range(n): + findex = index_list[i] - 1 + #print "place next letter at", findex + 1, "th free place" + tindex = free_indices[findex] + #print "so at position", tindex + 1 + perm_list[tindex] = alphabet[i] + free_indices.remove(tindex) + free_indices_p1.remove(tindex + 1) + #print "remaining free places:", free_indices_p1 + #print perm_list + + return "".join(perm_list) + + + + + +N = 5 + +index_list = [] +for i in range(1, N + 1): + index_list.append(i) + for j in range(1, N): + index_list.append(j) + for k in range(1, N - 1): + index_list.append(k) + for l in range(1, N - 2): + index_list.append(l) + for m in range(1, N - 3): + index_list.append(m) + print print_permutation(index_list) + index_list.pop() + index_list.pop() + index_list.pop() + index_list.pop() + index_list.pop() + + + + + + + + + + + + + + + + From 51f002b3ba39dc68ec038f01a4c87a02b6334227 Mon Sep 17 00:00:00 2001 From: Ben Hambrecht Date: Sun, 15 Apr 2018 21:21:18 +0200 Subject: [PATCH 8/8] A pretty map of S5 --- active_projects/eop/chapter2.py | 61 +++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 15 deletions(-) diff --git a/active_projects/eop/chapter2.py b/active_projects/eop/chapter2.py index ec4c76d1..f3cb0057 100644 --- a/active_projects/eop/chapter2.py +++ b/active_projects/eop/chapter2.py @@ -32,28 +32,59 @@ def print_permutation(index_list): return "".join(perm_list) +class PermutationGrid(Scene): + + def text_box(self, str): + box = TextMobject(str).scale(0.3) + box.add(SurroundingRectangle(box, stroke_color = DARK_GREY)) + return box + def construct(self): -N = 5 -index_list = [] -for i in range(1, N + 1): - index_list.append(i) - for j in range(1, N): - index_list.append(j) - for k in range(1, N - 1): - index_list.append(k) - for l in range(1, N - 2): - index_list.append(l) - for m in range(1, N - 3): - index_list.append(m) - print print_permutation(index_list) + N = 5 + + index_list = [] + perm5_box = VGroup() + for i in range(1, N + 1): + index_list.append(i) + perm4_box = VGroup() + for j in range(1, N): + index_list.append(j) + perm3_box = VGroup() + for k in range(1, N - 1): + index_list.append(k) + perm2_box = VGroup() + for l in range(1, N - 2): + index_list.append(l) + index_list.append(1) + perm_box = self.text_box(print_permutation(index_list)) + if l > 1: + perm_box.next_to(perm2_box[-1], DOWN, buff = 0) + perm2_box.add(perm_box) + index_list.pop() + index_list.pop() + if k > 1: + perm2_box.next_to(perm3_box[-1], RIGHT, buff = 0.08) + perm3_box.add(perm2_box) index_list.pop() + perm3_box.add(SurroundingRectangle(perm3_box, buff = 0.12, stroke_color = LIGHT_GRAY)) + if j > 1: + perm3_box.next_to(perm4_box[-1], DOWN, buff = 0) + perm4_box.add(perm3_box) index_list.pop() + if i > 1: + perm4_box.next_to(perm5_box[-1], RIGHT, buff = 0.16) + perm5_box.add(perm4_box) index_list.pop() - index_list.pop() - index_list.pop() + + perm5_box.move_to(ORIGIN) + self.add(perm5_box) + + + +