-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Every level but one of what I consider the "five basic sorts" is available except for quicksort, because its complexity warrants new features that belong in a later update. [ADDED] - Insertion sort, selection sort, and merge sort - A new "dimmed" color style to aid visual comprehension
- Loading branch information
Showing
20 changed files
with
473 additions
and
169 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
[remap] | ||
|
||
importer="texture" | ||
type="StreamTexture" | ||
path="res://.import/levels.png-a6e910382d32e95b5c3f382bb559bde4.stex" | ||
metadata={ | ||
"vram_texture": false | ||
} | ||
|
||
[deps] | ||
|
||
source_file="res://assets/levels.png" | ||
dest_files=[ "res://.import/levels.png-a6e910382d32e95b5c3f382bb559bde4.stex" ] | ||
|
||
[params] | ||
|
||
compress/mode=0 | ||
compress/lossy_quality=0.7 | ||
compress/hdr_mode=0 | ||
compress/bptc_ldr=0 | ||
compress/normal_map=0 | ||
flags/repeat=0 | ||
flags/filter=true | ||
flags/mipmaps=false | ||
flags/anisotropic=false | ||
flags/srgb=2 | ||
process/fix_alpha_border=true | ||
process/premult_alpha=false | ||
process/HDR_as_SRGB=false | ||
process/invert_color=false | ||
stream=false | ||
size_limit=0 | ||
detect_3d=true | ||
svg/scale=1.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,21 @@ | ||
extends ComparisonSort | ||
class_name BogoSort | ||
extends ComparisonSort | ||
|
||
func _init(array).(array): | ||
pass | ||
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! | ||
""" | ||
|
||
func check(action): | ||
return true | ||
func _init(array).(array): | ||
pass | ||
|
||
func next(): | ||
array = ArrayModel.new(array.size) | ||
func next(action): | ||
array = ArrayModel.new(array.size) | ||
if array.is_sorted(): | ||
emit_signal("done") | ||
|
||
func emphasized(i): | ||
return false | ||
func get_effect(i): | ||
return EFFECTS.NONE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,46 @@ | ||
extends ComparisonSort | ||
class_name BubbleSort | ||
extends ComparisonSort | ||
|
||
var swapped = false | ||
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. | ||
""" | ||
|
||
func _init(array).(array): | ||
pass | ||
var _index = 0 # First of two elements being compared | ||
var _end = array.size # Beginning of sorted subarray | ||
var _swapped = false | ||
|
||
func check(action): | ||
if array.get(index) > array.get(index + 1): | ||
return action == "swap" | ||
else: | ||
return action == "no_swap" | ||
func _init(array).(array): | ||
pass | ||
|
||
func next(): | ||
if array.get(index) > array.get(index + 1): | ||
array.swap(index, index + 1) | ||
swapped = true | ||
index += 1 | ||
if index == array.size - 1: | ||
if not swapped: | ||
emit_signal("done") | ||
index = 0 | ||
swapped = false | ||
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.NO_SWAP: | ||
return emit_signal("mistake") | ||
_index += 1 | ||
# Prevent player from having to spam tap through the end | ||
if _index + 1 == _end: | ||
if not _swapped or _end == 2: # Stop if only one element left | ||
emit_signal("done") | ||
_index = 0 | ||
_end -= 1 | ||
_swapped = false | ||
|
||
func emphasized(i): | ||
return i == index or i == index + 1 | ||
func get_effect(i): | ||
if i == _index or i == _index + 1: | ||
return EFFECTS.HIGHLIGHTED | ||
if i >= _end: | ||
return EFFECTS.DIMMED | ||
return EFFECTS.NONE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,43 +1,55 @@ | ||
extends Node | ||
class_name ComparisonSort | ||
extends Node | ||
|
||
signal done | ||
signal mistake | ||
|
||
const ACTIONS = ["swap", "no_swap"] | ||
const ACTIONS = { | ||
"SWAP": "ui_left", | ||
"NO_SWAP": "ui_right", | ||
|
||
"LEFT": "ui_left", | ||
"RIGHT": "ui_right", | ||
} | ||
|
||
const EFFECTS = { | ||
"NONE": GlobalTheme.GREEN, | ||
"HIGHLIGHTED": GlobalTheme.ORANGE, | ||
"DIMMED": GlobalTheme.DARK_GREEN, | ||
} | ||
|
||
const DISABLE_TIME = 1.0 | ||
|
||
var array: ArrayModel | ||
var index = 0 | ||
var timer = Timer.new() | ||
var active = true | ||
|
||
var _timer = Timer.new() | ||
|
||
func _init(array): | ||
self.array = array | ||
timer.one_shot = true | ||
timer.connect("timeout", self, "_on_Timer_timeout") | ||
add_child(timer) | ||
self.connect("mistake", self, "_on_ComparisonSort_mistake") | ||
"""Initialize array and timer.""" | ||
self.array = array | ||
_timer.one_shot = true | ||
_timer.connect("timeout", self, "_on_Timer_timeout") | ||
add_child(_timer) | ||
self.connect("mistake", self, "_on_ComparisonSort_mistake") | ||
|
||
func check(action): | ||
pass | ||
func _input(event): | ||
"""Pass input events for checking and take appropriate action.""" | ||
if not active: | ||
return | ||
for action in ACTIONS.values(): | ||
if event.is_action_pressed(action): | ||
return next(action) | ||
|
||
func next(): | ||
pass | ||
func next(action): | ||
"""Check the action and advance state or emit signal as needed.""" | ||
push_error("NotImplementedError") | ||
|
||
func _on_ComparisonSort_mistake(): | ||
active = false | ||
timer.start(1) | ||
"""Disable the controls for one second.""" | ||
active = false | ||
_timer.start(DISABLE_TIME) | ||
|
||
func _on_Timer_timeout(): | ||
active = true | ||
|
||
func _input(event): | ||
if not active: | ||
return | ||
|
||
for action in ACTIONS: | ||
if event.is_action_pressed(action): | ||
if check(action): | ||
next() | ||
else: | ||
emit_signal("mistake") | ||
"""Reenable the controls.""" | ||
active = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
class_name InsertionSort | ||
extends ComparisonSort | ||
|
||
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. | ||
""" | ||
|
||
var _end = 1 # Size of the sorted subarray | ||
var _index = 1 # Position of element currently being inserted | ||
|
||
func _init(array).(array): | ||
pass | ||
|
||
func next(action): | ||
if array.at(_index - 1) > array.at(_index): | ||
if action != null and action != ACTIONS.SWAP: | ||
return emit_signal("mistake") | ||
array.swap(_index - 1, _index) | ||
_index -= 1 | ||
if _index == 0: | ||
_grow() | ||
else: | ||
if action != null and action != ACTIONS.NO_SWAP: | ||
return emit_signal("mistake") | ||
_grow() | ||
|
||
func get_effect(i): | ||
if i == _index or i == _index - 1: | ||
return EFFECTS.HIGHLIGHTED | ||
if i < _end: | ||
return EFFECTS.DIMMED | ||
return EFFECTS.NONE | ||
|
||
func _grow(): | ||
_end += 1 | ||
if _end == array.size: | ||
emit_signal("done") | ||
_index = _end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
class_name MergeSort | ||
extends ComparisonSort | ||
|
||
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. | ||
""" | ||
|
||
var _left = 0 # Index of left subarray pointer | ||
var _right = 1 # Index of right subarray pointer | ||
var _sub_size = 2 # Combined size of left and right subarrays | ||
var _sub_no = 0 # Currently being merged left-right pair number | ||
|
||
func _init(array).(array): | ||
pass | ||
|
||
func next(action): | ||
if _left == _get_middle(): | ||
if action != null and action != ACTIONS.RIGHT: | ||
return emit_signal("mistake") | ||
_right += 1 | ||
elif _right == _get_end(): | ||
if action != null and action != ACTIONS.LEFT: | ||
return emit_signal("mistake") | ||
_left += 1 | ||
elif array.at(_left) <= array.at(_right): | ||
if action != null and action != ACTIONS.LEFT: | ||
return emit_signal("mistake") | ||
_left += 1 | ||
else: | ||
if action != null and action != ACTIONS.RIGHT: | ||
return emit_signal("mistake") | ||
_right += 1 | ||
# If both ends have been reached, merge and advance to next block | ||
if _left == _get_middle() and _right == _get_end(): | ||
array.sort(_get_begin(), _get_end()) | ||
_sub_no += 1 | ||
# If last block has been completed, go up a level | ||
if _sub_no == array.size / (_sub_size): | ||
_sub_size *= 2 | ||
_sub_no = 0 | ||
if _sub_size == array.size * 2: | ||
emit_signal("done") | ||
# Update pointers | ||
_left = _get_begin() | ||
_right = _get_middle() | ||
|
||
func get_effect(i): | ||
var is_left = _left != _get_middle() and i == _left | ||
var is_right = _right != _get_end() and i == _right | ||
if is_left or is_right: | ||
return EFFECTS.HIGHLIGHTED | ||
if i < _left or i >= _get_middle() and i < _right or i >= _get_end(): | ||
return EFFECTS.DIMMED | ||
return EFFECTS.NONE | ||
|
||
func _get_begin(): | ||
"""Get the index of the left subarray's head.""" | ||
return _sub_no * _sub_size | ||
|
||
func _get_middle(): | ||
"""Get the index of the right subarray's head.""" | ||
return _sub_no * _sub_size + _sub_size / 2 | ||
|
||
func _get_end(): | ||
"""Get the index of one past the right subarray's tail.""" | ||
return _sub_no * _sub_size + _sub_size |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
class_name SelectionSort | ||
extends ComparisonSort | ||
|
||
const NAME = "SELECTION SORT" | ||
const ABOUT = """ | ||
Selection sort incrementally builds a sorted array by repeatedly looking | ||
for the smallest element and swapping it onto the end of the sorted | ||
portion of the array, which initially starts with size zero but grows | ||
after each round. It is faster than an unoptimized bubble sort but | ||
slower than insertion sort. | ||
""" | ||
const CONTROLS = """ | ||
Keep on hitting RIGHT ARROW until you encounter an element that is | ||
smaller than the left highlighted element, then hit LEFT ARROW and | ||
repeat. | ||
""" | ||
|
||
var _base = 0 # Size of sorted subarray | ||
var _min = 0 # Index of smallest known element | ||
var _index = 1 # Element currently being compared | ||
|
||
func _init(array).(array): | ||
pass | ||
|
||
func next(action): | ||
if array.at(_index) < array.at(_min): | ||
if action != null and action != ACTIONS.SWAP: | ||
return emit_signal("mistake") | ||
_min = _index | ||
elif action != null and action != ACTIONS.NO_SWAP: | ||
return emit_signal("mistake") | ||
_index += 1 | ||
if _index == array.size: | ||
array.swap(_base, _min) | ||
_base += 1 | ||
_min = _base | ||
_index = _base + 1 | ||
if _base == array.size - 1: | ||
emit_signal("done") | ||
|
||
func get_effect(i): | ||
if i == _min or i == _index: | ||
return EFFECTS.HIGHLIGHTED | ||
if i < _base: | ||
return EFFECTS.DIMMED | ||
return EFFECTS.NONE |
Oops, something went wrong.