mirror of
https://github.com/3b1b/manim.git
synced 2025-08-05 16:49:03 +00:00
PascalsTriangle in eop/combinations
This commit is contained in:
parent
0e7fbe73b8
commit
0399b54b9a
1 changed files with 411 additions and 4 deletions
|
@ -1146,10 +1146,417 @@ class BuildFiveFromFour(ProbabilityOfThreeWomenInGroupOfFive):
|
|||
self.play(Write(new_numbers, run_time = 3))
|
||||
self.dither()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class BuildUpFromStart(Scene):
|
||||
CONFIG = {
|
||||
"n_iterations" : 7,
|
||||
}
|
||||
def construct(self):
|
||||
stacks = VGroup(VGroup(Male()), VGroup(Female()))
|
||||
stacks.arrange_submobjects(RIGHT, buff = LARGE_BUFF)
|
||||
stacks.numbers = self.get_numbers(stacks)
|
||||
|
||||
max_width = 2*SPACE_WIDTH - 3
|
||||
max_height = SPACE_HEIGHT - 1
|
||||
|
||||
self.add(stacks, stacks.numbers)
|
||||
for x in range(self.n_iterations):
|
||||
if x < 2:
|
||||
dither_time = 1
|
||||
else:
|
||||
dither_time = 0.2
|
||||
#Divide
|
||||
low_stacks = stacks
|
||||
low_group = VGroup(low_stacks, low_stacks.numbers)
|
||||
top_stacks = stacks.deepcopy()
|
||||
top_group = VGroup(top_stacks, top_stacks.numbers)
|
||||
for group, vect in (top_group, UP), (low_group, DOWN):
|
||||
group.generate_target()
|
||||
if group[0].get_height() > max_height:
|
||||
group.target[0].stretch_to_fit_height(max_height)
|
||||
for stack, num in zip(*group.target):
|
||||
num.next_to(stack, UP)
|
||||
group.target.next_to(ORIGIN, vect)
|
||||
self.play(*map(MoveToTarget, [top_group, low_group]))
|
||||
self.dither(dither_time)
|
||||
|
||||
#Expand
|
||||
for stacks, i in (low_stacks, 0), (top_stacks, -1):
|
||||
sym = stacks[i][i][i]
|
||||
new_stacks = VGroup()
|
||||
for stack in stacks:
|
||||
new_stack = VGroup()
|
||||
for line in stack:
|
||||
new_line = line.copy()
|
||||
new_sym = sym.copy()
|
||||
buff = 0.3*line.get_height()
|
||||
new_sym.next_to(line, RIGHT, buff = buff)
|
||||
new_line.add(new_sym)
|
||||
line.add(VectorizedPoint(line[-1].get_center()))
|
||||
new_stack.add(new_line)
|
||||
new_stacks.add(new_stack)
|
||||
new_stacks.arrange_submobjects(
|
||||
RIGHT, buff = LARGE_BUFF, aligned_edge = DOWN
|
||||
)
|
||||
if new_stacks.get_width() > max_width:
|
||||
new_stacks.stretch_to_fit_width(max_width)
|
||||
if new_stacks.get_height() > max_height:
|
||||
new_stacks.stretch_to_fit_height(max_height)
|
||||
new_stacks.move_to(stacks, DOWN)
|
||||
stacks.target = new_stacks
|
||||
stacks.numbers.generate_target()
|
||||
|
||||
for num, stack in zip(stacks.numbers.target, new_stacks):
|
||||
num.next_to(stack, UP)
|
||||
self.play(*map(MoveToTarget, [
|
||||
top_stacks, low_stacks,
|
||||
top_stacks.numbers, low_stacks.numbers,
|
||||
]))
|
||||
self.dither(dither_time)
|
||||
|
||||
#Shift
|
||||
dist = top_stacks[1].get_center()[0] - top_stacks[0].get_center()[0]
|
||||
self.play(
|
||||
top_group.shift, dist*RIGHT/2,
|
||||
low_group.shift, dist*LEFT/2,
|
||||
)
|
||||
self.dither(dither_time)
|
||||
|
||||
#Stack
|
||||
all_movers = VGroup()
|
||||
plusses = VGroup()
|
||||
expressions = VGroup(low_stacks.numbers[0])
|
||||
stacks = VGroup(low_stacks[0])
|
||||
v_buff = 0.25*stacks[0][0].get_height()
|
||||
|
||||
for i, top_stack in enumerate(top_stacks[:-1]):
|
||||
low_stack = low_stacks[i+1]
|
||||
top_num = top_stacks.numbers[i]
|
||||
low_num = low_stacks.numbers[i+1]
|
||||
movers = [top_stack, top_num, low_num]
|
||||
for mover in movers:
|
||||
mover.generate_target()
|
||||
plus = TexMobject("+")
|
||||
expr = VGroup(top_num.target, plus, low_num.target)
|
||||
expr.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||
top_stack.target.next_to(low_stack, UP, buff = v_buff)
|
||||
expr.next_to(top_stack.target, UP)
|
||||
|
||||
all_movers.add(*movers)
|
||||
plusses.add(plus)
|
||||
expressions.add(VGroup(top_num, plus, low_num))
|
||||
stacks.add(VGroup(*it.chain(low_stack, top_stack)))
|
||||
|
||||
last_group = VGroup(top_stacks[-1], top_stacks.numbers[-1])
|
||||
last_group.generate_target()
|
||||
last_group.target.align_to(low_stacks, DOWN)
|
||||
all_movers.add(last_group)
|
||||
stacks.add(top_stacks[-1])
|
||||
expressions.add(top_stacks.numbers[-1])
|
||||
|
||||
self.play(*it.chain(
|
||||
map(MoveToTarget, all_movers),
|
||||
map(Write, plusses),
|
||||
))
|
||||
|
||||
#Add
|
||||
new_numbers = self.get_numbers(stacks)
|
||||
self.play(ReplacementTransform(
|
||||
expressions, VGroup(*map(VGroup, new_numbers))
|
||||
))
|
||||
self.dither(dither_time)
|
||||
stacks.numbers = new_numbers
|
||||
|
||||
|
||||
####
|
||||
|
||||
def get_numbers(self, stacks):
|
||||
return VGroup(*[
|
||||
TexMobject(str(len(stack))).next_to(stack, UP)
|
||||
for stack in stacks
|
||||
])
|
||||
|
||||
class PascalsTriangle(Scene):
|
||||
CONFIG = {
|
||||
"max_n" : 9,
|
||||
}
|
||||
def construct(self):
|
||||
self.show_triangle()
|
||||
self.show_sum_of_two_over_rule()
|
||||
self.keep_in_mind_what_these_mean()
|
||||
self.issolate_9_choose_4_term()
|
||||
self.show_9_choose_4_pattern()
|
||||
self.cap_off_triangle()
|
||||
|
||||
def show_triangle(self):
|
||||
distance = 0.8
|
||||
max_width = 0.7*distance
|
||||
angle = 0.2*np.pi
|
||||
t_down = rotate_vector(distance*DOWN, -angle)
|
||||
t_right = 2*distance*np.sin(angle)*RIGHT
|
||||
|
||||
rows = VGroup()
|
||||
for n in range(self.max_n + 1):
|
||||
row = VGroup()
|
||||
for k in range(n+1):
|
||||
num = TexMobject(str(choose(n, k)))
|
||||
# if num.get_width() > max_width:
|
||||
# num.scale_to_fit_width(max_width)
|
||||
num.shift(n*t_down + k*t_right)
|
||||
row.add(num)
|
||||
rows.add(row)
|
||||
rows.to_edge(UP)
|
||||
|
||||
self.play(FadeIn(rows[1]))
|
||||
for last_row, curr_row in zip(rows[1:], rows[2:]):
|
||||
self.play(*[
|
||||
Transform(
|
||||
last_row.copy(), VGroup(*mobs),
|
||||
remover = True
|
||||
)
|
||||
for mobs in curr_row[1:], curr_row[:-1]
|
||||
])
|
||||
self.add(curr_row)
|
||||
self.dither()
|
||||
|
||||
self.rows = rows
|
||||
|
||||
def show_sum_of_two_over_rule(self):
|
||||
rows = self.rows
|
||||
|
||||
example = rows[5][3]
|
||||
ex_top1 = rows[4][2]
|
||||
ex_top2 = rows[4][3]
|
||||
|
||||
rects = VGroup()
|
||||
for mob, color in (example, GREEN), (ex_top1, BLUE), (ex_top2, YELLOW):
|
||||
mob.rect = SurroundingRectangle(mob, color = color)
|
||||
rects.add(mob.rect)
|
||||
|
||||
rows_to_fade = VGroup(*rows[1:4] + rows[6:])
|
||||
rows_to_fade.save_state()
|
||||
|
||||
top_row = rows[4]
|
||||
low_row = rows[5]
|
||||
top_row_copy = top_row.copy()
|
||||
top_row.save_state()
|
||||
top_row.add(ex_top2.rect)
|
||||
top_row_copy.add(ex_top1.rect)
|
||||
h_line = Line(LEFT, RIGHT)
|
||||
h_line.stretch_to_fit_width(low_row.get_width() + 2)
|
||||
h_line.next_to(low_row, UP, 1.5*SMALL_BUFF)
|
||||
plus = TexMobject("+")
|
||||
plus.next_to(h_line.get_left(), UP+RIGHT, buff = 1.5*SMALL_BUFF)
|
||||
|
||||
self.play(ShowCreation(example.rect))
|
||||
self.play(
|
||||
ReplacementTransform(example.rect.copy(), ex_top1.rect),
|
||||
ReplacementTransform(example.rect.copy(), ex_top2.rect),
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(rows_to_fade.fade, 1)
|
||||
self.play(
|
||||
top_row.align_to, low_row, LEFT,
|
||||
top_row_copy.next_to, top_row, UP,
|
||||
top_row_copy.align_to, low_row, RIGHT,
|
||||
)
|
||||
self.play(
|
||||
ShowCreation(h_line),
|
||||
Write(plus)
|
||||
)
|
||||
self.dither(2)
|
||||
for row in top_row, top_row_copy:
|
||||
row.remove(row[-1])
|
||||
self.play(
|
||||
rows_to_fade.restore,
|
||||
top_row.restore,
|
||||
Transform(
|
||||
top_row_copy, top_row.saved_state,
|
||||
remover = True
|
||||
),
|
||||
FadeOut(VGroup(h_line, plus)),
|
||||
FadeOut(rects),
|
||||
)
|
||||
self.dither()
|
||||
|
||||
def keep_in_mind_what_these_mean(self):
|
||||
morty = Mortimer().flip()
|
||||
morty.scale(0.7)
|
||||
morty.to_edge(LEFT)
|
||||
morty.shift(DOWN)
|
||||
|
||||
numbers = VGroup(*it.chain(*self.rows[1:]))
|
||||
random.shuffle(numbers.submobjects)
|
||||
|
||||
self.play(FadeIn(morty))
|
||||
self.play(PiCreatureSays(
|
||||
morty, "Keep in mind \\\\ what these mean.",
|
||||
bubble_kwargs = {
|
||||
"width" : 3.5,
|
||||
"height" : 2.5,
|
||||
}
|
||||
))
|
||||
self.play(
|
||||
Blink(morty),
|
||||
LaggedStart(
|
||||
Indicate, numbers,
|
||||
rate_func = wiggle,
|
||||
color = PINK,
|
||||
)
|
||||
)
|
||||
self.play(*map(FadeOut, [
|
||||
morty, morty.bubble, morty.bubble.content
|
||||
]))
|
||||
|
||||
def issolate_9_choose_4_term(self):
|
||||
rows = self.rows
|
||||
|
||||
for n in range(1, self.max_n+1):
|
||||
num = rows[n][0]
|
||||
line = get_stack(Female(), Male(), n, 0)[0]
|
||||
if n < self.max_n:
|
||||
line.next_to(num, LEFT)
|
||||
else:
|
||||
line.next_to(num, DOWN, MED_LARGE_BUFF)
|
||||
self.highlight_num(num)
|
||||
self.add(line)
|
||||
if n < self.max_n:
|
||||
self.dither(0.25)
|
||||
else:
|
||||
self.dither(1.25)
|
||||
self.dehighlight_num(num)
|
||||
self.remove(line)
|
||||
for k in range(1, 5):
|
||||
num = rows[self.max_n][k]
|
||||
line = get_stack(Female(), Male(), self.max_n, k)[0]
|
||||
line.next_to(num, DOWN, MED_LARGE_BUFF)
|
||||
self.highlight_num(num)
|
||||
self.add(line)
|
||||
self.dither(0.5)
|
||||
self.dehighlight_num(num)
|
||||
self.remove(line)
|
||||
num.highlight(YELLOW)
|
||||
num.scale_in_place(1.2)
|
||||
self.add(line)
|
||||
self.dither()
|
||||
|
||||
self.nine_choose_four_term = num
|
||||
self.nine_choose_four_line = line
|
||||
|
||||
def show_9_choose_4_pattern(self):
|
||||
rows = VGroup(*self.rows[1:])
|
||||
all_stacks = get_stacks(Female(), Male(), 9)
|
||||
stack = all_stacks[4]
|
||||
all_lines = VGroup(*it.chain(*all_stacks))
|
||||
|
||||
self.play(
|
||||
rows.shift, 3*UP,
|
||||
self.nine_choose_four_line.shift, 2.5*UP,
|
||||
)
|
||||
self.remove(self.nine_choose_four_line)
|
||||
|
||||
for n, line in enumerate(stack):
|
||||
line.next_to(self.nine_choose_four_term, DOWN, LARGE_BUFF)
|
||||
num = Integer(n+1)
|
||||
num.next_to(line, DOWN, MED_LARGE_BUFF)
|
||||
self.add(line, num)
|
||||
self.dither(0.1)
|
||||
self.remove(line, num)
|
||||
self.add(line, num)
|
||||
self.dither()
|
||||
self.curr_line = line
|
||||
|
||||
#Probability
|
||||
expr = TexMobject(
|
||||
"P(4", "\\female", "\\text{ out of }", "9", ")", "="
|
||||
)
|
||||
expr.move_to(num.get_left())
|
||||
expr.highlight_by_tex("female", MAROON_B)
|
||||
nine_choose_four_term = self.nine_choose_four_term.copy()
|
||||
nine_choose_four_term.generate_target()
|
||||
nine_choose_four_term.target.scale(1./1.2)
|
||||
over_512 = TexMobject("\\quad \\over 2^9")
|
||||
frac = VGroup(nine_choose_four_term.target, over_512)
|
||||
frac.arrange_submobjects(DOWN, buff = SMALL_BUFF)
|
||||
frac.next_to(expr, RIGHT, SMALL_BUFF)
|
||||
eq_result = TexMobject("\\approx 0.246")
|
||||
eq_result.next_to(frac, RIGHT)
|
||||
|
||||
def show_random_lines(n, dither_time = 1):
|
||||
for x in range(n):
|
||||
if x == n-1:
|
||||
dither_time = 0
|
||||
new_line = random.choice(all_lines)
|
||||
new_line.move_to(self.curr_line)
|
||||
self.remove(self.curr_line)
|
||||
self.curr_line = new_line
|
||||
self.add(self.curr_line)
|
||||
self.dither(dither_time)
|
||||
|
||||
self.play(FadeOut(num), FadeIn(expr))
|
||||
show_random_lines(4)
|
||||
self.play(
|
||||
MoveToTarget(nine_choose_four_term),
|
||||
Write(over_512)
|
||||
)
|
||||
show_random_lines(4)
|
||||
self.play(Write(eq_result))
|
||||
show_random_lines(6)
|
||||
self.play(
|
||||
self.nine_choose_four_term.scale_in_place, 1./1.2,
|
||||
self.nine_choose_four_term.highlight, WHITE,
|
||||
*map(FadeOut, [
|
||||
expr, nine_choose_four_term,
|
||||
over_512, eq_result, self.curr_line
|
||||
])
|
||||
)
|
||||
self.play(rows.shift, 3*DOWN)
|
||||
|
||||
def cap_off_triangle(self):
|
||||
top_row = self.rows[0]
|
||||
circle = Circle(color = YELLOW)
|
||||
circle.replace(top_row, dim_to_match = 1)
|
||||
circle.scale_in_place(1.5)
|
||||
|
||||
line_groups = VGroup()
|
||||
for n in range(4, -1, -1):
|
||||
line = VGroup(*[
|
||||
random.choice([Male, Female])()
|
||||
for k in range(n)
|
||||
])
|
||||
if n == 0:
|
||||
line.add(Line(LEFT, RIGHT).scale(0.1).set_stroke(BLACK, 0))
|
||||
line.arrange_submobjects(RIGHT, SMALL_BUFF)
|
||||
line.shift(SPACE_WIDTH*RIGHT/2 + SPACE_HEIGHT*UP/2)
|
||||
brace = Brace(line, UP)
|
||||
if n == 1:
|
||||
label = "1 Person"
|
||||
else:
|
||||
label = "%d People"%n
|
||||
brace_text = brace.get_text(label)
|
||||
line_group = VGroup(line, brace, brace_text)
|
||||
line_groups.add(line_group)
|
||||
|
||||
self.play(ShowCreation(circle))
|
||||
self.play(Write(top_row))
|
||||
self.dither()
|
||||
curr_line_group = line_groups[0]
|
||||
self.play(FadeIn(curr_line_group))
|
||||
for line_group in line_groups[1:]:
|
||||
self.play(ReplacementTransform(
|
||||
curr_line_group, line_group
|
||||
))
|
||||
curr_line_group = line_group
|
||||
self.dither()
|
||||
|
||||
###
|
||||
|
||||
def highlight_num(self, num):
|
||||
num.highlight(YELLOW)
|
||||
num.scale_in_place(1.2)
|
||||
|
||||
def dehighlight_num(self, num):
|
||||
num.highlight(WHITE)
|
||||
num.scale_in_place(1.0/1.2)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue