Forum Settings
Forums

Pirate sort (a funny sorting algorithm) (Creative programming)

New
Nov 23, 1:05 AM
#1

Offline
May 2025
50
It's much faster than quicksort!

.
.
.
.
.
.
because it copies it's homework.

How it works:
It basically assumes that it would only ever get used in testing like other funny sorting algorithms like bogosort. When testing sorting algorithms, you usually also run 'classic' algs. like quicksort to compare times.

Pirate sort exploits this, because instead of sorting anything, it just tries to find an array the algorithms that ran before it sorted and copies it. It might work on other machines / compilers, but trying to get variables from the stack or heap like this doesn't seem like it would be stable. There are some magic numbers to prevent most of the crashing. I don't really recommend running it, but it's funny that it works at all! (don't nitpick the code, I was going for an "it just works" approach, ok?)

Btw the name comes from both copying something like piracy and the shortening of array to arr.

Code:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
int compare(const void* a, const void* b) {
    return (*(int*)a - *(int*)b);
}
//by nanisukoshi 2025
int pirate_sort(int *p, int n, int **return_arr) {
    //assumptions:
    //in a test program being compared to other sort algs.
    //a sorting alg already sorted the array and saved it before pirate_sort was called somewhere
    //assumes the result is either in teh stack or in heap and a ptr is in stack
    //plundering time
    *return_arr = (int*)calloc(n,sizeof(int));
    int min = p[0];
    for (int i = 0; i < n; i++) {
        if (min > p[i])
            min = p[i];
    }
    int min2 = p[0];
    for (int i = 0; i < n; i++) {
        if (min2 > p[i] && p[i] != min)
            min2 = p[i];
    }
    int max = p[0];
    for (int i = 0; i < n; i++) {
        if (max < p[i])
            max = p[i];
    }
    int max2 = p[0];
    for (int i = 0; i < n; i++) {
        if (max2 < p[i] && p[i] != max)
            max2 = p[i];
    }
    if (n < 200000) {
        //stack approach, look after array

        int* p1 = p + n;
        for (int i = 0; i < 196; i++) {

            if (
                *((int*)(p1 + i)) == min
                &&
                *(((int*)(p1 + i)) + 1) == min2
                ) {

                memcpy(*return_arr, ((int*)(p1 + i)), n * sizeof(int));
                return 0;

            }
        }

        //stack approach, look before array
        for (int i = 0; i < 256; i++) {
            if (
                *((int*)(p - i)) == max
                &&
                *(((int*)(p - i)) - 1) == max2
                ) {

                memcpy(*return_arr, (((int*)(p - i)) - n + 1), n * sizeof(int));
                return 0;

            }
        }
    }
    //might be better to put stack and dynamic into 1 for loop, but meh

    //dyn. allocation yoinkery
    // 
    //malloc approach, look after array
    
    long long ours = (((unsigned long long) * return_arr) & 0xFFFFFFFF);
    int* p1 = p + n;
    for (int i = 0; i < 196; i++) {
        long long target = (long long)*(p1 + i);
        target &= 0xFFFFFFFF;
        if (abs(target-ours) < 0x1000000) {
            long long target_upper = (long long)*(p1 + i+1);

            int* test = (int*)(target | target_upper << 32);
            if (*test == min && *(test + 1) == min2) {
                memcpy(*return_arr, test, n * sizeof(int));
                return 0;
            }
        }
    }

    //malloc approach, look before array
    p1 = p;
    for (int i = 0; i < 256; i++) {
        long long target = (long long)*(p1 - i);
        target &= 0xFFFFFFFF;
        if (abs(target - ours) < 0x1000000) {
            long long target_upper = (long long)*(p1 - i + 1);
            
            int* test = (int*)(target | target_upper << 32);
            if (*test == min && *(test + 1) == min2) {
                memcpy(*return_arr, test, n * sizeof(int));
                return 0;
            }
        }
    }
    

    return -1;

}
int pa(int* a, int n) {
    printf("array:\n");
    for (int i = 0; i < n; i++) {
        printf("%d\n", a[i]);
    }
}
int smallexample() {
    //opt. A)
    //int a_s[] = {1,2,3,4,5,6}; // will steal 

    //opt. D)
    //int* a1 = (int*)malloc(6 * sizeof(int)); //will steal if qsort sorts it    
   
    int a[] = { 4,6,2,3,1,5 };
    int n = sizeof(a) / sizeof(a[0]);

    //opt. B)
    //int a0[] = {4,6,2,3,1,5 }; //will steal if qsort sorts it
    //qsort(a0, n, sizeof(int), compare);
    //pa(a1, n);

    //opt. C)
    int* a1 = (int*)malloc(n * sizeof(int)); //will steal if qsort sorts it    

    //opt. C-D)
    memcpy(a1, a, sizeof(a));
    qsort(a1, n, sizeof(int), compare);
    //pa(a1, n);

    int* result_ts;
    int err = pirate_sort(a, n, &result_ts);
        printf("pirate sorted ");
        pa(result_ts, n);
        free(result_ts);// a pirate is free()

    

}
void generate_array(int* a, int n) {
    for (int i = 0; i < n; i++)
        a[i] = rand() % 100000 + 1;  // 1..100000
}
void timecompare(int n) {
    srand((unsigned)time(NULL));

    int* a = malloc(n * sizeof(int));
    int* a_q = malloc(n * sizeof(int));
    if (!a || !a_q) exit(1);

    // generate original
    generate_array(a, n);

    memcpy(a_q, a, n * sizeof(int));

    clock_t t1 = clock();
    qsort(a_q, n, sizeof(int), compare);
    clock_t t2 = clock();
    double qsort_ms = 1000.0 * (t2 - t1) / CLOCKS_PER_SEC;

    int* result_ts = NULL;
    clock_t t3 = clock();
    int err = pirate_sort(a, n, &result_ts);
    clock_t t4 = clock();
    double pirate_ms = 1000.0 * (t4 - t3) / CLOCKS_PER_SEC;

    if (err != 0) {
        printf("pirate fail\n");
    }

    printf("qsort time:       %.3f ms\n", qsort_ms);
    printf("pirate_sort time: %.3f ms\n", pirate_ms);
    //pa(result_ts, n);
    free(a);
    free(a_q);
    free(result_ts);
}
int main() {
    //smallexample();
    printf("100 elements:\n");
    timecompare(100);
    printf("1000 elements:\n");
    timecompare(1000);
    printf("10000 elements:\n");
    timecompare(10000);
    printf("100000 elements:\n");
    timecompare(100000);
    printf("200000 elements:\n");
    timecompare(200000);
    return 0;
}
Nov 23, 7:10 PM
#2
Nostalgia Rules!

