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
@@ -30,6 +30,9 @@
3030
             <button class="algorithm-btn" onclick="selectAlgorithm('radix')">RADIX</button>
3131
             <button class="algorithm-btn" onclick="selectAlgorithm('gnome')">GNOME</button>
3232
             <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>
3336
             <button id="startBtn" onclick="startSort()">EXECUTE</button>
3437
             <button id="soundBtn" onclick="toggleSound()">SOUND: ON</button>
3538
             <div class="speed-control">
js/app.jsmodified
@@ -67,11 +67,16 @@ function estimateSortingTime() {
6767
         case 'heap':
6868
             return baseTime * Math.log2(array.length) * 2;
6969
         case 'shell':
70
+        case 'comb':
7071
             return baseTime * array.length * 0.3;
7172
         case 'radix':
7273
             return baseTime * 3;
7374
         case 'gnome':
7475
             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);
7580
         case 'bogo':
7681
             return baseTime * 10; // Who knows!
7782
         default:
@@ -339,6 +344,15 @@ async function startSort() {
339344
         case 'bogo':
340345
             await bogoSort();
341346
             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;
342356
     }
343357
     
344358
     // Stop slide whistle and play zoot
@@ -763,6 +777,138 @@ function markAllSorted() {
763777
     });
764778
 }
765779
 
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
+
766912
 // Initialize
767913
 generateArray();
768914
 document.querySelector('.algorithm-btn').click();