diff --git a/Lib/turtledemo/sorting_animate.py b/Lib/turtledemo/sorting_animate.py new file mode 100644 --- /dev/null +++ b/Lib/turtledemo/sorting_animate.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 +""" + + sorting_animation.py + +A minimal sorting algorithm animation: +Sorts a shelf of 10 blocks using insertion +sort, selection sort and quicksort. + +Shelfs are implemented using builtin lists. + +Blocks are turtles with shape "square", but +stretched to rectangles by shapesize() + --------------------------------------- + To exit press space button + --------------------------------------- +""" +from turtle import * + +class Block(Turtle): + def __init__(self, size): + self.size = size + Turtle.__init__(self, shape="square", visible=False) + self.pu() + self.shapesize(size * 1.5, 1.5, 2) # square-->rectangle + self.fillcolor("black") + self.st() + def glow(self): + self.fillcolor("red") + def unglow(self): + self.fillcolor("black") + def __repr__(self): + return "Block size: {0}".format(self.size) + +class Shelf(list): + def __init__(self, y): + "create an shelf. y is y-position of first block" + self.y = y + self.x = -150 + def push(self, d): + width, _, _ = d.shapesize() + yoffset = width/2 * 20 # to align the blocks by it's bottom edge + d.sety(self.y + yoffset) + d.setx(self.x+34*len(self)) + self.append(d) + def _close_gap_from_i(self, i): + for b in self[i:]: + xpos, _ = b.pos() + b.setx(xpos - 34) + def _open_gap_from_i(self, i): + for b in self[i:]: + xpos, _ = b.pos() + b.setx(xpos + 34) + def pop(self, key): + b = list.pop(self, key) + b.glow() + b.sety(200) + self._close_gap_from_i(key) + return b + def insert(self, key, b): + self._open_gap_from_i(key) + list.insert(self, key, b) + b.setx(self.x+34*key) + width, _, _ = b.shapesize() + yoffset = width/2 * 20 # to align the blocks by it's bottom edge + b.sety(self.y + yoffset) + b.unglow() + +def isort(shelf): + length = len(shelf) + for i in range(1, length): + holepos = i + while holepos > 0 and shelf[i].size < shelf[holepos - 1].size: + holepos = holepos - 1 + shelf.insert(holepos, shelf.pop(i)) + return + +def ssort(shelf): + length = len(shelf) + for j in range(0, length - 1): + imin = j + for i in range(j + 1, length): + if shelf[i].size < shelf[imin].size: + imin = i + if imin != j: + shelf.insert(j, shelf.pop(imin)) + +def partition(shelf, left, right, pivot_index): + pivot = shelf[pivot_index] + shelf.insert(right, shelf.pop(pivot_index)) + store_index = left + for i in range(left, right): # range is non-inclusive of ending value + if shelf[i].size < pivot.size: + shelf.insert(store_index, shelf.pop(i)) + store_index = store_index + 1 + shelf.insert(store_index, shelf.pop(right)) # move pivot to correct position + return store_index + +def qsort(shelf, left, right): + if left < right: + pivot_index = left + pivot_new_index = partition(shelf, left, right, pivot_index) + qsort(shelf, left, pivot_new_index - 1) + qsort(shelf, pivot_new_index + 1, right) + +def show_text(text): + goto(0,-250) + write(text, align="center", font=("Courier", 16, "bold")) + +def start_ssort(): + onkey(None,"s") + clear() + show_text("Selection Sort") + ssort(s) + +def start_isort(): + onkey(None,"i") + clear() + show_text("Insertion Sort") + isort(s) + +def start_qsort(): + onkey(None,"q") + clear() + show_text("Quicksort") + qsort(s, 0, len(s) - 1) + +def init_shelf(): + global s + s = Shelf(-200) + vals = (4, 2, 8, 9, 1, 5, 10, 3, 7, 6) + for i in vals: + s.push(Block(i)) + +def main(): + getscreen().clearscreen() + ht(); penup() + init_shelf() + show_text("press i for insertion sort, s for selection sort and q for quicksort") + onkey(start_isort, "i") + onkey(start_ssort, "s") + onkey(start_qsort, "q") + onkey(bye, "space") + listen() + return "EVENTLOOP" + +if __name__=="__main__": + msg = main() + print(msg) + mainloop()