Сортуйте це, швидко!


27

Ну ... є 59 (зараз 60) питань із тегами , але немає простих швидкості.

Це потрібно виправити.

Для незнайомих людей, які не знаходяться у стихій стихії , ось розбивка, люб’язно надана Wikipedia-

  1. Виберіть з масиву елемент, який називається стрижневим .
  2. Впорядкуйте масив так, щоб усі елементи зі значеннями меншими, ніж віссю, були до початку, тоді як усі елементи зі значеннями, що перевищують віссю, приходять після нього (рівні значення можуть йти в будь-якому напрямку). Після цього перегородки, шарнір знаходиться в остаточному положенні. Це називається операцією з розділенням.
  3. Рекурсивно застосовуйте вищезазначені етапи до підмасиву елементів із меншими значеннями та окремо до підмасиву елементів із більшими значеннями.

Правила

Правила прості:

  • Вкажіть числовий швидкохідний вибір у мові програмування на ваш вибір.
  • Сверток слід вибирати навмання або з медіаною з трьох (1-й, останній та середній елемент).
  • Ваша програма може бути повноцінною програмою або функцією.
  • Вхід можна отримати за допомогою STDIN, аргументів командного рядка або параметрів функції. Якщо використовується рядок, вхід розділено пробілом.
  • Вхід може містити десяткові та від’ємні значення. Однак дублікатів не буде.
  • Ви можете вивести в STDOUT або повернувшись із функції.
  • Немає вбудованих функцій сортування (або сортування), ані стандартних прорізів.
  • Список може бути довільної довжини.

Бонус №1: У списках або підсписах довжиною <= 5 використовуйте сортування вставок, щоб трохи прискорити роботу. Нагорода: -15%.

Бонус №2: Якщо ваша мова підтримує паралельність, сортуйте список паралельно. Якщо ви використовуєте сортування вставок у під-списках, остаточне сортування вставки не потрібно проводити паралельно. Вбудовані пули ниток / планування потоків дозволяється. Нагорода: -15%.

Примітка: Медіана з трьох людей бентежила деяких людей, тому ось пояснення, ввічливість (знову ж таки) Вікіпедії:

вибираючи серединку першого, середнього та останнього елемента перегородки для шарніра

Оцінка балів

Це . Базова оцінка в байтах. Якщо ви отримали один бонус, зніміть 15% від цього числа. Якщо у вас обох, зніміть 30%. Це дійсно звучить як крок продажів.

Йдеться не про те, щоб знайти найкоротшу відповідь загалом, а скоріше найкоротшу на кожній мові.

А тепер безсоромна копія фрагмента таблиць лідерів.

Таблиця лідерів

Фрагмент стека внизу цієї публікації генерує каталог з відповідей а) як список найкоротших варіантів для кожної мови та б) як загальний таблиця лідерів.

Щоб переконатися, що ваша відповідь відображається, будь ласка, почніть свою відповідь із заголовка, використовуючи наступний шаблон 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 виправлено зараз
Даніель М.

1
Чи є алгоритм середнього вибору важкою вимогою? Це непрактично (як, наприклад, він підбирає продуктивність) на мовах, які використовують зв'язаний список як основний тип масиву (Haskell, LISP), і вже є принаймні одна відповідь, яка ігнорує правило.
Джон Дворак

2
У мовах, що базуються на списку, проблематично як випадкове зведення, так і медіана з трьох. Обидва вимагають випадкового доступу до масиву, а доступ до кінця пов'язаного списку є O (n). Взяття медіани з перших трьох елементів не зовсім виконує однакову роботу (також тому, що ви захопите один і той же шар в межах трьох розщеплень) і лише ускладнює код без поважних причин.
Джон Дворак

1
Випадковий стрижень проблематичний в Haskell також з іншої причини - як тільки ви почнете катати кістки, ви більше не пишете функції. Ви визначаєте дію вводу-виводу, яка створює масив. Ви можете визначити функцію, яка приймає стан RNG як аргумент, але вона теж не надто велика.
Джон Дворак

Відповіді:


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←⍵[?⍴⍵]}

Це створює неназвану рекурсивну монадичну функцію, яка приймає масив праворуч. Він не має права на отримання премії.

Пояснення:

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

Спробуйте в Інтернеті

Виправлена ​​проблема (ціною 8 байт) завдяки марину та збережена 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;
}

Немає потреби в сранді (час (NULL)). Не потрібно видаляти, просто дозвольте розділити значення, а потім змінити 'if (a.empty ())' на 'if (a.size () <2)' та видалити 'lP (x)'.
Кріс Джефферсон

Усунення стирання дозволило мені зберегти багато байтів. Дякую!
Лінн

Ще один крихітний: Не потрібно призначати '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 байт (ймовірно, недійсний)

Я використовую метод "груповий", який використовує внутрішньо сортування. Я використовую його, щоб розділити оригінальний список на три підлісти (усі елементи менші за зріз, шарнір та всі елементи, що перевищують зрізний). Без сортування в "груповому порядку", він може повернути ці 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.

Збережено 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 Я перевірив це з купою різних справ і ніколи не отримав неправильного результату, але якщо ви зможете знайти тестовий випадок, який його порушує, дайте мені знати. Крім того, це може не працювати з дублікатами, але виклик визначає, що дублікатів не буде.
Морган Трапп

Я б подумав, що [2, 1, 3]це зламає 1/3 часу, тому що коли він вибере опорне значення 2, воно буде мати нижчий список [2, 1]- вибачте, що зараз не можу перевірити це.
VisualMelon

@VisualMelon Добре, звичайно, але потім рекурсивно сортує знову.
Морган Трапп

Ах, вибачте, пропустив це повністю, не зовсім так, як я б очікував, що буде запроваджено Quicksort - майте нагоду за те, що мене плутають
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, можливо, може скоротити це.
Нісса

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))])
Глен О

@GlenO Дякую за пропозицію. Я реалізував це і виправив проблему з повторними елементами.
Олексій А.

Я сказав, що це може бути проблемою, але я поцікавився плакатом запитань для уточнення, і "Вхід може містити десяткові та від'ємні значення. Однак дублікатів не буде"
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
    }
}

Спробуйте в Інтернеті

Збережено 4 байти завдяки флоделю!


Ви можете перекусити пару байтів, скинувши "> 1" з порівняння довжини. Це неявно порівнює його з 0, але додатковий шар рекурсії не є проблемою,
Miff

@Miff Дякую за ваш внесок, але я спробував це, і це не дає очікуваного результату для мене.
Олексій А.

1

К, 41 байт

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

ВІДПОВІСТЬ, APL !!! Жоден бонус не робить.


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

Тут нелінійна версія - з доданими розширеними назвами змінних та функцій та деякими проміжними результатами:

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викликів?
Кіос

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

Насолоджуйтесь! : 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

Цейлон (лише 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[];

Здається, немає взаємних платформних способів отримання випадкового числа на Цейлоні, тому це лише 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[];}}

Ми можемо трохи покращити, використовуючи новий (Цейлон 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

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. Зробіть приріст або зменшення в циклі for для останнього місця, до якого можна отримати доступ до змінної. 3. Зробіть клас int (або пару) для збереження байтів, використовуючи його замість нового int. 4. Використання Math.random () та лиття може бути коротшим, ніж створення об'єкта Random.
Блакитний

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

Необурені та пояснення

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

Unolfolf (l = список, h = голова (перший елемент), t = хвіст (решта або елементи, що залишилися)):

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

Спробуйте в Інтернеті!


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.