Ordina questo, veloce!


27

Beh ... ci sono 59 (ora 60) domande tagged , ma non semplici quicksorts.

Questo deve essere risolto.

Per chi non ha familiarità con Quicksort , ecco un dettaglio, per gentile concessione di Wikipedia-

  1. Scegli un elemento, chiamato pivot , dall'array.
  2. Riordinare l'array in modo che tutti gli elementi con valori inferiori al pivot vengano prima del pivot, mentre tutti gli elementi con valori maggiori del pivot lo seguano (valori uguali possono andare in entrambi i modi). Dopo questo partizionamento, il perno è nella sua posizione finale. Questa è chiamata operazione di partizione.
  3. Applicare in modo ricorsivo i passaggi precedenti all'array secondario di elementi con valori più piccoli e separatamente all'array secondario di elementi con valori maggiori.

Regole

Le regole sono semplici:

  • Implementa un quicksort numerico nel linguaggio di programmazione che preferisci.
  • Il perno deve essere scelto a caso o con una mediana di tre (1 °, ultimo e elemento intermedio).
  • Il tuo programma può essere un programma o una funzione completi.
  • È possibile ottenere l'input utilizzando STDIN, arg della riga di comando o parametri di funzione. Se si utilizza un input stringa, l'input è separato dallo spazio.
  • L'input può contenere valori decimali e negativi. Tuttavia, non ci saranno duplicati.
  • È possibile eseguire l'output su STDOUT o ritornando dalla funzione.
  • Nessuna funzione di ordinamento integrata (o relativa all'ordinamento) o scappatoie standard.
  • L'elenco può avere una lunghezza arbitraria.

Bonus n. 1: su liste o sotto-liste di lunghezza <= 5, usa l'ordinamento per inserzione per velocizzare un po 'le cose. Ricompensa: -15%.

Bonus n. 2: se la tua lingua supporta la concorrenza, ordina l'elenco in parallelo. Se si utilizza un ordinamento di inserzione in elenchi secondari, non è necessario che l'ordinamento di inserzione finale sia parallelo. Sono consentiti pool di thread / pianificazione thread incorporati. Ricompensa: -15%.

Nota: la mediana di tre stava confondendo alcune persone, quindi ecco una spiegazione, per gentile concessione di (di nuovo) Wikipedia:

scegliendo la mediana del primo, medio e ultimo elemento della partizione per il perno

punteggio

Questo è . Il punteggio di base è in byte. Se hai un bonus, prendi il 15% di sconto su quel numero. Se hai entrambi, prendi il 30% di sconto. Sembra davvero un passo di vendita.

Non si tratta di trovare la risposta più breve in generale, ma piuttosto la più breve in ogni lingua.

E ora, una copia spudorata dello snippet della classifica.

La classifica

Lo snippet di stack nella parte inferiore di questo post genera il catalogo dalle risposte a) come elenco della soluzione più breve per lingua eb) come classifica generale.

Per assicurarti che la tua risposta venga visualizzata, ti preghiamo di iniziare la risposta con un titolo, utilizzando il seguente modello Markdown:

## Language Name, N bytes

dove N è la dimensione del tuo invio. Se si migliora il punteggio, è possibile mantenere i vecchi punteggi nel titolo, colpendoli. Per esempio:

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

Se si desidera includere più numeri nell'intestazione (ad es. Perché il punteggio è la somma di due file o si desidera elencare separatamente le penalità del flag dell'interprete), assicurarsi che il punteggio effettivo sia l'ultimo numero nell'intestazione:

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

Puoi anche rendere il nome della lingua un collegamento che verrà quindi visualizzato nello snippet:

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


4
"Il perno deve essere scelto a caso o con una mediana di tre (1 °, ultimo e elemento intermedio)." Cosa significa questo? In precedenza hai detto che è stato scelto un solo elemento.
msh210

2
Lo snippet di @daniero è stato risolto ora
Daniel M.

1
L'algoritmo di scelta mediana è un requisito difficile? È poco pratico (come in, colma le prestazioni) in linguaggi che usano un elenco collegato come tipo di array primario (Haskell, LISP) e c'è già almeno una risposta che ignora la regola.
John Dvorak,

