93 lines
2.6 KiB
Python
93 lines
2.6 KiB
Python
|
from manim import *
|
||
|
|
||
|
|
||
|
class Sequence(VMobject):
|
||
|
# evenly spaced characters
|
||
|
|
||
|
def __init__(self, seq):
|
||
|
VMobject.__init__(self)
|
||
|
seq = [t.move_to(i * 0.5 * RIGHT) for i, t in enumerate(seq)]
|
||
|
self.add(VGroup(*seq).move_to(ORIGIN + 2*UP))
|
||
|
|
||
|
|
||
|
class Pointer(VMobject):
|
||
|
# pointer to sequence element
|
||
|
|
||
|
def __init__(self, pointee, name):
|
||
|
VMobject.__init__(self)
|
||
|
arrow = Arrow(ORIGIN, DOWN).next_to(pointee, UP)
|
||
|
name_tex = Tex(name).next_to(arrow, UP)
|
||
|
self.add(arrow, name_tex)
|
||
|
|
||
|
|
||
|
class ProgramCounter(VMobject):
|
||
|
# pointer to current code line
|
||
|
|
||
|
def __init__(self, line):
|
||
|
VMobject.__init__(self)
|
||
|
self.add(Arrow(ORIGIN, RIGHT).next_to(line, LEFT))
|
||
|
|
||
|
|
||
|
class Base(Scene):
|
||
|
def construct(self, n, k):
|
||
|
|
||
|
# initial situation
|
||
|
seq = [Tex("1")] + [Tex("?") for _ in range(n-2)] + [Tex("0")]
|
||
|
self.play(Create(Sequence(seq)))
|
||
|
|
||
|
# source code binary search
|
||
|
code = Code(file_name="binary-search.py", language="Python", insert_line_no=False, style='monokai')
|
||
|
code.move_to(DOWN)
|
||
|
self.play(Write(code))
|
||
|
line_lr, line_while, line_m, line_test, line_l, _, line_r = code[2]
|
||
|
|
||
|
def test(x):
|
||
|
return 1 if x <= k else 0
|
||
|
|
||
|
def update_pc(pc, line):
|
||
|
npc = ProgramCounter(line)
|
||
|
self.play(ReplacementTransform(pc, npc))
|
||
|
return npc
|
||
|
|
||
|
# initialize borders
|
||
|
pc = ProgramCounter(line_lr)
|
||
|
self.play(Create(pc))
|
||
|
l, r = 0, n-1
|
||
|
lp = Pointer(seq[l], "l")
|
||
|
rp = Pointer(seq[r], "r")
|
||
|
self.play(Write(lp), Create(rp))
|
||
|
|
||
|
while r - l > 1:
|
||
|
# calculate m
|
||
|
pc = update_pc(pc, line_m)
|
||
|
m = (l + r) // 2
|
||
|
mp = Pointer(seq[m], "m")
|
||
|
self.play(Create(mp))
|
||
|
|
||
|
# test
|
||
|
pc = update_pc(pc, line_test)
|
||
|
old = seq.copy()
|
||
|
seq[m] = Tex(str(test(m)))
|
||
|
self.play(ReplacementTransform(Sequence(old), Sequence(seq)))
|
||
|
|
||
|
if test(m):
|
||
|
# update left
|
||
|
pc = update_pc(pc, line_l)
|
||
|
l = m
|
||
|
op = lp
|
||
|
lp = Pointer(seq[m], "l")
|
||
|
self.play(Uncreate(mp), ReplacementTransform(op, lp))
|
||
|
else:
|
||
|
# update right
|
||
|
pc = update_pc(pc, line_r)
|
||
|
r = m
|
||
|
op = rp
|
||
|
rp = Pointer(seq[m], "r")
|
||
|
self.play(Uncreate(mp), ReplacementTransform(op, rp))
|
||
|
|
||
|
self.wait(2)
|
||
|
|
||
|
class Main(Base):
|
||
|
def construct(self):
|
||
|
Base.construct(self, 20, 6)
|