เรียงลำดับอย่างรวดเร็ว!


27

ดี ... มี 59 คำถาม (ตอนนี้ 60) ที่ติดแท็กแต่ไม่มีคำตอบง่าย ๆ

ที่จะต้องได้รับการแก้ไข

สำหรับผู้ที่ไม่คุ้นเคยกับquicksortนี่คือรายละเอียดความเอื้อเฟื้อของ Wikipedia-

  1. เลือกองค์ประกอบที่เรียกว่าpivotจากอาร์เรย์
  2. จัดลำดับอาร์เรย์ใหม่เพื่อให้องค์ประกอบทั้งหมดที่มีค่าน้อยกว่าเดือยมาก่อนหน้าเดือยในขณะที่องค์ประกอบทั้งหมดที่มีค่ามากกว่าเดือยมาหลังจากนั้น (ค่าเท่ากันสามารถไปทางใดทางหนึ่ง) หลังจากการแบ่งพาร์ติชันนี้เดือยจะอยู่ในตำแหน่งสุดท้าย สิ่งนี้เรียกว่าการดำเนินการพาร์ติชัน
  3. ใช้ขั้นตอนข้างต้นซ้ำกับองค์ประกอบย่อยที่มีค่าน้อยกว่าและแยกย่อยกับองค์ประกอบย่อยที่มีค่ามากกว่า

กฎระเบียบ

กฎง่าย ๆ :

  • ใช้ quicksort เชิงตัวเลขในภาษาการเขียนโปรแกรมที่คุณเลือก
  • เดือยควรจะเลือกโดยการสุ่มหรือกับค่ามัธยฐานของสาม (องค์ประกอบที่ 1, สุดท้ายและกลาง)
  • โปรแกรมของคุณอาจเป็นโปรแกรมหรือฟังก์ชั่นที่สมบูรณ์
  • คุณสามารถรับอินพุตโดยใช้ STDIN, บรรทัดคำสั่งหรือพารามิเตอร์ฟังก์ชัน หากใช้อินพุตสตริงอินพุตจะถูกคั่นด้วยช่องว่าง
  • อินพุตอาจมีค่าทศนิยมและค่าลบ อย่างไรก็ตามจะไม่มีการซ้ำซ้อน
  • คุณอาจส่งออกไปยัง STDOUT หรือโดยกลับมาจากฟังก์ชั่น
  • ไม่มีฟังก์ชั่นการเรียงลำดับ (หรือการเรียงลำดับที่เกี่ยวข้อง) ในตัวหรือช่องโหว่มาตรฐาน
  • รายการอาจมีความยาวโดยพลการ

โบนัส # 1: ในรายการหรือรายการย่อยที่มีความยาว <= 5 ให้ใช้การเรียงลำดับการแทรกเพื่อเร่งความเร็วให้เร็วขึ้น รางวัล: -15%

โบนัส # 2: หากภาษาของคุณรองรับการทำงานพร้อมกันให้เรียงลำดับรายการแบบขนาน หากคุณใช้การเรียงลำดับการแทรกในรายการย่อยการเรียงลำดับการแทรกสุดท้ายไม่จำเป็นต้องเป็นแบบขนาน บิวด์พูลในตัว / การกำหนดเวลาเธรดได้รับอนุญาต รางวัล: -15%

หมายเหตุ: ค่ามัธยฐานของสามกำลังสับสนบางคนดังนั้นนี่คือคำอธิบายความอนุเคราะห์จาก (อีกครั้ง) Wikipedia:

เลือกค่ามัธยฐานขององค์ประกอบแรกกลางและสุดท้ายของพาร์ติชันสำหรับเดือย

เกณฑ์การให้คะแนน

นี่คือรหัสกอล์ฟคะแนนฐานเป็นไบต์ หากคุณได้รับหนึ่งโบนัสให้ลด 15% หากคุณทั้งคู่ได้รับส่วนลด 30% นั่นฟังดูคล้ายกับยอดขาย

นี่ไม่เกี่ยวกับการหาคำตอบที่สั้นที่สุดโดยรวม แต่จะสั้นที่สุดในแต่ละภาษา

และในตอนนี้ข้อมูลโค้ดลีดเดอร์บอร์ดที่ไร้ยางอาย

