Classifique isso, rápido!


27

Bem ... existem 59 (agora 60) perguntas com a tag , mas não há quicksorts simples.

Isso deve ser consertado.

Para aqueles que não estão familiarizados com o quicksort , aqui está um detalhamento, cortesia da Wikipedia-

  1. Escolha um elemento, chamado de pivô , da matriz.
  2. Reordene a matriz para que todos os elementos com valores menores que o pivô venham antes do pivô, enquanto todos os elementos com valores maiores que o pivô venham depois dele (valores iguais podem ser usados ​​de qualquer maneira). Após essa partição, o pivô está em sua posição final. Isso é chamado de operação de partição.
  3. Aplique recursivamente as etapas acima ao subconjunto de elementos com valores menores e separadamente ao subconjunto de elementos com valores maiores.

Regras

As regras são simples:

  • Implemente um quicksort numérico na linguagem de programação de sua escolha.
  • O pivô deve ser escolhido aleatoriamente ou com mediana de três (1º, último e médio elemento).
  • Seu programa pode ser um programa ou função completa.
  • Você pode obter a entrada usando STDIN, argumentos de linha de comando ou parâmetros de função. Se estiver usando uma entrada de sequência, a entrada será separada por espaço.
  • A entrada pode conter valores decimais e negativos. No entanto, não haverá duplicatas.
  • Você pode enviar para STDOUT ou retornando da função.
  • Nenhuma função de classificação interna (ou relacionada à classificação) ou brechas padrão.
  • A lista pode ter um comprimento arbitrário.

Bônus nº 1: em listas ou sub-listas de comprimento <= 5, use a classificação por inserção para acelerar um pouco as coisas. Recompensa: -15%.

Bônus # 2: se o seu idioma suportar simultaneidade, classifique a lista em paralelo. Se você estiver usando uma classificação de inserção em sub-listas, a classificação final de inserção não precisará ser paralela. Pools de encadeamentos embutidos / agendamento de encadeamentos são permitidos. Recompensa: -15%.

Nota: A mediana de três estava confundindo algumas pessoas, então aqui está uma explicação, cortesia da (novamente) Wikipedia:

escolhendo a mediana do primeiro, meio e último elemento da partição para o pivô

Pontuação

Isso é . A pontuação base está em bytes. Se você recebeu um bônus, retire 15% desse número. Se você tiver os dois, tire 30% de desconto. Isso realmente soa como um discurso de vendas.

Não se trata de encontrar a resposta mais curta em geral, mas a mais curta em cada idioma.

E agora, uma cópia sem vergonha do snippet da tabela de classificação.

The Leaderboard

O snippet de pilha na parte inferior desta postagem gera o catálogo a partir das respostas a) como uma lista da solução mais curta por idioma eb) como uma tabela geral de líderes.

Para garantir que sua resposta seja exibida, inicie-a com um título, usando o seguinte modelo de remarcação:

## Language Name, N bytes

onde N é o tamanho do seu envio. Se você melhorar sua pontuação, poderá manter as pontuações antigas no título, identificando-as. Por exemplo:

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

Se você quiser incluir vários números no cabeçalho (por exemplo, porque sua pontuação é a soma de dois arquivos ou você deseja listar as penalidades do sinalizador de intérpretes separadamente), verifique se a pontuação real é o último número no cabeçalho:

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

Você também pode transformar o nome do idioma em um link que será exibido no snippet:

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


4
"O pivô deve ser escolhido aleatoriamente ou com mediana de três (1º, último e médio elemento)." O que isto significa? Você disse anteriormente que apenas um elemento é escolhido.
Msh210 #

2
@daniero O snippet foi corrigido agora
Daniel M.

1
O algoritmo de escolha mediana é um requisito difícil? É impraticável (por exemplo, ele libera o desempenho) em idiomas que usam uma lista vinculada como seu tipo de matriz principal (Haskell, LISP) e já existe pelo menos uma resposta que ignora a regra.
John Dvorak

2
O pivô aleatório e a mediana de três são problemáticos em idiomas baseados em lista. Ambos requerem acesso aleatório à matriz e o acesso ao final de uma lista vinculada é O (n). Pegar A mediana dos três primeiros elementos não faz exatamente o mesmo tipo de trabalho (também porque você pega o mesmo pivô em três divisões de qualquer maneira) e apenas complica o código sem um bom motivo.
John Dvorak