2
Sia il perno casuale che la mediana di tre sono problematici nelle lingue basate su elenchi. Entrambi richiedono l'accesso casuale all'array e l'accesso alla fine di un elenco collegato è O (n). Prendere Prendere la mediana dei primi tre elementi non fa esattamente lo stesso tipo di lavoro (anche perché prenderai lo stesso perno in tre parti comunque) e complica il codice senza una buona ragione.
John Dvorak,

1
Il pivot casuale è problematico in Haskell anche per un altro motivo: una volta che inizi a lanciare i dadi, non stai più scrivendo una funzione. Stai definendo un'azione I / O che produce un array. È possibile definire una funzione che accetta uno stato RNG come argomento, ma non è neanche troppo grande.
John Dvorak,

Risposte:


10

C ++, 440,3 405 388 byte

518 byte - bonus del 15% per ordinamento di inserzione = 440,3 byte

477 byte - bonus del 15% per l'ordinamento per inserzione = 405,45 byte

474 byte - bonus del 15% per l'ordinamento per inserzione = 402,9 byte

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

Grazie a @Luke per aver salvato 3 byte (2 davvero).

Grazie a @ Dúthomhas per aver salvato 18 (15 davvero) byte.

Nota che sono nuovo qui e questo è il mio primo post.

Questo è un .hfile (di intestazione).

Codice compresso:

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

Codice completo:

#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
È possibile salvare 10 byte utilizzando un solo nome di lettera anziché quickSort e rimuovendo gli spazi nell'ultima chiamata di funzione. E scommetto che puoi ottenere un punteggio migliore evitando il bonus (il 15% non è abbastanza)
edc65

1
È possibile salvare altri 5 byte sostituendo le parentesi quadre degli argomenti con singoli asterischi. Qualche macro magia potrebbe radere via altri byte, immagino.
Cadaniluk,

2
Non hai bisogno di uno spazio dopo #include.
Luca,

Sbarazzati di 34 byte rimuovendo la chiamata a srand(time(NULL));Otterrai comunque numeri pseudo casuali rand().
Dúthomhas,

9

APL, 49 42 byte

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

Questo crea una funzione monadica ricorsiva senza nome che accetta un array sulla destra. Non si qualifica per il bonus.

Spiegazione:

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

Provalo online

Risolto un problema (al costo di 8 byte) grazie a Marinus e risparmiato 7 byte grazie a Thomas Kwa!


La domanda specifica che non ci saranno duplicati. (Non so come mi ci è voluto così tanto tempo per vederlo ...)
Lirtosiast

5

C ++ 17, 254 199 195 byte

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

Con spazi bianchi:

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

Non c'è bisogno di srand (time (NULL)). Non c'è bisogno di cancellare, lascia che il valore venga partizionato, quindi modifica 'if (a.empty ())' in 'if (a.size () <2)' e rimuovi 'lP (x)'.
Chris Jefferson,

L'eliminazione della cancellazione mi ha permesso di salvare molti byte. Grazie!
Lynn,

Un altro piccolo: non c'è bisogno di assegnare 'r = q (r)', basta usare 'per (y: q (r))', ma è tutto ciò che posso vedere!
Chris Jefferson,

Solo per curiosità: dov'è usato in particolare C ++ 17 qui?
kirbyfan64sos,

1
for (y : a)altrimenti dovrebbe essere for (auto y : a)o for (int y : a). (In realtà, clang++questa è un'estensione C ++ 1z , ma in realtà non sembra essere C ++ 17? Non lo so ed è troppo tardi per andare a cercarla.)
Lynn

4

Pyth, 25 byte

L?tbsyMa_,]JObf<TJbf>TJbb

Questo definisce una funzione y, che accetta un elenco di numeri come input.

Provalo online: dimostrazione

Spiegazione

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 byte (probabilmente non valido)

Uso il metodo "raggruppa per", che utilizza internamente un ordinamento. Lo uso per dividere l'elenco originale in tre elenchi secondari (tutti gli elementi più piccoli del pivot, il pivot e tutti gli elementi più grandi del pivot). Senza l'ordinamento in "raggruppa per", potrebbe restituire queste 3 liste in un ordine diverso.

