Sắp xếp cái này, nhanh lên!


27

Chà ... có 59 (bây giờ là 60) câu hỏi được gắn thẻ , nhưng không có câu hỏi nhanh đơn giản nào.

Điều đó phải được sửa chữa.

Đối với những người không quen thuộc với quicksort , đây là một sự cố, lịch sự của Wikipedia-

  1. Chọn một phần tử, được gọi là trục , từ mảng.
  2. Sắp xếp lại mảng sao cho tất cả các phần tử có giá trị nhỏ hơn trục xuất hiện trước trục, trong khi tất cả các phần tử có giá trị lớn hơn trục xuất hiện sau nó (giá trị bằng nhau có thể đi theo một trong hai cách). Sau khi phân vùng này, trục nằm ở vị trí cuối cùng. Đây được gọi là hoạt động phân vùng.
  3. Áp dụng đệ quy các bước trên cho mảng con của các phần tử có giá trị nhỏ hơn và riêng biệt với mảng con của phần tử có giá trị lớn hơn.

Quy tắc

Các quy tắc rất đơn giản:

  • Thực hiện một quicksort số trong ngôn ngữ lập trình bạn chọn.
  • Trục phải được chọn ngẫu nhiên hoặc với trung vị là ba (phần tử thứ nhất, cuối cùng và giữa).
  • Chương trình của bạn có thể là một chương trình hoặc chức năng hoàn chỉnh.
  • Bạn có thể nhận đầu vào bằng STDIN, tham số dòng lệnh hoặc tham số hàm. Nếu sử dụng đầu vào chuỗi, đầu vào là khoảng cách.
  • Đầu vào có thể chứa giá trị thập phân và âm. Tuy nhiên, sẽ không có bản sao.
  • Bạn có thể xuất ra STDOUT hoặc bằng cách quay lại từ hàm.
  • Không có chức năng sắp xếp tích hợp (hoặc sắp xếp liên quan) hoặc sơ hở tiêu chuẩn.
  • Danh sách có thể là một chiều dài tùy ý.

Phần thưởng số 1: Trên danh sách hoặc danh sách phụ có độ dài <= 5, hãy sử dụng sắp xếp chèn để tăng tốc mọi thứ lên một chút. Phần thưởng: -15%.

Phần thưởng số 2: Nếu ngôn ngữ của bạn hỗ trợ đồng thời, hãy sắp xếp danh sách song song. Nếu bạn đang sử dụng một loại sắp xếp chèn trong danh sách phụ, thì loại chèn cuối cùng không cần phải song song. Được xây dựng trong nhóm luồng / lập lịch luồng được cho phép. Phần thưởng: -15%.

Lưu ý: Trung bình của ba người đã gây nhầm lẫn cho một số người, vì vậy đây là một lời giải thích, lịch sự của (một lần nữa) Wikipedia:

chọn trung vị của phần tử đầu tiên, giữa và cuối của phân vùng cho trục

Chấm điểm

Đây là . Điểm cơ bản được tính bằng byte. Nếu bạn có một phần thưởng, hãy giảm 15% số đó. Nếu bạn có cả hai, hãy giảm 30%. Điều đó thực sự nghe giống như một doanh số bán hàng.

Đây không phải là về việc tìm câu trả lời ngắn nhất trên tổng thể, mà là ngắn nhất trong mỗi ngôn ngữ.

Và bây giờ, một bản sao không biết xấu hổ của đoạn trích bảng xếp hạng.

Bảng xếp hạng

Đoạn trích đoạn ở cuối bài này tạo ra danh mục từ các câu trả lời a) dưới dạng danh sách các giải pháp ngắn nhất cho mỗi ngôn ngữ và b) dưới dạng bảng xếp hạng tổng thể.

Để đảm bảo rằng câu trả lời của bạn hiển thị, vui lòng bắt đầu câu trả lời của bạn bằng một tiêu đề, sử dụng mẫu Markdown sau:

## Language Name, N bytes

