Sortiere das, schnell!


27

Nun ... es gibt 59 (jetzt 60) Fragen mit Tags zum , aber keine einfachen QuickSorts.

Das muss behoben werden.

Für diejenigen, die mit Quicksort nicht vertraut sind , hier eine Aufschlüsselung mit freundlicher Genehmigung von Wikipedia-

  1. Wählen Sie aus dem Array ein Element aus, das als Pivot bezeichnet wird.
  2. Ordnen Sie das Array neu an, sodass alle Elemente mit Werten, die kleiner als der Pivot sind, vor dem Pivot stehen, während alle Elemente mit Werten, die größer als der Pivot sind, nach dem Pivot stehen (gleiche Werte können in beide Richtungen gehen). Nach dieser Unterteilung befindet sich der Zapfen in seiner Endposition. Dies wird als Partitionsoperation bezeichnet.
  3. Wenden Sie die obigen Schritte rekursiv auf das Unterarray von Elementen mit kleineren Werten und separat auf das Unterarray von Elementen mit größeren Werten an.

Regeln

Die Regeln sind einfach:

  • Implementieren Sie eine numerische Kurzübersicht in einer Programmiersprache Ihrer Wahl.
  • Der Drehpunkt sollte zufällig oder im Median von drei (1., letztes und mittleres Element) gewählt werden.
  • Ihr Programm kann ein vollständiges Programm oder eine Funktion sein.
  • Sie können die Eingabe über STDIN, Befehlszeilenargumente oder Funktionsparameter abrufen. Bei Verwendung einer Zeichenfolge wird die Eingabe durch Leerzeichen getrennt.
  • Die Eingabe kann dezimale und negative Werte enthalten. Es gibt jedoch keine Duplikate.
  • Sie können auf STDOUT ausgeben oder von der Funktion zurückkehren.
  • Keine eingebauten (oder sortierungsbezogenen) Sortierfunktionen oder Standardlücken.
  • Die Liste kann eine beliebige Länge haben.

Bonus Nr. 1: Verwenden Sie bei Listen oder Unterlisten mit einer Länge <= 5 die Einfügesortierung , um die Dinge etwas zu beschleunigen. Belohnung: -15%.

Bonus Nr. 2: Wenn Ihre Sprache Parallelität unterstützt, sortieren Sie die Liste parallel. Wenn Sie eine Einfügesortierung für Unterlisten verwenden, muss die endgültige Einfügesortierung nicht parallel sein. Eingebaute Thread Pools / Thread Scheduling sind erlaubt. Belohnung: -15%.

Hinweis: Der Median von drei verwirrte einige Leute, daher hier eine Erklärung mit freundlicher Genehmigung von Wikipedia:

Auswahl des Medians des ersten, mittleren und letzten Elements der Partition für den Drehpunkt

Wertung

Das ist . Die Basisbewertung wird in Byte angegeben. Wenn Sie einen Bonus erhalten haben, erhalten Sie 15% Rabatt auf diese Nummer. Wenn Sie beides haben, erhalten Sie 30% Rabatt. Das klingt wirklich nach einem Verkaufsgespräch.

Es geht nicht darum, die kürzeste Antwort insgesamt zu finden, sondern die kürzeste in jeder Sprache.

Und jetzt eine schamlose Kopie des Leaderboard-Snippets.

Das Leaderboard

Das Stapel-Snippet am Ende dieses Beitrags generiert den Katalog aus den Antworten a) als Liste der kürzesten Lösungen pro Sprache und b) als Gesamt-Bestenliste.

Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

## Language Name, N bytes

Wobei N die Größe Ihrer Einreichung ist. Wenn Sie Ihre Punktzahl verbessern, können Sie alte Punkte in der Überschrift behalten, indem Sie sie durchstreichen. Zum Beispiel:

## Ruby, <s>104</s> <s>101</s> 96 bytes

Wenn Sie mehrere Zahlen in Ihre Kopfzeile aufnehmen möchten (z. B. weil Ihre Punktzahl die Summe von zwei Dateien ist oder wenn Sie die Strafen für Interpreter-Flags separat auflisten möchten), stellen Sie sicher, dass die tatsächliche Punktzahl die letzte Zahl in der Kopfzeile ist:

## Perl, 43 + 2 (-p flag) = 45 bytes

Sie können den Namen der Sprache auch als Link festlegen, der dann im Snippet angezeigt wird:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes


4
"Der Drehpunkt sollte zufällig oder mit dem Median von drei (1., letztes und mittleres Element) gewählt werden." Was bedeutet das? Sie haben bereits gesagt, dass nur ein Element ausgewählt ist.
msh210

2
@daniero Snippet ist jetzt behoben
Daniel M.

1
Ist der Medianwahlalgorithmus eine schwierige Anforderung? Es ist in Sprachen, die eine verknüpfte Liste als primären Array-Typ verwenden (Haskell, LISP), unpraktisch (wie in) und es gibt bereits mindestens eine Antwort, die die Regel ignoriert.
John Dvorak

