Skip to content

Commit 5373b9e

Browse files
committed
More Sorts!
A total of ten sorts are now playable! [ADDED] - Cocktail sort, shell sort, comb sort, cycle sort, and odd-even sort
2 parents 3eeca62 + 8712c98 commit 5373b9e

24 files changed

+461
-145
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

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

25-
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?
25+
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?
2626

2727
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.
2828

levels/bogo_sort.gd

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
class_name BogoSort
2-
extends ComparisonSort
1+
"""
2+
BOGOSORT
33
4-
const NAME = "BOGOSORT"
5-
const ABOUT = """
64
Generates random permutations until the array is sorted.
7-
"""
8-
const CONTROLS = """
5+
96
Keep on hitting RIGHT ARROW to CONTINUE and hope for the best!
107
"""
118

9+
class_name BogoSort
10+
extends ComparisonSort
11+
1212
func _init(array).(array):
1313
pass
1414

levels/bubble_sort.gd

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
class_name BubbleSort
2-
extends ComparisonSort
1+
"""
2+
BUBBLE SORT
33
4-
const NAME = "BUBBLE SORT"
5-
const ABOUT = """
64
Bubble sort iterates through the array and looks at each pair of
75
elements, swapping them if they are out of order. When it has gone
86
through the entire array without swapping a single pair, it has
97
finished. Though simple to understand, bubble sort is hopelessly
108
inefficient on all but the smallest of arrays.
11-
"""
12-
const CONTROLS = """
9+
1310
If the two highlighted elements are out of order, hit LEFT ARROW to swap
1411
them. Otherwise, hit RIGHT ARROW to continue.
1512
"""
1613

