A classificação por mesclagem é um algoritmo de classificação que funciona dividindo uma determinada lista pela metade, classificando recursivamente ambas as listas menores e juntando-as novamente em uma lista classificada. O caso base da recursão está chegando a uma lista de singleton, que não pode ser dividida ainda mais, mas já está classificada por definição.
A execução do algoritmo na lista [1,7,6,3,3,2,5]
pode ser visualizada da seguinte maneira:
[1,7,6,3,3,2,5]
/ \ split
[1,7,6,3] [3,2,5]
/ \ / \ split
[1,7] [6,3] [3,2] [5]
/ \ / \ / \ | split
[1] [7] [6] [3] [3] [2] [5]
\ / \ / \ / | merge
[1,7] [3,6] [2,3] [5]
\ / \ / merge
[1,3,6,7] [2,3,5]
\ / merge
[1,2,3,3,5,6,7]
A tarefa
Escreva um programa ou função que pegue uma lista de números inteiros de qualquer maneira razoável como entrada e visualize as diferentes partições dessa lista enquanto estiver sendo classificado por um algoritmo de classificação de mesclagem. Isso significa que você não precisa gerar um gráfico como acima, mas apenas as listas são boas:
[1,7,6,3,3,2,5]
[1,7,6,3][3,2,5]
[1,7][6,3][3,2][5]
[1][7][6][3][3][2][5]
[1,7][3,6][2,3][5]
[1,3,6,7][2,3,5]
[1,2,3,3,5,6,7]
Além disso, qualquer notação razoável da lista é adequada; portanto, o seguinte também seria uma saída válida:
1 7 6 3 3 2 5
1 7 6 3|3 2 5
1 7|6 3|3 2|5
1|7|6|3|3|2|5
1 7|3 6|2 3|5
1 3 6 7|2 3 5
1 2 3 3 5 6 7
Finalmente, a maneira de dividir uma lista em duas listas menores é com você, desde que o comprimento das duas listas resultantes seja diferente, no máximo, uma. Isso significa que, em vez de dividir [3,2,4,3,7]
em [3,2,4]
e [3,7]
, você também pode dividir usando elementos em índices pares e ímpares ( [3,4,7]
e [2,3]
) ou mesmo aleatoriamente a divisão toda vez.
Isso é código-golfe , portanto o código mais curto em qualquer idioma medido em bytes vence.
Casos de teste
Como observado acima, o formato real e a maneira de dividir as listas pela metade são com você.
[10,2]
[10][2]
[2,10]
[4,17,1,32]
[4,17][1,32]
[4][17][1][32]
[4,17][1,32]
[1,4,17,32]
[6,5,4,3,2,1]
[6,5,4][3,2,1]
[6,5][4][3,2][1]
[6][5][4][3][2][1]
[5,6][4][2,3][1] <- Important: This step cannot be [5,6][3,4][1,2], because 3 and 4 are on different branches in the the tree
[4,5,6][1,2,3]
[1,2,3,4,5,6]
fonte
[[1,2],[3],[4,5],[6]]
estágio é realmente a solução correta, pois a classificação por mesclagem está funcionando recursivamente. Ou seja, se começarmos[1,2,3,4,5,6]
e dividirmos em[1,2,3]
e[4,5,6]
, essas listas serão processadas independentemente até serem mescladas na etapa final.[3]
e[2,1]
, então eles estarão em ramos diferentes, portanto não podemos mesclar[3]
e[2]
depois[2,1]
dividir em[2]
e[1]
.Respostas:
Haskell ,
137128127125121109106 bytes(-2) + (- 4) = (- 6) bytes graças a nimi ! Alterá-lo para coletar todas as etapas de uma lista (novamente devido ao nimi) economiza mais 12 bytes.
Outros 3 bytes devido a Laikoni , com ligação de guarda de padrão e um uso inteligente de compreensão de lista para codificar a guarda.
Experimente online!
Dividir as listas nos elementos ímpares e pares é um código mais curto do que nas duas metades seqüenciais, porque somos poupados da necessidade de medir o valor
length
.Funciona "imprimindo" as listas, repetindo com as listas divididas (
x >>= h
) se realmente houve alguma divisão, e "imprimindo" as listas classificadas; começando com a lista de uma entrada; assumindo a entrada não vazia. E, em vez da impressão real, basta coletá- los em uma lista.A lista produzida por
g[[6,5..1]]
, impressa linha por linha, é:fonte
p=print
e três vezesp
. Experimente online!g
você pode coletar todas as etapas de uma lista e devolvê-la. Experimente online!g x|y<-x>>=h=x:[z|x/=y,z<-g y++[sort<$>x]]
economiza mais alguns bytes.Wolfram Language (Mathematica) ,
146127111102 bytesExperimente online!
Retorna um
List
que contém as etapas.Explicação
Em uma entrada, divida todos os
List
s contendo 2 ou mais números inteiros ao meio. A primeira sub-lista possui os elementos indexados por ímpares (indexados a 1) e o segundo, os elementos indexados por pares.Repita isso até que nada mude (ou seja, todas as sublistas têm o comprimento 1). Mantenha todos os resultados intermediários. Armazene isso (a
List
de todas as etapas) emu
.Solte o último elemento de
u
e inverta-o.A partir do resultado acima, classifique todas as ocorrências de uma lista de números inteiros.
fonte
Limpo ,
228206168157140121104 bytesConstrói a lista de estágios do fim para dentro, usando o fato de que o
n
-ésimo elemento do final é a versão classificada don
-ésimo elemento desde o início.Ideia do comentário de JungHwan Min
Experimente online!
fonte
Carvão ,
145133123122 122 bytesExperimente online! Link é a versão detalhada do código.
Ainda tendo que contornar os erros do carvão vegetal ...Edit: Salvo 5 bytes, usando um duploMap
como compreensão de matriz de um pobre. Salva 4 bytes usandoPop
para duplicar a iteração sobre uma matriz. Salva 3 bytes usando concatenação em vez dePush
. Economizou 10 bytes ao criar umawhile
condição de golfista que também evita um bug no carvão. Economizou 1 byte ao descobrir que o carvão vegetal realmente possui um operador de filtro. Explicação:Divida a entrada em espaços e, em seguida, agrupe o resultado em uma matriz externa, salvando isso em
q
.Repita enquanto o primeiro elemento de
q
possui mais de um elemento. (O primeiro elemento deq
sempre tem mais elementos devido à maneira como as listas são divididas em duas.)Imprima os elementos de
q
união com espaços e linhas verticais. (A matriz faz com que o resultado seja impresso em sua própria linha. Existem outras maneiras de conseguir isso para a mesma contagem de bytes.)Crie uma lista duplicando cada elemento de
q
, em seguida, mapeie essa lista e pegue metade de cada lista (usando a abordagem de elemento alternativo), salvando o resultado novamenteq
.Imprima os elementos de
q
união com espaços e linhas verticais. Na verdade, neste ponto, os elementos deq
são listas vazias ou de elemento único; portanto, juntá-los apenas os converte em cadeias vazias ou em seus elementos. As cadeias vazias adicionariam linhas finais desnecessárias para que sejam filtradas. Um operador de nivelamento teria sido mais golfista (algo como⟦⪫Σθ|⟧
).Repita enquanto
q
tiver mais de um elemento. (O código a seguir requer um número par de elementos.)Copie
q
parah
, mas invertido (veja abaixo) e redefinaq
para uma lista vazia.Repita até
h
ficar vazio.Extraia o próximo elemento de
h
eme
. (Pop
extratos do final, e é por isso que eu tenho que reverterq
.)Inicialize
z
para uma lista vazia.Faça um loop sobre os elementos do próximo elemento de
h
.Copie
e
ad
e reponhae
a uma lista vazia.Loop sobre os elementos de
d
.Empurre-os para
z
oue
dependendo se eles são menores que o elemento atual do próximo elemento deh
.Empurre o elemento atual do próximo elemento de
h
paraz
.Concatene
z
com todos os elementos restantese
e empurre paraq
. Isso completa a mesclagem de dois elementos deh
.Imprima os elementos de
q
união com espaços e linhas verticais.fonte
while (...Map(...)...)
bug que eu já falei.Python 2 ,
145144 bytesIdeia do comentário de JungHwan Min
-1 byte, graças a Jonathan Frech
Experimente online!
fonte
<2
vez de==1
.JavaScript (ES6), 145 bytes
Recebe entrada como uma matriz dentro de uma matriz, ou seja
f([[6,5,4,3,2,1]])
. Funciona gerando a primeira e a última linha da saída, dividindo-se e chamando a si mesma novamente, até que cada sub-matriz tenha o comprimento 1. Aqui está uma demonstração básica de como funciona:fonte
Casca , 14 bytes
Toma uma matriz que contém uma única matriz. Experimente online!
Explicação
O built-in
½
pega uma matriz e divide-a no meio. Se seu comprimento for ímpar, a primeira parte será mais longa por um elemento. Uma matriz singleton[a]
resulta em[[a],[]]
e uma matriz vazia[]
fornece[[],[]]
, portanto é necessário remover as matrizes vazias antes de aplicarU
.fonte
Stax ,
116 (÷ 3>)3829 bytes CP437-9 bytes por comentário de @recursive. Agora a entrada é fornecida como um singleton cujo único elemento é uma matriz dos números a serem classificados.
Experimente online!
Versão descompactada com 35 bytes:
Explicação
O código pode ser dividido em duas partes. A primeira parte visualiza a divisão e a segunda visualiza a mesclagem.
Código para visualizar a divisão:
O código para visualizar a mesclagem:
Versão antiga, na verdade construindo a estrutura de lista aninhada.
cc0+=
é usado três vezes no código para verificar se o topo da pilha é um escalar ou uma matriz.{{cc0+=!{x!}Mm',*:}}X
cria um bloco que se chama recursivamente para gerar uma matriz aninhada de números corretamente. (A saída padrão no Stax vetoriza uma matriz aninhada antes da impressão).Existem outros dois blocos que executam a divisão e a mesclagem, respectivamente. Eles são muito detalhados e eu não me importo de explicar (há um pouco mais de informações na versão histórica deste post, mas não esperamos muito).
fonte
cH!
pode ser usado no lugar decH%!
.{Nd}M
pode ser substituído porT
também.