Skip to content

Commit

Permalink
Sorting Animation With Python [GUI & UI] 🤍
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonioBerna committed May 23, 2022
1 parent ff515c9 commit dec62b5
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 0 deletions.
Binary file added SortingAlgorithms/.DS_Store
Binary file not shown.
33 changes: 33 additions & 0 deletions SortingAlgorithms/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# SortingAlgorithms

## BubbleSort

<p align="center">
<img src="imgs/BubbleSort.png" width="752" height="656">
</p>


## InsertionSort

<p align="center">
<img src="imgs/InsertionSort.png" width="752" height="656">
</p>


## MergeSort

<p align="center">
<img src="imgs/MergeSort.png" width="752" height="656">
</p>

## QuickSort

<p align="center">
<img src="imgs/QuickSort.png" width="752" height="656">
</p>

## SelectionSort

<p align="center">
<img src="imgs/SelectionSort.png" width="752" height="656">
</p>
104 changes: 104 additions & 0 deletions SortingAlgorithms/gui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from tkinter import messagebox
from sort import Algorithms
import tkinter as tk
import random
import time


class Window(tk.Tk):
def __init__(self):
super().__init__()
self.title("Sorting Algorithms - Clever Code")
# self.resizable(False, False)

self.frame = tk.Frame()
self.frame.pack()
self.n_label = tk.Label(self.frame, text="n:", font=("Cascadia Code", "15"))
self.n_label.grid(row=0, column=0, padx=10, pady=10)
self.n_entry = tk.Entry(self.frame, justify="center", font=("Cascadia Code", "15"))
self.n_entry.grid(row=0, column=1, padx=10, sticky="E")

self.sort_frame = tk.Frame()
self.sort_frame.pack()
self.radio_value = tk.IntVar()
self.radio_value.set(-1)
self.bubble_sort = tk.Radiobutton(self.sort_frame, text="BubbleSort", variable=self.radio_value, value=0)
self.bubble_sort.grid(row=0, column=0, padx=10, sticky="W")
self.insertion_sort = tk.Radiobutton(self.sort_frame, text="InsertionSort", variable=self.radio_value, value=1)
self.insertion_sort.grid(row=0, column=1, padx=10, sticky="W")
self.merge_sort = tk.Radiobutton(self.sort_frame, text="MergeSort", variable=self.radio_value, value=2)
self.merge_sort.grid(row=1, column=0, padx=10, sticky="W")
self.quick_sort = tk.Radiobutton(self.sort_frame, text="QuickSort", variable=self.radio_value, value=3)
self.quick_sort.grid(row=1, column=1, padx=10, sticky="W")
self.selection_sort = tk.Radiobutton(self.sort_frame, text="SelectionSort", variable=self.radio_value, value=4)
self.selection_sort.grid(row=2, columnspan=2, padx=10)

self.button_frame = tk.Frame()
self.button_frame.pack()
self.reset_button = tk.Button(self.button_frame, text="Reset", font=("Cascadia Code", "15"), command=self.resetWindow)
self.reset_button.grid(row=0, column=0, padx=10, pady=10, sticky="WE")
self.start_button = tk.Button(self.button_frame, text="Start", font=("Cascadia Code", "15"), command=self.setAlgorithm)
self.start_button.grid(row=0, column=1, padx=10, pady=10, sticky="WE")

def resetWindow(self):
self.n_entry.delete(0, tk.END)
self.radio_value.set(-1)

def __checkAll(self):
try:
if self.radio_value.get() in [i for i in range(0, 5)] and int(self.n_entry.get()):
return True
except ValueError:
return False

def setAlgorithm(self):
if self.__checkAll():
N = int(self.n_entry.get())
A = [x + 1 for x in range(N)]
random.seed(time.time())
random.shuffle(A)

algo = Algorithms()
if self.radio_value.get() == 0:
self.title = "BubbleSort"
self.generator = algo.bubblesort(A)
elif self.radio_value.get() == 1:
self.title = "InsertionSort"
self.generator = algo.insertionsort(A)
elif self.radio_value.get() == 2:
self.title = "MergeSort"
self.generator = algo.mergesort(A, 0, N - 1)
elif self.radio_value.get() == 3:
self.title = "QuickSort"
self.generator = algo.quicksort(A, 0, N - 1)
else:
self.title = "SelectionSort"
self.generator = algo.selectionsort(A)

self.showFigure(A, N)
else:
messagebox.showerror("Si è verificato un errore", "Valori Inseriti Non Validi!")

def updateFigure(self, A, rects, iteration):
for rect, val in zip(rects, A):
rect.set_height(val)
iteration[0] += 1
self.text.set_text("# of Operations: {}".format(iteration[0]))

def showFigure(self, A, N):
fig, ax = plt.subplots()
ax.set_title(self.title)
bar_rects = ax.bar(range(len(A)), A, align="edge")
ax.set_xlim(0, N)
ax.set_ylim(0, int(1.07 * N))
self.text = ax.text(0.02, 0.95, "", transform=ax.transAxes)

