Triez ça, vite!

27

Eh bien ... il y a 59 (maintenant 60) questions marquées par , mais pas de rapide simple.

Cela doit être corrigé.

Pour ceux qui ne connaissent pas QuickSort , voici une ventilation, gracieuseté de Wikipedia-

  1. Choisissez un élément, appelé pivot , dans le tableau.
  2. Réorganisez le tableau de sorte que tous les éléments avec des valeurs inférieures au pivot viennent avant le pivot, tandis que tous les éléments avec des valeurs supérieures au pivot viennent après celui-ci (des valeurs égales peuvent aller dans les deux sens). Après ce cloisonnement, le pivot est dans sa position finale. C'est ce qu'on appelle l'opération de partition.
  3. Appliquer récursivement les étapes ci-dessus au sous-tableau d'éléments avec des valeurs plus petites et séparément au sous-tableau d'éléments avec des valeurs plus élevées.

Règles

Les règles sont simples:

  • Implémentez un tri rapide numérique dans le langage de programmation de votre choix.
  • Le pivot doit être choisi au hasard ou avec une médiane de trois (1er, dernier et élément central).
  • Votre programme peut être un programme ou une fonction complète.
  • Vous pouvez obtenir l'entrée à l'aide de STDIN, des arguments de ligne de commande ou des paramètres de fonction. Si vous utilisez une entrée de chaîne, l'entrée est séparée par des espaces.
  • L'entrée peut contenir des valeurs décimales et négatives. Cependant, il n'y aura pas de doublons.
  • Vous pouvez sortir vers STDOUT ou en revenant de la fonction.
  • Pas de fonctions de tri intégrées (ou liées au tri) ni de failles standard.
  • La liste peut être d'une longueur arbitraire.

Bonus n ° 1: sur les listes ou sous-listes de longueur <= 5, utilisez le tri par insertion pour accélérer un peu les choses. Récompense: -15%.

Bonus n ° 2: si votre langue prend en charge la simultanéité, triez la liste en parallèle. Si vous utilisez un tri par insertion sur des sous-listes, le tri par insertion final n'a pas besoin d'être en parallèle. Les pools de threads / planification de threads sont autorisés. Récompense: -15%.

Remarque: la médiane de trois déroutait certaines personnes, alors voici une explication, gracieuseté de (encore) Wikipedia:

choix de la médiane du premier, du milieu et du dernier élément de la partition pour le pivot

Notation

C'est du . Le score de base est en octets. Si vous avez obtenu un bonus, prenez 15% de réduction sur ce nombre. Si vous avez les deux, profitez d'une réduction de 30%. Cela ressemble vraiment à un argumentaire de vente.

Il ne s'agit pas de trouver la réponse la plus courte dans l'ensemble, mais plutôt la plus courte dans chaque langue.

Et maintenant, une copie sans vergogne de l'extrait de classement.

Le classement

L'extrait de pile au bas de cet article génère le catalogue à partir des réponses a) en tant que liste des solutions les plus courtes par langue et b) en tant que classement général.

Pour vous assurer que votre réponse apparaît, veuillez commencer votre réponse avec un titre, en utilisant le modèle Markdown suivant:

## Language Name, N bytes

où N est la taille de votre soumission. Si vous améliorez votre score, vous pouvez conserver les anciens scores dans le titre, en les barrant. Par exemple:

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