Trong đó N là kích thước của trình của bạn. Nếu bạn cải thiện điểm số của mình, bạn có thể giữ điểm số cũ trong tiêu đề, bằng cách đánh bại chúng thông qua. Ví dụ:

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

Nếu bạn muốn bao gồm nhiều số trong tiêu đề của mình (ví dụ: vì điểm của bạn là tổng của hai tệp hoặc bạn muốn liệt kê riêng các hình phạt cờ của thông dịch viên), hãy đảm bảo rằng điểm thực tế là số cuối cùng trong tiêu đề:

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

Bạn cũng có thể đặt tên ngôn ngữ thành liên kết sau đó sẽ hiển thị trong đoạn trích:

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


4
"Trục nên được chọn ngẫu nhiên hoặc với trung vị là ba (phần tử thứ nhất, cuối cùng và giữa)." Điều đó có nghĩa là gì? Trước đây bạn chỉ nói một yếu tố được chọn.
msh210

2
@daniero Đoạn mã được sửa ngay bây giờ
Daniel M.

1
Là thuật toán lựa chọn trung bình là một yêu cầu khó khăn? Nó không thực tế (như trong, nó chứa hiệu năng) trong các ngôn ngữ sử dụng danh sách được liên kết làm kiểu mảng chính của chúng (Haskell, LISP) và đã có ít nhất một câu trả lời bỏ qua quy tắc.
John Dvorak

2
Cả hai trục ngẫu nhiên và trung vị của ba đều có vấn đề trong các ngôn ngữ dựa trên danh sách. Cả hai đều yêu cầu truy cập ngẫu nhiên vào mảng và truy cập vào cuối danh sách được liên kết là O (n). Lấy trung vị của ba yếu tố đầu tiên không thực hiện cùng một loại công việc (cũng bởi vì bạn sẽ lấy cùng một trục trong ba lần phân tách) và chỉ làm phức tạp mã mà không có lý do chính đáng.
John Dvorak

1
Trục ngẫu nhiên cũng có vấn đề trong Haskell vì một lý do khác - một khi bạn bắt đầu gieo xúc xắc, bạn không còn viết hàm. Bạn đang xác định một hành động I / O tạo ra một mảng. Bạn có thể định nghĩa một hàm lấy trạng thái RNG làm đối số, nhưng nó cũng không quá tuyệt vời.
John Dvorak

Câu trả lời:


10

C ++, 440.3 405 388 byte

518 byte - Phần thưởng 15% cho sắp xếp chèn = 440,3 byte

477 byte - Phần thưởng 15% cho sắp xếp chèn = 405,45 byte

474 byte - Phần thưởng 15% cho sắp xếp chèn = 402,9 byte

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

Cảm ơn @Luke vì đã lưu 3 byte (2 thực sự).

Cảm ơn @ Dúthomhas vì đã lưu 18 (15 thực sự) byte.

Lưu ý rằng tôi mới ở đây và đây là bài viết đầu tiên của tôi.

Đây là một .htập tin (tiêu đề).

Mã nén:

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

Mã đầy đủ:

#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
Bạn có thể lưu 10 byte bằng một tên chữ cái thay vì quickSort và xóa khoảng trắng trong lệnh gọi hàm cuối cùng. Và tôi cá rằng bạn có thể đạt điểm cao hơn tránh tiền thưởng (15% là không đủ)
edc65

1
Bạn có thể lưu thêm 5 byte bằng cách thay thế dấu ngoặc vuông của các đối số bằng các dấu sao đơn. Một số phép thuật vĩ mô có thể loại bỏ một số byte hơn, tôi đoán vậy.
cadaniluk

2
Bạn không cần một không gian sau #include.
Lu-ca

Loại bỏ 34 byte bằng cách xóa cuộc gọi đến srand(time(NULL));Bạn vẫn sẽ nhận được các số giả ngẫu nhiên từ đó rand().
Dúthomhas

9

APL, 49 42 byte

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

Điều này tạo ra một hàm đơn thức đệ quy không tên, chấp nhận một mảng ở bên phải. Nó không đủ điều kiện cho tiền thưởng.

Giải trình:

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

Dùng thử trực tuyến

