mirror of
https://github.com/3b1b/manim.git
synced 2025-04-13 09:47:07 +00:00
Finished Hanoi project
This commit is contained in:
parent
941db9e07a
commit
951a681997
3 changed files with 211 additions and 28 deletions
|
@ -57,6 +57,9 @@ class Camera(object):
|
||||||
def set_image(self, pixel_array):
|
def set_image(self, pixel_array):
|
||||||
self.pixel_array = np.array(pixel_array)
|
self.pixel_array = np.array(pixel_array)
|
||||||
|
|
||||||
|
def set_background(self, pixel_array):
|
||||||
|
self.background = np.array(pixel_array)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.set_image(np.array(self.background))
|
self.set_image(np.array(self.background))
|
||||||
|
|
||||||
|
|
234
hanoi.py
234
hanoi.py
|
@ -577,6 +577,25 @@ class IntroduceKeith(Scene):
|
||||||
)
|
)
|
||||||
self.play(Blink(keith))
|
self.play(Blink(keith))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
original_content = bubble.content
|
||||||
|
bubble.write("I'm usually meh \\\\ on puzzles")
|
||||||
|
self.play(
|
||||||
|
keith.change_mode, "hesitant",
|
||||||
|
Transform(original_content, bubble.content),
|
||||||
|
)
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "happy",
|
||||||
|
morty.look_at, keith.eyes
|
||||||
|
)
|
||||||
|
self.play(Blink(keith))
|
||||||
|
bubble.write("But \\emph{analyzing} puzzles!")
|
||||||
|
VGroup(*bubble.content[3:12]).highlight(YELLOW)
|
||||||
|
self.play(
|
||||||
|
keith.change_mode, "hooray",
|
||||||
|
Transform(original_content, bubble.content)
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither()
|
||||||
self.play(FadeIn(randy))
|
self.play(FadeIn(randy))
|
||||||
self.play(
|
self.play(
|
||||||
randy.change_mode, "confused",
|
randy.change_mode, "confused",
|
||||||
|
@ -586,7 +605,7 @@ class IntroduceKeith(Scene):
|
||||||
morty.change_mode, "plain",
|
morty.change_mode, "plain",
|
||||||
morty.look_at, randy.eyes,
|
morty.look_at, randy.eyes,
|
||||||
FadeOut(bubble),
|
FadeOut(bubble),
|
||||||
FadeOut(bubble.content),
|
FadeOut(original_content),
|
||||||
ShowCreation(randy.bubble),
|
ShowCreation(randy.bubble),
|
||||||
Write(randy.bubble.content)
|
Write(randy.bubble.content)
|
||||||
)
|
)
|
||||||
|
@ -1675,6 +1694,28 @@ class RecursiveSolution(TowersOfHanoiScene):
|
||||||
def change_mode(self, mode):
|
def change_mode(self, mode):
|
||||||
self.play(self.eyes.change_mode_anim(mode))
|
self.play(self.eyes.change_mode_anim(mode))
|
||||||
|
|
||||||
|
class KeithSaysBigToSmall(Scene):
|
||||||
|
def construct(self):
|
||||||
|
keith = Keith()
|
||||||
|
keith.shift(2.5*DOWN + 3*LEFT)
|
||||||
|
bubble = keith.get_bubble("speech", height = 4.5)
|
||||||
|
bubble.write("""
|
||||||
|
Big problem
|
||||||
|
$\\Downarrow$
|
||||||
|
Smaller problem
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.add(keith)
|
||||||
|
self.play(Blink(keith))
|
||||||
|
self.play(
|
||||||
|
keith.change_mode, "speaking",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content)
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(Blink(keith))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
class CodeThisUp(Scene):
|
class CodeThisUp(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
keith = Keith()
|
keith = Keith()
|
||||||
|
@ -1721,6 +1762,23 @@ class HanoiSolutionCode(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class NoRoomForInefficiency(Scene):
|
||||||
|
def construct(self):
|
||||||
|
morty = Mortimer().flip()
|
||||||
|
morty.shift(2.5*DOWN+3*LEFT)
|
||||||
|
bubble = morty.get_bubble("speech", width = 4)
|
||||||
|
bubble.write("No room for \\\\ inefficiency")
|
||||||
|
VGroup(morty, bubble, bubble.content).to_corner(DOWN+RIGHT)
|
||||||
|
|
||||||
|
self.add(morty)
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "speaking",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content)
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
class WhyDoesBinaryAchieveThis(Scene):
|
class WhyDoesBinaryAchieveThis(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
keith = Keith()
|
keith = Keith()
|
||||||
|
@ -1746,6 +1804,22 @@ class WhyDoesBinaryAchieveThis(Scene):
|
||||||
self.play(Blink(morty))
|
self.play(Blink(morty))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class BothAreSelfSimilar(Scene):
|
||||||
|
def construct(self):
|
||||||
|
morty = Mortimer().flip()
|
||||||
|
morty.shift(2.5*DOWN+3*LEFT)
|
||||||
|
bubble = morty.get_bubble("speech")
|
||||||
|
bubble.write("Both are self-similar")
|
||||||
|
|
||||||
|
self.add(morty)
|
||||||
|
self.play(
|
||||||
|
morty.change_mode, "hooray",
|
||||||
|
ShowCreation(bubble),
|
||||||
|
Write(bubble.content)
|
||||||
|
)
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
class LargeScaleHanoiDecomposition(TowersOfHanoiScene):
|
class LargeScaleHanoiDecomposition(TowersOfHanoiScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_disks" : 8,
|
"num_disks" : 8,
|
||||||
|
@ -1834,7 +1908,19 @@ class ShowFourDiskFourBitsParallel(IntroduceSolveByCounting):
|
||||||
self.curr_bit_mob, self.bit_mobs_iter.next(),
|
self.curr_bit_mob, self.bit_mobs_iter.next(),
|
||||||
path_arc = -np.pi/3,
|
path_arc = -np.pi/3,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class ShowThreeDiskThreeBitsParallel(ShowFourDiskFourBitsParallel):
|
||||||
|
CONFIG = {
|
||||||
|
"num_disks" : 3,
|
||||||
|
"subtask_run_time" : 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class ShowFiveDiskFiveBitsParallel(ShowFourDiskFourBitsParallel):
|
||||||
|
CONFIG = {
|
||||||
|
"num_disks" : 5,
|
||||||
|
"subtask_run_time" : 2
|
||||||
|
}
|
||||||
|
|
||||||
class ShowSixDiskSixBitsParallel(ShowFourDiskFourBitsParallel):
|
class ShowSixDiskSixBitsParallel(ShowFourDiskFourBitsParallel):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"num_disks" : 6,
|
"num_disks" : 6,
|
||||||
|
@ -3032,7 +3118,8 @@ class DescribeTriforcePattern(SierpinskiGraphScene):
|
||||||
"index_pairs" : [(7, 1), (2, 3), (5, 6)],
|
"index_pairs" : [(7, 1), (2, 3), (5, 6)],
|
||||||
"scale" : 2,
|
"scale" : 2,
|
||||||
"disk_color" : MAROON_B,
|
"disk_color" : MAROON_B,
|
||||||
# "include_towers" : False,
|
"include_towers" : True,
|
||||||
|
"first_connect_0_and_2_islands" : True, #Dumb that I have to do this
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
index_pair = self.index_pairs[0]
|
index_pair = self.index_pairs[0]
|
||||||
|
@ -3064,31 +3151,47 @@ class DescribeTriforcePattern(SierpinskiGraphScene):
|
||||||
self.play(*map(ShowCreation, bold_edges[1:]))
|
self.play(*map(ShowCreation, bold_edges[1:]))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
nodes = self.nodes[:3**self.scale]
|
power_of_three = 3**(self.scale-1)
|
||||||
circles = VGroup(*[node.circle for node in nodes])
|
index_sets = [
|
||||||
towers = VGroup(*[node.towers for node in nodes])
|
range(0, power_of_three),
|
||||||
circles.save_state()
|
range(power_of_three, 2*power_of_three),
|
||||||
self.play(
|
range(2*power_of_three, 3*power_of_three),
|
||||||
circles.set_stroke, self.disk_color,
|
]
|
||||||
Animation(towers),
|
if self.first_connect_0_and_2_islands:
|
||||||
submobject_mode = "lagged_start",
|
index_sets = [index_sets[0], index_sets[2], index_sets[1]]
|
||||||
run_time = 3
|
islands = [
|
||||||
)
|
VGroup(*[self.nodes[i] for i in index_set])
|
||||||
|
for index_set in index_sets
|
||||||
|
]
|
||||||
|
def wiggle_island(island):
|
||||||
|
return ApplyMethod(
|
||||||
|
island.rotate_in_place, np.pi/12,
|
||||||
|
run_time = 1,
|
||||||
|
rate_func = wiggle
|
||||||
|
)
|
||||||
|
self.play(*map(wiggle_island, islands[:2]))
|
||||||
self.dither()
|
self.dither()
|
||||||
self.play(
|
self.play(wiggle_island(islands[2]))
|
||||||
circles.restore,
|
|
||||||
Animation(towers),
|
|
||||||
submobject_mode = "lagged_start",
|
|
||||||
)
|
|
||||||
self.dither()
|
self.dither()
|
||||||
for pair in self.index_pairs:
|
for index_set in index_sets:
|
||||||
self.zoom_into_nodes(pair)
|
self.zoom_into_nodes(index_set)
|
||||||
|
self.zoom_into_nodes(list(it.chain(*index_sets)))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class TriforcePatternWord(Scene):
|
||||||
|
def construct(self):
|
||||||
|
word = TextMobject("Triforce \\\\ pattern")
|
||||||
|
word.scale(2)
|
||||||
|
word.to_corner(DOWN+RIGHT)
|
||||||
|
self.play(Write(word))
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
class DescribeOrderTwoPattern(DescribeTriforcePattern):
|
class DescribeOrderTwoPattern(DescribeTriforcePattern):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"index_pairs" : [(8, 9), (17, 18), (4, 22)],
|
"index_pairs" : [(8, 9), (17, 18), (4, 22)],
|
||||||
"scale" : 3,
|
"scale" : 3,
|
||||||
"disk_color" : RED,
|
"disk_color" : RED,
|
||||||
|
"first_connect_0_and_2_islands" : False,
|
||||||
}
|
}
|
||||||
|
|
||||||
class BiggerTowers(SierpinskiGraphScene):
|
class BiggerTowers(SierpinskiGraphScene):
|
||||||
|
@ -3198,12 +3301,39 @@ class PatreonThanks(Scene):
|
||||||
self.play(morty.look_at, patrons[index])
|
self.play(morty.look_at, patrons[index])
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
|
class MortyLookingAtRectangle(Scene):
|
||||||
|
def construct(self):
|
||||||
|
morty = Mortimer()
|
||||||
|
morty.to_corner(DOWN+RIGHT)
|
||||||
|
url = TextMobject("www.desmos.com/careers")
|
||||||
|
url.to_corner(UP+LEFT)
|
||||||
|
rect = Rectangle(height = 9, width = 16)
|
||||||
|
rect.scale_to_fit_height(5)
|
||||||
|
rect.next_to(url, DOWN)
|
||||||
|
rect.shift_onto_screen()
|
||||||
|
url.save_state()
|
||||||
|
url.next_to(morty.get_corner(UP+LEFT), UP)
|
||||||
|
|
||||||
|
self.play(morty.change_mode, "raise_right_hand")
|
||||||
|
self.play(Write(url))
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
url.restore,
|
||||||
|
morty.change_mode, "happy"
|
||||||
|
)
|
||||||
|
self.play(ShowCreation(rect))
|
||||||
|
self.dither()
|
||||||
|
self.play(Blink(morty))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"sierpinski_graph_scene_config" :{
|
"sierpinski_graph_scene_config" :{
|
||||||
"include_towers" : False
|
"include_towers" : False
|
||||||
},
|
},
|
||||||
"max_order" : 8,
|
"min_order" : 2,
|
||||||
|
"max_order" : 7,
|
||||||
"path_stroke_width" : 7,
|
"path_stroke_width" : 7,
|
||||||
}
|
}
|
||||||
def construct(self):
|
def construct(self):
|
||||||
|
@ -3212,7 +3342,7 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
||||||
num_disks = order,
|
num_disks = order,
|
||||||
**self.sierpinski_graph_scene_config
|
**self.sierpinski_graph_scene_config
|
||||||
)
|
)
|
||||||
for order in range(2, self.max_order+1)
|
for order in range(self.min_order, self.max_order+1)
|
||||||
]
|
]
|
||||||
paths = [self.get_path(scene) for scene in graph_scenes]
|
paths = [self.get_path(scene) for scene in graph_scenes]
|
||||||
graphs = []
|
graphs = []
|
||||||
|
@ -3225,7 +3355,8 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
||||||
|
|
||||||
self.add(graph)
|
self.add(graph)
|
||||||
self.dither()
|
self.dither()
|
||||||
self.play(ShowCreation(path, run_time = 2))
|
self.play(ShowCreation(path, run_time = 3, rate_func = None))
|
||||||
|
self.dither()
|
||||||
self.play(graph.fade, 0.5, Animation(path))
|
self.play(graph.fade, 0.5, Animation(path))
|
||||||
for other_graph in graphs[1:]:
|
for other_graph in graphs[1:]:
|
||||||
other_graph.fade(0.5)
|
other_graph.fade(0.5)
|
||||||
|
@ -3237,7 +3368,7 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
||||||
run_time = 2
|
run_time = 2
|
||||||
)
|
)
|
||||||
self.dither()
|
self.dither()
|
||||||
|
self.path = path
|
||||||
|
|
||||||
def get_path(self, graph_scene):
|
def get_path(self, graph_scene):
|
||||||
path = VGroup()
|
path = VGroup()
|
||||||
|
@ -3254,11 +3385,60 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
||||||
graph_scene.start_color,
|
graph_scene.start_color,
|
||||||
graph_scene.end_color,
|
graph_scene.end_color,
|
||||||
)
|
)
|
||||||
path.set_stroke(width = self.path_stroke_width)
|
path.set_stroke(
|
||||||
|
width = self.path_stroke_width - graph_scene.num_disks/2
|
||||||
|
)
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
class Part1Thumbnail(Scene):
|
||||||
|
CONFIG = {
|
||||||
|
"part_number" : 1,
|
||||||
|
"sierpinski_order" : 5
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
toh_scene = TowersOfHanoiScene(
|
||||||
|
peg_spacing = 2,
|
||||||
|
part_number = 1,
|
||||||
|
)
|
||||||
|
toh_scene.remove(toh_scene.peg_labels)
|
||||||
|
toh_scene.pegs[2].set_fill(opacity = 0.5)
|
||||||
|
toh = VGroup(*toh_scene.get_mobjects())
|
||||||
|
toh.scale(2)
|
||||||
|
toh.to_edge(DOWN)
|
||||||
|
self.add(toh)
|
||||||
|
|
||||||
|
sierpinski_scene = ShowSierpinskiCurvesOfIncreasingOrder(
|
||||||
|
min_order = self.sierpinski_order,
|
||||||
|
max_order = self.sierpinski_order,
|
||||||
|
skip_animations = True,
|
||||||
|
)
|
||||||
|
sierpinski_scene.path.set_stroke(width = 10)
|
||||||
|
sierpinski = VGroup(*sierpinski_scene.get_mobjects())
|
||||||
|
sierpinski.scale(0.9)
|
||||||
|
sierpinski.to_corner(DOWN+RIGHT)
|
||||||
|
self.add(sierpinski)
|
||||||
|
|
||||||
|
binary = TexMobject("01011")
|
||||||
|
binary.highlight_by_tex("0", GREEN)
|
||||||
|
binary.highlight_by_tex("1", BLUE)
|
||||||
|
binary.gradient_highlight(GREEN, RED)
|
||||||
|
binary.add_background_rectangle()
|
||||||
|
binary.background_rectangle.set_fill(opacity = 0.5)
|
||||||
|
# binary.set_fill(opacity = 0.5)
|
||||||
|
binary.scale(4)
|
||||||
|
binary.to_corner(UP+LEFT)
|
||||||
|
self.add(binary)
|
||||||
|
|
||||||
|
part = TextMobject("Part %d"%self.part_number)
|
||||||
|
part.scale(4)
|
||||||
|
part.to_corner(UP+RIGHT)
|
||||||
|
part.add_background_rectangle()
|
||||||
|
self.add(part)
|
||||||
|
|
||||||
|
class Part2Thumbnail(Part1Thumbnail):
|
||||||
|
CONFIG = {
|
||||||
|
"part_number" : 2
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,7 @@ class Scene(object):
|
||||||
return self.camera.get_image()
|
return self.camera.get_image()
|
||||||
|
|
||||||
def set_camera_background(self, background):
|
def set_camera_background(self, background):
|
||||||
self.camera.set_image(background)
|
self.camera.set_background(background)
|
||||||
|
|
||||||
def reset_camera(self):
|
def reset_camera(self):
|
||||||
self.camera.reset()
|
self.camera.reset()
|
||||||
|
|
Loading…
Add table
Reference in a new issue