zeroed-some/sortmanteau / 53b34a9

Browse files

new sorts

Authored by espadonne
SHA
53b34a9cad68d51f5518b757631fd64dcafef99d
Parents
229c345
Tree
4f5bc6a

2 changed files

StatusFile+-
M index.html 6 3
M js/app.js 146 0
index.htmlmodified
@@ -10,9 +10,9 @@
10
     <div class="container">
10
     <div class="container">
11
         <header>
11
         <header>
12
             <div class="ascii-title">
12
             <div class="ascii-title">
13
-               ╔═╗ ╔═╗ ╔═╗ ╦╦  ╔═╗ ╔═╗ ╦═╗ ╔╦╗ ╔═╗ ╦═╗
13
+╔═╗╔═╗╔═╗╦╦  ╔═╗╔═╗╦═╗╔╦╗╔═╗╦═╗
14
-              ╠═╣ ╚═╗ ║   ║║  ╚═╗ ║ ║ ╠╦╝  ║  ║╣  ╠╦╝
14
+╠═╣╚═╗║  ║║  ╚═╗║ ║╠╦╝ ║ ║╣ ╠╦╝
15
-               ╩ ╩ ╚═╝ ╚═╝ ╩╩  ╚═╝ ╚═╝ ╩╚═  ╩  ╚═╝ ╩╚═
15
+╩ ╩╚═╝╚═╝╩╩  ╚═╝╚═╝╩╚═ ╩ ╚═╝╩╚═
16
             </div>
16
             </div>
17
             <p class="subtitle">&gt;&gt; TERMINAL SORTING VISUALIZATION &lt;&lt;</p>
17
             <p class="subtitle">&gt;&gt; TERMINAL SORTING VISUALIZATION &lt;&lt;</p>
18
         </header>
18
         </header>
@@ -30,6 +30,9 @@
30
             <button class="algorithm-btn" onclick="selectAlgorithm('radix')">RADIX</button>
30
             <button class="algorithm-btn" onclick="selectAlgorithm('radix')">RADIX</button>
31
             <button class="algorithm-btn" onclick="selectAlgorithm('gnome')">GNOME</button>
31
             <button class="algorithm-btn" onclick="selectAlgorithm('gnome')">GNOME</button>
32
             <button class="algorithm-btn" onclick="selectAlgorithm('bogo')">BOGO</button>
32
             <button class="algorithm-btn" onclick="selectAlgorithm('bogo')">BOGO</button>
33
+            <button class="algorithm-btn" onclick="selectAlgorithm('comb')">COMB</button>
34
+            <button class="algorithm-btn" onclick="selectAlgorithm('pancake')">PANCAKE</button>
35
+            <button class="algorithm-btn" onclick="selectAlgorithm('bitonic')">BITONIC</button>
33
             <button id="startBtn" onclick="startSort()">EXECUTE</button>
36
             <button id="startBtn" onclick="startSort()">EXECUTE</button>
34
             <button id="soundBtn" onclick="toggleSound()">SOUND: ON</button>
37
             <button id="soundBtn" onclick="toggleSound()">SOUND: ON</button>
35
             <div class="speed-control">
38
             <div class="speed-control">
js/app.jsmodified
@@ -67,11 +67,16 @@ function estimateSortingTime() {
67
         case 'heap':
67
         case 'heap':
68
             return baseTime * Math.log2(array.length) * 2;
68
             return baseTime * Math.log2(array.length) * 2;
69
         case 'shell':
69
         case 'shell':
70
+        case 'comb':
70
             return baseTime * array.length * 0.3;
71
             return baseTime * array.length * 0.3;
71
         case 'radix':
72
         case 'radix':
72
             return baseTime * 3;
73
             return baseTime * 3;
73
         case 'gnome':
74
         case 'gnome':
74
             return baseTime * array.length * 0.7;
75
             return baseTime * array.length * 0.7;
76
+        case 'pancake':
77
+            return baseTime * array.length * 0.8;
78
+        case 'bitonic':
79
+            return baseTime * Math.log2(array.length) * Math.log2(array.length);
75
         case 'bogo':
80
         case 'bogo':
76
             return baseTime * 10; // Who knows!
81
             return baseTime * 10; // Who knows!
77
         default:
82
         default:
@@ -339,6 +344,15 @@ async function startSort() {
339
         case 'bogo':
344
         case 'bogo':
340
             await bogoSort();
345
             await bogoSort();
341
             break;
346
             break;
347
+        case 'comb':
348
+            await combSort();
349
+            break;
350
+        case 'pancake':
351
+            await pancakeSort();
352
+            break;
353
+        case 'bitonic':
354
+            await bitonicSort();
355
+            break;
342
     }
356
     }
343
     
357
     
344
     // Stop slide whistle and play zoot
358
     // Stop slide whistle and play zoot
@@ -763,6 +777,138 @@ function markAllSorted() {
763
     });
