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):
|
||||
self.pixel_array = np.array(pixel_array)
|
||||
|
||||
def set_background(self, pixel_array):
|
||||
self.background = np.array(pixel_array)
|
||||
|
||||
def reset(self):
|
||||
self.set_image(np.array(self.background))
|
||||
|
||||
|
|
232
hanoi.py
232
hanoi.py
|
@ -577,6 +577,25 @@ class IntroduceKeith(Scene):
|
|||
)
|
||||
self.play(Blink(keith))
|
||||
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(
|
||||
randy.change_mode, "confused",
|
||||
|
@ -586,7 +605,7 @@ class IntroduceKeith(Scene):
|
|||
morty.change_mode, "plain",
|
||||
morty.look_at, randy.eyes,
|
||||
FadeOut(bubble),
|
||||
FadeOut(bubble.content),
|
||||
FadeOut(original_content),
|
||||
ShowCreation(randy.bubble),
|
||||
Write(randy.bubble.content)
|
||||
)
|
||||
|
@ -1675,6 +1694,28 @@ class RecursiveSolution(TowersOfHanoiScene):
|
|||
def change_mode(self, 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):
|
||||
def construct(self):
|
||||
keith = Keith()
|
||||
|
@ -1721,6 +1762,23 @@ class HanoiSolutionCode(Scene):
|
|||
def construct(self):
|
||||
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):
|
||||
def construct(self):
|
||||
keith = Keith()
|
||||
|
@ -1746,6 +1804,22 @@ class WhyDoesBinaryAchieveThis(Scene):
|
|||
self.play(Blink(morty))
|
||||
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):
|
||||
CONFIG = {
|
||||
"num_disks" : 8,
|
||||
|
@ -1835,6 +1909,18 @@ class ShowFourDiskFourBitsParallel(IntroduceSolveByCounting):
|
|||
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):
|
||||
CONFIG = {
|
||||
"num_disks" : 6,
|
||||
|
@ -3032,7 +3118,8 @@ class DescribeTriforcePattern(SierpinskiGraphScene):
|
|||
"index_pairs" : [(7, 1), (2, 3), (5, 6)],
|
||||
"scale" : 2,
|
||||
"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):
|
||||
index_pair = self.index_pairs[0]
|
||||
|
@ -3064,31 +3151,47 @@ class DescribeTriforcePattern(SierpinskiGraphScene):
|
|||
self.play(*map(ShowCreation, bold_edges[1:]))
|
||||
self.dither()
|
||||
|
||||
nodes = self.nodes[:3**self.scale]
|
||||
circles = VGroup(*[node.circle for node in nodes])
|
||||
towers = VGroup(*[node.towers for node in nodes])
|
||||
circles.save_state()
|
||||
self.play(
|
||||
circles.set_stroke, self.disk_color,
|
||||
Animation(towers),
|
||||
submobject_mode = "lagged_start",
|
||||
run_time = 3
|
||||
)
|
||||
power_of_three = 3**(self.scale-1)
|
||||
index_sets = [
|
||||
range(0, power_of_three),
|
||||
range(power_of_three, 2*power_of_three),
|
||||
range(2*power_of_three, 3*power_of_three),
|
||||
]
|
||||
if self.first_connect_0_and_2_islands:
|
||||
index_sets = [index_sets[0], index_sets[2], index_sets[1]]
|
||||
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.play(
|
||||
circles.restore,
|
||||
Animation(towers),
|
||||
submobject_mode = "lagged_start",
|
||||
)
|
||||
self.play(wiggle_island(islands[2]))
|
||||
self.dither()
|
||||
for pair in self.index_pairs:
|
||||
self.zoom_into_nodes(pair)
|
||||
for index_set in index_sets:
|
||||
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):
|
||||
CONFIG = {
|
||||
"index_pairs" : [(8, 9), (17, 18), (4, 22)],
|
||||
"scale" : 3,
|
||||
"disk_color" : RED,
|
||||
"first_connect_0_and_2_islands" : False,
|
||||
}
|
||||
|
||||
class BiggerTowers(SierpinskiGraphScene):
|
||||
|
@ -3198,12 +3301,39 @@ class PatreonThanks(Scene):
|
|||
self.play(morty.look_at, patrons[index])
|
||||
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):
|
||||
CONFIG = {
|
||||
"sierpinski_graph_scene_config" :{
|
||||
"include_towers" : False
|
||||
},
|
||||
"max_order" : 8,
|
||||
"min_order" : 2,
|
||||
"max_order" : 7,
|
||||
"path_stroke_width" : 7,
|
||||
}
|
||||
def construct(self):
|
||||
|
@ -3212,7 +3342,7 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
|||
num_disks = order,
|
||||
**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]
|
||||
graphs = []
|
||||
|
@ -3225,7 +3355,8 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
|||
|
||||
self.add(graph)
|
||||
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))
|
||||
for other_graph in graphs[1:]:
|
||||
other_graph.fade(0.5)
|
||||
|
@ -3237,7 +3368,7 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
|||
run_time = 2
|
||||
)
|
||||
self.dither()
|
||||
|
||||
self.path = path
|
||||
|
||||
def get_path(self, graph_scene):
|
||||
path = VGroup()
|
||||
|
@ -3254,11 +3385,60 @@ class ShowSierpinskiCurvesOfIncreasingOrder(Scene):
|
|||
graph_scene.start_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
|
||||
|
||||
|
||||
|
||||
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()
|
||||
|
||||
def set_camera_background(self, background):
|
||||
self.camera.set_image(background)
|
||||
self.camera.set_background(background)
|
||||
|
||||
def reset_camera(self):
|
||||
self.camera.reset()
|
||||
|
|
Loading…
Add table
Reference in a new issue