2
Sowohl der zufällige Pivot als auch der Median von drei sind in listenbasierten Sprachen problematisch. Beide erfordern einen wahlfreien Zugriff auf das Array, und der Zugriff auf das Ende einer verknüpften Liste ist O (n). Das Nehmen des Medians der ersten drei Elemente ist nicht ganz das Gleiche (auch, weil Sie den gleichen Drehpunkt sowieso innerhalb von drei Teilungen haben) und kompliziert den Code nur ohne triftigen Grund.
John Dvorak

1
Random Pivot ist in Haskell auch aus einem anderen Grund problematisch: Sobald Sie mit dem Würfeln beginnen, schreiben Sie keine Funktion mehr. Sie definieren eine E / A-Aktion, die ein Array erzeugt. Sie könnten eine Funktion definieren, die einen RNG-Status als Argument verwendet, aber auch nicht zu groß.
John Dvorak

Antworten:


10

C ++, 440,3 405 388 Bytes

518 Bytes - 15% Bonus für Einfügesortierung = 440,3 Bytes

477 Bytes - 15% Bonus für Einfügesortierung = 405,45 Bytes

474 Bytes - 15% Bonus für Einfügesortierung = 402,9 Bytes

456 bytes - 15% bonus for insertion sort = 387.6 bytes

Vielen Dank an @Luke für das Speichern von 3 Bytes (2 wirklich).

Vielen Dank an @ Dúthomhas für das Speichern von 18 (wirklich 15) Bytes.

Beachten Sie, dass ich neu hier bin und dies mein erster Beitrag ist.

Dies ist eine .h(Header-) Datei.

Komprimierter Code:

#include<iostream>
#include<ctime>
#include<cstdlib>
void s(int a[],int i,int j){int t=a[i];a[i]=a[j];a[j]=t;}int z(int a[],int b,int e){int p=a[(rand()%(e-b+1))+b];b--;while(b<e){do{b++;}while(a[b]<p);do{e--;}while(a[e]>p);if(b<e){s(a, b, e)}}return b;}void q(int a[],int b,int e){if(e-b<=5){for(int i=b;i<e;i++){for(int j=i;j>0;j--){if(a[j]<a[j-1]){s(a,j,j-1);}else{break;}}}return;}int x=z(a,b,e);q(a,b,x);q(a,x,e);}void q(int a[],int l){q(a,0,l);}

Vollständiger Code:

#include <iostream>
#include <ctime>
#include <cstdlib>

void swapElements(int toSort[], int i, int j) {
    int temp = toSort[i];
    toSort[i] = toSort[j];
    toSort[j] = temp;
}

int partitionElements(int toSort[], int beginPtr, int endPtr)
{
    int pivot = toSort[(rand() % endPtr - beginPtr + 1) + beginPtr];
    beginPtr--;
    while (beginPtr < endPtr) {
        do {
            beginPtr++;
        } while (toSort[beginPtr] < pivot);
        do {
            endPtr--;
        } while (toSort[endPtr] > pivot);
        if (beginPtr < endPtr) {
            // Make sure they haven't crossed yet
            swapElements(toSort, beginPtr, endPtr);
        }
    }
    return beginPtr;
}

void quickSort(int toSort[], int beginPtr, int endPtr)
{
    if (endPtr - beginPtr <= 5) { // Less than 5: insertion sort
        for (int i = beginPtr; i < endPtr; i++) {
            for (int j = i; j > 0; j--) {
                if (toSort[j] < toSort[j - 1]) {
                    swapElements(toSort, j, j - 1);
                } else {
                    break;
                }
            }
        }
        return;
    }
    int splitIndex = partitionElements(toSort, beginPtr, endPtr);
    quickSort(toSort, beginPtr, splitIndex );
    quickSort(toSort, splitIndex, endPtr);
}

void quickSort(int toSort[], int length)
{
    quickSort(toSort, 0, length);
}

5
Sie können 10 Bytes speichern, indem Sie einen einzelnen Buchstaben anstelle von quickSort verwenden und Leerzeichen im letzten Funktionsaufruf entfernen. Und ich wette, dass Sie ein besseres Ergebnis erzielen können, wenn Sie den Bonus vermeiden (15% sind nicht genug)
edc65

1
Sie können weitere 5 Byte speichern, indem Sie die eckigen Klammern der Argumente durch einzelne Sternchen ersetzen. Ein bisschen Makromagie könnte noch mehr Bytes abschneiden, denke ich.
Cadaniluk

2
Du brauchst kein Leerzeichen danach #include.
Luke

Beseitigen Sie 34 Bytes, indem Sie den Aufruf von entfernen. srand(time(NULL));Sie erhalten weiterhin Pseudozufallszahlen von rand().
Dúthomhas

