Sırala, çabuk!


27

Şey ... etiketli 59 (şu an 60) soru var , fakat basit bir çabukluk yok.

Bu sabit olmalı.

Quicksort'a aşina olmayanlar için , işte bir döküm, Wikipedia’nın izniyle

  1. Diziden, özet olarak adlandırılan bir öğe seçin .
  2. Diziyi, pivottan daha az değere sahip tüm elementlerin pivottan önce geleceği şekilde yeniden düzenleyin; Bu bölümlemeden sonra, pivot son konumunda. Buna bölüm işlemi denir.
  3. Yukarıdaki adımları, daha küçük değerlere sahip elementlerin alt dizisine ve ayrı olarak daha büyük değerlere sahip elementlerin alt dizisine tekrar tekrar uygulayın.

kurallar

Kurallar basit:

  • Seçtiğiniz programlama dilinde sayısal bir hızlı bağlantı noktası uygulayın.
  • Pivot rasgele veya üç ortanca (1., son ve orta eleman) ile seçilmelidir .
  • Programınız eksiksiz bir program veya işlev olabilir.
  • STDIN, komut satırı argümanları veya fonksiyon parametrelerini kullanarak girişi alabilirsiniz. Bir dize girişi kullanıyorsanız, giriş boşlukla ayrılmıştır.
  • Giriş ondalık ve negatif değerler içerebilir. Ancak, hiçbir kopya olmayacak.
  • STDOUT'a veya işlevden döndürerek çıktı alabilirsiniz.
  • Dahili sıralama (veya ilişkili sıralama) işlevi veya standart boşluklar yok.
  • Liste isteğe bağlı bir uzunluk olabilir.

Bonus # 1: Uzunluğu <= 5 olan listelerde veya alt listelerde, işleri biraz hızlandırmak için ekleme sıralamasını kullanın. Ödül: -15%.

Bonus # 2: Diliniz eşzamanlılığı destekliyorsa, listeyi paralel olarak sıralayın. Alt listelerde bir ekleme düzeni kullanıyorsanız, son ekleme düzeninin paralel olması gerekmez. Yerleşik diş havuzları / iş parçacığı planlamasına izin verilir. Ödül: -15%.

Not: Üçte birinin medyanı bazı insanların kafasını karıştırıyordu, bu yüzden burada (yine) Wikipedia'dan bir açıklama, nezaket:

Pivot için bölmenin ilk, orta ve son elemanının medyanını seçme

puanlama

Bu . Temel puan bayt cinsindendir. Bir bonusunuz varsa, bu numaradan% 15 indirim alın. Eğer ikisini birden aldıysan,% 30 indirim yap. Bu gerçekten bir satış perdesi gibi geliyor.

Bu, genel olarak en kısa cevabı bulmakla ilgili değil, her dilde en kısa cevabı bulmakla ilgilidir.

Ve şimdi, büyük afiş snippet'in utanmaz bir kopyası.

Afiş

Bu yazının altındaki Yığın Parçacığı, cevapları a) dil başına en kısa çözümün bir listesi olarak ve b) genel bir lider tablosu olarak oluşturur.

Cevabınızın göründüğünden emin olmak için, lütfen aşağıdaki Markdown şablonunu kullanarak cevabınızı bir başlık ile başlatın:

## Language Name, N bytes

N, gönderiminizin büyüklüğüdür. Puanınızı yükseltirseniz, başlıkları üstüne vurarak eski skorları başlıkta tutabilirsiniz. Örneğin:

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

Başlığınıza birden fazla sayı eklemek istiyorsanız (örneğin, puanınız iki dosyanın toplamı olduğundan veya tercüman bayrağı cezalarını ayrı ayrı listelemek istediğiniz için), gerçek puanın başlıktaki son sayı olduğundan emin olun:

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

Dil adını, daha sonra pasajda görünecek bir bağlantı da yapabilirsiniz:

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


4
"Pivot rasgele veya üç ortanca ile seçilmelidir (1., son ve orta eleman)." Ne anlama geliyor? Daha önce sadece bir elemanın seçildiğini söylemiştin.
msh210

2
@daniero Snippet şimdi sabittir
Daniel M.

1
Ortanca seçim algoritması zor bir gereklilik midir? Bağlantılı bir listeyi birincil dizi türü (Haskell, LISP) olarak kullanan dillerde (performansta olduğu gibi) pratik değildir ve zaten kuralı yok sayan en az bir cevap vardır.
John Dvorak