Si vous souhaitez inclure plusieurs nombres dans votre en-tête (par exemple, parce que votre score est la somme de deux fichiers ou que vous souhaitez répertorier les pénalités de drapeau d'interprète séparément), assurez-vous que le score réel est le dernier numéro de l'en-tête:

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

Vous pouvez également faire du nom de la langue un lien qui apparaîtra ensuite dans l'extrait de code:

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

Daniel M.
la source
4
"Le pivot doit être choisi au hasard ou avec une médiane de trois (1er, dernier et élément central)." Qu'est-ce que ça veut dire? Vous avez dit précédemment qu'un seul élément est choisi.
msh210
2
@daniero Snippet est résolu maintenant
Daniel M.
1
L'algorithme de choix médian est-il une exigence difficile? Il n'est pas pratique (comme dans, il réserve les performances) dans les langues qui utilisent une liste liée comme type de tableau principal (Haskell, LISP) et il existe déjà au moins une réponse qui ignore la règle.
John Dvorak
2
Le pivot aléatoire et la médiane de trois sont problématiques dans les langues basées sur des listes. Les deux nécessitent un accès aléatoire au tableau et accéder à la fin d'une liste chaînée est O (n). Prendre La médiane des trois premiers éléments ne fait pas tout à fait le même genre de travail (également parce que vous récupérerez le même pivot dans trois divisions de toute façon) et complique le code sans raison valable.
John Dvorak
1
Le pivot aléatoire est problématique dans Haskell pour une autre raison également - une fois que vous commencez à lancer les dés, vous n'écrivez plus de fonction. Vous définissez une action d'E / S qui produit un tableau. Vous pouvez définir une fonction qui prend un état RNG comme argument, mais ce n'est pas trop génial non plus.
John Dvorak

Réponses:

10

C ++, 440,3 405 388 octets

518 octets - 15% de bonus pour le tri par insertion = 440,3 octets

477 octets - 15% de bonus pour le tri par insertion = 405,45 octets

474 octets - 15% de bonus pour le tri par insertion = 402,9 octets

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

Merci à @Luke pour avoir économisé 3 octets (2 vraiment).

Merci à @ Dúthomhas pour avoir économisé 18 (15 vraiment) octets.

Notez que je suis nouveau ici et c'est mon premier post.

Il s'agit d'un .hfichier (en-tête).

Code compressé:

#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);}

Code complet:

#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);
}
TheCoffeeCup
la source
5
Vous pouvez enregistrer 10 octets en utilisant un nom de lettre unique au lieu de quickSort et en supprimant les espaces lors du dernier appel de fonction. Et je parie que vous pouvez obtenir un meilleur score en évitant le bonus (15% ne suffit pas)
edc65
1
Vous pouvez enregistrer 5 octets supplémentaires en remplaçant les crochets des arguments par des astérisques simples. Un peu de magie macro pourrait raser quelques octets de plus, je suppose.
cadaniluk
2
Vous n'avez pas besoin d'espace après #include.
Luke
Débarrassez-vous de 34 octets en supprimant l'appel à srand(time(NULL));Vous obtiendrez toujours des nombres pseudo-aléatoires rand().
Dúthomhas
9

APL, 49 42 octets

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

Cela crée une fonction monadique récursive sans nom qui accepte un tableau à droite. Il ne donne pas droit au bonus.

Explication:

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

Essayez-le en ligne

Correction d'un problème (au coût de 8 octets) grâce à marinus et économisé 7 octets grâce à Thomas Kwa!

Alex A.
la source
La question précise qu'il n'y aura pas de doublons. (Je ne sais pas comment il m'a fallu si longtemps pour voir ça ...)
lirtosiast
5

C ++ 17, 254 199 195 octets

#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;}

Avec espace:

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;
}
Lynn
la source
Pas besoin de srand (time (NULL)). Pas besoin d'effacer, laissez simplement la valeur être partitionnée, puis changez 'if (a.empty ())' en 'if (a.size () <2)' et supprimez 'lP (x)'.
Chris Jefferson
L'élimination de l'effacement m'a permis d'économiser beaucoup d'octets. Merci!
Lynn
Un autre minuscule: pas besoin d'attribuer «r = q (r)», utilisez simplement «pour (y: q (r))», mais c'est tout ce que je peux voir!
Chris Jefferson
Par curiosité: où le C ++ 17 en particulier est-il utilisé ici?
kirbyfan64sos
1
for (y : a)devrait autrement être for (auto y : a)ou for (int y : a). (En fait, clang++appelle cela une extension C ++ 1z , mais cela ne semble pas vraiment être C ++ 17? Je ne sais pas et il est trop tard dans la nuit pour aller le chercher.)
Lynn
4

Pyth, 25 octets

L?tbsyMa_,]JObf<TJbf>TJbb

Ceci définit une fonction y, qui prend une liste de nombres en entrée.

Essayez-le en ligne: Démonstration

Explication

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 octets (probablement invalide)

J'utilise la méthode "group-by", qui utilise en interne un tri. Je l'utilise pour diviser la liste d'origine en trois sous-listes (tous les éléments plus petits que le pivot, le pivot et tous les éléments plus grands que le pivot). Sans le tri en "group-by", il pourrait renvoyer ces 3 listes dans un ordre différent.

Comme je l'ai dit, cela n'est probablement pas valide. Je vais néanmoins le garder ici, car c'est une solution intéressante.

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

Essayez-le en ligne: Démonstration

Explication

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
Jakube
la source
3

> <> (Poisson), 313 309 octets

!;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.

Cela m'a pris très longtemps à écrire. Vous pouvez l'essayer ici , mettez simplement la liste qui doit être triée dans la pile initiale, séparée par des virgules, avant d'exécuter le programme.

