Skip to content

Commit

Permalink
More Sorts!
Browse files Browse the repository at this point in the history
A total of ten sorts are now playable!

[ADDED]
- Cocktail sort, shell sort, comb sort, cycle sort, and odd-even sort
  • Loading branch information
danielzting committed Aug 20, 2020
2 parents 3eeca62 + 8712c98 commit 5373b9e
Show file tree
Hide file tree
Showing 24 changed files with 461 additions and 145 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

![Level select screen](assets/levels.png)

You may have come across the famous [15 Sorting Algorithms in 6 Minutes](https://www.youtube.com/watch?v=kPRA0W1kECg) video by [Timo Bingoman](https://github.com/bingmann) at some point in your computer science career. There is currently no shortage of neat visualizations of all kinds of algorithms, but what if you could become the algorithm itself?
You may have come across the famous [15 Sorting Algorithms in 6 Minutes](https://www.youtube.com/watch?v=kPRA0W1kECg) video by [Timo Bingmann](https://github.com/bingmann) at some point in your computer science career. There is currently no shortage of neat visualizations of all kinds of algorithms, but what if you could become the algorithm itself?

In *Human Computer Simulator*, you control an algorithm operating on some data structure. Right now, the game is limited to sorting arrays. The end vision is to have a library of interactive, playable levels on anything from a search on a binary tree to Dijkstra's shortest path on a graph.

Expand Down
12 changes: 6 additions & 6 deletions levels/bogo_sort.gd
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
class_name BogoSort
extends ComparisonSort
"""
BOGOSORT
const NAME = "BOGOSORT"
const ABOUT = """
Generates random permutations until the array is sorted.
"""
const CONTROLS = """
Keep on hitting RIGHT ARROW to CONTINUE and hope for the best!
"""

class_name BogoSort
extends ComparisonSort

func _init(array).(array):
pass

Expand Down
12 changes: 6 additions & 6 deletions levels/bubble_sort.gd
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
class_name BubbleSort
extends ComparisonSort
"""
BUBBLE SORT
const NAME = "BUBBLE SORT"
const ABOUT = """
Bubble sort iterates through the array and looks at each pair of
elements, swapping them if they are out of order. When it has gone
through the entire array without swapping a single pair, it has
finished. Though simple to understand, bubble sort is hopelessly
inefficient on all but the smallest of arrays.
"""
const CONTROLS = """
If the two highlighted elements are out of order, hit LEFT ARROW to swap
them. Otherwise, hit RIGHT ARROW to continue.
"""

class_name BubbleSort
extends ComparisonSort

const ACTIONS = {
"SWAP": "Left",
"CONTINUE": "Right",
Expand Down
58 changes: 58 additions & 0 deletions levels/cocktail_sort.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""
COCKTAIL SORT
Cocktail shaker sort is a variation of bubble sort that
alternates going backwards and forwards.
If the two highlighted elements are out of order, hit LEFT ARROW to swap
them. Otherwise, hit RIGHT ARROW to continue.
"""

class_name CocktailSort
extends ComparisonSort

const ACTIONS = {
"SWAP": "Left",
"CONTINUE": "Right",
}
var _index = 0 # First of two elements being compared
var _sorted = 0 # Size of the sorted subarray at the end of the array
var _forwards = true
var _swapped = false

func _init(array).(array):
pass

func next(action):
if array.at(_index) > array.at(_index + 1):
if action != null and action != ACTIONS.SWAP:
return emit_signal("mistake")
array.swap(_index, _index + 1)
_swapped = true
else:
if action != null and action != ACTIONS.CONTINUE:
return emit_signal("mistake")
if _forwards:
_index += 1
if _index == array.size - _sorted - 1:
if not _swapped:
emit_signal("done")
_swapped = false
_forwards = false
_index -= 2
_sorted += 1
else:
_index -= 1
if _index == _sorted - 2:
if not _swapped:
emit_signal("done")
_swapped = false
_forwards = true
_index += 2

func get_effect(i):
if i == _index or i == _index + 1:
return EFFECTS.HIGHLIGHTED
if i < _sorted and _forwards == true or i < _sorted - 1 or i >= array.size - _sorted:
return EFFECTS.DIMMED
return EFFECTS.NONE
48 changes: 48 additions & 0 deletions levels/comb_sort.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""
COMB SORT
Comb sort is a variant of bubble sort that operates on gapped arrays.
If the two highlighted elements are out of order, hit LEFT ARROW to swap
them. Otherwise, hit RIGHT ARROW to continue.
"""

class_name CombSort
extends ComparisonSort

const SHRINK_FACTOR = 1.3
const ACTIONS = {
"SWAP": "Left",
"CONTINUE": "Right",
}
var _gap: int = array.size / SHRINK_FACTOR
var _index = 0 # First of two elements being compared
var _end = array.size # Beginning of sorted subarray
var _swapped = false

func _init(array).(array):
pass

func next(action):
if array.at(_index) > array.at(_index + _gap):
if action != null and action != ACTIONS.SWAP:
return emit_signal("mistake")
array.swap(_index, _index + _gap)
_swapped = true
elif action != null and action != ACTIONS.CONTINUE:
return emit_signal("mistake")
_index += 1
if _index + _gap >= array.size:
if not _swapped and _gap == 1:
emit_signal("done")
_gap /= SHRINK_FACTOR
_gap = max(_gap, 1)
_index = 0
_swapped = false

func get_effect(i):
if i == _index or i == _index + _gap:
return EFFECTS.HIGHLIGHTED
if i >= _end:
return EFFECTS.DIMMED
return EFFECTS.NONE
26 changes: 13 additions & 13 deletions levels/comparison_sort.gd
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ const EFFECTS = {
}

const DISABLE_TIME = 1.0
var NAME = _get_header().split(" ")[0]
var DESCRIPTION = _get_header().split(" ")[1]
var CONTROLS = _get_header().split(" ")[2]

var array: ArrayModel
var active = true
var done = false
var moves = 0
var test = _get_header().split(" ")[0]

var _timer = Timer.new()

Expand All @@ -28,10 +30,14 @@ func _init(array):
self.connect("mistake", self, "_on_ComparisonSort_mistake")
self.connect("done", self, "_on_ComparisonSort_done")

func _get_header():
return get_script().source_code.replace("\n", " ").split('"""')[1].strip_edges()

func _ready():
set_process_input(false)

func _input(event):
"""Pass input events for checking and take appropriate action."""
if done or not active:
return
if event.is_pressed():
moves += 1
return next(event.as_text())
Expand All @@ -40,20 +46,14 @@ func next(action):
"""Check the action and advance state or emit signal as needed."""
push_error("NotImplementedError")

func get_effect(i):
return get_effect(i)

func _get_effect(i):
push_error("NotImplementedError")

func _on_ComparisonSort_done():
done = true
set_process_input(false)

func _on_ComparisonSort_mistake():
"""Disable the controls for one second."""
active = false
set_process_input(false)
_timer.start(DISABLE_TIME)

func _on_Timer_timeout():
"""Reenable the controls."""
active = true
set_process_input(true)
50 changes: 50 additions & 0 deletions levels/cycle_sort.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
CYCLE SORT
Cycle sort repeatedly counts the number of elements less than the first
and swaps it with that index until the smallest element is reached. Then
it does this process starting at the next out-of-place element.
If the highlighted element is less than the pointer, hit LEFT ARROW.
Otherwise, hit RIGHT ARROW.
"""

class_name CycleSort
extends ComparisonSort

const ACTIONS = {
"SMALLER": "Left",
"BIGGER": "Right",
}
var _pointer = 0
var _index = 0
var _smaller = 0

func _init(array).(array):
pass

func next(action):
if array.at(_index) < array.at(_pointer):
if action != null and action != ACTIONS.SMALLER:
return emit_signal("mistake")
_smaller += 1
elif array.at(_index) >= array.at(_pointer):
if action != null and action != ACTIONS.BIGGER:
return emit_signal("mistake")
_index += 1
if _index == array.size:
array.swap(_pointer, _smaller)
while array.at(_pointer) == _pointer + 1:
_pointer += 1
if _pointer == array.size:
return emit_signal("done")
_index = 0
_smaller = 0

func get_effect(i):
if i == _index:
return EFFECTS.HIGHLIGHTED
return EFFECTS.NONE

func get_pointer():
return _pointer
12 changes: 6 additions & 6 deletions levels/insertion_sort.gd
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
class_name InsertionSort
extends ComparisonSort
"""
INSERTION SORT
const NAME = "INSERTION SORT"
const ABOUT = """
Insertion sort goes through the array and inserts each
element into its correct position. It is most similar to how most people
would sort a deck of cards. It is also slow on large arrays but it is
one of the faster quadratic algorithms. It is often used to sort smaller
subarrays in hybrid sorting algorithms.
"""
const CONTROLS = """
Hit LEFT ARROW to swap the two highlighted elements as long as they are
out of order. When this is no longer the case, hit RIGHT ARROW to
advance.
"""

class_name InsertionSort
extends ComparisonSort

const ACTIONS = {
"SWAP": "Left",
"CONTINUE": "Right",
Expand Down
12 changes: 6 additions & 6 deletions levels/merge_sort.gd
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
class_name MergeSort
extends ComparisonSort
"""
MERGE SORT
const NAME = "MERGE SORT"
const ABOUT = """
Merge sort is an efficient sorting algorithm that splits the array into
single-element chunks. Then it merges each pair of chunks until only one
sorted chunk is left by repeatedly choosing the smaller element at the
head of each chunk and moving the head back. However, it needs an entire
array's worth of auxiliary memory.
"""
const CONTROLS = """
Press the ARROW KEY corresponding to the side that the smaller
highlighted element is on. If you've reached the end of one side, press
the other side's ARROW KEY.
"""

class_name MergeSort
extends ComparisonSort

const ACTIONS = {
"LEFT": "Left",
"RIGHT": "Right",
Expand Down
42 changes: 42 additions & 0 deletions levels/odd_even_sort.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
ODD-EVEN SORT
Odd-even sort is a variant of bubble sort that alternates on elements at
odd and even indices.
If the two highlighted elements are out of order, hit LEFT ARROW to swap
them. Otherwise, hit RIGHT ARROW to continue.
"""

class_name OddEvenSort
extends ComparisonSort

const ACTIONS = {
"SWAP": "Left",
"CONTINUE": "Right",
}
var _index = 1
var _swapped = false

func _init(array).(array):
pass

func next(action):
if array.at(_index) > array.at(_index + 1):
if action != null and action != ACTIONS.SWAP:
return emit_signal("mistake")
array.swap(_index, _index + 1)
_swapped = true
elif action != null and action != ACTIONS.CONTINUE:
return emit_signal("mistake")
_index += 2
if _index + 1 >= array.size:
if _index % 2 == 0 and not _swapped:
emit_signal("done")
_index = 1 if _index % 2 == 0 else 0
_swapped = false

func get_effect(i):
if i == _index or i == _index + 1:
return EFFECTS.HIGHLIGHTED
return EFFECTS.NONE
Loading

0 comments on commit 5373b9e

Please sign in to comment.