| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | #!/usr/bin/env python | 
					
						
							|  |  |  | # -*- coding: utf-8 -*- | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-30 12:56:29 -07:00
										 |  |  | from big_ol_pile_of_manim_imports import * | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | from old_projects.efvgt import ConfettiSpiril | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #revert_to_original_skipping_status | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class HappyHolidays(TeacherStudentsScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         hats = VGroup(*list(map( | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             self.get_hat, self.pi_creatures | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         ))) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.add(self.get_snowflakes()) | 
					
						
							|  |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             *["hooray"]*3, | 
					
						
							| 
									
										
										
										
											2018-03-30 11:25:37 -07:00
										 |  |  |             look_at_arg = FRAME_Y_RADIUS*UP, | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             added_anims = [self.teacher.change, "hooray"] | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(LaggedStart( | 
					
						
							|  |  |  |             DrawBorderThenFill, hats | 
					
						
							|  |  |  |         ), Animation(self.pi_creatures)) | 
					
						
							|  |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             "happy", "wave_2", "wave_1", | 
					
						
							| 
									
										
										
										
											2018-03-30 11:25:37 -07:00
										 |  |  |             look_at_arg = FRAME_Y_RADIUS*UP, | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         ) | 
					
						
							|  |  |  |         self.look_at(self.teacher.get_corner(UP+LEFT)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(self.teacher.change, "happy") | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def get_hat(self, pi): | 
					
						
							|  |  |  |         hat = SVGMobject( | 
					
						
							|  |  |  |             file_name = "santa_hat", | 
					
						
							|  |  |  |             height = 0.5*pi.get_height() | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         hat.rotate(-np.pi/12) | 
					
						
							|  |  |  |         vect = RIGHT | 
					
						
							|  |  |  |         if not pi.is_flipped(): | 
					
						
							|  |  |  |             hat.flip() | 
					
						
							|  |  |  |             vect = LEFT | 
					
						
							|  |  |  |         hat.set_fill(RED_D) | 
					
						
							|  |  |  |         hat[0].remove(hat[0][1]) | 
					
						
							|  |  |  |         hat[0].set_fill("#EEE") | 
					
						
							|  |  |  |         hat[2].set_fill(WHITE) | 
					
						
							|  |  |  |         hat.add(hat[0]) | 
					
						
							|  |  |  |         hat.next_to(pi.body, UP, buff = SMALL_BUFF) | 
					
						
							|  |  |  |         hat.shift(SMALL_BUFF*vect) | 
					
						
							|  |  |  |         return hat | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_snowflakes(self, n_flakes = 50): | 
					
						
							|  |  |  |         snowflakes = VGroup(*[ | 
					
						
							|  |  |  |             SVGMobject( | 
					
						
							|  |  |  |                 file_name = "snowflake", | 
					
						
							|  |  |  |                 height = 0.5, | 
					
						
							|  |  |  |                 stroke_width = 0, | 
					
						
							|  |  |  |                 fill_opacity = 0.75, | 
					
						
							|  |  |  |                 fill_color = WHITE, | 
					
						
							|  |  |  |             ).rotate(np.pi/12, RIGHT) | 
					
						
							|  |  |  |             for x in range(n_flakes) | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         def random_confetti_spiral(mob, **kwargs): | 
					
						
							|  |  |  |             return ConfettiSpiril( | 
					
						
							| 
									
										
										
										
											2018-03-30 11:25:37 -07:00
										 |  |  |                 mob, x_start = 2*random.random()*FRAME_X_RADIUS - FRAME_X_RADIUS, | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |                 **kwargs | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         snowflake_spirils = LaggedStart( | 
					
						
							|  |  |  |             random_confetti_spiral, snowflakes, | 
					
						
							|  |  |  |             run_time = 10, | 
					
						
							|  |  |  |             rate_func = lambda x : x, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         return NormalAnimationAsContinualAnimation(snowflake_spirils) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class UtilitiesPuzzleScene(Scene): | 
					
						
							|  |  |  |     CONFIG = { | 
					
						
							|  |  |  |         "object_height" : 0.75, | 
					
						
							|  |  |  |         "h_distance" : 2, | 
					
						
							|  |  |  |         "v_distance" : 2, | 
					
						
							|  |  |  |         "line_width" : 4, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     def setup_configuration(self): | 
					
						
							|  |  |  |         houses = VGroup() | 
					
						
							|  |  |  |         for x in range(3): | 
					
						
							|  |  |  |             house = SVGMobject(file_name = "house") | 
					
						
							| 
									
										
										
										
											2018-08-08 10:30:52 -07:00
										 |  |  |             house.set_height(self.object_height) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             house.set_fill(LIGHT_GREY) | 
					
						
							|  |  |  |             house.move_to(x*self.h_distance*RIGHT) | 
					
						
							|  |  |  |             houses.add(house) | 
					
						
							|  |  |  |         houses.move_to(self.v_distance*UP/2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         utilities = VGroup(*[ | 
					
						
							|  |  |  |             self.get_utility(u, c).move_to(x*self.h_distance*RIGHT) | 
					
						
							|  |  |  |             for x, u, c in zip( | 
					
						
							|  |  |  |                 it.count(), | 
					
						
							|  |  |  |                 ["fire", "electricity", "water"],  | 
					
						
							|  |  |  |                 [RED_D, YELLOW_C, BLUE_D] | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         utilities.move_to(self.v_distance*DOWN/2) | 
					
						
							|  |  |  |         objects = VGroup(houses, utilities) | 
					
						
							|  |  |  |         bounding_box = SurroundingRectangle( | 
					
						
							|  |  |  |             objects,    | 
					
						
							|  |  |  |             buff = MED_LARGE_BUFF, | 
					
						
							|  |  |  |             stroke_width = 0 | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         objects.add(bounding_box) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(objects) | 
					
						
							|  |  |  |         self.set_variables_as_attrs( | 
					
						
							|  |  |  |             houses, utilities, objects, bounding_box | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_utility(self, name, color): | 
					
						
							|  |  |  |         circle = Circle( | 
					
						
							|  |  |  |             fill_color = color, | 
					
						
							|  |  |  |             fill_opacity = 1, | 
					
						
							|  |  |  |             stroke_width = 0, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         utility = SVGMobject( | 
					
						
							|  |  |  |             file_name = name, | 
					
						
							|  |  |  |             height = 0.65*circle.get_height(), | 
					
						
							|  |  |  |             fill_color = WHITE, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         if color == YELLOW: | 
					
						
							|  |  |  |             utility.set_fill(DARK_GREY) | 
					
						
							|  |  |  |         utility.move_to(circle) | 
					
						
							|  |  |  |         circle.add(utility) | 
					
						
							| 
									
										
										
										
											2018-08-08 10:30:52 -07:00
										 |  |  |         circle.set_height(self.object_height) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         return circle | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_line( | 
					
						
							|  |  |  |         self, utility_index, house_index,  | 
					
						
							|  |  |  |         *midpoints, | 
					
						
							|  |  |  |         **kwargs | 
					
						
							|  |  |  |         ): | 
					
						
							|  |  |  |         prop = kwargs.pop("prop", 1.0) | 
					
						
							|  |  |  |         utility = self.utilities[utility_index] | 
					
						
							|  |  |  |         points = [utility.get_center()] | 
					
						
							|  |  |  |         points += list(midpoints) | 
					
						
							|  |  |  |         points += [self.houses[house_index].get_center()] | 
					
						
							|  |  |  |         line = Line( | 
					
						
							|  |  |  |             points[0], points[-1], | 
					
						
							|  |  |  |             color = utility[0].get_color(), | 
					
						
							|  |  |  |             stroke_width = self.line_width | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         line.set_points_smoothly(points) | 
					
						
							|  |  |  |         line.pointwise_become_partial(line, 0, prop) | 
					
						
							|  |  |  |         return line | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_almost_solution_lines(self): | 
					
						
							|  |  |  |         bb = self.bounding_box | 
					
						
							|  |  |  |         return VGroup( | 
					
						
							|  |  |  |             VGroup( | 
					
						
							|  |  |  |                 self.get_line(0, 0), | 
					
						
							|  |  |  |                 self.get_line(0, 1), | 
					
						
							|  |  |  |                 self.get_line(0, 2, bb.get_top()), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             VGroup( | 
					
						
							|  |  |  |                 self.get_line(1, 0, bb.get_corner(DOWN+LEFT)), | 
					
						
							|  |  |  |                 self.get_line(1, 1), | 
					
						
							|  |  |  |                 self.get_line(1, 2, bb.get_corner(DOWN+RIGHT)), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             VGroup( | 
					
						
							|  |  |  |                 self.get_line(2, 0, bb.get_top()), | 
					
						
							|  |  |  |                 self.get_line(2, 1), | 
					
						
							|  |  |  |                 self.get_line(2, 2), | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_straight_lines(self): | 
					
						
							|  |  |  |         return VGroup(*[ | 
					
						
							|  |  |  |             VGroup(*[self.get_line(i, j) for j in range(3)]) | 
					
						
							|  |  |  |             for i in range(3) | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_no_crossing_words(self): | 
					
						
							|  |  |  |         arrow = Vector(DOWN) | 
					
						
							|  |  |  |         arrow.next_to(self.bounding_box.get_top(), UP, SMALL_BUFF) | 
					
						
							|  |  |  |         words = TextMobject("No crossing!") | 
					
						
							|  |  |  |         words.next_to(arrow, UP, buff = SMALL_BUFF) | 
					
						
							|  |  |  |         result = VGroup(words, arrow) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         result.set_color("RED") | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_region(self, *bounding_edges): | 
					
						
							|  |  |  |         region = VMobject(mark_paths_closed = True) | 
					
						
							|  |  |  |         for i, edge in enumerate(bounding_edges): | 
					
						
							|  |  |  |             new_edge = edge.copy() | 
					
						
							|  |  |  |             if i%2 == 1: | 
					
						
							|  |  |  |                 new_edge.points = new_edge.points[::-1] | 
					
						
							|  |  |  |             region.append_vectorized_mobject(new_edge) | 
					
						
							|  |  |  |         region.set_stroke(width = 0) | 
					
						
							|  |  |  |         region.set_fill(WHITE, opacity = 1) | 
					
						
							|  |  |  |         return region | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def convert_objects_to_dots(self, run_time = 2): | 
					
						
							|  |  |  |         group = VGroup(*it.chain(self.houses, self.utilities)) | 
					
						
							|  |  |  |         for mob in group: | 
					
						
							|  |  |  |             mob.target = Dot(color = mob.get_color()) | 
					
						
							|  |  |  |             mob.target.scale(2) | 
					
						
							|  |  |  |             mob.target.move_to(mob) | 
					
						
							|  |  |  |         self.play(LaggedStart(MoveToTarget, group, run_time = run_time)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | class PauseIt(PiCreatureScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         morty = self.pi_creatures | 
					
						
							|  |  |  |         morty.center().to_edge(DOWN) | 
					
						
							|  |  |  |         self.pi_creature_says( | 
					
						
							|  |  |  |             "Pause it!", target_mode = "surprised" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |          | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | class AboutToyPuzzles(UtilitiesPuzzleScene, TeacherStudentsScene, ThreeDScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.remove(self.pi_creatures) | 
					
						
							|  |  |  |         self.lay_out_puzzle() | 
					
						
							|  |  |  |         self.point_to_abstractions() | 
					
						
							|  |  |  |         self.show_this_video() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def lay_out_puzzle(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  |         lines = VGroup(*it.chain(*self.get_almost_solution_lines())) | 
					
						
							|  |  |  |         no_crossing_words = self.get_no_crossing_words() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.remove(self.objects) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             ReplacementTransform( | 
					
						
							|  |  |  |                 VGroup(houses[1], houses[1]).copy().fade(1), | 
					
						
							|  |  |  |                 VGroup(houses[0], houses[2]), | 
					
						
							|  |  |  |                 rate_func = squish_rate_func(smooth, 0.35, 1), | 
					
						
							|  |  |  |                 run_time = 2, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             FadeIn(houses[1]), | 
					
						
							|  |  |  |             LaggedStart(DrawBorderThenFill, utilities, run_time = 2) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             LaggedStart( | 
					
						
							|  |  |  |                 ShowCreation, lines,  | 
					
						
							|  |  |  |                 run_time = 3 | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             Animation(self.objects) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             Write(no_crossing_words[0]), | 
					
						
							|  |  |  |             GrowArrow(no_crossing_words[1]), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.objects.add_to_back(lines, no_crossing_words) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def point_to_abstractions(self): | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  |         objects.generate_target() | 
					
						
							|  |  |  |         objects.target.scale(0.5) | 
					
						
							|  |  |  |         objects.target.move_to( | 
					
						
							| 
									
										
										
										
											2018-03-30 11:25:37 -07:00
										 |  |  |             (FRAME_Y_RADIUS*DOWN + FRAME_X_RADIUS*LEFT)/2 | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         eulers = TexMobject(*"V-E+F=2") | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         eulers.set_color_by_tex_to_color_map({ | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             "V" : RED, | 
					
						
							|  |  |  |             "E" : GREEN, | 
					
						
							|  |  |  |             "F" : BLUE, | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         eulers.to_edge(UP, buff = 2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         cube = Cube() | 
					
						
							|  |  |  |         cube.set_stroke(WHITE, 2) | 
					
						
							| 
									
										
										
										
											2018-08-08 10:30:52 -07:00
										 |  |  |         cube.set_height(0.75) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         cube.pose_at_angle() | 
					
						
							|  |  |  |         cube.next_to(eulers, UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         tda = TextMobject("Topological \\\\ Data Analysis") | 
					
						
							|  |  |  |         tda.move_to(DOWN + 4*RIGHT) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         arrow_from_eulers = Arrow( | 
					
						
							|  |  |  |             eulers.get_bottom(), tda.get_corner(UP+LEFT), | 
					
						
							|  |  |  |             color = WHITE | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             objects.scale, 0.5, | 
					
						
							|  |  |  |             objects.move_to, DOWN + 4*LEFT, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         arrow_to_eulers = Arrow( | 
					
						
							|  |  |  |             self.houses[2].get_corner(UP+LEFT), | 
					
						
							|  |  |  |             eulers.get_bottom(), | 
					
						
							|  |  |  |             color = WHITE | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-03-31 15:37:23 -07:00
										 |  |  |         self.add(ContinualRotation(cube, axis = UP)) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             GrowArrow(arrow_to_eulers), | 
					
						
							|  |  |  |             Write(eulers), | 
					
						
							|  |  |  |             FadeIn(cube) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(5) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             GrowArrow(arrow_from_eulers), | 
					
						
							|  |  |  |             Write(tda) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.set_variables_as_attrs( | 
					
						
							|  |  |  |             eulers, cube, tda, | 
					
						
							|  |  |  |             arrows = VGroup(arrow_to_eulers, arrow_from_eulers), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def show_this_video(self): | 
					
						
							|  |  |  |         screen_rect = FullScreenFadeRectangle( | 
					
						
							|  |  |  |             stroke_color = WHITE, | 
					
						
							|  |  |  |             stroke_width = 2, | 
					
						
							|  |  |  |             fill_opacity = 0, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         everything = VGroup( | 
					
						
							|  |  |  |             self.objects, self.arrows, self.eulers,  | 
					
						
							|  |  |  |             self.cube, self.tda, | 
					
						
							|  |  |  |             screen_rect, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.teacher.save_state() | 
					
						
							|  |  |  |         self.teacher.fade(1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             everything.scale, 0.5, | 
					
						
							|  |  |  |             everything.next_to, self.teacher, UP+LEFT, | 
					
						
							|  |  |  |             self.teacher.restore, | 
					
						
							|  |  |  |             self.teacher.change, "raise_right_hand", UP+LEFT, | 
					
						
							|  |  |  |             LaggedStart(FadeIn, self.students) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             *["pondering"]*3, look_at_arg = everything | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(5) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ThisPuzzleIsHard(UtilitiesPuzzleScene, PiCreatureScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.introduce_components() | 
					
						
							|  |  |  |         self.failed_attempts() | 
					
						
							|  |  |  |         self.ask_meta_puzzle() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def introduce_components(self): | 
					
						
							|  |  |  |         randy = self.pi_creature | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try_it = TextMobject("Try it yourself!") | 
					
						
							|  |  |  |         try_it.to_edge(UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  |         self.remove(self.objects) | 
					
						
							|  |  |  |         house = houses[0] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         puzzle_words = TextMobject("""
 | 
					
						
							|  |  |  |             Puzzle: Connect each house to \\\\ | 
					
						
							|  |  |  |             each utility without crossing lines. | 
					
						
							|  |  |  |         """)
 | 
					
						
							|  |  |  |         # puzzle_words.next_to(self.objects, UP) | 
					
						
							|  |  |  |         puzzle_words.to_edge(UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.add(try_it) | 
					
						
							|  |  |  |         self.play(Animation(try_it)) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             LaggedStart(DrawBorderThenFill, houses), | 
					
						
							|  |  |  |             LaggedStart(GrowFromCenter, utilities), | 
					
						
							| 
									
										
										
										
											2018-08-08 10:30:52 -07:00
										 |  |  |             try_it.set_width, house.get_width(), | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             try_it.fade, 1, | 
					
						
							|  |  |  |             try_it.move_to, house, | 
					
						
							|  |  |  |             self.pi_creature.change, "happy", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(LaggedStart(FadeIn, puzzle_words)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.add_foreground_mobjects(self.objects) | 
					
						
							|  |  |  |         self.set_variables_as_attrs(puzzle_words) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def failed_attempts(self): | 
					
						
							|  |  |  |         bb = self.bounding_box | 
					
						
							|  |  |  |         utilities = self.utilities | 
					
						
							|  |  |  |         houses = self.houses | 
					
						
							|  |  |  |         randy = self.pi_creature | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         line_sets = [ | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 self.get_line(0, 0), | 
					
						
							|  |  |  |                 self.get_line(1, 1), | 
					
						
							|  |  |  |                 self.get_line(2, 2), | 
					
						
							|  |  |  |                 self.get_line(0, 1), | 
					
						
							|  |  |  |                 self.get_line(2, 1), | 
					
						
							|  |  |  |                 self.get_line(0, 2, bb.get_corner(UP+LEFT)), | 
					
						
							|  |  |  |                 self.get_line( | 
					
						
							|  |  |  |                     2, 0, bb.get_corner(DOWN+LEFT), | 
					
						
							|  |  |  |                     prop = 0.85, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 self.get_line( | 
					
						
							|  |  |  |                     2, 0, bb.get_corner(UP+RIGHT), bb.get_top(), | 
					
						
							|  |  |  |                     prop = 0.73, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 self.get_line(0, 0), | 
					
						
							|  |  |  |                 self.get_line(1, 1), | 
					
						
							|  |  |  |                 self.get_line(2, 2), | 
					
						
							|  |  |  |                 self.get_line(0, 1), | 
					
						
							|  |  |  |                 self.get_line(1, 2), | 
					
						
							|  |  |  |                 self.get_line( | 
					
						
							|  |  |  |                     2, 0,  | 
					
						
							|  |  |  |                     bb.get_bottom(), | 
					
						
							|  |  |  |                     bb.get_corner(DOWN+LEFT) | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 self.get_line(0, 2, bb.get_top()), | 
					
						
							|  |  |  |                 self.get_line( | 
					
						
							|  |  |  |                     2, 1, | 
					
						
							|  |  |  |                     utilities[1].get_bottom() + MED_SMALL_BUFF*DOWN, | 
					
						
							|  |  |  |                     utilities[1].get_left() + MED_SMALL_BUFF*LEFT, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 self.get_line( | 
					
						
							|  |  |  |                     1, 0, houses[2].get_corner(UP+LEFT) + MED_LARGE_BUFF*LEFT, | 
					
						
							|  |  |  |                     prop = 0.49, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 self.get_line( | 
					
						
							|  |  |  |                     1, 2, bb.get_right(), | 
					
						
							|  |  |  |                     prop = 0.25, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 self.get_line(0, 0), | 
					
						
							|  |  |  |                 self.get_line(0, 1), | 
					
						
							|  |  |  |                 self.get_line(0, 2, bb.get_top()), | 
					
						
							|  |  |  |                 self.get_line(1, 0, bb.get_corner(DOWN+LEFT)), | 
					
						
							|  |  |  |                 self.get_line(1, 1), | 
					
						
							|  |  |  |                 self.get_line(1, 2, bb.get_corner(DOWN+RIGHT)), | 
					
						
							|  |  |  |                 self.get_line(2, 1), | 
					
						
							|  |  |  |                 self.get_line(2, 2), | 
					
						
							|  |  |  |                 self.get_line(2, 0, bb.get_top(), prop = 0.45), | 
					
						
							|  |  |  |                 self.get_line(2, 0, prop = 0.45), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         modes = ["confused", "sassy", "angry"] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for line_set, mode in zip(line_sets, modes): | 
					
						
							|  |  |  |             good_lines = VGroup(*line_set[:-2]) | 
					
						
							|  |  |  |             bad_lines = line_set[-2:] | 
					
						
							|  |  |  |             self.play(LaggedStart(ShowCreation, good_lines)) | 
					
						
							|  |  |  |             for bl in bad_lines: | 
					
						
							|  |  |  |                 self.play( | 
					
						
							|  |  |  |                     ShowCreation( | 
					
						
							|  |  |  |                         bl, | 
					
						
							|  |  |  |                         rate_func = bezier([0, 0, 0, 1, 1, 1, 1, 1, 0.3, 1, 1]), | 
					
						
							|  |  |  |                         run_time = 1.5 | 
					
						
							|  |  |  |                     ), | 
					
						
							|  |  |  |                     randy.change, mode, | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 self.play(ShowCreation( | 
					
						
							|  |  |  |                     bl, rate_func = lambda t : smooth(1-t), | 
					
						
							|  |  |  |                 )) | 
					
						
							|  |  |  |                 self.remove(bl) | 
					
						
							|  |  |  |             self.play(LaggedStart(FadeOut, good_lines)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def ask_meta_puzzle(self): | 
					
						
							|  |  |  |         randy = self.pi_creature | 
					
						
							|  |  |  |         group = VGroup( | 
					
						
							|  |  |  |             self.puzzle_words, | 
					
						
							|  |  |  |             self.objects, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         rect = SurroundingRectangle(group, color = BLUE, buff = MED_LARGE_BUFF) | 
					
						
							|  |  |  |         group.add(rect) | 
					
						
							|  |  |  |         group.generate_target() | 
					
						
							|  |  |  |         group.target.scale(0.75) | 
					
						
							|  |  |  |         group.target.shift(DOWN) | 
					
						
							|  |  |  |         group[-1].set_stroke(width = 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         meta_puzzle_words = TextMobject("""
 | 
					
						
							|  |  |  |             Meta-puzzle: Prove that this\\\\ | 
					
						
							|  |  |  |             is impossible. | 
					
						
							|  |  |  |         """)
 | 
					
						
							|  |  |  |         meta_puzzle_words.next_to(group.target, UP) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         meta_puzzle_words.set_color(BLUE) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             MoveToTarget(group), | 
					
						
							|  |  |  |             randy.change, "pondering" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(Write(meta_puzzle_words)) | 
					
						
							|  |  |  |         self.play(randy.change, "confused") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         straight_lines = self.get_straight_lines() | 
					
						
							|  |  |  |         almost_solution_lines = self.get_almost_solution_lines() | 
					
						
							|  |  |  |         self.play(LaggedStart( | 
					
						
							|  |  |  |             ShowCreation, straight_lines, | 
					
						
							|  |  |  |             run_time = 2, | 
					
						
							|  |  |  |             lag_ratio = 0.8 | 
					
						
							|  |  |  |         ), Blink(randy)) | 
					
						
							|  |  |  |         self.play(Transform( | 
					
						
							|  |  |  |             straight_lines, almost_solution_lines, | 
					
						
							|  |  |  |             run_time = 3, | 
					
						
							|  |  |  |             submobject_mode = "lagged_start" | 
					
						
							|  |  |  |         )) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ###### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_pi_creature(self): | 
					
						
							|  |  |  |         return Randolph().to_corner(DOWN+LEFT) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class IntroduceGraph(PiCreatureScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         pi_creatures = self.pi_creatures | 
					
						
							|  |  |  |         dots = VGroup(*[ | 
					
						
							|  |  |  |             Dot(color = pi.get_color()).scale(2).move_to(pi) | 
					
						
							|  |  |  |             for pi in pi_creatures | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         lines = VGroup(*[ | 
					
						
							|  |  |  |             Line(pi1.get_center(), pi2.get_center()) | 
					
						
							|  |  |  |             for pi1, pi2 in it.combinations(pi_creatures, 2) | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         graph_word = TextMobject("``", "", "Graph", "''", arg_separator = "") | 
					
						
							|  |  |  |         graph_word.to_edge(UP) | 
					
						
							|  |  |  |         planar_graph_word = TextMobject("``", "Planar", " graph", "''", arg_separator = "") | 
					
						
							|  |  |  |         planar_graph_word.move_to(graph_word) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         vertices_word = TextMobject("Vertices") | 
					
						
							|  |  |  |         vertices_word.to_edge(RIGHT, buff = LARGE_BUFF) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         vertices_word.set_color(YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         vertex_arrows = VGroup(*[ | 
					
						
							|  |  |  |             Arrow(vertices_word.get_left(), dot) | 
					
						
							|  |  |  |             for dot in dots[-2:] | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         edge_word = TextMobject("Edge") | 
					
						
							|  |  |  |         edge_word.next_to(lines, LEFT, LARGE_BUFF) | 
					
						
							|  |  |  |         edge_arrow = Arrow( | 
					
						
							|  |  |  |             edge_word, lines, buff = SMALL_BUFF, | 
					
						
							|  |  |  |             color = WHITE | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play(LaggedStart(GrowFromCenter, pi_creatures)) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             LaggedStart(ShowCreation, lines), | 
					
						
							|  |  |  |             LaggedStart( | 
					
						
							|  |  |  |                 ApplyMethod, pi_creatures, | 
					
						
							|  |  |  |                 lambda pi : (pi.change, "pondering", lines) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(Write(graph_word)) | 
					
						
							|  |  |  |         self.play(ReplacementTransform( | 
					
						
							|  |  |  |             pi_creatures, dots, | 
					
						
							|  |  |  |             run_time = 2, | 
					
						
							|  |  |  |             submobject_mode = "lagged_start" | 
					
						
							|  |  |  |         )) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(dots) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(vertex_arrows), | 
					
						
							|  |  |  |             FadeIn(vertices_word), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(LaggedStart( | 
					
						
							|  |  |  |             ApplyMethod, lines, | 
					
						
							|  |  |  |             lambda l : (l.rotate_in_place, np.pi/12), | 
					
						
							|  |  |  |             rate_func = wiggle | 
					
						
							|  |  |  |         )) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(edge_word), | 
					
						
							|  |  |  |             GrowArrow(edge_arrow), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         line = lines[2] | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             line.set_points_smoothly, [ | 
					
						
							|  |  |  |                 line.get_start(), | 
					
						
							|  |  |  |                 dots.get_left() + MED_SMALL_BUFF*LEFT, | 
					
						
							|  |  |  |                 dots.get_corner(DOWN+LEFT) + MED_SMALL_BUFF*(DOWN+LEFT), | 
					
						
							|  |  |  |                 dots.get_bottom() + MED_SMALL_BUFF*DOWN, | 
					
						
							|  |  |  |                 line.get_end(), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             VGroup(edge_word, edge_arrow).shift, MED_LARGE_BUFF*LEFT, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(ReplacementTransform(graph_word, planar_graph_word)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_pi_creatures(self): | 
					
						
							|  |  |  |         pis = VGroup( | 
					
						
							|  |  |  |             PiCreature(color = BLUE_D), | 
					
						
							|  |  |  |             PiCreature(color = GREY_BROWN), | 
					
						
							|  |  |  |             PiCreature(color = BLUE_C).flip(), | 
					
						
							|  |  |  |             PiCreature(color = BLUE_E).flip(), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         pis.scale(0.5) | 
					
						
							|  |  |  |         pis.arrange_submobjects_in_grid(buff = 2) | 
					
						
							|  |  |  |         return pis | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class IsK33Planar(UtilitiesPuzzleScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         self.objects.shift(MED_LARGE_BUFF*DOWN) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         straight_lines = self.get_straight_lines() | 
					
						
							|  |  |  |         almost_solution_lines = self.get_almost_solution_lines() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         question = TextMobject("Is", "this graph", "planar?") | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         question.set_color_by_tex("this graph", YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         question.to_edge(UP) | 
					
						
							|  |  |  |         brace = Brace(question.get_part_by_tex("graph"), DOWN, buff = SMALL_BUFF) | 
					
						
							|  |  |  |         fancy_name = brace.get_text( | 
					
						
							|  |  |  |             "``Complete bipartite graph $K_{3, 3}$''", | 
					
						
							|  |  |  |             buff = SMALL_BUFF | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         fancy_name.set_color(YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.add(question) | 
					
						
							|  |  |  |         self.convert_objects_to_dots() | 
					
						
							|  |  |  |         self.play(LaggedStart(ShowCreation, straight_lines)) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             GrowFromCenter(brace), | 
					
						
							|  |  |  |             LaggedStart(FadeIn, fancy_name), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(ReplacementTransform( | 
					
						
							|  |  |  |             straight_lines, almost_solution_lines, | 
					
						
							|  |  |  |             run_time = 3, | 
					
						
							|  |  |  |             submobject_mode = "lagged_start" | 
					
						
							|  |  |  |         )) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class TwoKindsOfViewers(PiCreatureScene, UtilitiesPuzzleScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  |         objects.remove(self.bounding_box) | 
					
						
							|  |  |  |         lines = self.get_straight_lines() | 
					
						
							|  |  |  |         objects.add_to_back(lines) | 
					
						
							|  |  |  |         objects.scale(0.75) | 
					
						
							|  |  |  |         objects.next_to(ORIGIN, RIGHT, LARGE_BUFF) | 
					
						
							|  |  |  |         self.remove(objects) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pi1, pi2 = self.pi_creatures | 
					
						
							|  |  |  |         words = TextMobject( | 
					
						
							|  |  |  |             "$(V-E+F)$", "kinds of viewers" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         words.to_edge(UP) | 
					
						
							|  |  |  |         eulers = words.get_part_by_tex("V-E+F") | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         eulers.set_color(GREEN) | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         non_eulers = VGroup(*[m for m in words if m is not eulers]) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.add(words) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             pi1.shift, 2*LEFT, | 
					
						
							|  |  |  |             pi2.shift, 2*RIGHT, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         know_eulers = TextMobject("Know about \\\\ Euler's formula") | 
					
						
							|  |  |  |         know_eulers.next_to(pi1, DOWN) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         know_eulers.set_color(GREEN) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         dont = TextMobject("Don't") | 
					
						
							|  |  |  |         dont.next_to(pi2, DOWN) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         dont.set_color(RED) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(know_eulers), | 
					
						
							|  |  |  |             pi1.change, "hooray", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(dont), | 
					
						
							|  |  |  |             pi2.change, "maybe", eulers, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.pi_creature_thinks( | 
					
						
							|  |  |  |             pi1, "", | 
					
						
							|  |  |  |             bubble_kwargs = {"width" : 3, "height" : 2}, | 
					
						
							|  |  |  |             target_mode = "thinking" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(pi2.change, "confused", eulers) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ### Out of thin air | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         self.play(*list(map(FadeOut, [ | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             non_eulers, pi1, pi2, pi1.bubble, | 
					
						
							|  |  |  |             know_eulers, dont | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         ]))) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(eulers.next_to, ORIGIN, LEFT, LARGE_BUFF) | 
					
						
							|  |  |  |         arrow = Arrow(eulers, objects, color = WHITE) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             GrowArrow(arrow), | 
					
						
							|  |  |  |             LaggedStart(DrawBorderThenFill, VGroup(*it.chain(*objects))) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             objects.move_to, eulers, RIGHT, | 
					
						
							|  |  |  |             eulers.move_to, objects, LEFT, | 
					
						
							|  |  |  |             path_arc = np.pi, | 
					
						
							|  |  |  |             run_time = 1.5, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_pi_creatures(self): | 
					
						
							|  |  |  |         group = VGroup(Randolph(color = BLUE_C), Randolph()) | 
					
						
							|  |  |  |         group.scale(0.7) | 
					
						
							|  |  |  |         group.shift(MED_LARGE_BUFF*DOWN) | 
					
						
							|  |  |  |         return group | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class IntroduceRegions(UtilitiesPuzzleScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  |         lines, line_groups, regions = self.get_lines_line_groups_and_regions() | 
					
						
							|  |  |  |         back_region = regions[0] | 
					
						
							|  |  |  |         front_regions = VGroup(*regions[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.convert_objects_to_dots(run_time = 0) | 
					
						
							|  |  |  |         self.play(LaggedStart( | 
					
						
							|  |  |  |             ShowCreation, lines, | 
					
						
							|  |  |  |             run_time = 3, | 
					
						
							|  |  |  |         )) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(lines, objects) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         for region in front_regions: | 
					
						
							|  |  |  |             self.play(FadeIn(region)) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(back_region), | 
					
						
							|  |  |  |             Animation(front_regions), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(FadeOut(regions)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ##Paint bucket | 
					
						
							|  |  |  |         paint_bucket = SVGMobject( | 
					
						
							|  |  |  |             file_name = "paint_bucket", | 
					
						
							|  |  |  |             height = 0.5, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         paint_bucket.flip() | 
					
						
							|  |  |  |         paint_bucket.move_to(8*LEFT + 5*UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def click(region): | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 UpdateFromAlphaFunc( | 
					
						
							|  |  |  |                     region, | 
					
						
							|  |  |  |                     lambda m, a : m.set_fill(opacity = int(2*a)), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 ApplyMethod( | 
					
						
							|  |  |  |                     paint_bucket.scale_in_place, 0.5, | 
					
						
							|  |  |  |                     rate_func = there_and_back, | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 run_time = 0.25, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             paint_bucket.next_to, utilities, DOWN+LEFT, SMALL_BUFF | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         click(regions[1]) | 
					
						
							|  |  |  |         self.play(paint_bucket.next_to, utilities[1], UP+RIGHT, SMALL_BUFF) | 
					
						
							|  |  |  |         click(regions[2]) | 
					
						
							|  |  |  |         self.play(paint_bucket.next_to, houses[1], RIGHT) | 
					
						
							|  |  |  |         click(regions[3]) | 
					
						
							|  |  |  |         self.play(paint_bucket.move_to, 4*LEFT + 2*UP) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(front_regions, lines, objects) | 
					
						
							|  |  |  |         click(back_region) | 
					
						
							|  |  |  |         self.remove_foreground_mobjects(front_regions) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             FadeOut(back_region), | 
					
						
							|  |  |  |             FadeOut(front_regions[0]), | 
					
						
							|  |  |  |             FadeOut(paint_bucket), | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |             *list(map(Animation, front_regions[1:])) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #Line tries to escape | 
					
						
							|  |  |  |         point_sets = [ | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 VGroup(*houses[1:]).get_center(), | 
					
						
							|  |  |  |                 houses[2].get_top() + MED_SMALL_BUFF*UP, | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 houses[1].get_top() + SMALL_BUFF*UP, | 
					
						
							|  |  |  |                 utilities[0].get_center(), | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |             [VGroup(houses[1], utilities[1]).get_center()], | 
					
						
							|  |  |  |             [ | 
					
						
							|  |  |  |                 utilities[2].get_center() + 0.75*(DOWN+RIGHT) | 
					
						
							|  |  |  |             ], | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         escape_lines = VGroup(*[ | 
					
						
							|  |  |  |             Line(LEFT, RIGHT).set_points_smoothly( | 
					
						
							|  |  |  |                 [utilities[2].get_center()] + point_set | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             for point_set in point_sets | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         for line in escape_lines: | 
					
						
							|  |  |  |             self.play(ShowCreation(line, | 
					
						
							|  |  |  |                 rate_func = lambda t : 0.8*smooth(t) | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  |             self.play(ShowCreation(line, | 
					
						
							|  |  |  |                 rate_func = lambda t : smooth(1 - t) | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_lines_line_groups_and_regions(self): | 
					
						
							|  |  |  |         lines = self.get_almost_solution_lines() | 
					
						
							|  |  |  |         flat_lines = VGroup(*it.chain(*lines)) | 
					
						
							|  |  |  |         flat_lines.remove(lines[2][0]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         line_groups = [ | 
					
						
							|  |  |  |             VGroup(*[lines[i][j] for i, j in ij_set]) | 
					
						
							|  |  |  |             for ij_set in [ | 
					
						
							|  |  |  |                 [(0, 0), (1, 0), (1, 1), (0, 1)], | 
					
						
							|  |  |  |                 [(1, 1), (2, 1), (2, 2), (1, 2)], | 
					
						
							|  |  |  |                 [(0, 2), (2, 2), (2, 1), (0, 1)], | 
					
						
							|  |  |  |                 [(0, 0), (1, 0), (1, 2), (0, 2)], | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         regions = VGroup(*[ | 
					
						
							|  |  |  |             self.get_region(*line_group) | 
					
						
							|  |  |  |             for line_group in line_groups | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         back_region = FullScreenFadeRectangle(fill_opacity = 1 ) | 
					
						
							|  |  |  |         regions.submobjects.pop() | 
					
						
							|  |  |  |         regions.submobjects.insert(0, back_region) | 
					
						
							|  |  |  |         front_regions = VGroup(*regions[1:]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         back_region.set_color(BLUE_E) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:59:39 -07:00
										 |  |  |         front_regions.set_color_by_gradient(GREEN_E, MAROON_E) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return flat_lines, line_groups, regions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FromLastVideo(Scene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         title = TextMobject("From last video") | 
					
						
							|  |  |  |         title.to_edge(UP) | 
					
						
							|  |  |  |         rect = ScreenRectangle(height = 6) | 
					
						
							|  |  |  |         rect.next_to(title, DOWN) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.add(title) | 
					
						
							|  |  |  |         self.play(ShowCreation(rect)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class AskAboutRegions(IntroduceRegions): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  |         self.convert_objects_to_dots(run_time = 0) | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  |         lines, line_groups, regions = self.get_lines_line_groups_and_regions() | 
					
						
							|  |  |  |         back_region = regions[0] | 
					
						
							|  |  |  |         front_regions = VGroup(*regions[1:]) | 
					
						
							|  |  |  |         missing_lines = VGroup( | 
					
						
							|  |  |  |             self.get_line(2, 0, self.objects.get_top()), | 
					
						
							|  |  |  |             self.get_line( | 
					
						
							|  |  |  |                 2, 0,  | 
					
						
							|  |  |  |                 self.objects.get_bottom() + DOWN, | 
					
						
							|  |  |  |                 self.objects.get_corner(DOWN+LEFT) + DOWN+LEFT, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         missing_lines.set_stroke(width = 5) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         front_regions.save_state() | 
					
						
							|  |  |  |         front_regions.generate_target() | 
					
						
							|  |  |  |         front_regions.target.scale(0.5) | 
					
						
							|  |  |  |         front_regions.target.arrange_submobjects(RIGHT, buff = LARGE_BUFF) | 
					
						
							|  |  |  |         front_regions.target.to_edge(UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.add(front_regions) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(lines, objects) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(MoveToTarget(front_regions)) | 
					
						
							|  |  |  |         self.play(LaggedStart( | 
					
						
							|  |  |  |             ApplyMethod, front_regions, | 
					
						
							|  |  |  |             lambda m : (m.rotate_in_place, np.pi/12), | 
					
						
							|  |  |  |             rate_func = wiggle, | 
					
						
							|  |  |  |             lag_ratio = 0.75, | 
					
						
							|  |  |  |             run_time = 1 | 
					
						
							|  |  |  |         )) | 
					
						
							|  |  |  |         self.play(front_regions.restore) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #Show missing lines | 
					
						
							|  |  |  |         for line in missing_lines: | 
					
						
							|  |  |  |             self.play(ShowCreation( | 
					
						
							|  |  |  |                 line, | 
					
						
							|  |  |  |                 rate_func = there_and_back, | 
					
						
							|  |  |  |                 run_time = 2, | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #Count regions | 
					
						
							|  |  |  |         count = TexMobject("1") | 
					
						
							|  |  |  |         count.scale(1.5) | 
					
						
							|  |  |  |         count.to_edge(UP) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(back_region),  | 
					
						
							|  |  |  |             FadeIn(count), | 
					
						
							|  |  |  |             Animation(front_regions) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         last_region = None | 
					
						
							|  |  |  |         for n, region in zip(it.count(2), front_regions): | 
					
						
							|  |  |  |             new_count = TexMobject(str(n)) | 
					
						
							|  |  |  |             new_count.replace(count, dim_to_match = 1) | 
					
						
							|  |  |  |             self.remove(count) | 
					
						
							|  |  |  |             self.add(new_count) | 
					
						
							|  |  |  |             count = new_count | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             region.save_state() | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |             anims = [ApplyMethod(region.set_color, YELLOW)] | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             if last_region: | 
					
						
							|  |  |  |                 anims.append(ApplyMethod(last_region.restore)) | 
					
						
							|  |  |  |             anims.append(Animation(front_regions)) | 
					
						
							|  |  |  |             self.play(*anims, run_time = 0.25) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |             self.wait(0.5) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             last_region = region | 
					
						
							|  |  |  |         self.play(last_region.restore) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(FadeOut(count)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #Count edges per region | 
					
						
							|  |  |  |         fade_rect = FullScreenFadeRectangle(opacity = 0.8) | 
					
						
							|  |  |  |         line_group = line_groups[0].copy() | 
					
						
							|  |  |  |         region = front_regions[0].copy() | 
					
						
							|  |  |  |         self.foreground_mobjects = [] | 
					
						
							|  |  |  |         def show_lines(line_group): | 
					
						
							|  |  |  |             lg_copy = line_group.copy() | 
					
						
							|  |  |  |             lg_copy.set_stroke(WHITE, 6) | 
					
						
							|  |  |  |             self.play(LaggedStart( | 
					
						
							|  |  |  |                 FadeIn, lg_copy, | 
					
						
							|  |  |  |                 run_time = 3, | 
					
						
							|  |  |  |                 rate_func = there_and_back, | 
					
						
							|  |  |  |                 lag_ratio = 0.4, | 
					
						
							|  |  |  |                 remover = True, | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(fade_rect), | 
					
						
							|  |  |  |             Animation(region), | 
					
						
							|  |  |  |             Animation(line_group), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         show_lines(line_group) | 
					
						
							|  |  |  |         last_line_group = line_group | 
					
						
							|  |  |  |         last_region = region | 
					
						
							|  |  |  |         for i in range(1, 3): | 
					
						
							|  |  |  |             line_group = line_groups[i].copy() | 
					
						
							|  |  |  |             region = front_regions[i].copy() | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 FadeOut(last_region), | 
					
						
							|  |  |  |                 FadeOut(last_line_group), | 
					
						
							|  |  |  |                 FadeIn(region), | 
					
						
							|  |  |  |                 FadeIn(line_group), | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             show_lines(line_group) | 
					
						
							|  |  |  |             last_line_group = line_group | 
					
						
							|  |  |  |             last_region = region | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeOut(fade_rect), | 
					
						
							|  |  |  |             FadeOut(last_region), | 
					
						
							|  |  |  |             FadeOut(last_line_group), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class NewRegionClosedOnlyForNodesWithEdges(UtilitiesPuzzleScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         self.convert_objects_to_dots(run_time = 0) | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         bb = self.bounding_box | 
					
						
							|  |  |  |         lines = VGroup( | 
					
						
							|  |  |  |             self.get_line(2, 1), | 
					
						
							|  |  |  |             self.get_line(0, 1), | 
					
						
							|  |  |  |             self.get_line(0, 2, | 
					
						
							|  |  |  |                 bb.get_corner(UP+LEFT), | 
					
						
							|  |  |  |                 bb.get_top() + MED_LARGE_BUFF*UP, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             self.get_line(2, 2), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         lit_line = lines[2].copy() | 
					
						
							|  |  |  |         lit_line.points = lit_line.points[::-1] | 
					
						
							|  |  |  |         lit_line.set_stroke(WHITE, 5) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         region = self.get_region(*lines) | 
					
						
							|  |  |  |         region.set_fill(MAROON_E) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         arrow = Vector(DOWN+LEFT, color = WHITE) | 
					
						
							|  |  |  |         arrow.next_to(houses[2], UP+RIGHT, buff = SMALL_BUFF) | 
					
						
							|  |  |  |         words = TextMobject("Already has \\\\ an edge") | 
					
						
							|  |  |  |         words.next_to(arrow.get_start(), UP, SMALL_BUFF) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for line in lines[:-1]: | 
					
						
							|  |  |  |             self.play(ShowCreation(line)) | 
					
						
							|  |  |  |         lines[-1].pointwise_become_partial(lines[-1], 0, 0.92) | 
					
						
							|  |  |  |         lines[-1].save_state() | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play(ShowCreation(lines[-1])) | 
					
						
							|  |  |  |         self.add(region, lines, objects) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.remove(region) | 
					
						
							|  |  |  |         self.play(ShowCreation(lines[-1],  | 
					
						
							|  |  |  |             rate_func = lambda t : smooth(1-2*t*(1-t)) | 
					
						
							|  |  |  |         )) | 
					
						
							|  |  |  |         self.add(region, lines, objects) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.remove(region) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             ShowCreation(lines[-1], | 
					
						
							|  |  |  |                 rate_func = lambda t : smooth(1-0.5*t) | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             FadeIn(words), | 
					
						
							|  |  |  |             GrowArrow(arrow), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         for x in range(2): | 
					
						
							|  |  |  |             self.play(ShowCreationThenDestruction(lit_line)) | 
					
						
							|  |  |  |         self.play(lines[-1].restore) | 
					
						
							|  |  |  |         self.add(region, lines, objects) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class LightUpNodes(IntroduceRegions): | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |     CONFIG = { | 
					
						
							|  |  |  |         "vertices_word" : "Lit vertices", | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         self.setup_regions() | 
					
						
							|  |  |  |         self.setup_counters() | 
					
						
							|  |  |  |         self.describe_one_as_lit() | 
					
						
							|  |  |  |         self.show_rule_for_lighting() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setup_configuration(self): | 
					
						
							|  |  |  |         IntroduceRegions.setup_configuration(self) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.convert_objects_to_dots(run_time = 0) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.objects.shift(DOWN) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setup_regions(self): | 
					
						
							|  |  |  |         lines, line_groups, regions = self.get_lines_line_groups_and_regions() | 
					
						
							|  |  |  |         back_region = regions[0] | 
					
						
							|  |  |  |         front_regions = VGroup(*regions[1:]) | 
					
						
							|  |  |  |         self.set_variables_as_attrs( | 
					
						
							|  |  |  |             lines, line_groups, regions, | 
					
						
							|  |  |  |             back_region, front_regions, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setup_counters(self): | 
					
						
							|  |  |  |         titles = [ | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             TextMobject("\\# %s"%self.vertices_word), | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             TextMobject("\\# Edges"), | 
					
						
							|  |  |  |             TextMobject("\\# Regions"), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         for title, vect in zip(titles, [LEFT, ORIGIN, RIGHT]): | 
					
						
							| 
									
										
										
										
											2018-03-30 11:25:37 -07:00
										 |  |  |             title.shift(FRAME_X_RADIUS*vect/2) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             title.to_edge(UP) | 
					
						
							|  |  |  |             underline = Line(LEFT, RIGHT) | 
					
						
							|  |  |  |             underline.stretch_to_fit_width(title.get_width()) | 
					
						
							|  |  |  |             underline.next_to(title, DOWN, SMALL_BUFF) | 
					
						
							|  |  |  |             title.add(underline) | 
					
						
							|  |  |  |             self.add(title) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.count_titles = titles | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         self.v_count, self.e_count, self.f_count = self.counts = list(map( | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             Integer, [1, 0, 1] | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         )) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         for count, title in zip(self.counts, titles): | 
					
						
							|  |  |  |             count.next_to(title, DOWN) | 
					
						
							|  |  |  |             self.add(count) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def describe_one_as_lit(self): | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  |         vertices = VGroup(*it.chain(houses, utilities)) | 
					
						
							|  |  |  |         dim_arrows = VGroup() | 
					
						
							|  |  |  |         for vertex in vertices: | 
					
						
							|  |  |  |             arrow = Vector(0.5*(DOWN+LEFT), color = WHITE) | 
					
						
							|  |  |  |             arrow.next_to(vertex, UP+RIGHT, SMALL_BUFF) | 
					
						
							|  |  |  |             vertex.arrow = arrow | 
					
						
							|  |  |  |             dim_arrows.add(arrow) | 
					
						
							|  |  |  |         lit_vertex = utilities[0] | 
					
						
							|  |  |  |         lit_arrow = lit_vertex.arrow | 
					
						
							|  |  |  |         lit_arrow.rotate(np.pi/2, about_point = lit_vertex.get_center()) | 
					
						
							|  |  |  |         dim_arrows.remove(lit_arrow) | 
					
						
							|  |  |  |         lit_word = TextMobject("Lit up") | 
					
						
							|  |  |  |         lit_word.next_to(lit_arrow.get_start(), UP, SMALL_BUFF) | 
					
						
							|  |  |  |         dim_word = TextMobject("Dim") | 
					
						
							|  |  |  |         dim_word.next_to(dim_arrows[1].get_start(), UP, MED_LARGE_BUFF) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         dot = Dot().move_to(self.v_count) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             vertices.set_fill, None, 0, | 
					
						
							|  |  |  |             vertices.set_stroke, None, 1, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(ReplacementTransform(dot, lit_vertex)) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(lit_word), | 
					
						
							|  |  |  |             GrowArrow(lit_arrow) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play(*self.get_lit_vertex_animations(lit_vertex)) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(dim_word), | 
					
						
							|  |  |  |             LaggedStart(GrowArrow, dim_arrows) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         self.play(*list(map(FadeOut, [ | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |             lit_word, lit_arrow, dim_word, dim_arrows | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         ]))) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def show_rule_for_lighting(self): | 
					
						
							|  |  |  |         lines = self.lines | 
					
						
							|  |  |  |         regions = self.regions | 
					
						
							|  |  |  |         line_groups = self.line_groups | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         #First region, lines 0, 1, 4, 3 | 
					
						
							|  |  |  |         lines[4].rotate_in_place(np.pi) | 
					
						
							|  |  |  |         region = regions[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play(ShowCreation(lines[0])) | 
					
						
							|  |  |  |         self.play(*self.get_count_change_animations(0, 1, 0)) | 
					
						
							|  |  |  |         self.play(*it.chain( | 
					
						
							|  |  |  |             self.get_lit_vertex_animations(houses[0]), | 
					
						
							|  |  |  |             self.get_count_change_animations(1, 0, 0) | 
					
						
							|  |  |  |         )) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         for line, vertex in (lines[1], houses[1]), (lines[4], utilities[1]): | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 ShowCreation(line), | 
					
						
							|  |  |  |                 *self.get_count_change_animations(0, 1, 0) | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             self.play(*it.chain( | 
					
						
							|  |  |  |                 self.get_lit_vertex_animations(vertex), | 
					
						
							|  |  |  |                 self.get_count_change_animations(1, 0, 0), | 
					
						
							|  |  |  |             )) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             ShowCreation(lines[3], run_time = 2), | 
					
						
							|  |  |  |             *self.get_count_change_animations(0, 1, 0) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(line_groups[0]) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(objects) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(region), | 
					
						
							|  |  |  |             *self.get_count_change_animations(0, 0, 1) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #Next region, lines 2, 7, 8 | 
					
						
							|  |  |  |         region = regions[3] | 
					
						
							|  |  |  |         lines[6].rotate_in_place(np.pi) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for line, vertex in (lines[2], houses[2]), (lines[6], utilities[2]): | 
					
						
							|  |  |  |             self.play(ShowCreation(line), *it.chain( | 
					
						
							|  |  |  |                 self.get_lit_vertex_animations( | 
					
						
							|  |  |  |                     vertex, | 
					
						
							|  |  |  |                     run_time = 2,  | 
					
						
							|  |  |  |                     squish_range = (0.5, 1), | 
					
						
							|  |  |  |                 ), | 
					
						
							|  |  |  |                 self.get_count_change_animations(1, 1, 0) | 
					
						
							|  |  |  |             )) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             ShowCreation(lines[7]), | 
					
						
							|  |  |  |             *self.get_count_change_animations(0, 1, 1) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(line_groups[2]) | 
					
						
							|  |  |  |         self.add_foreground_mobjects(objects) | 
					
						
							|  |  |  |         self.play(FadeIn(region)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     #### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_count_change_animations(self, *changes): | 
					
						
							|  |  |  |         anims = [] | 
					
						
							|  |  |  |         for change, count in zip(changes, self.counts): | 
					
						
							|  |  |  |             if change == 0: | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             new_count = Integer(count.number + 1) | 
					
						
							|  |  |  |             new_count.move_to(count) | 
					
						
							|  |  |  |             anims.append(Transform( | 
					
						
							|  |  |  |                 count, new_count, | 
					
						
							|  |  |  |                 run_time = 2, | 
					
						
							|  |  |  |                 rate_func = squish_rate_func(smooth, 0.5, 1) | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  |             count.number += 1 | 
					
						
							|  |  |  |             anims.append(self.get_plus_one_anim(count)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return anims | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_plus_one_anim(self, count): | 
					
						
							|  |  |  |         plus_one = TexMobject("+1") | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         plus_one.set_color(YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         plus_one.move_to(count) | 
					
						
							|  |  |  |         plus_one.next_to(count, DOWN) | 
					
						
							|  |  |  |         plus_one.generate_target() | 
					
						
							|  |  |  |         plus_one.target.move_to(count) | 
					
						
							|  |  |  |         plus_one.target.set_fill(opacity = 0) | 
					
						
							|  |  |  |         move = MoveToTarget(plus_one, remover = True) | 
					
						
							|  |  |  |         grow = GrowFromCenter(plus_one) | 
					
						
							|  |  |  |         return UpdateFromAlphaFunc( | 
					
						
							|  |  |  |             plus_one, | 
					
						
							|  |  |  |             lambda m, a : ( | 
					
						
							|  |  |  |                 (grow if a < 0.5 else move).update(2*a%1) | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             remover = True, | 
					
						
							|  |  |  |             rate_func = double_smooth, | 
					
						
							|  |  |  |             run_time = 2 | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_lit_vertex_animations(self, vertex, run_time = 1, squish_range = (0, 1)): | 
					
						
							|  |  |  |         line = Line( | 
					
						
							|  |  |  |             LEFT, RIGHT, | 
					
						
							|  |  |  |             stroke_width = 0, | 
					
						
							|  |  |  |             stroke_color = BLACK, | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-08-08 10:30:52 -07:00
										 |  |  |         line.set_width(0.5*vertex.get_width()) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         line.next_to(ORIGIN, buff = 0.75*vertex.get_width()) | 
					
						
							|  |  |  |         lines = VGroup(*[ | 
					
						
							|  |  |  |             line.copy().rotate(angle) | 
					
						
							|  |  |  |             for angle in np.arange(0, 2*np.pi, np.pi/4) | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         lines.move_to(vertex) | 
					
						
							|  |  |  |         random.shuffle(lines.submobjects) | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             LaggedStart( | 
					
						
							|  |  |  |                 ApplyMethod, lines, | 
					
						
							|  |  |  |                 lambda l : (l.set_stroke, YELLOW, 4), | 
					
						
							|  |  |  |                 rate_func = squish_rate_func(there_and_back, *squish_range), | 
					
						
							|  |  |  |                 lag_ratio = 0.75, | 
					
						
							|  |  |  |                 remover = True, | 
					
						
							|  |  |  |                 run_time = run_time | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             ApplyMethod( | 
					
						
							|  |  |  |                 vertex.set_fill, None, 1, | 
					
						
							|  |  |  |                 run_time = run_time, | 
					
						
							|  |  |  |                 rate_func = squish_rate_func(smooth, *squish_range) | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ShowRule(TeacherStudentsScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         new_edge = TextMobject("New edge") | 
					
						
							|  |  |  |         new_vertex = TextMobject("New (lit) vertex") | 
					
						
							|  |  |  |         new_vertex.next_to(new_edge, UP+RIGHT, MED_LARGE_BUFF) | 
					
						
							|  |  |  |         new_region = TextMobject("New region") | 
					
						
							|  |  |  |         new_region.next_to(new_edge, DOWN+RIGHT, MED_LARGE_BUFF) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         VGroup(new_vertex, new_region).shift(RIGHT) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         arrows = VGroup(*[ | 
					
						
							|  |  |  |             Arrow( | 
					
						
							|  |  |  |                 new_edge.get_right(), mob.get_left(),  | 
					
						
							|  |  |  |                 color = WHITE, | 
					
						
							|  |  |  |                 buff = SMALL_BUFF | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-06-02 08:59:26 -04:00
										 |  |  |             for mob in (new_vertex, new_region) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         ]) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         for word, arrow in zip(["Either", "or"], arrows): | 
					
						
							|  |  |  |             word_mob = TextMobject(word) | 
					
						
							|  |  |  |             word_mob.scale(0.65) | 
					
						
							|  |  |  |             word_mob.next_to(ORIGIN, UP, SMALL_BUFF) | 
					
						
							|  |  |  |             word_mob.rotate(arrow.get_angle()) | 
					
						
							|  |  |  |             word_mob.shift(arrow.get_center()) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |             word_mob.set_color(GREEN) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             arrow.add(word_mob) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         new_vertex.set_color(YELLOW) | 
					
						
							|  |  |  |         new_edge.set_color(BLUE) | 
					
						
							|  |  |  |         new_region.set_color(RED) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         rule = VGroup(new_edge, arrows, new_vertex, new_region) | 
					
						
							|  |  |  |         rule.center().to_edge(UP) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         nine_total = TextMobject("(9 total)") | 
					
						
							|  |  |  |         nine_total.next_to(new_edge, DOWN) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             Animation(rule), | 
					
						
							|  |  |  |             self.teacher.change, "raise_right_hand" | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             *["confused"]*3, | 
					
						
							|  |  |  |             look_at_arg = rule | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             Write(nine_total), | 
					
						
							|  |  |  |             self.teacher.change, "happy", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             *["thinking"]*3,  | 
					
						
							|  |  |  |             look_at_arg = rule | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(3) | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ConcludeFiveRegions(LightUpNodes): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         self.setup_regions() | 
					
						
							|  |  |  |         self.setup_counters() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.describe_start_setup() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.show_nine_lines_to_start() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.show_five_to_lit_up_nodes() | 
					
						
							|  |  |  |         self.relate_four_lines_to_regions() | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  |         self.conclude_about_five_regions() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |     def describe_start_setup(self): | 
					
						
							|  |  |  |         to_dim = VGroup(*it.chain(self.houses, self.utilities[1:])) | 
					
						
							|  |  |  |         to_dim.set_stroke(width = 1) | 
					
						
							|  |  |  |         to_dim.set_fill(opacity = 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         full_screen_rect = FullScreenFadeRectangle( | 
					
						
							|  |  |  |             fill_color = LIGHT_GREY, | 
					
						
							|  |  |  |             fill_opacity = 0.25, | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             Indicate(self.v_count), | 
					
						
							|  |  |  |             *self.get_lit_vertex_animations(self.utilities[0]) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn( | 
					
						
							|  |  |  |                 full_screen_rect, | 
					
						
							|  |  |  |                 rate_func = there_and_back, | 
					
						
							|  |  |  |                 remover = True, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             Indicate(self.f_count), | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |             *list(map(Animation, self.mobjects)) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def show_nine_lines_to_start(self): | 
					
						
							|  |  |  |         line_sets = self.get_straight_lines() | 
					
						
							|  |  |  |         line_sets.target = VGroup() | 
					
						
							|  |  |  |         for lines in line_sets: | 
					
						
							|  |  |  |             lines.generate_target() | 
					
						
							|  |  |  |             for line in lines.target: | 
					
						
							|  |  |  |                 line.rotate(-line.get_angle()) | 
					
						
							| 
									
										
										
										
											2018-08-08 10:30:52 -07:00
										 |  |  |                 line.set_width(1.5) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             lines.target.arrange_submobjects(DOWN) | 
					
						
							|  |  |  |             line_sets.target.add(lines.target) | 
					
						
							|  |  |  |         line_sets.target.arrange_submobjects(DOWN) | 
					
						
							|  |  |  |         line_sets.target.center() | 
					
						
							|  |  |  |         line_sets.target.to_edge(RIGHT) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for lines in line_sets: | 
					
						
							|  |  |  |             self.play(LaggedStart(ShowCreation, lines, run_time = 1)) | 
					
						
							|  |  |  |             self.play(MoveToTarget(lines)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         ghost_lines = line_sets.copy() | 
					
						
							|  |  |  |         ghost_lines.fade(0.9) | 
					
						
							|  |  |  |         self.add(ghost_lines, line_sets) | 
					
						
							|  |  |  |         self.side_lines = VGroup(*it.chain(*line_sets)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def show_five_to_lit_up_nodes(self): | 
					
						
							|  |  |  |         side_lines = self.side_lines | 
					
						
							|  |  |  |         lines = self.lines | 
					
						
							|  |  |  |         vertices = VGroup(*it.chain(self.houses, self.utilities)) | 
					
						
							|  |  |  |         line_indices = [0, 1, 4, 6, 7] | 
					
						
							|  |  |  |         vertex_indices = [0, 1, 4, 5, 2] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for li, vi in zip(line_indices, vertex_indices): | 
					
						
							|  |  |  |             side_line = side_lines[li] | 
					
						
							|  |  |  |             line = lines[li] | 
					
						
							|  |  |  |             vertex = vertices[vi] | 
					
						
							|  |  |  |             self.play(ReplacementTransform(side_line, line)) | 
					
						
							|  |  |  |             self.play(*it.chain( | 
					
						
							|  |  |  |                 self.get_count_change_animations(1, 1, 0), | 
					
						
							|  |  |  |                 self.get_lit_vertex_animations(vertex), | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def relate_four_lines_to_regions(self): | 
					
						
							|  |  |  |         f_rect = SurroundingRectangle( | 
					
						
							|  |  |  |             VGroup(self.count_titles[-1], self.f_count) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         on_screen_side_lines = VGroup(*[m for m in self.side_lines if m in self.mobjects]) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         side_lines_rect = SurroundingRectangle(on_screen_side_lines) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         side_lines_rect.set_color(WHITE) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.play(ShowCreation(side_lines_rect)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.play(ReplacementTransform(side_lines_rect, f_rect)) | 
					
						
							|  |  |  |         self.play(FadeOut(f_rect)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def conclude_about_five_regions(self): | 
					
						
							|  |  |  |         lines = self.lines | 
					
						
							|  |  |  |         side_lines = self.side_lines | 
					
						
							|  |  |  |         regions = self.regions[1:] | 
					
						
							|  |  |  |         line_groups = self.line_groups | 
					
						
							|  |  |  |         line_indices = [3, 5, 2] | 
					
						
							|  |  |  |         objects = self.objects | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for region, line_group, li in zip(regions, line_groups, line_indices): | 
					
						
							|  |  |  |             self.play(ReplacementTransform( | 
					
						
							|  |  |  |                 side_lines[li], lines[li] | 
					
						
							|  |  |  |             )) | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 FadeIn(region),  | 
					
						
							|  |  |  |                 Animation(line_group),  | 
					
						
							|  |  |  |                 Animation(objects), | 
					
						
							|  |  |  |                 *self.get_count_change_animations(0, 1, 1) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         #Conclude | 
					
						
							|  |  |  |         words = TextMobject("Last line must \\\\ introduce 5th region") | 
					
						
							|  |  |  |         words.scale(0.8) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         words.set_color(BLUE) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         rect = SurroundingRectangle(self.f_count) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         rect.set_color(BLUE) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         words.next_to(rect, DOWN) | 
					
						
							|  |  |  |         randy = Randolph().flip() | 
					
						
							|  |  |  |         randy.scale(0.5) | 
					
						
							|  |  |  |         randy.next_to(words, RIGHT, SMALL_BUFF, DOWN) | 
					
						
							|  |  |  |         self.play(ShowCreation(rect), Write(words)) | 
					
						
							|  |  |  |         self.play(FadeIn(randy)) | 
					
						
							|  |  |  |         self.play(randy.change, "pondering") | 
					
						
							|  |  |  |         self.play(Blink(randy)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class WhatsWrongWithFive(TeacherStudentsScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.student_says( | 
					
						
							|  |  |  |             "What's wrong with \\\\ 5 regions?", | 
					
						
							|  |  |  |             target_mode = "maybe" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class CyclesHaveAtLeastFour(UtilitiesPuzzleScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_configuration() | 
					
						
							|  |  |  |         houses, utilities = self.houses, self.utilities | 
					
						
							|  |  |  |         vertices = VGroup( | 
					
						
							|  |  |  |             houses[0], utilities[0], | 
					
						
							|  |  |  |             houses[1], utilities[1], houses[0], | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         lines = [ | 
					
						
							|  |  |  |             VectorizedPoint(), | 
					
						
							|  |  |  |             self.get_line(0, 0), | 
					
						
							|  |  |  |             self.get_line(0, 1), | 
					
						
							|  |  |  |             self.get_line(1, 1), | 
					
						
							|  |  |  |             self.get_line(1, 0, self.objects.get_corner(DOWN+LEFT)), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         for line in lines[1::2]: | 
					
						
							|  |  |  |             line.points = line.points[::-1] | 
					
						
							|  |  |  |         arrows = VGroup() | 
					
						
							|  |  |  |         for vertex in vertices: | 
					
						
							|  |  |  |             vect = vertices.get_center() - vertex.get_center() | 
					
						
							|  |  |  |             arrow = Vector(vect, color = WHITE) | 
					
						
							|  |  |  |             arrow.next_to(vertex, -vect, buff = 0) | 
					
						
							|  |  |  |             vertex.arrow = arrow | 
					
						
							|  |  |  |             arrows.add(arrow) | 
					
						
							|  |  |  |         word_strings = [ | 
					
						
							|  |  |  |             "Start at a house", | 
					
						
							|  |  |  |             "Go to a utility", | 
					
						
							|  |  |  |             "Go to another house", | 
					
						
							|  |  |  |             "Go to another utility", | 
					
						
							|  |  |  |             "Back to the start", | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         words = VGroup() | 
					
						
							|  |  |  |         for word_string, arrow in zip(word_strings, arrows): | 
					
						
							|  |  |  |             vect = arrow.get_vector()[1]*UP | 
					
						
							|  |  |  |             word = TextMobject(word_string) | 
					
						
							|  |  |  |             word.next_to(arrow.get_start(), -vect) | 
					
						
							|  |  |  |             words.add(word) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         count = Integer(-1) | 
					
						
							|  |  |  |         count.fade(1) | 
					
						
							|  |  |  |         count.to_edge(UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         last_word = None | 
					
						
							|  |  |  |         last_arrow = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for line, word, arrow in zip(lines, words, arrows): | 
					
						
							|  |  |  |             anims = [] | 
					
						
							|  |  |  |             for mob in last_word, last_arrow: | 
					
						
							|  |  |  |                 if mob: | 
					
						
							|  |  |  |                     anims.append(FadeOut(mob)) | 
					
						
							|  |  |  |             new_count = Integer(count.number + 1) | 
					
						
							|  |  |  |             new_count.move_to(count) | 
					
						
							|  |  |  |             anims += [ | 
					
						
							|  |  |  |                 FadeIn(word), | 
					
						
							|  |  |  |                 GrowArrow(arrow), | 
					
						
							|  |  |  |                 ShowCreation(line), | 
					
						
							|  |  |  |                 FadeOut(count), | 
					
						
							|  |  |  |                 FadeIn(new_count), | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |             self.play(*anims) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |             self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             last_word = word | 
					
						
							|  |  |  |             last_arrow = arrow | 
					
						
							|  |  |  |             count = new_count | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class FiveRegionsFourEdgesEachGraph(Scene): | 
					
						
							|  |  |  |     CONFIG = { | 
					
						
							|  |  |  |         "v_color" : WHITE, | 
					
						
							|  |  |  |         "e_color" : YELLOW, | 
					
						
							|  |  |  |         "f_colors" : (BLUE, RED_E, BLUE_E), | 
					
						
							|  |  |  |         "n_edge_double_count_examples" : 6, | 
					
						
							|  |  |  |         "random_seed" : 1, | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.draw_squares() | 
					
						
							|  |  |  |         self.transition_to_graph() | 
					
						
							|  |  |  |         self.count_edges_per_region() | 
					
						
							|  |  |  |         self.each_edges_has_two_regions() | 
					
						
							|  |  |  |         self.ten_total_edges() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def draw_squares(self): | 
					
						
							|  |  |  |         words = VGroup( | 
					
						
							|  |  |  |             TextMobject("5", "regions"), | 
					
						
							|  |  |  |             TextMobject("4", "edges each"), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         words.arrange_submobjects(DOWN) | 
					
						
							|  |  |  |         words.to_edge(UP) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         words[0][0].set_color(self.f_colors[0]) | 
					
						
							|  |  |  |         words[1][0].set_color(self.e_color) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         squares = VGroup(*[Square() for x in range(5)]) | 
					
						
							|  |  |  |         squares.scale(0.5) | 
					
						
							|  |  |  |         squares.set_stroke(width = 0) | 
					
						
							|  |  |  |         squares.set_fill(opacity = 1) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:59:39 -07:00
										 |  |  |         squares.set_color_by_gradient(*self.f_colors) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         squares.arrange_submobjects(RIGHT, buff = MED_LARGE_BUFF) | 
					
						
							|  |  |  |         squares.next_to(words, DOWN, LARGE_BUFF) | 
					
						
							|  |  |  |         all_edges = VGroup() | 
					
						
							|  |  |  |         all_vertices = VGroup() | 
					
						
							|  |  |  |         for square in squares: | 
					
						
							|  |  |  |             corners = square.get_anchors()[:4] | 
					
						
							|  |  |  |             square.edges = VGroup(*[ | 
					
						
							|  |  |  |                 Line(c1, c2, color = self.e_color) | 
					
						
							|  |  |  |                 for c1, c2 in adjacent_pairs(corners) | 
					
						
							|  |  |  |             ]) | 
					
						
							|  |  |  |             square.vertices = VGroup(*[ | 
					
						
							|  |  |  |                 Dot(color = self.v_color).move_to(c) | 
					
						
							|  |  |  |                 for c in corners | 
					
						
							|  |  |  |             ]) | 
					
						
							|  |  |  |             all_edges.add(*square.edges) | 
					
						
							|  |  |  |             all_vertices.add(*square.vertices) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(words[0]), | 
					
						
							|  |  |  |             LaggedStart(FadeIn, squares, run_time = 1.5) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn(words[1]), | 
					
						
							|  |  |  |             LaggedStart(ShowCreation, all_edges), | 
					
						
							|  |  |  |             LaggedStart(GrowFromCenter, all_vertices), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.add_foreground_mobjects(words) | 
					
						
							|  |  |  |         self.set_variables_as_attrs(words, squares) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def transition_to_graph(self): | 
					
						
							|  |  |  |         squares = self.squares | 
					
						
							|  |  |  |         words = self.words | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         points = np.array([ | 
					
						
							|  |  |  |             UP+LEFT, | 
					
						
							|  |  |  |             UP+RIGHT, | 
					
						
							|  |  |  |             DOWN+RIGHT, | 
					
						
							|  |  |  |             DOWN+LEFT, | 
					
						
							|  |  |  |             3*(UP+RIGHT), | 
					
						
							|  |  |  |             3*(DOWN+LEFT), | 
					
						
							|  |  |  |             3*(DOWN+RIGHT), | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         points *= 0.75 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         regions = VGroup(*[ | 
					
						
							|  |  |  |             Square().set_anchor_points( | 
					
						
							|  |  |  |                 points[indices], mode = "corners" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             for indices in [ | 
					
						
							|  |  |  |                 [0, 1, 2, 3], | 
					
						
							|  |  |  |                 [0, 4, 2, 1], | 
					
						
							|  |  |  |                 [5, 0, 3, 2], | 
					
						
							|  |  |  |                 [5, 2, 4, 6], | 
					
						
							|  |  |  |                 [6, 4, 0, 5], | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         regions.set_stroke(width = 0) | 
					
						
							|  |  |  |         regions.set_fill(opacity = 1) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:59:39 -07:00
										 |  |  |         regions.set_color_by_gradient(*self.f_colors) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         all_edges = VGroup() | 
					
						
							|  |  |  |         all_movers = VGroup() | 
					
						
							|  |  |  |         for region, square in zip(regions, squares): | 
					
						
							|  |  |  |             corners = region.get_anchors()[:4] | 
					
						
							|  |  |  |             region.edges = VGroup(*[ | 
					
						
							|  |  |  |                 Line(c1, c2, color = self.e_color) | 
					
						
							|  |  |  |                 for c1, c2 in adjacent_pairs(corners) | 
					
						
							|  |  |  |             ]) | 
					
						
							|  |  |  |             all_edges.add(*region.edges) | 
					
						
							|  |  |  |             region.vertices = VGroup(*[ | 
					
						
							|  |  |  |                 Dot(color = self.v_color).move_to(c) | 
					
						
							|  |  |  |                 for c in corners | 
					
						
							|  |  |  |             ]) | 
					
						
							|  |  |  |             mover = VGroup( | 
					
						
							|  |  |  |                 square, square.edges, square.vertices, | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             mover.target = VGroup( | 
					
						
							|  |  |  |                 region, region.edges, region.vertices | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             all_movers.add(mover) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         back_region = FullScreenFadeRectangle() | 
					
						
							|  |  |  |         back_region.set_fill(regions[-1].get_color(), 0.5) | 
					
						
							|  |  |  |         regions[-1].set_fill(opacity = 0) | 
					
						
							|  |  |  |         back_region.add(regions[-1].copy().set_fill(BLACK, 1)) | 
					
						
							|  |  |  |         back_region.edges = regions[-1].edges | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeIn( | 
					
						
							|  |  |  |                 back_region, | 
					
						
							|  |  |  |                 rate_func = squish_rate_func(smooth, 0.7, 1), | 
					
						
							|  |  |  |                 run_time = 3, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |             LaggedStart( | 
					
						
							|  |  |  |                 MoveToTarget, all_movers, | 
					
						
							|  |  |  |                 run_time = 3, | 
					
						
							|  |  |  |                 replace_mobject_with_target_in_scene = True, | 
					
						
							|  |  |  |             ), | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.set_variables_as_attrs( | 
					
						
							|  |  |  |             regions, all_edges, back_region, | 
					
						
							|  |  |  |             graph = VGroup(*[m.target for m in all_movers]) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def count_edges_per_region(self): | 
					
						
							|  |  |  |         all_edges = self.all_edges | 
					
						
							|  |  |  |         back_region = self.back_region | 
					
						
							|  |  |  |         regions = self.regions | 
					
						
							|  |  |  |         graph = self.graph | 
					
						
							|  |  |  |         all_vertices = VGroup(*[r.vertices for r in regions]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ghost_edges = all_edges.copy() | 
					
						
							|  |  |  |         ghost_edges.set_stroke(LIGHT_GREY, 1) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         count = Integer(0) | 
					
						
							|  |  |  |         count.scale(2) | 
					
						
							|  |  |  |         count.next_to(graph, RIGHT, buff = 2) | 
					
						
							|  |  |  |         count.set_fill(YELLOW, opacity = 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         last_region = VGroup(back_region, *regions[1:]) | 
					
						
							|  |  |  |         last_region.add(all_edges) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for region in list(regions[:-1]) + [back_region]: | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 FadeIn(region), | 
					
						
							|  |  |  |                 Animation(ghost_edges), | 
					
						
							|  |  |  |                 FadeOut(last_region), | 
					
						
							|  |  |  |                 Animation(count), | 
					
						
							|  |  |  |                 Animation(all_vertices), | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             for edge in region.edges: | 
					
						
							|  |  |  |                 new_count = Integer(count.number + 1) | 
					
						
							|  |  |  |                 new_count.replace(count, dim_to_match = 1) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |                 new_count.set_color(count.get_color()) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |                 self.play( | 
					
						
							|  |  |  |                     ShowCreation(edge), | 
					
						
							|  |  |  |                     FadeOut(count), | 
					
						
							|  |  |  |                     FadeIn(new_count), | 
					
						
							|  |  |  |                     run_time = 0.5 | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 count = new_count | 
					
						
							|  |  |  |             last_region = VGroup(region, region.edges) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.add_foreground_mobjects(count) | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             FadeOut(last_region), | 
					
						
							|  |  |  |             Animation(ghost_edges), | 
					
						
							|  |  |  |             Animation(all_vertices), | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.set_variables_as_attrs(count, ghost_edges, all_vertices) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def each_edges_has_two_regions(self): | 
					
						
							|  |  |  |         regions = list(self.regions[:-1]) + [self.back_region] | 
					
						
							|  |  |  |         back_region = self.back_region | 
					
						
							|  |  |  |         self.add_foreground_mobjects(self.ghost_edges, self.all_vertices) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         edge_region_pair_groups = [] | 
					
						
							|  |  |  |         for r1, r2 in it.combinations(regions, 2): | 
					
						
							|  |  |  |             for e1 in r1.edges: | 
					
						
							|  |  |  |                 for e2 in r2.edges: | 
					
						
							|  |  |  |                     diff = e1.get_center()-e2.get_center() | 
					
						
							|  |  |  |                     if np.linalg.norm(diff) < 0.01: | 
					
						
							|  |  |  |                         edge_region_pair_groups.append(VGroup( | 
					
						
							|  |  |  |                             e1, r1, r2 | 
					
						
							|  |  |  |                         )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for x in range(self.n_edge_double_count_examples): | 
					
						
							|  |  |  |             edge, r1, r2 = random.choice(edge_region_pair_groups) | 
					
						
							|  |  |  |             if r2 is back_region: | 
					
						
							|  |  |  |                 #Flip again, maybe you're still unlucky, maybe not | 
					
						
							|  |  |  |                 edge, r1, r2 = random.choice(edge_region_pair_groups) | 
					
						
							|  |  |  |             self.play(ShowCreation(edge)) | 
					
						
							|  |  |  |             self.add_foreground_mobjects(edge) | 
					
						
							|  |  |  |             self.play(FadeIn(r1), run_time = 0.5) | 
					
						
							|  |  |  |             self.play(FadeIn(r2), Animation(r1), run_time = 0.5) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |             self.wait(0.5) | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |             self.play(*list(map(FadeOut, [r2, r1, edge])), run_time = 0.5) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             self.remove_foreground_mobjects(edge) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def ten_total_edges(self): | 
					
						
							|  |  |  |         double_count = self.count | 
					
						
							|  |  |  |         brace = Brace(double_count, UP) | 
					
						
							|  |  |  |         words = brace.get_text("Double-counts \\\\ edges") | 
					
						
							|  |  |  |         regions = self.regions | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         edges = VGroup(*it.chain( | 
					
						
							|  |  |  |             regions[0].edges, | 
					
						
							|  |  |  |             regions[-1].edges, | 
					
						
							|  |  |  |             [regions[1].edges[1]], | 
					
						
							|  |  |  |             [regions[2].edges[3]], | 
					
						
							|  |  |  |         )) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         count = Integer(0) | 
					
						
							|  |  |  |         count.scale(2) | 
					
						
							|  |  |  |         count.set_fill(WHITE, 0) | 
					
						
							|  |  |  |         count.next_to(self.graph, LEFT, LARGE_BUFF) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play( | 
					
						
							|  |  |  |             GrowFromCenter(brace), | 
					
						
							|  |  |  |             Write(words) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         for edge in edges: | 
					
						
							|  |  |  |             new_count = Integer(count.number + 1) | 
					
						
							|  |  |  |             new_count.replace(count, dim_to_match = 1) | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 ShowCreation(edge), | 
					
						
							|  |  |  |                 FadeOut(count), | 
					
						
							|  |  |  |                 FadeIn(new_count), | 
					
						
							|  |  |  |                 run_time = 0.5 | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             count = new_count | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class EulersFormulaForGeneralPlanarGraph(LightUpNodes, ThreeDScene): | 
					
						
							|  |  |  |     CONFIG = { | 
					
						
							|  |  |  |         "vertices_word" : "Vertices" | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.setup_counters() | 
					
						
							|  |  |  |         self.show_creation_of_graph() | 
					
						
							|  |  |  |         self.show_formula() | 
					
						
							|  |  |  |         self.transform_into_cube() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def show_creation_of_graph(self): | 
					
						
							|  |  |  |         points = np.array([ | 
					
						
							|  |  |  |             UP+LEFT, | 
					
						
							|  |  |  |             UP+RIGHT, | 
					
						
							|  |  |  |             DOWN+RIGHT, | 
					
						
							|  |  |  |             DOWN+LEFT, | 
					
						
							|  |  |  |             3*(UP+LEFT), | 
					
						
							|  |  |  |             3*(UP+RIGHT), | 
					
						
							|  |  |  |             3*(DOWN+RIGHT), | 
					
						
							|  |  |  |             3*(DOWN+LEFT), | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         points *= 0.75 | 
					
						
							|  |  |  |         points += DOWN | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |         vertices = VGroup(*list(map(Dot, points))) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         vertices.set_color(YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         edges = VGroup(*[ | 
					
						
							|  |  |  |             VGroup(*[ | 
					
						
							|  |  |  |                 Line(p1, p2, color = WHITE) | 
					
						
							|  |  |  |                 for p2 in points | 
					
						
							|  |  |  |             ]) | 
					
						
							|  |  |  |             for p1 in points | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         regions = self.get_cube_faces(points) | 
					
						
							|  |  |  |         regions.set_stroke(width = 0) | 
					
						
							|  |  |  |         regions.set_fill(opacity = 1) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:59:39 -07:00
										 |  |  |         regions.set_color_by_gradient(GREEN, RED, BLUE_E) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         regions[-1].set_fill(opacity = 0) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         pairs = [ | 
					
						
							|  |  |  |             (edges[0][1], vertices[1]), | 
					
						
							|  |  |  |             (edges[1][2], vertices[2]), | 
					
						
							|  |  |  |             (edges[2][6], vertices[6]), | 
					
						
							|  |  |  |             (edges[6][5], vertices[5]), | 
					
						
							|  |  |  |             (edges[5][1], regions[2]), | 
					
						
							|  |  |  |             (edges[0][4], vertices[4]), | 
					
						
							|  |  |  |             (edges[4][5], regions[1]), | 
					
						
							|  |  |  |             (edges[0][3], vertices[3]), | 
					
						
							|  |  |  |             (edges[3][2], regions[0]), | 
					
						
							|  |  |  |             (edges[4][7], vertices[7]), | 
					
						
							|  |  |  |             (edges[7][3], regions[4]), | 
					
						
							|  |  |  |             (edges[7][6], regions[3]), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.add_foreground_mobjects(vertices[0]) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         for edge, obj in pairs: | 
					
						
							|  |  |  |             anims = [ShowCreation(edge)] | 
					
						
							|  |  |  |             if obj in vertices: | 
					
						
							|  |  |  |                 obj.save_state() | 
					
						
							|  |  |  |                 obj.move_to(edge.get_start()) | 
					
						
							|  |  |  |                 anims.append(ApplyMethod(obj.restore)) | 
					
						
							|  |  |  |                 anims += self.get_count_change_animations(1, 1, 0) | 
					
						
							|  |  |  |                 self.add_foreground_mobjects(obj) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 anims = [FadeIn(obj)] + anims | 
					
						
							|  |  |  |                 anims += self.get_count_change_animations(0, 1, 1) | 
					
						
							|  |  |  |             self.play(*anims) | 
					
						
							|  |  |  |             self.add_foreground_mobjects(edge) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.set_variables_as_attrs(edges, vertices, regions) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def show_formula(self): | 
					
						
							|  |  |  |         counts = VGroup(*self.counts) | 
					
						
							|  |  |  |         count_titles = VGroup(*self.count_titles) | 
					
						
							|  |  |  |         groups = [count_titles, counts] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for group in groups: | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |             group.symbols = VGroup(*list(map(TexMobject, ["-", "+", "="]))) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             group.generate_target() | 
					
						
							| 
									
										
										
										
											2018-08-09 17:56:05 -07:00
										 |  |  |             line = VGroup(*it.chain(*list(zip(group.target, group.symbols)))) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |             line.arrange_submobjects(RIGHT) | 
					
						
							|  |  |  |             line.to_edge(UP, buff = MED_SMALL_BUFF) | 
					
						
							|  |  |  |         VGroup(counts.target, counts.symbols).shift(0.75*DOWN) | 
					
						
							|  |  |  |         for mob in count_titles.target: | 
					
						
							|  |  |  |             mob[-1].fade(1) | 
					
						
							|  |  |  |         count_titles.symbols.shift(0.5*SMALL_BUFF*UP) | 
					
						
							|  |  |  |         twos = VGroup(*[ | 
					
						
							|  |  |  |             TexMobject("2").next_to(group.symbols, RIGHT) | 
					
						
							|  |  |  |             for group in groups | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         twos.shift(0.5*SMALL_BUFF*UP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         words = TextMobject("``Euler's characteristic formula''") | 
					
						
							|  |  |  |         words.next_to(counts.target, DOWN) | 
					
						
							|  |  |  |         words.shift(MED_LARGE_BUFF*RIGHT) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         words.set_color(YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         for group in groups: | 
					
						
							|  |  |  |             self.play( | 
					
						
							|  |  |  |                 MoveToTarget(group), | 
					
						
							|  |  |  |                 Write(group.symbols) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.play(Write(twos)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.play(Write(words)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         self.top_formula = VGroup(count_titles, count_titles.symbols, twos[0]) | 
					
						
							|  |  |  |         self.bottom_formula = VGroup(counts, counts.symbols, twos[1]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def transform_into_cube(self): | 
					
						
							|  |  |  |         regions = self.regions | 
					
						
							|  |  |  |         points = np.array([ | 
					
						
							|  |  |  |             UP+LEFT, | 
					
						
							|  |  |  |             UP+RIGHT, | 
					
						
							|  |  |  |             DOWN+RIGHT, | 
					
						
							|  |  |  |             DOWN+LEFT, | 
					
						
							|  |  |  |             UP+LEFT+2*IN, | 
					
						
							|  |  |  |             UP+RIGHT+2*IN, | 
					
						
							|  |  |  |             DOWN+RIGHT+2*IN, | 
					
						
							|  |  |  |             DOWN+LEFT+2*IN, | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         cube = self.get_cube_faces(points) | 
					
						
							|  |  |  |         cube.shift(OUT) | 
					
						
							|  |  |  |         cube.rotate_in_place(np.pi/12, RIGHT) | 
					
						
							|  |  |  |         cube.rotate_in_place(np.pi/6, UP) | 
					
						
							|  |  |  |         cube.shift(MED_LARGE_BUFF*DOWN) | 
					
						
							|  |  |  |         shade_in_3d(cube) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for face, region in zip(cube, regions): | 
					
						
							|  |  |  |             face.set_fill(region.get_color(), opacity = 0.8) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.remove(self.edges) | 
					
						
							|  |  |  |         regions.set_stroke(WHITE, 3) | 
					
						
							|  |  |  |         cube.set_stroke(WHITE, 3) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         new_formula = TexMobject("V - E + F = 2") | 
					
						
							|  |  |  |         new_formula.to_edge(UP, buff = MED_SMALL_BUFF) | 
					
						
							|  |  |  |         new_formula.align_to(self.bottom_formula, RIGHT) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play(FadeOut(self.vertices)) | 
					
						
							|  |  |  |         self.play(ReplacementTransform(regions, cube, run_time = 2)) | 
					
						
							|  |  |  |         cube.sort_submobjects(lambda p : -p[2]) | 
					
						
							| 
									
										
										
										
											2018-03-31 15:37:23 -07:00
										 |  |  |         self.add(ContinualRotation(cube, axis = UP, in_place = False)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(3) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.play( | 
					
						
							|  |  |  |             FadeOut(self.top_formula), | 
					
						
							|  |  |  |             FadeIn(new_formula) | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(10) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def get_cube_faces(self, eight_points): | 
					
						
							|  |  |  |         return VGroup(*[ | 
					
						
							|  |  |  |             Square().set_anchor_points( | 
					
						
							|  |  |  |                 eight_points[indices], mode = "corners" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             for indices in [ | 
					
						
							|  |  |  |                 [0, 1, 2, 3], | 
					
						
							|  |  |  |                 [0, 4, 5, 1], | 
					
						
							|  |  |  |                 [1, 5, 6, 2], | 
					
						
							|  |  |  |                 [2, 6, 7, 3], | 
					
						
							|  |  |  |                 [3, 7, 4, 0], | 
					
						
							|  |  |  |                 [4, 5, 6, 7], | 
					
						
							|  |  |  |             ] | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class YouGaveFriendsAnImpossiblePuzzle(TeacherStudentsScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.student_says( | 
					
						
							|  |  |  |             "You gave friends \\\\ an impossible puzzle?", | 
					
						
							|  |  |  |             target_mode = "sassy", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             "angry", "sassy", "angry", | 
					
						
							|  |  |  |             added_anims = [self.teacher.change, "happy"] | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class FunnyStory(TeacherStudentsScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.teacher_says("Funny story", target_mode = "hooray") | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.change_student_modes( | 
					
						
							|  |  |  |             *["happy"]*3, | 
					
						
							|  |  |  |             added_anims = [RemovePiCreatureBubble( | 
					
						
							|  |  |  |                 self.teacher, | 
					
						
							|  |  |  |                 target_mode = "raise_right_hand" | 
					
						
							|  |  |  |             )], | 
					
						
							|  |  |  |             look_at_arg = UP+2*RIGHT | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(5) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class QuestionWrapper(Scene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         question = TextMobject( | 
					
						
							|  |  |  |             "Where", "\\emph{specifically}", "does\\\\",  | 
					
						
							|  |  |  |             "this proof break down?", | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         question.to_edge(UP) | 
					
						
							| 
									
										
										
										
											2018-03-30 11:51:31 -07:00
										 |  |  |         question.set_color_by_tex("specifically", YELLOW) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         screen_rect = ScreenRectangle(height = 5.5) | 
					
						
							|  |  |  |         screen_rect.next_to(question, DOWN) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         self.play(ShowCreation(screen_rect)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         for word in question: | 
					
						
							|  |  |  |             self.play(LaggedStart( | 
					
						
							|  |  |  |                 FadeIn, word, | 
					
						
							|  |  |  |                 run_time = 0.05*len(word) | 
					
						
							|  |  |  |             )) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |             self.wait(0.05) | 
					
						
							|  |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Homework(TeacherStudentsScene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         self.teacher_says("Consider this \\\\ homework") | 
					
						
							|  |  |  |         self.change_student_modes(*["pondering"]*3) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.student_says( | 
					
						
							|  |  |  |             "$V-E+F=0$ on \\\\ a torus!", | 
					
						
							|  |  |  |             target_mode = "hooray" | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  |         self.teacher_says("Not good enough!", target_mode = "surprised") | 
					
						
							|  |  |  |         self.change_student_modes(*["confused"]*3) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait(2) | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class WantToLearnMore(Scene): | 
					
						
							|  |  |  |     def construct(self): | 
					
						
							|  |  |  |         text = TextMobject("Want to learn more?") | 
					
						
							|  |  |  |         self.play(Write(text)) | 
					
						
							| 
									
										
										
										
											2018-01-15 19:15:05 -08:00
										 |  |  |         self.wait() | 
					
						
							| 
									
										
										
										
											2017-12-24 14:29:31 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class PatreonThanks(PatreonEndScreen): | 
					
						
							|  |  |  |     CONFIG = { | 
					
						
							|  |  |  |         "specific_patrons" : [ | 
					
						
							|  |  |  |             "Randall Hunt", | 
					
						
							|  |  |  |             "Desmos", | 
					
						
							|  |  |  |             "Burt Humburg", | 
					
						
							|  |  |  |             "CrypticSwarm", | 
					
						
							|  |  |  |             "Juan Benet", | 
					
						
							|  |  |  |             "David Kedmey", | 
					
						
							|  |  |  |             "Ali Yahya", | 
					
						
							|  |  |  |             "Mayank M. Mehrotra", | 
					
						
							|  |  |  |             "Lukas Biewald", | 
					
						
							|  |  |  |             "Yana Chernobilsky", | 
					
						
							|  |  |  |             "Kaustuv DeBiswas", | 
					
						
							|  |  |  |             "Kathryn Schmiedicke", | 
					
						
							|  |  |  |             "Yu Jun", | 
					
						
							|  |  |  |             "Dave Nicponski", | 
					
						
							|  |  |  |             "Damion Kistler", | 
					
						
							|  |  |  |             "Jordan Scales", | 
					
						
							|  |  |  |             "Markus Persson", | 
					
						
							|  |  |  |             "Egor Gumenuk", | 
					
						
							|  |  |  |             "Yoni Nazarathy", | 
					
						
							|  |  |  |             "Ryan Atallah", | 
					
						
							|  |  |  |             "Joseph John Cox", | 
					
						
							|  |  |  |             "Luc Ritchie", | 
					
						
							|  |  |  |             "Onuralp Soylemez", | 
					
						
							|  |  |  |             "John Bjorn Nelson", | 
					
						
							|  |  |  |             "Yaw Etse", | 
					
						
							|  |  |  |             "David Barbetta", | 
					
						
							|  |  |  |             "Julio Cesar Campo Neto", | 
					
						
							|  |  |  |             "Waleed Hamied", | 
					
						
							|  |  |  |             "Oliver Steele", | 
					
						
							|  |  |  |             "George Chiesa", | 
					
						
							|  |  |  |             "supershabam", | 
					
						
							|  |  |  |             "James Park", | 
					
						
							|  |  |  |             "Samantha D. Suplee", | 
					
						
							|  |  |  |             "Delton Ding", | 
					
						
							|  |  |  |             "Thomas Tarler", | 
					
						
							|  |  |  |             "Jonathan Eppele", | 
					
						
							|  |  |  |             "Isak Hietala", | 
					
						
							|  |  |  |             "1stViewMaths", | 
					
						
							|  |  |  |             "Jacob Magnuson", | 
					
						
							|  |  |  |             "Mark Govea", | 
					
						
							|  |  |  |             "Dagan Harrington", | 
					
						
							|  |  |  |             "Clark Gaebel", | 
					
						
							|  |  |  |             "Eric Chow", | 
					
						
							|  |  |  |             "Mathias Jansson", | 
					
						
							|  |  |  |             "David Clark", | 
					
						
							|  |  |  |             "Michael Gardner", | 
					
						
							|  |  |  |             "Mads Elvheim", | 
					
						
							|  |  |  |             "Erik Sundell", | 
					
						
							|  |  |  |             "Awoo", | 
					
						
							|  |  |  |             "Dr. David G. Stork", | 
					
						
							|  |  |  |             "Tianyu Ge", | 
					
						
							|  |  |  |             "Ted Suzman", | 
					
						
							|  |  |  |             "Linh Tran", | 
					
						
							|  |  |  |             "Andrew Busey", | 
					
						
							|  |  |  |             "John Haley", | 
					
						
							|  |  |  |             "Ankalagon", | 
					
						
							|  |  |  |             "Eric Lavault", | 
					
						
							|  |  |  |             "Boris Veselinovich", | 
					
						
							|  |  |  |             "Julian Pulgarin", | 
					
						
							|  |  |  |             "Jeff Linse", | 
					
						
							|  |  |  |             "Cooper Jones", | 
					
						
							|  |  |  |             "Ryan Dahl", | 
					
						
							|  |  |  |             "Robert Teed", | 
					
						
							|  |  |  |             "Jason Hise", | 
					
						
							|  |  |  |             "Meshal Alshammari", | 
					
						
							|  |  |  |             "Bernd Sing", | 
					
						
							|  |  |  |             "James Thornton", | 
					
						
							|  |  |  |             "Mustafa Mahdi", | 
					
						
							|  |  |  |             "Mathew Bramson", | 
					
						
							|  |  |  |             "Jerry Ling", | 
					
						
							|  |  |  |             "Shimin  Kuang", | 
					
						
							|  |  |  |             "Rish Kundalia", | 
					
						
							|  |  |  |             "Achille Brighton", | 
					
						
							|  |  |  |             "Ripta Pasay", | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-21 13:43:27 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 |