[ Última atualização: programa de benchmark e resultados preliminares disponíveis, veja abaixo]
Então, eu quero testar a relação velocidade / complexidade com um aplicativo clássico: classificação.
Escreva uma função ANSI C que classifique uma matriz de números de ponto flutuante em ordem crescente .
Você não pode usar nenhuma biblioteca, chamada de sistema, multithreading ou ASM embutido.
Entradas julgadas em dois componentes: comprimento e desempenho do código . Com a seguinte pontuação: as entradas serão classificadas por tamanho (log de # caracteres sem espaço em branco, para que você possa manter alguma formatação) e desempenho (log de # segundos sobre uma referência) e cada intervalo [melhor, pior] normalizado linearmente para [ 0,1] A pontuação total de um programa será a média das duas pontuações normalizadas. Menor pontuação ganha. Uma entrada por usuário.
A classificação precisará (eventualmente) estar em vigor (ou seja, a matriz de entrada deverá conter valores classificados no tempo de retorno) e você deverá usar a seguinte assinatura, incluindo nomes:
void sort(float* v, int n) {
}
Caracteres a serem contados: aqueles na sort
função, assinatura incluída, além de funções adicionais chamadas por ela (mas não incluindo o código de teste).
O programa deve manipular qualquer valor numérico float
e matrizes de comprimento> = 0, até 2 ^ 20.
Vou conectar sort
e suas dependências em um programa de testes e compilar no GCC (sem opções sofisticadas). Vou alimentar várias matrizes, verificar a exatidão dos resultados e o tempo total de execução. Os testes serão executados em um Intel Core i7 740QM (Clarksfield) no Ubuntu 13. Os
comprimentos dos arrays abrangerão todo o intervalo permitido, com uma densidade mais alta de arrays curtos. Os valores serão aleatórios, com uma distribuição de cauda gorda (tanto na faixa positiva quanto na negativa). Elementos duplicados serão incluídos em alguns testes.
O programa de teste está disponível aqui: https://gist.github.com/anonymous/82386fa028f6534af263
Ele importa o envio como user.c
. O número de casos de teste ( TEST_COUNT
) no benchmark real será 3000. Por favor, forneça algum feedback nos comentários da pergunta.
Prazo: 3 semanas (7 de abril de 2014, 16:00 GMT). Vou postar o benchmark em 2 semanas.
Pode ser aconselhável postar perto do prazo, para evitar que seu código seja entregue aos concorrentes.
Resultados preliminares, a partir da publicação do benchmark:
Aqui estão alguns resultados. A última coluna mostra a pontuação como porcentagem, quanto maior, melhor, colocando Johnny Cage em primeiro lugar. Algoritmos com ordens de magnitude mais lentas que o restante foram executados em um subconjunto de testes e o tempo extrapolado. O próprio C qsort
está incluído para comparação (o Johnny é mais rápido!). Vou fazer uma comparação final na hora do fechamento.
fonte
Respostas:
150 caracteres
Ordenação rápida.
Comprimido.
fonte
150 caracteres (sem espaços em branco)
fonte
if(*w<*v) { t=v[++l]; v[l]=*w; *w=t; }
pode serif(*w<*v) t=v[++l], v[l]=*w, *w=t;
67 7069 caracteresNão é rápido, mas incrivelmente pequeno. É um híbrido entre um algoritmo de classificação de seleção e de classificação de bolhas, eu acho. Se você está realmente tentando ler isso, deve saber que
++i-v-n
é o mesmo que++i != v+n
.fonte
if(a)b
->a?b:0
salva um caractere.++i-v-n
é o mesmo que++i != v+n
apenas em um condicional, é claro.if(*i>v[n])...
->*i>v[n]?...:0
123 caracteres (+3 novas linhas)
Uma classificação Shell padrão, compactada.
PS: descobriu que ainda é 10 vezes mais lento que o quicksort. Você também pode ignorar esta entrada.
fonte
Caráter 395
Mergesort.
Formatado.
fonte
331326327312 caracteresO radix classifica 8 bits de cada vez. Usa um bithack sofisticado para fazer com que os flutuadores negativos sejam classificados corretamente (roubados de http://stereopsis.com/radix.html ). Não é tão compacto, mas é realmente rápido (~ 8x mais rápido que a entrada preliminar mais rápida). Estou esperando o tamanho do código de velocidade superada ...
fonte
511424 caracteresRadixsort no local
Atualização: Muda para a classificação de inserção para tamanhos de matriz menores (aumenta o desempenho de referência em um fator de 4,0).
Formatado.
fonte
void*
inqsort
(linha 88) está jogando fora a aritmética do ponteiro.121114111 caracteresApenas uma bolha rápida e suja, com recursão. Provavelmente não é muito eficiente.
Ou, a versão longa
fonte
221193172 caracteresHeapsort - Não é o menor, mas está no local e garante o comportamento de O (n * log (n)).
Comprimido.
fonte
TEST_COUNT
= 3000, parece que falhará em pelo menos um teste.154166 caracteresOK, aqui está uma seção rápida mais longa, mas mais rápida.
Aqui está uma correção para sobreviver às entradas classificadas. E formatado, pois o espaço em branco não conta.
fonte
150 caracteres
Shellsort (com intervalo de Knuth).
Formatado.
fonte
C 270 (golfe)
Explicação: Uma matriz em branco é usada para armazenar cada número mínimo sucessivo. Uma matriz int é uma máscara com 0 indicando que o número ainda não foi copiado. Após obter o valor mínimo, uma máscara = 1 pula os números já usados. Em seguida, a matriz é copiada de volta ao original.
Mudei o código para eliminar o uso das funções da biblioteca.
fonte
144
Eu descaradamente peguei o código de Johnny, adicionei uma pequena otimização e o compactou de uma maneira muito suja. Deve ser mais curto e mais rápido.
Observe que, dependendo do seu compilador, a classificação (q, v + n- ++ q) deve ser substituída pela classificação (++ q, v + nq).
Bem, na verdade, comecei a formar meu código e o otimizei, mas parece que Johnny já fez todas as escolhas certas. Então acabei com quase o código dele. Eu não pensei no truque do goto, mas poderia ficar sem.
fonte
228 caracteres
Radixsort.
fonte