이것을 빨리 정렬하십시오!


27

음 ... 태그로 59 (현재 60) 개의 질문이 있지만 간단한 퀵 정렬은 없습니다.

반드시 수정해야합니다.

quicksort에 익숙하지 않은 분들을 위해 Wikipedia가 제공 한 분류가 있습니다.

  1. 배열에서 pivot 이라는 요소를 선택하십시오 .
  2. 피벗보다 작은 값을 가진 모든 요소가 피벗보다 먼저 나오고 피벗보다 큰 값을 가진 모든 요소가 그 뒤에 오도록 배열을 재정렬합니다 (동일한 값은 어느 쪽이든 갈 수 있음). 이 분할 후 피벗은 최종 위치에 있습니다. 이것을 파티션 작업이라고합니다.
  3. 위의 단계를 더 작은 값을 가진 요소의 하위 배열에 반복적으로 적용하고 더 큰 값을 가진 요소의 하위 배열에 별도로 적용하십시오.

규칙

규칙은 간단합니다.

  • 선택한 프로그래밍 언어로 숫자 퀵 정렬을 구현하십시오.
  • 피벗은 임의로 또는 3의 중간 값 (첫 번째, 마지막 및 중간 요소) 으로 선택해야합니다 .
  • 귀하의 프로그램은 완전한 프로그램 또는 기능 일 수 있습니다.
  • STDIN, 명령 행 인수 또는 함수 매개 변수를 사용하여 입력을 얻을 수 있습니다. 문자열 입력을 사용하는 경우 입력은 공백으로 구분됩니다.
  • 입력에 10 진수 및 음수 값이 포함될 수 있습니다. 그러나 중복은 없습니다.
  • STDOUT으로 출력하거나 기능에서 복귀하여 출력 할 수 있습니다.
  • 내장 정렬 (또는 정렬 관련) 기능이나 표준 허점이 없습니다.
  • 리스트는 임의의 길이 일 수있다.

보너스 # 1 : 길이 <= 5 인 목록 또는 하위 목록에서 삽입 정렬 을 사용 하여 속도를 높입니다. 보상 : -15 %.

보너스 # 2 : 언어가 동시성을 지원하는 경우 목록을 병렬로 정렬하십시오. 하위 목록에서 삽입 정렬을 사용하는 경우 최종 삽입 정렬이 병렬 일 필요는 없습니다. 내장 된 스레드 풀 / 스레드 스케줄링이 허용됩니다. 보상 : -15 %.

참고 : 세 사람의 중앙값은 일부 사람들을 혼란스럽게했기 때문에 여기에 (다시) Wikipedia의 설명이 있습니다.

피벗에 대한 파티션의 첫 번째, 중간 및 마지막 요소의 중앙값 선택

채점

이것은 입니다. 기본 점수는 바이트입니다. 하나의 보너스를 받으면 그 숫자를 15 % 할인하십시오. 둘 다 얻은 경우 30 % 할인을 받으십시오. 그것은 실제로 판매 피치처럼 들립니다.

이것은 전체적으로 가장 짧은 답변을 찾는 것이 아니라 각 언어에서 가장 짧은 답변을 찾는 것입니다.

이제 리더 보드 스 니펫의 수치스러운 사본입니다.

리더 보드

이 게시물의 맨 아래에있는 스택 스 니펫은 답변 a) 언어 당 가장 짧은 솔루션 목록으로, b) 전체 리더 보드로 카탈로그를 생성합니다.

답변이 표시되도록하려면 다음 마크 다운 템플릿을 사용하여 헤드 라인으로 답변을 시작하십시오.

## Language Name, N bytes

여기서 N은 제출 크기입니다. 점수를 높이면 헤드 라인을 쳐서 오래된 점수를 유지할 수 있습니다. 예를 들어 :

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

헤더에 여러 숫자를 포함하려는 경우 (예 : 점수가 두 파일의 합계이거나 인터프리터 플래그 페널티를 별도로 나열하려는 경우) 실제 점수가 헤더의 마지막 숫자인지 확인하십시오.

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

언어 이름을 링크로 만들면 스 니펫에 표시됩니다.

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


4
"피벗은 임의로 또는 3의 중간 값 (첫 번째, 마지막 및 중간 요소)으로 선택해야합니다." 이것은 무엇을 의미 하는가? 이전에 단 하나의 요소 만 선택했다고 말했습니다.
msh210

2
@daniero Snippet이 수정되었습니다
Daniel M.

1
중간 선택 알고리즘이 어려운 요구 사항입니까? 연결된 목록을 기본 배열 유형 (Haskell, LISP)으로 사용하는 언어에서는 성능이 저하되는 것처럼 실용적이지 않으며 규칙을 무시하는 응답이 이미 하나 이상 있습니다.
John Dvorak