Comment ça marche

Le programme saisit le premier, le milieu et le dernier élément de la pile initiale et calcule la médiane de ces trois éléments.
Il change ensuite la pile en:

élément [list 1] [list 2]

où tout dans la liste 1 est plus petit ou égal à l'élément et tout dans la liste 2 est plus grand.
Il répète récursivement ce processus sur la liste 1 et la liste 2 jusqu'à ce que la liste entière soit triée.

Thijs ter Haar
la source
2

CJam, 40 octets

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

Il s'agit d'une fonction nommée qui attend un tableau sur la pile et en envoie un en retour.

Essayez-le en ligne dans l' interpréteur CJam .

Le code ci-dessus suit la spécification aussi étroitement que possible. Si ce n'est pas nécessaire, 12 octets peuvent être enregistrés:

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

Python 3, 123 , 122.

1 octet enregistré grâce à Aaron.

C'est la première fois que je me donne la peine d'écrire un algorithme de tri. C'est en fait un peu plus facile que je ne le pensais.

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])

Non golfé:

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)
Morgan Thrapp
la source
Il semble que cela ne fonctionne pas, en raison de la <=comparaison - cela ne garantit pas que pc'est au bon endroit, vous devez probablement changer cela en une inégalité exclusive, et ajouter pau milieu indépendamment (je n'ai pas testé / peut teste pas le code).
VisualMelon
@VisualMelon Je l'ai testé avec un tas de cas différents et je n'ai jamais obtenu un résultat incorrect, mais si vous pouvez trouver un cas de test qui le casse, faites le moi savoir. En outre, cela peut ne pas fonctionner avec des doublons, mais le défi spécifie qu'il n'y aura pas de doublons.
Morgan Thrapp,
J'aurais pensé que [2, 1, 3]cela le casserait 1/3 du temps, car lorsqu'il sélectionne le pivot à 2, il aura la liste basse [2, 1]- je suis désolé, je ne peux pas le tester moi-même pour le moment.
VisualMelon
@VisualMelon Eh bien, bien sûr, mais il trie ensuite de manière récursive.
Morgan Thrapp,
Ah, désolé, j'ai complètement manqué cela, pas tout à fait comme je m'attendrais à ce qu'un Quicksort soit implémenté - ayez un vote positif pour me
dérouter
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)));}

Explication

//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)));
}
Ventes de Flávio Teixeira
la source
ES6 pourrait probablement raccourcir cela.
Nissa
1

Rubis, 87 60 octets

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

Non golfé:

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

Tester:

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]
daniero
la source
1

Octave, 76 75 octets

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

Version multiligne:

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

Julia, 83 octets

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))])

Cela crée une fonction récursive Qqui accepte un tableau et renvoie un tableau. Il n'utilise pas conditionnellement le tri par insertion, donc aucun bonus ne s'applique.

Non golfé:

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

Correction d'un problème et enregistrement de quelques octets grâce à Glen O!

Alex A.
la source
Mis à part les éventuels problèmes de perte d'éléments de répétition (qui existent déjà dans votre code), vous pouvez enregistrer quelques octets ici en les affectant flors de votre première utilisation filteret en utilisant à la endofplace de 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 Merci pour la suggestion. J'ai implémenté cela et corrigé le problème avec des éléments répétés.
Alex A.
J'ai dit que cela pourrait être un problème, mais j'ai demandé des éclaircissements à l'affiche de la question et "L'entrée peut contenir des valeurs décimales et négatives. Cependant, il n'y aura pas de doublons"
Glen O
1

R, 78 octets

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

Cela crée une fonction récursive Q qui accepte un vecteur et renvoie un vecteur. Il n'applique pas conditionnellement le tri par insertion, donc pas de bonus.

Non golfé:

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
    }
}

Essayez-le en ligne

4 octets enregistrés grâce à Flodel!

Alex A.
la source
Vous pouvez grignoter quelques octets en supprimant le "> 1" de la comparaison de longueur. Cela le compare implicitement à 0, mais une couche supplémentaire de récursivité n'est pas un problème,
Miff
@Miff Merci pour votre contribution, mais j'ai essayé et cela ne produit pas le résultat attendu pour moi.
Alex A.
1

K, 41 octets

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

PRENEZ CELA, APL !!! Ne fait aucun des bonus.

kirbyfan64sos
la source
1

Haskell, 137136 octets

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))

La version non golfée est ci-dessous, avec des noms de variable et de fonction étendus et quelques résultats intermédiaires ajoutés:

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))