กระดานผู้นำ

สแต็คส่วนย่อยที่ด้านล่างของโพสต์นี้สร้างแคตตาล็อกจากคำตอบ a) เป็นรายการคำตอบสั้นที่สุดต่อภาษาและ b) เป็นลีดเดอร์บอร์ดโดยรวม

เพื่อให้แน่ใจว่าคำตอบของคุณปรากฏขึ้นโปรดเริ่มคำตอบด้วยหัวข้อโดยใช้เทมเพลต Markdown ต่อไปนี้:

## 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
"เดือยควรถูกเลือกโดยการสุ่มหรือค่ามัธยฐานของสาม (องค์ประกอบที่ 1, สุดท้ายและตรงกลาง)" สิ่งนี้หมายความว่า? ก่อนหน้านี้คุณเคยกล่าวว่ามีเพียงองค์ประกอบเดียวที่ถูกเลือก
msh210

2
@daniero Snippet ได้รับการแก้ไขแล้ว
Daniel M.

1
อัลกอริทึมตัวเลือกค่ามัธยฐานเป็นข้อกำหนดที่ยากหรือไม่? มันไม่สามารถใช้งานได้ (ในขณะนั้นเป็นการเก็บข้อมูลประสิทธิภาพการทำงาน) ในภาษาที่ใช้รายการที่เชื่อมโยงเป็นประเภทอาเรย์หลัก (Haskell, LISP) และมีคำตอบอย่างน้อยหนึ่งคำตอบที่ไม่สนใจกฎ
John Dvorak

2
ทั้ง pivot สุ่มและค่ามัธยฐานของสามมีปัญหาในภาษาตามรายการ ทั้งสองต้องการการเข้าถึงแบบสุ่มในอาร์เรย์และการเข้าถึงจุดสิ้นสุดของรายการที่เชื่อมโยงคือ O (n) การรับค่ามัธยฐานขององค์ประกอบสามตัวแรกนั้นค่อนข้างไม่เหมือนกัน (เพราะคุณจะคว้าเดือยที่เหมือนกันภายในสามแยกต่อไป) และทำให้รหัสนั้นซับซ้อนเท่านั้นโดยไม่มีเหตุผลที่ดี
John Dvorak

1
การหมุนแบบสุ่มเป็นปัญหาใน Haskell ด้วยเหตุผลอื่นเช่นกัน - เมื่อคุณเริ่มหมุนลูกเต๋าคุณจะไม่เขียนฟังก์ชันอีกต่อไป คุณกำลังกำหนดการกระทำของ 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

ขอบคุณ @Luke สำหรับการบันทึก 3 ไบต์ (2 จริงๆ)

ขอบคุณ @ Dúthomhasที่ประหยัด 18 (15 จริงๆ) ไบต์

โปรดทราบว่าฉันใหม่ที่นี่และนี่คือโพสต์แรกของฉัน

นี่คือ.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
คุณสามารถบันทึก 10 ไบต์โดยใช้ชื่อตัวอักษรเดียวแทน quickSort และลบช่องว่างในการเรียกใช้ฟังก์ชันล่าสุด และฉันพนันได้เลยว่าคุณจะได้รับคะแนนที่ดีขึ้นหลีกเลี่ยงโบนัส (15% ไม่เพียงพอ)
edc65

1
คุณสามารถบันทึกอีก 5 ไบต์โดยแทนที่วงเล็บเหลี่ยมของอาร์กิวเมนต์ด้วยเครื่องหมายดอกจันเดี่ยว ฉันคาดว่าเวทย์มนตร์มาโครบางตัวจะสามารถตัดทิ้งได้อีก
cadaniluk

2
คุณไม่ต้องการช่องว่างหลังจาก#includeนั้น
ลุค

กำจัด 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

ลองออนไลน์

แก้ไขปัญหา (ที่ราคา 8 ไบต์) ขอบคุณ marinus และบันทึก 7 ไบต์ขอบคุณ Thomas Kwa!


