├── .github └── workflows │ └── ci.yaml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── assets └── Menlo-Regular.ttf ├── docs.sh ├── rustfmt.toml └── src ├── algorithms ├── all.rs ├── bubble.rs ├── cocktail.rs ├── cycle.rs ├── gnome.rs ├── heap.rs ├── insertion.rs ├── merge.rs ├── mod.rs ├── quicksort.rs ├── selection.rs └── shellsort.rs ├── app.rs ├── array.rs ├── cli.rs ├── main.rs └── state.rs /.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request, workflow_dispatch] 3 | 4 | env: 5 | CARGO_TERM_COLOR: always 6 | 7 | jobs: 8 | build: 9 | name: Build 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: Install Rust toolchain (nightly) 15 | id: install_rust 16 | uses: actions-rs/toolchain@v1 17 | with: 18 | toolchain: stable 19 | components: rustfmt, clippy 20 | default: true 21 | - name: Install SDL2 22 | run: sudo apt-get install libsdl2-dev 23 | 24 | - uses: actions/cache@v2 25 | with: 26 | path: | 27 | ~/.cargo/registry 28 | ~/.cargo/git 29 | target 30 | key: ${{ runner.os }}-rust-${{ steps.install_rust.outputs.rustc_hash }}-${{ hashFiles('**/Cargo.lock') }} 31 | restore-keys: | 32 | ${{ runner.os }}-rust-${{ steps.install_rust.outputs.rustc_hash }}- 33 | 34 | - name: cargo check 35 | run: cargo check --verbose --workspace --all-targets 36 | 37 | - name: cargo build 38 | run: cargo build --verbose 39 | 40 | - name: cargo test 41 | run: cargo test --verbose --workspace 42 | 43 | - name: cargo fmt 44 | run: cargo fmt --verbose --all -- --check 45 | 46 | - name: cargo clippy 47 | run: cargo clippy --verbose --workspace 48 | 49 | upload_docs: 50 | name: Upload documentation 51 | runs-on: ubuntu-latest 52 | needs: build 53 | if: github.ref == 'refs/heads/master' 54 | 55 | steps: 56 | - uses: actions/checkout@v2 57 | - name: Install Rust toolchain (stable) 58 | id: install_rust 59 | uses: actions-rs/toolchain@v1 60 | with: 61 | toolchain: nightly 62 | override: true 63 | 64 | - uses: actions/cache@v2 65 | with: 66 | path: | 67 | ~/.cargo/registry 68 | ~/.cargo/git 69 | target 70 | key: ${{ runner.os }}-rust-${{ steps.install_rust.outputs.rustc_hash }}-${{ hashFiles('**/Cargo.lock') }} 71 | restore-keys: | 72 | ${{ runner.os }}-rust-${{ steps.install_rust.outputs.rustc_hash }}- 73 | 74 | - name: Generate documentation 75 | run: ./docs.sh --verbose 76 | 77 | - name: Deploy 78 | uses: peaceiris/actions-gh-pages@v3 79 | with: 80 | github_token: ${{ secrets.GITHUB_TOKEN }} 81 | publish_dir: target/doc 82 | force_orphan: true 83 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | Cargo.lock 4 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "adler32" 5 | version = "1.0.4" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | 8 | [[package]] 9 | name = "ansi_term" 10 | version = "0.11.0" 11 | source = "registry+https://github.com/rust-lang/crates.io-index" 12 | dependencies = [ 13 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 14 | ] 15 | 16 | [[package]] 17 | name = "approx" 18 | version = "0.3.2" 19 | source = "registry+https://github.com/rust-lang/crates.io-index" 20 | dependencies = [ 21 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 22 | ] 23 | 24 | [[package]] 25 | name = "arrayvec" 26 | version = "0.5.1" 27 | source = "registry+https://github.com/rust-lang/crates.io-index" 28 | 29 | [[package]] 30 | name = "atty" 31 | version = "0.2.14" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | dependencies = [ 34 | "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 35 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 36 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 37 | ] 38 | 39 | [[package]] 40 | name = "autocfg" 41 | version = "0.1.7" 42 | source = "registry+https://github.com/rust-lang/crates.io-index" 43 | 44 | [[package]] 45 | name = "autocfg" 46 | version = "1.0.0" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | 49 | [[package]] 50 | name = "backtrace" 51 | version = "0.3.43" 52 | source = "registry+https://github.com/rust-lang/crates.io-index" 53 | dependencies = [ 54 | "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 57 | "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 58 | ] 59 | 60 | [[package]] 61 | name = "backtrace-sys" 62 | version = "0.1.32" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | dependencies = [ 65 | "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 67 | ] 68 | 69 | [[package]] 70 | name = "bitflags" 71 | version = "0.7.0" 72 | source = "registry+https://github.com/rust-lang/crates.io-index" 73 | 74 | [[package]] 75 | name = "bitflags" 76 | version = "1.2.1" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | 79 | [[package]] 80 | name = "byteorder" 81 | version = "1.3.4" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | 84 | [[package]] 85 | name = "cc" 86 | version = "1.0.50" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | 89 | [[package]] 90 | name = "cfg-if" 91 | version = "0.1.10" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | 94 | [[package]] 95 | name = "clap" 96 | version = "2.33.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | dependencies = [ 99 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 100 | "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", 101 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 102 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 103 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 105 | "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", 106 | ] 107 | 108 | [[package]] 109 | name = "cloudabi" 110 | version = "0.0.3" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | dependencies = [ 113 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 114 | ] 115 | 116 | [[package]] 117 | name = "color_quant" 118 | version = "1.0.1" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | 121 | [[package]] 122 | name = "crossbeam-deque" 123 | version = "0.7.2" 124 | source = "registry+https://github.com/rust-lang/crates.io-index" 125 | dependencies = [ 126 | "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 127 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 128 | ] 129 | 130 | [[package]] 131 | name = "crossbeam-epoch" 132 | version = "0.8.0" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | dependencies = [ 135 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 136 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 137 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 138 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 139 | "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 140 | "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 141 | ] 142 | 143 | [[package]] 144 | name = "crossbeam-queue" 145 | version = "0.2.1" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | dependencies = [ 148 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 149 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 150 | ] 151 | 152 | [[package]] 153 | name = "crossbeam-utils" 154 | version = "0.7.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | dependencies = [ 157 | "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 158 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 159 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 160 | ] 161 | 162 | [[package]] 163 | name = "deflate" 164 | version = "0.7.20" 165 | source = "registry+https://github.com/rust-lang/crates.io-index" 166 | dependencies = [ 167 | "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 168 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 169 | ] 170 | 171 | [[package]] 172 | name = "either" 173 | version = "1.5.3" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | 176 | [[package]] 177 | name = "failure" 178 | version = "0.1.6" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | dependencies = [ 181 | "backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)", 182 | "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 183 | ] 184 | 185 | [[package]] 186 | name = "failure_derive" 187 | version = "0.1.6" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | dependencies = [ 190 | "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 191 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 192 | "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", 193 | "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 194 | ] 195 | 196 | [[package]] 197 | name = "fnv" 198 | version = "1.0.6" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | 201 | [[package]] 202 | name = "fuchsia-cprng" 203 | version = "0.1.1" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | 206 | [[package]] 207 | name = "gif" 208 | version = "0.10.3" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | dependencies = [ 211 | "color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 212 | "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 213 | ] 214 | 215 | [[package]] 216 | name = "gl" 217 | version = "0.11.0" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | dependencies = [ 220 | "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 221 | ] 222 | 223 | [[package]] 224 | name = "gl_generator" 225 | version = "0.10.0" 226 | source = "registry+https://github.com/rust-lang/crates.io-index" 227 | dependencies = [ 228 | "khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 229 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 230 | "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 231 | ] 232 | 233 | [[package]] 234 | name = "hermit-abi" 235 | version = "0.1.6" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | dependencies = [ 238 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 239 | ] 240 | 241 | [[package]] 242 | name = "image" 243 | version = "0.20.1" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | dependencies = [ 246 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 247 | "gif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", 248 | "jpeg-decoder 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", 249 | "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 250 | "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 251 | "num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 252 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 253 | "png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 254 | "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", 255 | "tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 256 | ] 257 | 258 | [[package]] 259 | name = "inflate" 260 | version = "0.4.5" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | dependencies = [ 263 | "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 264 | ] 265 | 266 | [[package]] 267 | name = "interpolation" 268 | version = "0.1.0" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | 271 | [[package]] 272 | name = "jpeg-decoder" 273 | version = "0.1.18" 274 | source = "registry+https://github.com/rust-lang/crates.io-index" 275 | dependencies = [ 276 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 277 | "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 278 | ] 279 | 280 | [[package]] 281 | name = "khronos_api" 282 | version = "2.2.0" 283 | source = "registry+https://github.com/rust-lang/crates.io-index" 284 | 285 | [[package]] 286 | name = "khronos_api" 287 | version = "3.1.0" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | 290 | [[package]] 291 | name = "lazy_static" 292 | version = "0.2.11" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | 295 | [[package]] 296 | name = "lazy_static" 297 | version = "1.4.0" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | 300 | [[package]] 301 | name = "libc" 302 | version = "0.2.66" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | 305 | [[package]] 306 | name = "log" 307 | version = "0.4.8" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | dependencies = [ 310 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 311 | ] 312 | 313 | [[package]] 314 | name = "lzw" 315 | version = "0.10.0" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | 318 | [[package]] 319 | name = "memoffset" 320 | version = "0.5.3" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | dependencies = [ 323 | "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", 324 | ] 325 | 326 | [[package]] 327 | name = "num" 328 | version = "0.1.42" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | dependencies = [ 331 | "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 332 | "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 333 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 334 | ] 335 | 336 | [[package]] 337 | name = "num-derive" 338 | version = "0.2.5" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | dependencies = [ 341 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 342 | "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 343 | "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", 344 | ] 345 | 346 | [[package]] 347 | name = "num-integer" 348 | version = "0.1.42" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | dependencies = [ 351 | "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 352 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 353 | ] 354 | 355 | [[package]] 356 | name = "num-iter" 357 | version = "0.1.40" 358 | source = "registry+https://github.com/rust-lang/crates.io-index" 359 | dependencies = [ 360 | "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 361 | "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 362 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 363 | ] 364 | 365 | [[package]] 366 | name = "num-rational" 367 | version = "0.2.3" 368 | source = "registry+https://github.com/rust-lang/crates.io-index" 369 | dependencies = [ 370 | "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 371 | "num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 372 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 373 | ] 374 | 375 | [[package]] 376 | name = "num-traits" 377 | version = "0.2.11" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | dependencies = [ 380 | "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 381 | ] 382 | 383 | [[package]] 384 | name = "num_cpus" 385 | version = "1.12.0" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | dependencies = [ 388 | "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 389 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 390 | ] 391 | 392 | [[package]] 393 | name = "ordered-float" 394 | version = "1.0.2" 395 | source = "registry+https://github.com/rust-lang/crates.io-index" 396 | dependencies = [ 397 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 398 | ] 399 | 400 | [[package]] 401 | name = "piston" 402 | version = "0.39.0" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | dependencies = [ 405 | "pistoncore-event_loop 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", 406 | "pistoncore-input 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", 407 | "pistoncore-window 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)", 408 | ] 409 | 410 | [[package]] 411 | name = "piston-float" 412 | version = "0.3.0" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | 415 | [[package]] 416 | name = "piston-shaders_graphics2d" 417 | version = "0.3.1" 418 | source = "registry+https://github.com/rust-lang/crates.io-index" 419 | 420 | [[package]] 421 | name = "piston-texture" 422 | version = "0.6.0" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | 425 | [[package]] 426 | name = "piston-viewport" 427 | version = "0.5.0" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | dependencies = [ 430 | "piston-float 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 431 | ] 432 | 433 | [[package]] 434 | name = "piston2d-graphics" 435 | version = "0.28.0" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | dependencies = [ 438 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 439 | "interpolation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 440 | "piston-texture 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 441 | "piston-viewport 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 442 | "read_color 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 443 | "rusttype 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", 444 | "vecmath 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 445 | ] 446 | 447 | [[package]] 448 | name = "piston2d-opengl_graphics" 449 | version = "0.57.0" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | dependencies = [ 452 | "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 453 | "gl 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 454 | "image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)", 455 | "khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 456 | "piston-shaders_graphics2d 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 457 | "piston-texture 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 458 | "piston2d-graphics 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", 459 | "shader_version 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 460 | ] 461 | 462 | [[package]] 463 | name = "pistoncore-event_loop" 464 | version = "0.39.0" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | dependencies = [ 467 | "pistoncore-input 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", 468 | "pistoncore-window 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)", 469 | ] 470 | 471 | [[package]] 472 | name = "pistoncore-input" 473 | version = "0.23.0" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | dependencies = [ 476 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 477 | "piston-viewport 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 478 | "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", 479 | "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", 480 | ] 481 | 482 | [[package]] 483 | name = "pistoncore-sdl2_window" 484 | version = "0.52.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | dependencies = [ 487 | "gl 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 488 | "pistoncore-input 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", 489 | "pistoncore-window 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)", 490 | "sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", 491 | "shader_version 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 492 | ] 493 | 494 | [[package]] 495 | name = "pistoncore-window" 496 | version = "0.34.0" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | dependencies = [ 499 | "pistoncore-input 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", 500 | "shader_version 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 501 | ] 502 | 503 | [[package]] 504 | name = "png" 505 | version = "0.12.0" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | dependencies = [ 508 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 509 | "deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)", 510 | "inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", 511 | "num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 512 | ] 513 | 514 | [[package]] 515 | name = "proc-macro2" 516 | version = "0.4.30" 517 | source = "registry+https://github.com/rust-lang/crates.io-index" 518 | dependencies = [ 519 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 520 | ] 521 | 522 | [[package]] 523 | name = "proc-macro2" 524 | version = "1.0.8" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | dependencies = [ 527 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 528 | ] 529 | 530 | [[package]] 531 | name = "quote" 532 | version = "0.6.13" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | dependencies = [ 535 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 536 | ] 537 | 538 | [[package]] 539 | name = "quote" 540 | version = "1.0.2" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | dependencies = [ 543 | "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 544 | ] 545 | 546 | [[package]] 547 | name = "rand" 548 | version = "0.3.23" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | dependencies = [ 551 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 552 | "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 553 | ] 554 | 555 | [[package]] 556 | name = "rand" 557 | version = "0.4.6" 558 | source = "registry+https://github.com/rust-lang/crates.io-index" 559 | dependencies = [ 560 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 561 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 562 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 563 | "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 564 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 565 | ] 566 | 567 | [[package]] 568 | name = "rand" 569 | version = "0.5.6" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | dependencies = [ 572 | "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", 573 | "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 574 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 575 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 576 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 577 | ] 578 | 579 | [[package]] 580 | name = "rand_core" 581 | version = "0.3.1" 582 | source = "registry+https://github.com/rust-lang/crates.io-index" 583 | dependencies = [ 584 | "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", 585 | ] 586 | 587 | [[package]] 588 | name = "rand_core" 589 | version = "0.4.2" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | 592 | [[package]] 593 | name = "rayon" 594 | version = "1.3.0" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | dependencies = [ 597 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 598 | "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", 599 | "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 600 | ] 601 | 602 | [[package]] 603 | name = "rayon-core" 604 | version = "1.7.0" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | dependencies = [ 607 | "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", 608 | "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 609 | "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 610 | "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 611 | "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", 612 | ] 613 | 614 | [[package]] 615 | name = "rdrand" 616 | version = "0.4.0" 617 | source = "registry+https://github.com/rust-lang/crates.io-index" 618 | dependencies = [ 619 | "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 620 | ] 621 | 622 | [[package]] 623 | name = "read_color" 624 | version = "1.0.0" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | 627 | [[package]] 628 | name = "rustc-demangle" 629 | version = "0.1.16" 630 | source = "registry+https://github.com/rust-lang/crates.io-index" 631 | 632 | [[package]] 633 | name = "rustc_version" 634 | version = "0.2.3" 635 | source = "registry+https://github.com/rust-lang/crates.io-index" 636 | dependencies = [ 637 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 638 | ] 639 | 640 | [[package]] 641 | name = "rusttype" 642 | version = "0.7.9" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | dependencies = [ 645 | "rusttype 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 646 | ] 647 | 648 | [[package]] 649 | name = "rusttype" 650 | version = "0.8.2" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | dependencies = [ 653 | "approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", 654 | "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", 655 | "ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 656 | "stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", 657 | ] 658 | 659 | [[package]] 660 | name = "scoped_threadpool" 661 | version = "0.1.9" 662 | source = "registry+https://github.com/rust-lang/crates.io-index" 663 | 664 | [[package]] 665 | name = "scopeguard" 666 | version = "1.0.0" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | 669 | [[package]] 670 | name = "sdl2" 671 | version = "0.31.0" 672 | source = "registry+https://github.com/rust-lang/crates.io-index" 673 | dependencies = [ 674 | "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 675 | "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 676 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 677 | "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 678 | "rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)", 679 | "sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)", 680 | ] 681 | 682 | [[package]] 683 | name = "sdl2-sys" 684 | version = "0.31.0" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | dependencies = [ 687 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 688 | ] 689 | 690 | [[package]] 691 | name = "semver" 692 | version = "0.9.0" 693 | source = "registry+https://github.com/rust-lang/crates.io-index" 694 | dependencies = [ 695 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 696 | ] 697 | 698 | [[package]] 699 | name = "semver-parser" 700 | version = "0.7.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | 703 | [[package]] 704 | name = "serde" 705 | version = "1.0.104" 706 | source = "registry+https://github.com/rust-lang/crates.io-index" 707 | 708 | [[package]] 709 | name = "serde_derive" 710 | version = "1.0.104" 711 | source = "registry+https://github.com/rust-lang/crates.io-index" 712 | dependencies = [ 713 | "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 714 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 715 | "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", 716 | ] 717 | 718 | [[package]] 719 | name = "shader_version" 720 | version = "0.3.0" 721 | source = "registry+https://github.com/rust-lang/crates.io-index" 722 | 723 | [[package]] 724 | name = "sorting-visualization" 725 | version = "0.1.0" 726 | dependencies = [ 727 | "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", 728 | "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 729 | "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 730 | "piston 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", 731 | "piston2d-graphics 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)", 732 | "piston2d-opengl_graphics 0.57.0 (registry+https://github.com/rust-lang/crates.io-index)", 733 | "pistoncore-sdl2_window 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)", 734 | "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 735 | ] 736 | 737 | [[package]] 738 | name = "stb_truetype" 739 | version = "0.3.1" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | dependencies = [ 742 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 743 | ] 744 | 745 | [[package]] 746 | name = "strsim" 747 | version = "0.8.0" 748 | source = "registry+https://github.com/rust-lang/crates.io-index" 749 | 750 | [[package]] 751 | name = "syn" 752 | version = "0.15.44" 753 | source = "registry+https://github.com/rust-lang/crates.io-index" 754 | dependencies = [ 755 | "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", 756 | "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", 757 | "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 758 | ] 759 | 760 | [[package]] 761 | name = "syn" 762 | version = "1.0.14" 763 | source = "registry+https://github.com/rust-lang/crates.io-index" 764 | dependencies = [ 765 | "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 766 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 767 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 768 | ] 769 | 770 | [[package]] 771 | name = "synstructure" 772 | version = "0.12.3" 773 | source = "registry+https://github.com/rust-lang/crates.io-index" 774 | dependencies = [ 775 | "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", 776 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 777 | "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", 778 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 779 | ] 780 | 781 | [[package]] 782 | name = "textwrap" 783 | version = "0.11.0" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | dependencies = [ 786 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 787 | ] 788 | 789 | [[package]] 790 | name = "tiff" 791 | version = "0.2.2" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | dependencies = [ 794 | "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 795 | "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 796 | "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", 797 | "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", 798 | ] 799 | 800 | [[package]] 801 | name = "unicode-width" 802 | version = "0.1.7" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | 805 | [[package]] 806 | name = "unicode-xid" 807 | version = "0.1.0" 808 | source = "registry+https://github.com/rust-lang/crates.io-index" 809 | 810 | [[package]] 811 | name = "unicode-xid" 812 | version = "0.2.0" 813 | source = "registry+https://github.com/rust-lang/crates.io-index" 814 | 815 | [[package]] 816 | name = "vec_map" 817 | version = "0.8.1" 818 | source = "registry+https://github.com/rust-lang/crates.io-index" 819 | 820 | [[package]] 821 | name = "vecmath" 822 | version = "0.3.1" 823 | source = "registry+https://github.com/rust-lang/crates.io-index" 824 | dependencies = [ 825 | "piston-float 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 826 | ] 827 | 828 | [[package]] 829 | name = "winapi" 830 | version = "0.3.8" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | dependencies = [ 833 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 834 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 835 | ] 836 | 837 | [[package]] 838 | name = "winapi-i686-pc-windows-gnu" 839 | version = "0.4.0" 840 | source = "registry+https://github.com/rust-lang/crates.io-index" 841 | 842 | [[package]] 843 | name = "winapi-x86_64-pc-windows-gnu" 844 | version = "0.4.0" 845 | source = "registry+https://github.com/rust-lang/crates.io-index" 846 | 847 | [[package]] 848 | name = "xml-rs" 849 | version = "0.8.0" 850 | source = "registry+https://github.com/rust-lang/crates.io-index" 851 | 852 | [metadata] 853 | "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" 854 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 855 | "checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" 856 | "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" 857 | "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 858 | "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" 859 | "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 860 | "checksum backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" 861 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" 862 | "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" 863 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 864 | "checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 865 | "checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" 866 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 867 | "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" 868 | "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 869 | "checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" 870 | "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" 871 | "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" 872 | "checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" 873 | "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" 874 | "checksum deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)" = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" 875 | "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" 876 | "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" 877 | "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" 878 | "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" 879 | "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" 880 | "checksum gif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af" 881 | "checksum gl 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7d8c8e25e8ed44d4813809205090162723a866fb4be3a9d8bb983c9a0bf98f1" 882 | "checksum gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a0ffaf173cf76c73a73e080366bf556b4776ece104b06961766ff11449f38604" 883 | "checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" 884 | "checksum image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44665b4395d1844c96e7dc8ed5754782a1cdfd9ef458a80bbe45702681450504" 885 | "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" 886 | "checksum interpolation 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "84e53e2877f735534c2d3cdbb5ba1d04ee11107f599a1e811ab0ff3dd93fe66e" 887 | "checksum jpeg-decoder 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0256f0aec7352539102a9efbcb75543227b7ab1117e0f95450023af730128451" 888 | "checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" 889 | "checksum khronos_api 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" 890 | "checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73" 891 | "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 892 | "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" 893 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 894 | "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" 895 | "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" 896 | "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" 897 | "checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" 898 | "checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" 899 | "checksum num-iter 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "dfb0800a0291891dd9f4fe7bd9c19384f98f7fbe0cd0f39a2c6b88b9868bbc00" 900 | "checksum num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3" 901 | "checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" 902 | "checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" 903 | "checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518" 904 | "checksum piston 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "112ab16a36662994b990ab4b2ef1355604a5cea2ad82d87e44a90b3442f6c909" 905 | "checksum piston-float 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b058c3a640efd4bcf63266512e4bb03187192c1b29edd38b16d5a014613e3199" 906 | "checksum piston-shaders_graphics2d 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "97bc17dac1dfff3e5cb84116062c7b46ff9d3dc0d88696a46d2f054cf64a10b6" 907 | "checksum piston-texture 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3649b5f9d1ba48d95207976118e9e2ed473c1de36f6f79cc1b7ed5b75b655b61" 908 | "checksum piston-viewport 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d96dd995f7dabe6d57cda668ec0fda39d6fe6e1e0b23f772582f383f2013611" 909 | "checksum piston2d-graphics 0.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d74cad7ea53907a8ed5c79782afe83d7af7b1c78246299557dad95cef749df79" 910 | "checksum piston2d-opengl_graphics 0.57.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0f495259ab09f48d37ae82bd6a3db82e97f00d17be12f93223692e2a7929bfde" 911 | "checksum pistoncore-event_loop 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)" = "01389bd431d187b4534d35386ba2d5c0438b88ea6234b14aabd380323f0e9f40" 912 | "checksum pistoncore-input 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df15a3c7468e3a18996f35127191a9c9e85542c3591efde556b179aca9f94e47" 913 | "checksum pistoncore-sdl2_window 0.52.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ccfb7a5cb43a31840f10842bab7fc955cbdca96cd6ac9dd1b07daefa4359d58c" 914 | "checksum pistoncore-window 0.34.0 (registry+https://github.com/rust-lang/crates.io-index)" = "39cfc7a576a7997d1cbd5542dc82761f3d9b5a9386bfef6ecd6b7257f0867804" 915 | "checksum png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b" 916 | "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" 917 | "checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" 918 | "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" 919 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 920 | "checksum rand 0.3.23 (registry+https://github.com/rust-lang/crates.io-index)" = "64ac302d8f83c0c1974bf758f6b041c6c8ada916fbb44a609158ca8b064cc76c" 921 | "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" 922 | "checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9" 923 | "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" 924 | "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" 925 | "checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" 926 | "checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" 927 | "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" 928 | "checksum read_color 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9f4c8858baa4ad3c8bcc156ae91a0ffe22b76a3975c40c49b4f04c15c6bce0da" 929 | "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" 930 | "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 931 | "checksum rusttype 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "310942406a39981bed7e12b09182a221a29e0990f3e7e0c971f131922ed135d5" 932 | "checksum rusttype 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "14a911032fb5791ccbeec9f28fdcb9bf0983b81f227bafdfd227c658d0731c8a" 933 | "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" 934 | "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" 935 | "checksum sdl2 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a74c2a98a354b20713b90cce70aef9e927e46110d1bc4ef728fd74e0d53eba60" 936 | "checksum sdl2-sys 0.31.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c543ce8a6e33a30cb909612eeeb22e693848211a84558d5a00bb11e791b7ab7" 937 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 938 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 939 | "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" 940 | "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" 941 | "checksum shader_version 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a29e10c39144f4663c0f74de29b9a61237bf410be40753b1a3b682832abcf4aa" 942 | "checksum stb_truetype 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f77b6b07e862c66a9f3e62a07588fee67cd90a9135a2b942409f195507b4fb51" 943 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 944 | "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" 945 | "checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" 946 | "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" 947 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 948 | "checksum tiff 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4834f28a0330cb9f3f2c87d2649dca723cb33802e2bdcf18da32759fbec7ce" 949 | "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" 950 | "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" 951 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 952 | "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" 953 | "checksum vecmath 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1bdd6034ee9c1e5e12485f3e4120e12777f6c81cf43bf9a73bff98ed2b479afe" 954 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 955 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 956 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 957 | "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" 958 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | publish = false 3 | edition = "2018" 4 | name = "sorting-visualization" 5 | version = "0.1.0" 6 | authors = ["Dmytro Meleshko "] 7 | description = "A Rust program for visualizing sorting algorithms which uses Piston for graphics. Inspired by Hopson97/Sort-Algorithm-Visualiser." 8 | license = "MIT" 9 | repository = "https://github.com/dmitmel/sorting-visualization.git" 10 | homepage = "https://github.com/dmitmel/sorting-visualization" 11 | readme = "README.md" 12 | 13 | [dependencies] 14 | clap = "2.32" 15 | failure = "0.1" 16 | failure_derive = "0.1" 17 | piston = "0.39" 18 | piston2d-graphics = "0.28" 19 | piston2d-opengl_graphics = "0.57" 20 | pistoncore-sdl2_window = "0.52" 21 | rand = "0.5" 22 | 23 | [features] 24 | doc = [] 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dmytro Meleshko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sorting-visualization 2 | 3 | [![CI Status](https://github.com/dmitmel/sorting-visualization/workflows/CI/badge.svg)](https://github.com/dmitmel/sorting-visualization/actions?query=workflow:CI) 4 | 5 | A [Rust](https://www.rust-lang.org/) program for visualizing sorting algorithms which uses [Piston](http://www.piston.rs/) for graphics. Inspired by [**Hopson97/Sort-Algorithm-Visualiser**](https://github.com/Hopson97/Sort-Algorithm-Visualiser). 6 | 7 | [![Demo](https://i.imgur.com/jyPDiWX.gif)](https://gist.github.com/dmitmel/f8664421b547577065912c3246f4c1e9) 8 | 9 | ## Setup 10 | 11 | ```bash 12 | git clone https://github.com/dmitmel/sorting-visualization 13 | cd sorting-visualization 14 | cargo build --release 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```bash 20 | # see 'Features' section for the list of supported algorithms and their IDs 21 | # and use the --help flag to print all available animation options 22 | cargo run 23 | # list all available algorithms 24 | cargo run -- --list 25 | ``` 26 | 27 | ## Features 28 | 29 | - CLI 30 | - Supports different algorithms (IDs are in brackets): 31 | - [Bubble sort](https://en.wikipedia.org/wiki/Bubble_sort) \[`bubble`\] 32 | - [Cocktail sort](https://en.wikipedia.org/wiki/Cocktail_shaker_sort) \[`cocktail`\] 33 | - [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) \[`cycle`\] 34 | - [Gnome sort](https://en.wikipedia.org/wiki/Gnome_sort) \[`gnome`\] 35 | - [Heap sort](https://en.wikipedia.org/wiki/Heapsort) \[`heap`\] 36 | - [Insertion sort](https://en.wikipedia.org/wiki/Insertion_sort) \[`insertion`\] 37 | - [Merge sort](https://en.wikipedia.org/wiki/Merge_sort) \[`merge`\] 38 | - [Quicksort](https://en.wikipedia.org/wiki/Quicksort) \[`quicksort`\] 39 | - [Selection sort](https://en.wikipedia.org/wiki/Selection_sort) \[`selection`\] 40 | - [Shellsort](https://en.wikipedia.org/wiki/Shellsort) \[`shellsort`\] 41 | - Animation controls: 42 | - Space - pause/resume 43 | - - 2x faster 44 | - - 2x slower 45 | - Easy-to-use algorithm API 46 | - Algorithms can highlight important array elements 47 | - Code is well-documented 48 | 49 | ## Building docs 50 | 51 | ```bash 52 | ./docs.sh 53 | ``` 54 | 55 | **Nightly Rust is required for building docs** because it has [infra doc link resolution](https://github.com/rust-lang/rust/issues/43466) which is currently unstable. 56 | 57 | ## TODO 58 | 59 | 1. User-friendly GUI 60 | 2. More algorithms 61 | 3. Sound? 62 | 63 | ## Contributing 64 | 65 | [**Documentation**](https://dmitmel.github.io/sorting-visualization) 66 | 67 | PRs are appreciated! 68 | 69 | ## License 70 | 71 | [MIT](https://github.com/dmitmel/sorting-visualization/blob/master/LICENSE) © [Dmytro Meleshko](https://github.com/dmitmel) 72 | -------------------------------------------------------------------------------- /assets/Menlo-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dmitmel/sorting-visualization/895cedf116d57b1d9494297e1d56383c2370b57d/assets/Menlo-Regular.ttf -------------------------------------------------------------------------------- /docs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | cargo +nightly doc --document-private-items --features doc "$@" 6 | 7 | cat > target/doc/index.html < 9 | HTML 10 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | tab_spaces = 2 3 | -------------------------------------------------------------------------------- /src/algorithms/all.rs: -------------------------------------------------------------------------------- 1 | use super::{Algorithm, Array}; 2 | 3 | pub struct All; 4 | 5 | impl Algorithm for All { 6 | fn sort(&self, array: Array) { 7 | // Get the list of algorithms 8 | loop { 9 | for (_name, algo) in super::all() { 10 | // Run the algorithm on the array 11 | algo.sort(array.clone()); 12 | // Shuffles the array 13 | array.shuffle(); 14 | } 15 | } 16 | } 17 | 18 | fn name(&self) -> String { 19 | "All algorithms".to_string() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/algorithms/bubble.rs: -------------------------------------------------------------------------------- 1 | //! [Bubble sort](https://en.wikipedia.org/wiki/Bubble_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Bubble sort](https://en.wikipedia.org/wiki/Bubble_sort) 6 | pub struct BubbleSort; 7 | 8 | impl Algorithm for BubbleSort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len(); 11 | for i in 0..len - 1 { 12 | let last = len - i - 1; 13 | array.set_color(last, [0.0, 1.0, 0.0, 0.8]); 14 | 15 | for j in 0..last { 16 | array.set_color(j, [0.0, 1.0, 0.0, 0.8]); 17 | if array.get(j) > array.get(j + 1) { 18 | array.swap(j, j + 1); 19 | } 20 | array.wait(5); 21 | array.reset_color(j); 22 | } 23 | 24 | array.reset_color(last); 25 | } 26 | } 27 | 28 | fn name(&self) -> String { 29 | "Bubble sort".to_string() 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/algorithms/cocktail.rs: -------------------------------------------------------------------------------- 1 | //! [Cocktail sort](https://en.wikipedia.org/wiki/Cocktail_shaker_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Cocktail sort](https://en.wikipedia.org/wiki/Cocktail_shaker_sort) 6 | pub struct CocktailSort; 7 | 8 | impl Algorithm for CocktailSort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len(); 11 | let mut first = 0; 12 | let mut last = len - 1; 13 | let mut swapped: bool = true; 14 | 15 | while swapped { 16 | swapped = false; 17 | array.set_color(last, [0.0, 1.0, 0.0, 0.8]); 18 | 19 | for i in first..last { 20 | array.set_color(i, [0.0, 1.0, 0.0, 0.8]); 21 | if array.get(i) > array.get(i + 1) { 22 | array.swap(i, i + 1); 23 | swapped = true; 24 | } 25 | array.wait(5); 26 | array.reset_color(i); 27 | } 28 | 29 | array.reset_color(last); 30 | 31 | if !swapped { 32 | break; 33 | } 34 | 35 | swapped = false; 36 | last -= 1; 37 | array.set_color(first, [0.0, 1.0, 0.0, 0.8]); 38 | 39 | for j in (first..last).rev() { 40 | array.set_color(j, [0.0, 1.0, 0.0, 0.8]); 41 | if array.get(j) > array.get(j + 1) { 42 | array.swap(j, j + 1); 43 | swapped = true; 44 | } 45 | array.wait(5); 46 | array.reset_color(j); 47 | } 48 | 49 | array.reset_color(first); 50 | first += 1; 51 | } 52 | } 53 | 54 | fn name(&self) -> String { 55 | "Cocktail sort".to_string() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/algorithms/cycle.rs: -------------------------------------------------------------------------------- 1 | //! [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Cycle sort](https://en.wikipedia.org/wiki/Cycle_sort) 6 | pub struct CycleSort; 7 | 8 | impl Algorithm for CycleSort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len(); 11 | for cycle_start in 0..len - 1 { 12 | array.set_color(cycle_start, [0.0, 0.0, 1.0, 0.5]); 13 | 14 | let mut item = array.get(cycle_start); 15 | let mut sorted_index = self.find_sorted_index(&array, cycle_start, item); 16 | 17 | if sorted_index == cycle_start { 18 | continue; 19 | } 20 | 21 | while item == array.get(sorted_index) { 22 | sorted_index += 1; 23 | } 24 | 25 | let tmp = item; 26 | item = array.get(sorted_index); 27 | array.set(sorted_index, tmp); 28 | 29 | while sorted_index != cycle_start { 30 | array.set_color(sorted_index, [0.0, 0.0, 1.0, 0.5]); 31 | sorted_index = cycle_start; 32 | 33 | for i in cycle_start + 1..len { 34 | if array.get(i) < item { 35 | sorted_index += 1; 36 | } 37 | array.wait(2); 38 | } 39 | 40 | while item == array.get(sorted_index) { 41 | sorted_index += 1; 42 | array.wait(2); 43 | } 44 | 45 | let tmp = item; 46 | item = array.get(sorted_index); 47 | array.set(sorted_index, tmp); 48 | } 49 | } 50 | } 51 | 52 | fn name(&self) -> String { 53 | "Cycle sort".to_string() 54 | } 55 | } 56 | 57 | impl CycleSort { 58 | fn find_sorted_index( 59 | &self, 60 | array: &Array, 61 | cycle_start: usize, 62 | item: u32, 63 | ) -> usize { 64 | let len = array.len(); 65 | 66 | let mut sorted_index = cycle_start; 67 | for i in cycle_start + 1..len { 68 | if array.get(i) < item { 69 | sorted_index += 1; 70 | } 71 | array.wait(2); 72 | } 73 | 74 | sorted_index 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/algorithms/gnome.rs: -------------------------------------------------------------------------------- 1 | //! [Gnome sort](https://en.wikipedia.org/wiki/Gnome_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Gnome sort](https://en.wikipedia.org/wiki/Gnome_sort) 6 | pub struct GnomeSort; 7 | 8 | impl Algorithm for GnomeSort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len(); 11 | let mut i = 0; 12 | while i < len { 13 | array.set_color(i, [0.0, 1.0, 0.0, 0.8]); 14 | array.wait(5); 15 | array.reset_color(i); 16 | 17 | if i == 0 || array.get(i) >= array.get(i - 1) { 18 | i += 1; 19 | } else { 20 | array.swap(i, i - 1); 21 | i -= 1; 22 | } 23 | } 24 | } 25 | 26 | fn name(&self) -> String { 27 | "Gnome sort".to_string() 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/algorithms/heap.rs: -------------------------------------------------------------------------------- 1 | //! [Heap sort](https://en.wikipedia.org/wiki/Heapsort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Heap sort](https://en.wikipedia.org/wiki/Heapsort) 6 | pub struct HeapSort; 7 | 8 | impl Algorithm for HeapSort { 9 | fn sort(&self, array: Array) { 10 | let first = 0; 11 | let n = array.len(); 12 | 13 | for i in (first..n / 2 - 1).rev() { 14 | heapify(&array, n, i); 15 | } 16 | 17 | for i in (first..n).rev() { 18 | array.swap(first, i); 19 | heapify(&array, i, first); 20 | } 21 | 22 | fn heapify(array: &Array, n: usize, i: usize) { 23 | let mut largest = i; 24 | let left = 2 * i + 1; 25 | let right = 2 * i + 2; 26 | 27 | if left < n && array.get(left) > array.get(largest) { 28 | largest = left; 29 | } 30 | 31 | if right < n && array.get(right) > array.get(largest) { 32 | largest = right; 33 | } 34 | 35 | if largest != i { 36 | array.set_color(i, [0.0, 1.0, 0.0, 0.8]); 37 | array.swap(i, largest); 38 | heapify(array, n, largest); 39 | array.wait(5); 40 | array.reset_color(i); 41 | } 42 | } 43 | } 44 | 45 | fn name(&self) -> String { 46 | "HeapSort sort".to_string() 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/algorithms/insertion.rs: -------------------------------------------------------------------------------- 1 | //! [Insertion sort](https://en.wikipedia.org/wiki/Insertion_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Insertion sort](https://en.wikipedia.org/wiki/Insertion_sort) 6 | pub struct InsertionSort; 7 | 8 | impl Algorithm for InsertionSort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len(); 11 | for i in 1..len { 12 | array.set_color(i, [0.0, 1.0, 0.0, 0.8]); 13 | array.wait(7); 14 | 15 | let mut j = i; 16 | while j > 0 && array.get(j - 1) > array.get(j) { 17 | array.swap(j, j - 1); 18 | j -= 1; 19 | 20 | array.set_color(j, [0.0, 1.0, 0.0, 0.8]); 21 | array.wait(7); 22 | array.reset_color(j); 23 | } 24 | 25 | array.reset_color(i); 26 | } 27 | } 28 | 29 | fn name(&self) -> String { 30 | "Insertion sort".to_string() 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/algorithms/merge.rs: -------------------------------------------------------------------------------- 1 | //! [Merge sort](https://en.wikipedia.org/wiki/Merge_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Merge sort](https://en.wikipedia.org/wiki/Merge_sort) 6 | pub struct MergeSort; 7 | 8 | impl Algorithm for MergeSort { 9 | fn sort(&self, array: Array) { 10 | merge_sort(&array, 0, array.len() - 1); 11 | } 12 | 13 | fn name(&self) -> String { 14 | "Merge sort".to_string() 15 | } 16 | } 17 | 18 | fn merge_sort(array: &Array, left: usize, right: usize) { 19 | if left < right { 20 | let middle = (left + right) / 2; 21 | array.set_color(middle, [1.0, 0.0, 0.0, 1.0]); 22 | 23 | for i in left..middle { 24 | array.set_color(i, [0.0, 1.0, 0.0, 0.3]); 25 | } 26 | merge_sort(array, left, middle); 27 | 28 | for i in middle + 1..=right { 29 | array.set_color(i, [0.0, 0.0, 1.0, 0.3]); 30 | } 31 | merge_sort(array, middle + 1, right); 32 | 33 | merge(array, left, middle, right); 34 | 35 | for i in left..=right { 36 | array.reset_color(i); 37 | } 38 | } 39 | } 40 | 41 | fn merge(array: &Array, left: usize, middle: usize, right: usize) { 42 | let left_size = middle - left + 1; 43 | let right_size = right - middle; 44 | 45 | let left_array = sub_array(array, left, left_size); 46 | let right_array = sub_array(array, middle + 1, right_size); 47 | 48 | let mut i = 0; 49 | let mut j = 0; 50 | let mut k = left; 51 | let mut prev_k = k; 52 | 53 | while i < left_size && j < right_size { 54 | array.reset_color(prev_k); 55 | array.set_color(k, [1.0, 0.0, 0.0, 1.0]); 56 | prev_k = k; 57 | 58 | if left_array[i] <= right_array[j] { 59 | array.set(k, left_array[i]); 60 | i += 1; 61 | } else { 62 | array.set(k, right_array[j]); 63 | j += 1; 64 | } 65 | k += 1; 66 | array.wait(20); 67 | } 68 | 69 | array.reset_color(prev_k); 70 | 71 | while i < left_size { 72 | array.set(k, left_array[i]); 73 | i += 1; 74 | k += 1; 75 | array.wait(20); 76 | } 77 | 78 | while j < right_size { 79 | array.set(k, right_array[j]); 80 | j += 1; 81 | k += 1; 82 | array.wait(20); 83 | } 84 | } 85 | 86 | fn sub_array(array: &Array, begin: usize, size: usize) -> Vec { 87 | (0..size) 88 | .map(|i| { 89 | array.wait(10); 90 | array.get(begin + i) 91 | }) 92 | .collect() 93 | } 94 | -------------------------------------------------------------------------------- /src/algorithms/mod.rs: -------------------------------------------------------------------------------- 1 | //! Different sorting algorithms as well as the general 2 | //! [`Algorithm`](crate::algorithms::Algorithm) trait. 3 | 4 | use std::collections::HashMap; 5 | 6 | // re-export Array struct for use in algorithms 7 | pub use crate::array::Array; 8 | 9 | /// The general trait for all sorting algorithms. 10 | pub trait Algorithm { 11 | /// Sorts a given [array](crate::array::Array). This method is called in a so 12 | /// called "algorithm thread". 13 | fn sort(&self, array: Array); 14 | /// Returns the name of the algorithm that will be displayed to the user. 15 | /// Returned value is an owned [String] so it can be generated at runtime. 16 | fn name(&self) -> String; 17 | } 18 | 19 | /// A shorthand macro that declares modules of all algorithms, re-exports those 20 | /// algorithms and generates a function that returns all algorithms. 21 | macro_rules! algorithms { 22 | ($($id:ident => $type:ident,)+) => { 23 | $( 24 | pub mod $id; 25 | pub use self::$id::$type; 26 | )* 27 | 28 | /// Returns a [hashmap](HashMap) of all algorithms. It is used in the 29 | /// [cli](crate::cli) module. 30 | pub fn all() -> HashMap> { 31 | let mut algorithms: HashMap> = 32 | HashMap::new(); 33 | $(algorithms.insert(stringify!($id).to_string(), Box::new(self::$id::$type));)* 34 | algorithms 35 | } 36 | }; 37 | } 38 | 39 | algorithms![ 40 | bubble => BubbleSort, 41 | cocktail => CocktailSort, 42 | cycle => CycleSort, 43 | gnome => GnomeSort, 44 | heap => HeapSort, 45 | insertion => InsertionSort, 46 | merge => MergeSort, 47 | quicksort => Quicksort, 48 | selection => SelectionSort, 49 | shellsort => Shellsort, 50 | all => All, 51 | ]; 52 | -------------------------------------------------------------------------------- /src/algorithms/quicksort.rs: -------------------------------------------------------------------------------- 1 | //! [Quicksort](https://en.wikipedia.org/wiki/Quicksort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Quicksort](https://en.wikipedia.org/wiki/Quicksort) 6 | pub struct Quicksort; 7 | 8 | impl Algorithm for Quicksort { 9 | fn sort(&self, array: Array) { 10 | self.sort_slice(&array, 0, array.len() as isize - 1); 11 | } 12 | 13 | fn name(&self) -> String { 14 | "Quicksort".to_string() 15 | } 16 | } 17 | 18 | impl Quicksort { 19 | fn sort_slice(&self, array: &Array, low: isize, high: isize) { 20 | if low < high { 21 | let pivot = self.partition(array, low, high); 22 | 23 | for i in low..pivot { 24 | array.set_color(i as usize, [0.0, 1.0, 0.0, 0.3]); 25 | } 26 | array.set_color(pivot as usize, [1.0, 0.0, 0.0, 1.0]); 27 | for i in pivot + 1..=high { 28 | array.set_color(i as usize, [0.0, 0.0, 1.0, 0.3]); 29 | } 30 | 31 | self.sort_slice(array, low, pivot - 1); 32 | self.sort_slice(array, pivot + 1, high); 33 | 34 | for i in low..=high { 35 | array.reset_color(i as usize); 36 | } 37 | } 38 | } 39 | 40 | fn partition(&self, array: &Array, low: isize, high: isize) -> isize { 41 | let pivot = array.get(high as usize); 42 | let mut i = low; 43 | for j in low..high { 44 | if array.get(j as usize) <= pivot { 45 | array.swap(i as usize, j as usize); 46 | i += 1; 47 | } 48 | array.wait(15); 49 | } 50 | array.swap(i as usize, high as usize); 51 | i 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/algorithms/selection.rs: -------------------------------------------------------------------------------- 1 | //! [Selection sort](https://en.wikipedia.org/wiki/Selection_sort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Selection sort](https://en.wikipedia.org/wiki/Selection_sort) 6 | pub struct SelectionSort; 7 | 8 | impl Algorithm for SelectionSort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len(); 11 | for i in 0..len - 1 { 12 | array.set_color(i, [0.0, 1.0, 0.0, 0.7]); 13 | 14 | let mut min_i = i; 15 | for j in i + 1..len { 16 | if array.get(j) < array.get(min_i) { 17 | if min_i != i { 18 | array.reset_color(min_i); 19 | } 20 | 21 | min_i = j; 22 | array.set_color(min_i, [0.0, 1.0, 0.0, 0.7]); 23 | } 24 | 25 | array.wait(5); 26 | } 27 | 28 | array.wait(20); 29 | 30 | array.swap(i, min_i); 31 | array.reset_color(i); 32 | array.reset_color(min_i); 33 | } 34 | } 35 | 36 | fn name(&self) -> String { 37 | "Selection sort".to_string() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/algorithms/shellsort.rs: -------------------------------------------------------------------------------- 1 | //! [Shell sort](https://en.wikipedia.org/wiki/Shellsort) 2 | 3 | use super::{Algorithm, Array}; 4 | 5 | /// [Shell sort](https://en.wikipedia.org/wiki/Shellsort) 6 | pub struct Shellsort; 7 | 8 | impl Algorithm for Shellsort { 9 | fn sort(&self, array: Array) { 10 | let len = array.len() as i64; 11 | 12 | let mut gap = 1; 13 | 14 | while gap < (len >> 1) { 15 | gap = (gap << 1) + 1; 16 | } 17 | 18 | while gap >= 1 { 19 | let mut i = gap; 20 | while i < len { 21 | let mut k = i - gap; 22 | let mut j = i; 23 | while j >= gap && array.get(j as usize) < array.get(k as usize) { 24 | array.swap(j as usize, k as usize); 25 | array.wait(10); 26 | j = k; 27 | k -= gap; 28 | } 29 | array.wait(10); 30 | i += 1; 31 | } 32 | gap >>= 1; 33 | } 34 | } 35 | 36 | fn name(&self) -> String { 37 | "Shell sort".to_string() 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/app.rs: -------------------------------------------------------------------------------- 1 | //! The [`App`] struct and some constants. 2 | 3 | use graphics::color::{BLACK, TRANSPARENT, WHITE}; 4 | use graphics::types::Color; 5 | use opengl_graphics::{GlGraphics, GlyphCache}; 6 | use piston::input::*; 7 | 8 | use std::thread; 9 | 10 | use crate::algorithms::Algorithm; 11 | use crate::array::Array; 12 | 13 | use crate::state::*; 14 | 15 | /// Color that is used to clear the window before [drawing](App::render). 16 | pub const BACKGROUND_COLOR: Color = BLACK; 17 | 18 | /// Color of rectangles that represent the array values. 19 | pub const VALUE_COLOR: Color = WHITE; 20 | 21 | /// Color of the values that have been recently accessed. 22 | /// 23 | /// _See_ [`State.array_accesses`](State::array_accesses) 24 | pub const ACCESSED_VALUE_COLOR: Color = [1.0, 0.0, 0.0, 1.0]; 25 | 26 | /// Time in seconds after which array accesses are removed. 27 | /// 28 | /// _See_ [`State.array_accesses`](State::array_accesses) 29 | pub const ACCESSED_VALUE_TIMEOUT: f64 = 0.25; 30 | 31 | /// Font size of the status text in pixels. 32 | pub const STATUS_TEXT_FONT_SIZE: u32 = 16; 33 | 34 | /// Margins between the status text and window borders. 35 | pub const STATUS_TEXT_MARGIN: f64 = 8.0; 36 | 37 | /// Factor for increasing / decreasing speed of sorting array 38 | pub const SPEED_FACTOR: f64 = 2.0; 39 | 40 | /// This struct contains all [rendering](App::render), [updating](App::update) 41 | /// and [input handling](App::button) logic. 42 | #[derive(Debug)] 43 | pub struct App { 44 | state: SharedState, 45 | algorithm_thread: thread::JoinHandle<()>, 46 | } 47 | 48 | impl App { 49 | /// Creates a new app (with a state constructed from the given `array`) and 50 | /// starts an algorithm thread. This function is called `init` instead of 51 | /// `new` because it has side effects. 52 | pub fn init( 53 | algorithm: Box, 54 | array: Vec, 55 | speed: f64, 56 | ) -> Self { 57 | let array_len = array.len(); 58 | let colors = vec![TRANSPARENT; array_len]; 59 | 60 | let state = SharedState::new(State { 61 | time: 0.0, 62 | speed, 63 | paused: true, 64 | array, 65 | colors, 66 | array_accesses: vec![NO_ARRAY_ACCESS; array_len], 67 | }); 68 | 69 | let algorithm_state = state.clone(); 70 | 71 | let algorithm_thread = thread::Builder::new() 72 | .name("algorithm".to_string()) 73 | .spawn(move || { 74 | let array = Array::new(algorithm_state); 75 | array.wait(500); 76 | algorithm.sort(array); 77 | }) 78 | .unwrap(); 79 | 80 | Self { 81 | state, 82 | algorithm_thread, 83 | } 84 | } 85 | 86 | /// Draws the current [state](State). 87 | pub fn render( 88 | &mut self, 89 | args: RenderArgs, 90 | gl: &mut GlGraphics, 91 | glyphs: &mut GlyphCache<'_>, 92 | ) { 93 | gl.draw(args.viewport(), |ctx, gl| { 94 | use graphics::*; 95 | 96 | clear(BACKGROUND_COLOR, gl); 97 | 98 | // lock the state for the whole rendering cycle so that the algorithm 99 | // thread doesn't change something while the main thread is doing 100 | // rendering 101 | let state = self.state.get(); 102 | 103 | // transform of the bottom left point of the status text 104 | let status_text_transform = ctx.transform.trans( 105 | STATUS_TEXT_MARGIN, 106 | STATUS_TEXT_MARGIN + f64::from(STATUS_TEXT_FONT_SIZE), 107 | ); 108 | 109 | let status_text = format!( 110 | "paused = {}, speed = {}%", 111 | state.paused, 112 | state.speed * 100.0 113 | ); 114 | 115 | // draw the status text 116 | text::Text::new_color(WHITE, STATUS_TEXT_FONT_SIZE) 117 | .draw( 118 | &status_text, 119 | glyphs, 120 | &ctx.draw_state, 121 | status_text_transform, 122 | gl, 123 | ) 124 | .unwrap(); 125 | 126 | let len = state.array.len(); 127 | let max_value = *state.array.iter().max().unwrap_or(&0); 128 | 129 | // draws a rectangle with a given color which represents a value at a 130 | // specified index 131 | let mut draw_value = |index: usize, color: Color| { 132 | let value = state.array[index]; 133 | 134 | let window_w: f64 = args.width; 135 | let window_h: f64 = args.height; 136 | 137 | let array_y = 138 | STATUS_TEXT_MARGIN * 2.0 + f64::from(STATUS_TEXT_FONT_SIZE); 139 | 140 | let array_h = window_h - array_y; 141 | 142 | let w = window_w / (len as f64); 143 | let h = f64::from(value) * array_h / f64::from(max_value); 144 | let x = (index as f64) * w; 145 | let y = window_h - h; 146 | 147 | rectangle(color, [x, y, w, h], ctx.transform, gl); 148 | }; 149 | 150 | // draw all values 151 | for index in 0..len { 152 | draw_value(index, VALUE_COLOR); 153 | } 154 | 155 | // draw array accesses 156 | for (index, access_time) in state.array_accesses.iter().enumerate() { 157 | if *access_time < 0.0 { 158 | continue; 159 | } 160 | 161 | let mut color = ACCESSED_VALUE_COLOR; 162 | 163 | let access_age = state.time - access_time; 164 | // map age of this access to the [1.0, 0.0] interval of the alpha (transparency) component 165 | // so that new accesses are opaque and old ones are transparent 166 | let alpha = (1.0 - access_age / ACCESSED_VALUE_TIMEOUT) as f32; 167 | 168 | color[color.len() - 1] = alpha; 169 | draw_value(index, color); 170 | } 171 | 172 | // draw colored overlays (marks) for some values 173 | for (index, color) in state.colors.iter().enumerate() { 174 | draw_value(index, *color); 175 | } 176 | }); 177 | } 178 | 179 | /// Advances the [state](State) by a given amount of [time](UpdateArgs::dt). 180 | pub fn update(&mut self, args: UpdateArgs) { 181 | let mut state = self.state.get(); 182 | 183 | if !state.paused { 184 | state.time += args.dt * state.speed; 185 | } 186 | 187 | // time is copied (f64 implements the Copy trait) to a variable because it 188 | // can't be accessed when array_accesses is borrowed mutably 189 | let time = state.time; 190 | for access_time in state.array_accesses.iter_mut() { 191 | if time - *access_time > ACCESSED_VALUE_TIMEOUT { 192 | *access_time = NO_ARRAY_ACCESS; 193 | } 194 | } 195 | } 196 | 197 | /// Handles user input and updates the [state](State). 198 | /// 199 | /// # Controls 200 | /// 201 | /// | Key | Action | 202 | /// | ---------------------- | ------------ | 203 | /// | Space | pause/resume | 204 | /// | | 2x faster | 205 | /// | | 2x slower | 206 | pub fn button(&mut self, args: ButtonArgs) { 207 | let mut state = self.state.get(); 208 | 209 | // import commonly used enum values in the current scope 210 | use self::Button::Keyboard; 211 | use self::ButtonState::Press; 212 | 213 | match (args.button, args.state) { 214 | (Keyboard(Key::Space), Press) => { 215 | state.paused = !state.paused; 216 | self.algorithm_thread.thread().unpark(); 217 | } 218 | 219 | (Keyboard(Key::Up), Press) => state.speed *= SPEED_FACTOR, 220 | (Keyboard(Key::Down), Press) => state.speed /= SPEED_FACTOR, 221 | 222 | _ => {} 223 | }; 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/array.rs: -------------------------------------------------------------------------------- 1 | //! The [`Array`](crate::array::Array) struct. 2 | 3 | use graphics::color::TRANSPARENT; 4 | use graphics::types::Color; 5 | 6 | use crate::state::SharedState; 7 | 8 | /// A convenient wrapper around [`SharedState`] for 9 | /// [algorithms](crate::algorithms) that handles concurrency and all that stuff. 10 | /// **All methods in this struct lock the [state](crate::state::State) for as 11 | /// short as possible** so that the rendering thread can lock it when it wants. 12 | #[derive(Debug, Clone)] 13 | pub struct Array(SharedState); 14 | 15 | impl Array { 16 | /// Creates a new array from a copy of [`SharedState`]. 17 | pub fn new(state: SharedState) -> Self { 18 | Array(state) 19 | } 20 | 21 | /// Puts the current thread to sleep for the specified amount of time and 22 | /// blocks it if the animation is [paused](crate::state::State::paused). 23 | pub fn wait(&self, ms: u64) { 24 | use std::thread; 25 | use std::time::Duration; 26 | 27 | // state must be locked for as short as possible so we shouldn't keep it 28 | // locked while sleeping (`thread::sleep` and `thread::park`) 29 | 30 | thread::sleep(Duration::from_micros({ 31 | let state = self.0.get(); 32 | (ms as f64 * 1000.0 / state.speed) as u64 33 | })); 34 | 35 | let paused = { 36 | let state = self.0.get(); 37 | state.paused 38 | }; 39 | 40 | if paused { 41 | thread::park(); 42 | } 43 | } 44 | 45 | /// Returns the length of the underlying [vector](crate::state::State::array). 46 | pub fn len(&self) -> usize { 47 | let state = self.0.get(); 48 | state.array.len() 49 | } 50 | 51 | /// Returns a value at a given index. 52 | pub fn get(&self, index: usize) -> u32 { 53 | let mut state = self.0.get(); 54 | let value = state.array[index]; 55 | 56 | state.array_accesses[index] = state.time; 57 | 58 | value 59 | } 60 | 61 | /// Sets a value of the at a given index. 62 | pub fn set(&self, index: usize, value: u32) { 63 | let mut state = self.0.get(); 64 | state.array[index] = value; 65 | 66 | state.array_accesses[index] = state.time; 67 | } 68 | 69 | /// Swaps two values at given indices. 70 | pub fn swap(&self, a: usize, b: usize) { 71 | let mut state = self.0.get(); 72 | state.array.swap(a, b); 73 | } 74 | 75 | // /// Reverses the Array. 76 | // pub fn reverse(&self) { 77 | // let mut state = self.0.get(); 78 | // state.array.reverse(); 79 | // } 80 | 81 | /// Shuffles the Array. 82 | pub fn shuffle(&self) { 83 | use rand::{thread_rng, Rng}; 84 | let mut state = self.0.get(); 85 | thread_rng().shuffle(&mut state.array); 86 | } 87 | 88 | /// Resets color of the value at a given index (sets it to the transparent 89 | /// color). 90 | /// 91 | /// _See_ [`State.colors`](crate::state::State::colors) 92 | pub fn reset_color(&self, index: usize) { 93 | self.set_color(index, TRANSPARENT); 94 | } 95 | 96 | /// Sets color of the value at a given index. 97 | /// 98 | /// _See_ [`State.colors`](crate::state::State::colors) 99 | pub fn set_color(&self, index: usize, color: Color) { 100 | let mut state = self.0.get(); 101 | state.colors[index] = color; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | //! Command-line interface and command-line argument parsing. Uses [clap] under 2 | //! the hood. 3 | 4 | use crate::algorithms::{self, Algorithm}; 5 | 6 | /// [Internal name](clap::Arg::with_name) of the 7 | /// [algorithm](Options::algorithm) argument which is used to 8 | /// [get its value](clap::ArgMatches::value_of). 9 | const ALGORITHM_ARG: &str = "ALGORITHM"; 10 | /// [Internal name](clap::Arg::with_name) of the 11 | /// [`--length`/`-l`](Options::length) option which is used to 12 | /// [get its value](clap::ArgMatches::value_of). 13 | const LENGTH_OPT: &str = "LENGTH"; 14 | /// [Internal name](clap::Arg::with_name) of the 15 | /// [`--order`/`-o`](Options::order) option which is used to 16 | /// [get its value](clap::ArgMatches::value_of). 17 | const ORDER_OPT: &str = "ORDER"; 18 | /// [Internal name](clap::Arg::with_name) of the 19 | /// [`--speed`/`-s`](Options::speed) option which is used to 20 | /// [get its value](clap::ArgMatches::value_of). 21 | const SPEED_OPT: &str = "SPEED"; 22 | /// [Internal name](clap::Arg::with_name) of the 23 | /// `--list` option which is used to 24 | /// [get its value](clap::ArgMatches::value_of). 25 | const LIST_OPT: &str = "LIST"; 26 | 27 | /// Contains all options that can be provided by a user using the CLI. 28 | pub struct Options { 29 | /// Instance of a sorting [algorithm](Algorithm) struct. 30 | pub algorithm: Box, 31 | /// Number of elements in the [array](crate::array::Array). 32 | pub length: u32, 33 | /// Order of elements in the [array](crate::array::Array). 34 | pub order: Order, 35 | /// [Speed](crate::state::State::speed) factor. 36 | pub speed: f64, 37 | } 38 | 39 | /// Order of elements in the [array](crate::array::Array). 40 | pub enum Order { 41 | /// Sorted in the ascending order. 42 | Sorted, 43 | /// Sorted in the descending order. 44 | Reversed, 45 | /// [Shuffled](rand::Rng::shuffle). 46 | Shuffled, 47 | } 48 | 49 | /// Parses command-line arguments into [`Options`]. **If the help/version is 50 | /// printed or an error occurs, it will be displayed to the user and the process 51 | /// will exit.** 52 | /// 53 | /// _See_ [`clap::App.get_matches`](clap::App::get_matches) 54 | pub fn parse_options() -> Options { 55 | use clap::*; 56 | 57 | let mut algorithms = algorithms::all(); 58 | let algorithm_ids: Vec<&str> = 59 | algorithms.keys().map(|s| &s as &str).collect(); 60 | 61 | let parser = app_from_crate!() 62 | .setting(AppSettings::NextLineHelp) 63 | .setting(AppSettings::ColoredHelp) 64 | .arg( 65 | Arg::with_name(LIST_OPT) 66 | .long("list") 67 | .help("lists all available algorithms"), 68 | ) 69 | .arg( 70 | Arg::with_name(LENGTH_OPT) 71 | .short("l") 72 | .long("length") 73 | .help("Sets number of elements in the array") 74 | .default_value("100"), 75 | ) 76 | .arg( 77 | Arg::with_name(ORDER_OPT) 78 | .short("o") 79 | .long("order") 80 | .help("Sets order of elements in the array") 81 | .possible_values(&["sorted", "reversed", "shuffled"]) 82 | .case_insensitive(true) 83 | .default_value("shuffled"), 84 | ) 85 | .arg( 86 | Arg::with_name(ALGORITHM_ARG) 87 | .help("Sets sorting algorithm") 88 | .possible_values(&algorithm_ids) 89 | .case_insensitive(true) 90 | .required_unless(LIST_OPT), 91 | ) 92 | .arg( 93 | Arg::with_name(SPEED_OPT) 94 | .short("s") 95 | .long("speed") 96 | .help("Sets animation speed") 97 | .default_value("1.0"), 98 | ); 99 | 100 | let matches = parser.get_matches(); 101 | 102 | if matches.is_present(LIST_OPT) { 103 | println!("Available algorithms:"); 104 | for id in algorithm_ids { 105 | println!("- {}", id); 106 | } 107 | 108 | use std::process; 109 | process::exit(0); 110 | } 111 | 112 | // all option values can be safely unwrapped here because their corresponding 113 | // options are either required or have a default value 114 | Options { 115 | algorithm: { 116 | let id = matches.value_of(ALGORITHM_ARG).unwrap(); 117 | // remove may seem a bit odd here but it's the only safe and logical (if 118 | // you think about it) way to get the ownership of a value which is inside 119 | // of a container (i.e. HashMap, Vec etc) 120 | algorithms.remove(id).unwrap() 121 | }, 122 | 123 | length: value_t_or_exit!(matches, LENGTH_OPT, u32), 124 | 125 | order: match matches.value_of(ORDER_OPT).unwrap() { 126 | "sorted" => Order::Sorted, 127 | "reversed" => Order::Reversed, 128 | "shuffled" => Order::Shuffled, 129 | _ => unreachable!(), 130 | }, 131 | 132 | speed: value_t_or_exit!(matches, SPEED_OPT, f64), 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(feature = "doc", feature(external_doc))] 2 | #![cfg_attr(feature = "doc", doc(include = "../README.md"))] 3 | 4 | use failure::{Error, ResultExt}; 5 | 6 | use opengl_graphics::*; 7 | use piston::event_loop::*; 8 | use piston::input::*; 9 | use piston::window::WindowSettings; 10 | use sdl2_window::Sdl2Window as Window; 11 | 12 | mod algorithms; 13 | mod app; 14 | mod array; 15 | mod cli; 16 | mod state; 17 | 18 | use crate::app::App; 19 | use crate::cli::{Options, Order}; 20 | 21 | /// Required version of OpenGL. 22 | /// 23 | /// _Note:_ change this to [`OpenGL::V2_1`] if it doesn't work. 24 | const OPENGL_VERSION: OpenGL = OpenGL::V3_2; 25 | 26 | /// Title of the main window. 27 | const WINDOW_TITLE: &str = clap::crate_name!(); 28 | /// Initial size of the main window. 29 | const WINDOW_SIZE: (u32, u32) = (640, 480); 30 | 31 | fn main() { 32 | if let Err(error) = run() { 33 | eprintln!("error: {}", error); 34 | 35 | for cause in error.iter_causes() { 36 | eprintln!("caused by: {}", cause); 37 | } 38 | 39 | eprintln!("{}", error.backtrace()); 40 | eprintln!( 41 | "note: Run with `RUST_BACKTRACE=1` if you don't see a backtrace." 42 | ); 43 | 44 | use std::process; 45 | process::exit(1); 46 | } 47 | } 48 | 49 | fn run() -> Result<(), Error> { 50 | let Options { 51 | algorithm, 52 | length, 53 | order, 54 | speed, 55 | } = cli::parse_options(); 56 | 57 | let window_title = format!("{} - {}", WINDOW_TITLE, algorithm.name()); 58 | let mut window: Window = WindowSettings::new(window_title, WINDOW_SIZE) 59 | .opengl(OPENGL_VERSION) 60 | .exit_on_esc(true) 61 | .vsync(true) 62 | .build() 63 | // convert `Result<_, String>` to `Result<_, Error>` 64 | .map_err(|e| failure::format_err!("{}", e)) 65 | .context("couldn't create window")?; 66 | let mut gl = GlGraphics::new(OPENGL_VERSION); 67 | 68 | let mut array: Vec = (1..=length).collect(); 69 | 70 | match order { 71 | Order::Sorted => {} 72 | Order::Reversed => array.reverse(), 73 | Order::Shuffled => { 74 | use rand::{thread_rng, Rng}; 75 | thread_rng().shuffle(&mut array); 76 | } 77 | } 78 | 79 | // load font for the status text 80 | let font = include_bytes!("../assets/Menlo-Regular.ttf"); 81 | let mut glyphs = GlyphCache::from_bytes(font, (), TextureSettings::new()) 82 | // `GlyphCache::from_bytes` returns `Err(())` when an error occurs, so it's 83 | // replaced with an error with a meaningful message here 84 | .map_err(|_| failure::format_err!("couldn't load font"))?; 85 | 86 | // preload printable ASCII chars for faster rendering 87 | glyphs 88 | .preload_printable_ascii(app::STATUS_TEXT_FONT_SIZE) 89 | // convert `Result<_, String>` to `Result<_, Error>` 90 | .map_err(|e| failure::format_err!("{}", e)) 91 | .context("couldn't preload printable ASCII chars")?; 92 | 93 | let mut app = App::init(algorithm, array, speed); 94 | 95 | println!("Press [Space] to pause/resume"); 96 | println!("Press [Up] to speed up"); 97 | println!("Press [Down] to slow down"); 98 | println!(); 99 | 100 | let mut events = Events::new(EventSettings::new()); 101 | while let Some(event) = events.next(&mut window) { 102 | match event { 103 | Event::Loop(Loop::Render(args)) => app.render(args, &mut gl, &mut glyphs), 104 | Event::Loop(Loop::Update(args)) => app.update(args), 105 | Event::Input(Input::Button(args)) => app.button(args), 106 | _ => {} 107 | } 108 | } 109 | 110 | Ok(()) 111 | } 112 | -------------------------------------------------------------------------------- /src/state.rs: -------------------------------------------------------------------------------- 1 | //! Structs and type definitions that describe the app state. 2 | 3 | use std::sync::{Arc, Mutex, MutexGuard}; 4 | 5 | use graphics::types::Color; 6 | 7 | /// A wrapper around [`State`] that can be [safely shared](std::sync) between 8 | /// threads. 9 | #[derive(Debug, Clone)] 10 | pub struct SharedState(Arc>); 11 | 12 | impl SharedState { 13 | pub fn new(state: State) -> Self { 14 | SharedState(Arc::new(Mutex::new(state))) 15 | } 16 | 17 | pub fn get(&self) -> MutexGuard<'_, State> { 18 | self.0.lock().unwrap() 19 | } 20 | } 21 | 22 | /// Contains the state of the whole [app](crate::app::App). 23 | #[derive(Debug)] 24 | pub struct State { 25 | /// Current time in seconds. [Updated](crate::app::App::update) if the 26 | /// animation is not [paused](State::paused). 27 | pub time: f64, 28 | /// Speed factor (e.g. 1.0 - normal, 2.0 - 2x faster, 0.5 - 2x slower, etc). 29 | /// Affects the animation [time](State::time) and 30 | /// [delays](crate::array::Array::wait) in 31 | /// [algorithms](crate::algorithms::Algorithm). 32 | pub speed: f64, 33 | /// Is the animation paused? 34 | pub paused: bool, 35 | /// An array which is being sorted. 36 | pub array: Vec, 37 | /// Colored **overlays** of each value. **Overlay** means that these colors 38 | /// are _not_ used to [draw](crate::app::App::render) the values, instead 39 | /// they're drawn **over** the values. These colors can be used by an 40 | /// [algorithm](crate::algorithms::Algorithm) to highlight important array 41 | /// elements. 42 | /// 43 | /// The length of this vector is equal to the [array](State::array) 44 | /// length, so every color in this vector corresponds to a value with the 45 | /// exact same index. 46 | pub colors: Vec, 47 | /// Contains timestamps of the most recent array accesses of every element, 48 | /// which are drawn like [colored overlays](State::colors). The length of this 49 | /// vector is equal to the [array](State::array) length, so for every element 50 | /// in the [array](State::array) _only the most recent_ timestamp is stored 51 | /// here (not a big deal), so we can avoid memory allocations while program is 52 | /// running, and this is a pretty simple optimization. To optimize things even 53 | /// further I've done this: if an element hasn't been accessed yet or it has 54 | /// been accessed [long ago](crate::app::ACCESSED_VALUE_TIMEOUT), then instead 55 | /// of using an `Option` type for every element, I use negative values 56 | /// because they don't make any sense in the context of time (this saves 57 | /// [8 bytes](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0e335d0d6109850c7df766fd131c8916) 58 | /// for every element). When an [algorithm](crate::algorithms::Algorithm) 59 | /// [reads](crate::array::Array::get) or [writes](crate::array::Array::set) a 60 | /// value at a certain index from/to the array, the current 61 | /// [time](State::time) is stored at exactly the same index in this vector. 62 | pub array_accesses: Vec, 63 | } 64 | 65 | /// A constant that means "there's no array access here". _See_ documentation of 66 | /// [`State.array_accesses`](State::array_accesses) to understand why this 67 | /// constant is a negative number. 68 | pub const NO_ARRAY_ACCESS: f64 = -1.0; 69 | --------------------------------------------------------------------------------