1
O pivô aleatório também é problemático em Haskell por outro motivo - quando você começa a rolar dados, não está mais escrevendo uma função. Você está definindo uma ação de E / S que produz uma matriz. Você pode definir uma função que usa um estado RNG como argumento, mas também não é muito bom.
John Dvorak

Respostas:


10

C ++, 440,3 405 388 bytes

518 bytes - bônus de 15% para classificação de inserção = 440,3 bytes

477 bytes - bônus de 15% para classificação de inserção = 405,45 bytes

474 bytes - bônus de 15% para classificação de inserção = 402,9 bytes

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

Agradecemos ao @Luke por salvar 3 bytes (2 realmente).

Obrigado a @ Dúthomhas por salvar 18 (15 realmente) bytes.

Note que eu sou novo aqui e este é o meu primeiro post.

Este é um .harquivo (cabeçalho).

Código compactado:

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

Código completo:

#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
Você pode salvar 10 bytes usando um nome de letra única em vez de quickSort e removendo espaços na última chamada de função. E eu aposto que você pode obter uma melhor pontuação evitando o bônus (15% não é suficiente)
edc65

1
Você pode salvar outros 5 bytes substituindo os colchetes dos argumentos por asteriscos únicos. Alguma mágica macro poderia cortar mais alguns bytes, eu acho.
#

2
Você não precisa de um espaço depois #include.
Lucas

Livre-se de 34 bytes removendo a chamada para srand(time(NULL));Você ainda receberá números pseudo-aleatórios rand().
Dúthomhas 28/03

9

APL, 49 42 bytes

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

Isso cria uma função monádica recursiva sem nome que aceita uma matriz à direita. Não se qualifica para o bônus.

Explicação:

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

Experimente online

Corrigido um problema (ao custo de 8 bytes) graças ao marinus e salvou 7 bytes graças ao Thomas Kwa!


A pergunta especifica que não haverá duplicatas. (Não sei como ele me levou tanto tempo para ver que ...)
lirtosiast

5

C ++ 17, 254 199 195 bytes

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

Com espaço em branco:

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

Não há necessidade de srand (hora (NULL)). Não é necessário apagar, apenas deixe o valor ser particionado, altere 'if (a.empty ())' para 'if (a.size () <2)' e remova 'lP (x)'.
Chris Jefferson

Eliminar a exclusão me permitiu economizar muitos bytes. Obrigado!
Lynn

Um outro pequeno: Não há necessidade de atribuir 'r = q (r)', basta usar 'for (y: q (r))', mas é tudo o que posso ver!
Chris Jefferson

Apenas por curiosidade: onde o C ++ 17 é usado aqui em particular?
Kirbyfan64sos #

1
for (y : a)caso contrário, precisaria ser for (auto y : a)ou for (int y : a). (Na verdade, clang++chama isso de extensão C ++ 1z , mas realmente não parece ser C ++ 17? Eu não sei, e é tarde da noite para procurá-lo.)
Lynn

4

Pitão, 25 bytes

L?tbsyMa_,]JObf<TJbf>TJbb

Isso define uma função y, que recebe uma lista de números como entrada.

Experimente online: Demonstração

Explicação

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

Pitão, 21 bytes (provavelmente inválido)

Eu uso o método "agrupar por", que usa internamente uma classificação. Eu o uso para dividir a lista original em três sublistas (todos os elementos menores que o pivô, o pivô e todos os elementos maiores que o pivô). Sem a classificação em "agrupar por", ele poderia retornar essas 3 listas em uma ordem diferente.

Como dito, isso provavelmente é inválido. No entanto, vou mantê-lo aqui, porque é uma solução interessante.

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

Experimente online: Demonstração

Explicação

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

> <> (FISH), 313 309 bytes

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

Demorei muito para escrever. Você pode tentar aqui , basta colocar a lista que deve ser classificada na pilha inicial, separada por vírgulas, antes de executar o programa.

Como funciona

O programa pega o primeiro, o meio e o último elemento na pilha inicial e calcula a mediana desses três.
Em seguida, altera a pilha para:

elemento [lista 1] [lista 2]

onde tudo na lista 1 é menor ou igual ao elemento e tudo na lista 2 é maior.
Repete recursivamente esse processo na lista 1 e na lista 2 até que toda a lista seja classificada.


2

CJam, 40 bytes

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

Essa é uma função nomeada que espera uma matriz na pilha e envia uma em retorno.

Experimente on-line no intérprete CJam .

O código acima segue as especificações o mais próximo possível. Se isso não for necessário, 12 bytes podem ser salvos:

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