2
Hem rasgele pivot hem de üçünün ortancası listeye dayalı dillerde sorunlu. Her ikisi de diziye rasgele erişim gerektirir ve bağlantılı bir listenin sonuna erişim O (n) olur. İlk üç öğenin ortancasını almak, aynı işi yapmaz (aynı zamanda üç parçanın içinde aynı pivotu yakalayacağınız için) ve aynı zamanda sadece iyi bir sebep olmadan kodu zorlaştırır.
John Dvorak

1
Rastgele pivot Haskell'de başka bir nedenden ötürü de sorunlu - zar atmaya başladığınızda, artık bir fonksiyon yazmıyorsunuz. Bir dizi üreten bir G / Ç eylemi tanımlıyorsunuz. Bir RNG durumunu bir argüman olarak alan bir işlev tanımlayabilirsiniz, ancak bu da çok büyük değildir.
John Dvorak

Yanıtlar:


10

C ++, 440.3 405 388 bayt

518 bayt - ekleme sıralama için% 15 bonus = 440.3 bayt

477 bayt - ekleme sıralama için% 15 bonus = 405.45 bayt

474 bayt - ekleme sıralama için% 15 bonus = 402.9 bayt

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

3 bayt (2 gerçekten) kaydetmek için @Luke için teşekkürler.

18 (15) bayt tasarruf için @ Dúthomhas sayesinde.

Burada yeniyim ve bu benim ilk gönderim.

Bu bir .h(başlık) dosyadır.

Sıkıştırılmış Kod:

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

Tam kod:

#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
QuickSort yerine tek bir harf adı kullanarak ve son işlev çağrısında boşluk bırakarak 10 bayt kaydedebilirsiniz. Ve bahse girerim bonustan kaçınarak daha iyi bir puan alabilirsiniz (% 15 yeterli değil)
edc65

1
Bağımsız değişkenlerin köşeli parantezlerini tek yıldızlarla değiştirerek 5 bayttan daha tasarruf edebilirsiniz. Bazı makro sihir sanırım biraz daha baytları tıraş edebilir.
cadaniluk

2
Sonra boşluğa ihtiyacınız yok #include.
Luke

srand(time(NULL));Gelen çağrıyı kaldırarak 34 bayttan kurtulun. Hala sahte rastgele sayılar alabilirsiniz rand().
Dúthomhas

9

APL, 49 42 bayt

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

Bu, sağdaki bir diziyi kabul eden adsız özyinelemeli monadik bir işlev yaratır. Bonus için uygun değil.

Açıklama:

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

Çevrimiçi deneyin

Marinus sayesinde bir sorun düzeltildi (8 bayt pahasına) ve Thomas Kwa sayesinde 7 bayt tasarruf etti!


Soru, yinelenen olmayacağını belirtir. (Bunu görmek ne kadar uzun sürdü bilmiyorum ...)
lirtosiast

5

C ++ 17, 254 199 195 bayt

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

Boşluk ile:

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

Srand gerek yok (zaman (NULL)). Silmeye gerek yok, değerin bölünmesine izin verin, sonra 'if (a.empty ())' ifadesini 'if (a.size () <2)' olarak değiştirin ve 'lP (x)' harfini kaldırın.
Chris Jefferson

Silme işlemini ortadan kaldırmak, bir çok baytı kurtarmamı sağladı . Teşekkür ederim!
Lynn

Bir tane daha küçük olanı: 'r = q (r)' atamanıza gerek yok, sadece (y: q (r)) 'kullanın, ama tüm görebildiğim bu!
Chris Jefferson,

Sadece meraktan: C ++ 17 özellikle burada nerede kullanılıyor?
kirbyfan64sos

1
for (y : a)Aksi takdirde for (auto y : a)veya olması gerekirdi for (int y : a). (Aslında clang++bu bir çağıran C ++ 1z uzantısı , ama gerçekten C ++ 17 olmak görünmüyor bilmiyorum ve bunu aramak gitmek için gece çok geç?.)
Lynn

4

Pyth, 25 bayt

L?tbsyMa_,]JObf<TJbf>TJbb

Bu, ygiriş olarak sayıların listesini alan bir işlevi tanımlar .

Çevrimiçi deneyin: Gösteri

açıklama

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 bayt (muhtemelen geçersiz)

Dahili olarak bir sıralama kullanan "group by by" yöntemini kullanıyorum. Orijinal listeyi üç alt listeye ayırmak için kullanıyorum (pivottan daha küçük olan tüm öğeler, pivottan ve pivottan daha büyük olan tüm öğeler). "Grup-by" sırasındaki sıralama olmadan, bu 3 listeyi farklı bir sıraya göre döndürebilirdi.

Dediğim gibi, bu muhtemelen geçersiz. Yine de burada tutacağım, çünkü bu ilginç bir çözüm.

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