14+
class_name BubbleSort
15+
extends ComparisonSort
16+
1717
const ACTIONS = {
1818
"SWAP": "Left",
1919
"CONTINUE": "Right",

levels/cocktail_sort.gd

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
"""
2+
COCKTAIL SORT
3+
4+
Cocktail shaker sort is a variation of bubble sort that
5+
alternates going backwards and forwards.
6+
7+
If the two highlighted elements are out of order, hit LEFT ARROW to swap
8+
them. Otherwise, hit RIGHT ARROW to continue.
9+
"""
10+
11+
class_name CocktailSort
12+
extends ComparisonSort
13+
14+
const ACTIONS = {
15+
"SWAP": "Left",
16+
"CONTINUE": "Right",
17+
}
18+
var _index = 0 # First of two elements being compared
19+
var _sorted = 0 # Size of the sorted subarray at the end of the array
20+
var _forwards = true
21+
var _swapped = false
22+
23+
func _init(array).(array):
24+
pass
25+
26+
func next(action):
27+
if array.at(_index) > array.at(_index + 1):
28+
if action != null and action != ACTIONS.SWAP:
29+
return emit_signal("mistake")
30+
array.swap(_index, _index + 1)
31+
_swapped = true
32+
else:
33+
if action != null and action != ACTIONS.CONTINUE:
34+
return emit_signal("mistake")
35+
if _forwards:
36+
_index += 1
37+
if _index == array.size - _sorted - 1:
38+
if not _swapped:
39+
emit_signal("done")
40+
_swapped = false
41+
_forwards = false
42+
_index -= 2
43+
_sorted += 1
44+
else:
45+
_index -= 1
46+
if _index == _sorted - 2:
47+
if not _swapped:
48+
emit_signal("done")
49+
_swapped = false
50+
_forwards = true
51+
_index += 2
52+
53+
func get_effect(i):
54+
if i == _index or i == _index + 1:
55+
return EFFECTS.HIGHLIGHTED
56+
if i < _sorted and _forwards == true or i < _sorted - 1 or i >= array.size - _sorted:
57+
return EFFECTS.DIMMED
58+
return EFFECTS.NONE

levels/comb_sort.gd

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"""
2+
COMB SORT
3+
4+
Comb sort is a variant of bubble sort that operates on gapped arrays.
5+
6+
If the two highlighted elements are out of order, hit LEFT ARROW to swap
7+
them. Otherwise, hit RIGHT ARROW to continue.
8+
"""
9+
10+
class_name CombSort
11+
extends ComparisonSort
12+
13+
const SHRINK_FACTOR = 1.3
14+
const ACTIONS = {
15+
"SWAP": "Left",
16+
"CONTINUE": "Right",
17+
}
18+
var _gap: int = array.size / SHRINK_FACTOR
19+
var _index = 0 # First of two elements being compared
20+
var _end = array.size # Beginning of sorted subarray
21+
var _swapped = false
22+
23+
func _init(array).(array):
24+
pass
25+
26+
func next(action):
27+
if array.at(_index) > array.at(_index + _gap):
28+
if action != null and action != ACTIONS.SWAP:
29+
return emit_signal("mistake")
30+
array.swap(_index, _index + _gap)
31+
_swapped = true
32+
elif action != null and action != ACTIONS.CONTINUE:
33+
return emit_signal("mistake")
34+
_index += 1
35+
if _index + _gap >= array.size:
36+
if not _swapped and _gap == 1:
37+
emit_signal("done")
38+
_gap /= SHRINK_FACTOR
39+
_gap = max(_gap, 1)
40+
_index = 0
41+
_swapped = false
42+
43+
func get_effect(i):
44+
if i == _index or i == _index + _gap:
45+
return EFFECTS.HIGHLIGHTED
46+
if i >= _end:
47+
return EFFECTS.DIMMED
48+
return EFFECTS.NONE

levels/comparison_sort.gd

+13-13
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ const EFFECTS = {
1111
}
1212

1313
const DISABLE_TIME = 1.0
14+
var NAME = _get_header().split(" ")[0]
15+
var DESCRIPTION = _get_header().split(" ")[1]
16+
var CONTROLS = _get_header().split(" ")[2]
1417

1518
var array: ArrayModel
16-
var active = true
17-
var done = false
1819
var moves = 0
20+
var test = _get_header().split(" ")[0]
1921

2022
var _timer = Timer.new()
2123

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

33+
func _get_header():
34+
return get_script().source_code.replace("\n", " ").split('"""')[1].strip_edges()
35+
36+
func _ready():
37+
set_process_input(false)
38+
3139
func _input(event):
3240
"""Pass input events for checking and take appropriate action."""
33-
if done or not active:
34-
return
3541
if event.is_pressed():
3642
moves += 1
3743
return next(event.as_text())
@@ -40,20 +46,14 @@ func next(action):
4046
"""Check the action and advance state or emit signal as needed."""
4147
push_error("NotImplementedError")
4248

43-
func get_effect(i):
44-
return get_effect(i)
45-
46-
func _get_effect(i):
47-
push_error("NotImplementedError")
48-
4949
func _on_ComparisonSort_done():
50-
done = true
50+
set_process_input(false)
5151

5252
func _on_ComparisonSort_mistake():
5353
"""Disable the controls for one second."""
54-
active = false
54+
set_process_input(false)
5555
_timer.start(DISABLE_TIME)
5656

5757
func _on_Timer_timeout():
5858
"""Reenable the controls."""
59-
active = true
59+
set_process_input(true)

levels/cycle_sort.gd

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""
2+
CYCLE SORT
3+
4+
Cycle sort repeatedly counts the number of elements less than the first
5+
and swaps it with that index until the smallest element is reached. Then
6+
it does this process starting at the next out-of-place element.
7+
8+
If the highlighted element is less than the pointer, hit LEFT ARROW.
9+
Otherwise, hit RIGHT ARROW.
10+
"""
11+
12+
class_name CycleSort
13+
extends ComparisonSort
14+
15+
const ACTIONS = {
16+
"SMALLER": "Left",
17+
"BIGGER": "Right",
18+
}
19+
var _pointer = 0
20+
var _index = 0
21+
var _smaller = 0
22+
23+
func _init(array).(array):
24+
pass
25+
26+
func next(action):
27+
if array.at(_index) < array.at(_pointer):
28+
if action != null and action != ACTIONS.SMALLER:
29+
return emit_signal("mistake")
30+
_smaller += 1
31+
elif array.at(_index) >= array.at(_pointer):
32+
if action != null and action != ACTIONS.BIGGER:
33+
return emit_signal("mistake")
34+
_index += 1
35+
if _index == array.size:
36+
array.swap(_pointer, _smaller)
37+
while array.at(_pointer) == _pointer + 1:
38+
_pointer += 1
39+
if _pointer == array.size:
40+
return emit_signal("done")
41+
_index = 0
42+
_smaller = 0
43+
44+
func get_effect(i):
45+
if i == _index:
46+
return EFFECTS.HIGHLIGHTED
47+
return EFFECTS.NONE
48+
49+
func get_pointer():
50+
return _pointer

levels/insertion_sort.gd

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
class_name InsertionSort
2-
extends ComparisonSort
1+
"""
2+
INSERTION SORT
33
4-
const NAME = "INSERTION SORT"
5-
const ABOUT = """
64
Insertion sort goes through the array and inserts each
75
element into its correct position. It is most similar to how most people
86
would sort a deck of cards. It is also slow on large arrays but it is
97
one of the faster quadratic algorithms. It is often used to sort smaller
108
subarrays in hybrid sorting algorithms.
11-
"""
12-
const CONTROLS = """
9+
1310
Hit LEFT ARROW to swap the two highlighted elements as long as they are
1411
out of order. When this is no longer the case, hit RIGHT ARROW to
1512
advance.
1613
"""
1714

15+
class_name InsertionSort
16+
extends ComparisonSort
17+
1818
const ACTIONS = {
1919
"SWAP": "Left",
2020
"CONTINUE": "Right",

levels/merge_sort.gd

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
class_name MergeSort
2-
extends ComparisonSort
1+
"""
2+
MERGE SORT
33
4-
const NAME = "MERGE SORT"
5-
const ABOUT = """
64
Merge sort is an efficient sorting algorithm that splits the array into
75
single-element chunks. Then it merges each pair of chunks until only one
86
sorted chunk is left by repeatedly choosing the smaller element at the
97
head of each chunk and moving the head back. However, it needs an entire
108
array's worth of auxiliary memory.
11-
"""
12-
const CONTROLS = """
9+
1310
Press the ARROW KEY corresponding to the side that the smaller
1411
highlighted element is on. If you've reached the end of one side, press
1512
the other side's ARROW KEY.
1613
"""
1714

15+
class_name MergeSort
16+
extends ComparisonSort
17+
1818
const ACTIONS = {
1919
"LEFT": "Left",
2020
"RIGHT": "Right",

levels/odd_even_sort.gd

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
"""
2+
ODD-EVEN SORT
3+
4+
Odd-even sort is a variant of bubble sort that alternates on elements at
5+
odd and even indices.
6+
7+
If the two highlighted elements are out of order, hit LEFT ARROW to swap
8+
them. Otherwise, hit RIGHT ARROW to continue.
9+
"""
10+
11+
class_name OddEvenSort
12+
extends ComparisonSort
13+
14+
const ACTIONS = {
15+
"SWAP": "Left",
16+
"CONTINUE": "Right",
17+
}
18+
var _index = 1
19+
var _swapped = false
20+
21+
func _init(array).(array):
22+
pass
23+
24+
func next(action):
25+
if array.at(_index) > array.at(_index + 1):
26+
if action != null and action != ACTIONS.SWAP:
27+
return emit_signal("mistake")
28+
array.swap(_index, _index + 1)
29+
_swapped = true
30+
elif action != null and action != ACTIONS.CONTINUE:
31+
return emit_signal("mistake")
32+
_index += 2
33+
if _index + 1 >= array.size:
34+
if _index % 2 == 0 and not _swapped:
35+
emit_signal("done")
36+
_index = 1 if _index % 2 == 0 else 0
37+
_swapped = false
38+
39+
func get_effect(i):
40+
if i == _index or i == _index + 1:
41+
return EFFECTS.HIGHLIGHTED
42+
return EFFECTS.NONE

0 commit comments

Comments
 (0)