Come detto, questo probabilmente non è valido. Tuttavia lo terrò qui, perché è una soluzione interessante.

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

Provalo online: dimostrazione

Spiegazione

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

> <> (Pesce), 313 309 byte

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

Mi ci è voluto molto tempo per scrivere. Puoi provarlo qui , basta inserire l'elenco che deve essere ordinato nello stack iniziale, separato da virgole, prima di eseguire il programma.

Come funziona

Il programma prende il primo, il medio e l'ultimo elemento nello stack iniziale e calcola la mediana di questi tre.
Quindi cambia lo stack in:

[list 1] element [list 2]

dove tutto nella lista 1 è più piccolo o uguale all'elemento e tutto nella lista 2 è più grande.
Ripete in modo ricorsivo questo processo sull'elenco 1 e sull'elenco 2 fino a quando l'intero elenco non viene ordinato.


2

CJam, 40 byte

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

Questa è una funzione denominata che prevede un array nello stack e ne invia uno in cambio.

Provalo online nell'interprete CJam .

Il codice sopra riportato segue le specifiche il più vicino possibile. Se ciò non è necessario, è possibile salvare 12 byte:

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

2

Python 3, 123 , 122.

Salvato 1 byte grazie ad Aaron.

Questa è la prima volta che mi preoccupo davvero di scrivere un algoritmo di ordinamento. In realtà è un po 'più facile di quanto pensassi.

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)

Sembra che potrebbe non funzionare, a causa del <=confronto: non garantisce che psia nel posto giusto, probabilmente dovrai cambiarlo in una disuguaglianza esclusiva e aggiungerlo pnel mezzo in modo indipendente (non ho testato / posso non testare il codice).
VisualMelon,

@VisualMelon L'ho provato con un sacco di casi diversi e non ho mai ottenuto un risultato errato, ma se riesci a trovare un caso di test che lo rompe, fammelo sapere. Inoltre, potrebbe non funzionare con i duplicati, ma la sfida specifica che non ci saranno duplicati.
Morgan Thrapp,

Avrei pensato che l' [2, 1, 3]avrebbe spezzato per 1/3 del tempo, poiché quando seleziona il perno su 2, avrà la lista bassa [2, 1]: mi dispiace di non poterlo provare da solo.
VisualMelon,

@VisualMelon Bene, certo, ma poi ricorsivamente ordina.
Morgan Thrapp,

Ah, scusa, mi è sfuggito del tutto, non proprio come mi aspetto che venga implementato un Quicksort - abbi un voto per confondermi
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)));}

Spiegazione

//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 potrebbe probabilmente accorciarlo.
Nissa,

1

Rubino, 87 60 byte

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

Test:

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

Ottava, 76 75 byte

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

Versione multilinea:

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 byte

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

Ciò crea una funzione ricorsiva Qche accetta un array e restituisce un array. Non utilizza in modo condizionale l'ordinamento per inserzione, quindi non si applica alcun bonus.

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

Risolto un problema e salvato alcuni byte grazie a Glen O!


Possibili problemi con la perdita di elementi ripetitivi (che già esistono nel tuo codice) a parte, puoi salvare alcuni byte qui assegnando fal primo utilizzo filtere utilizzando endofinvece di 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 Grazie per il suggerimento. L'ho implementato e risolto il problema con elementi ripetuti.
Alex A.

Ho detto che potrebbe essere un problema, ma ho chiesto chiarimenti al poster della domanda e "L'input può contenere valori decimali e negativi. Tuttavia, non ci saranno duplicati"
Glen O,

1

R, 78 byte

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

Questo crea una funzione ricorsiva Qche accetta un vettore e restituisce un vettore. Non applica in modo condizionale l'ordinamento per inserzione, quindi nessun 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
    }
}

Provalo online

Salvato 4 byte grazie a flodel!


È possibile sgranocchiare un paio di byte eliminando "> 1" dal confronto della lunghezza. Ciò lo confronta implicitamente con 0, ma un ulteriore livello di ricorsione non è un problema,
Miff

@Miff Grazie per il tuo contributo, ma ci ho provato e non produce il risultato atteso per me.
Alex A.