2
목록 기반 언어에서는 랜덤 피벗과 3의 중간 값이 모두 문제가됩니다. 둘 다 배열에 무작위로 액세스해야하며 연결된 목록의 끝에 액세스하는 것은 O (n)입니다. 처음 세 요소의 중앙값을 가져 오는 것은 같은 종류의 작업을 수행하지 않으며 (어쨌든 세 개의 분할 내에서 동일한 피벗을 잡을 수 있기 때문에) 정당한 이유없이 코드를 복잡하게 만듭니다.
John Dvorak

1
주사위 던지기를 시작하면 더 이상 함수를 작성하지 않아도됩니다. 배열을 생성하는 I / O 작업을 정의하고 있습니다. RNG 상태를 인수로 사용하는 함수를 정의 할 수 있지만 너무 크지 않습니다.
John Dvorak

답변:


10

C ++, 440.3 405 388 바이트

518 바이트-삽입 정렬시 15 % 보너스 = 440.3 바이트

477 바이트-삽입 정렬시 15 % 보너스 = 405.45 바이트

474 바이트-삽입 정렬시 15 % 보너스 = 402.9 바이트

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

3 바이트를 절약 한 @Luke에게 감사드립니다 (정말 2 개).

18 (15 실제) 바이트를 절약 한 @ Dúthomhas에게 감사합니다.

나는 여기에 처음이며 이것은 나의 첫 번째 게시물입니다.

이것은 .h(헤더) 파일입니다.

압축 코드 :

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

전체 코드 :

#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 대신 단일 문자 이름을 사용하고 마지막 함수 호출에서 공백을 제거하여 10 바이트를 저장할 수 있습니다. 그리고 난 당신이 보너스를 피하고 더 나은 점수를 얻을 수 있다는 것을 내기 (15 %는 충분하지 않습니다)
edc65

1
인수의 대괄호를 별표로 대체하여 5 바이트를 더 절약 할 수 있습니다. 일부 매크로 매직은 더 많은 바이트를 깎을 수 있다고 생각합니다.
cadaniluk

2
뒤에 공백이 필요하지 않습니다 #include.
Luke

에 대한 호출을 제거하여 34 바이트를 제거하십시오 . srand(time(NULL));에서 여전히 의사 난수를 얻습니다 rand().
Dúthomhas

9

APL, 49 42 바이트

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

이것은 이름없는 재귀 monadic 함수를 만들어 오른쪽에 배열을 받아들입니다. 보너스를받을 자격이 없습니다.

설명:

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

온라인으로 사용해보십시오

marinus 덕분에 (8 바이트의 비용으로) 문제가 수정되었고 Thomas Kwa 덕분에 7 바이트가 절약되었습니다!


질문은 중복이 없음을 나타냅니다. (이 그것을보고 너무 오래 걸렸다 어떻게 ... 몰라)
lirtosiast

5

C ++ 17 254 199 195 바이트

#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 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 (time (NULL))가 필요 없습니다. 지우지 않아도됩니다. 값을 분할 한 다음 'if (a.empty ())'를 'if (a.size () <2)'로 변경하고 'lP (x)'를 제거하십시오.
크리스 제퍼슨

지우기를 제거하면 많은 바이트 를 절약 할 수있었습니다 . 고맙습니다!
Lynn

다른 작은 하나 : 'r = q (r)'을 할당 할 필요가 없으며 'for (y : q (r))'을 사용하십시오. 그러나 이것이 내가 볼 수있는 전부입니다!
크리스 제퍼슨

호기심에서 C ++ 17은 어디에 사용됩니까?
kirbyfan64sos

1
for (y : a)그렇지 않으면 for (auto y : a)또는 이어야 for (int y : a)합니다. (실제로 clang++이것을 C ++ 1z 확장 이라고 부르지 만 실제로는 C ++ 17 인 것 같지 않습니까? 모르겠습니다. 밤에는 너무 늦어서 찾아 볼 수 없습니다.)
Lynn

4

Pyth, 25 바이트

L?tbsyMa_,]JObf<TJbf>TJbb

이것은 y숫자 목록을 입력으로 받는 함수를 정의합니다 .

온라인으로 사용해보십시오 : 데모

설명

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 바이트 (아마 유효하지 않음)

내부적으로 정렬을 사용하는 "group-by"방법을 사용합니다. 원본 목록을 세 개의 하위 목록 (피벗보다 작은 모든 요소, 피벗 및 피벗보다 큰 모든 요소)으로 나누는 데 사용합니다. "group-by"로 정렬하지 않으면이 3 개의 목록을 다른 순서로 반환 할 수 있습니다.

