# SOLVING "LIGHTS OUT" VIA LINEAR ALGEBRA # By Nathaniel Johnston (March 2024) # Manim v0.18.0 (https://docs.manim.community/en/stable/index.html) code for YouTube video # Provided as-is in the hope that maybe it's useful for someone. No warrany, guarantees, etc. # Code is probably a disaster because the goal is just to get it working as quickly as possible, not to make pretty/flexible code. from manim import * import random import math # COLORS (just for easy reference): # orange border: #fa7d19 # orange fill: same, but opacity is 0.4 # blue border: #2d70b3 # blue fill: same, but opacity is 0.4 # Like linspace, but with a slower change near the endpoints and steeper change near the middle of the interval [x,y] def smoothspace(x, y, num = 50): arr = np.linspace(0, 1, num) for i,v in enumerate(arr): t = (math.sin(v*PI - PI/2) + 1)/2 # smooth out the curve on [0,1] arr[i] = (1-t)*x + t*y return arr class CreateSceneA(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) # Draw 3x3 lights out loBorderFill = Polygon( np.array([-1.6, -1.6, 0]), np.array([-1.6, 1.6, 0]), np.array([1.6, 1.6, 0]), np.array([1.6, -1.6, 0]), np.array([-1.6, -1.6, 0]), np.array([-1.5, -1.5, 0]), np.array([1.5, -1.5, 0]), np.array([1.5, 1.5, 0]), np.array([-1.5, 1.5, 0]), np.array([-1.5, -1.5, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=3.2, height=3.2) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=3, height=3) vLin1 = Line(start=[-0.5, 1.5, 0], end=[-0.5, -1.5, 0], color=BLACK, stroke_width=1) vLin2 = Line(start=[0.5, 1.5, 0], end=[0.5, -1.5, 0], color=BLACK, stroke_width=1) hLin1 = Line(start=[-1.5, 0.5, 0], end=[1.5, 0.5, 0], color=BLACK, stroke_width=1) hLin2 = Line(start=[-1.5, -0.5, 0], end=[1.5, -0.5, 0], color=BLACK, stroke_width=1) loGrid = VGroup(loOuter, loBorder, vLin1, vLin2, hLin1, hLin2) loGrid.z_index = 500 # keep grid in front of everything except for the cursor self.play(Create(loGrid), FadeIn(loBorderFill), run_time = 1.5) # All buttons on to start butSz = 0.9 loBut1 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([-1,1,0]) loBut2 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([0,1,0]) loBut3 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([1,1,0]) loBut4 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([-1,0,0]) loBut5 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz) loBut6 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([1,0,0]) loBut7 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([-1,-1,0]) loBut8 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([0,-1,0]) loBut9 = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([1,-1,0]) loButtons = VGroup(loBut1, loBut2, loBut3, loBut4, loBut5, loBut6, loBut7, loBut8, loBut9) loButtons.z_index = 550 self.play(FadeIn(loButtons), run_time = 1) self.wait(1) # illustrate what happens if we click at the top-left mouseMoveAnimate(self, mCursor, -1, 1) # highlight the 3 cells that will be affected cellHighlightBorder = Polygon( np.array([-1.5, 1.5, 0]), np.array([0.5, 1.5, 0]), np.array([0.5, 0.5, 0]), np.array([-0.5, 0.5, 0]), np.array([-0.5, -0.5, 0]), np.array([-1.5, -0.5, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0, stroke_width=8) cellHighlightBorder.z_index = 999 loBut1.z_index = 998 loBut2.z_index = 998 loBut4.z_index = 998 whiteOpacityCover = Rectangle(fill_color=WHITE, fill_opacity=0.5, color=WHITE, stroke_width=0, width=15, height=9) whiteOpacityCover.z_index = 600 # so it fades out everything except for the cursor and the new (temporary) border self.play(Create(cellHighlightBorder), FadeIn(whiteOpacityCover)) self.wait(1) self.play(Uncreate(cellHighlightBorder), FadeOut(whiteOpacityCover)) self.wait(1) loBut1.z_index = 550 loBut2.z_index = 550 loBut4.z_index = 550 # click loBut1.set_fill(color = "#173959", opacity = 0.4) loBut2.set_fill(color = "#173959", opacity = 0.4) loBut4.set_fill(color = "#173959", opacity = 0.4) mouseClickAnimate(self, mCursor) # illustrate what happens if we click at the middle-left mouseMoveAnimate(self, mCursor, -1, 0) # highlight the 4 cells that will be affected cellHighlightBorder = Polygon( np.array([-1.5, 1.5, 0]), np.array([-0.5, 1.5, 0]), np.array([-0.5, 0.5, 0]), np.array([0.5, 0.5, 0]), np.array([0.5, -0.5, 0]), np.array([-0.5, -0.5, 0]), np.array([-0.5, -1.5, 0]), np.array([-1.5, -1.5, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0, stroke_width=8) cellHighlightBorder.z_index = 999 loBut1.z_index = 998 loBut4.z_index = 998 loBut5.z_index = 998 loBut7.z_index = 998 whiteOpacityCover = Rectangle(fill_color=WHITE, fill_opacity=0.5, color=WHITE, stroke_width=0, width=15, height=9) whiteOpacityCover.z_index = 600 # so it fades out everything except for the cursor and the new (temporary) border self.play(Create(cellHighlightBorder), FadeIn(whiteOpacityCover)) self.wait(1) self.play(Uncreate(cellHighlightBorder), FadeOut(whiteOpacityCover)) self.wait(1) loBut1.z_index = 550 loBut4.z_index = 550 loBut5.z_index = 550 loBut7.z_index = 550 # click loBut1.set_fill(color = "#FFFF00", opacity = 0.4) loBut4.set_fill(color = "#FFFF00", opacity = 0.4) loBut5.set_fill(color = "#173959", opacity = 0.4) loBut7.set_fill(color = "#173959", opacity = 0.4) mouseClickAnimate(self, mCursor) # click again to toggle back loBut1.set_fill(color = "#173959", opacity = 0.4) loBut4.set_fill(color = "#173959", opacity = 0.4) loBut5.set_fill(color = "#FFFF00", opacity = 0.4) loBut7.set_fill(color = "#FFFF00", opacity = 0.4) mouseClickAnimate(self, mCursor) # now solve the 3x3: top-right, then middle, then bottom-left then bottom-right # Top-right mouseMoveAnimate(self, mCursor, 1, 1) loBut2.set_fill(color = "#FFFF00", opacity = 0.4) loBut3.set_fill(color = "#173959", opacity = 0.4) loBut6.set_fill(color = "#173959", opacity = 0.4) mouseClickAnimate(self, mCursor) # Middle mouseMoveAnimate(self, mCursor, 0, 0) loBut2.set_fill(color = "#173959", opacity = 0.4) loBut4.set_fill(color = "#FFFF00", opacity = 0.4) loBut5.set_fill(color = "#173959", opacity = 0.4) loBut6.set_fill(color = "#FFFF00", opacity = 0.4) loBut8.set_fill(color = "#173959", opacity = 0.4) mouseClickAnimate(self, mCursor) # Bottom-left mouseMoveAnimate(self, mCursor, -1, -1) loBut4.set_fill(color = "#173959", opacity = 0.4) loBut7.set_fill(color = "#173959", opacity = 0.4) loBut8.set_fill(color = "#FFFF00", opacity = 0.4) mouseClickAnimate(self, mCursor) # Bottom-right mouseMoveAnimate(self, mCursor, 1, -1) loBut6.set_fill(color = "#173959", opacity = 0.4) loBut8.set_fill(color = "#173959", opacity = 0.4) loBut9.set_fill(color = "#173959", opacity = 0.4) mouseClickAnimate(self, mCursor) class CreateSceneB(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) # Draw 5x5 lights out loBorderFill = Polygon( np.array([-2.6, -2.6, 0]), np.array([-2.6, 2.6, 0]), np.array([2.6, 2.6, 0]), np.array([2.6, -2.6, 0]), np.array([-2.6, -2.6, 0]), np.array([-2.5, -2.5, 0]), np.array([2.5, -2.5, 0]), np.array([2.5, 2.5, 0]), np.array([-2.5, 2.5, 0]), np.array([-2.5, -2.5, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=5.2, height=5.2) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=5, height=5) vLin1 = Line(start=[-1.5, 2.5, 0], end=[-1.5, -2.5, 0], color=BLACK, stroke_width=1) vLin2 = Line(start=[-0.5, 2.5, 0], end=[-0.5, -2.5, 0], color=BLACK, stroke_width=1) vLin3 = Line(start=[0.5, 2.5, 0], end=[0.5, -2.5, 0], color=BLACK, stroke_width=1) vLin4 = Line(start=[1.5, 2.5, 0], end=[1.5, -2.5, 0], color=BLACK, stroke_width=1) hLin1 = Line(start=[-2.5, 1.5, 0], end=[2.5, 1.5, 0], color=BLACK, stroke_width=1) hLin2 = Line(start=[-2.5, 0.5, 0], end=[2.5, 0.5, 0], color=BLACK, stroke_width=1) hLin3 = Line(start=[-2.5, -0.5, 0], end=[2.5, -0.5, 0], color=BLACK, stroke_width=1) hLin4 = Line(start=[-2.5, -1.5, 0], end=[2.5, -1.5, 0], color=BLACK, stroke_width=1) loGrid = VGroup(loOuter, loBorder, vLin1, vLin2, vLin3, vLin4, hLin1, hLin2, hLin3, hLin4) loGrid.z_index = 500 # keep grid in front of everything except for the cursor self.play(Create(loGrid), FadeIn(loBorderFill), run_time = 1.5) # All buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * 5 for i in range(5)] # initialize the array for i in range(5): for j in range(5): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-2,j-2,0]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 self.play(FadeIn(loButtons), run_time = 1) self.wait(1) # Solve the 5x5 mouseMoveAnimate(self, mCursor, -2, -2, 0.5, 0.1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 0, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -1, -2, 0.2, 0.1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -2, -1, 0.2, 0.1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -1, -1, 0.2, 0.1) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 1, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 1, -1, 0.2, 0.1) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 4, 1) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 3, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 2, -1, 0.2, 0.1) toggleLOBut(loBut, 4, 1) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 4, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 0, 0, 0.2, 0.1) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 2, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 1, 0, 0.2, 0.1) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 3, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 2, 0, 0.2, 0.1) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 4, 1) toggleLOBut(loBut, 4, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -1, 1, 0.2, 0.1) toggleLOBut(loBut, 1, 3) toggleLOBut(loBut, 0, 3) toggleLOBut(loBut, 2, 3) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 1, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 0, 1, 0.2, 0.1) toggleLOBut(loBut, 2, 3) toggleLOBut(loBut, 1, 3) toggleLOBut(loBut, 3, 3) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 2, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 1, 1, 0.2, 0.1) toggleLOBut(loBut, 3, 3) toggleLOBut(loBut, 2, 3) toggleLOBut(loBut, 4, 3) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 3, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -1, 2, 0.2, 0.1) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 0, 4) toggleLOBut(loBut, 2, 4) toggleLOBut(loBut, 1, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 0, 2, 0.2, 0.1) toggleLOBut(loBut, 2, 4) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 3, 4) toggleLOBut(loBut, 2, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 2, 2, 0.2, 0.1) toggleLOBut(loBut, 4, 4) toggleLOBut(loBut, 3, 4) toggleLOBut(loBut, 4, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) class CreateSceneC(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) # Draw 4x4 lights out wid = 4 hei = 4 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei) loGrid = VGroup(loOuter, loBorder) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1) loGrid.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1) loGrid.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor self.play(Create(loGrid), FadeIn(loBorderFill), run_time = 1.5) self.wait(1) # All buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 self.play(FadeIn(loButtons), run_time = 1) self.wait(1) # Draw 6x6 lights out wid = 6 hei = 6 loBorderFillSix = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuterSix = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2) loBorderSix = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei) loGridSix = VGroup(loOuterSix, loBorderSix) vLinSix = [0 for i in range(wid-1)] # initialize the array hLinSix = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLinSix[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1) loGridSix.add(vLinSix[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLinSix[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1) loGridSix.add(hLinSix[i]) loGridSix.z_index = 500 # keep grid in front of everything except for the cursor # All buttons on to start butSz = 0.9 loButtonsSix = VGroup() loButSix = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): if(i==0 or i==5 or j==0 or j==5): loButSix[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]) loButtonsSix.add(loButSix[i][j]) loButtonsSix.z_index = 550 self.play(FadeOut(loGrid), FadeOut(loBorderFill), FadeIn(loGridSix), FadeIn(loBorderFillSix), FadeIn(loButtonsSix), run_time = 1) self.wait(1) # Draw triangular lights out loBorderFillTri = Polygon( np.array([-3.1, -3.1, 0]), np.array([-3.1, 3.1, 0]), np.array([-1.9, 3.1, 0]), np.array([-1.9, 2.1, 0]), np.array([-0.9, 2.1, 0]), np.array([-0.9, 1.1, 0]), np.array([0.1, 1.1, 0]), np.array([0.1, 0.1, 0]), np.array([1.1, 0.1, 0]), np.array([1.1, -0.9, 0]), np.array([2.1, -0.9, 0]), np.array([2.1, -1.9, 0]), np.array([3.1, -1.9, 0]), np.array([3.1, -3.1, 0]), np.array([-3.1, -3.1, 0]), np.array([-3, -3, 0]), np.array([3, -3, 0]), np.array([3, -2, 0]), np.array([2, -2, 0]), np.array([2, -1, 0]), np.array([1, -1, 0]), np.array([1, 0, 0]), np.array([0, 0, 0]), np.array([0, 1, 0]), np.array([-1, 1, 0]), np.array([-1, 2, 0]), np.array([-2, 2, 0]), np.array([-2, 3, 0]), np.array([-3, 3, 0]), np.array([-3, -3, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuterTri = Polygon( np.array([-3.1, -3.1, 0]), np.array([-3.1, 3.1, 0]), np.array([-1.9, 3.1, 0]), np.array([-1.9, 2.1, 0]), np.array([-0.9, 2.1, 0]), np.array([-0.9, 1.1, 0]), np.array([0.1, 1.1, 0]), np.array([0.1, 0.1, 0]), np.array([1.1, 0.1, 0]), np.array([1.1, -0.9, 0]), np.array([2.1, -0.9, 0]), np.array([2.1, -1.9, 0]), np.array([3.1, -1.9, 0]), np.array([3.1, -3.1, 0]), color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4) loBorderTri = Polygon( np.array([-3, -3, 0]), np.array([3, -3, 0]), np.array([3, -2, 0]), np.array([2, -2, 0]), np.array([2, -1, 0]), np.array([1, -1, 0]), np.array([1, 0, 0]), np.array([0, 0, 0]), np.array([0, 1, 0]), np.array([-1, 1, 0]), np.array([-1, 2, 0]), np.array([-2, 2, 0]), np.array([-2, 3, 0]), np.array([-3, 3, 0]), color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2) loGridTri = VGroup(loOuterTri, loBorderTri) vLinTri = [0 for i in range(5)] # initialize the array hLinTri = [0 for i in range(5)] # initialize the array for i in range(5): vLinTri[i] = Line(start=[1+i-wid/2, hei/2-i, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1) loGridTri.add(vLinTri[i]) for i in reversed(range(5)): # reversed just so that lines are drawn top first, then the one below it, and so on hLinTri[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2-i, 1+i-hei/2, 0], color=BLACK, stroke_width=1) loGridTri.add(hLinTri[i]) loGridTri.z_index = 500 # keep grid in front of everything except for the cursor # All buttons on to start butSz = 0.9 loButtonsTri = VGroup() loButTri = [[0] * 6 for i in range(6)] # initialize the array for i in range(6): for j in range(6): if(i<=5-j): loButTri[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-5/2,j-5/2,0]) loButtonsTri.add(loButTri[i][j]) loButtonsTri.z_index = 550 self.play(FadeOut(loGridSix), FadeOut(loBorderFillSix), FadeOut(loButtons), FadeOut(loButtonsSix), FadeIn(loGridTri), FadeIn(loBorderFillTri), FadeIn(loButtonsTri), run_time = 1) self.wait(1) mCursor = makeMouse(self) mouseMoveAnimate(self, mCursor, -1.5, -1.5, 0.7, 0.5) toggleLOBut(loButTri, 0, 1) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 2, 1) toggleLOBut(loButTri, 1, 2) toggleLOBut(loButTri, 1, 0) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -2.5, 1.5, 0.7, 0.5) toggleLOBut(loButTri, 0, 4) toggleLOBut(loButTri, 1, 4) toggleLOBut(loButTri, 0, 3) toggleLOBut(loButTri, 0, 5) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -1.5, -0.5, 0.7, 0.5) toggleLOBut(loButTri, 1, 2) toggleLOBut(loButTri, 0, 2) toggleLOBut(loButTri, 2, 2) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 1, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -0.5, -0.5, 0.7, 0.5) toggleLOBut(loButTri, 2, 2) toggleLOBut(loButTri, 1, 2) toggleLOBut(loButTri, 3, 2) toggleLOBut(loButTri, 2, 1) toggleLOBut(loButTri, 2, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -0.5, -1.5, 0.7, 0.5) toggleLOBut(loButTri, 2, 1) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 3, 1) toggleLOBut(loButTri, 2, 0) toggleLOBut(loButTri, 2, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 1.5, -2.5, 0.7, 0.5) toggleLOBut(loButTri, 4, 0) toggleLOBut(loButTri, 3, 0) toggleLOBut(loButTri, 5, 0) toggleLOBut(loButTri, 4, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -2.5, -2.5, 0.7, 0.5) # Do random movements to indicate frustration wigspeed = 0.5 for i in range(20): rndx = random.randint(-100,100) / 100; rndy = random.randint(-100,100) / 100; rndnorm = 2*math.sqrt(math.pow(rndx,2) + math.pow(rndy,2)) rndx = rndx / rndnorm rndy = rndy / rndnorm mouseMoveAnimate(self, mCursor, -2.5+rndx, -2.5+rndy, 0.5*wigspeed, 0) mouseMoveAnimate(self, mCursor, -2.5, -2.5, 0.5*wigspeed, 0) wigspeed *= 0.85 * 0.85 self.wait(1) class CreateSceneD(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) # Draw 5x5 lights out wid = 5 hei = 5 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei) loGrid = VGroup(loOuter, loBorder) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1) loGrid.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1) loGrid.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor self.play(Create(loGrid), FadeIn(loBorderFill), run_time = 1.5) self.wait(1) # Random buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 toggleLOBut(loBut, 0, 4) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 2, 4) toggleLOBut(loBut, 3, 4) toggleLOBut(loBut, 1, 3) toggleLOBut(loBut, 3, 3) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 4, 1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 4, 0) self.play(FadeIn(loButtons), run_time = 1) self.wait(1) mCursor = makeMouse(self) mouseMoveAnimate(self, mCursor, 2, 1, 0.7, 0.5) toggleLOBut(loBut, 4, 3) toggleLOBut(loBut, 3, 3) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 4, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 1, 0, 0.7, 0.5) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 3, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 0, 0, 0.7, 0.5) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 2, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, -2, 0, 0.7, 0.5) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 0, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.2) mouseMoveAnimate(self, mCursor, 0, -1, 0.7, 0.5) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 2, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) class CreateSceneE(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) # Draw 3x3 lights out wid = 3 hei = 3 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0).shift([-3,0,0]) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2).shift([-3,0,0]) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei).shift([-3,0,0]) loGrid = VGroup(loOuter, loBorder) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor self.play(Create(loGrid), FadeIn(loBorderFill), run_time = 1.5) self.wait(1) # Buttons 1,2,3,7,8 on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FEFF98", fill_opacity=1, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]).shift([-3,0,0]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 2, 0) self.play(FadeIn(loButtons), run_time = 1) self.wait(1) lNum = 1 gridLabel = [[0] * wid for i in range(hei)] # initialize the array varLabel = [[0] * wid for i in range(hei)] # initialize the array for j in range(hei): for i in range(wid): gridLabel[i][j] = Tex(r"$\displaystyle " + str(lNum) + "$", color=BLACK).shift([i-1,1-j,0]).scale(1.5).shift([-3,0,0]) gridLabel[i][j].z_index = 800+lNum varLabel[i][j] = Tex(r"$\displaystyle x_{" + str(lNum) + "}$", color=BLACK).shift([i-1,1-j,0]).scale(1.2).shift([-3,0,0]) varLabel[i][j].z_index = 830+lNum lNum = lNum + 1 self.play(Write(gridLabel[0][0]), run_time = 1) self.wait(1) self.play(Write(gridLabel[1][0]), run_time = 1) self.wait(1) self.play(Write(gridLabel[2][0]), run_time = 1) self.wait(1) self.play(Write(gridLabel[0][1]), run_time = 1) self.wait(1) self.play(Write(gridLabel[1][1]), run_time = 0.5) self.play(Write(gridLabel[2][1]), run_time = 0.5) self.play(Write(gridLabel[0][2]), run_time = 0.5) self.play(Write(gridLabel[1][2]), run_time = 0.5) self.play(Write(gridLabel[2][2]), run_time = 0.5) self.wait(1) template = TexTemplate(preamble=r'\usepackage{soul}') # needed for LaTeX strikethrough vector1 = Tex(r"$\displaystyle (1,1,1,0,0,0,1,1,0)$", color=BLACK).scale(1.2).shift([3,2.5,0]) vector2 = Tex(r"$\displaystyle (1,1,0,1,0,0,0,0,0)$", color=BLACK).scale(1.2).next_to(vector1, DOWN) vector3a = Tex(r"(", "2", "$, {}$", "2", "$,1,1,0,0,1,1,0)$", color=BLACK, tex_template=template).scale(1.2).next_to(vector2, DOWN) vector3b = Tex(r"(", "\st{2}", "$, {}$", "\st{2}", "$,1,1,0,0,1,1,0)$", color=BLACK, tex_template=template).scale(1.2).next_to(vector2, DOWN) vector3c = Tex(r"(", "0", "$, {}$", "0", "$,1,1,0,0,1,1,0)$", color=BLACK, tex_template=template).scale(1.2).next_to(vector2, DOWN) vector4 = Tex(r"$\displaystyle (1,1,1,0,1,0,0,0,0)$", color=BLACK).scale(1.2).next_to(vector1, DOWN) vector5 = Tex(r"$(1,1,0,1,1,0,1,1,0)$", color=BLACK, tex_template=template).scale(1.2).next_to(vector2, DOWN) vector3b = Tex(r"(", "\st{2}", "$, {}$", "\st{2}", "$,1,1,0,0,1,1,0)$", color=BLACK, tex_template=template).scale(1.2).next_to(vector2, DOWN) vector3c = Tex(r"(", "0", "$, {}$", "0", "$,1,1,0,0,1,1,0)$", color=BLACK, tex_template=template).scale(1.2).next_to(vector2, DOWN) vecPlus = Tex(r"$\displaystyle {} + {}$", color=BLACK).scale(1.2).next_to(vector2, LEFT) vecEqual = Tex(r"$\displaystyle {} = {}$", color=BLACK).scale(1.2).next_to(vector3a, LEFT) modExplain = Tex(r"(because $2 \equiv 0$, $3 \equiv 1$, ...)", color=GREY_D).next_to(vector3a, 1.5*DOWN) self.play(Write(vector1), run_time = 10) self.wait(1) mouseMoveAnimate(self, mCursor, -4, 1, 0.7, 1) # highlight the 3 cells that will be affected cellHighlightBorder = Polygon( np.array([-4.5, 1.5, 0]), np.array([-2.5, 1.5, 0]), np.array([-2.5, 0.5, 0]), np.array([-3.5, 0.5, 0]), np.array([-3.5, -0.5, 0]), np.array([-4.5, -0.5, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0, stroke_width=8) cellHighlightBorder.z_index = 999 whiteOpacityCover = Polygon( np.array([-4.5, 1.5, 0]), np.array([-2.5, 1.5, 0]), np.array([-2.5, 0.5, 0]), np.array([-3.5, 0.5, 0]), np.array([-3.5, -0.5, 0]), np.array([-4.5, -0.5, 0]), np.array([-4.5, 1.5, 0]), np.array([-5.5, 2.5, 0]), np.array([-5.5, -2.5, 0]), np.array([-1, -2.5, 0]), np.array([-1, 2.5, 0]), np.array([-5.5, 2.5, 0]), fill_color=WHITE, fill_opacity=0.5, color=WHITE, stroke_width=0) whiteOpacityCover.z_index = 850 # so it fades out everything except for the cursor and the new (temporary) border self.play(Create(cellHighlightBorder), FadeIn(whiteOpacityCover)) self.wait(1) self.play(Write(vecPlus), run_time = 0.1) self.play(Write(vector2), run_time = 1) self.wait(1) self.play(Uncreate(cellHighlightBorder), FadeOut(whiteOpacityCover)) self.wait(1) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 0, 1) self.play(Write(vecEqual), run_time = 0.1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0) self.play(Write(vector3a), vector2.animate.set_color(GRAY), vector1.animate.set_color(GRAY), vecPlus.animate.set_color(GRAY_C), run_time = 1) self.wait(1) vector3b[1].set_color(RED_E) vector3b[3].set_color(RED_E) self.play(TransformMatchingTex(vector3a,vector3b), run_time = 0.5) self.wait(1) self.play(TransformMatchingTex(vector3b,vector3c), Write(modExplain), run_time = 0.5) self.wait(1) self.play(FadeOut(vector1), FadeOut(vector2), FadeOut(vecPlus), FadeOut(vecEqual), FadeOut(modExplain), run_time = 1) self.play(vector3c.animate.align_to(vector1, UP), run_time = 1) self.wait(1) vecPlus.set_color(BLACK) # Now click the top center and affect 4 cells mouseMoveAnimate(self, mCursor, -3, 1, 0.4, 1) self.play(Write(vecPlus), run_time = 0.1) self.play(Write(vector4), run_time = 1) self.wait(1) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 1, 1) self.play(Write(vecEqual), run_time = 0.1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0) self.play(Write(vector5), vector3c.animate.set_color(GRAY), vector4.animate.set_color(GRAY), vecPlus.animate.set_color(GRAY_C), run_time = 1) self.wait(1) self.play(FadeOut(vector3c), FadeOut(vector4), FadeOut(vecPlus), FadeOut(vecEqual), run_time = 1) self.play(vector5.animate.align_to(vector1, UP), run_time = 1) self.wait(1) vecPlus.set_color(BLACK) self.play(Transform(gridLabel[0][0], varLabel[0][0]), run_time = 1) self.wait(1) self.play(Transform(gridLabel[1][0], varLabel[1][0]), run_time = 1) self.wait(1) self.play(Transform(gridLabel[2][0], varLabel[2][0]), run_time = 0.3) self.play(Transform(gridLabel[0][1], varLabel[0][1]), run_time = 0.3) self.play(Transform(gridLabel[1][1], varLabel[1][1]), run_time = 0.3) self.play(Transform(gridLabel[2][1], varLabel[2][1]), run_time = 0.3) self.play(Transform(gridLabel[0][2], varLabel[0][2]), run_time = 0.3) self.play(Transform(gridLabel[1][2], varLabel[1][2]), run_time = 0.3) self.play(Transform(gridLabel[2][2], varLabel[2][2]), run_time = 0.3) self.wait(1) butVector1 = Tex(r"$ + \ $", r"$x_1$", r"$(1,1,0,1,0,0,0,0,0)$", color=BLACK).scale(0.9).move_to(vector5.get_center()) vecPlus.align_to(vector5, UP) self.play(vector5.animate.scale(0.75), run_time = 1) self.play(vector5.animate.next_to(butVector1, LEFT + [-1.5,0.6,0]), run_time = 1) butVector1.next_to(vector5,RIGHT) self.play(Write(butVector1), run_time = 1) self.wait(1) butVector2 = Tex(r"$ + \ $", r"$x_2$", r"$(1,1,1,0,1,0,0,0,0)$", color=BLACK).scale(0.9).next_to(butVector1,DOWN) butVector3 = Tex(r"$ + \ $", r"$x_3$", r"$(0,1,1,0,0,1,0,0,0)$", color=BLACK).scale(0.9).next_to(butVector2,DOWN) butVector4 = Tex(r"$ + \ $", r"$x_4$", r"$(1,0,0,1,1,0,1,0,0)$", color=BLACK).scale(0.9).next_to(butVector3,DOWN) butVector5 = Tex(r"$ + \ $", r"$x_5$", r"$(0,1,0,1,1,1,0,1,0)$", color=BLACK).scale(0.9).next_to(butVector4,DOWN) butVector6 = Tex(r"$ + \ $", r"$x_6$", r"$(0,0,1,0,1,1,0,0,1)$", color=BLACK).scale(0.9).next_to(butVector5,DOWN) butVector7 = Tex(r"$ + \ $", r"$x_7$", r"$(0,0,0,1,0,0,1,1,0)$", color=BLACK).scale(0.9).next_to(butVector6,DOWN) butVector8 = Tex(r"$ + \ $", r"$x_8$", r"$(0,0,0,0,1,0,1,1,1)$", color=BLACK).scale(0.9).next_to(butVector7,DOWN) butVector9 = Tex(r"$ + \ $", r"$x_9$", r"$(0,0,0,0,0,1,0,1,1)$", color=BLACK).scale(0.9).next_to(butVector8,DOWN) butVectorEq = Tex(r"$ = \ \hphantom{x_9}(0,0,0,0,0,0,0,0,0)$", color=BLACK).scale(0.9).next_to(butVector9,DOWN) self.play(Write(butVector2), run_time = 1) self.wait(1) self.play(Write(butVector3), Write(butVector4), Write(butVector5), Write(butVector6), Write(butVector7), Write(butVector8), Write(butVector9), run_time = 1) self.wait(1) self.play(Write(butVectorEq), run_time = 1) self.wait(1) butVector1b = Tex(r"$ + \ $", r"$1$", r"$(1,1,0,1,0,0,0,0,0)$", color=BLACK).scale(0.9).move_to(butVector1.get_center()) butVector2b = Tex(r"$ + \ $", r"$1$", r"$(1,1,1,0,1,0,0,0,0)$", color=BLACK).scale(0.9).next_to(butVector1,DOWN) butVector3b = Tex(r"$ + \ $", r"$1$", r"$(0,1,1,0,0,1,0,0,0)$", color=BLACK).scale(0.9).next_to(butVector2,DOWN) butVector4b = Tex(r"$ + \ $", r"$1$", r"$(1,0,0,1,1,0,1,0,0)$", color=BLACK).scale(0.9).next_to(butVector3,DOWN) butVector5b = Tex(r"$ + \ $", r"$0$", r"$(0,1,0,1,1,1,0,1,0)$", color=GRAY).scale(0.9).next_to(butVector4,DOWN) butVector6b = Tex(r"$ + \ $", r"$0$", r"$(0,0,1,0,1,1,0,0,1)$", color=GRAY).scale(0.9).next_to(butVector5,DOWN) butVector7b = Tex(r"$ + \ $", r"$1$", r"$(0,0,0,1,0,0,1,1,0)$", color=BLACK).scale(0.9).next_to(butVector6,DOWN) butVector8b = Tex(r"$ + \ $", r"$1$", r"$(0,0,0,0,1,0,1,1,1)$", color=BLACK).scale(0.9).next_to(butVector7,DOWN) butVector9b = Tex(r"$ + \ $", r"$1$", r"$(0,0,0,0,0,1,0,1,1)$", color=BLACK).scale(0.9).next_to(butVector8,DOWN) self.play(butVector5.animate.set_color(GRAY), butVector6.animate.set_color(GRAY), run_time = 0.5) self.play(TransformMatchingTex(butVector1,butVector1b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector2,butVector2b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector3,butVector3b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector4,butVector4b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector7,butVector7b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector8,butVector8b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector9,butVector9b), run_time = 0.5) self.wait(0.5) self.play(TransformMatchingTex(butVector5,butVector5b), TransformMatchingTex(butVector6,butVector6b), run_time = 0.5) self.wait(0.5) self.play(FadeOut(butVector5b), FadeOut(butVector6b), run_time = 1) self.wait(1) self.play(butVector7b.animate.next_to(butVector4,DOWN), butVector8b.animate.next_to(butVector5,DOWN), butVector9b.animate.next_to(butVector6,DOWN), butVectorEq.animate.next_to(butVector7,DOWN), run_time = 1) self.wait(1) mouseMoveAnimate(self, mCursor, -4, 1, 0.5, 0.5) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 0, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -3, 1, 0.5, 0.5) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2, 1, 0.5, 0.5) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 2, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -4, 0, 0.5, 0.5) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 0, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -4, -1, 0.5, 0.5) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 0, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -3, -1, 0.5, 0.5) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2, -1, 0.5, 0.5) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 2, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) butVector5.set_color(BLACK) butVector6.set_color(BLACK) butVector5b.set_color(BLACK) butVector6b.set_color(BLACK) self.play(butVector7b.animate.next_to(butVector6,DOWN), butVector8b.animate.next_to(butVector7,DOWN), butVector9b.animate.next_to(butVector8,DOWN), butVectorEq.animate.next_to(butVector9,DOWN), FadeIn(butVector5b), FadeIn(butVector6b), run_time = 1) self.play(TransformMatchingTex(butVector1b,butVector1), TransformMatchingTex(butVector2b,butVector2), TransformMatchingTex(butVector3b,butVector3), TransformMatchingTex(butVector4b,butVector4), TransformMatchingTex(butVector5b,butVector5), TransformMatchingTex(butVector6b,butVector6), TransformMatchingTex(butVector7b,butVector7), TransformMatchingTex(butVector8b,butVector8), TransformMatchingTex(butVector9b,butVector9), run_time = 0.5) self.wait(1) class CreateSceneF(Scene): def construct(self): self.camera.background_color=WHITE # white background matrix3x3 = Tex(r"$\displaystyle \begin{bmatrix}1 & 1 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 1 & 1 & 1 & 0 & 1 & 0 & 0 & 0 & 0 \\ 0 & 1 & 1 & 0 & 0 & 1 & 0 & 0 & 0 \\ 1 & 0 & 0 & 1 & 1 & 0 & 1 & 0 & 0 \\ 0 & 1 & 0 & 1 & 1 & 1 & 0 & 1 & 0 \\ 0 & 0 & 1 & 0 & 1 & 1 & 0 & 0 & 1 \\ 0 & 0 & 0 & 1 & 0 & 0 & 1 & 1 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 1 & 1 & 1 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 1 & 1 \end{bmatrix}\begin{bmatrix}x_1 \\ x_2 \\ x_3 \\ x_4 \\ x_5 \\ x_6 \\ x_7 \\ x_8 \\ x_9\end{bmatrix} = \begin{bmatrix}1 \\ 1 \\ 0 \\ 1 \\ 1 \\ 0 \\ 1 \\ 1 \\ 0\end{bmatrix}$", color=BLACK).shift([-2,0,0]) self.play(Write(matrix3x3), run_time = 1) self.wait(1) class CreateSceneG(Scene): def construct(self): self.camera.background_color=WHITE # white background template = TexTemplate(preamble=r'\usepackage{soul}') # needed for LaTeX strikethrough M = np.array([[1, 1, 0, 1, 0, 0, 0, 0, 0, 1], [1, 1, 1, 0, 1, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 1, 0, 0, 0, 0], [1, 0, 0, 1, 1, 0, 1, 0, 0, 1], [0, 1, 0, 1, 1, 1, 0, 1, 0, 1], [0, 0, 1, 0, 1, 1, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0, 1, 1, 0, 1], [0, 0, 0, 0, 1, 0, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 0, 1, 1, 0]]) matrix3x3 = Matrix(M, h_buff=1).set_color(BLACK).shift([-1.25,0,0]).scale(0.8) matrix3x3.z_index = 50 augBar = Line(start=np.array([1.97, 2.8, 0]), end=np.array([1.97, -2.8, 0]), color=GRAY) augBar.z_index = 51 self.play(Write(matrix3x3), Write(augBar), run_time = 1) self.wait(1) yelBack = BackgroundRectangle(matrix3x3.get_columns()[0], buff=0.16, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 0 self.play(FadeIn(yelBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3.get_entries()[0], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[10], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[30], Circle, color="#2d70b3"), run_time = 1) self.wait(1) self.play(FadeOut(yelBack), run_time = 1) self.wait(1) yelBack = BackgroundRectangle(matrix3x3.get_columns()[1], buff=0.16, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 0 self.play(FadeIn(yelBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3.get_entries()[1], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[11], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[21], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[41], Circle, color="#2d70b3"), run_time = 1) self.wait(1) self.play(FadeOut(yelBack), run_time = 1) self.wait(1) yelBack = BackgroundRectangle(matrix3x3.get_columns()[9], buff=0.16, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 0 self.play(FadeIn(yelBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3.get_entries()[9], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[19], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[39], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[49], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[69], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[79], Circle, color="#2d70b3"), run_time = 1) self.wait(1) self.play(FadeOut(matrix3x3), FadeOut(augBar), FadeOut(yelBack), run_time = 1) self.wait(1) rowOp2a = Tex(r"$R_i + {}$", r"$cR_j$", color=BLACK).scale(1.2).shift([-2,0,0]) rowOp2b = Tex(r"$R_i + {}$", r"$R_j$", color=BLACK).scale(1.2).shift([-2,0,0]) rowOp1 = Tex(r"$R_i \leftrightarrow R_j$", color=BLACK).scale(1.2).next_to(rowOp2a,UP) rowOp3 = Tex(r"c", r"$R_i$", color=BLACK).scale(1.2).next_to(rowOp2a,DOWN) self.play(Write(rowOp1), run_time = 1) self.wait(1) self.play(Write(rowOp2a), run_time = 1) self.wait(1) self.play(TransformMatchingTex(rowOp2a,rowOp2b), run_time = 1) self.wait(1) self.play(Write(rowOp3), run_time = 1) self.wait(1) self.play(FadeOut(rowOp3), run_time = 1) self.wait(1) self.play(FadeOut(rowOp1), FadeOut(rowOp2b), run_time = 1) self.wait(1) self.play(FadeIn(matrix3x3), FadeIn(augBar), run_time = 1) self.wait(1) # for highlighting rows yelBackRect = [0 for i in range(9)] # initialize the array bluBackRect = [0 for i in range(9)] # initialize the array for i in range(9): yelBackRect[i] = BackgroundRectangle(matrix3x3.get_rows()[i], buff=0.16, color="#FFFF00", fill_opacity=0.2) bluBackRect[i] = BackgroundRectangle(matrix3x3.get_rows()[i], buff=0.16, color="#00FFFF", fill_opacity=0.2) yelBackRect[i].z_index = 0 bluBackRect[i].z_index = 0 self.play(FadeIn(bluBackRect[0]), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3.get_entries()[0], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[10], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3.get_entries()[30], Circle, color="#2d70b3"), run_time = 1) self.wait(1) # R2 + R1, then R4 + R1 M = addRows(self, [2], 1, yelBackRect, M, matrix3x3) M = addRows(self, [4], 1, yelBackRect, M, matrix3x3) self.play(FadeOut(bluBackRect[0]), run_time = 1) yelBack = BackgroundRectangle(matrix3x3.get_columns()[0], buff=0.16, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 0 self.play(FadeIn(yelBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3.get_entries()[0], Circle, color="#2d70b3"), run_time = 1) self.wait(1) self.play(FadeOut(yelBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3.get_entries()[11], Circle, color="#2d70b3"), run_time = 1) self.wait(1) # Swap R2 and R3 # Be careful: you need to redraw the matrix after swapping rows so that indices don't get super confusing afterwards. M = swapRows(self, 2, 3, yelBackRect, M, matrix3x3) matrix3x3b = Matrix(M, h_buff=1).set_color(BLACK).shift([-1.25,0,0]).scale(0.8) matrix3x3b.z_index = 50 self.play(FadeOut(matrix3x3), FadeIn(matrix3x3b), run_time = 0.1) # Add R2 to R1, R4, R5 self.play(FadeIn(bluBackRect[1]), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3b.get_entries()[11], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3b.get_entries()[1], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3b.get_entries()[31], Circle, color="#2d70b3"), run_time = 1) self.play(Circumscribe(matrix3x3b.get_entries()[41], Circle, color="#2d70b3"), run_time = 1) self.wait(1) M = addRows(self, [1,4,5], 2, yelBackRect, M, matrix3x3b) self.play(FadeOut(bluBackRect[1]), run_time = 1) self.wait(1) # Add R3 to R1, R2, R4, R5, R6 self.play(FadeIn(bluBackRect[2]), run_time = 0.5) M = addRows(self, [1,2,4,5,6], 3, yelBackRect, M, matrix3x3b, 0.5) self.play(FadeOut(bluBackRect[2]), run_time = 0.5) self.wait(0.5) # Add R4 to R2, R3, R6, R7 self.play(FadeIn(bluBackRect[3]), run_time = 0.5) M = addRows(self, [2,3,6,7], 4, yelBackRect, M, matrix3x3b, 0.5) self.play(FadeOut(bluBackRect[3]), run_time = 0.5) self.wait(0.5) # Swap R5 and R8 # Be careful: you need to redraw the matrix after swapping rows so that indices don't get super confusing afterwards. M = swapRows(self, 5, 8, yelBackRect, M, matrix3x3b, 0.5) matrix3x3c = Matrix(M, h_buff=1).set_color(BLACK).shift([-1.25,0,0]).scale(0.8) matrix3x3c.z_index = 50 self.play(FadeOut(matrix3x3b), FadeIn(matrix3x3c), run_time = 0.1) # Add R5 to R1, R2, R3 self.play(FadeIn(bluBackRect[4]), run_time = 0.5) M = addRows(self, [1,2,3], 5, yelBackRect, M, matrix3x3c, 0.5) self.play(FadeOut(bluBackRect[4]), run_time = 0.5) self.wait(0.5) # Swap R6 and R7 # Be careful: you need to redraw the matrix after swapping rows so that indices don't get super confusing afterwards. M = swapRows(self, 6, 7, yelBackRect, M, matrix3x3c, 0.5) matrix3x3d = Matrix(M, h_buff=1).set_color(BLACK).shift([-1.25,0,0]).scale(0.8) matrix3x3d.z_index = 50 self.play(FadeOut(matrix3x3c), FadeIn(matrix3x3d), run_time = 0.1) # Add R6 to R1, R3, R4, R9 self.play(FadeIn(bluBackRect[5]), run_time = 0.5) M = addRows(self, [1,3,4,9], 6, yelBackRect, M, matrix3x3d, 0.5) self.play(FadeOut(bluBackRect[5]), run_time = 0.5) self.wait(0.5) # Add R7 to R1, R4, R5 self.play(FadeIn(bluBackRect[6]), run_time = 0.5) M = addRows(self, [1,4,5], 7, yelBackRect, M, matrix3x3d, 0.5) self.play(FadeOut(bluBackRect[6]), run_time = 0.5) self.wait(0.5) # Add R8 to R2, R4, R5, R6 self.play(FadeIn(bluBackRect[7]), run_time = 0.5) M = addRows(self, [2,4,5,6], 8, yelBackRect, M, matrix3x3d, 0.5) self.play(FadeOut(bluBackRect[7]), run_time = 0.5) self.wait(0.5) # Add R9 to R2, R3, R4, R7 self.play(FadeIn(bluBackRect[8]), run_time = 0.5) M = addRows(self, [2,3,4,7], 9, yelBackRect, M, matrix3x3d, 0.5) self.play(FadeOut(bluBackRect[8]), run_time = 0.5) self.wait(1) idBack = BackgroundRectangle(VGroup(matrix3x3d.get_columns()[0],matrix3x3d.get_columns()[8]), buff=0.16, color="#FFFF00", fill_opacity=0.2) self.play(FadeIn(idBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix3x3d.get_entries()[9], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix3x3d.get_entries()[19], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix3x3d.get_entries()[29], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix3x3d.get_entries()[39], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix3x3d.get_entries()[69], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix3x3d.get_entries()[79], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix3x3d.get_entries()[89], Circle, color="#2d70b3"), run_time = 0.5) self.wait(1) self.play(FadeOut(matrix3x3d), FadeOut(augBar), FadeOut(idBack), run_time = 1) self.wait(1) laThm1 = Tex(r"\underline{Theorem from linear algebra:}", color=BLACK).shift([-2.3,1.7,0]) self.play(Write(laThm1), run_time = 1) self.wait(1) laThm2 = Tex(r"Suppose $A$ is an $n \times n$ matrix. The following are equivalent:", color=BLACK).scale(0.85).next_to(laThm1, 1.4*DOWN).align_to(laThm1, LEFT) self.play(Write(laThm2), run_time = 1) laThm3 = Tex(r"a) The reduced row echelon form of $A$ is the identity.", color=BLACK).scale(0.85).next_to(laThm2, DOWN).align_to(laThm2, LEFT) self.play(Write(laThm3), run_time = 1) laThm4 = Tex(r"b) $A$ is invertible.", color=BLACK).scale(0.85).next_to(laThm3, DOWN).align_to(laThm3, LEFT) self.play(Write(laThm4), run_time = 1) laThm5 = Tex(r"c) The linear system $A\mathbf{x} = \mathbf{b}$ has a solution for all vectors $\mathbf{b}$.", color=BLACK).scale(0.85).next_to(laThm4, DOWN).align_to(laThm4, LEFT) self.play(Write(laThm5), run_time = 1) self.wait(1) self.play(Indicate(laThm3)) self.wait(1) self.play(Indicate(laThm5)) self.wait(1) class CreateSceneH(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) mCursor.scale(0.6) # Draw 3x3 lights out wid = 3 hei = 3 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0).shift([-3,0,0]) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2).shift([-3,0,0]) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei).shift([-3,0,0]) loGrid = VGroup(loOuter, loBorder) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor self.play(Create(loGrid), FadeIn(loBorderFill), run_time = 1) self.wait(1) # All buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]).shift([-3,0,0]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 self.play(FadeIn(loButtons), run_time = 1) self.wait(2) self.play(FadeOut(loGrid), FadeOut(loBorderFill), FadeOut(loButtons), run_time = 1) self.wait(1) # Draw 5x5 lights out wid = 5 hei = 5 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0).shift([-3,0,0]) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2).shift([-3,0,0]) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei).shift([-3,0,0]) loGrid = VGroup(loOuter, loBorder) fiveBoard = VGroup(loOuter, loBorder, loBorderFill) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(vLin[i]) fiveBoard.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(hLin[i]) fiveBoard.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor # All buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]).shift([-3,0,0]) fiveBoard.add(loBut[i][j]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 self.play(FadeIn(loButtons), FadeIn(loGrid), FadeIn(loBorderFill), run_time = 1) self.wait(1) lNum = 1 gridLabel = [[0] * wid for i in range(hei)] # initialize the array for j in range(hei): for i in range(wid): gridLabel[i][j] = Tex(r"$\displaystyle " + str(lNum) + "$", color=BLACK).shift([i-2,2-j,0]).scale(1.25).shift([-3,0,0]) gridLabel[i][j].z_index = 800+lNum fiveBoard.add(gridLabel[i][j]) self.play(Write(gridLabel[i][j]), run_time = 0.3) lNum = lNum + 1 self.wait(1) # Move the 5x5 board to the top-right self.play(fiveBoard.animate.move_to([4,2,0]).scale(0.6), run_time = 1) self.wait(1) # Draw the 25x25 matrix M = np.array([[1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1]]) matrix5x5 = Matrix(M, h_buff=0.9).set_color(BLACK).shift([-2.5,0,0]).scale(0.33) matrix5x5.z_index = 50 augBar = Line(start=np.array([1.08, 3.3, 0]), end=np.array([1.08, -3.3, 0]), color=GRAY, stroke_width=0.8) augBar.z_index = 51 self.play(Write(matrix5x5), Write(augBar), run_time = 2) self.wait(1) yelBack = BackgroundRectangle(matrix5x5.get_columns()[0], buff=0.12, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 0 self.play(FadeIn(yelBack), run_time = 1) self.wait(1) self.play(Circumscribe(matrix5x5.get_entries()[0], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix5x5.get_entries()[26], Circle, color="#2d70b3"), run_time = 0.5) self.play(Circumscribe(matrix5x5.get_entries()[130], Circle, color="#2d70b3"), run_time = 0.5) self.wait(1) mouseMoveAnimate(self, mCursor, 2.7, 3.3, 1, 1) toggleLOBut(loBut, 0, 4) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 0, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) toggleLOBut(loBut, 0, 4) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 0, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) self.play(FadeOut(yelBack), run_time = 1) self.wait(1) yelBack = BackgroundRectangle(matrix5x5.get_columns()[25], buff=0.12, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 0 self.play(FadeIn(yelBack), run_time = 1) self.wait(1) self.play(FadeOut(yelBack), run_time = 1) self.wait(1) # Transform to RREF M = np.array([[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0], [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1], [0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1], [0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0], [0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1], [0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0], [0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1], [0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0], [0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0], [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,1,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]) rref5x5 = Matrix(M, h_buff=0.9).set_color(BLACK).shift([-2.5,0,0]).scale(0.33) self.play(Transform(matrix5x5, rref5x5), run_time = 1) self.wait(1) idBack = BackgroundRectangle(VGroup(rref5x5.get_columns()[0],rref5x5.get_columns()[24]), buff=0.12, color="#FFFF00", fill_opacity=0.2) self.play(FadeIn(idBack), run_time = 1) self.wait(1) self.play(FadeOut(idBack), run_time = 1) self.wait(1) idBack = BackgroundRectangle(VGroup(rref5x5.get_rows()[23],rref5x5.get_rows()[24]), buff=0.12, color="#FFFF00", fill_opacity=0.2) self.play(FadeIn(idBack), run_time = 1) self.wait(1) self.play(FadeOut(idBack), run_time = 1) self.wait(1) idBack = BackgroundRectangle(VGroup(rref5x5.get_columns()[23],rref5x5.get_columns()[24]), buff=0.12, color="#FFFF00", fill_opacity=0.2) self.play(FadeIn(idBack), run_time = 1) self.wait(1) mouseMoveAnimate(self, mCursor, 4.5, 0.9, 1, 1) mouseMoveAnimate(self, mCursor, 5.1, 0.9, 0.5, 0.5) mouseMoveAnimate(self, mCursor, 4.5, 0.9, 0.5, 0.5) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 3, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) mouseMoveAnimate(self, mCursor, 5.1, 0.9, 1, 1) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 4, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) mouseMoveAnimate(self, mCursor, 4.5, 0.9, 1, 1) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 3, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) mouseMoveAnimate(self, mCursor, 5.1, 0.9, 1, 1) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 4, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) self.wait(1) self.play(FadeOut(idBack), run_time = 1) self.wait(1) # Zoom back into the board self.play(FadeOut(matrix5x5), FadeOut(augBar), run_time = 1) self.wait(1) fiveBoard.add(mCursor) self.play(fiveBoard.animate.move_to([-3,0,0]).scale(1/0.6), run_time = 1) self.wait(1) # Button 24 is redundant mouseMoveAnimate(self, mCursor, -2, -2, 1, 1) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 3, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 3, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 1) self.wait(1) mouseMoveAnimate(self, mCursor, -4, 2, 1, 1) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 0, 4) toggleLOBut(loBut, 2, 4) toggleLOBut(loBut, 1, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -3, 2, 0.5, 0.5) toggleLOBut(loBut, 2, 4) toggleLOBut(loBut, 1, 4) toggleLOBut(loBut, 3, 4) toggleLOBut(loBut, 2, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2, 2, 0.5, 0.5) toggleLOBut(loBut, 3, 4) toggleLOBut(loBut, 2, 4) toggleLOBut(loBut, 4, 4) toggleLOBut(loBut, 3, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -5, 1, 0.5, 0.5) toggleLOBut(loBut, 0, 3) toggleLOBut(loBut, 1, 3) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 0, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -3, 1, 0.5, 0.5) toggleLOBut(loBut, 3, 3) toggleLOBut(loBut, 2, 3) toggleLOBut(loBut, 1, 3) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 2, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1, 1, 0.5, 0.5) toggleLOBut(loBut, 4, 3) toggleLOBut(loBut, 3, 3) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 4, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -5, 0, 0.5, 0.5) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 0, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -4, 0, 0.5, 0.5) toggleLOBut(loBut, 1, 2) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 1, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2, 0, 0.5, 0.5) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 3, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1, 0, 0.5, 0.5) toggleLOBut(loBut, 4, 2) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 4, 1) toggleLOBut(loBut, 4, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -5, -1, 0.5, 0.5) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 0, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -3, -1, 0.5, 0.5) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 2, 1) toggleLOBut(loBut, 1, 1) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 2, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1, -1, 0.5, 0.5) toggleLOBut(loBut, 4, 1) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 4, 0) toggleLOBut(loBut, 4, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -4, -2, 0.5, 0.5) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -3, -2, 0.5, 0.5) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 2, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) self.wait(1) self.play(FadeOut(fiveBoard), FadeOut(mCursor), run_time = 1) self.wait(1) class CreateSceneI(Scene): def construct(self): self.camera.background_color=WHITE # white background mCursor = makeMouse(self) # Draw 5x5 lights out wid = 5 hei = 5 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0).shift([-3,0,0]) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2).shift([-3,0,0]) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei).shift([-3,0,0]) loGrid = VGroup(loOuter, loBorder) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1).shift([-3,0,0]) loGrid.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor # Random buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]).shift([-3,0,0]) if(random.randint(1, 2) == 1): toggleLOBut(loBut, i, j) loButtons.add(loBut[i][j]) loButtons.z_index = 550 self.play(FadeIn(loButtons), FadeIn(loGrid), FadeIn(loBorderFill), run_time = 1) self.wait(1) self.play(FadeOut(loButtons), FadeOut(loGrid), FadeOut(loBorderFill), run_time = 1) self.wait(1) # Draw triangular lights out loBorderFillTri = Polygon( np.array([-3.1, -3.1, 0]), np.array([-3.1, 3.1, 0]), np.array([-1.9, 3.1, 0]), np.array([-1.9, 2.1, 0]), np.array([-0.9, 2.1, 0]), np.array([-0.9, 1.1, 0]), np.array([0.1, 1.1, 0]), np.array([0.1, 0.1, 0]), np.array([1.1, 0.1, 0]), np.array([1.1, -0.9, 0]), np.array([2.1, -0.9, 0]), np.array([2.1, -1.9, 0]), np.array([3.1, -1.9, 0]), np.array([3.1, -3.1, 0]), np.array([-3.1, -3.1, 0]), np.array([-3, -3, 0]), np.array([3, -3, 0]), np.array([3, -2, 0]), np.array([2, -2, 0]), np.array([2, -1, 0]), np.array([1, -1, 0]), np.array([1, 0, 0]), np.array([0, 0, 0]), np.array([0, 1, 0]), np.array([-1, 1, 0]), np.array([-1, 2, 0]), np.array([-2, 2, 0]), np.array([-2, 3, 0]), np.array([-3, 3, 0]), np.array([-3, -3, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuterTri = Polygon( np.array([-3.1, -3.1, 0]), np.array([-3.1, 3.1, 0]), np.array([-1.9, 3.1, 0]), np.array([-1.9, 2.1, 0]), np.array([-0.9, 2.1, 0]), np.array([-0.9, 1.1, 0]), np.array([0.1, 1.1, 0]), np.array([0.1, 0.1, 0]), np.array([1.1, 0.1, 0]), np.array([1.1, -0.9, 0]), np.array([2.1, -0.9, 0]), np.array([2.1, -1.9, 0]), np.array([3.1, -1.9, 0]), np.array([3.1, -3.1, 0]), color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4) loBorderTri = Polygon( np.array([-3, -3, 0]), np.array([3, -3, 0]), np.array([3, -2, 0]), np.array([2, -2, 0]), np.array([2, -1, 0]), np.array([1, -1, 0]), np.array([1, 0, 0]), np.array([0, 0, 0]), np.array([0, 1, 0]), np.array([-1, 1, 0]), np.array([-1, 2, 0]), np.array([-2, 2, 0]), np.array([-2, 3, 0]), np.array([-3, 3, 0]), color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2) loGridTri = VGroup(loOuterTri, loBorderTri) vLinTri = [0 for i in range(5)] # initialize the array hLinTri = [0 for i in range(5)] # initialize the array for i in range(5): vLinTri[i] = Line(start=[0.5+i-wid/2, hei/2-i-0.5, 0], end=[0.5+i-wid/2, -hei/2-0.5, 0], color=BLACK, stroke_width=1) loGridTri.add(vLinTri[i]) for i in reversed(range(5)): # reversed just so that lines are drawn top first, then the one below it, and so on hLinTri[i] = Line(start=[-wid/2-0.5, 0.5+i-hei/2, 0], end=[wid/2-i-0.5, 0.5+i-hei/2, 0], color=BLACK, stroke_width=1) loGridTri.add(hLinTri[i]) loGridTri.z_index = 500 # keep grid in front of everything except for the cursor # All buttons on to start butSz = 0.9 loButtonsTri = VGroup() loButTri = [[0] * 6 for i in range(6)] # initialize the array for i in range(6): for j in range(6): if(i<=5-j): loButTri[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-5/2,j-5/2,0]) loButtonsTri.add(loButTri[i][j]) loButtonsTri.z_index = 550 self.play(FadeIn(loGridTri), FadeIn(loBorderFillTri), FadeIn(loButtonsTri), run_time = 1) self.wait(1) # Solve the triangular board mouseMoveAnimate(self, mCursor, -2.5, 2.5, 1, 1) toggleLOBut(loButTri, 0, 5) toggleLOBut(loButTri, 0, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1.5, 1.5, 0.5, 0.5) toggleLOBut(loButTri, 0, 4) toggleLOBut(loButTri, 1, 3) toggleLOBut(loButTri, 1, 4) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2.5, 0.5, 0.5, 0.5) toggleLOBut(loButTri, 0, 3) toggleLOBut(loButTri, 0, 4) toggleLOBut(loButTri, 0, 2) toggleLOBut(loButTri, 1, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1.5, -0.5, 0.5, 0.5) toggleLOBut(loButTri, 1, 2) toggleLOBut(loButTri, 0, 2) toggleLOBut(loButTri, 2, 2) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 1, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -0.5, -0.5, 0.5, 0.5) toggleLOBut(loButTri, 2, 2) toggleLOBut(loButTri, 1, 2) toggleLOBut(loButTri, 3, 2) toggleLOBut(loButTri, 2, 1) toggleLOBut(loButTri, 2, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2.5, -1.5, 0.5, 0.5) toggleLOBut(loButTri, 0, 1) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 0, 0) toggleLOBut(loButTri, 0, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1.5, -1.5, 0.5, 0.5) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 2, 1) toggleLOBut(loButTri, 0, 1) toggleLOBut(loButTri, 1, 0) toggleLOBut(loButTri, 1, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -0.5, -1.5, 0.5, 0.5) toggleLOBut(loButTri, 2, 1) toggleLOBut(loButTri, 3, 1) toggleLOBut(loButTri, 1, 1) toggleLOBut(loButTri, 2, 0) toggleLOBut(loButTri, 2, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, 1.5, -1.5, 0.5, 0.5) toggleLOBut(loButTri, 4, 1) toggleLOBut(loButTri, 3, 1) toggleLOBut(loButTri, 4, 0) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -2.5, -2.5, 0.5, 0.5) toggleLOBut(loButTri, 0, 0) toggleLOBut(loButTri, 1, 0) toggleLOBut(loButTri, 0, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -1.5, -2.5, 0.5, 0.5) toggleLOBut(loButTri, 1, 0) toggleLOBut(loButTri, 0, 0) toggleLOBut(loButTri, 2, 0) toggleLOBut(loButTri, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, 0.5, -2.5, 0.5, 0.5) toggleLOBut(loButTri, 3, 0) toggleLOBut(loButTri, 2, 0) toggleLOBut(loButTri, 4, 0) toggleLOBut(loButTri, 3, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, 2.5, -2.5, 0.5, 0.5) toggleLOBut(loButTri, 5, 0) toggleLOBut(loButTri, 4, 0) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) self.wait(1) self.play(FadeOut(loGridTri), FadeOut(loBorderFillTri), FadeOut(loButtonsTri), FadeOut(mCursor), run_time = 1) self.wait(1) # Draw 4x4 lights out wid = 4 hei = 4 loBorderFill = Polygon( np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), hei/2+0.1, 0]), np.array([wid/2+0.1, hei/2+0.1, 0]), np.array([wid/2+0.1, -(hei/2+0.1), 0]), np.array([-(wid/2+0.1), -(hei/2+0.1), 0]), np.array([-wid/2, -hei/2, 0]), np.array([wid/2, -hei/2, 0]), np.array([wid/2, hei/2, 0]), np.array([-wid/2, hei/2, 0]), np.array([-wid/2, -hei/2, 0]), color=BLACK, fill_color=BLACK, fill_opacity=0.4, stroke_width=0) loOuter = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=4, width=wid+0.2, height=hei+0.2) loBorder = Rectangle(color=BLACK, fill_color=WHITE, fill_opacity=0, stroke_width=2, width=wid, height=hei) loGrid = VGroup(loOuter, loBorder) vLin = [0 for i in range(wid-1)] # initialize the array hLin = [0 for i in range(hei-1)] # initialize the array for i in range(wid-1): vLin[i] = Line(start=[1+i-wid/2, hei/2, 0], end=[1+i-wid/2, -hei/2, 0], color=BLACK, stroke_width=1) loGrid.add(vLin[i]) for i in reversed(range(hei-1)): # reversed just so that lines are drawn top first, then the one below it, and so on hLin[i] = Line(start=[-wid/2, 1+i-hei/2, 0], end=[wid/2, 1+i-hei/2, 0], color=BLACK, stroke_width=1) loGrid.add(hLin[i]) loGrid.z_index = 500 # keep grid in front of everything except for the cursor # All buttons on to start butSz = 0.9 loButtons = VGroup() loBut = [[0] * wid for i in range(hei)] # initialize the array for i in range(wid): for j in range(hei): loBut[i][j] = Rectangle(fill_color="#FFFF00", fill_opacity=0.4, color=BLACK, stroke_width=2, width=butSz, height=butSz).shift([i-(wid-1)/2,j-(hei-1)/2,0]) loButtons.add(loBut[i][j]) loButtons.z_index = 550 mCursor.move_to([-7,-5,0]) self.play(FadeIn(mCursor), FadeIn(loGrid), FadeIn(loBorderFill), FadeIn(loButtons), run_time = 1) self.wait(1) # solve it mouseMoveAnimate(self, mCursor, -1.5, -0.5, 1, 1) toggleLOBut(loBut, 0, 1) toggleLOBut(loBut, 0, 0) toggleLOBut(loBut, 0, 2) toggleLOBut(loBut, 1, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, -0.5, 1.5, 1, 1) toggleLOBut(loBut, 1, 3) toggleLOBut(loBut, 0, 3) toggleLOBut(loBut, 2, 3) toggleLOBut(loBut, 1, 2) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, 1.5, 0.5, 1, 1) toggleLOBut(loBut, 3, 2) toggleLOBut(loBut, 2, 2) toggleLOBut(loBut, 3, 1) toggleLOBut(loBut, 3, 3) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) mouseMoveAnimate(self, mCursor, 0.5, -1.5, 1, 1) toggleLOBut(loBut, 2, 0) toggleLOBut(loBut, 1, 0) toggleLOBut(loBut, 3, 0) toggleLOBut(loBut, 2, 1) mouseClickAnimate(self, mCursor, 0.05, 0.15, 0.45, 0.1, 0.5) self.wait(1) self.play(FadeOut(loGrid), FadeOut(loBorderFill), FadeOut(loButtons), FadeOut(mCursor), run_time = 1) self.wait(1) # Matrix version of 4x4 M = np.array([[1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1], [0,1,0,0,0,0,0,0,0,0,0,0,1,1,0,1,1], [0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1], [0,0,0,1,0,0,0,0,0,0,0,0,1,1,1,0,1], [0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,1], [0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0], [0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0], [0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,1,1], [0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,1], [0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,1], [0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1,1], [0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,1], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]) matrix4x4 = Matrix(M, h_buff=0.9).set_color(BLACK).scale(0.5) matrix4x4.z_index = 40 augBar = Line(start=np.array([3.39, 3.2, 0]), end=np.array([3.39, -3.2, 0]), color=GRAY, stroke_width=1) augBar.z_index = 51 self.play(Create(matrix4x4), Create(augBar), run_time = 1) self.wait(1) yelBack = BackgroundRectangle(matrix4x4.get_columns()[12], buff=0.14, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 1 self.play(FadeIn(yelBack), run_time = 1) self.play(FadeOut(yelBack), run_time = 1) yelBack = BackgroundRectangle(matrix4x4.get_columns()[13], buff=0.14, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 1 self.play(FadeIn(yelBack), run_time = 1) self.play(FadeOut(yelBack), run_time = 1) yelBack = BackgroundRectangle(matrix4x4.get_columns()[14], buff=0.14, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 1 self.play(FadeIn(yelBack), run_time = 1) self.play(FadeOut(yelBack), run_time = 1) yelBack = BackgroundRectangle(matrix4x4.get_columns()[15], buff=0.14, color="#FFFF00", fill_opacity=0.2) yelBack.z_index = 1 self.play(FadeIn(yelBack), run_time = 1) self.play(FadeOut(yelBack), run_time = 1) self.wait(1) self.play(FadeOut(matrix4x4), FadeOut(augBar), run_time = 1) self.wait(1) laThm1 = Tex(r"If all columns have an odd number of 1s then", color=BLACK).scale(0.85).shift([-2.5,2,0]) laThm2 = Tex(r"adding all rows (mod 2) results in the all-ones vector $\mathbf{1} = (1,1,\ldots,1)$.", color=BLACK).scale(0.85).next_to(laThm1, DOWN).align_to(laThm1, LEFT) laThm3 = Tex(r"So $(1,1,\ldots,1) \in \mathrm{range}(A^T)$.", color=BLACK).next_to(laThm2, 2*DOWN).scale(0.85).align_to(laThm2, LEFT) laThm4 = Tex(r"But $A$ is symmetric ($A^T = A$), so $\mathbf{1} \in \mathrm{range}(A)$.", color=BLACK).scale(0.85).next_to(laThm3, DOWN).align_to(laThm3, LEFT) laThm5 = Tex(r"So there exists $\mathbf{x}$ such that $A\mathbf{x} = \mathbf{1}$.", color=BLACK).scale(0.85).next_to(laThm4, 2*DOWN).align_to(laThm4, LEFT) self.play(Write(laThm1), run_time = 2) self.play(Write(laThm2), run_time = 2.5) self.wait(2) self.play(Write(laThm3), run_time = 2) self.wait(2) self.play(Write(laThm4), run_time = 2.5) self.wait(2) self.play(Write(laThm5), run_time = 2.5) self.wait(2) # Animate a row addition or collection of row operations all from the same row def addRows(self, addTo, addFrom, yelBackRect, M, matrix3x3, wait_time = 1): leftRowOps = [0 for i in range(max(addTo)+1)] # initialize the array leftRowOpGroup = VGroup() yelBackGroup = VGroup() for i in addTo: M[i-1] = (M[i-1] + M[addFrom-1]) % 2 leftRowOps[i-1] = Tex(r"$\xrightarrow{R_" + str(i) + "+R_" + str(addFrom) + "}$", color=BLACK).next_to(yelBackRect[i-1], LEFT).scale(0.9) leftRowOpGroup.add(leftRowOps[i-1]) yelBackGroup.add(yelBackRect[i-1]) newMatrix3x3 = Matrix(M, h_buff=1).set_color(BLACK).shift([-1.25,0,0]).scale(0.8) self.play(FadeIn(yelBackGroup), FadeIn(leftRowOpGroup), run_time = 1) self.wait(wait_time) for i in addTo: self.play(Transform(matrix3x3.get_rows()[i-1], newMatrix3x3.get_rows()[i-1]), run_time = 1/len(addTo)) self.wait(wait_time) self.play(FadeOut(yelBackGroup), FadeOut(leftRowOpGroup), run_time = 1) self.wait(wait_time) return M # Animate a row swap def swapRows(self, swap1, swap2, yelBackRect, M, matrix3x3, wait_time = 1): M[[swap1-1, swap2-1]] = M[[swap2-1, swap1-1]] leftRowOp = Tex(r"$\xrightarrow{R_" + str(swap1) + " \leftrightarrow R_" + str(swap2) + "}$", color=BLACK).next_to(yelBackRect[swap2-1], LEFT).scale(0.9).shift([0,(swap2-swap1)*0.3,0]) newMatrix3x3 = Matrix(M, h_buff=1).set_color(BLACK).shift([-1.25,0,0]).scale(0.8) self.play(FadeIn(yelBackRect[swap1-1]), FadeIn(yelBackRect[swap2-1]), FadeIn(leftRowOp), run_time = 1) self.wait(wait_time) self.play(matrix3x3.get_rows()[swap1-1].animate.move_to(newMatrix3x3.get_rows()[swap2-1].get_center()), matrix3x3.get_rows()[swap2-1].animate.move_to(newMatrix3x3.get_rows()[swap1-1].get_center()), run_time = 1) self.wait(wait_time) self.play(FadeOut(yelBackRect[swap1-1]), FadeOut(yelBackRect[swap2-1]), FadeOut(leftRowOp), run_time = 1) self.wait(wait_time) return M # Toggle a button color def toggleLOBut(loBut, x, y): yellowCol = "#FFFF00" yellowColB = "#FEFF98" blueCol = "#173959" curColor = loBut[x][y].get_color().to_hex() if(curColor.lower() == yellowCol.lower() or curColor.lower() == yellowColB.lower()): loBut[x][y].set_fill(color = blueCol, opacity = 0.4) else: loBut[x][y].set_fill(color = yellowCol, opacity = 0.4) # Draw the mouse cursor def makeMouse(self, mCursScale = 0.005, mCursLocation = [-7,-5,0], wait_time = 1): mCursor = Polygon( mCursScale * np.array([0, 0, 0]), mCursScale * np.array([73, -67, 0]), mCursScale * np.array([39, -72, 0]), mCursScale * np.array([59, -117, 0]), mCursScale * np.array([46, -123, 0]), mCursScale * np.array([25, -78, 0]), mCursScale * np.array([0, -100, 0]), color=BLACK, fill_color=WHITE, fill_opacity=1, stroke_width=3).shift(mCursLocation) mCursor.z_index = 1000 # keep cursor in front self.add(mCursor) self.wait(wait_time) return mCursor # Animate the mouse moving to a particular location def mouseMoveAnimate(self, mCursor, x, y, move_duration = 1, wait_time = 1): self.play(mCursor.animate.move_to([x+0.18,y-0.3,0]), run_time=move_duration) # 0.18 and 0.3 adjustment is needed because these coordinates refer to the center of the cursor, not its tip if(wait_time > 0): self.wait(wait_time) # Animate the mouse clicking at its current location def mouseClickAnimate(self, mCursor, clickDepth = 0.05, clickLineStart = 0.15, clickLineEnd = 0.45, clickSpeed = 0.1, wait_time = 1): clickLine1 = Line(mCursor.get_start() + clickLineStart*np.array([0,1,0]), mCursor.get_start() + clickLineEnd*np.array([0,1,0]), color=BLACK) clickLine2 = Line(mCursor.get_start() + clickLineStart*np.array([1,0,0]), mCursor.get_start() + clickLineEnd*np.array([1,0,0]), color=BLACK) clickLine3 = Line(mCursor.get_start() + clickLineStart*np.array([0,-1,0]), mCursor.get_start() + clickLineEnd*np.array([0,-1,0]), color=BLACK) clickLine4 = Line(mCursor.get_start() + clickLineStart*np.array([-1,0,0]), mCursor.get_start() + clickLineEnd*np.array([-1,0,0]), color=BLACK) clickLine5 = Line(mCursor.get_start() + clickLineStart*np.array([0.7071,0.7071,0]), mCursor.get_start() + clickLineEnd*np.array([0.7071,0.7071,0]), color=BLACK) clickLine6 = Line(mCursor.get_start() + clickLineStart*np.array([0.7071,-0.7071,0]), mCursor.get_start() + clickLineEnd*np.array([0.7071,-0.7071,0]), color=BLACK) clickLine7 = Line(mCursor.get_start() + clickLineStart*np.array([-0.7071,0.7071,0]), mCursor.get_start() + clickLineEnd*np.array([-0.7071,0.7071,0]), color=BLACK) clickLine8 = Line(mCursor.get_start() + clickLineStart*np.array([-0.7071,-0.7071,0]), mCursor.get_start() + clickLineEnd*np.array([-0.7071,-0.7071,0]), color=BLACK) # click in and make click lines mCursor.move_to(mCursor.get_center() + clickDepth*np.array([1,-1,0])) self.play(Create(clickLine1), Create(clickLine2), Create(clickLine3), Create(clickLine4), Create(clickLine5), Create(clickLine6), Create(clickLine7), Create(clickLine8), run_time = clickSpeed) # click back out and remove click lines mCursor.move_to(mCursor.get_center() + clickDepth*np.array([-1,1,0])) self.play(Uncreate(clickLine1.set_points(clickLine1.get_points()[::-1])), Uncreate(clickLine2.set_points(clickLine2.get_points()[::-1])), Uncreate(clickLine3.set_points(clickLine3.get_points()[::-1])), Uncreate(clickLine4.set_points(clickLine4.get_points()[::-1])), Uncreate(clickLine5.set_points(clickLine5.get_points()[::-1])), Uncreate(clickLine6.set_points(clickLine6.get_points()[::-1])), Uncreate(clickLine7.set_points(clickLine7.get_points()[::-1])), Uncreate(clickLine8.set_points(clickLine8.get_points()[::-1])), run_time = clickSpeed) # weird code here is so that the Uncreate happens in the opposite order self.wait(wait_time)