iteration = [0]
anim = animation.FuncAnimation(fig, func=self.updateFigure, fargs=(bar_rects, iteration), frames=self.generator, interval=1, repeat=False)
plt.show()

if __name__ == "__main__":
window = Window()
window.mainloop()
Binary file added SortingAlgorithms/imgs/BubbleSort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SortingAlgorithms/imgs/InsertionSort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SortingAlgorithms/imgs/MergeSort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SortingAlgorithms/imgs/QuickSort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SortingAlgorithms/imgs/SelectionSort.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added SortingAlgorithms/imgs/gui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions SortingAlgorithms/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
matplotlib==3.5.1
97 changes: 97 additions & 0 deletions SortingAlgorithms/sort.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
class Algorithms:
def swap(self, A, i, j):
if i != j:
A[i], A[j] = A[j], A[i]

def bubblesort(self, A):
if len(A) == 1:
return

swapped = True
for i in range(len(A) - 1):
if not swapped:
break
swapped = False
for j in range(len(A) - 1 - i):
if A[j] > A[j + 1]:
self.swap(A, j, j + 1)
swapped = True
yield A

def insertionsort(self, A):
for i in range(1, len(A)):
j = i
while j > 0 and A[j] < A[j - 1]:
self.swap(A, j, j - 1)
j -= 1
yield A

def mergesort(self, A, start, end):
if end <= start:
return

mid = start + ((end - start + 1) // 2) - 1
yield from self.mergesort(A, start, mid)
yield from self.mergesort(A, mid + 1, end)
yield from self.merge(A, start, mid, end)
yield A

def merge(self, A, start, mid, end):
merged = []
leftIdx = start
rightIdx = mid + 1

while leftIdx <= mid and rightIdx <= end:
if A[leftIdx] < A[rightIdx]:
merged.append(A[leftIdx])
leftIdx += 1
else:
merged.append(A[rightIdx])
rightIdx += 1

while leftIdx <= mid:
merged.append(A[leftIdx])
leftIdx += 1

while rightIdx <= end:
merged.append(A[rightIdx])
rightIdx += 1

for i, sorted_val in enumerate(merged):
A[start + i] = sorted_val
yield A

def quicksort(self, A, start, end):
if start >= end:
return

pivot = A[end]
pivotIdx = start

for i in range(start, end):
if A[i] < pivot:
self.swap(A, i, pivotIdx)
pivotIdx += 1
yield A
self.swap(A, end, pivotIdx)
yield A

yield from self.quicksort(A, start, pivotIdx - 1)
yield from self.quicksort(A, pivotIdx + 1, end)


def selectionsort(self, A):
if len(A) == 1:
return

for i in range(len(A)):
# Find minimum unsorted value.
minVal = A[i]
minIdx = i
for j in range(i, len(A)):
if A[j] < minVal:
minVal = A[j]
minIdx = j
yield A
self.swap(A, i, minIdx)
yield A
78 changes: 78 additions & 0 deletions SortingAlgorithms/ui.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from sort import Algorithms
import random
import time


def main():
while True:
N = int(input("Enter number of integers: "))
if N > 0:
while True:
try:
method = int(input("Enter sorting method:\n(1) BubbleSort\n(2) InsertionSort\n(3) MergeSort\n(4) QuickSort\n(5) SelectionSort\n(0) Exit\n> "))
if method in [i for i in range(0, 6)]:

# init random list A
A = [x + 1 for x in range(N)]
random.seed(time.time())
random.shuffle(A)

algo = Algorithms()
if method == 0:
print("Bye.")
exit()
elif method == 1:
title = "BubbleSort"
generator = algo.bubblesort(A)
elif method == 2:
title = "InsertionSort"
generator = algo.insertionsort(A)
elif method == 3:
title = "MergeSort"
generator = algo.mergesort(A, 0, N - 1)
elif method == 4:
title = "QuickSort"
generator = algo.quicksort(A, 0, N - 1)
elif method == 5:
title = "SelectionSort"
generator = algo.selectionsort(A)

print(f"You selected {title}")
output(A, N, title, generator)
print("Bye.")
exit()
else:
print("You must enter a number between 0 and 5... Try Again!")
except Exception as e:
print(f"Error: {e}... Try Again!")
else:
print("You must enter a number > 0... Try again!")


def update_fig(A, rects, iteration, text):
for rect, val in zip(rects, A):
rect.set_height(val)
iteration[0] += 1
text.set_text("# of Operations: {}".format(iteration[0]))

def output(A, N, title, generator):
fig, ax = plt.subplots()
ax.set_title(title)

bar_rects = ax.bar(range(len(A)), A, align="edge")
ax.set_xlim(0, N)
ax.set_ylim(0, int(1.07 * N))

text = ax.text(0.02, 0.95, "", transform=ax.transAxes)

iteration = [0]
anim = animation.FuncAnimation(fig, func=update_fig,
fargs=(bar_rects, iteration, text), frames=generator, interval=1,
repeat=False)
plt.show()


if __name__ == "__main__":
main()

0 comments on commit dec62b5

Please sign in to comment.