A distância de Hamming entre duas cordas de igual comprimento é o número de posições nas quais os símbolos correspondentes são diferentes.
Let P
Ser uma seqüência de comprimento binária n
e T
ser uma seqüência de comprimento binária 2n-1
. Podemos calcular as n
distâncias de Hamming entre P
todas as n
subcadeias de comprimento da T
ordem da esquerda para a direita e colocá-las em uma matriz (ou lista).
Exemplo de seqüência de distância de Hamming
Let P = 101
e T = 01100
. A sequência de distâncias de Hamming que você obtém desse par é 2,2,1
.
Tarefa
Para aumentar a n
partir de n=1
, considere todos os pares possíveis de cadeias binárias P
de comprimento n
e T
comprimento 2n-1
. Existem 2**(n+2n-1)
tais pares e, portanto, muitas seqüências de distâncias de Hamming. No entanto, muitas dessas sequências serão idênticas. A tarefa é descobrir quantas são distintas para cada uma n
.
Seu código deve gerar um número por valor de n
.
Ponto
Sua pontuação é a mais alta que n
seu código alcança na minha máquina em 5 minutos. O tempo é para o tempo total de execução, não o tempo apenas para isso n
.
Quem ganha
A pessoa com a pontuação mais alta ganha. Se duas ou mais pessoas terminam com a mesma pontuação, então é a primeira resposta que ganha.
Respostas de exemplo
Para n
de 1
para 8
as respostas ideais são 2, 9, 48, 297, 2040, 15425, 125232, 1070553
.
Línguas e bibliotecas
Você pode usar qualquer idioma e bibliotecas disponíveis que desejar. Sempre que possível, seria bom poder executar seu código; portanto, inclua uma explicação completa de como executar / compilar seu código no Linux, se possível.
Minha máquina Os tempos serão executados na minha máquina de 64 bits. Esta é uma instalação padrão do ubuntu com 8GB de RAM, processador de oito núcleos AMD FX-8350 e Radeon HD 4250. Isso também significa que eu preciso executar seu código.
Respostas principais
- 11 em C ++ por feersum. 25 segundos.
- 11 em C ++ por Andrew Epstein. 176 segundos.
- 10 em Javascript por Neil. 54 segundos.
- 9 em Haskell por nimi. 4 minutos e 59 segundos.
- 8 em Javascript por fəˈnɛtɪk. 10 segundos.
fastest-code
deixa mais espaço para otimizações por meio de otimizações em nível de código e de um bom algoritmo. Então eu acho que issofaster-code
é melhor do quefaster-algorithm
.Respostas:
C ++ 11 (deve chegar a 11 ou 12)
No momento, isso é de thread único.
Compilar:
fonte
feersum.cpp:111:61: warning: shifting a negative signed value is undefined [-Wshift-negative-value] int middle = int(s >> npre * MAX_N_BITS) & ~(~0 << MAX_N_BITS);
Haskell, pontuação 9
Compile com
-O3
. São necessários 6min35s no meu laptop de 6 anos para rodarn=9
, então talvez ele esteja abaixo de 5min no hardware de referência.fonte
JavaScript, pontuação 10
Explicação: O cálculo
n=10
é difícil porque existem mais de dois bilhões de pares e mais de 26 bilhões de seqüências em potencial. Para acelerar as coisas, divido o cálculo em 121 posições. Como as seqüências são invariantes no complemento bit a bit, posso assumir, sem perda de generalidade, que o bit do meioT
é zero. Isso significa que eu posso determinar o primeiro e o último elemento da sequência independentemente dos bits superiorn-1
e inferiorn-1
daT
. Cada compartimento corresponde a um par diferente de primeiro e último elementos; Depois, percorro todos os conjuntos possíveis de bits superior e inferior que correspondem a cada compartimento e calculo os elementos restantes da sequência, finalmente contando as seqüências exclusivas de cada compartimento. Resta então totalizar todos os 121 compartimentos. Originalmente levando 45 horas, isso agora foi concluído em pouco menos de três minutos e meio na minha AMD FX-8120. Edit: Obrigado a @ChristianSievers por uma aceleração de 50%. Saída total:fonte
n
como parâmetro. (Desculpem a má escolha de nome de parâmetro lá.)n=1
(não sei de antemão por que ele trava).C ++, pontuação
1011Esta é uma tradução da resposta de @ Neil em C ++, com alguma paralelização simples.
n=9
termina em 0,4 segundos,n=10
em 4,5 segundos en=11
em aproximadamente 1 minuto no meu Macbook Pro de 2015. Além disso, obrigado a @ChristianSievers. Devido a seus comentários sobre a resposta de @ Neil, notei algumas simetrias adicionais. Dos 121 baldes originais (paran=10
), aos 66 baldes ao contabilizar a reversão, reduzi para apenas 21 baldes.Use o seguinte script para executar o código:
A saída foi a seguinte: (O formato é
M: result, seconds
)n=12
demorou 42 minutos para calcular em um único encadeamento e deu um resultado de 7368225813.fonte
sudo apt-get install libiomp-dev
.__builtin_popcount
.__builtin_popcount
em um contexto constexpr. Eu poderia ir com a implementação ingênua e isso não afetaria o tempo de execução.JavaScript 2,9,48,297,2040,15425,125232,1070553,9530752
Execute no console:
Experimente online!
Ou como um snippet de pilha:
Mostrar snippet de código
O código pré-inicializa a matriz para tornar a adição de 1s na matriz muito mais rápida
O código localiza todas as seqüências de distância de hamming e as trata como base de números (entrada + 1), usa-as para colocar 1s em uma matriz. Como resultado, isso gera uma matriz com os n 1s em que n é o número de seqüências únicas de distâncias de hamming. Finalmente, o número de 1s é contado usando array.reduce () para somar todos os valores na matriz.
Este código não poderá executar a entrada 10, pois atinge os limites de memória
Esse código é executado no tempo O (2 ^ 2n) porque é quantos elementos ele gera.
fonte
n = 9
leva 5 minutos e 30 segundos para eu usar o node.js, então é muito lento.n = 8
originalmente levou 24 segundos no meu PC, mas eu pude otimizar o código paran = 8
levar 6 segundos. Eu tentein = 9
e isso levou 100 segundos.