Đã khắc phục sự cố (với chi phí 8 byte) nhờ vào bến và lưu 7 byte nhờ Thomas Kwa!


Câu hỏi chỉ định sẽ không có bản sao. (Không biết làm thế nào tôi mất nhiều thời gian để thấy điều đó ...)
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;}

Với khoảng trắng:

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

Không cần srand (thời gian (NULL)). Không cần xóa, chỉ cần để giá trị được phân vùng, sau đó thay đổi 'if (a.empty ())' thành 'if (a.size () <2)' và xóa 'lP (x)'.
Chris Jefferson

Loại bỏ xóa cho phép tôi tiết kiệm rất nhiều byte. Cảm ơn bạn!
Lynn

Một điều nhỏ bé khác: Không cần gán 'r = q (r)', chỉ cần sử dụng 'cho (y: q (r))', nhưng đó là tất cả những gì tôi có thể thấy!
Chris Jefferson

Chỉ tò mò thôi: C ++ 17 đặc biệt được sử dụng ở đâu?
kirbyfan64sos

1
for (y : a)mặt khác sẽ cần phải for (auto y : a)hoặc for (int y : a). (Trên thực tế, clang++gọi đây là phần mở rộng C ++ 1z , nhưng dường như nó không thực sự là C ++ 17? Tôi không biết và đã quá muộn để đi tìm nó.)
Lynn

4

Bình thường, 25 byte

L?tbsyMa_,]JObf<TJbf>TJbb

Điều này xác định một hàm y, lấy danh sách các số làm đầu vào.

Dùng thử trực tuyến: Trình diễn

Giải trình

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 (có thể không hợp lệ)

Tôi sử dụng phương pháp "nhóm theo", bên trong sử dụng một loại. Tôi sử dụng nó để chia danh sách ban đầu thành ba danh sách phụ (tất cả các yếu tố nhỏ hơn trục, trục và tất cả các yếu tố lớn hơn trục). Nếu không sắp xếp theo "nhóm theo", nó có thể trả về 3 danh sách này theo thứ tự khác nhau.

Như đã nói, điều này có lẽ không hợp lệ. Tuy nhiên, tôi sẽ giữ nó ở đây, bởi vì đó là một giải pháp thú vị.

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

Dùng thử trực tuyến: Trình diễn

Giải trình

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

> <> (Cá), 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.

Điều này làm tôi mất rất lâu để viết. Bạn có thể thử nó ở đây , chỉ cần đặt danh sách phải được sắp xếp vào ngăn xếp ban đầu, được phân tách bằng dấu phẩy, trước khi chạy chương trình.

Làm thế nào nó hoạt động

Chương trình lấy phần tử đầu tiên, giữa và cuối trong ngăn xếp ban đầu và tính toán trung vị của ba phần tử này.
Sau đó, nó thay đổi ngăn xếp thành:

[danh sách 1] phần tử [danh sách 2]

trong đó mọi thứ trong danh sách 1 nhỏ hơn hoặc bằng phần tử và mọi thứ trong danh sách 2 đều lớn hơn.
Nó đệ quy lặp lại quá trình này trong danh sách 1 và danh sách 2 cho đến khi toàn bộ danh sách được sắp xếp.


2

CJam, 40 byte

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

Đây là một hàm được đặt tên dự kiến ​​một mảng trên ngăn xếp và trả lại một mảng.

Hãy thử trực tuyến trong trình thông dịch CJam .

Các mã trên theo thông số kỹ thuật càng chặt chẽ càng tốt. Nếu không cần thiết, 12 byte có thể được lưu:

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

2

Trăn 3, 123 , 122.

Lưu được 1 byte nhờ Aaron.

Đây là lần đầu tiên tôi thực sự bận tâm viết một thuật toán sắp xếp. Nó thực sự dễ dàng hơn một chút so với tôi nghĩ.

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

Ung dung:

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)

