Skip to content

Commit 310c68a

Browse files
committed
The Redesign and Sound Update
A huge redesign with more features! [ADDED] - Optional sound effects based on the average value of compared elements - Customizable data types (random, reversed, sorted, etc.) - Big preview mode in level select screen - Extended, rewritten descriptions of all levels with pseudocode [REMOVED] - Tier system - Sizes of 8, 128, and 256
2 parents 5373b9e + 5abdf55 commit 310c68a

26 files changed

+876
-402
lines changed

CONTRIBUTING.md

-4
This file was deleted.

README.md

+8-20
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,23 @@
11
<br />
22
<p align="center">
3-
<img src="assets/icon.png" alt="Logo" width="80" height="80">
3+
<img src="assets/icon.png" alt="Logo" width="64" height="64">
44

55
<h1 align="center">Human Computer Simulator</h1>
66

77
<p align="center">
8-
A game where you get to become your favorite algorithm or data structure!
9-
<br />
10-
<a href="https://github.com/DanielZTing/human-computer-simulator/issues/new?template=bug_report.md">Report Bug</a>
11-
·
12-
<a href="https://github.com/DanielZTing/human-computer-simulator/issues/new?template=feature_request.md">Request Feature</a>
8+
Become your favorite sorting algorithm!
139
</p>
1410
</p>
1511