Offline
Jun 2008
15899
Interesting, well I'm always up to giving these a new try when they come out.
Nov 28, 12:38 PM
#3

Offline
Sep 2016
23648
So it only works when it runs after an actual sorting function.
*kappa*
Nov 29, 4:08 AM
#4

Offline
May 2025
50
Reply to Zarutaku
So it only works when it runs after an actual sorting function.
@Zarutaku precisely, it just works*

it also crashes if it doesn't find a sorted array sometimes, which is very funny to me. Like flipping the table before you lose in a board game
Nov 29, 12:41 PM
#5

Offline
Jan 2020
998
Looks pretty intimidating for someone who's only ever used bubble sort and the standard
std::sort
from the algorithm header...
And that's C++ we're talking about here. No idea how they approach it in pure C.
Nov 29, 5:16 PM
#6
Nostalgia Rules!

Offline
Jun 2008
15899
Got a feeling a lot of people are going to be into this just because it starts with the word pirate. XD
Nov 30, 2:47 AM
#7

Offline
May 2025
50
Reply to RudeRedis
Looks pretty intimidating for someone who's only ever used bubble sort and the standard
std::sort
from the algorithm header...
And that's C++ we're talking about here. No idea how they approach it in pure C.
@RudeRedis
RudeRedis said:
from the algorithm header
I didn't write it to be readable (cursed code was kind of the passive goal). I was 'speedrunning' because I had this pirate sort idea and couldn't get it out of my head unless I made it.

But to explain it:
int pirate_sort(int *p, int n, int **return_arr)

int - return value for errors, 0 -> ok, not 0 -> error number

int *p - pointer to the original array, it could have been "int original_array[]", but I'm too lazy to write 'original_array' and adding something to a pointer to move in memory outside the bounds of an array feels more natural to me when it's an 'int*' than an 'int a[]'

int n - number of elements


int **return_arr - it's a pointer to a pointer, which you need when you want to change a pointer outside the function (or the whole array).
-You don't need int ** for this: a[0] = 2; // int *a;

-But you do need it for this: (make a new array and have the reference to it outside of the function)
*return_arr = (int*)calloc(n,sizeof(int));

More topics from this board

» Did I go over the top with the stamps on my profile?

vermerin - 1 second ago

0 by vermerin »»
1 second ago

» ♥Kukuri♥ ("Magical Circle Guru-Guru" 2017) Custom NENDOROID Doll

MasterTasuke - Dec 14

6 by kuroneko99 »»
2 hours ago

» AI-Powered Anime Recommendations + Stats ( 1 2 )

ameo___ - May 23, 2022

79 by therex55213 »»
3 hours ago

» 【 ART THREAD 】Let's share our art! ‪‪❤︎‬ ( 1 2 3 4 5 ... Last Page )

mewmewforever - Aug 30, 2024

269 by Retro8bit »»
6 hours ago

» Have you ever used ballpoint pens for drawing?

DesuMaiden - Dec 11

7 by Fukoku »»
7 hours ago
It’s time to ditch the text file.
Keep track of your anime easily by creating your own list.
Sign Up Login