Je profite du fait qu'il n'y a pas de doublons pour utiliser deux comparaisons strictes. Je devrai vérifier si Data.List.partitioncela ne raccourcit pas les choses, même si je dois ajouter une déclaration d'importation. Je ne prends pas le bonus de tri par insertion parce que je considère Data.List.insertcomme une fonction liée au tri - donc interdite - et si vous ne l'utilisez pas, l'ajout du tri par insertion pousse le code à 246 octets, 209,1 avec le bonus, donc cela ne vaut pas la peine.

Edit: Merci à RobAu pour leur suggestion de créer un alias à utiliser f=filter. Il ne peut enregistrer qu'un seul octet mais tout est utile.

arjanen
la source
1
f=filterpourrait raser certains octets.
RobAu
Peut - être que vous pouvez raser quelques octets en faisant une fonction pour gérer les deux redondants q$f(>n)let des q$f(<n)lappels?
Cyoce
1

Tcl, 138 octets

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]}

Il s'agit d'un tri rapide extrêmement standard.

Le pivot est simplement le premier élément de chaque sous-tableau (je soutiens qu'il s'agit d'un nombre aléatoire. Https://xkcd.com/221/ )

Il n'est pas particulièrement efficace en termes d'utilisation de la mémoire, bien qu'il puisse être amélioré avec tailcallla deuxième récursivité et un cas de base de n <1 éléments.

Voici la version lisible:

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]
}

Fonctionne sur toutes les entrées et permet les doublons. Oh, c'est aussi stable . Vous pouvez le tester avec quelque chose de simple, comme:

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

Prendre plaisir! : O)

Dúthomhas
la source
Vous pouvez enregistrer des octets en les remplaçant foreachpar 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>

edc65
la source
1

Ceylan (JVM seulement), 183 170

Aucun bonus ne s'applique.

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[];

Il semble qu'il n'y ait aucun moyen multiplateforme de produire un nombre aléatoire à Ceylan, c'est donc uniquement JVM. (À la fin, j'ai une version non aléatoire qui fonctionne également en JS et est plus petite.)

Ceci définit une fonction qui prend un itérable de flottants et en retourne une version triée.

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 [];
    }
}

Si (contre la spécification) des entrées en double sont passées, celles-ci seront filtrées.

Cela fait 183 octets: 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[];}}

Nous pouvons nous améliorer un peu en utilisant la nouvelle ifexpression (Ceylon 1.2) :

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 [];

C'est 170 octets: 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[];


Voici une version non aléatoire:

{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 [];

Sans espaces, ce serait 107 octets: {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[];

Paŭlo Ebermann
la source
0

AutoIt , 320.45 304,3 octets

C'est très rapide (pour AutoIt de toute façon). Admissible au bonus de tri par insertion. Ajoutera une explication après le golf final.

L'entrée est 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

Entrée + sortie de test aléatoire:

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
mınxomaτ
la source
Intéressant, jamais entendu parler d'AutoIt auparavant
Daniel M.
0

Java, 346 octets

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

Code compressé:

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;}}

Code complet:

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;
    }

}
TheCoffeeCup
la source
Améliorations du couple: 1. supprimez les espaces entre int [] et a dans l'en-tête de la méthode. 2. Faites de l'incrémentation ou de la décrémentation dans une boucle for le dernier endroit auquel une variable est accédée. 3. Créez une classe int (ou un couple) pour enregistrer les octets en l'utilisant au lieu d'un nouvel int. 4. L'utilisation de Math.random () et la conversion peuvent être plus courtes que la création d'un objet Random.
Blue
0

Mathematica, 93 90 octets

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

Aucun bonus, vous n'avez pas encore de méthode minimale pour trier l'insertion. Quand j'apprenais C ++ récemment, je l'ai fait une comparaison des différents algorithmes de tri ici .

Jason B.
la source
0

Python2, 120 octets

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:]est exactement aussi long if len(a)>2mais semble plus golfé.

Filip Haglund
la source
0

Lua, 242 octets

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

Non golfé & Explication

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                                                         #
ATaco
la source
0

Raquette 121 octets

(λ(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))))))

Non golfé (l = liste, h = tête (premier élément), t = queue (reste ou éléments restants)):

(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))  )))))

Essai:

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

Sortie:

'(1 2 2 3 4 5 5 5 6 7 8 8 9 9)
rnso
la source
0

Japt , 23 octets

Chaque bonus devrait être de trois octets ou moins pour être rentable dans le score total, donc je n'ai pris aucun bonus.

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.

Essayez-le en ligne!

Lente
la source
20 octets
Shaggy