Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

Genius sorting algorithm: Sleep sort

Name: Anonymous 2011-01-20 12:22

Man, am I a genius. Check out this sorting algorithm I just invented.


#!/bin/bash
function f() {
    sleep "$1"
    echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait


example usage:
./sleepsort.bash 5 3 6 3 6 3 1 4 7

Name: Anonymous 2011-01-20 12:27

>>1
Oh god, it works.

But I don't like to wait 218382 seconds to sort '(0 218382)

Name: Anonymous 2011-01-20 12:31

>>2
yes the worst case is very big

Name: Anonymous 2011-01-20 12:45

What's the complexity?

Name: Anonymous 2011-01-20 12:56

#!/bin/bash
function f() {
    sleep $(echo "$1 / 10" |bc -l)
    echo "$1"
}
while [ -n "$1" ]
do
    f "$1" &
    shift
done
wait


OMG OPTIMISED
Make sure you have an implementation of sleep that accepts floating-point arguments.

Name: Anonymous 2011-01-20 13:10

>>4
Well i'm not sure how you define it. Basically O(highest_value_in_input)

Name: Anonymous 2011-01-20 14:16

O(highest_value_in_input + n) there is a linear time for creating each thread (it is a thread right?)

congrats OP, it is awesome

Name: Anonymous 2011-01-20 14:31

okay, so basically it sleeps longer depending on the number so the smaller numbers wake up sooner?

Name: Anonymous 2011-01-20 14:35

dicksort() {
    while [ -n "$1" ]
    do
       (sleep "$1"; echo "$1") &
       shift
    done
    wait
}

dicksort 2 1 4 3 2 1 99999999

Name: Anonymous 2011-01-20 14:41

Standard value based sort if you ask me.

Name: Anonymous 2011-01-20 15:25

f() {
    if test -n "$1"
        then ( sleep $1; echo $1 ) &
        shift
        f $*
        wait
    fi
}

Name: Anonymous 2011-01-20 15:41

>>10
What else would you sort them based on? IHBT

Name: Anonymous 2011-01-20 15:57

I highly enjoyed this.

Name: Anonymous 2011-01-20 16:03

>>11
Not tail recursive.

Name: Anonymous 2011-01-20 16:08

>>14
Recurse my tail!

Name: Anonymous 2011-01-20 16:24

>>15
(tail (anus! 'my))

Name: Anonymous 2011-01-20 16:26

>>15
Intercourse under my tail!

Name: Anonymous 2011-01-20 16:28

If the difference between any two of the numbers is too small, race conditions will fuck you up the ass.

Name: Anonymous 2011-01-20 16:30

>>18
Luckily, 1 second should be enough for anyone.

Name: >>18 2011-01-20 16:32

like perhaps in:
./sleepsort 0.000002 0.000003 0.000001

Name: Anonymous 2011-01-20 16:38

What about
./sleepsort -1 -2 -3 ?

If you slept exp(n) instead of n it could easily include negative integers too!

Name: Anonymous 2011-01-20 17:12

This is sort of like a simple bucket/radix sort but instead of using a space-based array, it's effectivly using a time-based "array"

Name: Anonymous 2011-01-20 17:13

>>21
obviously the correct solution is to divide every input by two and add MAXINT/2.

Name: Anonymous 2011-01-20 17:16

>>23
OMG OPTIMIS-Oh, wait.

Name: Anonymous 2011-01-20 17:28

This thread is entertaining.  My gratitude goes to all participators.

Name: Anonymous 2011-01-20 18:19

>>21,23-24
For optimal results, use a logistic functioneg. 0.5+9.5/((1+0.5e^(-1.5(t-10)))^(2)) to normalize the inputs. You can bound the sleep time arbitrarily this way. I'm not writing that in bash.

Name: Anonymous 2011-01-20 18:43

>>26
Still doesn't solve the race condition problem. Over here it happens with values with mutual differences as high as those in:
./sleepsort 0.02 0.03 0.01

Name: Anonymous 2011-01-20 19:47

using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;

namespace SleepSort
{
    public class SleepSort
    {
        static void Main(string[] args)
        {
            var xs = new[] { 11, 215, 12, 1985, 12, 1203, 12, 152 };
            var sorted = Sort(xs, x => x);
            Console.Write("Sorted:");
            foreach (var x in sorted)
                Console.Write(" {0}", x);
            Console.WriteLine();
            Console.ReadKey(true);
        }

        public static IEnumerable<T> Sort<T>(IEnumerable<T> xs, Func<T, int> conv)
        {
            const int WEIGHT = 40000;
            var ev = new EventWaitHandle(false, EventResetMode.ManualReset);
            var q = new Queue<T>();
            ParameterizedThreadStart f = x => { ev.WaitOne(); Thread.SpinWait(conv((T)x) * WEIGHT); lock (q) { q.Enqueue((T)x); } };
            var ts = xs.Select(x => { var t = new Thread(f); t.Start(x); return t; }).ToArray();
            ev.Set();
            foreach (var t in ts)
                t.Join();
            return q;
        }
    }
}

It's still a bit of a stochastic sort.

Name: Anonymous 2011-01-20 20:21

>>28
Lol I just tried to compile this in java, but I assume now that it's C#

Name: Anonymous 2011-01-20 20:30

>>27
Well no, in fact it makes the race condition worse. Many of the differences are going to be quite small indeed after coming out of that function.

I can think of a few enhancements:
First: tailor A and Khttp://en.wikipedia.org/wiki/Generalised_logistic_curve  to the range of inputs. This adds some complexity, but it is nearly canceled by the act of spawning the sleeps and calculating Y(t) anyway.

Second: keep track of deltas upon return. When the gap is large enough relative to previous gapsFeigenbaum constant? start a new partition, reiterate the process on each. (Note: multiple partitions can be sleep-sorted at the same time.) This will distribute the sleep times more evenly among elements, however: there is still no guarantee on most platforms that any kind of sleep sort will be free of race conditions, on any set of inputs, no matter the minimum range between elements.

Third, a meta-enhancement: make best-guesses at values for the range chosen in the first enhancement for the purposes of optimal calculations. Likewise establish a good terminal condition for the second, probably when all partitions have 1 element.

If you have a huge range in input with many clusters, I think these variations are optimal over anything less sophisticated. I've no idea how often that is the case (actually... does anyone have info on this?) but it seems like it's probably common enough. Even if the clustering isn't bad, the partitioning process deals with it automatically.

Name: Anonymous 2011-01-20 20:48

>>30
lolwut

Name: Anonymous 2011-01-20 21:22

Good thread.

Name: Anonymous 2011-01-20 21:56

Yeah, that's pretty cool but check my doubles.

Name: Anonymous 2011-01-21 5:34

>>33
sweet dubs bro

Name: Anonymous 2011-01-21 5:39

Block the threads until every single one is created, also you should probably attempt to indicate to the OS that every thread doesn't need a very large stack.

Name: Anonymous 2011-01-21 5:54

Thread was better than I expected, nh OP.

Name: Anonymous 2011-01-21 6:17

>>35
Yes I was thinking about whether this algorithm could have potential use for a huge amount (eg billions) of numbers in a small range.. but i'm not sure which OS would handle billions of processes/threads... so like I said before it's essential a radix sort but in the time dimension.. the way around as others have said would be to have radix style buckets to group the numbers, then sort each bucket etc..

Name: Anonymous 2011-01-21 7:10

Oh shit, we're busted, there's a REALISTICALLY THINKING PERSON in this thread!

Name: Anonymous 2011-01-21 7:30

>>29
lol'd, but does Java have lambda expressions and var and LINQ? Didn't think so.

>>35
My implementation (>>28) blocks them, but even after letting them continue they won't all start at the exact same time.

Name: Anonymous 2011-01-21 7:38

Someone email this to Knuth.

Newer Posts