9

APL, 49-42 Bytes

{1≥⍴⍵:⍵⋄(∇⍵/⍨⍵<p),(⍵/⍨⍵=p),∇⍵/⍨⍵>p←⍵[?⍴⍵]}

Dadurch wird eine unbenannte rekursive monadische Funktion erstellt, die ein Array auf der rechten Seite akzeptiert. Es ist nicht für den Bonus qualifiziert.

Erläuterung:

{1≥⍴⍵:⍵⋄                                     ⍝ If length(⍵) ≤ 1, return ⍵
                                  p←⍵[?⍴⍵]}  ⍝ Choose a random pivot
                           ∇⍵/⍨⍵>            ⍝ Recurse on >p
                  (⍵/⍨⍵=p),                  ⍝ Concatenate with =p
        (∇⍵/⍨⍵<p),                           ⍝ Recurse on <p

Probieren Sie es online aus

Behebung eines Problems (zu Lasten von 8 Bytes) durch Marinus und Speicherung von 7 Bytes durch Thomas Kwa!


Die Frage gibt an, dass keine Duplikate vorhanden sind. (Ich weiß nicht, wie lange ich
gebraucht habe

5

C ++ 17, 254 199 195 Bytes

#include<vector>
#include<cstdlib>
#define P push_back(y)
using V=std::vector<int>;V q(V a){int p=a.size();if(p<2)return a;p=rand()%p;V l,r;for(y:a)(y<a[p]?l:r).P;l=q(l);for(y:q(r))l.P;return l;}

Mit Leerzeichen:

V q(V a) {
    int p = a.size();

    if (p < 2)
        return a;

    p = rand() % p;
    V l,r;

    for (y : a)
        (y < a[p] ? l : r).P;

    l=q(l);

    for (y : q(r))
        l.P;

    return l;
}

Keine Notwendigkeit für Srand (Zeit (NULL)). Das Löschen ist nicht erforderlich, lassen Sie den Wert einfach partitionieren und ändern Sie dann if (a.empty ()) in if (a.size () <2) und entfernen Sie lP (x).
Chris Jefferson

Durch das Eliminieren des Löschvorgangs konnte ich viele Bytes sparen . Vielen Dank!
Lynn

Eine andere kleine: Keine Notwendigkeit, 'r = q (r)' zuzuweisen, verwenden Sie einfach 'for (y: q (r))', aber das ist alles, was ich sehen kann!
Chris Jefferson

Nur aus Neugier: Wo wird hier insbesondere C ++ 17 eingesetzt?
kirbyfan64sos

1
for (y : a)müsste sonst sein for (auto y : a)oder for (int y : a). ( Nenntclang++ dies eigentlich eine C ++ 1z-Erweiterung , aber es scheint nicht wirklich C ++ 17 zu sein? Ich weiß es nicht und es ist zu spät nachts, um nachzuschlagen.)
Lynn

4

Pyth, 25 Bytes

L?tbsyMa_,]JObf<TJbf>TJbb

Dies definiert eine Funktion y, die eine Liste von Zahlen als Eingabe akzeptiert.

Probieren Sie es online aus: Demonstration

Erläuterung

L?tbsyMa_,]JObf<TJbf>TJbb
L                          define function y(b), that returns: 
 ?tb                         if t[1:] (if the list has more than one element):
            Ob                 choose a random element of b
           J                   save it in J
          ]                    put J in a list
         ,    f<TJb            create a pair, that contains ^ and a list of 
                               all numbers smaller than J: [[J], [smaller than J]] 
        _                      reverse this list: [[smaller than J], [J]]
       a           f>TJb       append a list with all elements bigger than J: 
                               [[smaller than J], [J], [bigger than J]]
     yM                        call y recursively for each sublist
    s                          combine the results and return it
                        b    else: simply return b

Pyth, 21 Bytes (wahrscheinlich ungültig)

Ich verwende die "group-by" -Methode, die intern eine Sortierung verwendet. Ich verwende es, um die ursprüngliche Liste in drei Unterlisten aufzuteilen (alle Elemente kleiner als der Pivot, der Pivot und alle Elemente größer als der Pivot). Ohne die Sortierung in "Gruppieren nach" könnten diese 3 Listen in einer anderen Reihenfolge zurückgegeben werden.

Wie gesagt, das ist wahrscheinlich ungültig. Trotzdem behalte ich es hier, weil es eine interessante Lösung ist.

L?tb&]JObsyM.g._-kJbb

Probieren Sie es online aus: Demonstration

Erläuterung

L?tb&]JObsyM.g._-kJbb
L                      def y(b): return
 ?tb                     if t[1:] (if the list has more than one element):
       Ob                  choose a random element of b
      J                    save it in J
    &]                     put it in an array and call "and" 
                           (hack which allows to call 2 functions in one statement)

            .g     b       group the elements in b by:
              ._-kJ           the sign of (k - J)
                           this generates three lists
                             - all the elements smaller than J
                             - J
                             - all the elements bigger than J
          yM               call y recursively for all three lists
         s                 and combine them
                    b    else: return b