1

K, 41 byte

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

PRENDI, APL !!! Non fa alcun bonus.


1

Haskell, 137136 byte

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

Di seguito è riportata la versione non modificata, con nomi di funzioni e variabili espansi e alcuni risultati intermedi aggiunti:

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

Sto sfruttando il fatto che non ci sono duplicati per usare due severi confronti. Dovrò verificare se Data.List.partitionnon rende le cose più brevi, anche considerando che dovrei aggiungere una dichiarazione di importazione. Non prendo il bonus di ordinamento di inserzione perché lo consideroData.List.insert una funzione correlata all'ordinamento - quindi vietato - e se non lo si utilizza, l'aggiunta di ordinamento di inserzione porta il codice a 246 byte, 209.1 con il bonus, quindi non ne vale la pena.

Modifica: grazie a RobAu per il suggerimento di creare un alias da utilizzare f=filter. Può salvare solo un byte ma tutto aiuta.


1
f=filterpotrebbe radere alcuni byte.
RobAu,

Forse puoi radere qualche byte creando una funzione per gestire i due ridondanti q$f(>n)le le q$f(<n)lchiamate?
Cyoce,

1

Tcl, 138 byte

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

Questo è un quicksort estremamente standard.

Il pivot è semplicemente il primo elemento di ogni subarray (sostengo che si tratta di un numero casuale. Https://xkcd.com/221/ )

Non è particolarmente efficiente in termini di utilizzo della memoria, anche se potrebbe essere migliorato con tailcallla seconda ricorsione e un caso base di n <1 elementi.

Ecco la versione leggibile:

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

Funziona su tutti gli input e consente duplicati. Oh, è anche stabile . Puoi provarlo con qualcosa di semplice, come:

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

Godere! : O)


È possibile salvare i byte sostituendoli foreachcon 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 (solo JVM), 183 170

Non si applicano bonus.

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

Sembra che non ci sia un modo multipiattaforma per produrre un numero casuale in Ceylon, quindi questo è solo JVM. (Alla fine ho una versione non casuale che funziona anche in JS, ed è più piccola.)

Questo definisce una funzione che accetta un iterabile di float e ne restituisce una versione ordinata.

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

Se (contro la specifica) vengono passate voci duplicate, queste verranno filtrate.

Sono 183 byte: 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[];}}

Possiamo migliorare un po 'usando la nuova ifespressione (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 [];

Sono 170 byte: 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[];


Ecco una versione non casuale:

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

Senza spazi questo sarebbe 107 byte: {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 byte

Questo è molto veloce (comunque per AutoIt). Si qualifica per il bonus ordinamento inserzione. Aggiungerà una spiegazione dopo che si è verificato il golf finale.

L'input è 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

Ingresso + uscita test casuale:

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

Interessante, mai sentito parlare di AutoIt prima
Daniel M.

0

Java, 346 byte

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

Codice compresso:

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

Codice completo:

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

}

Miglioramenti di coppia: 1. sbarazzarsi degli spazi tra int [] e a nell'intestazione del metodo. 2. Effettuare l'incremento o il decremento in un ciclo for nell'ultima posizione in cui si accede a una variabile. 3. Crea una classe int (o una coppia) per salvare byte usandola invece di una nuova int. 4. L'uso di Math.random () e il casting potrebbero essere più brevi rispetto alla creazione di un oggetto Random.
Blue

0

Mathematica, 93 90 byte

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

Nessun bonus, non ho ancora un modo minimo per eseguire l'ordinamento per inserzione. Quando stavo imparando C ++ di recente, ho fatto un confronto tra i vari algoritmi di ordinamento qui .


0

Python2, 120 byte

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:]è esattamente lungo if len(a)>2ma sembra più golfato.


0

Lua, 242 byte

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

Racchetta 121 byte

(λ(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 = list, h = head (primo elemento), t = tail (resto o elementi rimanenti)):

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

test:

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

Produzione:

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

0

Japt , 23 byte

Ogni bonus dovrebbe essere di tre byte o meno per pagare nel punteggio totale, quindi non ho preso alcun 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.

Provalo online!


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.