Điều này có vẻ như nó có thể không hoạt động, do <=so sánh - không đảm bảo rằng pnó ở đúng nơi, bạn có thể cần phải thay đổi điều đó thành bất đẳng thức độc quyền và thêm pvào giữa một cách độc lập (Tôi không kiểm tra / có thể 't kiểm tra mã).
VisualMelon

@VisualMelon Tôi đã thử nghiệm nó với một loạt các trường hợp khác nhau và không bao giờ có kết quả không chính xác, nhưng nếu bạn có thể tìm thấy một trường hợp thử nghiệm phá vỡ nó, hãy cho tôi biết. Ngoài ra, nó có thể không hoạt động với các bản sao, nhưng thách thức chỉ ra rằng sẽ không có bản sao.
Morgan Thrapp

Tôi đã nghĩ rằng nó [2, 1, 3]sẽ phá vỡ 1/3 thời gian, vì khi nó chọn trục là 2, nó sẽ có danh sách thấp [2, 1]- tôi xin lỗi tôi không thể tự kiểm tra điều này ngay bây giờ.
VisualMelon

@VisualMelon Vâng, chắc chắn, nhưng sau đó sắp xếp lại một cách đệ quy.
Morgan Thrapp

À, xin lỗi, đã bỏ lỡ hoàn toàn, không hoàn toàn như tôi mong đợi một Quicksort sẽ được triển khai - có một upvote khiến tôi bối rối
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)));}

Giải trình

//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 có thể rút ngắn điều này.
Nissa

1

Hồng ngọc 87 60 byte

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

Ung dung:

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

Kiểm tra:

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

Phiên bản nhiều dòng:

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

Điều này tạo ra một hàm đệ quy Qchấp nhận một mảng và trả về một mảng. Nó không có điều kiện sử dụng sắp xếp chèn, do đó không áp dụng tiền thưởng.

Ung dung:

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

Đã khắc phục sự cố và lưu một số byte nhờ Glen O!


Các vấn đề có thể xảy ra khi mất các phần tử lặp lại (đã tồn tại trong mã của bạn), bạn có thể lưu một vài byte ở đây bằng cách gán fkhi bạn sử dụng lần đầu filtervà sử dụng endofthay vì 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 Cảm ơn bạn đã gợi ý. Tôi đã thực hiện điều đó và khắc phục sự cố với các yếu tố lặp đi lặp lại.
Alex A.

Tôi nói đó có thể là một vấn đề, nhưng tôi đã hỏi người đăng câu hỏi để làm rõ và "Đầu vào có thể chứa các giá trị thập phân và âm. Tuy nhiên, sẽ không có bản sao"
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

Điều này tạo ra một hàm đệ quy Qchấp nhận một vectơ và trả về một vectơ. Nó không có điều kiện áp dụng sắp xếp chèn, vì vậy không có tiền thưởng.

Ung dung:

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

Dùng thử trực tuyến

Đã lưu 4 byte nhờ flodel!


Bạn có thể tách một vài byte bằng cách bỏ "> 1" khỏi so sánh độ dài. Điều này ngầm so sánh nó với 0, nhưng một lớp đệ quy bổ sung không phải là vấn đề,
Miff

@Miff Cảm ơn bạn đã nhập nhưng tôi đã thử và nó không mang lại kết quả như mong đợi cho tôi.
Alex A.

1

K, 41 byte

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

HÃY THỬ, APL !!! Không làm bất kỳ phần thưởng nào.


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

Phiên bản không được đề cập dưới đây, với các tên hàm và biến được mở rộng và một số kết quả trung gian được thêm vào:

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

Tôi đang lợi dụng thực tế là không có sự trùng lặp để sử dụng hai so sánh nghiêm ngặt. Tôi sẽ phải kiểm tra nếu Data.List.partitionkhông làm mọi thứ ngắn hơn, thậm chí xem xét tôi sẽ phải thêm một báo cáo nhập khẩu. Tôi không lấy phần thưởng sắp xếp chèn vì tôi coi đó Data.List.insertlà một hàm liên quan đến sắp xếp - do đó bị cấm - và nếu không sử dụng nó, việc thêm loại chèn sẽ đẩy mã lên tới 246 byte, 209.1 với phần thưởng, vì vậy nó không có giá trị.