777
     });
764
 }
778
 }
765
 
779
 
780
+// Comb Sort (improved Bubble Sort with gap)
781
+async function combSort() {
782
+    let gap = array.length;
783
+    let shrink = 1.3;
784
+    let sorted = false;
785
+    
786
+    while (gap > 1 || !sorted) {
787
+        // Update gap
788
+        gap = Math.floor(gap / shrink);
789
+        if (gap < 1) gap = 1;
790
+        
791
+        sorted = true;
792
+        
793
+        // Single pass with current gap
794
+        for (let i = 0; i + gap < array.length; i++) {
795
+            await compare(i, i + gap);
796
+            if (array[i] > array[i + gap]) {
797
+                await swap(i, i + gap);
798
+                sorted = false;
799
+            }
800
+        }
801
+        
802
+        // Mark sorted elements when gap is 1 (final pass)
803
+        if (gap === 1 && sorted) {
804
+            for (let i = 0; i < array.length; i++) {
805
+                document.querySelectorAll('.bar-row')[i].classList.add('sorted');
806
+                await sleep(getDelay() / 4);
807
+            }
808
+        }
809
+    }
810
+}
811
+
812
+// Pancake Sort (flip sort)
813
+async function pancakeSort() {
814
+    for (let curr_size = array.length; curr_size > 1; curr_size--) {
815
+        // Find index of maximum element in unsorted portion
816
+        let maxIdx = 0;
817
+        for (let i = 1; i < curr_size; i++) {
818
+            await compare(i, maxIdx);
819
+            if (array[i] > array[maxIdx]) {
820
+                maxIdx = i;
821
+            }
822
+        }
823
+        
824
+        // Move maximum element to end if it's not already there
825
+        if (maxIdx !== curr_size - 1) {
826
+            // Flip to move max to beginning
827
+            if (maxIdx !== 0) {
828
+                await flip(maxIdx + 1);
829
+            }
830
+            
831
+            // Flip to move max to correct position
832
+            await flip(curr_size);
833
+        }
834
+        
835
+        document.querySelectorAll('.bar-row')[curr_size - 1].classList.add('sorted');
836
+    }
837
+    document.querySelectorAll('.bar-row')[0].classList.add('sorted');
838
+}
839
+
840
+// Helper function for pancake sort - flips array from 0 to n-1
841
+async function flip(n) {
842
+    let start = 0;
843
+    let end = n - 1;
844
+    
845
+    while (start < end) {
846
+        await swap(start, end);
847
+        start++;
848
+        end--;
849
+    }
850
+}
851
+
852
+// Bitonic Sort (requires power of 2 array size)
853
+async function bitonicSort() {
854
+    // Adjust array size to nearest power of 2 if needed
855
+    const originalLength = array.length;
856
+    const nextPowerOf2 = Math.pow(2, Math.ceil(Math.log2(array.length)));
857
+    
858
+    // Pad with large values if necessary
859
+    while (array.length < nextPowerOf2) {
860
+        array.push(999);
861
+    }
862
+    renderArray();
863
+    
864
+    // Start the bitonic sort
865
+    await bitonicSortRecursive(0, array.length, true);
866
+    
867
+    // Remove padding if we added any
868
+    if (array.length > originalLength) {
869
+        array.length = originalLength;
870
+        renderArray();
871
+    }
872
+    
873
+    // Mark all as sorted
874
+    for (let i = 0; i < originalLength; i++) {
875
+        document.querySelectorAll('.bar-row')[i].classList.add('sorted');
876
+    }
877
+}
878
+
879
+async function bitonicSortRecursive(lo, cnt, dir) {
880
+    if (cnt > 1) {
881
+        let k = Math.floor(cnt / 2);
882
+        
883
+        // Sort in ascending order
884
+        await bitonicSortRecursive(lo, k, true);
885
+        
886
+        // Sort in descending order
887
+        await bitonicSortRecursive(lo + k, k, false);
888
+        
889
+        // Merge the whole sequence
890
+        await bitonicMerge(lo, cnt, dir);
891
+    }
892
+}
893
+
894
+async function bitonicMerge(lo, cnt, dir) {
895
+    if (cnt > 1) {
896
+        let k = Math.floor(cnt / 2);
897
+        
898
+        for (let i = lo; i < lo + k; i++) {
899
+            await compare(i, i + k);
900
+            
901
+            // Swap if needed based on direction
902
+            if ((array[i] > array[i + k]) === dir) {
903
+                await swap(i, i + k);
904
+            }
905
+        }
906
+        
907
+        await bitonicMerge(lo, k, dir);
908
+        await bitonicMerge(lo + k, k, dir);
909
+    }
910
+}
911
+
766
 // Initialize
912
 // Initialize
767
 generateArray();
913
 generateArray();
768
 document.querySelector('.algorithm-btn').click();
914
 document.querySelector('.algorithm-btn').click();