2

Python 3, 123 , 122.

Guardado 1 byte graças a Aaron.

Esta é a primeira vez que me preocupo em escrever um algoritmo de classificação. Na verdade, é um pouco mais fácil do que eu pensava.

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)

Parece que pode não funcionar, devido à <=comparação - não garante que pesteja no lugar certo, você provavelmente precisará mudar isso para uma desigualdade exclusiva e adicionar pno meio de forma independente (eu não testei / posso teste o código).
VisualMelon

@VisualMelon Testei-o com vários casos diferentes e nunca obtive um resultado incorreto, mas se você encontrar um caso de teste que o interrompa, avise-me. Além disso, pode não funcionar com duplicatas, mas o desafio especifica que não haverá duplicatas.
Morgan Thrapp

Eu teria pensado que isso [2, 1, 3]iria quebrá-lo em 1/3 do tempo, pois quando ele seleciona o pivô para 2, a lista é baixa [2, 1]- desculpe-me por não poder testar isso agora.
VisualMelon

@VisualMelon Bem, claro, mas depois recursivamente classifica novamente.
Morgan Thrapp

Ah, desculpe, perdi isso completamente, não é bem como eu esperaria um Quicksort a ser implementado - têm um upvote para me confundindo
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)));}

Explicação

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

O ES6 provavelmente poderia reduzir isso.
Nissa

1

Rubi, 87 60 bytes

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

Teste:

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

Oitava, 76 75 bytes

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

Versão multilinhas:

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

1

Julia, 83 bytes

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

Isso cria uma função recursiva Qque aceita uma matriz e retorna uma matriz. Ele não usa condicionalmente a classificação por inserção, portanto, nenhum bônus se aplica.

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

Foi corrigido um problema e salvou alguns bytes graças ao Glen O!


Possíveis problemas com a perda de elementos de repetição (que já existem no seu código), você pode salvar alguns bytes aqui atribuindo fquando usar pela primeira vez filtere usando em endofvez de length. Q(x)=endof(x)<2?x:(p=rand(x);[Q((f=filter)(i->i<p,x));p;Q(f(i->i>p,x))])
Glen O

@GlenO Obrigado pela sugestão. Eu implementei isso e resolvi o problema com elementos repetidos.
Alex A.

Eu disse que poderia ser um problema, mas pedi esclarecimentos ao pôster da pergunta e "A entrada pode conter valores decimais e negativos. No entanto, não haverá duplicatas"
Glen O

1

R, 78 bytes

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

Isso cria uma função recursiva Qque aceita um vetor e retorna um vetor. Não aplica condicionalmente a classificação de inserção, portanto, não há bônus.

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

Experimente online

Economizou 4 bytes graças ao flodel!


Você pode morder alguns bytes largando o "> 1" na comparação de comprimento. Isso implicitamente o compara a 0, mas uma camada extra de recursão não é um problema, #
1170 Miff

@Miff Obrigado pela sua contribuição, mas eu tentei isso e não produz o resultado esperado para mim.
Alex A.

1

K, 41 bytes

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

Tome isso, APL !!! Não faz nenhum dos bônus.


1

Haskell, 137136 bytes

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

A versão ungolfed está abaixo, com nomes expandidos de variáveis ​​e funções e alguns resultados intermediários adicionados:

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

Estou aproveitando o fato de que não há duplicatas para usar duas comparações estritas. Vou ter que verificar se Data.List.partitionisso não torna as coisas mais curtas, mesmo considerando que eu teria que adicionar uma declaração de importação. Não estou aceitando o bônus de classificação de inserção porque considero Data.List.insertuma função relacionada à classificação - portanto, proibida - e, se não a estiver usando, adicionar a classificação de inserção leva o código a 246 bytes, 209,1 com o bônus, por isso não vale a pena.

Edit: Obrigado ao RobAu por sua sugestão de criar um alias para usar f=filter. Pode economizar apenas um byte, mas tudo ajuda.


1
f=filterpode cortar alguns bytes.
26416 RobAu

Talvez você possa raspar alguns bytes criando uma função para lidar com as duas chamadas redundantes q$f(>n)le q$f(<n)l?
Cyoce 28/03

1

Tcl, 138 bytes

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

Este é um quicksort extremamente padrão.