Chỉnh sửa: Cảm ơn RobAu về đề xuất của họ để tạo bí danh để sử dụng f=filter. Nó có thể chỉ lưu một byte nhưng mọi thứ đều có ích.


1
f=filtercó thể cạo đi một số byte.
RobAu

Có lẽ bạn có thể cạo một vài byte bằng cách tạo một hàm để xử lý hai dự phòng q$f(>n)lq$f(<n)l cuộc gọi và cuộc gọi ?
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]}

Đây là một quicksort cực kỳ tiêu chuẩn.

Trục đơn giản là yếu tố đầu tiên của mỗi phân đoạn (tôi cho rằng đây là số ngẫu nhiên. Https://xkcd.com/221/ )

Nó không đặc biệt hiệu quả về mặt sử dụng bộ nhớ, mặc dù nó có thể được cải thiện một số với tailcallđệ quy thứ hai và trường hợp cơ bản gồm n <1 phần tử.

Đây là phiên bản dễ đọc:

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

Hoạt động trên tất cả các đầu vào và cho phép trùng lặp. Ồ, nó cũng ổn định . Bạn có thể kiểm tra nó với một cái gì đó đơn giản, như:

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

Thưởng thức! : O)


Bạn có thể lưu byte thay thế foreachbằng 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 (chỉ JVM), 183 170

Không có tiền thưởng áp dụng.

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

Dường như không có cách nào đa nền tảng để tạo ra một số ngẫu nhiên trong Ceylon, vì vậy đây chỉ là JVM. (Cuối cùng, tôi cũng có một phiên bản không ngẫu nhiên, cũng hoạt động trong JS và nhỏ hơn.)

Điều này xác định một hàm có một vòng lặp nổi và trả về một phiên bản đã sắp xếp của nó.

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

Nếu (so với đặc điểm kỹ thuật) các mục trùng lặp được thông qua, những mục đó sẽ được lọc ra.

Đây là 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[];}}

Chúng ta có thể cải thiện một chút bằng cách sử dụng ifbiểu thức mới (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 [];

Đây là 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[];


Đây là một phiên bản không ngẫu nhiên:

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

Không có khoảng trắng, đây sẽ là 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

Tự động , 320,45 304,3 byte

Điều này rất nhanh (đối với AutoIt anyway). Đủ điều kiện để nhận tiền thưởng sắp xếp chèn. Sẽ thêm lời giải thích sau khi chơi golf cuối cùng xảy ra.

Đầu vào là 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

Kiểm tra ngẫu nhiên đầu vào + đầu ra:

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

Thú vị, chưa bao giờ nghe nói về AutoIt trước đây
Daniel M.

0

Java, 346 byte

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

Mã nén:

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

Mã đầy đủ:

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

}

Cải tiến cặp đôi: 1. thoát khỏi khoảng trắng giữa int [] và a trong tiêu đề phương thức. 2. Đặt mức tăng hoặc giảm trong vòng lặp for là nơi cuối cùng một biến được truy cập. 3. Tạo một lớp int (hoặc một cặp) để lưu byte bằng cách sử dụng nó thay vì int mới. 4. Sử dụng Math.random () và truyền có thể ngắn hơn so với tạo đối tượng Ngẫu nhiên.
Blue

0

Toán học, 93 90 byte

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

Không có tiền thưởng, chưa có cách tối thiểu để sắp xếp chèn. Khi tôi học C ++ gần đây, tôi đã so sánh các thuật toán sắp xếp khác nhau ở đây .


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:]là chính xác miễn là if len(a)>2nhưng trông golf hơn.


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

Ung thư và giải thích

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

Vợt 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 (phần tử đầu tiên), t = tail (phần còn lại hoặc phần tử còn lại)):

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

Kiểm tra:

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

Đầu ra:

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

0

Japt , 23 byte

Mỗi phần thưởng sẽ cần có ba byte hoặc ít hơn để trả hết trong tổng số điểm, vì vậy tôi đã không nhận bất kỳ phần thưởng nào.

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.

Hãy thử trực tuyến!


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.