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
e cada n
substring 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
.
Definição de proximidade
Agora vamos considerar duas dessas seqüências de distâncias de Hamming. Diga x = (0, 2, 2, 3, 0)
e y = (2, 1, 4, 4, 2)
como exemplos. Dizemos isso x
e y
somos close
se y <= x <= 2*y
ou se x <= y <= 2*x
. Aqui a multiplicação escalar e a desigualdade são consideradas elementares. Ou seja, para duas seqüências A
e B
, A <= B iff A[i] <= B[i]
para todos os índices i
.
Observe que seqüências de distâncias de Hamming formam uma ordem parcial sob essa maneira de compará-las. Em outras palavras, muitos pares de sequências não são maiores ou iguais nem menores que ou iguais um ao outro. Por exemplo (1,2)
e (2,1)
.
Então, usando o exemplo acima, (0, 2, 2, 3, 0) <= 2*(2, 1, 4, 4, 2) = (4, 2, 8, 8, 4)
mas (0, 2, 2, 3, 0)
não é maior que (2, 1, 4, 4, 2)
. Também (2, 1, 4, 4, 2)
não é menor ou igual a 2*(0, 2, 2, 3, 0) = (0, 4, 4, 6, 0)
. Como resultado x
e y
não estão próximos um do outro.
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 é encontrar o tamanho do maior conjunto de seqüências de distância de Hamming para que não haja duas sequências próximas umas das outras.
Seu código deve gerar um número por valor de n
.
Ponto
Em geral, sua pontuação é a mais alta que n
seu código atinge na minha máquina em 5 minutos (mas continue lendo). O tempo é para o tempo total de execução, não o tempo apenas para essen
.
Para fornecer pontuações para respostas não ideais, porque é provável que seja difícil encontrar respostas ótimas, precisaremos de um sistema de pontuação um pouco sutil. Sua pontuação é o valor mais alto n
para o qual mais ninguém postou uma resposta correta mais alta para qualquer tamanho menor que igual a isso. Por exemplo, se você produzir 2, 4, 21
e alguém produzir 2, 5, 15
, você só pontuará se 1
alguém tiver uma resposta melhor n = 2
. Se você produzir 2, 5, 21
, pontuará, 3
independentemente do resultado de qualquer outra pessoa, porque essas respostas são ótimas. Claramente, se você tiver todas as respostas ideais, obterá a pontuação mais alta que n
você postar. No entanto, mesmo que sua resposta não seja ótima, você ainda pode obter a pontuação se ninguém mais conseguir vencê-la.
Respostas de exemplo e exemplo trabalhado
(Essas respostas ainda estão desmarcadas. A verificação independente seria recebida com gratidão.)
Graças a ETHproductions:
- n = 1 dá 2.
- n = 2 dá 5.
- n = 3 dá 21.
Vamos olhar com n = 2
mais detalhes. Nesse caso, a lista completa de sequências de distâncias de Hamming (representadas por tuplas aqui) é:
[(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
Podemos ver que (0,0)
não está perto de nenhuma outra tupla. De fato, se tomarmos (0, 0)
, (0, 1)
, (1, 0)
, (2, 1)
, (1,2)
em seguida, nenhuma dessas tuplas estão perto de qualquer um dos outros. Isso dá uma pontuação de 5
para n = 2
.
Para n = 3
a lista completa de distintas seqüências de distância de Hamming, consulte:
[(0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 2), (0, 2, 3), (0, 3, 0), (0, 3, 1), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 2, 3), (1, 3, 0), (1, 3, 1), (1, 3, 2), (2, 0, 1), (2, 0, 2), (2, 0, 3), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 1, 3), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 2, 3), (2, 3, 1), (2, 3, 2), (2, 3, 3), (3, 0, 2), (3, 0, 3), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 2), (3, 3, 3)]
Nessas 48
seqüências, podemos escolher um conjunto de tamanho 21
para que nenhum par nesse conjunto esteja próximo um do outro.
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.
Resposta principal
- Pontuação de 4 para 2, 5, 21, 83, 361 por Christian Sievers. C ++
- Pontuação de 5 para 2, 5, 21, 83, 372 por fəˈnɛtɪk. Javascript
Respostas:
C ++ usando a biblioteca igraph
Obrigado por uma boa oportunidade de aprender uma nova biblioteca!
Este programa agora calcula
2, 5, 21, 83, 361
rapidamente. Você pode controlar a impressão dos nós com aPRINTNODES
constante.O gráfico usado possui arestas extras entre os nós correspondentes aos vetores de distância em que um está próximo (mas não é igual) ao outro invertido. Isso acelera o cálculo, e qualquer conjunto independente encontrado é, obviamente, também um dos gráficos originais. Além disso, mesmo que não seja completamente aplicado, o conjunto independente calculado é fechado em reversão. Acredito que sempre exista um conjunto independente máximo com essa propriedade. Pelo menos há um para
n<=4
. (Tenho certeza de que posso mostrar que 83 é o ideal.)Para compilar no debian, instale
libigraph0-dev
e façag++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o ig ig.cpp -ligraph
.Descrição antiga:
A biblioteca igraph possui uma função para calcular o tamanho máximo de um conjunto de vértices independente de um gráfico. Ele pode lidar com esse problema
n=3
em menos de um segundo e não termina em dias porn=4
.Então, o que faço é decompor o gráfico em componentes conectados e deixar a biblioteca manipular os
MAXDIRECT
componentes pequenos (menos de nós). Para os outros componentes, seleciono um vértice e o apago. Na melhor das hipóteses, isso divide o gráfico em vários componentes, mas geralmente não. De qualquer forma, os componentes (talvez apenas um) são menores e podemos usar recursão.Obviamente, a seleção do vértice é importante. Eu apenas tomo um grau máximo. Descobri que obtenho um melhor resultado (mas apenas para
n=4
) quando uso uma lista de nós invertidos. Isso explica a parte mágica daconstruct
função.Pode valer a pena melhorar a seleção. Mas parece mais importante reconsiderar os nós excluídos. No momento, nunca mais os olho. Alguns deles podem estar desconectados de qualquer um dos nós selecionados. O problema é que não sei quais nós formam o conjunto independente. Por um lado, a exclusão de nós renumera os nós restantes. Isso pode ser tratado anexando atributos a eles. Mas pior, o cálculo do número de independência apenas fornece esse número. A melhor alternativa que a biblioteca oferece é calcular todos os maiores conjuntos independentes, o que é mais lento (o quanto parece depender do tamanho do gráfico). Ainda assim, este parece o caminho imediato a seguir. Muito mais vagamente, também acho útil considerar se podemos usar a maneira especial como o gráfico é definido.
O caso
n=6
pode se tornar acessível (não necessariamente em 5 minutos) se eu substituir a recursão por um loop usando uma fila para os componentes restantes.Achei interessante observar os componentes dos gráficos. Pois
n=4
, seus tamanhos são168, 2*29, 2*28, 3, 4*2, 4*1
. Somente o maior não pode ser tratado diretamente.Pois
n=5
, os tamanhos são1376, 2*128, 2*120, 119, several <=6
.Espero que esses tamanhos duplos correspondam a gráficos isomórficos, mas usar isso não parece valer a pena porque sempre há um único componente maior:
Pois
n=6
, o maior componente contém11941
nós (de um total de15425
), os próximos dois maiores componentes têm tamanho596
.Pois
n=7
, esses números são107593 (125232), 2647
.fonte
g++ -std=c++11 -Wall -O3 -I/usr/include/igraph -o sievers sievers.cpp -ligraph
. Importa onde-ligraph
está.set
eu uso para evitar duplicatas, mas eu nem pensei na ordem deles quando escrevi esse código. O loop interno que começai+1
apenas evita olhar para um par e também sua versão trocada, que não é necessária, e é a maneira mais fácil de evitar loops (arestas(a,a)
). Não depende da ordem em que os nós vêm, não me importo se recebo(a,b)
ou(b,a)
.Javascript, Seq: 2,5,21,
8183,37267,349Consegui aumentar o valor de 4 usando a remoção aleatória de elementos no início da minha pesquisa. Curiosamente, remover 20 elementos com mais de 6 conexões foi mais rápido do que remover 5 elementos com mais de 8 conexões ...
Essa sequência provavelmente não é ideal para 5 e pode não ser ideal para 4. Nenhum dos nós está perto de outro no conjunto.
Código:
Experimente online!
Trecho que pode ser adicionado ao final do programa para mostrar quais seqüências de distâncias de Hamming cada sequência de distâncias de Hamming selecionada
Explicação:
Primeiro, o código gera todas as distâncias de impedimento exclusivas das substrings.
Em seguida, o código converte essa lista em um gráfico não direcionado
Por fim, o código percorre esse gráfico, removendo o vértice com mais conexões a cada ciclo antes de restaurar os nós que agora teriam menos conexões que o máximo atual. Quando termina este ciclo, gera o número de nós restantes
Conjuntos:
1:
2:
3:
4:
5:
fonte