|
18 | 18 | position: absolute;
|
19 | 19 | }
|
20 | 20 | path {
|
21 |
| - transition: transform 1s |
| 21 | + transition: transform 500ms; |
| 22 | + } |
| 23 | + #controls, #controls>*{ |
| 24 | + position: relative; |
| 25 | + min-width: 200px; |
| 26 | + width: 100%; |
22 | 27 | }
|
23 | 28 | </style>
|
24 | 29 |
|
25 |
| - <button id="insertionSortBtn" type="button">Insertion Sort</button> |
26 |
| - <br><hr><br> |
| 30 | + <div id="controls"> |
| 31 | + <button id="shuffleBtn" type="button">Shuffle</button> |
| 32 | + <button id="insertionSortBtn" type="button">Insertion Sort</button> |
| 33 | + <button id="quickSortBtn" type="button">Quick Sort</button> |
| 34 | + <br><hr><br> |
| 35 | + </div> |
27 | 36 | <script type="module" defer>
|
28 |
| - import {mergeSort} from './sorting-algorithms.js' |
29 |
| - console.log(JSON.stringify(mergeSort([5, 8, 2, 6, 7, 1, 5, 2, 9, 3, 5, 8, 2, 7]))); |
| 37 | + import { |
| 38 | + quickSort, |
| 39 | + insertionSort, |
| 40 | + selectionSort, |
| 41 | + heapSort, |
| 42 | + } from './sorting-algorithms-ui.js' |
30 | 43 |
|
31 | 44 | document.addEventListener('DOMContentLoaded', async function() {
|
32 |
| - let btn = document.getElementById('insertionSortBtn'); |
33 |
| - btn.addEventListener('click', insertionSort); |
| 45 | + const delayMs = 10; |
| 46 | + document.getElementById('insertionSortBtn').addEventListener('click', async function(e) { |
| 47 | + elems = await insertionSort(elems, {cmp, swap}); |
| 48 | + console.log('done sorting'); |
| 49 | + console.log(elems); |
| 50 | + }); |
| 51 | + document.getElementById('quickSortBtn').addEventListener('click', async function(e) { |
| 52 | + elems = await quickSort(elems, {cmp, swap}); |
| 53 | + console.log('done sorting'); |
| 54 | + console.log(elems); |
| 55 | + }); |
| 56 | + document.getElementById('shuffleBtn').addEventListener('click', async function(e) { |
| 57 | + elems = await shuffle(elems); |
| 58 | + console.log('done shuffling'); |
| 59 | + console.log(elems); |
| 60 | + }); |
34 | 61 |
|
35 | 62 | let elems = Array.from(document.querySelectorAll('path')).sort(cmp);
|
| 63 | + let indexToPos = elems.map(getPos); |
36 | 64 | let idToPos = {};
|
37 | 65 | let positions = elems.forEach(elem => {
|
38 | 66 | idToPos[elem.id] = getPos(elem);
|
39 |
| - elem.setAttribute('data-pos', getPos(elem).join(" ")); |
40 | 67 | elem.setAttribute('data-originalPos', getPos(elem).join(" "));
|
41 | 68 | });
|
42 |
| - |
43 |
| - // let skull = document.getElementById('path1513'); |
44 |
| - // let leftFemur = document.getElementById('path493'); |
45 |
| - // let rightTibia = document.getElementById('path431'); |
46 |
| - // await swap(skull, leftFemur); |
47 |
| - // await swap(leftFemur, rightTibia); |
48 |
| - // await swap(skull, rightTibia); |
49 |
| - // await swap(rightTibia, leftFemur); |
50 |
| - await shuffle(); |
| 69 | + |
| 70 | + function cmp(e1, e2) { |
| 71 | + let leftVal = parseInt(e1.id.replace('path', '')) |
| 72 | + let rightVal = parseInt(e2.id.replace('path', '')) |
| 73 | + return leftVal - rightVal; |
| 74 | + } |
51 | 75 |
|
52 | 76 | function randInt(n) {
|
53 | 77 | return Math.floor(Math.random() * n);
|
54 | 78 | }
|
55 | 79 |
|
56 |
| - async function shuffle() { |
57 |
| - let keep = []; |
58 |
| - let copy = [...elems]; |
59 |
| - for (let i = 0; i < elems.length; i++) { |
60 |
| - let elem = elems[i]; |
61 |
| - let idx = randInt(copy.length); |
62 |
| - await swap(elem, copy[idx], 10); |
63 |
| - keep.push(copy[idx]); |
64 |
| - copy.splice(idx, 1); |
| 80 | + // based on https://stackoverflow.com/a/2450976/9638991 |
| 81 | + async function shuffle(arr) { |
| 82 | + let currentIndex = arr.length, randomIndex; |
| 83 | + // While there remain elements to shuffle. |
| 84 | + while (currentIndex != 0) { |
| 85 | + // Pick a remaining element. |
| 86 | + randomIndex = randInt(currentIndex); |
| 87 | + currentIndex--; |
| 88 | + await swap(arr, currentIndex, randomIndex, 1); |
65 | 89 | }
|
66 |
| - elems = keep; |
| 90 | + return arr; |
67 | 91 | }
|
68 | 92 |
|
69 | 93 | function delay(ms) {
|
|
72 | 96 |
|
73 | 97 | function getPos(elem) {
|
74 | 98 | let bbox = elem.getBBox();
|
75 |
| - // let x = rect.left + (rect.right - rect.left) / 2; |
76 |
| - // let y = rect.top + (rect.bottom - rect.top) / 2; |
77 | 99 | return [+bbox.x.toFixed(2), +bbox.y.toFixed(2)];
|
78 | 100 | }
|
79 | 101 |
|
80 |
| - async function swap(e1, e2, delayMs=3000) { |
81 |
| - let [x1, y1] = e1.dataset.pos.split(" ").map((val) => { |
82 |
| - return +val; |
83 |
| - }); |
84 |
| - let [x2, y2] = e2.dataset.pos.split(" ").map((val) => { |
85 |
| - return +val; |
86 |
| - }); |
| 102 | + async function swap(elems, i, j) { |
| 103 | + let [x1, y1] = indexToPos[i]; |
| 104 | + let [x2, y2] = indexToPos[j]; |
87 | 105 |
|
88 |
| - let [ox1, oy1] = e1.dataset.originalPos.split(" ").map((val) => { |
| 106 | + let [ox1, oy1] = elems[i].dataset.originalPos.split(" ").map((val) => { |
89 | 107 | return +val;
|
90 | 108 | });
|
91 |
| - let [ox2, oy2] = e2.dataset.originalPos.split(" ").map((val) => { |
| 109 | + let [ox2, oy2] = elems[j].dataset.originalPos.split(" ").map((val) => { |
92 | 110 | return +val;
|
93 | 111 | });
|
94 | 112 |
|
95 |
| - // console.log('--> swap()') |
96 |
| - // console.log(`ox1=${ox1},oy1=${oy1}`) |
97 |
| - // console.log(`x1=${x1},y1=${y1}`) |
98 |
| - // console.log(`ox2=${ox2},oy2=${oy2}`) |
99 |
| - // console.log(`x2=${x2},y2=${y2}`) |
100 | 113 | if (x2 == ox1 && y2 == oy1) {
|
101 |
| - e1.setAttribute('transform', `translate(0 0)`); |
102 |
| - e1.setAttribute('data-pos', e1.dataset.originalPos); |
| 114 | + elems[i].setAttribute('transform', `translate(0 0)`); |
103 | 115 | } else {
|
104 |
| - e1.setAttribute('transform', `translate(-${ox1} -${oy1}) translate(${x2} ${y2})`); |
105 |
| - e1.setAttribute('data-pos', [x2, y2].join(" ")); |
| 116 | + elems[i].setAttribute('transform', `translate(-${ox1} -${oy1}) translate(${x2} ${y2})`); |
106 | 117 | }
|
107 | 118 | if (x1 == ox2 && y1 == oy2) {
|
108 |
| - e2.setAttribute('transform', `translate(0 0)`); |
109 |
| - e2.setAttribute('data-pos', e2.dataset.originalPos); |
| 119 | + elems[j].setAttribute('transform', `translate(0 0)`); |
110 | 120 | } else {
|
111 |
| - e2.setAttribute('transform', `translate(-${ox2} -${oy2}) translate(${x1} ${y1})`); |
112 |
| - e2.setAttribute('data-pos', [x1, y1].join(" ")); |
113 |
| - } |
114 |
| - if (delayMs) { |
115 |
| - await delay(delayMs); |
116 |
| - } |
117 |
| - } |
118 |
| - |
119 |
| - function cmp(e1, e2) { |
120 |
| - let leftVal = parseInt(e1.id.replace('path', '')) |
121 |
| - let rightVal = parseInt(e2.id.replace('path', '')) |
122 |
| - console.log(`${leftVal} - ${rightVal} = ${leftVal-rightVal}`) |
123 |
| - return leftVal - rightVal; |
124 |
| - } |
125 |
| - |
126 |
| - async function insertionSort() { |
127 |
| - for (let i = 0; i < elems.length; i++) { |
128 |
| - for (let j = i; j > 0 && cmp(elems[j - 1], elems[j]) < 0; j--) { |
129 |
| - swap(elems[j], elems[j - 1], 1000); |
130 |
| - } |
| 121 | + elems[j].setAttribute('transform', `translate(-${ox2} -${oy2}) translate(${x1} ${y1})`); |
131 | 122 | }
|
132 |
| - console.log(elems); |
| 123 | + let tmp = elems[i]; |
| 124 | + elems[i] = elems[j]; |
| 125 | + elems[j] = tmp; |
| 126 | + await delay(delayMs); |
133 | 127 | }
|
134 | 128 | })
|
135 | 129 | </script>
|
|
0 commit comments