คำถามระบุว่าจะไม่มีการทำซ้ำ (ไม่รู้ว่ามันใช้เวลานานเท่าไหร่ที่ฉันจะเห็นว่า ... )
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 (เวลา (NULL)) ไม่ต้องการลบเพียงแค่ปล่อยให้ค่าถูกแบ่งพาร์ติชันแล้วเปลี่ยน 'if (a.empty ())' เป็น 'if (a.size () <2)' และลบ 'lP (x)'
Chris Jefferson

การกำจัดการลบทำให้ฉันสามารถบันทึกจำนวนมากได้ ขอขอบคุณ!
ลินน์

อีกอันจิ๋วหนึ่ง: ไม่จำเป็นต้องกำหนด 'r = q (r)' เพียงใช้ 'สำหรับ (y: q (r))' แต่นั่นคือทั้งหมดที่ฉันเห็น!
Chris Jefferson

เพิ่งมาจากความอยากรู้: 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 ไบต์ (อาจไม่ถูกต้อง)

ฉันใช้วิธี "จัดกลุ่มตาม" ซึ่งใช้การเรียงลำดับภายใน ฉันใช้มันเพื่อแยกรายการดั้งเดิมออกเป็นสามรายการย่อย (องค์ประกอบทั้งหมดเล็กกว่า pivot, pivot และองค์ประกอบทั้งหมดที่ใหญ่กว่า pivot) หากไม่มีการเรียงลำดับใน "จัดกลุ่มตาม" ก็สามารถส่งคืน 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

Python 3, 123 , 122

บันทึก 1 ไบต์ขอบคุณ Aaron

นี่เป็นครั้งแรกที่ฉันใส่ใจที่จะเขียนอัลกอริทึมการเรียงลำดับ จริงๆแล้วมันง่ายกว่าที่คิดนิดหน่อย

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)

ดูเหมือนว่ามันอาจจะไม่ได้ผลเนื่องจากการ<=เปรียบเทียบ - ไม่รับประกันว่าpอยู่ในที่ที่ถูกต้องคุณอาจต้องเปลี่ยนมันให้เป็นอสมการแบบเอกสิทธิ์และเพิ่มpตรงกลางด้วยตนเอง (ฉันไม่ได้ทดสอบ / สามารถ ไม่ทดสอบรหัส)
VisualMelon

@VisualMelon ฉันทดสอบกับกรณีที่แตกต่างกันและไม่เคยได้รับผลที่ไม่ถูกต้อง แต่ถ้าคุณสามารถหากรณีทดสอบที่ทำลายมันได้โปรดแจ้งให้เราทราบ นอกจากนี้อาจใช้งานไม่ได้กับการซ้ำซ้อน แต่ความท้าทายระบุว่าจะไม่ซ้ำซ้อน
Morgan Thrapp

ฉันคิดว่า[2, 1, 3]มันจะทำลายมัน 1/3 ของเวลาเพราะเมื่อมันเลือกเดือยให้เป็น 2 มันจะมีลิสต์ต่ำ[2, 1]- ฉันขอโทษที่ฉันไม่สามารถทดสอบตัวเองได้ในตอนนี้
VisualMelon

@VisualMelon เอาล่ะแน่นอน แต่มันก็เรียงลำดับซ้ำอีกครั้ง
Morgan Thrapp

อาขอโทษพลาดอย่างสมบูรณ์ไม่ใช่วิธีที่ฉันคาดหวังว่าจะใช้งาน Quicksort - มี upvote ที่ทำให้ฉันสับสน
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)));}

คำอธิบาย

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

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

ทดสอบ:

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 76ไบต์

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

Julia, 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ที่ยอมรับอาร์เรย์และส่งกลับอาร์เรย์ มันไม่ได้ใช้การเรียงลำดับการแทรกตามเงื่อนไขดังนั้นจึงไม่มีโบนัส

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

แก้ไขปัญหาและบันทึกบางไบต์ด้วย Glen O!


ปัญหาที่เป็นไปได้กับการสูญเสียขององค์ประกอบซ้ำ (ซึ่งมีอยู่แล้วในรหัสของคุณ) กันคุณสามารถบันทึกไม่กี่ไบต์ที่นี่โดยการกำหนดfเมื่อคุณใช้งานครั้งแรกfilterและการใช้แทนendof lengthQ(x)=endof(x)<2?x:(p=rand(x);[Q((f=filter)(i->i<p,x));p;Q(f(i->i>p,x))])
เกลน O