말했듯이 이것은 아마도 유효하지 않습니다. 그럼에도 불구하고 흥미로운 솔루션이기 때문에 여기에 보관하겠습니다.

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

온라인으로 사용해보십시오 : 데모

설명

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

> <> (생선) 313 309 바이트

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

글을 쓰는 데 시간이 오래 걸렸습니다. 당신은 여기를 시도 할 수 있습니다 단지 프로그램을 실행하기 전에, 쉼표로 구분, 초기 스택으로 정렬하는 목록을 넣어.

작동 원리

이 프로그램은 초기 스택에서 첫 번째, 중간 및 마지막 요소를 잡고이 세 가지의 중앙값을 계산합니다.
그런 다음 스택을 다음과 같이 변경합니다.

[목록 1] 요소 [목록 2]

여기서리스트 1의 모든 것이 요소보다 작거나 같고리스트 2의 모든 것이 더 큽니다.
전체 목록이 정렬 될 때까지 목록 1과 목록 2에서이 프로세스를 반복적으로 반복합니다.


2

CJam, 40 바이트

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

이것은 스택에 배열을 기대하고 그에 대한 대가로 푸시하는 명명 된 함수입니다.

CJam 통역사 에서 온라인으로 사용해보십시오 .

위의 코드는 사양을 최대한 가깝게 따릅니다. 필요하지 않은 경우 12 바이트를 저장할 수 있습니다.

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

2

파이썬 3, 123 , 122.

Aaron 덕분에 1 바이트를 절약했습니다.

실제로 정렬 알고리즘을 작성하는 데 방해가 된 것은 이번이 처음입니다. 실제로 생각했던 것보다 조금 더 쉽습니다.

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

언 골프 드 :

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)

이것은 <=비교 로 인해 작동하지 않을 수있는 것처럼 보입니다 p. 적절한 장소에 있다는 것을 보장하지는 않습니다. 아마도 독점 불평등으로 변경 p하고 중간에 독립적으로 추가해야 합니다 (테스트 하지 못했습니다 / 할 수 없음) 코드를 테스트하지 마십시오).
VisualMelon

@VisualMelon 나는 여러 가지 다른 사례로 테스트했지만 잘못된 결과를 얻지 못했지만 테스트 사례를 발견하면 알려주십시오. 또한 중복으로 작동하지 않을 수도 있지만 과제는 중복이 발생하지 않도록 지정합니다.
Morgan Thrapp

[2, 1, 3]피벗을 2로 선택할 때 낮은 목록이 될 것이므로 1/3의 시간을 깰 것이라고 생각했을 것 [2, 1]입니다. 지금은 직접 테스트 할 수 없습니다.
VisualMelon

@VisualMelon 글쎄,하지만 재귀 적으로 다시 정렬됩니다.
Morgan Thrapp

아, 죄송합니다. Quicksort가 어떻게 구현 될지 잘 모르겠습니다. 혼란스러워
VisualMelon

2

자바 스크립트 (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)));}

설명

//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는 아마도 이것을 단축시킬 수 있습니다.
Nissa

1

루비, 87 60 바이트

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

언 골프 드 :

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

테스트:

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

옥타브, 76 75 바이트

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

여러 줄 버전 :

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

줄리아, 83 바이트

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

이것은 Q배열을 받아들이고 배열을 반환하는 재귀 함수 를 만듭니다 . 조건에 따라 삽입 정렬을 사용하지 않으므로 보너스가 적용되지 않습니다.

언 골프 드 :

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

Glen O! 덕분에 문제를 해결하고 일부 바이트를 절약했습니다.


코드에 이미 존재하는 반복 요소가 손실 될 수있는 문제를 제외하고 f처음 사용할 때를 할당 filter하고 endof대신에를 사용하여 몇 바이트를 절약 할 수 있습니다 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 제안 해 주셔서 감사합니다. 나는 그것을 구현하고 반복 된 요소로 문제를 해결했습니다.
Alex A.

문제가 될 수 있다고 말했지만 질문 포스터에 설명을 요청했습니다. "입력에 10 진수와 음수 값이 포함될 수 있습니다. 그러나 중복은 없습니다"
Glen O

1

R, 78 바이트

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

Q벡터를 받아들이고 벡터를 반환 하는 재귀 함수 를 만듭니다 . 조건에 따라 삽입 정렬을 적용하지 않으므로 보너스가 없습니다.

언 골프 드 :

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

온라인으로 사용해보십시오

flodel 덕분에 4 바이트를 절약했습니다!


길이 비교에서 "> 1"을 삭제하여 몇 바이트를 줄일 수 있습니다. 이것은 암시 적으로이를 0과 비교하지만 추가 재귀 계층은 문제가되지 않습니다.
Miff

