mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Final(?) animations for chessbaord puzzle part 1
This commit is contained in:
parent
5b1ce542d7
commit
6451371a75
1 changed files with 299 additions and 111 deletions
|
@ -1323,6 +1323,22 @@ class TwoSquareCase(ThreeDScene):
|
|||
self.wait()
|
||||
|
||||
|
||||
class IGotThis(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.student_says(
|
||||
"Pssh, I got this",
|
||||
target_mode="tease",
|
||||
look_at_arg=self.screen,
|
||||
added_anims=[self.teacher.change, "happy", self.screen],
|
||||
run_time=2,
|
||||
)
|
||||
self.change_student_modes(
|
||||
"thinking", "pondering",
|
||||
look_at_arg=self.screen
|
||||
)
|
||||
self.wait(6)
|
||||
|
||||
|
||||
class WalkingTheSquare(ThreeDScene):
|
||||
def construct(self):
|
||||
# Setup objects
|
||||
|
@ -1967,6 +1983,82 @@ class SeventyFivePercentChance(Scene):
|
|||
self.wait()
|
||||
|
||||
|
||||
class DoesFlippingAddOrSubtract(Scene):
|
||||
def construct(self):
|
||||
# Setup sum
|
||||
full_sum = Group()
|
||||
coins = Group()
|
||||
n_shown = 5
|
||||
for n in it.chain(range(n_shown), range(64 - n_shown, 64)):
|
||||
coin = Coin(numeric_labels=True)
|
||||
coin.set_height(0.7)
|
||||
coins.add(coin)
|
||||
if (random.random() < 0.5 or (n == 2)) and (n != 62):
|
||||
coin.flip()
|
||||
num = Integer(n)
|
||||
summand = Group(
|
||||
coin,
|
||||
TexMobject("\\cdot"),
|
||||
num,
|
||||
TexMobject("+"),
|
||||
)
|
||||
VGroup(*summand[1:]).set_stroke(BLACK, 3, background=True)
|
||||
summand.arrange(RIGHT, buff=MED_SMALL_BUFF)
|
||||
|
||||
full_sum.add(summand)
|
||||
|
||||
dots = TexMobject("\\dots")
|
||||
full_sum = Group(*full_sum[:n_shown], dots, *full_sum[n_shown:])
|
||||
full_sum.arrange(RIGHT, buff=MED_SMALL_BUFF)
|
||||
full_sum.set_width(FRAME_WIDTH - 1)
|
||||
full_sum[-1][-1].scale(0, about_edge=LEFT)
|
||||
full_sum.move_to(UP)
|
||||
|
||||
brace = Brace(full_sum, DOWN)
|
||||
s_label = VGroup(
|
||||
TextMobject("Sum mod 64 = "),
|
||||
Integer(53),
|
||||
)
|
||||
s_label[1].set_color(BLUE)
|
||||
s_label[1].match_height(s_label[0])
|
||||
s_label.arrange(RIGHT)
|
||||
s_label.next_to(brace, DOWN)
|
||||
|
||||
words = TextMobject("Can't know if a flip will add or subtract")
|
||||
words.to_edge(UP)
|
||||
|
||||
self.add(full_sum)
|
||||
self.add(brace)
|
||||
self.add(s_label)
|
||||
self.add(words)
|
||||
self.wait()
|
||||
|
||||
# Do some flips
|
||||
s_label[1].add_updater(lambda m: m.set_value(m.get_value() % 64))
|
||||
for x in range(10):
|
||||
n = random.randint(-n_shown, n_shown - 1)
|
||||
coin = coins[n]
|
||||
n = n % 64
|
||||
diff_label = Integer(n, include_sign=True)
|
||||
if not coin.is_heads():
|
||||
diff_label.set_color(GREEN)
|
||||
else:
|
||||
diff_label.set_color(RED)
|
||||
diff_label.set_value(-diff_label.get_value())
|
||||
diff_label.next_to(coin, UP, aligned_edge=LEFT)
|
||||
self.play(
|
||||
ChangeDecimalToValue(
|
||||
s_label[1],
|
||||
s_label[1].get_value() + n,
|
||||
rate_func=squish_rate_func(smooth, 0.5, 1)
|
||||
),
|
||||
FlipCoin(coin),
|
||||
FadeIn(diff_label, 0.5 * DOWN)
|
||||
)
|
||||
self.play(FadeOut(diff_label))
|
||||
self.wait()
|
||||
|
||||
|
||||
class ShowCube(ThreeDScene):
|
||||
def construct(self):
|
||||
# Camera stuffs
|
||||
|
@ -2154,34 +2246,99 @@ class ShowCube(ThreeDScene):
|
|||
)
|
||||
|
||||
colors = [RED, GREEN, BLUE_D]
|
||||
color_chars = ["R", "G", "B"]
|
||||
color_labels = VGroup()
|
||||
anims = []
|
||||
for sphere, cl, coords in zip(spheres, coord_labels, vert_coords):
|
||||
index = np.dot(coords, [0, 1, 2]) % 3
|
||||
color = colors[index]
|
||||
color_label = TexMobject(color_chars[index])
|
||||
color_label.rotate(PI / 2, RIGHT)
|
||||
color_label.set_color(color)
|
||||
color_label.next_to(cl, RIGHT, SMALL_BUFF)
|
||||
color_label.match_depth(cl)
|
||||
anims.append(AnimationGroup(
|
||||
ApplyMethod(sphere.set_color, color),
|
||||
ApplyMethod(cl.set_color, color),
|
||||
FadeIn(color_label, LEFT)
|
||||
))
|
||||
color_labels.add(color_label)
|
||||
self.play(LaggedStart(*anims, run_time=6, lag_ratio=0.3))
|
||||
self.wait(7)
|
||||
self.play(FadeOut(color_labels))
|
||||
title = TextMobject("Strategy", "\\, $\\Leftrightarrow$ \\,", "Coloring")
|
||||
title[2].set_submobject_colors_by_gradient(*colors)
|
||||
title.set_stroke(BLACK, 5, background=True)
|
||||
title.set_height(0.7)
|
||||
title.to_edge(UP)
|
||||
title.shift(LEFT)
|
||||
title.fix_in_frame()
|
||||
|
||||
color_label_templates = [
|
||||
TexMobject(char, color=color).rotate(PI / 2, RIGHT).match_depth(coord_labels[0])
|
||||
for char, color in zip("RGB", colors)
|
||||
]
|
||||
coord_labels.color_labels = VGroup(*[VMobject() for cl in coord_labels])
|
||||
|
||||
def get_coloring_animation(ns,
|
||||
spheres=spheres,
|
||||
coord_labels=coord_labels,
|
||||
colors=colors,
|
||||
color_label_templates=color_label_templates,
|
||||
):
|
||||
anims = []
|
||||
new_color_labels = VGroup()
|
||||
for n, sphere, coord_label, old_color_label in zip(ns, spheres, coord_labels, coord_labels.color_labels):
|
||||
color = colors[int(n)]
|
||||
sphere.generate_target()
|
||||
coord_label.generate_target()
|
||||
sphere.target.set_color(color)
|
||||
coord_label.target.set_fill(color)
|
||||
color_label = color_label_templates[n].copy()
|
||||
color_label.next_to(coord_label, RIGHT, SMALL_BUFF)
|
||||
anims += [
|
||||
MoveToTarget(sphere),
|
||||
MoveToTarget(coord_label),
|
||||
FadeIn(color_label, 0.25 * IN),
|
||||
FadeOut(old_color_label, 0.25 * OUT),
|
||||
]
|
||||
new_color_labels.add(color_label)
|
||||
coord_labels.color_labels = new_color_labels
|
||||
return LaggedStart(*anims, run_time=2)
|
||||
|
||||
self.play(
|
||||
FadeIn(title, DOWN),
|
||||
get_coloring_animation(np.random.randint(0, 3, 8)),
|
||||
)
|
||||
self.wait()
|
||||
for x in range(4):
|
||||
self.play(get_coloring_animation(np.random.randint(0, 3, 8)))
|
||||
self.wait()
|
||||
|
||||
# Some specific color examples
|
||||
S0 = TexMobject("S = 0")
|
||||
S0.to_edge(LEFT)
|
||||
S0.shift(UP)
|
||||
S0.fix_in_frame()
|
||||
self.play(
|
||||
FadeIn(S0, DOWN),
|
||||
get_coloring_animation([0] * 8)
|
||||
)
|
||||
self.wait(5)
|
||||
|
||||
bit_sum = TexMobject("S = \\,&(c_0 + c_1 + c_2) \\\\ &\\quad \\mod 3")
|
||||
bit_sum.scale(0.8)
|
||||
bit_sum.to_edge(LEFT)
|
||||
bit_sum.shift(UP)
|
||||
bit_sum.fix_in_frame()
|
||||
self.play(
|
||||
FadeIn(bit_sum, DOWN),
|
||||
FadeOut(S0, UP),
|
||||
get_coloring_animation([sum(coords) % 3 for coords in vert_coords])
|
||||
)
|
||||
self.wait(6)
|
||||
|
||||
bit_sum_with_coefs = TexMobject(
|
||||
"S = \\,&(0\\cdot c_0 + 1\\cdot c_1 + 2\\cdot c_2) \\\\ &\\quad \\mod 3"
|
||||
)
|
||||
bit_sum_with_coefs.scale(0.8)
|
||||
bit_sum_with_coefs.move_to(bit_sum, LEFT)
|
||||
bit_sum_with_coefs.fix_in_frame()
|
||||
self.play(
|
||||
FadeIn(bit_sum_with_coefs, DOWN),
|
||||
FadeOut(bit_sum, UP),
|
||||
get_coloring_animation([np.dot(coords, [0, 1, 2]) % 3 for coords in vert_coords])
|
||||
)
|
||||
self.wait(4)
|
||||
|
||||
# Focus on (0, 0, 0)
|
||||
self.play(
|
||||
LaggedStartMap(FlipCoin, coins),
|
||||
FlipCoin(coins),
|
||||
coord_labels[1:].set_opacity, 0.2,
|
||||
coord_labels.color_labels[1:].set_opacity, 0.2,
|
||||
spheres[1:].set_opacity, 0.2,
|
||||
)
|
||||
self.wait(6)
|
||||
self.wait(2)
|
||||
|
||||
lines = VGroup()
|
||||
for n in [1, 2, 4]:
|
||||
|
@ -2192,11 +2349,9 @@ class ShowCube(ThreeDScene):
|
|||
ShowCreationThenDestruction(line),
|
||||
spheres[n].set_opacity, 1,
|
||||
coord_labels[n].set_opacity, 1,
|
||||
spheres[0].set_opacity, 0.2,
|
||||
coord_labels[0].set_opacity, 0.2,
|
||||
coord_labels.color_labels[n].set_opacity, 1,
|
||||
FlipCoin(coin)
|
||||
)
|
||||
self.wait()
|
||||
line.reverse_points()
|
||||
self.add(line, coord_labels)
|
||||
self.play(
|
||||
|
@ -2204,7 +2359,7 @@ class ShowCube(ThreeDScene):
|
|||
ShowCreation(line)
|
||||
)
|
||||
lines.add(line)
|
||||
self.wait(15)
|
||||
self.wait(10)
|
||||
|
||||
# Focus on (0, 1, 0)
|
||||
self.play(
|
||||
|
@ -2212,11 +2367,12 @@ class ShowCube(ThreeDScene):
|
|||
Uncreate(lines[1]),
|
||||
FadeOut(lines[::2]),
|
||||
Group(
|
||||
spheres[1], coord_labels[1],
|
||||
spheres[4], coord_labels[4],
|
||||
spheres[0], coord_labels[0], coord_labels.color_labels[0],
|
||||
spheres[1], coord_labels[1], coord_labels.color_labels[1],
|
||||
spheres[4], coord_labels[4], coord_labels.color_labels[4],
|
||||
).set_opacity, 0.2,
|
||||
)
|
||||
self.wait(6)
|
||||
self.wait(3)
|
||||
|
||||
lines = VGroup()
|
||||
curr_n = 2
|
||||
|
@ -2229,11 +2385,9 @@ class ShowCube(ThreeDScene):
|
|||
ShowCreationThenDestruction(line),
|
||||
spheres[new_n].set_opacity, 1,
|
||||
coord_labels[new_n].set_opacity, 1,
|
||||
# spheres[curr_n].set_opacity, 0.2,
|
||||
# coord_labels[curr_n].set_opacity, 0.2,
|
||||
coord_labels.color_labels[new_n].set_opacity, 1,
|
||||
FlipCoin(coin)
|
||||
)
|
||||
self.wait()
|
||||
line.reverse_points()
|
||||
self.add(line, coord_labels)
|
||||
self.play(
|
||||
|
@ -2242,66 +2396,17 @@ class ShowCube(ThreeDScene):
|
|||
)
|
||||
lines.add(line)
|
||||
self.wait(10)
|
||||
|
||||
# Show a few more colorings
|
||||
self.play(
|
||||
LaggedStartMap(Uncreate, lines),
|
||||
spheres.set_opacity, 1,
|
||||
coord_labels.set_opacity, 1,
|
||||
coord_labels.color_labels.set_opacity, 1,
|
||||
FadeOut(bit_sum_with_coefs),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
title = TextMobject("Strategy", "\\, $\\Leftrightarrow$ \\,", "Coloring")
|
||||
title[2].set_submobject_colors_by_gradient(*colors)
|
||||
title.set_stroke(BLACK, 5, background=True)
|
||||
title.set_height(0.7)
|
||||
title.to_edge(UP)
|
||||
title.shift(LEFT)
|
||||
title.fix_in_frame()
|
||||
|
||||
def get_coloring_animation(ns, spheres=spheres, coord_labels=coord_labels, colors=colors):
|
||||
anims = []
|
||||
for n, sphere, cl in zip(ns, spheres, coord_labels):
|
||||
color = colors[int(n)]
|
||||
sphere.generate_target()
|
||||
cl.generate_target()
|
||||
sphere.target.set_color(color)
|
||||
cl.target.set_fill(color)
|
||||
anims += [MoveToTarget(sphere), MoveToTarget(cl)]
|
||||
return LaggedStart(*anims, run_time=1)
|
||||
|
||||
self.play(FadeIn(title, DOWN))
|
||||
for x in range(8):
|
||||
self.play(get_coloring_animation(np.random.randint(0, 3, 8)))
|
||||
self.wait()
|
||||
|
||||
S0 = TexMobject("S = 0")
|
||||
S0.to_edge(LEFT)
|
||||
S0.shift(UP)
|
||||
S0.fix_in_frame()
|
||||
self.play(
|
||||
FadeIn(S0, DOWN),
|
||||
get_coloring_animation([0] * 8)
|
||||
)
|
||||
self.wait(5)
|
||||
|
||||
bit_sum = TexMobject("S = &(c_0 + c_1 + c_2) \\\\ &\\quad \\mod 3")
|
||||
bit_sum.to_edge(LEFT)
|
||||
bit_sum.shift(UP)
|
||||
bit_sum.fix_in_frame()
|
||||
self.play(
|
||||
FadeIn(bit_sum, DOWN),
|
||||
FadeOut(S0, UP),
|
||||
get_coloring_animation([sum(coords) % 3 for coords in vert_coords])
|
||||
)
|
||||
self.wait(6)
|
||||
self.play(
|
||||
FadeOut(bit_sum, UP),
|
||||
get_coloring_animation([
|
||||
sum([n * c for n, c in enumerate(coords)]) % 3
|
||||
for coords in vert_coords
|
||||
])
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Count all strategies
|
||||
count = TextMobject("$3^8$ total strategies")
|
||||
|
@ -2320,7 +2425,7 @@ class ShowCube(ThreeDScene):
|
|||
full_coins.flip_by_message("64^ 2^64")
|
||||
|
||||
self.play(FadeIn(count, DOWN))
|
||||
self.wait(15)
|
||||
self.wait(4)
|
||||
self.remove(board, coins)
|
||||
frame.clear_updaters()
|
||||
frame.generate_target()
|
||||
|
@ -2356,7 +2461,7 @@ class ShowCube(ThreeDScene):
|
|||
frame.generate_target()
|
||||
frame.target.shift(2 * DOWN)
|
||||
frame.target.set_rotation(-15 * DEGREES, 70 * DEGREES)
|
||||
self.add(full_coins)
|
||||
full_coins.unlock_shader_data()
|
||||
self.play(
|
||||
MoveToTarget(frame, run_time=3),
|
||||
LaggedStartMap(FadeOut, full_board),
|
||||
|
@ -2364,12 +2469,15 @@ class ShowCube(ThreeDScene):
|
|||
FadeOut(count),
|
||||
FadeOut(count64),
|
||||
)
|
||||
self.play(FadeIn(color_labels))
|
||||
frame.add_updater(lambda m, dt: m.increment_theta(0.01 * dt))
|
||||
self.wait(30)
|
||||
|
||||
|
||||
class CubeSupplement(ThreeDScene):
|
||||
CONFIG = {
|
||||
"try_different_strategies": False,
|
||||
}
|
||||
|
||||
def construct(self):
|
||||
# Map 8 states to square choices
|
||||
boards = Group(*[Chessboard(shape=(1, 3)) for x in range(8)])
|
||||
|
@ -2385,49 +2493,72 @@ class CubeSupplement(ThreeDScene):
|
|||
for coords, coins in zip(vert_coords, coin_sets):
|
||||
coins.flip_by_bools(coords)
|
||||
|
||||
def get_choice_boards(values, boards):
|
||||
choices = VGroup()
|
||||
for value, board in zip(values, boards):
|
||||
choice = VGroup(*[Square() for x in range(3)])
|
||||
choice.arrange(RIGHT, buff=0)
|
||||
choice.match_height(board)
|
||||
choice.next_to(board, RIGHT, buff=1.25)
|
||||
choice.set_fill(GREY_D, 1)
|
||||
choice.set_stroke(WHITE, 1)
|
||||
choice[value].set_fill(TEAL)
|
||||
choices.add(choice)
|
||||
return choices
|
||||
|
||||
colors = [RED, GREEN, BLUE_D]
|
||||
color_words = ["Red", "Green", "Blue"]
|
||||
s_values = [sum([n * v for n, v in enumerate(cs)]) % 3 for cs in vert_coords]
|
||||
s_labels = VGroup()
|
||||
choice_boards = get_choice_boards(s_values, boards)
|
||||
c_labels = VGroup()
|
||||
s_arrows = VGroup()
|
||||
for value, board in zip(s_values, boards):
|
||||
for value, board, choice_board in zip(s_values, boards, choice_boards):
|
||||
arrow = Vector(RIGHT)
|
||||
arrow.next_to(board, RIGHT, SMALL_BUFF)
|
||||
|
||||
label = VGroup(*[Square() for x in range(3)])
|
||||
label.arrange(RIGHT, buff=0)
|
||||
label.match_height(board)
|
||||
label.next_to(arrow, RIGHT, MED_SMALL_BUFF)
|
||||
label.set_fill(GREY_D, 1)
|
||||
label.set_stroke(WHITE, 1)
|
||||
label[value].set_fill(TEAL)
|
||||
label.generate_target()
|
||||
label.target[value].set_fill(colors[value])
|
||||
|
||||
c_label = TextMobject(color_words[value], color=colors[value])
|
||||
c_label.next_to(label, RIGHT)
|
||||
|
||||
s_labels.add(label)
|
||||
c_label.next_to(choice_board, RIGHT)
|
||||
c_labels.add(c_label)
|
||||
s_arrows.add(arrow)
|
||||
|
||||
choice_board.generate_target()
|
||||
choice_board.target[value].set_fill(colors[value])
|
||||
|
||||
self.play(
|
||||
LaggedStartMap(FadeIn, boards, lag_ratio=0.25),
|
||||
LaggedStartMap(FadeIn, coin_sets, lag_ratio=0.25),
|
||||
)
|
||||
self.play(
|
||||
LaggedStartMap(GrowArrow, s_arrows, lag_ratio=0.25),
|
||||
LaggedStartMap(FadeIn, s_labels, lambda m: (m, LEFT), lag_ratio=0.25),
|
||||
LaggedStartMap(FadeIn, choice_boards, lambda m: (m, LEFT), lag_ratio=0.25),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Associate choices with colors
|
||||
self.play(
|
||||
LaggedStartMap(MoveToTarget, s_labels),
|
||||
LaggedStartMap(FadeIn, c_labels),
|
||||
)
|
||||
self.wait()
|
||||
# Fork
|
||||
if self.try_different_strategies:
|
||||
for x in range(5):
|
||||
values = list(np.arange(8) % 3)
|
||||
random.shuffle(values)
|
||||
new_cboards = get_choice_boards(values, boards)
|
||||
self.play(
|
||||
LaggedStartMap(FadeOut, choice_boards, lambda m: (m, 0.25 * UP)),
|
||||
LaggedStartMap(FadeIn, new_cboards, lambda m: (m, 0.25 * DOWN)),
|
||||
)
|
||||
choice_boards = new_cboards
|
||||
self.wait(2)
|
||||
|
||||
else:
|
||||
# Associate choices with colors
|
||||
self.play(
|
||||
LaggedStartMap(MoveToTarget, choice_boards),
|
||||
LaggedStartMap(FadeIn, c_labels),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class TryDifferentCaseThreeStrategies(CubeSupplement):
|
||||
CONFIG = {
|
||||
"try_different_strategies": True,
|
||||
}
|
||||
|
||||
|
||||
class CubeEdgeDescription(Scene):
|
||||
|
@ -3429,6 +3560,61 @@ class SimpleRect(Scene):
|
|||
self.play(FadeOut(rect))
|
||||
|
||||
|
||||
class WhenIsItHopeless(Scene):
|
||||
def construct(self):
|
||||
boards = Group(
|
||||
Chessboard(shape=(1, 3)),
|
||||
Chessboard(shape=(2, 2)),
|
||||
Chessboard(shape=(2, 3)),
|
||||
Chessboard(shape=(2, 3)),
|
||||
Chessboard(shape=(2, 4)),
|
||||
Chessboard(shape=(2, 4)),
|
||||
Chessboard(shape=(3, 3)),
|
||||
Chessboard(shape=(3, 4)),
|
||||
Chessboard(shape=(3, 4)),
|
||||
Chessboard(shape=(3, 4)),
|
||||
)
|
||||
last_board = None
|
||||
last_coins = None
|
||||
last_words = None
|
||||
for n, board in zip(it.count(3), boards):
|
||||
board.scale(1 / board[0].get_height())
|
||||
coins = CoinsOnBoard(board)
|
||||
coins.flip_at_random()
|
||||
diff = len(board) - n
|
||||
if diff > 0:
|
||||
board[-diff:].set_opacity(0)
|
||||
coins[-diff:].set_opacity(0)
|
||||
|
||||
if sum(int_to_bit_coords(n)) == 1:
|
||||
words = TextMobject("Maybe possible")
|
||||
words.set_color(GREEN)
|
||||
else:
|
||||
words = TextMobject("Futile!")
|
||||
words.set_color(RED)
|
||||
words.scale(1.5)
|
||||
words.next_to(board, UP, MED_LARGE_BUFF)
|
||||
|
||||
if n == 3:
|
||||
self.play(
|
||||
FadeIn(board),
|
||||
FadeIn(coins),
|
||||
FadeIn(words, DOWN),
|
||||
)
|
||||
else:
|
||||
self.play(
|
||||
ReplacementTransform(last_board, board),
|
||||
ReplacementTransform(last_coins, coins),
|
||||
FadeOut(last_words),
|
||||
FadeIn(words, DOWN),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
last_board = board
|
||||
last_coins = coins
|
||||
last_words = words
|
||||
|
||||
|
||||
class FourDCubeColoringFromTrees(ThreeDScene):
|
||||
def construct(self):
|
||||
# Camera stuffs
|
||||
|
@ -3677,7 +3863,9 @@ class IntroduceHypercube(FourDCubeColoringFromTrees):
|
|||
self.wait(15)
|
||||
|
||||
|
||||
# TODO, have this read names in from a file
|
||||
# Animations for Matt
|
||||
|
||||
|
||||
class ChessEndScreen(PatreonEndScreen):
|
||||
CONFIG = {
|
||||
"scroll_time": 20,
|
||||
|
|
Loading…
Add table
Reference in a new issue