Çevrimiçi deneyin: Gösteri

açıklama

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

> <> (Balık), 313 309 bayt

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

Bu bana yazmak çok uzun sürdü. Burada deneyebilirsiniz , programı çalıştırmadan önce virgülle ayrılmış ilk yığına yerleştirilmesi gereken listeyi koymanız yeterlidir.

Nasıl çalışır

Program ilk yığındaki ilk, orta ve son elemanı kapar ve bu üçünün ortancasını hesaplar.
Daha sonra yığını şu şekilde değiştirir:

[list 1] element [liste 2]

1. listedeki her şey elemana göre daha küçük veya eşittir ve 2. listedeki her şey daha büyüktür.
Tüm liste sıralanana kadar bu işlemi liste 1 ve liste 2'de tekrar tekrar eder.


2

CJam, 40 bayt

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

Bu, yığında bir dizi bekleyen ve karşılığında bir tane iterek adlandırılmış bir işlevdir.

CJam tercümanında çevrimiçi olarak deneyin .

Yukarıdaki kod, belirtimi olabildiğince yakından takip eder. Bu gerekli değilse, 12 bayt kaydedilebilir:

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

2

Python 3, 123 , 122.

Aaron sayesinde 1 byte kurtarıldı.

Bu aslında bir sıralama algoritması yazmak için uğraşıyorum. Aslında düşündüğümden biraz daha kolay.

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)

<=Karşılaştırma nedeniyle işe yaramayacak gibi görünüyor - bunun pdoğru yerde olduğunu garanti etmiyor , muhtemelen özel bir eşitsizliğe dönüştürmeniz ve portada bağımsız olarak eklemeniz gerekebilir (test etmedim / yapabilirim kodu sınama).
VisualMelon

@VisualMelon Bir sürü farklı durumla test ettim ve asla yanlış bir sonuç almadım, ancak bunu kıran bir test durumu bulabilirseniz, bana bildirin. Ayrıca, yinelenenlerle çalışmayabilir, ancak zorluk yinelenen olmayacağını belirtir.
Morgan Thrapp

[2, 1, 3]Pivotu 2 olacak şekilde seçtiğinde, zamanın 1 / 3'ünü kıracağını düşünürdüm , düşük listeye sahip olacak [2, 1]- Üzgünüm, şu anda kendimi test edemiyorum.
VisualMelon

@VisualMelon Eh, elbette, fakat sonra tekrar tekrar sıralar.
Morgan Thrapp,

Beni kafa karıştırıcı bir upvote var - Ha, pardon, tamamen değil, oldukça Quicksort uygulanacak ı beklenir nasıl cevapsız
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)));}

açıklama

//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 muhtemelen bunu kısaltabilir.
Nissa

1

Yakut, 87 60 bayt

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

Ölçek:

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

Octave, 76 75 bayt

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

Çok hatlı versiyon:

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 bayt

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

Bu, bir Qdiziyi kabul eden ve bir dizi döndüren özyinelemeli bir işlev oluşturur . Koşullu olarak ekleme sıralama kullanmaz, bu nedenle bonus uygulanmaz.

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

Bir sorun düzeltildi ve Glen O!


Yinelenen öğelerin kaybolmasıyla ilgili olası sorunlar (kodunuzda zaten var) bir yana, filk kullanımda atayarak filterve endofyerine kullanarak birkaç bayttan tasarruf edebilirsiniz 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 Öneri için teşekkürler. Bunu uyguladım ve konuyu tekrarlayan unsurlarla düzelttim.
Alex A.

Bunun bir sorun olabilir dedi, ama ben açıklama soru afişi istedi ve "Giriş ondalık ve negatif değerler içerebilir Ancak, hiçbir çiftleri olacaktır."
Glen O

1

R, 78 bayt

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

Bu, bir Qvektörü kabul eden ve bir vektörü döndüren özyinelemeli bir işlev yaratır . Koşullu olarak ekleme sıralama uygulamıyor, bu yüzden bonus yok.

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

Çevrimiçi deneyin

Flodel sayesinde 4 byte kurtarıldı!


Uzunluk karşılaştırmasından "> 1" 'i bırakarak birkaç baytı çıkarabilirsiniz. Bu örtülü olarak 0 ile karşılaştırır, ancak fazladan bir özyineleme katmanı sorun olmaz,
Miff

@Miff Girişiniz için teşekkürler ama denedim ve bu benim için beklenen sonucu vermedi.
Alex A.

1

K, 41 bayt

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

BU ALIN, APL !!! Bonusların hiçbirini yapmaz.


1