@GlenO ขอบคุณสำหรับคำแนะนำ ฉันได้ดำเนินการแล้วและแก้ไขปัญหาด้วยองค์ประกอบที่ทำซ้ำ
Alex A.

ฉันบอกว่ามันอาจเป็นปัญหา แต่ฉันถามผู้โพสต์คำถามเพื่อความกระจ่างและ "อินพุตอาจมีค่าทศนิยมและค่าลบอย่างไรก็ตามจะไม่มีการซ้ำซ้อน"
เกลน 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ที่ยอมรับเวกเตอร์และส่งคืนเวกเตอร์ มันไม่ได้ใช้การเรียงลำดับการแทรกตามเงื่อนไขดังนั้นจึงไม่มีโบนัส

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

ลองออนไลน์

บันทึกแล้ว 4 ไบต์ด้วย flodel!


คุณสามารถตอดสองสามไบต์ได้โดยปล่อย "> 1" จากการเปรียบเทียบความยาว สิ่งนี้เป็นการเปรียบเทียบโดยนัยกับ 0 แต่การเรียกซ้ำอีกชั้นหนึ่งไม่ใช่ปัญหา
Miff

@Miff ขอบคุณสำหรับการป้อนข้อมูลของคุณ แต่ฉันลองแล้วมันไม่ได้ผลตามที่คาดหวังไว้สำหรับฉัน
Alex A.


1

Haskell, 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.partitionว่าไม่ได้ทำให้สั้นลงแม้ว่าจะต้องเพิ่มงบการนำเข้า ฉันไม่ได้รับโบนัสการจัดเรียงการแทรกเพราะฉันคิดData.List.insertว่าเป็นฟังก์ชั่นที่เกี่ยวข้องกับการเรียงลำดับ - ซึ่งเป็นสิ่งต้องห้าม - และหากไม่ได้ใช้งานการเพิ่มการเรียงลำดับการแทรกจะผลักรหัสไปที่ 246 ไบต์และ 209.1 ด้วยโบนัส

แก้ไข:ขอบคุณที่ RobAu f=filterสำหรับข้อเสนอแนะของพวกเขาในการสร้างนามแฝงกับการใช้ มันอาจบันทึกเพียงหนึ่งไบต์ แต่ทุกอย่างช่วย


1
f=filterอาจโกนหนวดออกเป็นบางไบต์
RobAu

บางทีคุณสามารถโกนหนวดได้สองสามไบต์โดยการทำฟังก์ชั่นเพื่อจัดการกับทั้งสองซ้ำซ้อนq$f(>n)lและการq$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]}

นี่คือ quicksort มาตรฐานที่มากเกินไป

เดือยเป็นเพียงองค์ประกอบแรกของแต่ละ subarray (ฉันยืนยันว่านี่เป็นตัวเลขสุ่ม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 {}
}

สนุก! O):


คุณสามารถบันทึกไบต์แทนที่foreachด้วย 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 (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 ด้วยและมีขนาดเล็กกว่า)

สิ่งนี้จะกำหนดฟังก์ชั่นที่ใช้ท่วงท่าซ้ำ ๆ ของมันและคืนค่าเวอร์ชั่นที่เรียงไว้

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

เราสามารถปรับปรุงได้เล็กน้อยโดยใช้ifนิพจน์ใหม่ (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 [];

นี่คือ 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

Java, 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 [] และ a ในส่วนหัวของเมธอด 2. ทำให้การเพิ่มหรือลดในห่วงสำหรับสถานที่สุดท้ายที่ตัวแปรเข้าถึง 3. สร้างคลาส int (หรือคู่) เพื่อบันทึกไบต์โดยใช้แทน int ใหม่ 4. การใช้ Math.random () และการคัดเลือกอาจจะสั้นกว่าการสร้างออบเจ็กต์แบบสุ่ม
Blue

0

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

Lua 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 ไบต์

โบนัสแต่ละอย่างจะต้องมีสามไบต์หรือน้อยกว่าเพื่อจ่ายเป็นคะแนนรวมดังนั้นฉันจึงไม่ได้รับโบนัสใด ๆ

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.