16-
## Table of Contents
17-
18-
* [About the Project](#about-the-project)
19-
* [Getting Started](#getting-started)
20-
21-
## About The Project
22-
2312
![Level select screen](assets/levels.png)
13+
Have you ever wondered what it feels like to be a sorting algorithm‽ Now you can find out! In *Human Computer Simulator*, you control an algorithm operating on an array, trying to sort as fast as possible. With 10 different levels, a cool visualization, and optional sound effects, you can fulfill your sorting dreams...
2414

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?
26-
27-
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.
15+
A demo (large download warning: ~5 MB gzipped) is available on this repository's [Github Pages](https://danielzting.github.io/human-computer-simulator). It requires a desktop browser with support for WebAssembly and WebGL.
2816

29-
It's written using the Godot game engine and licensed with [almost no restrictions](LICENSE.txt). Use it to make a lecture a bit more interesting, review for an assignment, or just kill time. Hope you enjoy.
17+
## Anti-pitch
3018

31-
## Getting Started
19+
This is beta software, so there will inevitably be things that are confusing, broken, or straight up wrong. See the [issues](https://github.com/DanielZTing/human-computer-simulator/issues) for a list of caveats and don't hesitate to open another one if you find something new.
3220

33-
This software is in an alpha stage of development and I do not plan on releasing ready-to-run builds until a stable v1.0 release. However, it is very easy to run and hack the source code yourself. Just grab the lightweight free and open source [Godot game engine](https://godotengine.org/download), import the `project.godot` file, and hit the play button.
21+
## Contributing
3422

35-
A demo version (large download warning: ~20 MB) is available on this repository's [Github Pages](https://danielzting.github.io/human-computer-simulator). It requires a desktop browser with support for WebAssembly and WebGL; mobile is not currently supported. Since this is still in alpha, some things might be dumb, make no sense whatsoever, or just break outright. I welcome any feedback you may have.
23+
I welcome any bug reports or feature requests. Pull requests are appreciated as well, though I apologize for my code in advance. If you like this so much that you want to [throw money at me](https://venmo.com/DanielZTing), I will add any 80x24 ASCII text block of your choosing to the README and credits.

assets/levels.png

31 KB
Loading

levels/bogo_sort.gd

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
"""
2-
BOGOSORT
1+
class_name BogoSort
2+
extends ComparisonSort
33

4+
const NAME = "BOGOSORT"
5+
const DESCRIPTION = """
46
Generates random permutations until the array is sorted.
5-
7+
"""
8+
const CONTROLS = """
69
Keep on hitting RIGHT ARROW to CONTINUE and hope for the best!
710
"""
8-
9-
class_name BogoSort
10-
extends ComparisonSort
11+
const CODE = """
12+
def bogosort(a):
13+
while not a.sorted():
14+
a.shuffle()
15+
"""
1116

1217
func _init(array).(array):
1318
pass
@@ -19,3 +24,6 @@ func next(action):
1924

2025
func get_effect(i):
2126
return EFFECTS.NONE
27+
28+
func get_frac():
29+
return array.frac(0)

levels/bubble_sort.gd

+28-11
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
1-
"""
2-
BUBBLE SORT
1+
class_name BubbleSort
2+
extends ComparisonSort
33

4-
Bubble sort iterates through the array and looks at each pair of
5-
elements, swapping them if they are out of order. When it has gone
6-
through the entire array without swapping a single pair, it has
7-
finished. Though simple to understand, bubble sort is hopelessly
8-
inefficient on all but the smallest of arrays.
4+
const NAME = "BUBBLE SORT"
5+
const DESCRIPTION = """
6+
Bubble sort looks at consecutive pairs of elements and swaps them if
7+
they are out of order, finishing when it has gone through the whole
8+
array from beginning to end without a single swap. The actual level
9+
contains an optimization that skips over elements guaranteed to be
10+
already in place.
911
12+
Due to its simplicity, it is commonly taught as the first sorting
13+
algorithm students learn in computer science classes, but is rarely used
14+
in real life because it is slow on large data and other simple quadratic
15+
algorithms like insertion sort perform better.
16+
"""
17+
const CONTROLS = """
1018
If the two highlighted elements are out of order, hit LEFT ARROW to swap
1119
them. Otherwise, hit RIGHT ARROW to continue.
1220
"""
13-
14-
class_name BubbleSort
15-
extends ComparisonSort
16-
21+
const CODE = """
22+
def bubble_sort(a):
23+
swapped = true
24+
while swapped:
25+
swapped = false
26+
for i in range(len(a) - 1):
27+
if a[i] > a[i + 1]:
28+
a.swap(i, i + 1)
29+
swapped = true
30+
"""
1731
const ACTIONS = {
1832
"SWAP": "Left",
1933
"CONTINUE": "Right",
@@ -48,3 +62,6 @@ func get_effect(i):
4862
if i >= _end:
4963
return EFFECTS.DIMMED
5064
return EFFECTS.NONE
65+
66+
func get_frac():
67+
return (array.frac(_index) + array.frac(_index + 1)) / 2.0

levels/cocktail_sort.gd renamed to levels/cocktail_shaker_sort.gd

+31-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
1-
"""
2-
COCKTAIL SORT
1+
class_name CocktailSort
2+
extends ComparisonSort
33

4-
Cocktail shaker sort is a variation of bubble sort that
5-
alternates going backwards and forwards.
4+
const NAME = "COCKTAIL SHAKER SORT"
5+
const DESCRIPTION = """
6+
Cocktail shaker sort is a variation of bubble sort that alternates going
7+
backwards and forwards. The actual level contains an optimization that
8+
skips over elements guaranteed to be already in place.
69
10+
Because it is bidirectional, it is slightly faster than bubble sort, but
11+
is still quadratic and therefore not used on large data.
12+
"""
13+
const CONTROLS = """
714
If the two highlighted elements are out of order, hit LEFT ARROW to swap
815
them. Otherwise, hit RIGHT ARROW to continue.
916
"""
10-
11-
class_name CocktailSort
12-
extends ComparisonSort
13-
17+
const CODE = """
18+
def cocktail_shaker_sort(a):
19+
swapped = true
20+
while swapped:
21+
swapped = false
22+
for i in range(len(a) - 1):
23+
if array[i] > array[i + 1]:
24+
a.swap(i, i + 1)
25+
swapped = true
26+
if not swapped:
27+
break
28+
swapped = false
29+
for i in range(len(a) - 1, 0, -1)
30+
if a[i - 1] > a[i]:
31+
a.swap(i - 1, i)
32+
swapped = true
33+
"""
1434
const ACTIONS = {
1535
"SWAP": "Left",
1636
"CONTINUE": "Right",
@@ -56,3 +76,6 @@ func get_effect(i):
5676
if i < _sorted and _forwards == true or i < _sorted - 1 or i >= array.size - _sorted:
5777
return EFFECTS.DIMMED
5878
return EFFECTS.NONE
79+
80+
func get_frac():
81+
return (array.frac(_index) + array.frac(_index + 1)) / 2.0

levels/comb_sort.gd

+28-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,33 @@
1-
"""
2-
COMB SORT
1+
class_name CombSort
2+
extends ComparisonSort
33

4-
Comb sort is a variant of bubble sort that operates on gapped arrays.
4+
const NAME = "COMB SORT"
5+
const DESCRIPTION = """
6+
Comb sort is a variant of bubble sort that compares elements a certain
7+
gap apart instead of consecutive elements. This gap is divided after
8+
every pass by an experimentally determined optimal factor of about 1.3.
9+
Once the gap becomes 1, comb sort becomes a regular bubble sort.
510
11+
This allows comb sort to get rid of small values near the end more
12+
quickly, which turns out to be the bottleneck in bubble sort, but still
13+
has a quadratic worst case.
14+
"""
15+
const CONTROLS = """
616
If the two highlighted elements are out of order, hit LEFT ARROW to swap
717
them. Otherwise, hit RIGHT ARROW to continue.
818
"""
9-
10-
class_name CombSort
11-
extends ComparisonSort
12-
19+
const CODE = """
20+
def comb_sort(a):
21+
gap = len(a)
22+
swapped = true
23+
while gap != 1 or swapped:
24+
swapped = false
25+
gap = max(gap / 1.3, 1)
26+
for i in range(len(a) - gap):
27+
if a[i] > a[i + gap]:
28+
a.swap(i, i + gap)
29+
swapped = true
30+
"""
1331
const SHRINK_FACTOR = 1.3
1432
const ACTIONS = {
1533
"SWAP": "Left",
@@ -46,3 +64,6 @@ func get_effect(i):
4664
if i >= _end:
4765
return EFFECTS.DIMMED
4866
return EFFECTS.NONE
67+
68+
func get_frac():
69+
return (array.frac(_index) + array.frac(_index + _gap)) / 2.0

levels/comparison_sort.gd

-9
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,8 @@ 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]
1714

1815
var array: ArrayModel
19-
var moves = 0
20-
var test = _get_header().split(" ")[0]
2116

2217
var _timer = Timer.new()
2318

@@ -30,16 +25,12 @@ func _init(array):
3025
self.connect("mistake", self, "_on_ComparisonSort_mistake")
3126
self.connect("done", self, "_on_ComparisonSort_done")
3227

33-
func _get_header():
34-
return get_script().source_code.replace("\n", " ").split('"""')[1].strip_edges()
35-
3628
func _ready():
3729
set_process_input(false)
3830

3931
func _input(event):
4032
"""Pass input events for checking and take appropriate action."""
4133
if event.is_pressed():
42-
moves += 1
4334
return next(event.as_text())
4435

4536
func next(action):

levels/cycle_sort.gd

+39-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,38 @@
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-
121
class_name CycleSort
132
extends ComparisonSort
143

4+
const NAME = "CYCLE SORT"
5+
const DESCRIPTION = """
6+
Cycle sort looks at the first element and finds its correct final
7+
position by counting the number of elements smaller than it. Then it
8+
saves the element at that index, writes the first element there, and
9+
repeats the process with the saved element. For the sake of
10+
demonstration, in the actual level, swaps are used instead.
11+
12+
This results in a quadratic runtime but gives it the special property
13+
of being optimal in the number of writes to the array. This makes cycle
14+
sort useful in situations where writes are very expensive.
15+
"""
16+
const CONTROLS = """
17+
If the highlighted element is less than the element below the blue
18+
pointer, hit LEFT ARROW. Otherwise, hit RIGHT ARROW.
19+
"""
20+
const CODE = """
21+
def cycle_sort(a):
22+
for i in range(len(a)):
23+
while True:
24+
less = equal = 0
25+
for element in a:
26+
if element < a[i]:
27+
less += 1
28+
elif element == a[i]:
29+
equal += 1
30+
if less <= i and i < less + equal:
31+
break
32+
while a[i] == a[less]:
33+
less += 1
34+
a.swap(i, less)
35+
"""
1536
const ACTIONS = {
1637
"SMALLER": "Left",
1738
"BIGGER": "Right",
@@ -33,8 +54,11 @@ func next(action):
3354
return emit_signal("mistake")
3455
_index += 1
3556
if _index == array.size:
57+
# Skip over duplicates to avoid infinite cycling
58+
while _smaller != _pointer and array.at(_pointer) == array.at(_smaller):
59+
_smaller += 1
3660
array.swap(_pointer, _smaller)
37-
while array.at(_pointer) == _pointer + 1:
61+
while array.is_in_place(_pointer):
3862
_pointer += 1
3963
if _pointer == array.size:
4064
return emit_signal("done")
@@ -48,3 +72,6 @@ func get_effect(i):
4872

4973
func get_pointer():
5074
return _pointer
75+
76+
func get_frac():
77+
return array.frac(_index)

levels/insertion_sort.gd

+25-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,28 @@
1-
"""
2-
INSERTION SORT
3-
4-
Insertion sort goes through the array and inserts each
5-
element into its correct position. It is most similar to how most people
6-
would sort a deck of cards. It is also slow on large arrays but it is
7-
one of the faster quadratic algorithms. It is often used to sort smaller
8-
subarrays in hybrid sorting algorithms.
9-
10-
Hit LEFT ARROW to swap the two highlighted elements as long as they are
11-
out of order. When this is no longer the case, hit RIGHT ARROW to
12-
advance.
13-
"""
14-
151
class_name InsertionSort
162
extends ComparisonSort
173

4+
const NAME = "INSERTION SORT"
5+
const DESCRIPTION = """
6+
Insertion sort goes through the array and inserts each element into its
7+
correct place, like how most people would sort a hand of playing cards.
8+
9+
It is one of the fastest quadratic algorithms in practice and is
10+
efficient on small or almost sorted data. It is also simple, stable, and
11+
in-place. For these reasons it is sometimes used within faster divide
12+
and conquer algorithms when the array has been divided to a small size.
13+
"""
14+
const CONTROLS = """
15+
If the two highlighted elements are out of order, hit LEFT ARROW to swap
16+
them. Otherwise, hit RIGHT ARROW to continue.
17+
"""
18+
const CODE = """
19+
def insertion_sort(a):
20+
for i in range(len(a)):
21+
j = i
22+
while j > 0 and a[j - 1] > a[j]:
23+
a.swap(j - 1, j)
24+
j -= 1
25+
"""
1826
const ACTIONS = {
1927
"SWAP": "Left",
2028
"CONTINUE": "Right",
@@ -50,3 +58,6 @@ func _grow():
5058
if _end == array.size:
5159
emit_signal("done")
5260
_index = _end
61+
62+
func get_frac():
63+
return (array.frac(_index - 1) + array.frac(_index)) / 2.0

0 commit comments

Comments
 (0)