Haskell, 137136 bayt

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

Ungolfed versiyonu genişletilmiş değişken ve fonksiyon isimleri ve bazı ara sonuçlarla birlikte aşağıdadır:

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

İki katı karşılaştırma yapmanın kopyası olmadığı gerçeğinden faydalanıyorum. Data.List.partitionBir import ifadesi eklemek zorunda kalacağımı düşünmeme rağmen, işleri daha kısa yapıp yapmadığını kontrol etmek zorunda kalacağım. Ekleme sıralama bonusunu almıyorum, çünkü Data.List.insertsıralama ile ilgili bir işlev olarak görüyorum - bu nedenle yasak - ve kullanılmazsa, ekleme sıralama eklenmesi kodu 246 bayta, 209.1 değerine iter, bu yüzden buna değmez.

Düzenleme: Kullanmak için takma ad oluşturma önerileri için RobAu'ya teşekkür ederiz f=filter. Yalnızca bir bayt kurtarabilir, ancak her şey yardımcı olur.


1
f=filterbazı baytları tıraş edebilir.
RobAu

Belki iki gereksiz q$f(>n)lve q$f(<n)lçağrıları ele almak için bir işlev yaparak birkaç baytı tıraş edebilirsiniz.
Cyoce

1

Tcl, 138 bayt

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

Bu son derece standart bir quicksort.

Pivot, her bir alt dizinin ilk elemanıdır (bunun rastgele bir sayı olduğunu iddia ediyorum. Https://xkcd.com/221/ )

Bu özellikle bellek kullanımı açısından verimli değildir, ancak tailcallikinci özyinelemede ve n <1 elementin temel durumunda olduğu gibi geliştirilebilir.

İşte okunabilir sürüm:

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

Tüm girdilerde çalışır ve kopyalara izin verir. Oh, ayrıca kararlı . Basit bir şeyle test edebilirsiniz:

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

Keyfini çıkarın! :O)


Sen yerine byte kaydedebilirsiniz foreachtarafından 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

Seylan (yalnızca JVM), 183 170

Bonus yoktur.

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

Seylan'da rastgele bir sayı üretmenin çapraz platform yolu yok gibi görünüyor, bu yüzden bu sadece JVM'dir. (Sonunda JS'de çalışan ve daha küçük olan rastgele olmayan bir sürüme de sahibim.)

Bu, yüzen bir yinelenebilir alır ve sıralanmış bir sürümünü döndüren bir işlev tanımlar.

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

(Şartnameye göre) yinelenen girişler iletilirse, bunlar filtrelenir.

Bu 183 bayttır: 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[];}}

Yeni (Ceylon 1.2) ififadesini kullanarak biraz geliştirebiliriz :

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

Bu 170 bayttır: 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[];


İşte rastgele olmayan bir sürüm:

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

Boşluksuz olarak bu 107 bayt olur: {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 bayt

Bu çok hızlı (yine de AutoIt için). Ekleme sıralama bonusu için hak kazanır. Son golf oynadıktan sonra açıklama ekleyecektir.

Girdi olduğunu 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

Rastgele test girişi + çıkışı:

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

İlginç, daha önce AutoIt hiç duymadım
Daniel M.

0

Java, 346 bayt

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

Sıkıştırılmış Kod:

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

Tam kod:

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

}

Çift iyileştirmeleri: 1. int [] ve a arasındaki metot başlığındaki boşluklardan kurtulun. 2. Bir for döngüsündeki artış veya azalmayı, değişkene erişilen son yere yapın. 3. Baytları yeni bir int yerine kullanarak kaydetmek için bir int (veya çift) sınıfı yapın. 4. Math.random () işlevinin kullanılması ve yayınlanması bir Rastgele nesne oluşturmaya göre daha kısa olabilir.
Mavi,

0

Mathematica, 93 90 bayt

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

Bonus yok, henüz ekleme sıralama yapmak için minimal bir yol yok. Geçenlerde C ++ öğrenirken, burada çeşitli sıralama algoritmalarının karşılaştırmasını yaptım .


0

Python2, 120 bayt

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:]tam olarak sürece if len(a)>2ama daha golf gibi görünüyor.


0

Lua, 242 Bayt

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 ve Patlama

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

Raket 121 bayt

(λ(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 = kafa (ilk eleman), t = kuyruk (kalan veya kalan elemanlar)):

(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 yapmak:

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

Çıktı:

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

0

Japt , 23 bayt

Her bonusun toplam puanın karşılığını almak için üç ya da daha az olması gerekir, bu yüzden herhangi bir bonus almadım.

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.

Çevrimiçi deneyin!


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.