3

> <> (Fisch), 313 309 Bytes

!;00l[l2-[b1.
>:0)?v~$:@&vl2,$:&${:}$
^-1@{< ]]. >055[3[5b.
?v~~@~ v:}@:}@:}:}@:}@}}}(}(}({{:@=
.>=$~?$>~]]
.001-}}d6.{$}1+}d6
?v:{:}@{(?v08.}:01-=
 >{$~~{09.>95.v-1@{<   v-1}$<
.:@}:@{=${::&@>:0)?^~}&>:0)?^~+}d6
 1-:0a.{{$&l&1+-: >:0)?v~:1)?!v62fb.
>:0)?v~:}:1)?v~69.^@{-1<>.!]]~<
^@{-1<:}@@73.>69@@:3+[{[b1.

Ich habe sehr lange gebraucht, um zu schreiben. Sie können es hier ausprobieren , indem einfach die Liste, die sortiert werden soll, in den Anfangsstapel, der durch Kommas getrennt ist, einfügen, bevor Sie das Programm ausführen.

Wie es funktioniert

Das Programm erfasst das erste, mittlere und letzte Element im Anfangsstapel und berechnet den Median dieser drei Elemente.
Es ändert dann den Stapel in:

[Liste 1] Element [Liste 2]

Dabei ist alles in Liste 1 kleiner oder gleich dem Element und alles in Liste 2 größer.
Dieser Vorgang wird in Liste 1 und Liste 2 rekursiv wiederholt, bis die gesamte Liste sortiert ist.


2

CJam, 40 Bytes

{_1>{_mR:P-PaL@{_P<{+}{@\+\}?}/J\J+}&}:J

Dies ist eine benannte Funktion, die ein Array auf dem Stapel erwartet und eins zurückschiebt.

Probieren Sie es online im CJam-Interpreter aus .

Der obige Code folgt der Spezifikation so genau wie möglich. Wenn dies nicht erforderlich ist, können 12 Bytes gespeichert werden:

{_1>{_mR:P;_{P<},J_@^J+}&}:J

2

Python 3, 123 , 122.

1 Byte dank Aaron gespeichert.

Dies ist das erste Mal, dass ich mir die Mühe gemacht habe, einen Sortieralgorithmus zu schreiben. Es ist eigentlich ein bisschen einfacher als ich dachte.

from random import*
def q(s):
 if len(s)<2:return s
 p=choice(s);return q([d for d in s if d<=p])+q([d for d in s if d>p])

Ungolfed:

from random import choice
def quick_sort(seq):
    if len(seq) < 2:
        return seq
    low = []
    high = []
    pivot = choice(seq)
    for digit in seq:
        if digit > pivot:
            high += [digit]
        else:
            low += [digit]
    return quick_sort(low) + quick_sort(high)

Das sieht so aus, als würde es aufgrund des <=Vergleichs möglicherweise nicht funktionieren - es garantiert nicht, dass pes an der richtigen Stelle ist. Wahrscheinlich müssen Sie dies in eine exklusive Ungleichung ändern und pin der Mitte unabhängig hinzufügen (ich habe es nicht getestet / kann) den Code nicht testen).
VisualMelon

@VisualMelon Ich habe es mit einer Reihe verschiedener Fälle getestet und nie ein falsches Ergebnis erhalten. Wenn Sie jedoch einen Testfall finden, der das Problem beseitigt, lassen Sie es mich wissen. Möglicherweise funktioniert es auch nicht mit Duplikaten, die Abfrage gibt jedoch an, dass keine Duplikate vorhanden sind.
Morgan Thrapp

Ich hätte gedacht, dass [2, 1, 3]das 1/3 der Zeit kaputt gehen würde, denn wenn der Pivot auf 2 gesetzt wird, wird die niedrige Liste lauten [2, 1]- es tut mir leid, dass ich das jetzt selbst nicht testen kann.
VisualMelon

@VisualMelon Na klar, aber es wird dann wieder rekursiv sortiert.
Morgan Thrapp

Ah, tut mir leid, habe das komplett verpasst, nicht ganz, wie ich erwartet hätte, dass ein Quicksort implementiert wird. Habe ein Plus für die Verwirrung
VisualMelon

2

Javascript (ES2015), 112

q=l=>{let p=l[(Math.random()*l.length)|0];return l.length<2?l:q(l.filter(x=>x<=p)).concat(q(l.filter(x=>x>p)));}

Erläuterung

//Define lambda function q for quicksort
q=l=>{

    //Evaluate the pivot
    let p=l[(Math.random()*l.length)|0];

    //return the list if the length is less than 2
    return l.length < 2 ? l:

    //else return the sorted list of the elements less or equal than 
      the pivot concatenated with the sorted list of the elements 
      greater than the pivot
    q(l.filter(x=>x<=p)).concat(q(l.filter(x=>x>p)));
}

ES6 könnte dies wahrscheinlich verkürzen.
Nissa

1

Rubin, 87 60 Bytes

q=->a,p=a.sample{a[1]?(l,r=a.partition{|e|e<p};q[l]+q[r]):a}

Ungolfed:

def quicksort(a, pivot=a.sample)
  if a.size > 1
    l,r = a.partition { |e| e < pivot}
    quicksort(l) + quicksort(r)
  else
    a
  end
end

Prüfung:

q[[9, 18, 8, 5, 13, 20, 7, 14, 16, 15, 10, 11, 2, 4, 3, 1, 12, 17, 6, 19]]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]

1

Oktave, 76 75 Bytes

function u=q(u)n=numel(u);if n>1 k=u(randi(n));u=[q(u(u<k)),q(u(u>=k))];end

Mehrzeilige Version:

function u=q(u) 
   n=numel(u);
   if n>1 
      k=u(randi(n));
      u=[q(u(u<k)),q(u(u>=k))];
   end

1

Julia, 83 Bytes

Q(x)=endof(x)<2?x:(p=rand(x);[Q((f=filter)(i->i<p,x));f(i->i==p,x);Q(f(i->i>p,x))])

Dies erzeugt eine rekursive Funktion Q , die ein Array akzeptiert und ein Array zurückgibt. Es wird keine bedingte Einfügesortierung verwendet, sodass kein Bonus angewendet wird.

Ungolfed:

function Q(x::AbstractArray)
    if endof(x)  1
        # Return on empty or 1-element arrays
        x
    else
        # Select a random pivot
        p = rand(x)

        # Return the function applied to the elements less than
        # the pivot concatenated with those equal to the pivot
        # and the function applied to those greater than the pivot
        [Q(filter(i -> i < p, x));
         filter(i -> i == p, x);
         Q(filter(i -> i > p, x))]
    end
end

Ein Problem wurde behoben und dank Glen O einige Bytes gespart!


Abgesehen von möglichen Problemen mit dem Verlust von Wiederholungselementen (die bereits in Ihrem Code vorhanden sind) können Sie hier einige Bytes einsparen, findem Sie bei der ersten Verwendung zuweisen filterund endofanstelle von verwenden length. Q(x)=endof(x)<2?x:(p=rand(x);[Q((f=filter)(i->i<p,x));p;Q(f(i->i>p,x))])
Glen O

@ GlenO Danke für den Vorschlag. Ich habe das implementiert und das Problem mit wiederholten Elementen behoben.
Alex A.

Ich sagte, es könnte ein Problem sein, aber ich stellte das Fragenposter zur Klärung und "Die Eingabe kann Dezimal- und Negativwerte enthalten. Es wird jedoch keine Duplikate geben"
Glen O

1

R, 78 Bytes

Q=function(x)if(length(x)>1)c(Q(x[x<(p=sample(x,1))]),x[x==p],Q(x[x>p]))else x

Dadurch wird eine rekursive Funktion erstellt Q, die einen Vektor akzeptiert und einen Vektor zurückgibt. Es wird keine bedingte Einfügesortierung angewendet, daher kein Bonus.

Ungolfed:

Q <- function(x) {
    # Check length
    if (length(x) > 1) {
        # Select a random pivot
        p <- sample(x, 1)

        # Recurse on the subarrays consisting of
        # elements greater than and less than p,
        # concatenate with those equal to p
        c(Q(x[x < p]), x[x == p], Q(x[x > p]))
    } else {
        x
    }
}

Probieren Sie es online aus

4 Bytes gespart dank flodel!


Sie können ein paar Bytes weg knabbern, indem Sie die "> 1" aus dem Längenvergleich entfernen. Dies vergleicht es implizit mit 0, aber eine zusätzliche Rekursionsebene ist kein Problem
Miff

@Miff Danke für deine Eingabe, aber ich habe es versucht und es liefert nicht das erwartete Ergebnis für mich.
Alex A.

1

K, 41 Bytes

s:{$[#x;(s@x@&x<p),p,s@x@&x>p:x@*1?#x;x]}

NEHMEN SIE DAS, APL !!! Tut keinen der Boni.


1

Haskell, 137136 Bytes

f=filter
m a b c=max(min a b)(min(max a b)c)
q[]=[]
q l=let{n=m(head l)(head$drop(length l`div`2)l)(last l)}in(q$f(<n)l)++(n:(q$f(>n)l))

Die ungolfed Version ist hierunter, mit erweiterten Variablen- und Funktionsnamen und einigen Zwischenergebnissen, die hinzugefügt wurden:

median a b c = max (min a b) (min (max a b) c)
quicksort [] = []
quicksort l = let mid = median (head l) (middle l) (last l)
                  lesser = filter (< mid) l
                  greater = filter (> mid) l
                  middle l = head $ drop (length l `div` 2) l
              in (quicksort lesser) ++ (mid : (quicksort greater))

Ich nutze die Tatsache, dass es keine Duplikate gibt, um zwei strenge Vergleiche durchzuführen. Ich muss prüfen, ob Data.List.partitiondie Dinge nicht kürzer werden, auch wenn ich eine Import-Anweisung hinzufügen müsste. Ich nehme den Einfügesortierbonus nicht an, weil ich ihn als Data.List.insertsortierungsbezogene Funktion betrachte - daher verboten - und wenn ich ihn nicht benutze, wird der Code durch Hinzufügen der Einfügesortierung auf 246 Byte erhöht (209,1 mit dem Bonus), es lohnt sich also nicht.

Bearbeiten: Vielen Dank an RobAu für den Vorschlag, einen Alias ​​für die Verwendung zu erstellen f=filter. Es kann nur ein Byte speichern, aber alles hilft.


1
f=filterkönnte einige Bytes abschneiden.
RobAu

Vielleicht können Sie ein paar Bytes sparen, indem Sie eine Funktion erstellen, die die beiden redundanten q$f(>n)lund q$f(<n)laufgerufenen Daten verarbeitet.
Cyoce

1

Tcl, 138 Bytes

proc q v {if {$v eq {}} return
lassign {} a b
foreach x [lassign $v p] {if {$x<$p} {lappend a $x} {lappend b $x}}
concat [q $a] $p [q $b]}

Dies ist eine sehr übliche Quicksorte.

Der Pivot ist einfach das erste Element eines jeden Subarrays (ich behaupte, dass dies eine Zufallszahl ist. Https://xkcd.com/221/ )

Es ist im Hinblick auf die Speichernutzung nicht besonders effizient, obwohl es zum Teil durch tailcalldie zweite Rekursion und einen Basisfall von n <1 Elementen verbessert werden könnte .

Hier ist die lesbare Version:

proc quicksort xs {
  if {![llength $xs]} return
  set lhs [list]
  set rhs [list]
  foreach x [lassign $xs pivot] {
    if {$x < $pivot} \
      then {lappend lhs $x} \
      else {lappend rhs $x}
  }
  concat [quicksort $lhs] $pivot [quicksort $rhs]
}

Funktioniert mit allen Eingaben und erlaubt Duplikate. Oh, es ist auch stabil . Sie können es mit etwas Einfachem testen, wie:

while 1 {
  puts -nonewline {xs? }
  flush stdout
  gets stdin xs
  if {$xs eq {}} exit
  puts [q $xs]    ;# or [quicksort $xs]
  puts {}
}

Genießen! :O)


Sie können Bytes ersetzen sparen foreachdurch lmap
sergiol

1

JavaScript (ES6), 191

Q=(a,l=0,h=a.length-1)=>l<h&&(p=((a,i,j,p=a[i+(0|Math.random()*(j-i))])=>{for(--i,++j;;[a[i],a[j]]=[a[j],a[i]]){while(a[--j]>p);while(a[++i]<p);if(i>=j)return j}})(a,l,h),Q(a,l,p),Q(a,p+1,h))

// More readable
U=(a,l=0,h=a.length-1)=>l<h && 
  (p=( // start of partition function
    (a,i,j,p=a[i+(0|Math.random()*(j-i))])=>
    {
      for(--i,++j;;[a[i],a[j]]=[a[j],a[i]])
      {
        while(a[--j]>p);
        while(a[++i]<p);
        if(i>=j)return j
      }
    } // end of partition function
  )(a,l,h),U(a,l,p),U(a,p+1,h))

// This is the shortest insertion sort that I could code, it's 72 bytes
// The bonus is worth  ~30 bytes - so no bonus
I=a=>{for(i=0;++i<a.length;a[j]=x)for(x=a[j=i];j&&a[j-1]>x;)a[j]=a[--j]}


// TEST
z=Array(10000).fill().map(_=>Math.random()*10000|0)

Q(z)

O.innerHTML=z.join(' ')
<div id=O></div>


1

Ceylon (JVM nur), 183 170

Es gelten keine Boni.

import ceylon.math.float{r=random}{Float*}q({Float*}l)=>if(exists p=l.getFromFirst((r()*l.size).integer))then q(l.filter((e)=>e<p)).chain{p,*q(l.filter((e)=>p<e))}else[];

Es scheint, dass es in Ceylon keine plattformübergreifende Möglichkeit gibt, eine Zufallszahl zu erzeugen. Dies ist also nur JVM. (Am Ende habe ich eine nicht zufällige Version, die auch in JS funktioniert und kleiner ist.)

Dies definiert eine Funktion, die eine Iteration von Floats annimmt und eine sortierte Version davon zurückgibt.

import ceylon.math.float {
    r=random
}

{Float*} q({Float*} l) {
    if (exists p = l.getFromFirst((r() * l.size).integer)) {
        return q(l.filter((e) => e < p)).chain { p, *q(l.filter((e) => p < e)) };
    } else {
        return [];
    }
}

Wenn (entgegen der Spezifikation) doppelte Einträge übergeben werden, werden diese herausgefiltert.

Dies sind 183 Bytes: import ceylon.math.float{r=random}{Float*}q({Float*}l){if(exists p=l.getFromFirst((r()*l.size).integer)){return q(l.filter((e)=>e<p)).chain{p,*q(l.filter((e)=>p<e))};}else{return[];}}

Mit dem neuen ifAusdruck (Ceylon 1.2) können wir uns ein wenig verbessern :

import ceylon.math.float {
    r=random
}

{Float*} q({Float*} l) =>
        if (exists p = l.getFromFirst((r() * l.size).integer))
        then q(l.filter((e) => e < p)).chain { p, *q(l.filter((e) => p < e)) }
        else [];

Das sind 170 Bytes: import ceylon.math.float{r=random}{Float*}q({Float*}l)=>if(exists p=l.getFromFirst((r()*l.size).integer))then q(l.filter((e)=>e<p)).chain{p,*q(l.filter((e)=>p<e))}else[];


Hier ist eine nicht zufällige Version:

{Float*} r({Float*} l) =>
        if (exists p = l.first)
        then r(l.filter((e) => e < p)).chain { p, *r(l.filter((e) => p < e)) }
        else [];

Ohne Leerzeichen wären das 107 Bytes: {Float*}r({Float*}l)=>if(exists p=l.first)then r(l.filter((e)=>e<p)).chain{p,*r(l.filter((e)=>p<e))}else[];


0

AutoIt , 320.45 304.3 Bytes

Das geht recht schnell (für AutoIt sowieso). Qualifiziert sich für den Einfügungssortierbonus. Wird eine Erklärung hinzufügen, nachdem das endgültige Golfen stattgefunden hat.

Eingabe ist q(Array, StartingElement, EndingElement).

Func q(ByRef $1,$2,$3)
$5=$3
$L=$2
$6=$1[($2+$3)/2]
If $3-$2<6 Then
For $i=$2+1 To $3
$4=$1[$i]
For $j=$i-1 To $2 Step -1
$5=$1[$j]
ExitLoop $4>=$5
$1[$j+1]=$5
Next
$1[$j+1]=$4
Next
Else
Do
While $1[$L]<$6
$L+=1
WEnd
While $1[$5]>$6
$5-=1
WEnd
ContinueLoop $L>$5
$4=$1[$L]
$1[$L]=$1[$5]
$1[$5]=$4
$L+=1
$5-=1
Until $L>$5
q($1,$2,$5)
q($1,$L,$3)
EndIf
EndFunc

Zufallstest Eingabe + Ausgabe:

862, 543, 765, 577, 325, 664, 503, 524, 192, 904, 143, 483, 146, 794, 201, 511, 199, 876, 918, 416
143, 146, 192, 199, 201, 325, 416, 483, 503, 511, 524, 543, 577, 664, 765, 794, 862, 876, 904, 918

Interessant, noch nie von AutoIt gehört
Daniel M.

0

Java, 346 Bytes

407 bytes - 15% bonus for insertion sort = 345.95 bytes

Komprimierter Code:

class z{Random r=new Random();void q(int[] a){q(a,0,a.length);}void q(int[] a,int b,int e){if(e-b<6){for(int i=b;i<e;i++){for(int j=i;j>0&a[j]<a[j-1];j--){s(a,j,j-1);}}return;}int s=p(a,b,e);q(a,b,s);q(a,s,e);}int p(int[] a,int b,int e){int p=a[r.nextInt(e-b)+b--];while(b<e){do{b++;}while(a[b]<p);do{e--;}while(a[e]>p);if(b<e){s(a,b,e);}}return b;}void s(int[] a,int b,int e){int t=a[b];a[b]=a[e];a[e]=t;}}

Vollständiger Code:

public class QuickSort {

    private static final Random RANDOM = new Random();

    public static void quickSort(int[] array) {
        quickSort(array, 0, array.length);
    }

    private static void quickSort(int[] array, int begin, int end) {
        if (end - begin <= 5) {
            for (int i = begin; i < end; i++) {
                for (int j = i; j > 0 && array[j] < array[j - 1]; j--) {
                    swap(array, j, j - 1);
                }
            }
            return;
        }
        int splitIndex = partition(array, begin, end);
        quickSort(array, begin, splitIndex);
        quickSort(array, splitIndex, end);
    }

    private static int partition(int[] array, int begin, int end) {
        int pivot = array[RANDOM.nextInt(end - begin) + begin];
        begin--;
        while (begin < end) {
            do {
                begin++;
            } while (array[begin] < pivot);
            do {
                end--;
            } while (array[end] > pivot);
            if (begin < end) {
                // Make sure they haven't crossed yet
                swap(array, begin, end);
            }
        }
        return begin;
    }

    private static void swap(int[] array, int begin, int end) {
        int temp = array[begin];
        array[begin] = array[end];
        array[end] = temp;
    }

}

Einige Verbesserungen: 1. Entfernen Sie die Leerzeichen zwischen int [] und a im Methodenkopf. 2. Setzen Sie das Inkrement oder Dekrement in einer for-Schleife an die letzte Stelle, an der auf eine Variable zugegriffen wird. 3. Erstellen Sie eine Klasse int (oder ein Paar), um Bytes zu speichern, indem Sie sie anstelle einer neuen int verwenden. 4. Die Verwendung von Math.random () und das Casting sind möglicherweise kürzer als das Erstellen eines Zufallsobjekts.
Blue

0

Mathematica, 93-90 Bytes

If[Length@#>1,pv=RandomChoice@#;Join[qs2[#~Select~(#<pv&)],{pv},qs2[#~Select~(#>pv&)]],#]&

Kein Bonus, es gibt noch keine minimale Möglichkeit, Einfügungen zu sortieren. Als ich kürzlich C ++ lernte, habe ich hier verschiedene Sortieralgorithmen verglichen .


0

Python2, 120 Bytes

def p(a):
 if[]==a[1:]:return a
 b,c,m=[],[],__import__("random").choice(a)
 for x in a:[b,c][x>m]+=[x];return p(b)+p(c)

if[]==a[1:]ist genauso lang if len(a)>2, sieht aber besser aus.


0

Lua, 242 Bytes

function f(t,p)if(#t>0)then local P,l,r,i=math.random(#t),{},{},table.insert p=t[P]for k,v in ipairs(t)do if(k~=P)then i(v<p and l or r,v)end end t={}for k,v in pairs(f(l))do i(t,v)end i(t,p)for k,v in pairs(f(r))do i(t,v)end end return t end

Ungolfed & Explination

function f(t,p)                                             # Assign 'p' here, which saves two bytes, because we can't assign it to t[P] IN the local group.
    if(#t>0)then                                            # Just return 0 length lists...
        local P,l,r,i=math.random(#t),{},{},table.insert    # Using local here actually makes the a,b=1,2 method more efficient here. Which is unnormal for Lua
        p = t[P]                                            # P is the index of the pivot, p is the value of the pivot, l and r are the sub-lists around the pivot, and i is table.insert to save bytes.
        for k,v in ipairs(t) do                             # We use a completely random pivot, because it's cheaper on the bytes.
            if(k~=P)then                                    # Avoid 'sorting' the pivot.
                i(v<p and l or r,v)                         # If the value is less than the pivot value, push it to the left list, otherwise, push it to the right list.
            end                                             #
        end                                                 #
        t = {}                                              # We can re-use t here, because we don't need it anymore, and it's already a local value. Saving bytes!
        for k,v in pairs(f(l)) do                           # Quick sort the left list, then append it to the new output list.
            i(t,v)                                          #
        end                                                 #
        i(t,p)                                              # Append the pivot value.
        for k,v in pairs(f(r)) do                           # Ditto the right list.
            i(t,v)                                          #
        end                                                 #
    end                                                     #
    return t                                                # Return...
end                                                         #

0

Schläger 121 Bytes

(λ(l)(if(null? l)l(let((h(car l))(t(cdr l)))(append(qs (filter(λ(x)(< x h))t))(list h)(qs (filter(λ(x)(>= x h))t))))))

Ungolfed (l = Liste, h = Kopf (erstes Element), t = Schwanz (Rest oder verbleibende Elemente)):

(define qs
  (λ(l)
    (if (null? l) l
        (let ((h (first l))
              (t (rest  l)))
          (append (qs (filter (λ(x) (< x h) ) t))
                  (list h) 
                  (qs (filter (λ(x) (>= x h)) t))  )))))

Testen:

(qs (list 5 8 6 8 9 1 2 4 9 3 5 7 2 5))

Ausgabe:

'(1 2 2 3 4 5 5 5 6 7 8 8 9 9)

0

Japt , 23 Bytes

Jeder Bonus müsste drei Bytes oder weniger umfassen, um sich in der Gesamtpunktzahl auszahlen zu können, also habe ich keine Boni genommen.

Z=Uö;Ê<2?UUf<Z)cßUf¨Z
Z=Uö;                   // Take a random element from the input for partitioning.
     Ê<2                // If the input is shorter than two elements,
        ?U              // return it.
          :             // Otherwise
           ß      ß     // recursively run again
            Uf<Z        // with both items that are smaller than the partition
                   Uf¨Z // and those that are larger or equal,
                )c      // returning the combined result.

Probieren Sie es online!


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.