@Miff 입력 해 주셔서 감사하지만 시도했지만 예상 결과가 나오지 않습니다.
Alex A.

1

K, 41 바이트

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

그거 알아봐! 보너스를하지 않습니다.


1

하스켈, 137136 바이트

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 버전이 아래에 있습니다.

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

두 가지 엄격한 비교를 사용하기 위해 중복이 없다는 사실을 이용하고 있습니다. Data.List.partitionimport 문을 추가해야한다고 생각하더라도 짧아지지 않는지 확인해야 합니다. Data.List.insert정렬 관련 함수로 간주 되어 삽입 금지 보너스를 사용하지 않으므로 금지합니다. 삽입 정렬을 추가하면 보너스와 함께 246 바이트, 209.1로 코드가 푸시되므로 가치가 없습니다.

편집 : 사용할 별칭을 만들라는 제안에 대해 RobAu에게 감사드립니다 f=filter. 1 바이트 만 절약 할 수 있지만 모든 것이 도움이됩니다.


1
f=filter일부 바이트를 깎을 수 있습니다.
RobAu

두 개의 중복 q$f(>n)lq$f(<n)l호출 을 처리하는 기능을 만들어 몇 바이트를 줄일 수 있습니까?
Cyoce

1

Tcl, 138 바이트

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

이것은 매우 표준적인 퀵 정렬입니다.

피벗은 단순히 각 하위 배열의 첫 번째 요소입니다 (이는 임의의 숫자라고 주장합니다. https://xkcd.com/221/ )

메모리 사용 측면에서 특히 효율적이지 않지만 tailcall두 번째 재귀와 n <1 요소의 기본 경우로 일부를 향상시킬 수 있습니다 .

다음은 읽을 수있는 버전입니다.

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

모든 입력에서 작동하며 중복을 허용합니다. 아, 그것은 또한 안정적 입니다. 다음과 같은 간단한 것으로 테스트 할 수 있습니다.

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

즐겨! :영형)


당신은 대체 바이트 저장할 수 있습니다 foreach에 의해 lmap
sergiol

1

자바 스크립트 (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

실론 (JVM 만) 183 170

보너스는 적용되지 않습니다.

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

Ceylon에서 임의의 숫자를 생성하는 크로스 플랫폼 방법이없는 것 같으므로 JVM 전용입니다. (결국 JS에서도 작동하며 더 작은 비 임의 버전이 있습니다.)

이 함수는 iterable의 float를 가져 와서 정렬 된 버전을 반환하는 함수를 정의합니다.

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

(사양에 대해) 중복 항목이 전달되면 해당 항목이 필터링됩니다.

183 바이트입니다. 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[];}}

새로운 (Ceylon 1.2) if표현식 을 사용하여 조금 개선 할 수 있습니다 .

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

이것은 170 바이트입니다. 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[];


다음은 비 랜덤 버전입니다.

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

공백이 없으면 107 바이트입니다. {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 바이트

이것은 매우 빠릅니다 (어쨌든 AutoIt의 경우). 삽입 정렬 보너스를받을 자격이 있습니다. 마지막 골프가 발생한 후 설명을 추가합니다.

입력은 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

무작위 테스트 입력 + 출력 :

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

흥미롭고 전에는 AutoIt에 대해 들어 본 적이 없습니다
Daniel M.

0

자바, 346 바이트

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

압축 코드 :

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

전체 코드 :

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

}

몇 가지 개선 사항 : 1. int []와 메소드 헤더에서 공백을 제거하십시오. 2. for 루프에서 변수에 마지막으로 액세스 한 위치를 늘리거나 줄입니다. 3. 새로운 int 대신 바이트를 사용하여 클래스를 int (또는 커플)로 만들어 바이트를 저장하십시오. 4. Math.random ()을 사용하고 임의 객체를 만드는 것보다 캐스팅이 짧을 수 있습니다.
Blue

0

수학, 93 90 바이트

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

보너스는 없습니다. 아직 삽입 정렬을 수행 할 수있는 최소한의 방법은 없습니다. 최근에 C ++을 배울 때 다양한 정렬 알고리즘을 여기 에서 비교 했습니다 .


0

Python2, 120 바이트

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:]길이는 정확 if len(a)>2하지만 더 골프처럼 보입니다.


0

루아, 242 바이트

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

라켓 121 바이트

(λ(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 (첫 번째 요소), t = tail (휴식 또는 나머지 요소)) :

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

테스트 :

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

산출:

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

0

Japt , 23 바이트

각 보너스는 총 점수에서 3 바이트 이하가되어야하므로 보너스를받지 않았습니다.

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.

온라인으로 사용해보십시오!


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.