O pivô é simplesmente o primeiro elemento de cada sub-matriz (eu afirmo que este é um número aleatório. Https://xkcd.com/221/ )

Não é particularmente eficiente em termos de uso de memória, embora possa ser melhorado com tailcalla segunda recursão e um caso base de n <1 elementos.

Aqui está a versão legível:

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

Funciona em todas as entradas e permite duplicatas. Oh, também é estável . Você pode testá-lo com algo simples, como:

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

Apreciar! : O)


Você pode salvar bytes substituindo foreachpor 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

Ceilão (apenas JVM), 183 170

Nenhum bônus se aplica.

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

Parece que não há uma maneira multiplataforma de produzir um número aleatório no Ceilão, portanto, isso é apenas JVM. (No final, tenho uma versão não aleatória que também funciona em JS e é menor.)

Isso define uma função que pega uma iterável de flutuadores e retorna uma versão classificada dela.

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

Se (contra a especificação) entradas duplicadas forem passadas, essas serão filtradas.

São 183 bytes: 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[];}}

Podemos melhorar um pouco usando a nova ifexpressão (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 [];

São 170 bytes: 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[];


Aqui está uma versão não aleatória:

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

Sem espaços, isso seria 107 bytes: {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 bytes

Isso é bastante rápido (para o AutoIt de qualquer maneira). Qualifica-se para o bônus de ordenação por inserção. Acrescentará explicação após a ocorrência do golfe final.

Entrada é 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

Entrada + saída de teste aleatório:

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

Interessante, nunca ouvi falar em AutoIt antes
Daniel M.

0

Java, 346 bytes

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

Código compactado:

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

Código completo:

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

}

Algumas melhorias: 1. Livre-se dos espaços entre int [] e a no cabeçalho do método. 2. Faça o incremento ou decremento em um loop for o último local em que uma variável é acessada. 3. Crie uma classe int (ou duas) para salvar bytes usando-a em vez de uma nova int. 4. O uso de Math.random () e a conversão podem ser mais curtos do que criar um objeto Aleatório.
Azul

0

Mathematica, 93 90 bytes

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

Sem bônus, ainda não há uma maneira mínima de classificar a inserção. Quando eu estava aprendendo C ++ recentemente, fiz uma comparação de vários algoritmos de classificação aqui .


0

Python2, 120 bytes

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:]é exatamente enquanto, if len(a)>2mas parece mais jogado.


0

Lua, 242 bytes

function f(t,p)if(#t>0)then local P,l,r,i=math.random(#t),{},{},table.insert p=t[P]for k,v in ipairs(t)do if(k~=P)then i(v<p and l or r,v)end end t={}for k,v in pairs(f(l))do i(t,v)end i(t,p)for k,v in pairs(f(r))do i(t,v)end end return t end

Ungolfed & Explination

function f(t,p)                                             # Assign 'p' here, which saves two bytes, because we can't assign it to t[P] IN the local group.
    if(#t>0)then                                            # Just return 0 length lists...
        local P,l,r,i=math.random(#t),{},{},table.insert    # Using local here actually makes the a,b=1,2 method more efficient here. Which is unnormal for Lua
        p = t[P]                                            # P is the index of the pivot, p is the value of the pivot, l and r are the sub-lists around the pivot, and i is table.insert to save bytes.
        for k,v in ipairs(t) do                             # We use a completely random pivot, because it's cheaper on the bytes.
            if(k~=P)then                                    # Avoid 'sorting' the pivot.
                i(v<p and l or r,v)                         # If the value is less than the pivot value, push it to the left list, otherwise, push it to the right list.
            end                                             #
        end                                                 #
        t = {}                                              # We can re-use t here, because we don't need it anymore, and it's already a local value. Saving bytes!
        for k,v in pairs(f(l)) do                           # Quick sort the left list, then append it to the new output list.
            i(t,v)                                          #
        end                                                 #
        i(t,p)                                              # Append the pivot value.
        for k,v in pairs(f(r)) do                           # Ditto the right list.
            i(t,v)                                          #
        end                                                 #
    end                                                     #
    return t                                                # Return...
end                                                         #

0

Raquete 121 bytes

(λ(l)(if(null? l)l(let((h(car l))(t(cdr l)))(append(qs (filter(λ(x)(< x h))t))(list h)(qs (filter(λ(x)(>= x h))t))))))

Ungolfed (l = lista, h = cabeça (primeiro elemento), t = cauda (elementos restantes ou restantes)):

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

Teste:

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

Saída:

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

0

Japonês , 23 bytes

Cada bônus precisaria ter três bytes ou menos para compensar a pontuação total, por isso não recebi nenhum bônus.

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.

Experimente online!


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.