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


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

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

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

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 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 !!! Не делает никаких бонусов.


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вызовов?
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

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

Мы можем немного улучшить, используя новое 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 раньше
Даниэль М.

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

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)

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.