Сортируй это, быстро!

27

Ну ... есть 59 (сейчас 60) вопросов с тегами , но нет простых быстрых сортировок.

Это должно быть исправлено.

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

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

правила

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

  • Реализуйте числовую быструю сортировку на выбранном вами языке программирования.
  • Точка должна быть выбрана случайным образом или с медианой из трех (1-й, последний и средний элемент).
  • Ваша программа может быть полной программой или функцией.
  • Вы можете получить ввод, используя STDIN, аргументы командной строки или параметры функции. Если используется строковый ввод, ввод разделяется пробелом.
  • Входные данные могут содержать десятичные и отрицательные значения. Однако дубликатов не будет.
  • Вы можете вывести на STDOUT или вернувшись из функции.
  • Нет встроенных функций сортировки (или связанных с сортировкой) или стандартных лазеек.
  • Список может быть произвольной длины.

Бонус # 1: В списках или подсписках длиной <= 5 используйте сортировку вставкой, чтобы немного ускорить процесс. Вознаграждение: -15%.

Бонус # 2: Если ваш язык поддерживает параллелизм, сортируйте список параллельно. Если вы используете сортировку вставки в подсписках, окончательная сортировка вставки не обязательно должна быть параллельной. Встроенные пулы потоков / планирование потоков разрешены. Вознаграждение: -15%.

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

выбирая медиану первого, среднего и последнего элемента раздела для оси

счет

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

Дело не в том, чтобы найти самый короткий ответ в целом, а скорее в самом коротком для каждого языка.

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

Таблица лидеров

Фрагмент стека в нижней части этого поста создает каталог из ответов а) в виде списка кратчайшего решения для каждого языка и б) в качестве общей таблицы лидеров.

Чтобы убедиться, что ваш ответ обнаружен, начните его с заголовка, используя следующий шаблон уценки:

## 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 также проблематичен и по другой причине - как только вы начинаете бросать кости, вы больше не пишете функцию. Вы определяете действие ввода / вывода, которое создает массив. Вы можете определить функцию, которая принимает состояние ГСЧ в качестве аргумента, но она также не слишком велика.
Джон Дворжак

Ответы:

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);
}
TheCoffeeCup
источник
5
Вы можете сохранить 10 байтов, используя одно буквенное имя вместо быстрой сортировки и удаляя пробелы в последнем вызове функции. Бьюсь об заклад, вы можете получить лучший результат, избегая бонусов (15% недостаточно)
edc65
1
Вы можете сохранить еще 5 байтов, заменив квадратные скобки аргументов одиночными звездочками. Я полагаю, что некоторая макро-магия может сбрить еще несколько байтов.
cadaniluk
2
Вам не нужно место после #include.
Лука
Избавьтесь от 34 байтов, удалив вызов. srand(time(NULL));Вы по-прежнему будете получать псевдослучайные числа rand().
Дутомас,
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 байт) благодаря 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)'.
Крис Джефферсон
Устранение стирания позволило мне сэкономить много байтов. Спасибо!
Линн
Еще один маленький вопрос: не нужно присваивать «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? Я не знаю, и уже слишком поздно, чтобы искать его.)
Линн,
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
Jakube
источник
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 байт благодаря Аарону.

Я впервые потрудился написать алгоритм сортировки. На самом деле это немного проще, чем я думал.

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 Я проверил это с кучей разных случаев и никогда не получал неправильный результат, но если вы можете найти тестовый случай, который ломает его, дайте мне знать. Кроме того, он может не работать с дубликатами, но в вызове указано, что дубликатов не будет.
Морган Трепп
Я бы подумал, что [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)));
}
Flávio Teixeira Продажа
источник
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]
daniero
источник
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которая принимает массив и возвращает массив. Условно не используется сортировка вставки, поэтому бонус не применяется.

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вместо 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 Спасибо за предложение. Я реализовал это и исправил проблему с помощью повторяющихся элементов.
Алекс А.
Я сказал, что это может быть проблемой, но я попросил у плаката с вопросом пояснение: «Входные данные могут содержать десятичные и отрицательные значения. Однако дубликатов не будет»
Глен О
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 Спасибо за ваш вклад, но я попробовал это, и он не дает ожидаемого результата для меня.
Алекс А.
1

К, 41 байт

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

ПРИНЯТЬ ЭТО, APL !!! Не делает никаких бонусов.

kirbyfan64sos
источник
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. Это может сохранить только один байт, но все помогает.

arjanen
источник
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]}

Это чрезвычайно стандартная быстрая сортировка.

Сводка - это просто первый элемент каждого подмассива (я утверждаю, что это случайное число. 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 {}
}

Наслаждайтесь! : О)

Dúthomhas
источник
Вы можете сохранить замену байтов 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>

edc65
источник
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[];}}

Мы можем немного улучшить, используя новое 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
mınxomaτ
источник
Интересно, никогда не слышал об AutoIt раньше
Даниэль М.
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;
    }

}
TheCoffeeCup
источник
Пара улучшений: 1. Избавьтесь от пробелов между int [] и a в заголовке метода. 2. Сделайте инкремент или декремент в цикле for последним местом доступа к переменной. 3. Создайте класс int (или пару) для сохранения байтов, используя его вместо нового int. 4. Использование Math.random () и приведение может быть короче, чем создание объекта 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

Луа, 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 & Объяснение

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                                                         #
Ataco
источник
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))))))

Необработанный (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)
rnso
источник
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.

Попробуйте онлайн!

гнида
источник
20 байтов
лохматый