Skip to content

Instantly share code, notes, and snippets.

@dashmage
Last active August 23, 2024 05:26
Show Gist options
  • Save dashmage/2aac098c09d4e6d31488e6d000e3fc2f to your computer and use it in GitHub Desktop.
Save dashmage/2aac098c09d4e6d31488e6d000e3fc2f to your computer and use it in GitHub Desktop.
Knuth/ Fisher-Yates Shuffle Animation
"""
Knuth/ Fisher-Yates shuffle algorithm visualized with the manim library.
Install manim (preferably in a virtual environment),
$ pip install manim
Generate the animation play the resulting mp4 file,
$ manim -pql scene.py KnuthShuffle
To generate a higher quality animation once you're done testing the code (takes more time to execute),
$ manim -qh scene.py KnuthShuffle
"""
from manim import *
import random
class KnuthShuffle(Scene):
def construct(self):
# Initial list
data = ["A", "B", "C", "D", "E"]
# Create text objects for the list elements
elements = [Text(str(num)) for num in data]
# Create white square outlines for the elements
outlines = [Square(side_length=1.2, color=WHITE) for _ in data]
for i, (element, outline) in enumerate(zip(elements, outlines)):
element.move_to(DOWN * 1.2 + RIGHT * (i * 1.2 - 4) + 1.2)
outline.move_to(element.get_center())
self.play(*[Write(element) for element in elements])
self.play(*[Create(outline) for outline in outlines])
self.wait()
for i in range(len(data) - 1, 0, -1):
# Random index between 0 and i
j = random.randint(0, i)
if i != j:
arrow = CurvedDoubleArrow(elements[i].get_bottom() + DOWN * 0.5, elements[j].get_bottom() + DOWN * 0.5, color=RED, angle=-TAU/4)
else:
arrow = CurvedDoubleArrow(elements[i].get_bottom() + DOWN * 0.5 + RIGHT * 0.5, elements[j].get_bottom() + DOWN * 0.5 + LEFT * 0.5, color=RED, angle=-TAU/4)
self.play(FadeIn(arrow))
self.wait(0.5)
# Swap the elements in the list
data[i], data[j] = data[j], data[i]
# Animate the swap
self.play(
elements[i].animate.move_to(elements[j].get_center()),
elements[j].animate.move_to(elements[i].get_center()),
outlines[i].animate.move_to(outlines[j].get_center()),
outlines[j].animate.move_to(outlines[i].get_center())
)
# Update their positions in the list
elements[i], elements[j] = elements[j], elements[i]
outlines[i], outlines[j] = outlines[j], outlines[i]
self.wait(0.5)
self.play(outlines[i].animate.set_fill(PINK, opacity=0.2))
# Remove the arrow
self.play(FadeOut(arrow))
# Final wait before ending the scene
self.wait(2)
@dashmage
Copy link
Author

knuth_shuffle.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment